Revision: 201011
authorDremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:15:52 +0300
changeset 8 4a7fac7dd34a
parent 7 71e347f905f2
child 9 2a0f36a70380
Revision: 201011 Kit: 201015
QtGSTPlayer/QtGSTPlayer.pro
QtGSTPlayer/QtGSTPlayer.qrc
QtGSTPlayer/folder.png
QtGSTPlayer/folderview.cpp
QtGSTPlayer/folderview.h
QtGSTPlayer/main.cpp
QtGSTPlayer/record_play.c
QtGSTPlayer/record_play.h
QtGSTPlayer/settings.png
QtGSTPlayer/views.cpp
QtGSTPlayer/views.h
data/gst_dll_2001F41F.txt
group/bld.inf
gst_nokia_speech/bwins/libgstnokiaaacencu.def
gst_nokia_speech/config.h
gst_nokia_speech/eabi/libgstnokiaaacencu.def
gst_nokia_speech/group/bld.inf
gst_nokia_speech/group/gstaacenc.mmp
gst_nokia_speech/gstaacenc.c
gst_nokia_speech/gstaacenc.h
gst_nokia_speech/gstframedaudioenc.c
gst_nokia_speech/gstframedaudioenc.h
gst_plugins_base/bwins/libgstappu.def
gst_plugins_base/bwins/libgstaudioresampleu.def
gst_plugins_base/bwins/libgstaudiou.def
gst_plugins_base/bwins/libgstcddau.def
gst_plugins_base/bwins/libgstdecodebin2u.def
gst_plugins_base/bwins/libgstdecodebinu.def
gst_plugins_base/bwins/libgstffmpegcolorspaceu.def
gst_plugins_base/bwins/libgstinterfacesu.def
gst_plugins_base/bwins/libgstnetbufferu.def
gst_plugins_base/bwins/libgstpbutilsu.def
gst_plugins_base/bwins/libgstplaybinu.def
gst_plugins_base/bwins/libgstrtpu.def
gst_plugins_base/bwins/libgsttagu.def
gst_plugins_base/bwins/libgsttcpu.def
gst_plugins_base/bwins/libgstvideoscaleu.def
gst_plugins_base/bwins/libgstvideou.def
gst_plugins_base/bwins/liboilu.def
gst_plugins_base/config.h
gst_plugins_base/eabi/libgstappu.def
gst_plugins_base/eabi/libgstaudioresampleu.def
gst_plugins_base/eabi/libgstaudiou.def
gst_plugins_base/eabi/libgstcddau.def
gst_plugins_base/eabi/libgstdecodebin2u.def
gst_plugins_base/eabi/libgstdecodebinu.def
gst_plugins_base/eabi/libgstgdpu.def
gst_plugins_base/eabi/libgstinterfacesu.def
gst_plugins_base/eabi/libgstnetbufferu.def
gst_plugins_base/eabi/libgstplaybinu.def
gst_plugins_base/eabi/libgstrtpu.def
gst_plugins_base/eabi/libgsttagu.def
gst_plugins_base/eabi/libgsttcpu.def
gst_plugins_base/eabi/libgstvideoscaleu.def
gst_plugins_base/eabi/libgstvideotestsrcu.def
gst_plugins_base/eabi/libgstvideou.def
gst_plugins_base/eabi/liboilu.def
gst_plugins_base/ext/alsa/gstalsa.c
gst_plugins_base/ext/alsa/gstalsa.h
gst_plugins_base/ext/alsa/gstalsadeviceprobe.c
gst_plugins_base/ext/alsa/gstalsadeviceprobe.h
gst_plugins_base/ext/alsa/gstalsamixer.c
gst_plugins_base/ext/alsa/gstalsamixer.h
gst_plugins_base/ext/alsa/gstalsamixerelement.c
gst_plugins_base/ext/alsa/gstalsamixerelement.h
gst_plugins_base/ext/alsa/gstalsamixeroptions.c
gst_plugins_base/ext/alsa/gstalsamixeroptions.h
gst_plugins_base/ext/alsa/gstalsamixertrack.c
gst_plugins_base/ext/alsa/gstalsamixertrack.h
gst_plugins_base/ext/alsa/gstalsaplugin.c
gst_plugins_base/ext/alsa/gstalsasink.c
gst_plugins_base/ext/alsa/gstalsasink.h
gst_plugins_base/ext/alsa/gstalsasrc.c
gst_plugins_base/ext/alsa/gstalsasrc.h
gst_plugins_base/ext/cdparanoia/gstcdparanoiasrc.c
gst_plugins_base/ext/cdparanoia/gstcdparanoiasrc.h
gst_plugins_base/ext/gio/gstgio.c
gst_plugins_base/ext/gio/gstgio.h
gst_plugins_base/ext/gio/gstgiobasesink.c
gst_plugins_base/ext/gio/gstgiobasesink.h
gst_plugins_base/ext/gio/gstgiobasesrc.c
gst_plugins_base/ext/gio/gstgiobasesrc.h
gst_plugins_base/ext/gio/gstgiosink.c
gst_plugins_base/ext/gio/gstgiosink.h
gst_plugins_base/ext/gio/gstgiosrc.c
gst_plugins_base/ext/gio/gstgiosrc.h
gst_plugins_base/ext/gio/gstgiostreamsink.c
gst_plugins_base/ext/gio/gstgiostreamsink.h
gst_plugins_base/ext/gio/gstgiostreamsrc.c
gst_plugins_base/ext/gio/gstgiostreamsrc.h
gst_plugins_base/ext/gnomevfs/gstgnomevfs.c
gst_plugins_base/ext/gnomevfs/gstgnomevfs.h
gst_plugins_base/ext/gnomevfs/gstgnomevfssink.c
gst_plugins_base/ext/gnomevfs/gstgnomevfssink.h
gst_plugins_base/ext/gnomevfs/gstgnomevfssrc.c
gst_plugins_base/ext/gnomevfs/gstgnomevfssrc.h
gst_plugins_base/ext/gnomevfs/gstgnomevfsuri.c
gst_plugins_base/ext/gnomevfs/gstgnomevfsuri.h
gst_plugins_base/ext/libvisual/visual.c
gst_plugins_base/ext/ogg/gstogg.c
gst_plugins_base/ext/ogg/gstoggaviparse.c
gst_plugins_base/ext/ogg/gstoggdemux.c
gst_plugins_base/ext/ogg/gstoggdemux.h
gst_plugins_base/ext/ogg/gstoggmux.c
gst_plugins_base/ext/ogg/gstoggmux.h
gst_plugins_base/ext/ogg/gstoggparse.c
gst_plugins_base/ext/ogg/gstogmparse.c
gst_plugins_base/ext/pango/gstclockoverlay.c
gst_plugins_base/ext/pango/gstclockoverlay.h
gst_plugins_base/ext/pango/gsttextoverlay.c
gst_plugins_base/ext/pango/gsttextoverlay.h
gst_plugins_base/ext/pango/gsttextrender.c
gst_plugins_base/ext/pango/gsttextrender.h
gst_plugins_base/ext/pango/gsttimeoverlay.c
gst_plugins_base/ext/pango/gsttimeoverlay.h
gst_plugins_base/ext/theora/gsttheoradec.h
gst_plugins_base/ext/theora/gsttheoraenc.h
gst_plugins_base/ext/theora/gsttheoraparse.h
gst_plugins_base/ext/theora/theora.c
gst_plugins_base/ext/theora/theoradec.c
gst_plugins_base/ext/theora/theoraenc.c
gst_plugins_base/ext/theora/theoraparse.c
gst_plugins_base/ext/vorbis/vorbis.c
gst_plugins_base/ext/vorbis/vorbisdec.c
gst_plugins_base/ext/vorbis/vorbisdec.h
gst_plugins_base/ext/vorbis/vorbisenc.c
gst_plugins_base/ext/vorbis/vorbisenc.h
gst_plugins_base/ext/vorbis/vorbisparse.c
gst_plugins_base/ext/vorbis/vorbisparse.h
gst_plugins_base/ext/vorbis/vorbistag.c
gst_plugins_base/ext/vorbis/vorbistag.h
gst_plugins_base/group/bld.inf
gst_plugins_base/group/ffmpegcolorspace.mmp
gst_plugins_base/group/gstadder.mmp
gst_plugins_base/group/gstaudio.mmp
gst_plugins_base/group/gstaudioconvert.mmp
gst_plugins_base/group/gstaudiorate.mmp
gst_plugins_base/group/gstaudioresample.mmp
gst_plugins_base/group/gstcdda.mmp
gst_plugins_base/group/gstdecodebin.mmp
gst_plugins_base/group/gstfft.mmp
gst_plugins_base/group/gstinterfaces.mmp
gst_plugins_base/group/gstpbutils.mmp
gst_plugins_base/group/gstplayback.mmp
gst_plugins_base/group/gstplaybin.mmp
gst_plugins_base/group/gstsubparse.mmp
gst_plugins_base/group/gstvideo.mmp
gst_plugins_base/group/gstvideotestsrc.mmp
gst_plugins_base/group/gstvolume.mmp
gst_plugins_base/group/liboil.mmp
gst_plugins_base/gst-libs/gst/app/gstapp-marshal.c
gst_plugins_base/gst-libs/gst/app/gstapp-marshal.h
gst_plugins_base/gst-libs/gst/app/gstapp-marshal.list
gst_plugins_base/gst-libs/gst/app/gstappsink.c
gst_plugins_base/gst-libs/gst/app/gstappsink.h
gst_plugins_base/gst-libs/gst/app/gstappsrc.c
gst_plugins_base/gst-libs/gst/audio/TODO
gst_plugins_base/gst-libs/gst/audio/audio-enumtypes.c
gst_plugins_base/gst-libs/gst/audio/audio-enumtypes.h
gst_plugins_base/gst-libs/gst/audio/audio.c
gst_plugins_base/gst-libs/gst/audio/audio.h
gst_plugins_base/gst-libs/gst/audio/gstaudioclock.c
gst_plugins_base/gst-libs/gst/audio/gstaudioclock.h
gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.c
gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.h
gst_plugins_base/gst-libs/gst/audio/gstaudiofilterexample.c
gst_plugins_base/gst-libs/gst/audio/gstaudiofiltertemplate.c
gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c
gst_plugins_base/gst-libs/gst/audio/gstaudiosink.h
gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.c
gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.h
gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.c
gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.h
gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.c
gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.h
gst_plugins_base/gst-libs/gst/audio/gstringbuffer.c
gst_plugins_base/gst-libs/gst/audio/gstringbuffer.h
gst_plugins_base/gst-libs/gst/audio/make_filter
gst_plugins_base/gst-libs/gst/audio/multichannel-enumtypes.c
gst_plugins_base/gst-libs/gst/audio/multichannel-enumtypes.h
gst_plugins_base/gst-libs/gst/audio/multichannel.c
gst_plugins_base/gst-libs/gst/audio/multichannel.h
gst_plugins_base/gst-libs/gst/audio/testchannels.c
gst_plugins_base/gst-libs/gst/cdda/base64.c
gst_plugins_base/gst-libs/gst/cdda/base64.h
gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.c
gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.h
gst_plugins_base/gst-libs/gst/cdda/sha1.c
gst_plugins_base/gst-libs/gst/cdda/sha1.h
gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f32.h
gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f64.h
gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s16.h
gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s32.h
gst_plugins_base/gst-libs/gst/fft/gstfft.c
gst_plugins_base/gst-libs/gst/fft/gstfftf32.c
gst_plugins_base/gst-libs/gst/fft/gstfftf64.c
gst_plugins_base/gst-libs/gst/fft/gstffts16.c
gst_plugins_base/gst-libs/gst/fft/gstffts32.c
gst_plugins_base/gst-libs/gst/fft/kiss_fft_s16.h
gst_plugins_base/gst-libs/gst/fft/kiss_fft_s32.h
gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f32.c
gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f64.c
gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s16.c
gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s32.c
gst_plugins_base/gst-libs/gst/fft/kiss_version
gst_plugins_base/gst-libs/gst/floatcast/floatcast.h
gst_plugins_base/gst-libs/gst/interfaces/colorbalance.c
gst_plugins_base/gst-libs/gst/interfaces/colorbalance.h
gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.c
gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.h
gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.c
gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.h
gst_plugins_base/gst-libs/gst/interfaces/mixer.c
gst_plugins_base/gst-libs/gst/interfaces/mixer.h
gst_plugins_base/gst-libs/gst/interfaces/mixertrack.c
gst_plugins_base/gst-libs/gst/interfaces/mixertrack.h
gst_plugins_base/gst-libs/gst/interfaces/navigation.c
gst_plugins_base/gst-libs/gst/interfaces/navigation.h
gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.c
gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.h
gst_plugins_base/gst-libs/gst/interfaces/tuner.c
gst_plugins_base/gst-libs/gst/interfaces/tuner.h
gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.c
gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.h
gst_plugins_base/gst-libs/gst/interfaces/tunernorm.c
gst_plugins_base/gst-libs/gst/interfaces/tunernorm.h
gst_plugins_base/gst-libs/gst/interfaces/videoorientation.h
gst_plugins_base/gst-libs/gst/interfaces/xoverlay.h
gst_plugins_base/gst-libs/gst/netbuffer/README
gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.c
gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.h
gst_plugins_base/gst-libs/gst/pbutils/descriptions.c
gst_plugins_base/gst-libs/gst/pbutils/install-plugins.c
gst_plugins_base/gst-libs/gst/pbutils/missing-plugins.c
gst_plugins_base/gst-libs/gst/pbutils/pbutils-enumtypes.c
gst_plugins_base/gst-libs/gst/pbutils/pbutils.c
gst_plugins_base/gst-libs/gst/riff/riff-ids.h
gst_plugins_base/gst-libs/gst/riff/riff-media.c
gst_plugins_base/gst-libs/gst/riff/riff-read.c
gst_plugins_base/gst-libs/gst/riff/riff.c
gst_plugins_base/gst-libs/gst/rtp/README
gst_plugins_base/gst-libs/gst/rtp/gstbasertpaudiopayload.c
gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.c
gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.h
gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c
gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.h
gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.c
gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.h
gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c
gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.h
gst_plugins_base/gst-libs/gst/rtp/gstrtppayloads.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtsp-enumtypes.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtsp-enumtypes.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.h
gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c
gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.h
gst_plugins_base/gst-libs/gst/rtsp/md5.c
gst_plugins_base/gst-libs/gst/rtsp/md5.h
gst_plugins_base/gst-libs/gst/rtsp/rtsp-marshal.c
gst_plugins_base/gst-libs/gst/rtsp/rtsp-marshal.h
gst_plugins_base/gst-libs/gst/sdp/gstsdpmessage.c
gst_plugins_base/gst-libs/gst/tag/gstid3tag.c
gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c
gst_plugins_base/gst-libs/gst/tag/gsttagdemux.h
gst_plugins_base/gst-libs/gst/tag/gstvorbistag.c
gst_plugins_base/gst-libs/gst/tag/tag.h
gst_plugins_base/gst-libs/gst/tag/tags.c
gst_plugins_base/gst-libs/gst/video/gstvideofilter.c
gst_plugins_base/gst-libs/gst/video/video-enumtypes.c
gst_plugins_base/gst-libs/gst/video/video-enumtypes.h
gst_plugins_base/gst-libs/gst/video/video.c
gst_plugins_base/gst-libs/gst/video/video.h
gst_plugins_base/gst/adder/gstadder.c
gst_plugins_base/gst/adder/gstadder.h
gst_plugins_base/gst/app/gstapp.c
gst_plugins_base/gst/audioconvert/audioconvert.c
gst_plugins_base/gst/audioconvert/audioconvert.h
gst_plugins_base/gst/audioconvert/gstaudioconvert.c
gst_plugins_base/gst/audioconvert/gstaudioconvert.h
gst_plugins_base/gst/audioconvert/gstaudioquantize.c
gst_plugins_base/gst/audioconvert/gstchannelmix.c
gst_plugins_base/gst/audioconvert/gstfastrandom.h
gst_plugins_base/gst/audiorate/gstaudiorate.c
gst_plugins_base/gst/audioresample/README
gst_plugins_base/gst/audioresample/arch_double.h
gst_plugins_base/gst/audioresample/arch_float.h
gst_plugins_base/gst/audioresample/arch_int.h
gst_plugins_base/gst/audioresample/buffer.c
gst_plugins_base/gst/audioresample/buffer.h
gst_plugins_base/gst/audioresample/debug.h
gst_plugins_base/gst/audioresample/fixed_arm4.h
gst_plugins_base/gst/audioresample/fixed_arm5e.h
gst_plugins_base/gst/audioresample/fixed_bfin.h
gst_plugins_base/gst/audioresample/fixed_debug.h
gst_plugins_base/gst/audioresample/fixed_generic.h
gst_plugins_base/gst/audioresample/functable.c
gst_plugins_base/gst/audioresample/functable.h
gst_plugins_base/gst/audioresample/gstaudioresample.c
gst_plugins_base/gst/audioresample/gstaudioresample.h
gst_plugins_base/gst/audioresample/resample.c
gst_plugins_base/gst/audioresample/resample.h
gst_plugins_base/gst/audioresample/resample_chunk.c
gst_plugins_base/gst/audioresample/resample_double.c
gst_plugins_base/gst/audioresample/resample_float.c
gst_plugins_base/gst/audioresample/resample_functable.c
gst_plugins_base/gst/audioresample/resample_int.c
gst_plugins_base/gst/audioresample/resample_ref.c
gst_plugins_base/gst/audioresample/resample_sse.h
gst_plugins_base/gst/audioresample/speex_resampler.h
gst_plugins_base/gst/audioresample/speex_resampler_double.c
gst_plugins_base/gst/audioresample/speex_resampler_float.c
gst_plugins_base/gst/audioresample/speex_resampler_int.c
gst_plugins_base/gst/audioresample/speex_resampler_wrapper.h
gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.c
gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.h
gst_plugins_base/gst/ffmpegcolorspace/avcodec.h
gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcodecmap.c
gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcolorspace.c
gst_plugins_base/gst/ffmpegcolorspace/imgconvert.c
gst_plugins_base/gst/ffmpegcolorspace/imgconvert_template.h
gst_plugins_base/gst/gdp/README
gst_plugins_base/gst/gdp/gstgdpdepay.c
gst_plugins_base/gst/gdp/gstgdpdepay.h
gst_plugins_base/gst/gdp/gstgdppay.c
gst_plugins_base/gst/gdp/gstgdppay.h
gst_plugins_base/gst/oil/liboil.h
gst_plugins_base/gst/oil/stub.c
gst_plugins_base/gst/playback/README
gst_plugins_base/gst/playback/decodetest.c
gst_plugins_base/gst/playback/gstdecodebin.c
gst_plugins_base/gst/playback/gstdecodebin2.c
gst_plugins_base/gst/playback/gstinputselector.c
gst_plugins_base/gst/playback/gstinputselector.h
gst_plugins_base/gst/playback/gstplay-enum.c
gst_plugins_base/gst/playback/gstplay-enum.h
gst_plugins_base/gst/playback/gstplay-marshal.c
gst_plugins_base/gst/playback/gstplay-marshal.h
gst_plugins_base/gst/playback/gstplay-marshal.list
gst_plugins_base/gst/playback/gstplayback.c
gst_plugins_base/gst/playback/gstplaybasebin.c
gst_plugins_base/gst/playback/gstplaybasebin.h
gst_plugins_base/gst/playback/gstplaybin.c
gst_plugins_base/gst/playback/gstplaybin2.c
gst_plugins_base/gst/playback/gstplaysink.c
gst_plugins_base/gst/playback/gstplaysink.h
gst_plugins_base/gst/playback/gstqueue2.c
gst_plugins_base/gst/playback/gstscreenshot.c
gst_plugins_base/gst/playback/gststreaminfo.c
gst_plugins_base/gst/playback/gststreamselector.c
gst_plugins_base/gst/playback/gsturidecodebin.c
gst_plugins_base/gst/playback/test.c
gst_plugins_base/gst/playback/test4.c
gst_plugins_base/gst/playback/test5.c
gst_plugins_base/gst/playback/test6.c
gst_plugins_base/gst/playback/test7.c
gst_plugins_base/gst/subparse/gstssaparse.c
gst_plugins_base/gst/subparse/gstssaparse.h
gst_plugins_base/gst/subparse/gstsubparse.c
gst_plugins_base/gst/subparse/gstsubparse.h
gst_plugins_base/gst/subparse/samiparse.c
gst_plugins_base/gst/subparse/tmplayerparse.c
gst_plugins_base/gst/tcp/README
gst_plugins_base/gst/tcp/gstmultifdsink.c
gst_plugins_base/gst/tcp/gstmultifdsink.h
gst_plugins_base/gst/tcp/gsttcp-enumtypes.c
gst_plugins_base/gst/tcp/gsttcp-marshal.c
gst_plugins_base/gst/tcp/gsttcp-marshal.h
gst_plugins_base/gst/tcp/gsttcp-marshal.list
gst_plugins_base/gst/tcp/gsttcp.c
gst_plugins_base/gst/tcp/gsttcp.h
gst_plugins_base/gst/tcp/gsttcpclientsink.c
gst_plugins_base/gst/tcp/gsttcpclientsrc.c
gst_plugins_base/gst/tcp/gsttcpserversink.c
gst_plugins_base/gst/tcp/gsttcpserversrc.c
gst_plugins_base/gst/typefind/gsttypefindfunctions.c
gst_plugins_base/gst/videorate/gstvideorate.c
gst_plugins_base/gst/videorate/gstvideorate.h
gst_plugins_base/gst/videoscale/README
gst_plugins_base/gst/videoscale/gstvideoscale.c
gst_plugins_base/gst/videoscale/gstvideoscale.h
gst_plugins_base/gst/videoscale/vs_4tap.c
gst_plugins_base/gst/videoscale/vs_4tap.h
gst_plugins_base/gst/videoscale/vs_image.c
gst_plugins_base/gst/videoscale/vs_image.h
gst_plugins_base/gst/videoscale/vs_scanline.c
gst_plugins_base/gst/videoscale/vs_scanline.h
gst_plugins_base/gst/videotestsrc/gstvideotestsrc.c
gst_plugins_base/gst/videotestsrc/gstvideotestsrc.h
gst_plugins_base/gst/videotestsrc/videotestsrc.c
gst_plugins_base/gst/videotestsrc/videotestsrc.h
gst_plugins_base/gst/volume/gstvolume.c
gst_plugins_base/gst/volume/gstvolume.h
gst_plugins_base/sys/v4l/gstv4l.c
gst_plugins_base/sys/v4l/gstv4lcolorbalance.c
gst_plugins_base/sys/v4l/gstv4lcolorbalance.h
gst_plugins_base/sys/v4l/gstv4lelement.c
gst_plugins_base/sys/v4l/gstv4lelement.h
gst_plugins_base/sys/v4l/gstv4ljpegsrc.h
gst_plugins_base/sys/v4l/gstv4lmjpegsink.h
gst_plugins_base/sys/v4l/gstv4lmjpegsrc.h
gst_plugins_base/sys/v4l/gstv4lsrc.c
gst_plugins_base/sys/v4l/gstv4lsrc.h
gst_plugins_base/sys/v4l/gstv4ltuner.c
gst_plugins_base/sys/v4l/gstv4ltuner.h
gst_plugins_base/sys/v4l/gstv4lxoverlay.c
gst_plugins_base/sys/v4l/gstv4lxoverlay.h
gst_plugins_base/sys/v4l/v4l_calls.c
gst_plugins_base/sys/v4l/v4l_calls.h
gst_plugins_base/sys/v4l/v4lmjpegsink_calls.h
gst_plugins_base/sys/v4l/v4lmjpegsrc_calls.h
gst_plugins_base/sys/v4l/v4lsrc_calls.c
gst_plugins_base/sys/v4l/v4lsrc_calls.h
gst_plugins_base/sys/v4l/videodev_mjpeg.h
gst_plugins_base/sys/ximage/ximage.c
gst_plugins_base/sys/ximage/ximagesink.c
gst_plugins_base/sys/ximage/ximagesink.h
gst_plugins_base/sys/xvimage/xvimagesink.c
gst_plugins_base/sys/xvimage/xvimagesink.h
gst_plugins_base/tsrc/check/elements/adder/src/adder.c
gst_plugins_base/tsrc/check/elements/audioconvert/src/audioconvert.c
gst_plugins_base/tsrc/check/elements/audiorate/src/audiorate.c
gst_plugins_base/tsrc/check/elements/audioresample/src/audioresample.c
gst_plugins_base/tsrc/check/elements/audiotestsrc/src/audiotestsrc.c
gst_plugins_base/tsrc/check/elements/createelementbase/src/createelementbase.c
gst_plugins_base/tsrc/check/elements/createelementbasevideo/group/bld.inf
gst_plugins_base/tsrc/check/elements/createelementbasevideo/group/createelementbasevideo.mmp
gst_plugins_base/tsrc/check/elements/createelementbasevideo/src/createelementbasevideo.c
gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/group/bld.inf
gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/group/ffmpegcolorspace.mmp
gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/src/ffmpegcolorspace.c
gst_plugins_base/tsrc/check/elements/decodebin/src/decodebin.c
gst_plugins_base/tsrc/check/elements/ffmpegcolorspace/src/ffmpegcolorspace.c
gst_plugins_base/tsrc/check/elements/gdpdepay/src/gdpdepay.c
gst_plugins_base/tsrc/check/elements/multifdsink/src/multifdsink.c
gst_plugins_base/tsrc/check/elements/playbin/src/playbin.c
gst_plugins_base/tsrc/check/elements/subparse/src/subparse.c
gst_plugins_base/tsrc/check/elements/videorate/src/videorate.c
gst_plugins_base/tsrc/check/elements/volume/src/volume.c
gst_plugins_base/tsrc/check/generic/clock-selection/src/clock-selection.c
gst_plugins_base/tsrc/check/generic/states/src/states.c
gst_plugins_base/tsrc/check/gst/typefindfunctions/src/typefindfunctions.c
gst_plugins_base/tsrc/check/libs/fft/src/fft.c
gst_plugins_base/tsrc/check/libs/netbuffer/src/netbuffer.c
gst_plugins_base/tsrc/check/libs/pbutils/src/pbutils.c
gst_plugins_base/tsrc/check/libs/rtp/src/rtp.c
gst_plugins_base/tsrc/check/libs/tag/src/tag.c
gst_plugins_base/tsrc/check/libs/taudio/src/taudio.c
gst_plugins_base/tsrc/check/libs/video/src/video.c
gst_plugins_base/tsrc/check/pipelines/simple-launch-lines/src/simple-launch-lines.c
gst_plugins_base/tsrc/check/pipelines/streamheader/src/streamheader.c
gst_plugins_base/tsrc/examples/dynamic/addstream/src/addstream.c
gst_plugins_good/bwins/gstqtmuxu.def
gst_plugins_good/bwins/libgstalawu.def
gst_plugins_good/bwins/libgstalphacoloru.def
gst_plugins_good/bwins/libgstalphau.def
gst_plugins_good/bwins/libgstaudiofxu.def
gst_plugins_good/bwins/libgstauparseu.def
gst_plugins_good/bwins/libgstaviu.def
gst_plugins_good/bwins/libgstjpegU.DEF
gst_plugins_good/bwins/libgstmulawu.def
gst_plugins_good/bwins/libgstpngu.def
gst_plugins_good/bwins/libgstqtdemuxu.def
gst_plugins_good/eabi/gstqtmuxu.def
gst_plugins_good/eabi/libgstalawu.def
gst_plugins_good/eabi/libgstalphacoloru.def
gst_plugins_good/eabi/libgstalphau.def
gst_plugins_good/eabi/libgstaudiofxu.def
gst_plugins_good/eabi/libgstauparseu.def
gst_plugins_good/eabi/libgstaviu.def
gst_plugins_good/eabi/libgstjpegU.DEF
gst_plugins_good/eabi/libgstmulawu.def
gst_plugins_good/eabi/libgstpngu.def
gst_plugins_good/eabi/libgstqtdemuxu.def
gst_plugins_good/ext/jpeg/README
gst_plugins_good/ext/jpeg/gstjpeg.c
gst_plugins_good/ext/jpeg/gstjpegdec.c
gst_plugins_good/ext/jpeg/gstjpegdec.h
gst_plugins_good/ext/jpeg/gstjpegenc.c
gst_plugins_good/ext/jpeg/gstjpegenc.h
gst_plugins_good/ext/jpeg/gstsmokedec.c
gst_plugins_good/ext/jpeg/gstsmokedec.h
gst_plugins_good/ext/jpeg/gstsmokeenc.c
gst_plugins_good/ext/jpeg/gstsmokeenc.h
gst_plugins_good/ext/jpeg/smokecodec.c
gst_plugins_good/ext/jpeg/smokecodec.h
gst_plugins_good/ext/jpeg/smokeformat.h
gst_plugins_good/ext/libpng/gstpng.c
gst_plugins_good/ext/libpng/gstpngdec.c
gst_plugins_good/ext/libpng/gstpngdec.h
gst_plugins_good/ext/libpng/gstpngenc.c
gst_plugins_good/ext/libpng/gstpngenc.h
gst_plugins_good/group/bld.inf
gst_plugins_good/group/gstalaw.mmp
gst_plugins_good/group/gstalpha.mmp
gst_plugins_good/group/gstalphacolor.mmp
gst_plugins_good/group/gstamrmux.mmp
gst_plugins_good/group/gstaudiofx.mmp
gst_plugins_good/group/gstauparse.mmp
gst_plugins_good/group/gstautodetect.mmp
gst_plugins_good/group/gstavi.mmp
gst_plugins_good/group/gstjpeg.mmp
gst_plugins_good/group/gstmulaw.mmp
gst_plugins_good/group/gstpng.mmp
gst_plugins_good/group/gstqtdemux.mmp
gst_plugins_good/group/gstqtmux.mmp
gst_plugins_good/gst/alpha/gstalpha.c
gst_plugins_good/gst/alpha/gstalphacolor.c
gst_plugins_good/gst/alpha/gstalphacolor.h
gst_plugins_good/gst/amrmux/gstamrmux.c
gst_plugins_good/gst/amrmux/gstamrmux.h
gst_plugins_good/gst/amrmux/gstamrmux.mmp
gst_plugins_good/gst/audiofx/audioamplify.c
gst_plugins_good/gst/audiofx/audioamplify.h
gst_plugins_good/gst/audiofx/audiochebband.c
gst_plugins_good/gst/audiofx/audiochebband.h
gst_plugins_good/gst/audiofx/audiocheblimit.c
gst_plugins_good/gst/audiofx/audiocheblimit.h
gst_plugins_good/gst/audiofx/audiodynamic.c
gst_plugins_good/gst/audiofx/audiodynamic.h
gst_plugins_good/gst/audiofx/audioecho.c
gst_plugins_good/gst/audiofx/audioecho.h
gst_plugins_good/gst/audiofx/audiofirfilter.c
gst_plugins_good/gst/audiofx/audiofirfilter.h
gst_plugins_good/gst/audiofx/audiofx.c
gst_plugins_good/gst/audiofx/audiofxbasefirfilter.c
gst_plugins_good/gst/audiofx/audiofxbasefirfilter.h
gst_plugins_good/gst/audiofx/audiofxbaseiirfilter.c
gst_plugins_good/gst/audiofx/audiofxbaseiirfilter.h
gst_plugins_good/gst/audiofx/audioiirfilter.c
gst_plugins_good/gst/audiofx/audioiirfilter.h
gst_plugins_good/gst/audiofx/audioinvert.c
gst_plugins_good/gst/audiofx/audioinvert.h
gst_plugins_good/gst/audiofx/audiokaraoke.c
gst_plugins_good/gst/audiofx/audiokaraoke.h
gst_plugins_good/gst/audiofx/audiopanorama.c
gst_plugins_good/gst/audiofx/audiopanorama.h
gst_plugins_good/gst/audiofx/audiowsincband.c
gst_plugins_good/gst/audiofx/audiowsincband.h
gst_plugins_good/gst/audiofx/audiowsinclimit.c
gst_plugins_good/gst/audiofx/audiowsinclimit.h
gst_plugins_good/gst/audiofx/math_compat.h
gst_plugins_good/gst/auparse/gstauparse.c
gst_plugins_good/gst/auparse/gstauparse.h
gst_plugins_good/gst/autodetect/gstautoaudiosink.c
gst_plugins_good/gst/autodetect/gstautoaudiosink.h
gst_plugins_good/gst/autodetect/gstautoaudiosrc.c
gst_plugins_good/gst/autodetect/gstautoaudiosrc.h
gst_plugins_good/gst/autodetect/gstautodetect.c
gst_plugins_good/gst/autodetect/gstautovideosink.c
gst_plugins_good/gst/autodetect/gstautovideosrc.c
gst_plugins_good/gst/autodetect/gstautovideosrc.h
gst_plugins_good/gst/avi/README
gst_plugins_good/gst/avi/avi-ids.h
gst_plugins_good/gst/avi/gstavi.c
gst_plugins_good/gst/avi/gstavidemux.c
gst_plugins_good/gst/avi/gstavidemux.h
gst_plugins_good/gst/avi/gstavimux.c
gst_plugins_good/gst/avi/gstavimux.h
gst_plugins_good/gst/avi/gstavisubtitle.c
gst_plugins_good/gst/avi/gstavisubtitle.h
gst_plugins_good/gst/law/alaw-decode.c
gst_plugins_good/gst/law/alaw-decode.h
gst_plugins_good/gst/law/alaw-encode.c
gst_plugins_good/gst/law/alaw-encode.h
gst_plugins_good/gst/law/alaw.c
gst_plugins_good/gst/law/mulaw-conversion.c
gst_plugins_good/gst/law/mulaw-conversion.h
gst_plugins_good/gst/law/mulaw-decode.c
gst_plugins_good/gst/law/mulaw-decode.h
gst_plugins_good/gst/law/mulaw-encode.c
gst_plugins_good/gst/law/mulaw-encode.h
gst_plugins_good/gst/law/mulaw.c
gst_plugins_good/gst/qtdemux/gstrtpxqtdepay.c
gst_plugins_good/gst/qtdemux/gstrtpxqtdepay.h
gst_plugins_good/gst/qtdemux/qtdemux.c
gst_plugins_good/gst/qtdemux/qtdemux.h
gst_plugins_good/gst/qtdemux/qtdemux_dump.c
gst_plugins_good/gst/qtdemux/qtdemux_dump.h
gst_plugins_good/gst/qtdemux/qtdemux_fourcc.h
gst_plugins_good/gst/qtdemux/qtdemux_types.c
gst_plugins_good/gst/qtdemux/qtdemux_types.h
gst_plugins_good/gst/qtdemux/qtpalette.h
gst_plugins_good/gst/qtdemux/quicktime.c
gst_plugins_good/gst/qtmux/atoms.c
gst_plugins_good/gst/qtmux/atoms.h
gst_plugins_good/gst/qtmux/descriptors.c
gst_plugins_good/gst/qtmux/descriptors.h
gst_plugins_good/gst/qtmux/fourcc.h
gst_plugins_good/gst/qtmux/ftypcc.h
gst_plugins_good/gst/qtmux/gstqtmux.c
gst_plugins_good/gst/qtmux/gstqtmux.h
gst_plugins_good/gst/qtmux/gstqtmuxmap.c
gst_plugins_good/gst/qtmux/gstqtmuxmap.h
gst_plugins_good/gst/qtmux/properties.c
gst_plugins_good/gst/qtmux/properties.h
gst_plugins_good/gst/wavenc/gstwavenc.c
gst_plugins_good/gst/wavenc/gstwavenc.h
gst_plugins_good/gst/wavenc/riff.h
gst_plugins_good/gst/wavparse/gstwavparse.c
gst_plugins_good/gst/wavparse/gstwavparse.h
gst_plugins_symbian/config.h
gst_plugins_symbian/tsrc/gstreamertestmodule/conf/GStreamerTestClass.cfg
gst_plugins_symbian/tsrc/gstreamertestmodule/group/GStreamerTestClass.pkg
gst_plugins_symbian/tsrc/gstreamertestmodule/group/bld.inf
gst_plugins_symbian/tsrc/gstreamertestmodule/inc/GStreamerTestClass.h
gst_plugins_symbian/tsrc/gstreamertestmodule/src/GStreamerTestClassBlocks.cpp
gstreamer_core/bwins/libgstbaseu.def
gstreamer_core/bwins/libgstcoreelementsu.def
gstreamer_core/bwins/libgstreameru.def
gstreamer_core/config.h
gstreamer_core/eabi/libgstbaseu.def
gstreamer_core/eabi/libgstcoreelementsu.def
gstreamer_core/eabi/libgstcoreelementsu_old.def
gstreamer_core/eabi/libgstreameru.def
gstreamer_core/group/bld.inf
gstreamer_core/group/gstbase.mmp
gstreamer_core/group/gstindexers.mmp
gstreamer_core/group/gstreamer.mmp
gstreamer_core/gst/glib-compat-private.h
gstreamer_core/gst/gst.c
gstreamer_core/gst/gst.h
gstreamer_core/gst/gst_global.h
gstreamer_core/gst/gst_private.h
gstreamer_core/gst/gstbin.c
gstreamer_core/gst/gstbin.h
gstreamer_core/gst/gstbuffer.c
gstreamer_core/gst/gstbuffer.h
gstreamer_core/gst/gstbufferlist.c
gstreamer_core/gst/gstbufferlist.h
gstreamer_core/gst/gstbus.c
gstreamer_core/gst/gstbus.h
gstreamer_core/gst/gstcaps.c
gstreamer_core/gst/gstcaps.h
gstreamer_core/gst/gstchildproxy.c
gstreamer_core/gst/gstchildproxy.h
gstreamer_core/gst/gstclock.c
gstreamer_core/gst/gstclock.h
gstreamer_core/gst/gstconfig.h
gstreamer_core/gst/gstdebugutils.c
gstreamer_core/gst/gstdebugutils.h
gstreamer_core/gst/gstelement.c
gstreamer_core/gst/gstelement.h
gstreamer_core/gst/gstelementfactory.c
gstreamer_core/gst/gstelementfactory.h
gstreamer_core/gst/gstenumtypes.c
gstreamer_core/gst/gstenumtypes.h
gstreamer_core/gst/gsterror.c
gstreamer_core/gst/gsterror.h
gstreamer_core/gst/gstevent.c
gstreamer_core/gst/gstevent.h
gstreamer_core/gst/gstformat.h
gstreamer_core/gst/gstghostpad.c
gstreamer_core/gst/gstghostpad.h
gstreamer_core/gst/gstindex.c
gstreamer_core/gst/gstindexfactory.c
gstreamer_core/gst/gstinfo.c
gstreamer_core/gst/gstinfo.h
gstreamer_core/gst/gstinterface.c
gstreamer_core/gst/gstinterface.h
gstreamer_core/gst/gstiterator.c
gstreamer_core/gst/gstiterator.h
gstreamer_core/gst/gstmacros.h
gstreamer_core/gst/gstmessage.c
gstreamer_core/gst/gstmessage.h
gstreamer_core/gst/gstminiobject.c
gstreamer_core/gst/gstminiobject.h
gstreamer_core/gst/gstobject.c
gstreamer_core/gst/gstobject.h
gstreamer_core/gst/gstpad.c
gstreamer_core/gst/gstpad.h
gstreamer_core/gst/gstpadtemplate.c
gstreamer_core/gst/gstparamspecs.c
gstreamer_core/gst/gstparamspecs.h
gstreamer_core/gst/gstparse.c
gstreamer_core/gst/gstparse.h
gstreamer_core/gst/gstpipeline.c
gstreamer_core/gst/gstpipeline.h
gstreamer_core/gst/gstplugin.c
gstreamer_core/gst/gstplugin.h
gstreamer_core/gst/gstpluginfeature.c
gstreamer_core/gst/gstpoll.c
gstreamer_core/gst/gstpoll.h
gstreamer_core/gst/gstpreset.c
gstreamer_core/gst/gstpreset.h
gstreamer_core/gst/gstquark.c
gstreamer_core/gst/gstquark.h
gstreamer_core/gst/gstquery.c
gstreamer_core/gst/gstquery.h
gstreamer_core/gst/gstregistry.c
gstreamer_core/gst/gstregistrybinary.c
gstreamer_core/gst/gstregistrybinary.h
gstreamer_core/gst/gstregistryxml.c
gstreamer_core/gst/gstsegment.c
gstreamer_core/gst/gstsegment.h
gstreamer_core/gst/gststructure.c
gstreamer_core/gst/gststructure.h
gstreamer_core/gst/gstsystemclock.c
gstreamer_core/gst/gstsystemclock.h
gstreamer_core/gst/gsttaglist.c
gstreamer_core/gst/gsttaglist.h
gstreamer_core/gst/gsttagsetter.c
gstreamer_core/gst/gsttagsetter.h
gstreamer_core/gst/gsttask.c
gstreamer_core/gst/gsttask.h
gstreamer_core/gst/gsttaskpool.c
gstreamer_core/gst/gsttaskpool.h
gstreamer_core/gst/gsttrace.c
gstreamer_core/gst/gsttrace.h
gstreamer_core/gst/gsttypefind.c
gstreamer_core/gst/gsttypefind.h
gstreamer_core/gst/gsttypefindfactory.c
gstreamer_core/gst/gsturi.c
gstreamer_core/gst/gsturi.h
gstreamer_core/gst/gstutils.c
gstreamer_core/gst/gstutils.h
gstreamer_core/gst/gstvalue.c
gstreamer_core/gst/gstvalue.h
gstreamer_core/gst/gstversion.h
gstreamer_core/gst/gstxml.c
gstreamer_core/gst/helpfile.cpp
gstreamer_core/gst/parse/grammar.tab.c
gstreamer_core/gst/parse/grammar.tab.h
gstreamer_core/gst/parse/grammar.tab.pre.c
gstreamer_core/gst/parse/grammar.tab.pre.h
gstreamer_core/gst/parse/lex._gst_parse_yy.c
gstreamer_core/gst/parse/lex._gst_parse_yy.pre.c
gstreamer_core/gst/parse/parse.l
gstreamer_core/gst/parse/types.h
gstreamer_core/libs/gst/base/gstadapter.c
gstreamer_core/libs/gst/base/gstadapter.h
gstreamer_core/libs/gst/base/gstbasesink.c
gstreamer_core/libs/gst/base/gstbasesink.h
gstreamer_core/libs/gst/base/gstbasesrc.c
gstreamer_core/libs/gst/base/gstbasesrc.h
gstreamer_core/libs/gst/base/gstbasetransform.c
gstreamer_core/libs/gst/base/gstbasetransform.h
gstreamer_core/libs/gst/base/gstbitreader.c
gstreamer_core/libs/gst/base/gstbitreader.h
gstreamer_core/libs/gst/base/gstbytereader.c
gstreamer_core/libs/gst/base/gstbytereader.h
gstreamer_core/libs/gst/base/gstcollectpads.c
gstreamer_core/libs/gst/base/gstcollectpads.h
gstreamer_core/libs/gst/base/gstdataqueue.c
gstreamer_core/libs/gst/base/gstdataqueue.h
gstreamer_core/libs/gst/base/gstpushsrc.c
gstreamer_core/libs/gst/base/gsttypefindhelper.c
gstreamer_core/libs/gst/base/gsttypefindhelper.h
gstreamer_core/libs/gst/check/gstbufferstraw.c
gstreamer_core/libs/gst/check/gstcheck.c
gstreamer_core/libs/gst/check/gstcheck.h
gstreamer_core/libs/gst/check/gstconsistencychecker.c
gstreamer_core/libs/gst/check/gstconsistencychecker.h
gstreamer_core/libs/gst/check/std_log_result.h
gstreamer_core/libs/gst/controller/gstcontroller.c
gstreamer_core/libs/gst/controller/gstcontroller.h
gstreamer_core/libs/gst/controller/gstcontrollerprivate.h
gstreamer_core/libs/gst/controller/gstcontrolsource.c
gstreamer_core/libs/gst/controller/gsthelper.c
gstreamer_core/libs/gst/controller/gstinterpolation.c
gstreamer_core/libs/gst/controller/gstinterpolationcontrolsource.c
gstreamer_core/libs/gst/controller/gstinterpolationcontrolsourceprivate.h
gstreamer_core/libs/gst/controller/gstlfocontrolsource.c
gstreamer_core/libs/gst/controller/lib.c
gstreamer_core/libs/gst/dataprotocol/dataprotocol.c
gstreamer_core/libs/gst/net/gstnetclientclock.c
gstreamer_core/libs/gst/net/gstnettimepacket.c
gstreamer_core/libs/gst/net/gstnettimepacket.h
gstreamer_core/libs/gst/net/gstnettimeprovider.c
gstreamer_core/plugins/elements/gstcapsfilter.c
gstreamer_core/plugins/elements/gstelements.c
gstreamer_core/plugins/elements/gstfakesink.c
gstreamer_core/plugins/elements/gstfakesink.h
gstreamer_core/plugins/elements/gstfakesrc.c
gstreamer_core/plugins/elements/gstfakesrc.h
gstreamer_core/plugins/elements/gstfdsink.c
gstreamer_core/plugins/elements/gstfdsink.h
gstreamer_core/plugins/elements/gstfdsrc.c
gstreamer_core/plugins/elements/gstfdsrc.h
gstreamer_core/plugins/elements/gstfilesink.c
gstreamer_core/plugins/elements/gstfilesrc.c
gstreamer_core/plugins/elements/gstidentity.c
gstreamer_core/plugins/elements/gstidentity.h
gstreamer_core/plugins/elements/gstmultiqueue.c
gstreamer_core/plugins/elements/gstqueue.c
gstreamer_core/plugins/elements/gsttee.c
gstreamer_core/plugins/elements/gsttee.h
gstreamer_core/plugins/elements/gsttypefindelement.c
gstreamer_core/plugins/elements/gsttypefindelement.h
gstreamer_core/plugins/indexers/gstfileindex.c
gstreamer_core/plugins/indexers/gstindexers.c
gstreamer_core/plugins/indexers/gstmemindex.c
gstreamer_core/tools/grammar.y
gstreamer_core/tools/gst-inspect.c
gstreamer_core/tools/gst-launch.c
gstreamer_core/tools/gst-run.c
gstreamer_core/tools/gst-typefind.c
gstreamer_core/tools/gst-xmlinspect.c
gstreamer_core/tools/tools.h
gstreamer_core/tsrc/check/elements/createelementcore/src/createelementcore.c
gstreamer_core/tsrc/check/elements/fakesink/src/fakesink.c
gstreamer_core/tsrc/check/elements/fakesrc/src/fakesrc.c
gstreamer_core/tsrc/check/elements/fdsrc/group/bld.inf
gstreamer_core/tsrc/check/elements/fdsrc/src/fdsrc.c
gstreamer_core/tsrc/check/elements/filesink/src/filesink.c
gstreamer_core/tsrc/check/elements/filesrc/src/filesrc.c
gstreamer_core/tsrc/check/elements/gstqueue/src/gstqueue.c
gstreamer_core/tsrc/check/elements/identity/src/identity.c
gstreamer_core/tsrc/check/elements/multiqueue/src/multiqueue.c
gstreamer_core/tsrc/check/elements/tee/src/tee.c
gstreamer_core/tsrc/check/generic/gststates/src/gststates.c
gstreamer_core/tsrc/check/generic/sinks/src/sinks.c
gstreamer_core/tsrc/check/gst/gst/src/gst.c
gstreamer_core/tsrc/check/gst/gstbin/src/gstbin.c
gstreamer_core/tsrc/check/gst/gstbuffer/src/gstbuffer.c
gstreamer_core/tsrc/check/gst/gstbus/src/gstbus.c
gstreamer_core/tsrc/check/gst/gstcaps/src/gstcaps.c
gstreamer_core/tsrc/check/gst/gstelement/src/gstelement.c
gstreamer_core/tsrc/check/gst/gstevent/src/gstevent.c
gstreamer_core/tsrc/check/gst/gstghostpad/src/gstghostpad.c
gstreamer_core/tsrc/check/gst/gstindex/src/gstindex.c
gstreamer_core/tsrc/check/gst/gstinterface/src/gstinterface.c
gstreamer_core/tsrc/check/gst/gstiterator/src/gstiterator.c
gstreamer_core/tsrc/check/gst/gstmessage/src/gstmessage.c
gstreamer_core/tsrc/check/gst/gstminiobject/src/gstminiobject.c
gstreamer_core/tsrc/check/gst/gstobject/src/gstobject.c
gstreamer_core/tsrc/check/gst/gstpad/src/gstpad.c
gstreamer_core/tsrc/check/gst/gstparamspecs/src/gstparamspecs.c
gstreamer_core/tsrc/check/gst/gstpipeline/src/gstpipeline.c
gstreamer_core/tsrc/check/gst/gstplugin/src/gstplugin.c
gstreamer_core/tsrc/check/gst/gstpoll/src/gstpoll.c
gstreamer_core/tsrc/check/gst/gstquery/src/gstquery.c
gstreamer_core/tsrc/check/gst/gstregistry/src/gstregistry.c
gstreamer_core/tsrc/check/gst/gstsegment/src/gstsegment.c
gstreamer_core/tsrc/check/gst/gststructure/src/gststructure.c
gstreamer_core/tsrc/check/gst/gstsystemclock/src/gstsystemclock.c
gstreamer_core/tsrc/check/gst/gsttag/src/gsttag.c
gstreamer_core/tsrc/check/gst/gsttagsetter/src/gsttagsetter.c
gstreamer_core/tsrc/check/gst/gsttask/src/gsttask.c
gstreamer_core/tsrc/check/gst/gsturi/src/gsturi.c
gstreamer_core/tsrc/check/gst/gstutils/src/gstutils.c
gstreamer_core/tsrc/check/gst/gstvalue/src/gstvalue.c
gstreamer_core/tsrc/check/libs/adapter/src/adapter.c
gstreamer_core/tsrc/check/libs/basesrc/src/basesrc.c
gstreamer_core/tsrc/check/libs/collectpads/src/collectpads.c
gstreamer_core/tsrc/check/libs/controller/src/controller.c
gstreamer_core/tsrc/check/libs/gdp/src/gdp.c
gstreamer_core/tsrc/check/libs/gstnetclientclock/src/gstnetclientclock.c
gstreamer_core/tsrc/check/libs/gstnettimeprovider/src/gstnettimeprovider.c
gstreamer_core/tsrc/check/libs/libsabi/src/libsabi.c
gstreamer_core/tsrc/check/libs/typefindhelper/src/typefindhelper.c
gstreamer_core/tsrc/check/pipelines/cleanup/src/cleanup.c
gstreamer_core/tsrc/check/pipelines/core-simple-launch-lines/src/core-simple-launch-lines.c
gstreamer_core/tsrc/check/pipelines/parse-disabled/src/parse-disabled.c
gstreamer_core/tsrc/check/pipelines/parse-launch/src/parse-launch.c
gstreamer_core/tsrc/check/pipelines/stress/src/stress.c
gstreamer_core/tsrc/examples/adapter/src/adapter_test.c
gstreamer_core/tsrc/examples/controller/src/audio-example.c
gstreamer_core/tsrc/examples/helloworld/src/helloworld.c
gstreamer_core/tsrc/examples/launch/data/Crnival.mp3
gstreamer_core/tsrc/examples/launch/group/bld.inf
gstreamer_core/tsrc/examples/launch/src/launch.c
gstreamer_core/tsrc/examples/launch/src/mp3parselaunch.c
gstreamer_core/tsrc/examples/manual/bin/src/bin.c
gstreamer_core/tsrc/examples/manual/createelements/src/elementcreate.c
gstreamer_core/tsrc/examples/manual/elementfactory/src/elementfactory.c
gstreamer_core/tsrc/examples/manual/getelements/src/elementget.c
gstreamer_core/tsrc/examples/manual/init/src/init.c
gstreamer_core/tsrc/examples/manual/linkelements/src/elementlink.c
gstreamer_core/tsrc/examples/manual/makeelements/src/elementmake.c
gstreamer_core/tsrc/examples/manual/manual_decodebin/src/manual_decodebin.c
gstreamer_core/tsrc/examples/manual/manual_dynamic/src/manual_dynamic.c
gstreamer_core/tsrc/examples/manual/manual_ghostpad/src/manual_ghostpad.c
gstreamer_core/tsrc/examples/manual/manual_helloworld/group/bld.inf
gstreamer_core/tsrc/examples/manual/manual_helloworld/src/manual_helloworld.c
gstreamer_core/tsrc/examples/manual/manual_playbin/src/manual_playbin.c
gstreamer_core/tsrc/examples/manual/manual_typefind/src/manual_typefind.c
gstreamer_core/tsrc/examples/manual/pad/src/pad.c
gstreamer_core/tsrc/examples/manual/query/group/bld.inf
gstreamer_core/tsrc/examples/manual/query/src/query.c
gstreamer_core/tsrc/examples/metadata/src/read-metadata.c
gstreamer_core/tsrc/examples/queue/src/queue.c
gstreamer_core/tsrc/examples/typefind/src/typefind.c
gstreamer_core/tsrc/group/bld.inf
gstreamer_core/tsrc/group/custom/precase_custom.xml
gstreamer_core/tsrc/gstreamertestcases/Bwins/GstreamerTestCasesU.DEF
gstreamer_core/tsrc/gstreamertestcases/EABI/GstreamerTestCasesU.def
gstreamer_core/tsrc/gstreamertestcases/conf/GstreamerTestCases.cfg
gstreamer_core/tsrc/gstreamertestcases/group/GstreamerTestCases.mmp
gstreamer_core/tsrc/gstreamertestcases/group/GstreamerTestCases_DoxyFile.txt
gstreamer_core/tsrc/gstreamertestcases/group/bld.inf
gstreamer_core/tsrc/gstreamertestcases/group/gstreamer_testcases.pkg
gstreamer_core/tsrc/gstreamertestcases/inc/GstreamerTestCases.h
gstreamer_core/tsrc/gstreamertestcases/init/gstreamertestcases.ini
gstreamer_core/tsrc/gstreamertestcases/init/testframework.ini
gstreamer_core/tsrc/gstreamertestcases/src/GstreamerTestCases.cpp
gstreamer_core/tsrc/gstreamertestcases/src/GstreamerTestCasesBlocks.cpp
gstreamer_core/tsrc/gstreamertestcases_suite1/Bwins/gstreamertestcases_suite1u.def
gstreamer_core/tsrc/gstreamertestcases_suite1/EABI/gstreamertestcases_suite1u.def
gstreamer_core/tsrc/gstreamertestcases_suite1/conf/gstreamertestcases_suite1.cfg
gstreamer_core/tsrc/gstreamertestcases_suite1/data/khuda.wav
gstreamer_core/tsrc/gstreamertestcases_suite1/group/GstreamerTestCases_DoxyFile.txt
gstreamer_core/tsrc/gstreamertestcases_suite1/group/GstreamerTestCases_suite1.mmp
gstreamer_core/tsrc/gstreamertestcases_suite1/group/bld.inf
gstreamer_core/tsrc/gstreamertestcases_suite1/group/gstreamer_testcases.pkg
gstreamer_core/tsrc/gstreamertestcases_suite1/inc/GstreamerTestCases.h
gstreamer_core/tsrc/gstreamertestcases_suite1/init/gstreamertestcases_suite1.ini
gstreamer_core/tsrc/gstreamertestcases_suite1/init/testframework.ini
gstreamer_core/tsrc/gstreamertestcases_suite1/src/GstreamerTestCases.cpp
gstreamer_core/tsrc/gstreamertestcases_suite1/src/GstreamerTestCasesBlocks.cpp
gstreamer_core/tsrc/gstreamertestcases_suite2/Bwins/gstreamertestcases_suite2u.def
gstreamer_core/tsrc/gstreamertestcases_suite2/EABI/gstreamertestcases_suite2u.def
gstreamer_core/tsrc/gstreamertestcases_suite2/conf/gstreamertestcases_suite2.cfg
gstreamer_core/tsrc/gstreamertestcases_suite2/data/khuda.wav
gstreamer_core/tsrc/gstreamertestcases_suite2/group/GstreamerTestCases_DoxyFile.txt
gstreamer_core/tsrc/gstreamertestcases_suite2/group/GstreamerTestCases_suite2.mmp
gstreamer_core/tsrc/gstreamertestcases_suite2/group/bld.inf
gstreamer_core/tsrc/gstreamertestcases_suite2/group/gstreamer_testcases.pkg
gstreamer_core/tsrc/gstreamertestcases_suite2/inc/GstreamerTestCases.h
gstreamer_core/tsrc/gstreamertestcases_suite2/init/gstreamertestcases_suite2.ini
gstreamer_core/tsrc/gstreamertestcases_suite2/init/testframework.ini
gstreamer_core/tsrc/gstreamertestcases_suite2/src/GstreamerTestCases.cpp
gstreamer_core/tsrc/gstreamertestcases_suite2/src/GstreamerTestCasesBlocks.cpp
gstreamer_core/tsrc/gstreamertestcases_suite3/Bwins/gstreamertestcases_suite3u.def
gstreamer_core/tsrc/gstreamertestcases_suite3/EABI/gstreamertestcases_suite3u.def
gstreamer_core/tsrc/gstreamertestcases_suite3/conf/gstreamertestcases_suite3.cfg
gstreamer_core/tsrc/gstreamertestcases_suite3/data/khuda.wav
gstreamer_core/tsrc/gstreamertestcases_suite3/group/GstreamerTestCases_DoxyFile.txt
gstreamer_core/tsrc/gstreamertestcases_suite3/group/GstreamerTestCases_suite3.mmp
gstreamer_core/tsrc/gstreamertestcases_suite3/group/bld.inf
gstreamer_core/tsrc/gstreamertestcases_suite3/group/gstreamer_testcases.pkg
gstreamer_core/tsrc/gstreamertestcases_suite3/inc/GstreamerTestCases.h
gstreamer_core/tsrc/gstreamertestcases_suite3/init/gstreamertestcases_suite3.ini
gstreamer_core/tsrc/gstreamertestcases_suite3/init/testframework.ini
gstreamer_core/tsrc/gstreamertestcases_suite3/src/GstreamerTestCases.cpp
gstreamer_core/tsrc/gstreamertestcases_suite3/src/GstreamerTestCasesBlocks.cpp
gstregistrygenerator/group/gstregistrygenerator.mmp
gstregistrygenerator/src/gstregistrygenerator.cpp
rom/gstreamer.iby
sis/gstreamer.pkg
sis/gstreamer_framework.pkg
tsrc/group/bld.inf
tsrc/group/gstreamer_testcases.pkg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer.pro	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,33 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Wed Feb 17 14:34:47 2010
+######################################################################
+
+
+# ============================================================================
+#  Name        : QtGSTPlayer.pro
+#  Part of     : LibHb / gstplayer
+#  Description : Project definition file for simple gstplayer
+#  Version     : %version: 1 %
+#
+#  Copyright ? 2008 Nokia.  All rights reserved.
+#  This material, including documentation and any related computer
+#  programs, is protected by copyright controlled by Nokia.  All
+#  rights are reserved.  Copying, including reproducing, storing,
+#  adapting or translating, any or all of this material requires the
+#  prior written consent of Nokia.  This material also contains
+#  confidential information which may not be disclosed to others
+#  without the prior written consent of Nokia.
+# ============================================================================
+#
+
+TEMPLATE = app
+TARGET = 
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp folderview.cpp views.cpp record_play.c
+HEADERS += folderview.h views.h
+
+RESOURCES += QtGSTPlayer.qrc
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer.qrc	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/QtGSTPlayer" >
+        <file>folder.png</file>
+        <file>settings.png</file>
+    </qresource>
+</RCC>
Binary file QtGSTPlayer/folder.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/folderview.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,357 @@
+#include <QModelIndex>
+#include <QDirModel>
+#include <QApplication>
+
+//#include <hbformitem.h>
+//#include <hbformview.h>
+#include <hblistview.h>
+#include <hblistviewitem.h>
+#include <hbmenu.h>
+#include <hbmainwindow.h>
+
+#include <QDebug>
+#include <QAction>
+#include <HbAction>
+#include "folderview.h"
+#include "views.h"
+#include <HbAbstractViewItem>
+#include <QTimer>
+#include <hbnotificationdialog.h>
+/*! Constructor of FolderView. 
+ */
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+int mCurrentState = 0;
+
+#ifdef __cplusplus
+}
+#endif
+//extern int mCurrentState;
+
+FolderView::FolderView(QGraphicsItem *parent)
+        : HbView(parent),mModel( NULL ), mFolderPath("c:\\data\\Sounds\\Digital\\"),mTimer(NULL),mIsRecording( FALSE )
+{
+    mCurrentState = NONE;
+   
+    // Create a main widget for this view 
+    // In this case, list view is appropriate
+    // Note: HbListView is not derived from HbView,
+    // this is just like any other Hb widget but with a feature of 
+    // model-view separation
+    mFileList = new HbListView(this);
+
+    // Create a model to set for the list view
+    mModel = new QDirModel(this);
+    mFileList->setModel(mModel);
+    
+    // Setting initial path for folder list
+    mFileList->setRootIndex(mModel->index(mFolderPath));
+    //mFileList->
+    // Setting the main widget for this view
+    setWidget(mFileList);
+    //int x = mFileList->indexCount();    
+    QObject::connect(mFileList, SIGNAL(pressed(const QModelIndex)), this, SLOT(item_pressed(const QModelIndex)));
+
+    // add menu
+    HbMenu* menu1 = menu()->addMenu(tr("Record"));
+
+    HbAction* menu1_Action = new HbAction(tr("RAW"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_RAW()));
+    menu1->addAction( menu1_Action );
+
+    menu1_Action = new HbAction(tr("WAV"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_WAV()));
+    menu1->addAction( menu1_Action );
+
+    //create action Nokia India sub menu item.
+    menu1_Action = new HbAction(tr("AMR"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_AMR()));
+    menu1->addAction( menu1_Action );
+
+    menu1_Action = new HbAction(tr("G711"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_G711()));
+    menu1->addAction( menu1_Action );
+    
+    menu1_Action = new HbAction(tr("AAC"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_AAC()));
+    menu1->addAction( menu1_Action );
+    menu1_Action = new HbAction(tr("G729"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_G729()));
+    menu1->addAction( menu1_Action );
+
+    menu1_Action = new HbAction(tr("ILBC"), this);
+    connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_ILBC()));
+    menu1->addAction( menu1_Action );
+    
+   
+
+    //menu()->addAction(tr("Play"), this, SLOT(play()));
+    menu()->addAction(tr("Stop"), this, SLOT(stop()));
+    menu()->addAction(tr("Pause"), this, SLOT(pause()));
+    menu()->addAction(tr("Resume"), this, SLOT(resume()));
+    menu()->addAction(tr("Exit"), qApp, SLOT(quit()));
+    
+    
+    /// timer required to get the glib events
+    mTimer = new QTimer(this);
+    connect(mTimer, SIGNAL(timeout()), this, SLOT(timertimeout()));
+    mTimer->start(10);
+
+}
+
+FolderView::~FolderView()
+{
+    if(mCurrentState != NONE)
+        gst_unref();
+delete mFileList;
+delete mModel;
+mTimer->stop();
+delete mTimer;
+}
+
+
+void FolderView::folderViewTriggered()
+{
+    mainWindow()->setCurrentView(Views::folderView());
+}
+
+/*void FolderView::settingsViewTriggered()
+{
+    mainWindow()->setCurrentView(Views::settingsView());
+}*/
+
+void FolderView::showNote(const int err)
+{
+    if(err)
+    {
+        HbNotificationDialog* notifyDialog = new HbNotificationDialog;
+        notifyDialog->setTimeout(HbPopup::StandardTimeout);
+        QString strong;
+        QString sprint= strong.sprintf("Format Not supported(%d)",err);
+        notifyDialog->setTitleTextWrapping(Hb::TextWordWrap);
+        notifyDialog->setTitle(QString("Error"));
+        notifyDialog->setWrapMode(Hb::TextWordWrap);
+        notifyDialog->setText(sprint);
+        
+        notifyDialog->exec();
+        delete notifyDialog;
+    }
+}
+void FolderView::item_pressed(const QModelIndex &index)
+{
+    if( mIsRecording )
+    {
+        return;
+    }
+    QVariant variant=index.data();
+    QString str = variant.toString();
+    
+    
+    QString fullpath = mFolderPath;
+    fullpath.append( str );
+    
+    TBuf16<1024> buf16;
+    buf16.Copy( (TUint16*)fullpath.data_ptr()->data ,fullpath.data_ptr()->size );
+    TBuf8<1024> buf8;
+    buf8.Copy( buf16 );
+
+    if( NONE != mCurrentState )
+    {
+    gst_unref();
+    }
+   
+    int err = gst_play_file( (char*)buf8.PtrZ() );
+    if(err)
+    {
+        showNote(err);
+        mCurrentState = NONE;
+    }
+    else
+    {
+        mCurrentState = PLAYING;
+    }   
+
+}
+void FolderView::pause()
+{
+    if( PLAYING == mCurrentState  ){
+    gst_pause();
+    mCurrentState = PAUSE;
+    }
+}
+
+void FolderView::resume()
+{
+    if( PAUSE == mCurrentState  ){
+    gst_resume();
+    mCurrentState = PLAYING;
+    }
+}
+
+void FolderView::stop()
+{
+    if( mIsRecording == TRUE )
+    {
+        gst_record_stop();
+    
+        if( mModel )
+            delete mModel;
+        
+        mModel = new QDirModel(this);
+        mFileList->setModel(mModel);
+
+        mFileList->reset();
+        mFileList->setRootIndex(mModel->index(mFolderPath));
+//        mFileList->show();
+//      int x = mFileList->indexCount();
+        //setWidget(mFileList);
+        mIsRecording = FALSE;
+        return;
+    }
+    if( PLAYING == mCurrentState || PAUSE == mCurrentState ){
+    gst_unref();
+    mCurrentState = NONE;
+    }
+}
+
+void FolderView::record_AMR()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_AMR );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+    }
+}
+
+void FolderView::record_WAV()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_WAV );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+        //gst_record_wav();
+    }    
+}
+
+void FolderView::record_RAW()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_RAW );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+    }
+}
+
+void FolderView::record_G711()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_G711 );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+    }
+}
+
+void FolderView::record_G729()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_G729 );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+    }
+}
+
+void FolderView::record_ILBC()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_ILBC );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+    }
+}
+
+void FolderView::record_AAC()
+{
+    if( mCurrentState == NONE ){
+        int err = gst_record_file( RECORD_AAC );
+        if(err)
+        {
+            showNote(err);
+            mCurrentState = NONE;
+            mIsRecording = FALSE;
+        }
+        else
+        {
+            mCurrentState = PLAYING;
+            mIsRecording = TRUE;
+        }
+    }
+}
+void FolderView::timertimeout()
+{
+    if( PLAYING == mCurrentState ){
+    gst_get_events();
+    }
+    
+    if( STOP == mCurrentState ){
+        gst_unref();
+        mCurrentState = NONE;
+        mIsRecording = FALSE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/folderview.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,64 @@
+#ifndef FOLDERVIEW_H
+#define FOLDERVIEW_H
+
+#include <hbview.h>
+//#include <hbformview.h>
+
+#include "record_play.h"
+
+QT_BEGIN_NAMESPACE
+class QDirModel;
+QT_END_NAMESPACE
+
+//class HbFormItem;
+class HbListView;
+
+class FolderView : public HbView
+{
+    Q_OBJECT
+
+public:
+    explicit FolderView(QGraphicsItem *parent = 0);
+    ~FolderView();
+public slots:
+    void folderViewTriggered();
+    //void settingsViewTriggered();
+    void item_pressed(const QModelIndex &index);
+//
+    void record_AMR();
+    void record_WAV();
+    void record_RAW();
+    void record_G711();
+    void record_G729();
+    void record_ILBC();
+    void record_AAC();
+
+    void pause();
+    void resume();
+    void stop();
+    void timertimeout();
+    void showNote(const int err);
+
+//void record_file( int type );
+
+
+private:
+    HbListView *mFileList;
+
+//signals:
+//    void pressed(const QModelIndex &index);
+//    void released(const QModelIndex &index);
+//    void activated(const QModelIndex &index);
+//    void longPressed(HbAbstractViewItem *item, const QPointF &coords);
+
+    QDirModel *mModel;
+    QString mFolderPath;
+    QTimer *mTimer;
+    bool mIsRecording;
+    
+    
+    //state st;
+
+};
+
+#endif // FOLDERVIEW_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/main.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,52 @@
+/*! This is an example application demonstrating how a simple Hb
+  application is created. This application implements a folder
+  browser.  The application creates two views. The main view (Folder
+  view) shows the folder contents. The second view (Settings view) can
+  be used to set the path which is shown in the Folder view.  Settings
+  view uses the HbFormView. Folder view inherits HbView and implements
+  a couple of methods to populate the Folder view.  */
+
+#include <hbapplication.h>
+#include <hbmainwindow.h>
+#include <hbmenu.h>
+#include <hbaction.h>
+#include <hbtoolbar.h>
+
+
+#include <gst/gst_global.h>
+#include <stdlib.h>
+#include <gst/gst.h>
+
+#include "folderview.h"
+#include "views.h"
+
+int main(int argc, char *argv[])
+{
+    // Create HbApplication
+    gst_init (&argc, &argv);
+    HbApplication a(argc, argv);
+    a.setApplicationName(QObject::tr("Folder Browser"));
+    //LOG(_L("Entering main.cpp"));
+
+    // Create main window
+    HbMainWindow mainWindow;
+
+    // Create View#1 : Folder view
+    HbView *folderView = new FolderView;
+    // Title pane text
+    folderView->setTitle(QObject::tr("QtGSTPlayer"));
+ 
+    // Add two views to main window, 
+    // the adding order determines which one is shown first
+  
+    mainWindow.addView(folderView);
+    /*mainWindow.addView(settingsView);*/
+
+    // Store the mainwindow ptr.
+    Views::win = &mainWindow;
+
+    // Show main window
+    mainWindow.show();
+
+    return a.exec();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/record_play.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,855 @@
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <gst/gst.h>
+#include "record_play.h"
+
+
+GstElement *bin;
+extern int mCurrentState;
+
+static GstElement *
+create_video_output ()
+{
+  static gboolean have_video = FALSE;
+  GstBin *bin;
+  GstElement *queue, *sink;
+  GstPad *pad;
+
+  if (have_video) {
+    //g_print ("Already playing a video stream. Ignoring this one\n");
+    return NULL;
+  }
+  
+  /* create a new bin to hold the elements */
+  if((bin = (GstBin*) gst_bin_new (NULL)) == NULL)
+  //bin = (GstBin*) gst_pipeline_new("pipeline");
+  return NULL;
+
+  /* Queue to ensure all streams can push data */
+  queue = gst_element_factory_make ("queue", "q");
+  if(queue == NULL)
+      return NULL;/* Queue should always be available */
+  /* Set the queue to buffer 1/10 of a second of raw video */
+  g_object_set (queue, "max-size-time", (GstClockTime) GST_SECOND / 10,
+      "max-size-bytes", 0, "max-size-buffers", 0, NULL);
+
+//  cs = gst_element_factory_make ("ffmpegcolorspace", "cs");
+//  if (!cs)
+//    goto no_output;
+    
+  /* and a video sink */
+  sink = gst_element_factory_make ("fakesink"/*autovideosink*/, "sink");
+  if (!sink)
+    goto no_output;
+
+  /* add objects to the main pipeline */
+  gst_bin_add_many (GST_BIN (bin), queue, sink, NULL);
+
+  /* Link the elements */
+  gst_element_link_many (queue, sink, NULL);
+
+  /* Retrieve the sinkpad from the queue and 'ghost' it onto
+   * the bin so that the caller can find it generically */
+  pad = gst_element_get_pad (queue, "sink");
+  gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
+  gst_object_unref (pad);
+
+  //have_video = TRUE;
+
+  return GST_ELEMENT (bin);
+
+  /* ERRORS */
+no_output:
+  {
+    //g_print ("Could not create either ffmpegcolorspace or autovideosink for output");
+    return NULL;
+  }
+}
+
+static GstElement *
+create_audio_output ()
+{
+  static gboolean have_audio = FALSE;
+  GstBin *bin;
+  GstElement *queue, *audioconvert,*audioresample, *sink;
+  GstPad *pad;
+
+  if (have_audio) {
+    //g_print ("Already playing an audio stream. Ignoring this one\n");
+    return NULL;
+  }
+
+  /* create a new bin to hold the elements */
+  bin = (GstBin*) gst_bin_new (NULL);
+  if(!bin)
+      goto no_output;
+  
+  /* Queue to ensure all streams can push data */
+  queue = gst_element_factory_make ("queue", "q");
+  if (!queue) /* Queue should always be available */
+      goto no_output;
+  /* Set the queue to buffer 1/10 of a second of raw audio */
+  g_object_set (queue, "max-size-time", (GstClockTime) GST_SECOND / 10,
+      "max-size-bytes", 0, "max-size-buffers", 0, NULL);
+
+  /* an audio converter to convert floating-point audio samples to int format */
+  audioconvert = gst_element_factory_make ("audioconvert", "ac");
+  if (!audioconvert)
+      goto no_output;
+
+  /* an audio converter to convert floating-point audio samples to int format */
+  audioresample = gst_element_factory_make ("audioresample", "audioresample");
+  if (!audioresample)
+      goto no_output;
+  
+  /* and an audio sink */
+  sink = gst_element_factory_make ("autoaudiosink", "sink");
+  if (!sink)
+      goto no_output;
+
+  /* add objects to the bin */
+  gst_bin_add_many (GST_BIN (bin), queue, audioconvert,audioresample, sink, NULL);
+
+  /* link the elements */
+  gst_element_link_many (queue, audioconvert,audioresample, sink, NULL);
+
+  /* Retrieve the sinkpad from the queue element and 'ghost' it onto
+   * the bin so that the caller can find it generically */
+  pad = gst_element_get_pad (queue, "sink");
+  gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
+  gst_object_unref (pad);
+
+  //have_audio = TRUE;
+
+  return GST_ELEMENT (bin);
+
+  /* ERRORS */
+no_output:
+  { 
+    //g_print ("Could not create either ffmpegcolorspace or autovideosink for output");
+    return NULL;
+  }
+}
+
+static void 
+new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
+      GstBin *top_pipeline)
+{
+  GstPad *out_pad;
+  GstElement *output = NULL;
+  GstCaps *caps;
+  GstStructure *s;
+  const gchar *stream_type;
+
+  /* Decide which output we are creating based on the stream contents */
+  caps = gst_pad_get_caps (pad);
+  if (caps == NULL) {
+    //g_print ("Decodebin produced an unknown stream - ignoring\n");
+    return;
+  }
+  
+  s = gst_caps_get_structure (caps, 0);
+  if(s == NULL)/* Caps on a pad should always have exactly one entry */
+      return;
+  
+  stream_type = gst_structure_get_name (s);
+  
+  if (g_str_has_prefix (stream_type, "video/x-raw-")) {
+    /* Is a new video stream */
+    //g_print ("Encountered a new video stream\n");
+    output = create_video_output ();
+  }
+  else if (g_str_has_prefix (stream_type, "audio/x-raw-")) {
+    //g_print ("Encountered a new audio stream\n");
+    output = create_audio_output ();
+  }
+  else {
+    //g_print ("Found unknown stream of type %s - ignoring\n", stream_type);
+  }
+  
+  /* If no renderer was created, ignore this stream */
+  if (output == NULL)
+    return;
+
+  /* Add the output into our pipeline */
+  gst_bin_add (top_pipeline, output);
+  
+  /* If we created a output pipeline, retrieve the sink pad from it */
+  out_pad = gst_element_get_pad (output, "sink");
+  g_return_if_fail (out_pad != NULL);
+
+  /* Attempt to link the new pad to the output */  
+  if (gst_pad_link (pad, out_pad) != GST_PAD_LINK_OK) {
+    //g_print ("Failed to add the rendering pipeline for this new data stream\n");
+    gst_bin_remove (top_pipeline, output);
+    gst_object_unref (out_pad);
+    return;
+  }
+  gst_object_unref (out_pad);
+  
+  /* New output renderer is successfully linked in the pipeline.
+   * Change its state to playing so it is ready to receive data */
+  gst_element_set_state (output, GST_STATE_PLAYING);
+}
+
+static void
+print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
+{
+  gint i, count;
+
+  count = gst_tag_list_get_tag_size (list, tag);
+
+  for (i = 0; i < count; i++) {
+    gchar *str;
+
+    if (gst_tag_get_type (tag) == G_TYPE_STRING) {
+      if (!gst_tag_list_get_string_index (list, tag, i, &str))
+        g_assert_not_reached ();
+    } else {
+      str =
+          g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
+    }
+
+    if (i == 0) {
+      //g_print ("  %15s: %s\n", gst_tag_get_nick (tag), str);
+    } else {
+      //g_print ("                 : %s\n", str);
+    }
+
+    g_free (str);
+  }
+}
+
+
+
+static gboolean
+bus_call (GstBus     *bus,
+          GstMessage *message,
+          gpointer    data)
+{
+  switch (GST_MESSAGE_TYPE (message)){
+      case GST_MESSAGE_EOS:
+        gst_message_unref (message);
+        gst_element_set_state (bin, GST_STATE_NULL);
+        /* Unreffing the bin will clean up all its children too */
+        gst_object_unref (bin);           
+        mCurrentState = NONE;
+        break;
+      case GST_MESSAGE_ERROR:{
+        GError *gerror;
+        gchar *debug;
+
+        gst_message_parse_error (message, &gerror, &debug);
+        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+        gst_message_unref (message);
+        g_error_free (gerror);
+        g_free (debug);
+        gst_element_set_state (bin, GST_STATE_NULL);
+        /* Unreffing the bin will clean up all its children too */
+        gst_object_unref (bin);           
+        mCurrentState = NONE;
+        break;
+      }
+      case GST_MESSAGE_WARNING:{
+        GError *gerror;
+        gchar *debug;
+
+        gst_message_parse_warning (message, &gerror, &debug);
+        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+        gst_message_unref (message);
+        g_error_free (gerror);
+        g_free (debug);
+        break;
+      }
+      case GST_MESSAGE_TAG:
+      {
+        GstTagList *tags;
+
+        gst_message_parse_tag (message, &tags);
+        if (tags) {
+          //g_print ("TAGS received from element \"%s\".\n",
+           //   GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
+
+          gst_tag_list_foreach (tags, print_tag, NULL);
+          gst_tag_list_free (tags);
+          tags = NULL;
+        }
+        break;
+      }
+      default:
+        gst_message_unref (message);
+        break;
+    }
+  return TRUE;
+}
+
+
+
+//static void
+//event_loop (GstElement * pipe)
+//{
+//  GstBus *bus;
+//  GstMessage *message = NULL;
+//
+//  bus = gst_element_get_bus (GST_ELEMENT (pipe));
+//
+//  while (TRUE) {
+//    message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1);
+//
+//    g_assert (message != NULL);
+//
+//    switch (message->type) {
+//      case GST_MESSAGE_EOS:
+//        gst_message_unref (message);
+//        return;
+//      case GST_MESSAGE_ERROR:{
+//        GError *gerror;
+//        gchar *debug;
+//
+//        gst_message_parse_error (message, &gerror, &debug);
+//        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+//        gst_message_unref (message);
+//        g_error_free (gerror);
+//        g_free (debug);
+//        return;
+//      }
+//      case GST_MESSAGE_WARNING:{
+//        GError *gerror;
+//        gchar *debug;
+//
+//        gst_message_parse_warning (message, &gerror, &debug);
+//        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+//        gst_message_unref (message);
+//        g_error_free (gerror);
+//        g_free (debug);
+//        break;
+//      }
+//      case GST_MESSAGE_TAG:
+//      {
+//        GstTagList *tags;
+//
+//        gst_message_parse_tag (message, &tags);
+//        if (tags) {
+//          //g_print ("TAGS received from element \"%s\".\n",
+//              GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
+//
+//          gst_tag_list_foreach (tags, print_tag, NULL);
+//          gst_tag_list_free (tags);
+//          tags = NULL;
+//        }
+//        break;
+//      }
+//      default:
+//        gst_message_unref (message);
+//        break;
+//    }
+//  }
+//}
+
+int
+gst_play_file (const char* file)
+{
+  GstElement *filesrc, *decodebin, *sink;
+  GstCaps* caps;
+  //int length = strlen( file );
+  //gst_init (&argc, &argv);
+
+  if (file == NULL) {
+    //g_print ("file is not present");
+    goto no_output;
+  }
+
+  //g_print ("Constructing pipeline\n");
+  
+  /* create a new bin to hold the elements */
+  bin = gst_pipeline_new ("pipeline");
+  if(!bin)
+      goto no_output;
+
+  /* create a disk reader */
+  filesrc = gst_element_factory_make ("filesrc", "disk_source");
+  if(!filesrc)
+      goto no_output;
+  
+  g_object_set (G_OBJECT (filesrc), "location", file, NULL);
+
+  if( g_str_has_suffix (file, "raw") )
+  {
+      sink = gst_element_factory_make ("devsoundsink", "sink");
+      caps = gst_caps_new_simple ("audio/x-raw-int",
+                   "width", G_TYPE_INT, 16,
+                   "depth", G_TYPE_INT, 16,
+                   "signed",G_TYPE_BOOLEAN, TRUE,
+                   "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                   "rate", G_TYPE_INT,  8000,
+                   "channels", G_TYPE_INT, 1, NULL);     
+      gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
+      
+      gst_element_link_filtered (filesrc, sink, caps);      
+  }
+  else if( g_str_has_suffix (file, "g711") )
+  {
+      sink = gst_element_factory_make ("devsoundsink", "sink");
+      caps = gst_caps_new_simple ("audio/x-alaw",
+                   "width", G_TYPE_INT, 16,
+                   "depth", G_TYPE_INT, 16,
+                   "signed",G_TYPE_BOOLEAN, TRUE,
+                   "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                   "rate", G_TYPE_INT,  8000,
+                   "channels", G_TYPE_INT, 1, NULL);   
+      gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
+      
+      gst_element_link_filtered (filesrc, sink, caps);     
+  }
+  else if( g_str_has_suffix (file, "g729") )
+  {
+      sink = gst_element_factory_make ("devsoundsink", "sink");
+      caps = gst_caps_new_simple ("audio/g729",
+                   "width", G_TYPE_INT, 16,
+                   "depth", G_TYPE_INT, 16,
+                   "signed",G_TYPE_BOOLEAN, TRUE,
+                   "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                   "rate", G_TYPE_INT,  8000,
+                   "channels", G_TYPE_INT, 1, NULL);  
+      gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
+      
+      gst_element_link_filtered (filesrc, sink, caps);   
+  }
+  else if( g_str_has_suffix (file, "ilbc") )
+  {
+      sink = gst_element_factory_make ("devsoundsink", "sink");
+      
+      caps = gst_caps_new_simple ("audio/ilbc",
+                   "width", G_TYPE_INT, 16,
+                   "depth", G_TYPE_INT, 16,
+                   "signed",G_TYPE_BOOLEAN, TRUE,
+                   "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                   "rate", G_TYPE_INT,  8000,
+                   "channels", G_TYPE_INT, 1, NULL);   
+      
+      gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
+
+      gst_element_link_filtered (filesrc, sink, caps);   
+  }
+  else if( g_str_has_suffix (file, "amr") )
+  {
+      sink = gst_element_factory_make ("devsoundsink", "sink");
+      caps = gst_caps_new_simple ("audio/amr",
+                   "width", G_TYPE_INT, 8,
+                   "depth", G_TYPE_INT, 8,
+                   "signed",G_TYPE_BOOLEAN, TRUE,
+                   "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                   "rate", G_TYPE_INT,  8000,
+                   "channels", G_TYPE_INT, 1, NULL);   
+      gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
+      
+      //gst_element_link (source, sink);
+      gst_element_link_filtered (filesrc, sink, caps);     
+  }
+  
+  else
+  {
+      /* Create the decodebin */
+      decodebin = gst_element_factory_make ("decodebin", NULL);
+      if (!decodebin) {
+        //g_print ("could not find the \"decodebin\" element\n");
+        return -1;
+      }
+    
+      /* add objects to the main pipeline */
+      gst_bin_add_many (GST_BIN (bin), filesrc, decodebin, NULL);
+    
+      /* link the elements. */
+      gst_element_link_many (filesrc, decodebin, NULL);
+      
+      /* Connect to decodebin's 'new-decoded-pad' signal to detect when it produces
+       * a new stream */
+      g_signal_connect (G_OBJECT (decodebin), "new-decoded-pad", 
+          G_CALLBACK (new_decoded_pad), bin);
+  }
+
+  gst_bus_add_watch( gst_pipeline_get_bus (GST_PIPELINE (bin)), bus_call, NULL);
+  //g_print ("Starting playback\n");   
+  /* start playing */
+  gst_element_set_state (bin, GST_STATE_PLAYING);
+  return 0;
+  
+no_output:
+      return -1;
+  
+}
+
+
+int
+gst_record_file (int type)
+{
+    GstElement *audiosrc, *filesink;
+    char* carray = NULL;
+    GstCaps* caps;
+    //g_print ("Constructing pipeline\n");
+    
+    /* switch case for recording type*/
+    switch( type )
+    {
+        case RECORD_RAW: 
+            caps = gst_caps_new_simple ("audio/x-raw-int",
+                       "width", G_TYPE_INT, 16,
+                       "depth", G_TYPE_INT, 16,
+                       "signed",G_TYPE_BOOLEAN, TRUE,
+                       "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                       "rate", G_TYPE_INT,  8000,
+                       "channels", G_TYPE_INT, 1, NULL);
+            
+            carray = "c:\\data\\sounds\\Digital\\record.raw";
+            break;
+            
+        case RECORD_AMR: 
+            {
+            return gst_record_amr();
+            }
+            break;
+
+        case RECORD_G711:  
+
+            caps = gst_caps_new_simple ("audio/x-alaw",
+                       "width", G_TYPE_INT, 8,
+                       "depth", G_TYPE_INT, 8,
+                       "signed",G_TYPE_BOOLEAN, TRUE,
+                       "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                       "rate", G_TYPE_INT,  8000,
+                       "channels", G_TYPE_INT, 1, NULL);
+
+            carray = "c:\\data\\sounds\\Digital\\record.g711";
+            break;
+            
+        case RECORD_G729: // 
+
+            caps = gst_caps_new_simple ("audio/g729",
+                       "width", G_TYPE_INT, 16,
+                       "depth", G_TYPE_INT, 16,
+                       "signed",G_TYPE_BOOLEAN, TRUE,
+                       "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                       "rate", G_TYPE_INT,  8000,
+                       "channels", G_TYPE_INT, 1, NULL);
+            
+            carray = "c:\\data\\sounds\\Digital\\record.g729";
+            break;
+            
+        case RECORD_ILBC: // 
+
+            caps = gst_caps_new_simple ("audio/ilbc",
+                       "width", G_TYPE_INT, 16,
+                       "depth", G_TYPE_INT, 16,
+                       "signed",G_TYPE_BOOLEAN, TRUE,
+                       "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                       "rate", G_TYPE_INT,  8000,
+                       "channels", G_TYPE_INT, 1, NULL);
+            
+            carray = "c:\\data\\sounds\\Digital\\record.ilbc";
+            break;
+        case RECORD_WAV:
+            {
+                return gst_record_wav();
+            }
+            break;
+        case RECORD_AAC:
+            {
+                return gst_record_aac();
+            }
+            break;
+        default:
+            return -1;
+            break;            
+    }
+    /* create a new bin to hold the elements */
+    bin = gst_pipeline_new ("pipeline");
+    if(!bin)
+        goto no_output;
+    
+    /* create a disk reader */
+    audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
+    if(!audiosrc)
+        goto no_output;
+   
+    /* Create the decodebin */
+    filesink = gst_element_factory_make ("filesink", NULL);
+    if(!filesink)
+        goto no_output;
+    
+    g_object_set (G_OBJECT (audiosrc),
+              "blocksize", 1280,
+               NULL);
+    
+    g_object_set (G_OBJECT (filesink), "location", carray,"buffer-size",1280, NULL);
+   
+    /* add objects to the main pipeline */
+    gst_bin_add_many (GST_BIN (bin), audiosrc, filesink, NULL);
+
+    /* link the elements. */
+    gst_element_link_filtered (audiosrc, filesink, caps);
+    //gst_element_link_many (audiosrc, filesink, NULL);
+    gst_bus_add_watch( gst_pipeline_get_bus (GST_PIPELINE (bin)), bus_call, NULL);
+    
+    //g_print ("Starting recoring\n");   
+    /* start playing */
+    gst_element_set_state (bin, GST_STATE_PLAYING);
+
+    /* Run event loop listening for bus messages until EOS or ERROR */
+    //event_loop (bin);
+    
+//    //g_print ("Finished playback - stopping pipeline\n");
+//    
+//    /* stop the bin */
+//    gst_element_set_state (bin, GST_STATE_NULL);
+//    
+//    /* Unreffing the bin will clean up all its children too */
+//    gst_object_unref (bin);
+//    
+    return 0;
+no_output:
+    return -1;
+
+}
+
+
+int
+gst_record_wav ()
+{
+    GstElement *audiosrc, *filesink, *wavenc;
+    char* carray = NULL;
+    GstCaps* caps;
+    
+    //g_print ("Constructing pipeline\n");
+    
+    /* create a new bin to hold the elements */
+    bin = gst_pipeline_new ("pipeline");
+    if(!bin)
+        goto no_output;
+
+    /* create a disk reader */
+    audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
+    if(!audiosrc)
+        goto no_output;
+
+    /* Create the decodebin */
+    filesink = gst_element_factory_make ("filesink", NULL);
+    if(!filesink)
+        goto no_output;
+
+    wavenc = gst_element_factory_make ("wavenc", NULL);
+    if(!wavenc)
+        goto no_output;
+    
+    caps = gst_caps_new_simple ("audio/x-raw-int",
+              "width", G_TYPE_INT, 16,
+              "depth", G_TYPE_INT, 16,
+              "signed",G_TYPE_BOOLEAN, TRUE,
+              "endianness",G_TYPE_INT, G_BYTE_ORDER,
+              "rate", G_TYPE_INT, 16000,
+              "channels", G_TYPE_INT, 1, NULL);
+    
+    carray = "c:\\data\\sounds\\Digital\\record.wav";
+    
+    g_object_set (G_OBJECT (audiosrc),
+              "blocksize", 1280,
+               NULL);
+    
+    g_object_set (G_OBJECT (filesink), "location", carray,"buffer-size",1280, NULL);
+    
+    /* add objects to the main pipeline */
+    gst_bin_add_many (GST_BIN (bin), audiosrc,wavenc, filesink, NULL);
+
+    /* link the elements. */
+    gst_element_link_filtered (audiosrc, wavenc, caps);
+    gst_element_link (wavenc, filesink);
+    gst_bus_add_watch( gst_pipeline_get_bus (GST_PIPELINE (bin)), bus_call, NULL);
+    //g_print ("Starting recoring\n");   
+    /* start playing */
+    gst_element_set_state (bin, GST_STATE_PLAYING);
+
+    return 0;
+    
+no_output:
+    return -1;
+}
+
+int gst_pause()
+{
+    gst_element_set_state (bin, GST_STATE_PAUSED);
+    return 0;
+}
+
+int gst_resume()
+{
+    gst_element_set_state (bin, GST_STATE_PLAYING);
+    return 0;
+}
+
+
+int gst_record_stop()
+{
+    gst_element_send_event (bin, gst_event_new_eos ());
+    //gst_element_set_state (bin, GST_STATE_NULL);
+    return 0;
+}
+
+
+int gst_seek()
+{
+// need to implement..
+}
+
+int gst_get_events()
+{
+    return g_main_context_iteration(NULL, FALSE);
+    //return 0;
+}
+
+int gst_unref()
+{
+    //g_print ("Finished playback - stopping pipeline\n");
+    /* stop the bin */
+    gst_element_set_state (bin, GST_STATE_NULL);
+    /* Unreffing the bin will clean up all its children too */
+    gst_object_unref (bin);   
+    return 0;
+}
+
+int gst_record_aac()
+{
+    GstElement *audiosrc,*filesink,*aacenc, *mp4mux;
+    GstBus *bus;
+    GstPad *mp4sinkpad,*aacencsrcpad;
+    char* carray = NULL;
+    GstCaps* caps;
+    
+    /*create a pipeline*/
+    bin = gst_pipeline_new ("pipeline");
+    if(!bin)
+        goto no_output;
+    /* create a disk reader */
+    audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
+    if(!audiosrc)
+        goto no_output;
+
+    /* Create the decodebin */
+    filesink = gst_element_factory_make ("filesink", NULL);
+    if(!filesink)
+        goto no_output;
+    //setting num-buffers
+    //g_object_set (G_OBJECT (audiosrc), "num-buffers", 5000 , NULL);
+    g_object_set (G_OBJECT (audiosrc),
+            "blocksize", 1280,
+            NULL);
+
+    aacenc = gst_element_factory_make("nokiaaacenc", "nokiaaacenc");
+    if(!aacenc)
+        goto no_output;
+    mp4mux = gst_element_factory_make("mp4mux", "mp4mux");
+    if(!mp4mux)
+        goto no_output;
+    caps = gst_caps_new_simple("audio/x-raw-int",
+            "width", G_TYPE_INT, 16,
+            "depth", G_TYPE_INT, 16,
+            "signed",G_TYPE_BOOLEAN, TRUE,
+            "endianness",G_TYPE_INT, G_BYTE_ORDER,
+            "rate", G_TYPE_INT, 8000,
+            "channels", G_TYPE_INT, 1, NULL);
+    carray = "c:\\data\\sounds\\Digital\\record.mp4";
+
+   
+    g_object_set(G_OBJECT (filesink), "location", carray, NULL);
+    bus = gst_pipeline_get_bus(GST_PIPELINE (bin));
+    
+    gst_bus_add_watch(bus, bus_call, NULL);
+   
+    gst_object_unref(bus);
+    
+
+    //add objects to the main pipeline 
+    gst_bin_add_many(GST_BIN (bin),audiosrc,aacenc,mp4mux,filesink, NULL);
+   
+    gst_element_link_filtered (audiosrc, aacenc, caps);
+   
+    mp4sinkpad  = gst_element_get_request_pad( mp4mux, "audio_%d");
+    
+    aacencsrcpad  = gst_element_get_pad( aacenc, "src");  
+    if (gst_pad_link (aacencsrcpad,mp4sinkpad) != GST_PAD_LINK_OK) {
+
+    g_print("gst_pad_link (aacencsrcpad,mp4sinkpad) failed");
+    
+    return -1;
+    }       
+    //gst_element_link (aacenc, filesink);
+    gst_element_link (mp4mux, filesink);
+    
+    gst_caps_unref (caps);
+    
+
+    gst_element_set_state(bin, GST_STATE_PLAYING);
+    
+    return 0;
+no_output:
+    return -1;
+}
+
+int gst_record_amr()
+{
+      GstElement *audiosrc, *filesink, *amrmux;
+      GstBus *bus;
+      char* carray = NULL;
+      GstCaps* caps;
+       /* create a new bin to hold the elements */
+      bin = gst_pipeline_new ("pipeline");
+      if(!bin)
+          goto no_output;
+      //g_print ("pipeline created");
+      audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source"); 
+     // encoder = gst_element_factory_make ("wavenc", NULL); 
+      if(!audiosrc)
+          goto no_output;
+
+      amrmux = gst_element_factory_make ("amrmux", "muxer"); 
+      if(!amrmux)
+          goto no_output;
+
+      filesink = gst_element_factory_make("filesink", "filesink");
+      if(!filesink)
+          goto no_output;
+      
+      caps = gst_caps_new_simple ("audio/amr",
+                 "width", G_TYPE_INT, 8,
+                 "depth", G_TYPE_INT, 8,
+                 "signed",G_TYPE_BOOLEAN, TRUE,
+                 "endianness",G_TYPE_INT, G_BYTE_ORDER,
+                 "rate", G_TYPE_INT,  8000,
+                 "channels", G_TYPE_INT, 1, NULL);
+      carray = "c:\\data\\sounds\\Digital\\record.amr";
+      
+      g_object_set (G_OBJECT (audiosrc),
+                "blocksize", 1280,
+                 NULL);
+      
+      g_object_set(G_OBJECT (filesink), "location", carray, NULL);
+       
+      bus = gst_pipeline_get_bus (GST_PIPELINE (bin));
+      gst_bus_add_watch (bus, bus_call, NULL);
+      gst_object_unref (bus);
+      
+
+      /* add objects to the main pipeline */
+      gst_bin_add_many(GST_BIN (bin),audiosrc,amrmux,filesink , NULL);
+      /* link the elements */
+      gst_element_link_filtered (audiosrc, amrmux, caps);
+      
+      gst_element_link( amrmux, filesink );
+      
+      gst_element_set_state (bin, GST_STATE_PLAYING);
+      
+      return 0;
+no_output:
+      return -1;
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/record_play.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+ 
+#ifndef __HELP_FILE_H__
+#define __HELP_FILE_H__
+#include <glib.h>
+#include <stdio.h>
+
+enum
+{
+    NONE,
+    PLAYING,
+    STOP,
+    PAUSE,
+    /*RESUME,
+    RECORDING*/
+};
+
+enum
+{
+    RECORD_NONE,
+    RECORD_AMR,
+    RECORD_WAV,
+    RECORD_RAW,
+    RECORD_G711,
+    RECORD_G729,
+    RECORD_ILBC,
+    RECORD_AAC
+};
+
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+int gst_play_file( const char* file );
+
+int gst_record_file( int type );
+
+int gst_record_wav();
+
+int gst_pause();
+
+int gst_resume();
+
+int gst_record_stop();
+
+int gst_seek();
+
+int gst_unref();
+
+int gst_get_events();
+
+int gst_record_aac();
+
+int gst_record_amr();
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__HELP_FILE_H__
+
Binary file QtGSTPlayer/settings.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/views.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,31 @@
+#include <hbmainwindow.h>
+#include <hbview.h>
+//#include <hbformview.h>
+
+#include "views.h"
+
+// Helper methods for retrieving the views used in this application
+namespace Views {
+
+    // Store the mainwindow ptr here because we cannot call HbWidget::mainWindow() from these static functions.
+    HbMainWindow *win;
+    
+/*!
+  Returns the pointer to folder view.
+*/
+    HbView *folderView()
+    {
+    	// 0 since folderView was added first to the main window
+        return win->viewAt(0);
+    }
+
+/*!
+  Returns the pointer to settings view.
+*/
+  /*  HbFormView *settingsView()
+    {
+	    // 1 since settingsView was the second view added
+        return static_cast<HbFormView *>(win->viewAt(1));
+    }
+    */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/views.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,15 @@
+#ifndef VIEWS_H
+#define VIEWS_H
+
+class HbView;
+//class HbFormView;
+class HbMainWindow;
+
+namespace Views
+{
+    extern HbMainWindow *win;
+    HbView *folderView();
+    //HbFormView *settingsView();
+}
+
+#endif // VIEWS_H
--- a/data/gst_dll_2001F41F.txt	Fri Mar 19 09:35:09 2010 +0200
+++ b/data/gst_dll_2001F41F.txt	Fri Apr 16 15:15:52 2010 +0300
@@ -7,6 +7,7 @@
 libgstdecodebin2.dll
 libgstdevsoundsink.dll
 libgstdevsoundsrc.dll
+libgstapp.dll
 libgstqueue2.dll
 libgstadder.dll
 libgsttypefindfunctions.dll
@@ -14,9 +15,27 @@
 libgstwavparse.dll
 libgstaudiotestsrc.dll
 libgstautodetect.dll
-libgstsubparse.dll
-libgsttcp.dll
-libgstvolume.dll
+libgstmad.dll
+libgstvideorate.dll
+libgstvideoscale.dll
+libgstvideotestsrc.dll
+libgstavi.dll
+libgstffmpegcolorspace.dll
+libgstmpegstream.dll
+libgstmpeg2dec.dll
+libgstsdlvideosink.dll
+libgstauparse.dll
+libgstqtdemux.dll
+gstqtmux.dll
+libgstnokiaaacenc.dll
+libgstlibgstqueue2.dll
+libgstjpeg.dll
 libgstplaybin.dll
 libgstgdp.dll
-libgstapp.dll
\ No newline at end of file
+libgstvolume.dll
+libgsttcp.dll
+libgstsubparse.dll
+libgstaudiofx.dll
+libgstmulaw.dll
+libgstalaw.dll
+libgstamrmux.dll
--- a/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -21,10 +21,11 @@
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
-* Description:
+* Description : This is a top level bld file to generate all libraries.
 *
 */
 
+
 #include <platform_paths.hrh>
 
 PRJ_PLATFORMS
@@ -37,6 +38,7 @@
 #include "../gst_plugins_good/group/bld.inf"
 #include "../gst_plugins_symbian/group/bld.inf"
 #include "../gstregistrygenerator/group/bld.inf"
+#include "../gst_nokia_speech/group/bld.inf"
 #endif
 
 PRJ_EXPORTS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/bwins/libgstnokiaaacencu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_aac_enc_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/config.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,274 @@
+/* config.h.  Generated by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* defined if cdda headers are in a cdda/ directory */
+/* #undef CDPARANOIA_HEADERS_IN_DIR */
+
+/* Default audio sink */
+#define DEFAULT_AUDIOSINK "autoaudiosink"
+
+/* Default audio source */
+#define DEFAULT_AUDIOSRC "alsasrc"
+
+/* Default video sink */
+#define DEFAULT_VIDEOSINK "autovideosink"
+
+/* Default video source */
+#define DEFAULT_VIDEOSRC "v4lsrc"
+
+/* Default visualizer */
+#define DEFAULT_VISUALIZER "goom"
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#ifdef __SYMBIAN32__
+#undef ENABLE_NLS
+#else
+#define ENABLE_NLS 1
+#endif
+
+
+/* gettext package name */
+#define GETTEXT_PACKAGE "gst-plugins-base-0.10"
+
+/* macro to use to show function name */
+#define GST_FUNCTION __PRETTY_FUNCTION__
+
+/* Defined if gcov is enabled to force a rebuild due to config.h changing */
+/* #undef GST_GCOV_ENABLED */
+
+/* Default errorlevel to use */
+#define GST_LEVEL_DEFAULT GST_LEVEL_NONE
+
+/* GStreamer license */
+#define GST_LICENSE "LGPL"
+
+/* package name in plugins */
+#define GST_PACKAGE_NAME "GStreamer Base Plug-ins source release"
+
+/* package origin */
+#define GST_PACKAGE_ORIGIN "Unknown package origin"
+
+/* support for features: gstalsa */
+#define HAVE_ALSA 
+
+/* support for features: cdparanoia */
+/* #undef HAVE_CDPARANOIA */
+
+/* Define if the host CPU is an Alpha */
+/* #undef HAVE_CPU_ALPHA */
+
+/* Define if the host CPU is an ARM */
+/* #undef HAVE_CPU_ARM */
+#ifdef __SYMBIAN32__
+#define HAVE_CPU_ARM 1
+#endif
+
+/* Define if the host CPU is a CRIS */
+/* #undef HAVE_CPU_CRIS */
+
+/* Define if the host CPU is a CRISv32 */
+/* #undef HAVE_CPU_CRISV32 */
+
+/* Define if the host CPU is a HPPA */
+/* #undef HAVE_CPU_HPPA */
+
+/* Define if the host CPU is an x86 */
+#ifndef __SYMBIAN32__
+#define HAVE_CPU_I386 1
+#endif
+/* Define if the host CPU is a IA64 */
+/* #undef HAVE_CPU_IA64 */
+
+/* Define if the host CPU is a M68K */
+/* #undef HAVE_CPU_M68K */
+
+/* Define if the host CPU is a MIPS */
+/* #undef HAVE_CPU_MIPS */
+
+/* Define if the host CPU is a PowerPC */
+/* #undef HAVE_CPU_PPC */
+
+/* Define if the host CPU is a 64 bit PowerPC */
+/* #undef HAVE_CPU_PPC64 */
+
+/* Define if the host CPU is a S390 */
+/* #undef HAVE_CPU_S390 */
+
+/* Define if the host CPU is a SPARC */
+/* #undef HAVE_CPU_SPARC */
+
+/* Define if the host CPU is a x86_64 */
+/* #undef HAVE_CPU_X86_64 */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* support for features: */
+#define HAVE_EXTERNAL 
+
+/* FIONREAD ioctl found in sys/filio.h */
+/* #undef HAVE_FIONREAD_IN_SYS_FILIO */
+
+/* FIONREAD ioctl found in sys/ioclt.h */
+#define HAVE_FIONREAD_IN_SYS_IOCTL 1
+
+/* defined if the compiler implements __func__ */
+#define HAVE_FUNC 1
+
+/* defined if the compiler implements __FUNCTION__ */
+#define HAVE_FUNCTION 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* support for features: gnomevfssrc */
+#define HAVE_GNOME_VFS 
+
+/* support for features: v4lsrc v4lmjpegsrc v4lmjpegsink */
+#define HAVE_GST_V4L 
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `asound' library (-lasound). */
+/* #undef HAVE_LIBASOUND */
+
+/* support for features: libvisual */
+/* #undef HAVE_LIBVISUAL */
+
+/* Define if you have C99's lrint function. */
+#define HAVE_LRINT 1
+
+/* Define if you have C99's lrintf function. */
+#define HAVE_LRINTF 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* support for features: oggdemux oggmux */
+#define HAVE_OGG 
+
+/* support for features: pango */
+#define HAVE_PANGO 
+
+/* defined if the compiler implements __PRETTY_FUNCTION__ */
+#define HAVE_PRETTY_FUNCTION 1
+
+/* Define if RDTSC is available */
+#define HAVE_RDTSC 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* support for features: theoradec theoraenc */
+/* #undef HAVE_THEORA */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if valgrind should be used */
+#define HAVE_VALGRIND 1
+
+/* support for features: vorbisenc vorbisdec */
+#define HAVE_VORBIS 
+
+/* defined if vorbis_synthesis_restart is present */
+#define HAVE_VORBIS_SYNTHESIS_RESTART 1
+
+/* support for features: ximagesink */
+#define HAVE_X 
+
+/* support for features: xshm */
+#define HAVE_XSHM 
+
+/* support for features: xvimagesink */
+#define HAVE_XVIDEO 
+
+/* gettext locale dir */
+#define LOCALEDIR "/home/datha/gst-plugins-base-0.10.8/share/locale"
+
+/* Name of package */
+#define PACKAGE "gst-plugins-base"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GStreamer nokia speech"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GStreamer nokia speech"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "gst_nokia_speech"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.10.0"
+
+/* directory where plugins are located */
+
+/* The size of a `char', as computed by sizeof. */
+/* #undef SIZEOF_CHAR */
+
+/* The size of a `int', as computed by sizeof. */
+/* #undef SIZEOF_INT */
+
+/* The size of a `long', as computed by sizeof. */
+/* #undef SIZEOF_LONG */
+
+/* The size of a `short', as computed by sizeof. */
+/* #undef SIZEOF_SHORT */
+
+/* The size of a `void*', as computed by sizeof. */
+/* #undef SIZEOF_VOIDP */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.10.0"
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/eabi/libgstnokiaaacencu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_aac_enc_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,9 @@
+PRJ_PLATFORMS
+DEFAULT
+
+PRJ_EXPORTS
+
+PRJ_MMPFILES
+#ifndef WINSCW
+gstaacenc.mmp
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/group/gstaacenc.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,87 @@
+// Gstreamer.MMP
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstnokiaaacenc.dll
+TARGETTYPE      DLL
+UID             0x20004c45 0x0FE80A1C
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           HAVE_CONFIG_H //RAW_FRAME_SIZE
+
+
+USERINCLUDE     ..
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+SYSTEMINCLUDE /epoc32/include/internal
+SOURCEPATH  ..
+SOURCE      gstaacenc.c gstframedaudioenc.c
+LIBRARY         euser.lib
+LIBRARY         libc.lib
+LIBRARY         libdl.lib
+LIBRARY         libglib.lib
+LIBRARY         libgmodule.lib
+
+LIBRARY         libgobject.lib
+LIBRARY         libgthread.lib
+LIBRARY         libm.lib
+LIBRARY         libz.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         enhaacplusencoder.lib
+LIBRARY         libgstbase.lib
+
+#ifdef WINSCW
+LIBRARY		ewsd.lib //wsd solution
+#endif
+
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/gstaacenc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,603 @@
+/* GStreamer AAC encoder
+ * Copyright 2009 Collabora Multimedia,
+ * Copyright 2009 Nokia Corporation
+ *  @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
+ *
+ * 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.
+ */
+
+/* TODO non-GPL license */
+
+/**
+ * SECTION:element-nokiaaacenc
+ * @seealso: nokiaaacdec
+ *
+ * nokiaaacenc encodes raw audio to AAC streams.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+#include <string.h>
+
+#include "gstaacenc.h"
+
+GST_DEBUG_CATEGORY_STATIC (aac_enc);
+#define GST_CAT_DEFAULT aac_enc
+
+enum
+{
+  AAC_PROFILE_AUTO = 0,
+  AAC_PROFILE_LC = 2,
+  AAC_PROFILE_HE = 5
+};
+
+#define GST_TYPE_AAC_ENC_PROFILE (gst_aac_enc_profile_get_type ())
+static GType
+gst_aac_enc_profile_get_type (void)
+{
+  static GType gst_aac_enc_profile_type = 0;
+
+  if (!gst_aac_enc_profile_type) {
+    static GEnumValue gst_aac_enc_profile[] = {
+      {AAC_PROFILE_AUTO, "Codec selects LC or HE", "AUTO"},
+      {AAC_PROFILE_LC, "Low complexity profile", "LC"},
+      {AAC_PROFILE_HE, "High Efficiency", "HE"},
+      {0, NULL, NULL},
+    };
+
+    gst_aac_enc_profile_type = g_enum_register_static ("GstNokiaAacEncProfile",
+        gst_aac_enc_profile);
+  }
+
+  return gst_aac_enc_profile_type;
+}
+
+#define GST_TYPE_AAC_ENC_OUTPUTFORMAT (gst_aac_enc_outputformat_get_type ())
+static GType
+gst_aac_enc_outputformat_get_type (void)
+{
+  static GType gst_aac_enc_outputformat_type = 0;
+
+  if (!gst_aac_enc_outputformat_type) {
+    static GEnumValue gst_aac_enc_outputformat[] = {
+      {RAW, "AAC Raw format", "RAW"},
+      {USE_ADTS, "Audio Data Transport Stream format", "ADTS"},
+      {USE_ADIF, "Audio Data Interchange Format", "ADIF"},
+      {0, NULL, NULL},
+    };
+
+    gst_aac_enc_outputformat_type =
+        g_enum_register_static ("GstNokiaAacEncOutputFormat",
+        gst_aac_enc_outputformat);
+  }
+
+  return gst_aac_enc_outputformat_type;
+}
+
+enum
+{
+  PROP_0,
+  PROP_BITRATE,
+  PROP_PROFILE,
+  PROP_FORMAT
+};
+
+static GstStaticPadTemplate gst_aac_enc_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "endianness = (int) BYTE_ORDER, "
+        "signed = (bool) TRUE, "
+        "width = (int) 16, "
+        "depth = (int) 16, "
+        "rate = (int) [ 8000, 96000 ],  channels = (int) [ 1, 2 ] ")
+    );
+
+static GstStaticPadTemplate gst_aac_enc_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/mpeg, " "mpegversion = (int) 4, "
+        "rate = (int) [ 8000, 96000 ],  channels = (int) [ 1, 2 ] ")
+    );
+
+static void gst_aac_enc_base_init (gpointer g_class);
+static void gst_aac_enc_class_init (GstAACEncClass * klass);
+static void gst_aac_enc_init (GstAACEnc * filter, GstAACEncClass * klass);
+
+static void gst_aac_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_aac_enc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_aac_enc_finalize (GObject * object);
+static void gst_aac_enc_reset (GstAACEnc * enc);
+static GstStateChangeReturn gst_aac_enc_change_state (GstElement * element,
+    GstStateChange transition);
+static gboolean gst_aac_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_aac_enc_chain (GstPad * pad, GstBuffer * buffer);
+
+GST_BOILERPLATE (GstNokiaAACEnc, gst_aac_enc, GstElement, GST_TYPE_ELEMENT);
+
+static void
+gst_aac_enc_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Nokia AAC encoder", "Codec/Encoder/Audio",
+      "Nokia AAC encoder",
+      "MCC, Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_aac_enc_src_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_aac_enc_sink_template));
+}
+
+/* initialize the plugin's class */
+static void
+gst_aac_enc_class_init (GstAACEncClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  GST_DEBUG_CATEGORY_INIT (aac_enc, "nokiaaacenc", 0, "Nokia AAC encoder");
+
+  gobject_class->set_property = gst_aac_enc_set_property;
+  gobject_class->get_property = gst_aac_enc_get_property;
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_aac_enc_finalize);
+
+  /* properties */
+  g_object_class_install_property (gobject_class, PROP_BITRATE,
+      g_param_spec_int ("bitrate", "Bitrate (bps)", "Bitrate in bits/sec",
+          8 * 1000, 320 * 1000, 128 * 1000,
+          (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT)));
+  g_object_class_install_property (gobject_class, PROP_PROFILE,
+      g_param_spec_enum ("profile", "Profile",
+          "MPEG/AAC encoding profile",
+          GST_TYPE_AAC_ENC_PROFILE, AAC_PROFILE_LC,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (gobject_class, PROP_FORMAT,
+      g_param_spec_enum ("output-format", "Output format",
+          "Format of output frames",
+          GST_TYPE_AAC_ENC_OUTPUTFORMAT, RAW,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_aac_enc_change_state);
+}
+
+static void
+gst_aac_enc_init (GstAACEnc * enc, GstAACEncClass * klass)
+{
+  enc->sinkpad =
+      gst_pad_new_from_static_template (&gst_aac_enc_sink_template, "sink");
+  gst_pad_set_setcaps_function (enc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_aac_enc_sink_setcaps));
+  gst_pad_set_chain_function (enc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_aac_enc_chain));
+  gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
+
+  enc->srcpad =
+      gst_pad_new_from_static_template (&gst_aac_enc_src_template, "src");
+  gst_pad_use_fixed_caps (enc->srcpad);
+  gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
+
+#ifndef GST_DISABLE_GST_DEBUG
+  gst_framed_audio_enc_init (&enc->enc, GST_ELEMENT (enc), aac_enc);
+#else
+  gst_framed_audio_enc_init (&enc->enc, GST_ELEMENT (enc), NULL);
+#endif
+
+  gst_aac_enc_reset (enc);
+}
+
+static void
+gst_aac_enc_reset (GstAACEnc * enc)
+{
+  gst_framed_audio_enc_reset (&enc->enc);
+  if (enc->encoder)
+    EnAACPlus_Enc_Delete (enc->encoder);
+  enc->encoder = NULL;
+  g_free (enc->buffer);
+  enc->buffer = NULL;
+}
+
+static void
+gst_aac_enc_finalize (GObject * object)
+{
+  GstAACEnc *enc = (GstAACEnc *) object;
+
+  gst_framed_audio_enc_finalize (&enc->enc);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_aac_enc_setup_encoder (GstAACEnc * enc)
+{
+  AACPLUS_ENC_CONFIG enc_params;
+  AACPLUS_ENC_MODE mode;
+  gint rate, channels;
+  guint maxbitrate;
+
+  rate = enc->rate;
+  channels = enc->channels;
+
+  /* only up to 2 channels supported */
+  enc_params.sampleRate = rate;
+  enc_params.bitRate = enc->bitrate;
+  enc_params.nChannels = channels;
+  enc_params.aac_tools = USE_ALL;
+  enc_params.pcm_mode = 16;
+  enc_params.format = enc->format;
+
+  /* check, warn and correct if the max bitrate for the given samplerate is
+   * exceeded. Maximum of 6144 bit for a channel */
+  maxbitrate =
+      (guint) (6144.0 * (gdouble) rate / (gdouble) 1024.0 + .5) * channels;
+  if (enc_params.bitRate > maxbitrate) {
+    GST_ELEMENT_INFO (enc, RESOURCE, SETTINGS, (NULL),
+        ("bitrate %d exceeds maximum allowed bitrate of %d for samplerate %d "
+            "and %d channels.  Setting bitrate to %d",
+            enc_params.bitRate, maxbitrate, rate, channels, maxbitrate));
+    enc_params.bitRate = maxbitrate;
+  }
+
+  /* set up encoder */
+  if (enc->encoder)
+    EnAACPlus_Enc_Delete (enc->encoder);
+
+  /* only these profiles are really known to and supported by codec */
+  switch (enc->profile) {
+    case AAC_PROFILE_LC:
+      mode = MODE_AACLC;
+      break;
+    case AAC_PROFILE_HE:
+      mode = MODE_EAACPLUS;
+      break;
+    case AAC_PROFILE_AUTO:
+      mode = MODE_AUTO;
+      break;
+    default:
+      mode = MODE_AACLC;
+      g_assert_not_reached ();
+      break;
+  }
+  enc->encoder = EnAACPlus_Enc_Create (&enc_params, mode);
+
+  if (!enc->encoder)
+    goto setup_failed;
+
+  /* query and setup params,
+   * also set up some buffers for fancy HE */
+  EnAACPlus_Enc_GetSetParam (enc->encoder, &enc->info);
+
+#define DUMP_FIELD(f)  \
+  GST_DEBUG_OBJECT (enc, "encoder info: " G_STRINGIFY (f) " = %d", enc->info.f);
+
+  DUMP_FIELD (InBufSize);
+  DUMP_FIELD (OutBufSize);
+  DUMP_FIELD (Frame_Size);
+  DUMP_FIELD (writeOffset);
+  DUMP_FIELD (InBufSize);
+
+  enc->raw_frame_size = enc->info.Frame_Size;
+  enc->codec_frame_size = enc->info.OutBufSize;
+  enc->frame_duration =
+      GST_FRAMES_TO_CLOCK_TIME (enc->raw_frame_size / enc->channels / 2,
+      enc->rate);
+
+  g_free (enc->buffer);
+  /* safety margin */
+  enc->buffer = g_malloc (enc->info.InBufSize * 2);
+
+  return TRUE;
+
+  /* ERRORS */
+setup_failed:
+  {
+    GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL));
+    return FALSE;
+  }
+}
+
+static gint
+gst_aac_enc_rate_idx (gint rate)
+{
+  static int rates[] = {
+    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025,
+    8000, 7350
+  };
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (rates); ++i)
+    if (rates[i] == rate)
+      return i;
+
+  return 0xF;
+}
+
+static gboolean
+gst_aac_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstAACEnc *enc;
+  gboolean ret = TRUE;
+  GstStructure *s;
+  GstBuffer *buf = NULL;
+  gint rate, channels;
+
+  enc = GST_AAC_ENC (GST_PAD_PARENT (pad));
+
+  /* extract stream properties */
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!s)
+    goto refuse_caps;
+
+  ret = gst_structure_get_int (s, "rate", &rate);
+  ret &= gst_structure_get_int (s, "channels", &channels);
+
+  if (!ret)
+    goto refuse_caps;
+
+  enc->rate = rate;
+  enc->channels = channels;
+
+  /* NOTE:
+   * - codec only supports LC or HE (= LC + SBR etc)
+   * - HE has (more) restrictive samplerate/channels/bitrate combination
+   * - AUTO makes codec select between LC or HE (depending on settings)
+   */
+
+  gst_aac_enc_setup_encoder (enc);
+  if (!enc->encoder)
+    return FALSE;
+
+  /* HE iff writeOffset <> 0 iff Frame_Size <> 1024 * 2 * channels */
+  if (enc->info.writeOffset)
+    rate /= 2;
+
+  /* create codec_data if raw output */
+  if (enc->format == RAW) {
+    gint rate_idx;
+    guint8 *data;
+
+    buf = gst_buffer_new_and_alloc (5);
+    data = GST_BUFFER_DATA (buf);
+    rate_idx = gst_aac_enc_rate_idx (rate);
+
+    GST_DEBUG_OBJECT (enc, "codec_data: profile=%d, sri=%d, channels=%d",
+        enc->profile, rate_idx, enc->channels);
+
+    /* always write LC profile, and use implicit signaling for HE SBR */
+    data[0] = ((2 & 0x1F) << 3) | ((rate_idx & 0xE) >> 1);
+    data[1] = ((rate_idx & 0x1) << 7);
+    if (rate_idx != 0x0F) {
+      data[1] |= ((channels & 0xF) << 3);
+      GST_BUFFER_SIZE (buf) = 2;
+    } else {
+      gint srate;
+
+      srate = rate << 7;
+      data[1] |= ((srate >> 24) & 0xFF);
+      data[2] = ((srate >> 16) & 0xFF);
+      data[3] = ((srate >> 8) & 0xFF);
+      data[4] = (srate & 0xFF);
+      data[4] |= ((channels & 0xF) << 3);
+      GST_BUFFER_SIZE (buf) = 5;
+    }
+  }
+
+  /* fix some in src template */
+  caps = gst_caps_copy (gst_pad_get_pad_template_caps (enc->srcpad));
+  gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate,
+      "channels", G_TYPE_INT, channels, NULL);
+  if (buf) {
+    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
+    gst_buffer_unref (buf);
+  }
+  ret = gst_pad_set_caps (enc->srcpad, caps);
+  gst_caps_unref (caps);
+
+  return ret;
+
+  /* ERRORS */
+refuse_caps:
+  {
+    GST_WARNING_OBJECT (enc, "refused caps %" GST_PTR_FORMAT, caps);
+    return FALSE;
+  }
+}
+
+static gint
+gst_aac_enc_get_data (GstElement * element, const guint8 * in, guint8 * out,
+    GstDtxDecision * dtx)
+{
+  GstAACEnc *enc;
+  gint res;
+  gint offset;
+  UWord32 used, encoded;
+  Word8 *inbuffer;
+
+  enc = GST_AAC_ENC_CAST (element);
+
+  offset = enc->info.writeOffset;
+  if (offset) {
+    memcpy (enc->buffer + offset, in, enc->raw_frame_size);
+    inbuffer = (Word8 *) enc->buffer;
+  } else {
+    inbuffer = (Word8 *) in;
+  }
+
+  res = EnAACPlus_Enc_Encode (enc->encoder, &enc->info, inbuffer, &used,
+      (UWord8 *) out, &encoded);
+
+  if (offset) {
+    memcpy (enc->buffer, enc->buffer + used, offset);
+  }
+
+  return res == 0 ? encoded : -1;
+}
+
+/* set parameters */
+#define AUDIO_SAMPLE_RATE   ((GST_AAC_ENC (enc->element))->rate)
+#define RAW_FRAME_SIZE      ((GST_AAC_ENC (enc->element))->raw_frame_size)
+/* safe maximum frame size */
+#define CODEC_FRAME_SIZE    ((GST_AAC_ENC (enc->element))->codec_frame_size)
+/* do not set variable frame;
+ * this will make every frame act as a silence frame and force output */
+/* #define CODEC_FRAME_VARIABLE 1 */
+#define FRAME_DURATION      ((GST_AAC_ENC (enc->element))->frame_duration)
+#define codec_get_data(enc, in, out, dtx)  \
+    gst_aac_enc_get_data (enc, in, out, dtx)
+
+/* and include code */
+#include "gstframedaudioenc.c"
+
+static GstFlowReturn
+gst_aac_enc_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstAACEnc *enc;
+
+  enc = GST_AAC_ENC (GST_PAD_PARENT (pad));
+
+  if (G_UNLIKELY (enc->encoder == NULL))
+    goto not_negotiated;
+
+  return gst_framed_audio_enc_chain (&enc->enc, buf, enc->srcpad, &enc->cnpad);
+
+  /* ERRORS */
+not_negotiated:
+  {
+    GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
+        ("format wasn't negotiated before chain function"));
+    gst_buffer_unref (buf);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+}
+
+static void
+gst_aac_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAACEnc *enc;
+
+  enc = GST_AAC_ENC (object);
+
+  switch (prop_id) {
+    case PROP_BITRATE:
+      enc->bitrate = g_value_get_int (value);
+      break;
+    case PROP_PROFILE:
+      enc->profile = g_value_get_enum (value);
+      break;
+    case PROP_FORMAT:
+      enc->format = g_value_get_enum (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_aac_enc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAACEnc *enc;
+
+  enc = GST_AAC_ENC (object);
+
+  switch (prop_id) {
+    case PROP_BITRATE:
+      g_value_set_int (value, enc->bitrate);
+      break;
+    case PROP_PROFILE:
+      g_value_set_enum (value, enc->profile);
+      break;
+    case PROP_FORMAT:
+      g_value_set_enum (value, enc->format);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstStateChangeReturn
+gst_aac_enc_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstAACEnc *enc = GST_AAC_ENC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_aac_enc_reset (enc);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+
+  if (!gst_element_register (plugin, "nokiaaacenc", GST_RANK_SECONDARY,
+          GST_TYPE_AAC_ENC))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* this is the structure that gst-register looks for
+ * so keep the name plugin_desc, or you cannot get your plug-in registered */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "nokiaaacenc",
+    "Nokia AAC MCC codec",
+    plugin_init, VERSION, "Proprietary", "gst-nokia-speech", "")
+
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+   {
+      return &gst_plugin_desc;
+   }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/gstaacenc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,92 @@
+/* GStreamer AAC encoder
+ * Copyright 2009 Collabora Multimedia,
+ * Copyright 2009 Nokia Corporation
+ *  @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
+ *
+ * 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.
+ */
+
+/* TODO non-GPL license */
+
+#ifndef __GST_AAC_ENC_H__
+#define __GST_AAC_ENC_H__
+
+#include <gst/gst.h>
+
+#include <eaacplus_api.h>
+
+#include "gstframedaudioenc.h"
+
+G_BEGIN_DECLS
+
+/* #define's don't like whitespacey bits */
+#define GST_TYPE_AAC_ENC			\
+  (gst_aac_enc_get_type())
+#define GST_AAC_ENC(obj)						\
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AAC_ENC,GstAACEnc))
+#define GST_AAC_ENC_CLASS(klass)					\
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AAC_ENC,GstAACEncClass))
+#define GST_IS_AAC_ENC(obj)					\
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AAC_ENC))
+#define GST_IS_AAC_ENC_CLASS(klass)				\
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AAC_ENC))
+#define GST_AAC_ENC_CAST(obj)          ((GstAACEnc*)(obj))
+
+
+typedef struct _GstNokiaAACEnc      GstNokiaAACEnc;
+typedef struct _GstNokiaAACEncClass GstNokiaAACEncClass;
+
+typedef GstNokiaAACEnc      GstAACEnc;
+typedef GstNokiaAACEncClass GstAACEncClass;
+
+struct _GstNokiaAACEnc
+{
+  GstElement element;
+
+  GstPad *sinkpad, *srcpad, *cnpad;
+
+  GstFramedAudioEnc enc;
+  HANDLE_AACPLUS_ENC encoder;
+  AACPLUS_ENC_INFO info;
+
+  /* mode selection */
+  GstClockTime frame_duration;
+  gint raw_frame_size;
+  gint codec_frame_size;
+
+  /* optional helper (history) buffer */
+  guint8 *buffer;
+
+  /* stream description */
+  gint rate;
+  gint channels;
+
+  /* properties */
+  gint bitrate;
+  guint profile;
+  guint format;
+};
+
+struct _GstNokiaAACEncClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_aac_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AAC_ENC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/gstframedaudioenc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,439 @@
+/* GStreamer Framed Audio Encoder
+ * Copyright 2009 Collabora Ltd,
+ * Copyright 2009 Nokia Corporation
+ *  @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+#include <string.h>
+
+#include "gstframedaudioenc.h"
+
+/* generic part */
+#ifndef RAW_FRAME_SIZE
+
+/* this will reference caller's debug category;
+ * there is a copy of this per plugin lib (= debug category) */
+GST_DEBUG_CATEGORY_STATIC (framedaudioenc_debug);
+#define GST_CAT_DEFAULT framedaudioenc_debug
+
+void
+gst_framed_audio_enc_reset (GstFramedAudioEnc * enc)
+{
+  gst_adapter_clear (enc->adapter);
+  enc->next_ts = GST_CLOCK_TIME_NONE;
+}
+
+/* installs @enc as element private for @element's pad,
+ * and possibly some event and query handler.
+ * if these need overriding, chain up to them
+ * chain and setcaps still need to be set by @element */
+void
+gst_framed_audio_enc_init (GstFramedAudioEnc * enc, GstElement * element,
+    GstDebugCategory * cat)
+{
+  enc->element = element;
+#ifndef GST_DISABLE_GST_DEBUG
+  framedaudioenc_debug = cat;
+#endif
+
+  enc->adapter = gst_adapter_new ();
+
+  /* hook some */
+  enc->sinkpad = gst_element_get_pad (enc->element, "sink");
+  g_assert (enc->sinkpad);
+  gst_pad_set_element_private (enc->sinkpad, enc);
+
+  /* watch downstream events */
+  gst_pad_set_event_function (enc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_framed_audio_enc_sink_event));
+
+  gst_framed_audio_enc_reset (enc);
+}
+
+void
+gst_framed_audio_enc_finalize (GstFramedAudioEnc * enc)
+{
+  gst_object_unref (enc->adapter);
+
+  gst_pad_set_element_private (enc->sinkpad, NULL);
+  gst_object_unref (enc->sinkpad);
+}
+
+GstPad *
+gst_framed_audio_enc_request_new_pad (GstFramedAudioEnc * enc,
+    GstPadTemplate * templ, const gchar * req_name, GstPad ** pad_p)
+{
+  GstElement *element;
+  GstPad *newpad;
+  GstElementClass *klass;
+  GstCaps *caps;
+
+  g_return_val_if_fail (templ != NULL, NULL);
+
+  element = enc->element;
+  klass = GST_ELEMENT_GET_CLASS (element);
+
+  if (templ != gst_element_class_get_pad_template (klass, "cn"))
+    goto wrong_template;
+
+  GST_DEBUG_OBJECT (enc->element, "adding cn pad");
+  newpad = gst_pad_new_from_template (templ, "cn");
+  /* set template caps */
+  caps = gst_caps_copy (gst_pad_get_pad_template_caps (newpad));
+  gst_pad_set_caps (newpad, caps);
+  gst_caps_unref (caps);
+  gst_pad_use_fixed_caps (newpad);
+  gst_pad_set_active (newpad, TRUE);
+  /* only 1 pad by name can be added */
+  if (gst_element_add_pad (element, newpad)) {
+    GST_OBJECT_LOCK (element);
+    gst_object_replace ((GstObject **) pad_p, GST_OBJECT_CAST (newpad));
+    GST_OBJECT_UNLOCK (element);
+    GST_DEBUG_OBJECT (enc->element, "cn pad added");
+  } else {
+    gst_object_unref (newpad);
+    goto already_requested;
+  }
+
+  return newpad;
+
+  /* ERRORS */
+wrong_template:
+  {
+    GST_ERROR_OBJECT (element, "not our template!");
+    return NULL;
+  }
+already_requested:
+  {
+    GST_ERROR_OBJECT (element, "only 1 instance of a pad can be requested");
+    return NULL;
+  }
+}
+
+void
+gst_framed_audio_enc_release_pad (GstFramedAudioEnc * enc, GstPad * pad,
+    GstPad ** pad_p, void (disable_cn) (GstElement *))
+{
+  GstElement *element = enc->element;
+
+  GST_DEBUG_OBJECT (enc->element, "releasing cn pad");
+
+  GST_OBJECT_LOCK (element);
+  if (pad != *pad_p)
+    goto wrong_pad;
+  GST_OBJECT_UNLOCK (element);
+
+  /* reconfigure encoder */
+  disable_cn (element);
+
+  if (gst_element_remove_pad (element, pad)) {
+    GST_OBJECT_LOCK (element);
+    gst_object_replace ((GstObject **) pad_p, NULL);
+    GST_OBJECT_UNLOCK (element);
+    GST_DEBUG_OBJECT (enc->element, "cn pad released");
+  }
+
+  /* ERRORS */
+wrong_pad:
+  {
+    GST_OBJECT_UNLOCK (element);
+    GST_ERROR_OBJECT (element, "pad not requested; can not be released!");
+    return;
+  }
+}
+
+gboolean
+gst_framed_audio_enc_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstFramedAudioEnc *enc;
+
+  enc = gst_pad_get_element_private (pad);
+  g_return_val_if_fail (enc, FALSE);
+
+  GST_LOG_OBJECT (enc->element, "received %s", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_STOP:
+      /* fall-through */
+    case GST_EVENT_EOS:
+      gst_adapter_clear (enc->adapter);
+      enc->next_ts = GST_CLOCK_TIME_NONE;
+      break;
+    default:
+      break;
+  }
+
+  return gst_pad_event_default (pad, event);
+}
+
+#else
+/* included part */
+
+/* parameters:
+     RAW_FRAME_SIZE
+     CODEC_FRAME_SIZE
+     FRAME_DURATION
+     AUDIO_SAMPLE_RATE (optional)
+   callback:
+     codec_get_data(enc, in, out, dtx)
+
+   If one does not mind a few cycles, include'ing can also be replaced by
+   a regular include & call, at the expense of some additional parameters
+   passed some way or another.
+*/
+
+#ifndef AUDIO_SAMPLE_RATE
+#define AUDIO_SAMPLE_RATE   (8000)
+#endif
+
+/* quite some conditional stuff;
+ * the (ugly?) cost of trying to stay inner loop optimal */
+
+static GstFlowReturn
+gst_framed_audio_enc_chain (GstFramedAudioEnc * enc, GstBuffer * buf,
+    GstPad * srcpad, GstPad ** _cnpad)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstBuffer *obuf = NULL;
+#ifdef CN_PAD
+  GstBuffer *cnbuf = NULL;
+  GstPad *cnpad = NULL;
+#endif
+  gboolean discont = FALSE;
+  const guint8 *data;
+  guint8 *odata;
+  gint av, flush, osize;
+
+#ifdef CN_PAD
+  GST_OBJECT_LOCK (enc->element);
+  if (_cnpad)
+    cnpad = *_cnpad;
+  if (cnpad)
+    gst_object_ref (cnpad);
+  GST_OBJECT_UNLOCK (enc->element);
+#endif
+
+  if (G_LIKELY (buf)) {
+    GST_LOG_OBJECT (enc->element, "input buffer of size %d with ts: %"
+        GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+    discont = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT);
+
+    /* reposition to the new buffer's timestamp,
+     * while correcting for some minor left-over */
+    if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+      if (GST_CLOCK_TIME_IS_VALID (enc->next_ts)) {
+        GstClockTimeDiff diff, limit;
+        GstClockTime tleft;
+
+        tleft = GST_FRAMES_TO_CLOCK_TIME
+            (gst_adapter_available (enc->adapter) / 2, AUDIO_SAMPLE_RATE);
+        diff =
+            GST_CLOCK_DIFF (enc->next_ts + tleft, GST_BUFFER_TIMESTAMP (buf));
+        limit = GST_SECOND / AUDIO_SAMPLE_RATE / 2;
+        /* try for a perfect stream if possible, do not act on rounding errors */
+        if (diff > limit || diff < -limit) {
+          enc->next_ts = GST_BUFFER_TIMESTAMP (buf);
+          if (enc->next_ts > tleft)
+            enc->next_ts -= tleft;
+          GST_LOG_OBJECT (enc->element, "marking discont based on timestamps");
+          discont = TRUE;
+        }
+      } else
+        enc->next_ts = GST_BUFFER_TIMESTAMP (buf);
+    }
+
+    gst_adapter_push (enc->adapter, buf);
+    buf = NULL;
+  }
+
+  av = gst_adapter_available (enc->adapter);
+  if (G_UNLIKELY (av < RAW_FRAME_SIZE))
+    goto done;
+
+  data = gst_adapter_peek (enc->adapter, av);
+  obuf = gst_buffer_new_and_alloc (av / RAW_FRAME_SIZE * CODEC_FRAME_SIZE);
+  odata = GST_BUFFER_DATA (obuf);
+  osize = 0;
+  flush = 0;
+
+  while (TRUE) {
+    gint esize;
+#ifdef CN_PAD
+    GstDtxDecision dtx;
+
+    /* safe default to start with, should get set */
+    dtx = GST_DTX_DECISION_VOICE;
+    esize = codec_get_data (enc->element, data + flush, odata, &dtx);
+#else
+    esize = codec_get_data (enc->element, data + flush, odata, NULL);
+#endif
+
+    if (G_UNLIKELY (esize < 0))
+      goto encode_failed;
+
+#ifdef CN_PAD
+    /* cn in a separate stream */
+    switch (dtx) {
+      case GST_DTX_DECISION_VOICE:
+#endif
+        flush += RAW_FRAME_SIZE;
+        av -= RAW_FRAME_SIZE;
+
+        odata += esize;
+        osize += esize;
+#ifdef CN_PAD
+        break;
+      case GST_DTX_DECISION_SID_UPDATE:
+        GST_LOG_OBJECT (enc->element, "dtx: SID_UPDATE %d", esize);
+        /* if already data before, need to put SID data separately */
+        if (G_UNLIKELY (osize)) {
+          cnbuf = gst_buffer_new_and_alloc (esize);
+          memcpy (GST_BUFFER_DATA (cnbuf), data + osize, esize);
+        } else {
+          cnbuf = obuf;
+          obuf = NULL;
+        }
+        /* and send one or both */
+        goto send;
+        break;
+      case GST_DTX_DECISION_SID_NONE:
+        GST_LOG_OBJECT (enc->element, "dtx: SID_NONE %d", esize);
+        /* maybe send preceding voice, if any */
+        goto send;
+        break;
+    }
+#endif
+
+#ifdef CODEC_FRAME_VARIABLE
+    /* flush output after insufficient data */
+    if (av >= RAW_FRAME_SIZE)
+      continue;
+#else
+    /* ... or some reduced (e.g. silence) frame */
+    if (esize >= CODEC_FRAME_SIZE && av >= RAW_FRAME_SIZE)
+      continue;
+#endif
+
+#ifdef CN_PAD
+  send:
+#endif
+    /* maybe a silent discarded frame */
+    if (G_LIKELY (osize)) {
+      GST_BUFFER_SIZE (obuf) = osize;
+      GST_BUFFER_DURATION (obuf)
+          = FRAME_DURATION * (flush / RAW_FRAME_SIZE);
+      GST_BUFFER_TIMESTAMP (obuf) = enc->next_ts;
+      if (G_UNLIKELY (discont)) {
+        GST_BUFFER_FLAG_SET (obuf, GST_BUFFER_FLAG_DISCONT);
+        discont = FALSE;
+      }
+
+      GST_LOG_OBJECT (enc->element,
+          "pushing buffer of size %d with ts: %" GST_TIME_FORMAT,
+          GST_BUFFER_SIZE (obuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (obuf)));
+      gst_buffer_set_caps (obuf, GST_PAD_CAPS (srcpad));
+      ret = gst_pad_push (srcpad, obuf);
+      obuf = NULL;
+    } else {
+      ret = GST_FLOW_OK;
+    }
+
+#ifdef CN_PAD
+    /* check for stuff to send on cn pad */
+    if (cnbuf && cnpad) {
+      /* only at most 1 SID update per buffer */
+      GST_BUFFER_SIZE (cnbuf) = esize;
+      GST_BUFFER_DURATION (cnbuf) = FRAME_DURATION;
+      GST_BUFFER_TIMESTAMP (cnbuf) = enc->next_ts;
+
+      GST_LOG_OBJECT (enc->element,
+          "pushing cn buffer of size %d with ts: %" GST_TIME_FORMAT,
+          GST_BUFFER_SIZE (cnbuf),
+          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (cnbuf)));
+      gst_buffer_set_caps (cnbuf, GST_PAD_CAPS (cnpad));
+      if (G_LIKELY (ret == GST_FLOW_OK)) {
+        ret = gst_pad_push (cnpad, cnbuf);
+        /* cn pad may not be linked */
+        if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED))
+          ret = GST_FLOW_OK;
+      } else
+        gst_pad_push (cnpad, cnbuf);
+      cnbuf = NULL;
+    } else if (G_UNLIKELY (cnbuf)) {
+      /* should not occur */
+      gst_buffer_unref (cnbuf);
+      cnbuf = NULL;
+    }
+
+    if (dtx != GST_DTX_DECISION_VOICE) {
+      /* still need to count non-voice encoded frame */
+      flush += RAW_FRAME_SIZE;
+      av -= RAW_FRAME_SIZE;
+    }
+#endif /* CN_PAD */
+
+    /* remove used part */
+    gst_adapter_flush (enc->adapter, flush);
+    if (GST_CLOCK_TIME_IS_VALID (enc->next_ts))
+      enc->next_ts += FRAME_DURATION * (flush / RAW_FRAME_SIZE);
+
+    /* end if insufficient left or error */
+    if (av < RAW_FRAME_SIZE || ret != GST_FLOW_OK)
+      break;
+
+    /* allocate new buffer */
+    if (!obuf) {
+      obuf = gst_buffer_new_and_alloc (av / RAW_FRAME_SIZE * CODEC_FRAME_SIZE);
+      odata = GST_BUFFER_DATA (obuf);
+      osize = 0;
+    }
+    /* and prepare to consume again */
+    data = gst_adapter_peek (enc->adapter, av);
+    flush = 0;
+  }
+
+  if (!av) {
+    enc->next_ts = GST_CLOCK_TIME_NONE;
+  }
+
+done:
+#ifdef CN_PAD
+  GST_OBJECT_LOCK (enc->element);
+  if (cnpad)
+    gst_object_unref (cnpad);
+  GST_OBJECT_UNLOCK (enc->element);
+#endif
+
+  return ret;
+
+  /* ERRORS */
+encode_failed:
+  {
+    GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), (NULL));
+    ret = GST_FLOW_ERROR;
+    gst_buffer_unref (obuf);
+    goto done;
+  }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_nokia_speech/gstframedaudioenc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,68 @@
+/* GStreamer Framed Audio Encoder
+ * Copyright 2009 Collabora Ltd,
+ * Copyright 2009 Nokia Corporation
+ *  @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
+ *
+ * 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_FRAMED_AUDIO_ENC_H__
+#define __GST_FRAMED_AUDIO_ENC_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstNokiaFramedAudioEnc      GstNokiaFramedAudioEnc;
+typedef struct _GstNokiaFramedAudioEncClass GstNokiaFramedAudioEncClass;
+
+typedef GstNokiaFramedAudioEnc      GstFramedAudioEnc;
+typedef GstNokiaFramedAudioEncClass GstFramedAudioEncClass;
+
+struct _GstNokiaFramedAudioEnc
+{
+  /* helper for this element */
+  GstElement *element;
+
+  /* private stuff */
+
+  /* pad with incoming data */
+  GstPad *sinkpad;
+
+  GstAdapter *adapter;
+  GstClockTime next_ts;
+};
+
+typedef enum _GstDtxDecision {
+  GST_DTX_DECISION_VOICE,
+  GST_DTX_DECISION_SID_UPDATE,
+  GST_DTX_DECISION_SID_NONE
+} GstDtxDecision;
+
+void      gst_framed_audio_enc_init (GstFramedAudioEnc * enc, GstElement * element,
+          GstDebugCategory * cat);
+void      gst_framed_audio_enc_reset (GstFramedAudioEnc * enc);
+void      gst_framed_audio_enc_finalize (GstFramedAudioEnc * enc);
+GstPad *  gst_framed_audio_enc_request_new_pad (GstFramedAudioEnc * enc,
+          GstPadTemplate * templ, const gchar * req_name, GstPad ** pad_p);
+void      gst_framed_audio_enc_release_pad (GstFramedAudioEnc * enc, GstPad * pad,
+          GstPad ** pad_p, void (disable_cn) (GstElement *));
+gboolean  gst_framed_audio_enc_sink_event (GstPad * pad, GstEvent * event);
+
+G_END_DECLS
+
+#endif /* __GST_FRAMED_AUDIO_ENC_H__ */
--- a/gst_plugins_base/bwins/libgstappu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstappu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -9,26 +9,27 @@
 	gst_app_sink_get_type @ 8 NONAME
 	gst_app_sink_is_eos @ 9 NONAME
 	gst_app_sink_pull_buffer @ 10 NONAME
-	gst_app_sink_pull_preroll @ 11 NONAME
-	gst_app_sink_set_callbacks @ 12 NONAME
-	gst_app_sink_set_caps @ 13 NONAME
-	gst_app_sink_set_drop @ 14 NONAME
-	gst_app_sink_set_emit_signals @ 15 NONAME
-	gst_app_sink_set_max_buffers @ 16 NONAME
-	gst_app_src_end_of_stream @ 17 NONAME
-	gst_app_src_get_caps @ 18 NONAME
-	gst_app_src_get_emit_signals @ 19 NONAME
-	gst_app_src_get_latency @ 20 NONAME
-	gst_app_src_get_max_bytes @ 21 NONAME
-	gst_app_src_get_size @ 22 NONAME
-	gst_app_src_get_stream_type @ 23 NONAME
-	gst_app_src_get_type @ 24 NONAME
-	gst_app_src_push_buffer @ 25 NONAME
-	gst_app_src_set_callbacks @ 26 NONAME
-	gst_app_src_set_caps @ 27 NONAME
-	gst_app_src_set_emit_signals @ 28 NONAME
-	gst_app_src_set_latency @ 29 NONAME
-	gst_app_src_set_max_bytes @ 30 NONAME
-	gst_app_src_set_size @ 31 NONAME
-	gst_app_src_set_stream_type @ 32 NONAME
+	gst_app_sink_pull_buffer_list @ 11 NONAME
+	gst_app_sink_pull_preroll @ 12 NONAME
+	gst_app_sink_set_callbacks @ 13 NONAME
+	gst_app_sink_set_caps @ 14 NONAME
+	gst_app_sink_set_drop @ 15 NONAME
+	gst_app_sink_set_emit_signals @ 16 NONAME
+	gst_app_sink_set_max_buffers @ 17 NONAME
+	gst_app_src_end_of_stream @ 18 NONAME
+	gst_app_src_get_caps @ 19 NONAME
+	gst_app_src_get_emit_signals @ 20 NONAME
+	gst_app_src_get_latency @ 21 NONAME
+	gst_app_src_get_max_bytes @ 22 NONAME
+	gst_app_src_get_size @ 23 NONAME
+	gst_app_src_get_stream_type @ 24 NONAME
+	gst_app_src_get_type @ 25 NONAME
+	gst_app_src_push_buffer @ 26 NONAME
+	gst_app_src_set_callbacks @ 27 NONAME
+	gst_app_src_set_caps @ 28 NONAME
+	gst_app_src_set_emit_signals @ 29 NONAME
+	gst_app_src_set_latency @ 30 NONAME
+	gst_app_src_set_max_bytes @ 31 NONAME
+	gst_app_src_set_size @ 32 NONAME
+	gst_app_src_set_stream_type @ 33 NONAME
 
--- a/gst_plugins_base/bwins/libgstaudioresampleu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstaudioresampleu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,52 +1,4 @@
 EXPORTS
 	_GST_PLUGIN_DESC @ 1 NONAME
-	audioresample_buffer_new @ 2 NONAME
-	audioresample_buffer_new_and_alloc @ 3 NONAME
-	audioresample_buffer_new_subbuffer @ 4 NONAME
-	audioresample_buffer_new_with_data @ 5 NONAME
-	audioresample_buffer_queue_flush @ 6 NONAME
-	audioresample_buffer_queue_free @ 7 NONAME
-	audioresample_buffer_queue_get_depth @ 8 NONAME
-	audioresample_buffer_queue_get_offset @ 9 NONAME
-	audioresample_buffer_queue_new @ 10 NONAME
-	audioresample_buffer_queue_peek @ 11 NONAME
-	audioresample_buffer_queue_pull @ 12 NONAME
-	audioresample_buffer_queue_push @ 13 NONAME
-	audioresample_buffer_ref @ 14 NONAME
-	audioresample_buffer_unref @ 15 NONAME
-	functable_calculate @ 16 NONAME
-	functable_calculate_multiply @ 17 NONAME
-	functable_evaluate @ 18 NONAME
-	functable_fir @ 19 NONAME
-	functable_fir2 @ 20 NONAME
-	functable_free @ 21 NONAME
-	functable_func_boxcar @ 22 NONAME
-	functable_func_hanning @ 23 NONAME
-	functable_func_sinc @ 24 NONAME
-	functable_new @ 25 NONAME
-	functable_set_length @ 26 NONAME
-	functable_set_multiplier @ 27 NONAME
-	functable_set_offset @ 28 NONAME
-	gst_audioresample_get_type @ 29 NONAME
-	resample_add_input_data @ 30 NONAME
-	resample_format_size @ 31 NONAME
-	resample_free @ 32 NONAME
-	resample_get_input_size_for_output @ 33 NONAME
-	resample_get_output_data @ 34 NONAME
-	resample_get_output_size @ 35 NONAME
-	resample_get_output_size_for_input @ 36 NONAME
-	resample_init @ 37 NONAME
-	resample_input_eos @ 38 NONAME
-	resample_input_flush @ 39 NONAME
-	resample_input_pushthrough @ 40 NONAME
-	resample_new @ 41 NONAME
-	resample_scale_chunk @ 42 NONAME
-	resample_scale_functable @ 43 NONAME
-	resample_scale_ref @ 44 NONAME
-	resample_set_filter_length @ 45 NONAME
-	resample_set_format @ 46 NONAME
-	resample_set_input_rate @ 47 NONAME
-	resample_set_method @ 48 NONAME
-	resample_set_n_channels @ 49 NONAME
-	resample_set_output_rate @ 50 NONAME
+	gst_audio_resample_get_type @ 2 NONAME
 
--- a/gst_plugins_base/bwins/libgstaudiou.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstaudiou.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,57 +1,72 @@
 EXPORTS
 	gst_audio_buffer_clip @ 1 NONAME
 	gst_audio_channel_position_get_type @ 2 NONAME
-	gst_audio_clock_get_type @ 3 NONAME
-	gst_audio_clock_new @ 4 NONAME
-	gst_audio_default_registry_mixer_filter @ 5 NONAME
-	gst_audio_duration_from_pad_buffer @ 6 NONAME
-	gst_audio_filter_class_add_pad_templates @ 7 NONAME
-	gst_audio_filter_get_type @ 8 NONAME
-	gst_audio_fixate_channel_positions @ 9 NONAME
-	gst_audio_frame_byte_size @ 10 NONAME
-	gst_audio_frame_length @ 11 NONAME
-	gst_audio_get_channel_positions @ 12 NONAME
-	gst_audio_is_buffer_framed @ 13 NONAME
-	gst_audio_set_caps_channel_positions_list @ 14 NONAME
-	gst_audio_set_channel_positions @ 15 NONAME
-	gst_audio_set_structure_channel_positions_list @ 16 NONAME
-	gst_audio_sink_get_type @ 17 NONAME
-	gst_audio_src_get_type @ 18 NONAME
-	gst_audio_structure_set_int @ 19 NONAME
-	gst_base_audio_sink_create_ringbuffer @ 20 NONAME
-	gst_base_audio_sink_get_provide_clock @ 21 NONAME
-	gst_base_audio_sink_get_slave_method @ 22 NONAME
-	gst_base_audio_sink_get_type @ 23 NONAME
-	gst_base_audio_sink_set_provide_clock @ 24 NONAME
-	gst_base_audio_sink_set_slave_method @ 25 NONAME
-	gst_base_audio_src_create_ringbuffer @ 26 NONAME
-	gst_base_audio_src_get_provide_clock @ 27 NONAME
-	gst_base_audio_src_get_type @ 28 NONAME
-	gst_base_audio_src_set_provide_clock @ 29 NONAME
-	gst_ring_buffer_acquire @ 30 NONAME
-	gst_ring_buffer_advance @ 31 NONAME
-	gst_ring_buffer_clear @ 32 NONAME
-	gst_ring_buffer_clear_all @ 33 NONAME
-	gst_ring_buffer_close_device @ 34 NONAME
-	gst_ring_buffer_commit @ 35 NONAME
-	gst_ring_buffer_commit_full @ 36 NONAME
-	gst_ring_buffer_debug_spec_buff @ 37 NONAME
-	gst_ring_buffer_debug_spec_caps @ 38 NONAME
-	gst_ring_buffer_delay @ 39 NONAME
-	gst_ring_buffer_device_is_open @ 40 NONAME
-	gst_ring_buffer_get_type @ 41 NONAME
-	gst_ring_buffer_is_acquired @ 42 NONAME
-	gst_ring_buffer_may_start @ 43 NONAME
-	gst_ring_buffer_open_device @ 44 NONAME
-	gst_ring_buffer_parse_caps @ 45 NONAME
-	gst_ring_buffer_pause @ 46 NONAME
-	gst_ring_buffer_prepare_read @ 47 NONAME
-	gst_ring_buffer_read @ 48 NONAME
-	gst_ring_buffer_release @ 49 NONAME
-	gst_ring_buffer_samples_done @ 50 NONAME
-	gst_ring_buffer_set_callback @ 51 NONAME
-	gst_ring_buffer_set_flushing @ 52 NONAME
-	gst_ring_buffer_set_sample @ 53 NONAME
-	gst_ring_buffer_start @ 54 NONAME
-	gst_ring_buffer_stop @ 55 NONAME
+	gst_audio_check_channel_positions @ 3 NONAME
+	gst_audio_clock_adjust @ 4 NONAME
+	gst_audio_clock_get_time @ 5 NONAME
+	gst_audio_clock_get_type @ 6 NONAME
+	gst_audio_clock_new @ 7 NONAME
+	gst_audio_clock_reset @ 8 NONAME
+	gst_audio_default_registry_mixer_filter @ 9 NONAME
+	gst_audio_duration_from_pad_buffer @ 10 NONAME
+	gst_audio_filter_class_add_pad_templates @ 11 NONAME
+	gst_audio_filter_get_type @ 12 NONAME
+	gst_audio_fixate_channel_positions @ 13 NONAME
+	gst_audio_frame_byte_size @ 14 NONAME
+	gst_audio_frame_length @ 15 NONAME
+	gst_audio_get_channel_positions @ 16 NONAME
+	gst_audio_is_buffer_framed @ 17 NONAME
+	gst_audio_set_caps_channel_positions_list @ 18 NONAME
+	gst_audio_set_channel_positions @ 19 NONAME
+	gst_audio_set_structure_channel_positions_list @ 20 NONAME
+	gst_audio_sink_get_type @ 21 NONAME
+	gst_audio_src_get_type @ 22 NONAME
+	gst_audio_structure_set_int @ 23 NONAME
+	gst_base_audio_sink_create_ringbuffer @ 24 NONAME
+	gst_base_audio_sink_get_provide_clock @ 25 NONAME
+	gst_base_audio_sink_get_slave_method @ 26 NONAME
+	gst_base_audio_sink_get_type @ 27 NONAME
+	gst_base_audio_sink_set_provide_clock @ 28 NONAME
+	gst_base_audio_sink_set_slave_method @ 29 NONAME
+	gst_base_audio_sink_slave_method_get_type @ 30 NONAME
+	gst_base_audio_src_create_ringbuffer @ 31 NONAME
+	gst_base_audio_src_get_provide_clock @ 32 NONAME
+	gst_base_audio_src_get_slave_method @ 33 NONAME
+	gst_base_audio_src_get_type @ 34 NONAME
+	gst_base_audio_src_set_provide_clock @ 35 NONAME
+	gst_base_audio_src_set_slave_method @ 36 NONAME
+	gst_base_audio_src_slave_method_get_type @ 37 NONAME
+	gst_buffer_format_get_type @ 38 NONAME
+	gst_buffer_format_type_get_type @ 39 NONAME
+	gst_ring_buffer_acquire @ 40 NONAME
+	gst_ring_buffer_activate @ 41 NONAME
+	gst_ring_buffer_advance @ 42 NONAME
+	gst_ring_buffer_clear @ 43 NONAME
+	gst_ring_buffer_clear_all @ 44 NONAME
+	gst_ring_buffer_close_device @ 45 NONAME
+	gst_ring_buffer_commit @ 46 NONAME
+	gst_ring_buffer_commit_full @ 47 NONAME
+	gst_ring_buffer_convert @ 48 NONAME
+	gst_ring_buffer_debug_spec_buff @ 49 NONAME
+	gst_ring_buffer_debug_spec_caps @ 50 NONAME
+	gst_ring_buffer_delay @ 51 NONAME
+	gst_ring_buffer_device_is_open @ 52 NONAME
+	gst_ring_buffer_get_type @ 53 NONAME
+	gst_ring_buffer_is_acquired @ 54 NONAME
+	gst_ring_buffer_is_active @ 55 NONAME
+	gst_ring_buffer_may_start @ 56 NONAME
+	gst_ring_buffer_open_device @ 57 NONAME
+	gst_ring_buffer_parse_caps @ 58 NONAME
+	gst_ring_buffer_pause @ 59 NONAME
+	gst_ring_buffer_prepare_read @ 60 NONAME
+	gst_ring_buffer_read @ 61 NONAME
+	gst_ring_buffer_release @ 62 NONAME
+	gst_ring_buffer_samples_done @ 63 NONAME
+	gst_ring_buffer_seg_state_get_type @ 64 NONAME
+	gst_ring_buffer_set_callback @ 65 NONAME
+	gst_ring_buffer_set_flushing @ 66 NONAME
+	gst_ring_buffer_set_sample @ 67 NONAME
+	gst_ring_buffer_start @ 68 NONAME
+	gst_ring_buffer_state_get_type @ 69 NONAME
+	gst_ring_buffer_stop @ 70 NONAME
 
--- a/gst_plugins_base/bwins/libgstcddau.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstcddau.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,5 @@
 EXPORTS
-	__gst_cdda_rfc822_binary @ 1 NONAME
-	gst_cdda_base_src_add_track @ 2 NONAME
-	gst_cdda_base_src_get_type @ 3 NONAME
+	gst_cdda_base_src_add_track @ 1 NONAME
+	gst_cdda_base_src_get_type @ 2 NONAME
+	gst_cdda_base_src_mode_get_type @ 3 NONAME
 
--- a/gst_plugins_base/bwins/libgstdecodebin2u.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstdecodebin2u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,18 +1,21 @@
 EXPORTS
 	_GST_PLUGIN_DESC @ 1 NONAME
 	gst_autoplug_select_result_get_type @ 2 NONAME
-	gst_factory_list_debug @ 3 NONAME
-	gst_factory_list_filter @ 4 NONAME
-	gst_factory_list_get_elements @ 5 NONAME
-	gst_factory_list_is_type @ 6 NONAME
-	gst_play_flags_get_type @ 7 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT @ 8 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 9 NONAME
-	gst_play_marshal_BOXED__INT @ 10 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT @ 11 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED @ 12 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 13 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT @ 14 NONAME
-	gst_play_marshal_OBJECT__BOXED @ 15 NONAME
-	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 16 NONAME
+	gst_decode_bin_plugin_init @ 3 NONAME
+	gst_decode_pad_get_type @ 4 NONAME
+	gst_factory_list_debug @ 5 NONAME
+	gst_factory_list_filter @ 6 NONAME
+	gst_factory_list_get_elements @ 7 NONAME
+	gst_factory_list_is_type @ 8 NONAME
+	gst_play_flags_get_type @ 9 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_BOXED @ 10 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 11 NONAME
+	gst_play_marshal_BOXED__INT @ 12 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED @ 13 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED_BOXED @ 14 NONAME
+	gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT @ 15 NONAME
+	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 16 NONAME
+	gst_play_marshal_OBJECT__BOXED @ 17 NONAME
+	gst_play_marshal_OBJECT__INT @ 18 NONAME
+	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 19 NONAME
 
--- a/gst_plugins_base/bwins/libgstdecodebinu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstdecodebinu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,12 +1,13 @@
 EXPORTS
 	_GST_PLUGIN_DESC @ 1 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT @ 2 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_BOXED @ 2 NONAME
 	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 3 NONAME
 	gst_play_marshal_BOXED__INT @ 4 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT @ 5 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED @ 6 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 7 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT @ 8 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED @ 5 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED_BOXED @ 6 NONAME
+	gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT @ 7 NONAME
+	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 8 NONAME
 	gst_play_marshal_OBJECT__BOXED @ 9 NONAME
-	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 10 NONAME
+	gst_play_marshal_OBJECT__INT @ 10 NONAME
+	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 11 NONAME
 
--- a/gst_plugins_base/bwins/libgstffmpegcolorspaceu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstffmpegcolorspaceu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -5,25 +5,25 @@
 	av_free_static @ 4 NONAME
 	av_freep @ 5 NONAME
 	av_malloc @ 6 NONAME
-	av_mallocz_static @ 7 NONAME
-	av_realloc @ 8 NONAME
-	av_strdup @ 9 NONAME
-	avcodec_alloc_context @ 10 NONAME
-	avcodec_find_best_pix_fmt @ 11 NONAME
-	avcodec_get_chroma_sub_sample @ 12 NONAME
-	avcodec_get_context_defaults @ 13 NONAME
-	avcodec_get_pix_fmt @ 14 NONAME
-	avcodec_get_pix_fmt_loss @ 15 NONAME
-	avcodec_get_pix_fmt_name @ 16 NONAME
-	avcodec_init @ 17 NONAME
-	dsputil_static_init @ 18 NONAME
-	get_pix_fmt_info @ 19 NONAME
-	gst_ffmpegcolorspace_register @ 20 NONAME
-	gst_ffmpegcsp_avpicture_fill @ 21 NONAME
-	gst_ffmpegcsp_caps_with_codectype @ 22 NONAME
-	gst_ffmpegcsp_codectype_to_caps @ 23 NONAME
-	img_convert @ 24 NONAME
-	img_get_alpha_info @ 25 NONAME
-	av_mallocz @ 26 NONAME
-	avpicture_get_size @ 27 NONAME
+	av_mallocz @ 7 NONAME
+	av_mallocz_static @ 8 NONAME
+	av_realloc @ 9 NONAME
+	av_strdup @ 10 NONAME
+	avcodec_alloc_context @ 11 NONAME
+	avcodec_find_best_pix_fmt @ 12 NONAME
+	avcodec_get_chroma_sub_sample @ 13 NONAME
+	avcodec_get_context_defaults @ 14 NONAME
+	avcodec_get_pix_fmt @ 15 NONAME
+	avcodec_get_pix_fmt_loss @ 16 NONAME
+	avcodec_get_pix_fmt_name @ 17 NONAME
+	avcodec_init @ 18 NONAME
+	avpicture_get_size @ 19 NONAME
+	dsputil_static_init @ 20 NONAME
+	get_pix_fmt_info @ 21 NONAME
+	gst_ffmpegcolorspace_register @ 22 NONAME
+	gst_ffmpegcsp_avpicture_fill @ 23 NONAME
+	gst_ffmpegcsp_caps_with_codectype @ 24 NONAME
+	gst_ffmpegcsp_codectype_to_caps @ 25 NONAME
+	img_convert @ 26 NONAME
+	img_get_alpha_info @ 27 NONAME
 
--- a/gst_plugins_base/bwins/libgstinterfacesu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstinterfacesu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -39,53 +39,80 @@
 	gst_mixer_track_get_type @ 38 NONAME
 	gst_mixer_type_get_type @ 39 NONAME
 	gst_mixer_volume_changed @ 40 NONAME
-	gst_navigation_get_type @ 41 NONAME
-	gst_navigation_send_event @ 42 NONAME
-	gst_navigation_send_key_event @ 43 NONAME
-	gst_navigation_send_mouse_event @ 44 NONAME
-	gst_property_probe_get_properties @ 45 NONAME
-	gst_property_probe_get_property @ 46 NONAME
-	gst_property_probe_get_type @ 47 NONAME
-	gst_property_probe_get_values @ 48 NONAME
-	gst_property_probe_get_values_name @ 49 NONAME
-	gst_property_probe_needs_probe @ 50 NONAME
-	gst_property_probe_needs_probe_name @ 51 NONAME
-	gst_property_probe_probe_and_get_values @ 52 NONAME
-	gst_property_probe_probe_and_get_values_name @ 53 NONAME
-	gst_property_probe_probe_property @ 54 NONAME
-	gst_property_probe_probe_property_name @ 55 NONAME
-	gst_tuner_channel_changed @ 56 NONAME
-	gst_tuner_channel_flags_get_type @ 57 NONAME
-	gst_tuner_channel_get_type @ 58 NONAME
-	gst_tuner_find_channel_by_name @ 59 NONAME
-	gst_tuner_find_norm_by_name @ 60 NONAME
-	gst_tuner_frequency_changed @ 61 NONAME
-	gst_tuner_get_channel @ 62 NONAME
-	gst_tuner_get_frequency @ 63 NONAME
-	gst_tuner_get_norm @ 64 NONAME
-	gst_tuner_get_type @ 65 NONAME
-	gst_tuner_list_channels @ 66 NONAME
-	gst_tuner_list_norms @ 67 NONAME
-	gst_tuner_norm_changed @ 68 NONAME
-	gst_tuner_norm_get_type @ 69 NONAME
-	gst_tuner_set_channel @ 70 NONAME
-	gst_tuner_set_frequency @ 71 NONAME
-	gst_tuner_set_norm @ 72 NONAME
-	gst_tuner_signal_changed @ 73 NONAME
-	gst_tuner_signal_strength @ 74 NONAME
-	gst_video_orientation_get_hcenter @ 75 NONAME
-	gst_video_orientation_get_hflip @ 76 NONAME
-	gst_video_orientation_get_type @ 77 NONAME
-	gst_video_orientation_get_vcenter @ 78 NONAME
-	gst_video_orientation_get_vflip @ 79 NONAME
-	gst_video_orientation_set_hcenter @ 80 NONAME
-	gst_video_orientation_set_hflip @ 81 NONAME
-	gst_video_orientation_set_vcenter @ 82 NONAME
-	gst_video_orientation_set_vflip @ 83 NONAME
-	gst_x_overlay_expose @ 84 NONAME
-	gst_x_overlay_get_type @ 85 NONAME
-	gst_x_overlay_got_xwindow_id @ 86 NONAME
-	gst_x_overlay_handle_events @ 87 NONAME
-	gst_x_overlay_prepare_xwindow_id @ 88 NONAME
-	gst_x_overlay_set_xwindow_id @ 89 NONAME
+	gst_navigation_command_get_type @ 41 NONAME
+	gst_navigation_event_get_type @ 42 NONAME
+	gst_navigation_event_parse_command @ 43 NONAME
+	gst_navigation_event_parse_key_event @ 44 NONAME
+	gst_navigation_event_parse_mouse_button_event @ 45 NONAME
+	gst_navigation_event_parse_mouse_move_event @ 46 NONAME
+	gst_navigation_event_type_get_type @ 47 NONAME
+	gst_navigation_get_type @ 48 NONAME
+	gst_navigation_message_get_type @ 49 NONAME
+	gst_navigation_message_new_angles_changed @ 50 NONAME
+	gst_navigation_message_new_commands_changed @ 51 NONAME
+	gst_navigation_message_new_mouse_over @ 52 NONAME
+	gst_navigation_message_parse_angles_changed @ 53 NONAME
+	gst_navigation_message_parse_mouse_over @ 54 NONAME
+	gst_navigation_message_type_get_type @ 55 NONAME
+	gst_navigation_query_get_type @ 56 NONAME
+	gst_navigation_query_new_angles @ 57 NONAME
+	gst_navigation_query_new_commands @ 58 NONAME
+	gst_navigation_query_parse_angles @ 59 NONAME
+	gst_navigation_query_parse_commands_length @ 60 NONAME
+	gst_navigation_query_parse_commands_nth @ 61 NONAME
+	gst_navigation_query_set_angles @ 62 NONAME
+	gst_navigation_query_set_commands @ 63 NONAME
+	gst_navigation_query_set_commandsv @ 64 NONAME
+	gst_navigation_query_type_get_type @ 65 NONAME
+	gst_navigation_send_command @ 66 NONAME
+	gst_navigation_send_event @ 67 NONAME
+	gst_navigation_send_key_event @ 68 NONAME
+	gst_navigation_send_mouse_event @ 69 NONAME
+	gst_property_probe_get_properties @ 70 NONAME
+	gst_property_probe_get_property @ 71 NONAME
+	gst_property_probe_get_type @ 72 NONAME
+	gst_property_probe_get_values @ 73 NONAME
+	gst_property_probe_get_values_name @ 74 NONAME
+	gst_property_probe_needs_probe @ 75 NONAME
+	gst_property_probe_needs_probe_name @ 76 NONAME
+	gst_property_probe_probe_and_get_values @ 77 NONAME
+	gst_property_probe_probe_and_get_values_name @ 78 NONAME
+	gst_property_probe_probe_property @ 79 NONAME
+	gst_property_probe_probe_property_name @ 80 NONAME
+	gst_tuner_channel_changed @ 81 NONAME
+	gst_tuner_channel_flags_get_type @ 82 NONAME
+	gst_tuner_channel_get_type @ 83 NONAME
+	gst_tuner_find_channel_by_name @ 84 NONAME
+	gst_tuner_find_norm_by_name @ 85 NONAME
+	gst_tuner_frequency_changed @ 86 NONAME
+	gst_tuner_get_channel @ 87 NONAME
+	gst_tuner_get_frequency @ 88 NONAME
+	gst_tuner_get_norm @ 89 NONAME
+	gst_tuner_get_type @ 90 NONAME
+	gst_tuner_list_channels @ 91 NONAME
+	gst_tuner_list_norms @ 92 NONAME
+	gst_tuner_norm_changed @ 93 NONAME
+	gst_tuner_norm_get_type @ 94 NONAME
+	gst_tuner_set_channel @ 95 NONAME
+	gst_tuner_set_frequency @ 96 NONAME
+	gst_tuner_set_norm @ 97 NONAME
+	gst_tuner_signal_changed @ 98 NONAME
+	gst_tuner_signal_strength @ 99 NONAME
+	gst_video_orientation_get_hcenter @ 100 NONAME
+	gst_video_orientation_get_hflip @ 101 NONAME
+	gst_video_orientation_get_type @ 102 NONAME
+	gst_video_orientation_get_vcenter @ 103 NONAME
+	gst_video_orientation_get_vflip @ 104 NONAME
+	gst_video_orientation_set_hcenter @ 105 NONAME
+	gst_video_orientation_set_hflip @ 106 NONAME
+	gst_video_orientation_set_vcenter @ 107 NONAME
+	gst_video_orientation_set_vflip @ 108 NONAME
+	gst_x_overlay_expose @ 109 NONAME
+	gst_x_overlay_get_type @ 110 NONAME
+	gst_x_overlay_got_xwindow_id @ 111 NONAME
+	gst_x_overlay_handle_events @ 112 NONAME
+	gst_x_overlay_prepare_xwindow_id @ 113 NONAME
+	gst_x_overlay_set_xwindow_id @ 114 NONAME
+	gst_color_balance_get_balance_type @ 115 NONAME
+	gst_mixer_get_mixer_type @ 116 NONAME
 
--- a/gst_plugins_base/bwins/libgstnetbufferu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstnetbufferu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,10 +1,13 @@
 EXPORTS
 	gst_netaddress_equal @ 1 NONAME
-	gst_netaddress_get_ip4_address @ 2 NONAME
-	gst_netaddress_get_ip6_address @ 3 NONAME
-	gst_netaddress_get_net_type @ 4 NONAME
-	gst_netaddress_set_ip4_address @ 5 NONAME
-	gst_netaddress_set_ip6_address @ 6 NONAME
-	gst_netbuffer_get_type @ 7 NONAME
-	gst_netbuffer_new @ 8 NONAME
+	gst_netaddress_get_address_bytes @ 2 NONAME
+	gst_netaddress_get_ip4_address @ 3 NONAME
+	gst_netaddress_get_ip6_address @ 4 NONAME
+	gst_netaddress_get_net_type @ 5 NONAME
+	gst_netaddress_set_address_bytes @ 6 NONAME
+	gst_netaddress_set_ip4_address @ 7 NONAME
+	gst_netaddress_set_ip6_address @ 8 NONAME
+	gst_netbuffer_get_type @ 9 NONAME
+	gst_netbuffer_new @ 10 NONAME
+	gst_netaddress_to_string @ 11 NONAME
 
--- a/gst_plugins_base/bwins/libgstpbutilsu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstpbutilsu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -16,18 +16,18 @@
 	gst_missing_element_message_new @ 15 NONAME
 	gst_missing_encoder_installer_detail_new @ 16 NONAME
 	gst_missing_encoder_message_new @ 17 NONAME
-	gst_missing_plugin_message_get_installer_detail @ 18 NONAME
-	gst_missing_uri_sink_installer_detail_new @ 19 NONAME
-	gst_missing_uri_sink_message_new @ 20 NONAME
-	gst_missing_uri_source_installer_detail_new @ 21 NONAME
-	gst_missing_uri_source_message_new @ 22 NONAME
-	gst_pb_utils_add_codec_description_to_tag_list @ 23 NONAME
-	gst_pb_utils_get_codec_description @ 24 NONAME
-	gst_pb_utils_get_decoder_description @ 25 NONAME
-	gst_pb_utils_get_element_description @ 26 NONAME
-	gst_pb_utils_get_encoder_description @ 27 NONAME
-	gst_pb_utils_get_sink_description @ 28 NONAME
-	gst_pb_utils_get_source_description @ 29 NONAME
-	gst_pb_utils_init @ 30 NONAME
-	gst_missing_plugin_message_get_description @ 31 NONAME
+	gst_missing_plugin_message_get_description @ 18 NONAME
+	gst_missing_plugin_message_get_installer_detail @ 19 NONAME
+	gst_missing_uri_sink_installer_detail_new @ 20 NONAME
+	gst_missing_uri_sink_message_new @ 21 NONAME
+	gst_missing_uri_source_installer_detail_new @ 22 NONAME
+	gst_missing_uri_source_message_new @ 23 NONAME
+	gst_pb_utils_add_codec_description_to_tag_list @ 24 NONAME
+	gst_pb_utils_get_codec_description @ 25 NONAME
+	gst_pb_utils_get_decoder_description @ 26 NONAME
+	gst_pb_utils_get_element_description @ 27 NONAME
+	gst_pb_utils_get_encoder_description @ 28 NONAME
+	gst_pb_utils_get_sink_description @ 29 NONAME
+	gst_pb_utils_get_source_description @ 30 NONAME
+	gst_pb_utils_init @ 31 NONAME
 
--- a/gst_plugins_base/bwins/libgstplaybinu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstplaybinu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -10,32 +10,36 @@
 	gst_play_bin_plugin_init @ 9 NONAME
 	gst_play_flags_get_type @ 10 NONAME
 	gst_play_frame_conv_convert @ 11 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT @ 12 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_BOXED @ 12 NONAME
 	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 13 NONAME
 	gst_play_marshal_BOXED__INT @ 14 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT @ 15 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED @ 16 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 17 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT @ 18 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED @ 15 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED_BOXED @ 16 NONAME
+	gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT @ 17 NONAME
+	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 18 NONAME
 	gst_play_marshal_OBJECT__BOXED @ 19 NONAME
-	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 20 NONAME
-	gst_play_sink_get_flags @ 21 NONAME
-	gst_play_sink_get_last_frame @ 22 NONAME
-	gst_play_sink_get_mute @ 23 NONAME
-	gst_play_sink_get_type @ 24 NONAME
-	gst_play_sink_get_volume @ 25 NONAME
-	gst_play_sink_reconfigure @ 26 NONAME
-	gst_play_sink_release_pad @ 27 NONAME
-	gst_play_sink_request_pad @ 28 NONAME
-	gst_play_sink_set_audio_sink @ 29 NONAME
-	gst_play_sink_set_flags @ 30 NONAME
-	gst_play_sink_set_mute @ 31 NONAME
-	gst_play_sink_set_video_sink @ 32 NONAME
-	gst_play_sink_set_vis_plugin @ 33 NONAME
-	gst_play_sink_set_volume @ 34 NONAME
-	gst_stream_info_get_type @ 35 NONAME
-	gst_stream_info_is_mute @ 36 NONAME
-	gst_stream_info_new @ 37 NONAME
-	gst_stream_info_set_mute @ 38 NONAME
-	gst_stream_selector_get_type @ 39 NONAME
+	gst_play_marshal_OBJECT__INT @ 20 NONAME
+	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 21 NONAME
+	gst_play_sink_get_flags @ 22 NONAME
+	gst_play_sink_get_font_desc @ 23 NONAME
+	gst_play_sink_get_last_frame @ 24 NONAME
+	gst_play_sink_get_mute @ 25 NONAME
+	gst_play_sink_get_sink @ 26 NONAME
+	gst_play_sink_get_type @ 27 NONAME
+	gst_play_sink_get_vis_plugin @ 28 NONAME
+	gst_play_sink_get_volume @ 29 NONAME
+	gst_play_sink_reconfigure @ 30 NONAME
+	gst_play_sink_release_pad @ 31 NONAME
+	gst_play_sink_request_pad @ 32 NONAME
+	gst_play_sink_set_flags @ 33 NONAME
+	gst_play_sink_set_font_desc @ 34 NONAME
+	gst_play_sink_set_mute @ 35 NONAME
+	gst_play_sink_set_sink @ 36 NONAME
+	gst_play_sink_set_vis_plugin @ 37 NONAME
+	gst_play_sink_set_volume @ 38 NONAME
+	gst_stream_info_get_type @ 39 NONAME
+	gst_stream_info_is_mute @ 40 NONAME
+	gst_stream_info_new @ 41 NONAME
+	gst_stream_info_set_mute @ 42 NONAME
+	gst_stream_selector_get_type @ 43 NONAME
 
--- a/gst_plugins_base/bwins/libgstrtpu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstrtpu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,19 +1,18 @@
-EXPORTS
-	gst_base_rtp_audio_payload_base_init @ 1 NONAME
-	gst_base_rtp_audio_payload_get_adapter @ 2 NONAME
-	gst_base_rtp_audio_payload_get_type @ 3 NONAME
-	gst_base_rtp_audio_payload_push @ 4 NONAME
-	gst_base_rtp_audio_payload_set_frame_based @ 5 NONAME
-	gst_base_rtp_audio_payload_set_frame_options @ 6 NONAME
-	gst_base_rtp_audio_payload_set_sample_based @ 7 NONAME
-	gst_base_rtp_audio_payload_set_sample_options @ 8 NONAME
-	gst_base_rtp_audio_payload_set_samplebits_options @ 9 NONAME
-	gst_base_rtp_depayload_get_type @ 10 NONAME
-	gst_base_rtp_depayload_push @ 11 NONAME
-	gst_base_rtp_depayload_push_ts @ 12 NONAME
-	gst_basertppayload_get_type @ 13 NONAME
-	gst_basertppayload_is_filled @ 14 NONAME
-	gst_basertppayload_push @ 15 NONAME
+EXPORTS	gst_base_rtp_audio_payload_get_adapter @ 1 NONAME
+	gst_base_rtp_audio_payload_get_type @ 2 NONAME
+	gst_base_rtp_audio_payload_push @ 3 NONAME
+	gst_base_rtp_audio_payload_set_frame_based @ 4 NONAME
+	gst_base_rtp_audio_payload_set_frame_options @ 5 NONAME
+	gst_base_rtp_audio_payload_set_sample_based @ 6 NONAME
+	gst_base_rtp_audio_payload_set_sample_options @ 7 NONAME
+	gst_base_rtp_audio_payload_set_samplebits_options @ 8 NONAME
+	gst_base_rtp_depayload_get_type @ 9 NONAME
+	gst_base_rtp_depayload_push @ 10 NONAME
+	gst_base_rtp_depayload_push_ts @ 11 NONAME
+	gst_basertppayload_get_type @ 12 NONAME
+	gst_basertppayload_is_filled @ 13 NONAME
+	gst_basertppayload_push @ 14 NONAME
+	gst_basertppayload_push_list @ 15 NONAME
 	gst_basertppayload_set_options @ 16 NONAME
 	gst_basertppayload_set_outcaps @ 17 NONAME
 	gst_rtcp_buffer_add_packet @ 18 NONAME
@@ -34,72 +33,88 @@
 	gst_rtcp_packet_bye_get_reason_len @ 33 NONAME
 	gst_rtcp_packet_bye_get_ssrc_count @ 34 NONAME
 	gst_rtcp_packet_bye_set_reason @ 35 NONAME
-	gst_rtcp_packet_get_count @ 36 NONAME
-	gst_rtcp_packet_get_length @ 37 NONAME
-	gst_rtcp_packet_get_padding @ 38 NONAME
-	gst_rtcp_packet_get_rb @ 39 NONAME
-	gst_rtcp_packet_get_rb_count @ 40 NONAME
-	gst_rtcp_packet_get_type @ 41 NONAME
-	gst_rtcp_packet_remove @ 42 NONAME
-	gst_rtcp_packet_rr_get_ssrc @ 43 NONAME
-	gst_rtcp_packet_rr_set_ssrc @ 44 NONAME
-	gst_rtcp_packet_sdes_add_entry @ 45 NONAME
-	gst_rtcp_packet_sdes_add_item @ 46 NONAME
-	gst_rtcp_packet_sdes_copy_entry @ 47 NONAME
-	gst_rtcp_packet_sdes_first_entry @ 48 NONAME
-	gst_rtcp_packet_sdes_first_item @ 49 NONAME
-	gst_rtcp_packet_sdes_get_entry @ 50 NONAME
-	gst_rtcp_packet_sdes_get_item_count @ 51 NONAME
-	gst_rtcp_packet_sdes_get_ssrc @ 52 NONAME
-	gst_rtcp_packet_sdes_next_entry @ 53 NONAME
-	gst_rtcp_packet_sdes_next_item @ 54 NONAME
-	gst_rtcp_packet_set_rb @ 55 NONAME
-	gst_rtcp_packet_sr_get_sender_info @ 56 NONAME
-	gst_rtcp_packet_sr_set_sender_info @ 57 NONAME
-	gst_rtcp_unix_to_ntp @ 58 NONAME
-	gst_rtp_buffer_allocate_data @ 59 NONAME
-	gst_rtp_buffer_calc_header_len @ 60 NONAME
-	gst_rtp_buffer_calc_packet_len @ 61 NONAME
-	gst_rtp_buffer_calc_payload_len @ 62 NONAME
-	gst_rtp_buffer_compare_seqnum @ 63 NONAME
-	gst_rtp_buffer_default_clock_rate @ 64 NONAME
-	gst_rtp_buffer_ext_timestamp @ 65 NONAME
-	gst_rtp_buffer_get_csrc @ 66 NONAME
-	gst_rtp_buffer_get_csrc_count @ 67 NONAME
-	gst_rtp_buffer_get_extension @ 68 NONAME
-	gst_rtp_buffer_get_extension_data @ 69 NONAME
-	gst_rtp_buffer_get_header_len @ 70 NONAME
-	gst_rtp_buffer_get_marker @ 71 NONAME
-	gst_rtp_buffer_get_packet_len @ 72 NONAME
-	gst_rtp_buffer_get_padding @ 73 NONAME
-	gst_rtp_buffer_get_payload @ 74 NONAME
-	gst_rtp_buffer_get_payload_buffer @ 75 NONAME
-	gst_rtp_buffer_get_payload_len @ 76 NONAME
-	gst_rtp_buffer_get_payload_subbuffer @ 77 NONAME
-	gst_rtp_buffer_get_payload_type @ 78 NONAME
-	gst_rtp_buffer_get_seq @ 79 NONAME
-	gst_rtp_buffer_get_ssrc @ 80 NONAME
-	gst_rtp_buffer_get_timestamp @ 81 NONAME
-	gst_rtp_buffer_get_version @ 82 NONAME
-	gst_rtp_buffer_new_allocate @ 83 NONAME
-	gst_rtp_buffer_new_allocate_len @ 84 NONAME
-	gst_rtp_buffer_new_copy_data @ 85 NONAME
-	gst_rtp_buffer_new_take_data @ 86 NONAME
-	gst_rtp_buffer_pad_to @ 87 NONAME
-	gst_rtp_buffer_set_csrc @ 88 NONAME
-	gst_rtp_buffer_set_extension @ 89 NONAME
-	gst_rtp_buffer_set_extension_data @ 90 NONAME
-	gst_rtp_buffer_set_marker @ 91 NONAME
-	gst_rtp_buffer_set_packet_len @ 92 NONAME
-	gst_rtp_buffer_set_padding @ 93 NONAME
-	gst_rtp_buffer_set_payload_type @ 94 NONAME
-	gst_rtp_buffer_set_seq @ 95 NONAME
-	gst_rtp_buffer_set_ssrc @ 96 NONAME
-	gst_rtp_buffer_set_timestamp @ 97 NONAME
-	gst_rtp_buffer_set_version @ 98 NONAME
-	gst_rtp_buffer_validate @ 99 NONAME
-	gst_rtp_buffer_validate_data @ 100 NONAME
-	gst_rtp_payload_info_for_name @ 101 NONAME
-	gst_rtp_payload_info_for_pt @ 102 NONAME
-	gst_rtcp_packet_move_to_next @ 103 NONAME
+	gst_rtcp_packet_fb_get_media_ssrc @ 36 NONAME
+	gst_rtcp_packet_fb_get_sender_ssrc @ 37 NONAME
+	gst_rtcp_packet_fb_get_type @ 38 NONAME
+	gst_rtcp_packet_fb_set_media_ssrc @ 39 NONAME
+	gst_rtcp_packet_fb_set_sender_ssrc @ 40 NONAME
+	gst_rtcp_packet_fb_set_type @ 41 NONAME
+	gst_rtcp_packet_get_count @ 42 NONAME
+	gst_rtcp_packet_get_length @ 43 NONAME
+	gst_rtcp_packet_get_padding @ 44 NONAME
+	gst_rtcp_packet_get_rb @ 45 NONAME
+	gst_rtcp_packet_get_rb_count @ 46 NONAME
+	gst_rtcp_packet_get_type @ 47 NONAME
+	gst_rtcp_packet_move_to_next @ 48 NONAME
+	gst_rtcp_packet_remove @ 49 NONAME
+	gst_rtcp_packet_rr_get_ssrc @ 50 NONAME
+	gst_rtcp_packet_rr_set_ssrc @ 51 NONAME
+	gst_rtcp_packet_sdes_add_entry @ 52 NONAME
+	gst_rtcp_packet_sdes_add_item @ 53 NONAME
+	gst_rtcp_packet_sdes_copy_entry @ 54 NONAME
+	gst_rtcp_packet_sdes_first_entry @ 55 NONAME
+	gst_rtcp_packet_sdes_first_item @ 56 NONAME
+	gst_rtcp_packet_sdes_get_entry @ 57 NONAME
+	gst_rtcp_packet_sdes_get_item_count @ 58 NONAME
+	gst_rtcp_packet_sdes_get_ssrc @ 59 NONAME
+	gst_rtcp_packet_sdes_next_entry @ 60 NONAME
+	gst_rtcp_packet_sdes_next_item @ 61 NONAME
+	gst_rtcp_packet_set_rb @ 62 NONAME
+	gst_rtcp_packet_sr_get_sender_info @ 63 NONAME
+	gst_rtcp_packet_sr_set_sender_info @ 64 NONAME
+	gst_rtcp_unix_to_ntp @ 65 NONAME
+	gst_rtp_buffer_allocate_data @ 66 NONAME
+	gst_rtp_buffer_calc_header_len @ 67 NONAME
+	gst_rtp_buffer_calc_packet_len @ 68 NONAME
+	gst_rtp_buffer_calc_payload_len @ 69 NONAME
+	gst_rtp_buffer_compare_seqnum @ 70 NONAME
+	gst_rtp_buffer_default_clock_rate @ 71 NONAME
+	gst_rtp_buffer_ext_timestamp @ 72 NONAME
+	gst_rtp_buffer_get_csrc @ 73 NONAME
+	gst_rtp_buffer_get_csrc_count @ 74 NONAME
+	gst_rtp_buffer_get_extension @ 75 NONAME
+	gst_rtp_buffer_get_extension_data @ 76 NONAME
+	gst_rtp_buffer_get_header_len @ 77 NONAME
+	gst_rtp_buffer_get_marker @ 78 NONAME
+	gst_rtp_buffer_get_packet_len @ 79 NONAME
+	gst_rtp_buffer_get_padding @ 80 NONAME
+	gst_rtp_buffer_get_payload @ 81 NONAME
+	gst_rtp_buffer_get_payload_buffer @ 82 NONAME
+	gst_rtp_buffer_get_payload_len @ 83 NONAME
+	gst_rtp_buffer_get_payload_subbuffer @ 84 NONAME
+	gst_rtp_buffer_get_payload_type @ 85 NONAME
+	gst_rtp_buffer_get_seq @ 86 NONAME
+	gst_rtp_buffer_get_ssrc @ 87 NONAME
+	gst_rtp_buffer_get_timestamp @ 88 NONAME
+	gst_rtp_buffer_get_version @ 89 NONAME
+	gst_rtp_buffer_list_get_payload_len @ 90 NONAME
+	gst_rtp_buffer_list_get_payload_type @ 91 NONAME
+	gst_rtp_buffer_list_get_seq @ 92 NONAME
+	gst_rtp_buffer_list_get_ssrc @ 93 NONAME
+	gst_rtp_buffer_list_get_timestamp @ 94 NONAME
+	gst_rtp_buffer_list_set_payload_type @ 95 NONAME
+	gst_rtp_buffer_list_set_seq @ 96 NONAME
+	gst_rtp_buffer_list_set_ssrc @ 97 NONAME
+	gst_rtp_buffer_list_set_timestamp @ 98 NONAME
+	gst_rtp_buffer_list_validate @ 99 NONAME
+	gst_rtp_buffer_new_allocate @ 100 NONAME
+	gst_rtp_buffer_new_allocate_len @ 101 NONAME
+	gst_rtp_buffer_new_copy_data @ 102 NONAME
+	gst_rtp_buffer_new_take_data @ 103 NONAME
+	gst_rtp_buffer_pad_to @ 104 NONAME
+	gst_rtp_buffer_set_csrc @ 105 NONAME
+	gst_rtp_buffer_set_extension @ 106 NONAME
+	gst_rtp_buffer_set_extension_data @ 107 NONAME
+	gst_rtp_buffer_set_marker @ 108 NONAME
+	gst_rtp_buffer_set_packet_len @ 109 NONAME
+	gst_rtp_buffer_set_padding @ 110 NONAME
+	gst_rtp_buffer_set_payload_type @ 111 NONAME
+	gst_rtp_buffer_set_seq @ 112 NONAME
+	gst_rtp_buffer_set_ssrc @ 113 NONAME
+	gst_rtp_buffer_set_timestamp @ 114 NONAME
+	gst_rtp_buffer_set_version @ 115 NONAME
+	gst_rtp_buffer_validate @ 116 NONAME
+	gst_rtp_buffer_validate_data @ 117 NONAME
+	gst_rtp_payload_info_for_name @ 118 NONAME
+	gst_rtp_payload_info_for_pt @ 119 NONAME
 
--- a/gst_plugins_base/bwins/libgsttagu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgsttagu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,19 +1,22 @@
 EXPORTS
 	gst_tag_demux_get_type @ 1 NONAME
-	gst_tag_freeform_string_to_utf8 @ 2 NONAME
-	gst_tag_from_id3_tag @ 3 NONAME
-	gst_tag_from_id3_user_tag @ 4 NONAME
-	gst_tag_from_vorbis_tag @ 5 NONAME
-	gst_tag_id3_genre_count @ 6 NONAME
-	gst_tag_id3_genre_get @ 7 NONAME
-	gst_tag_image_type_get_type @ 8 NONAME
-	gst_tag_list_from_vorbiscomment_buffer @ 9 NONAME
-	gst_tag_list_new_from_id3v1 @ 10 NONAME
-	gst_tag_list_to_vorbiscomment_buffer @ 11 NONAME
-	gst_tag_parse_extended_comment @ 12 NONAME
-	gst_tag_register_musicbrainz_tags @ 13 NONAME
-	gst_tag_to_id3_tag @ 14 NONAME
-	gst_tag_to_vorbis_comments @ 15 NONAME
-	gst_tag_to_vorbis_tag @ 16 NONAME
-	gst_vorbis_tag_add @ 17 NONAME
+	gst_tag_demux_result_get_type @ 2 NONAME
+	gst_tag_freeform_string_to_utf8 @ 3 NONAME
+	gst_tag_from_id3_tag @ 4 NONAME
+	gst_tag_from_id3_user_tag @ 5 NONAME
+	gst_tag_from_vorbis_tag @ 6 NONAME
+	gst_tag_id3_genre_count @ 7 NONAME
+	gst_tag_id3_genre_get @ 8 NONAME
+	gst_tag_image_data_to_image_buffer @ 9 NONAME
+	gst_tag_image_type_get_type @ 10 NONAME
+	gst_tag_list_add_id3_image @ 11 NONAME
+	gst_tag_list_from_vorbiscomment_buffer @ 12 NONAME
+	gst_tag_list_new_from_id3v1 @ 13 NONAME
+	gst_tag_list_to_vorbiscomment_buffer @ 14 NONAME
+	gst_tag_parse_extended_comment @ 15 NONAME
+	gst_tag_register_musicbrainz_tags @ 16 NONAME
+	gst_tag_to_id3_tag @ 17 NONAME
+	gst_tag_to_vorbis_comments @ 18 NONAME
+	gst_tag_to_vorbis_tag @ 19 NONAME
+	gst_vorbis_tag_add @ 20 NONAME
 
--- a/gst_plugins_base/bwins/libgsttcpu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgsttcpu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -15,8 +15,8 @@
 	gst_tcp_gdp_write_caps @ 14 NONAME
 	gst_tcp_host_to_ip @ 15 NONAME
 	gst_tcp_marshal_BOXED__INT @ 16 NONAME
-	gst_tcp_marshal_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64 @ 17 NONAME
-	gst_tcp_marshal_VOID__INT_BOXED @ 18 NONAME
+	gst_tcp_marshal_VOID__INT_BOXED @ 17 NONAME
+	gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64 @ 18 NONAME
 	gst_tcp_marshal_VOID__STRING_UINT @ 19 NONAME
 	gst_tcp_protocol_get_type @ 20 NONAME
 	gst_tcp_read_buffer @ 21 NONAME
--- a/gst_plugins_base/bwins/libgstvideoscaleu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstvideoscaleu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -2,49 +2,76 @@
 	_GST_PLUGIN_DESC @ 1 NONAME
 	gst_video_scale_get_type @ 2 NONAME
 	vs_4tap_init @ 3 NONAME
-	vs_image_scale_4tap_Y @ 4 NONAME
-	vs_image_scale_linear_RGB @ 5 NONAME
-	vs_image_scale_linear_RGB555 @ 6 NONAME
-	vs_image_scale_linear_RGB565 @ 7 NONAME
-	vs_image_scale_linear_RGBA @ 8 NONAME
-	vs_image_scale_linear_UYVY @ 9 NONAME
-	vs_image_scale_linear_Y @ 10 NONAME
-	vs_image_scale_linear_YUYV @ 11 NONAME
-	vs_image_scale_nearest_RGB @ 12 NONAME
-	vs_image_scale_nearest_RGB555 @ 13 NONAME
-	vs_image_scale_nearest_RGB565 @ 14 NONAME
-	vs_image_scale_nearest_UYVY @ 15 NONAME
-	vs_image_scale_nearest_Y @ 16 NONAME
-	vs_image_scale_nearest_YUYV @ 17 NONAME
-	vs_scanline_downsample_RGB @ 18 NONAME
-	vs_scanline_downsample_RGBA @ 19 NONAME
-	vs_scanline_downsample_UYVY @ 20 NONAME
-	vs_scanline_downsample_Y @ 21 NONAME
-	vs_scanline_downsample_YUYV @ 22 NONAME
-	vs_scanline_merge_4tap_Y @ 23 NONAME
-	vs_scanline_merge_linear_RGB @ 24 NONAME
-	vs_scanline_merge_linear_RGB555 @ 25 NONAME
-	vs_scanline_merge_linear_RGB565 @ 26 NONAME
-	vs_scanline_merge_linear_RGBA @ 27 NONAME
-	vs_scanline_merge_linear_UYVY @ 28 NONAME
-	vs_scanline_merge_linear_Y @ 29 NONAME
-	vs_scanline_merge_linear_YUYV @ 30 NONAME
-	vs_scanline_resample_4tap_Y @ 31 NONAME
-	vs_scanline_resample_linear_RGB @ 32 NONAME
-	vs_scanline_resample_linear_RGB555 @ 33 NONAME
-	vs_scanline_resample_linear_RGB565 @ 34 NONAME
-	vs_scanline_resample_linear_RGBA @ 35 NONAME
-	vs_scanline_resample_linear_UYVY @ 36 NONAME
-	vs_scanline_resample_linear_Y @ 37 NONAME
-	vs_scanline_resample_linear_YUYV @ 38 NONAME
-	vs_scanline_resample_nearest_RGB @ 39 NONAME
-	vs_scanline_resample_nearest_RGB555 @ 40 NONAME
-	vs_scanline_resample_nearest_RGB565 @ 41 NONAME
-	vs_scanline_resample_nearest_RGBA @ 42 NONAME
-	vs_scanline_resample_nearest_UYVY @ 43 NONAME
-	vs_scanline_resample_nearest_Y @ 44 NONAME
-	vs_scanline_resample_nearest_YUYV @ 45 NONAME
-	vs_image_scale_nearest_RGBA @ 46 NONAME
-	vs_scanline_downsample_RGB555 @ 47 NONAME
-	vs_scanline_downsample_RGB565 @ 48 NONAME
+	vs_image_scale_4tap_RGB @ 4 NONAME
+	vs_image_scale_4tap_RGB555 @ 5 NONAME
+	vs_image_scale_4tap_RGB565 @ 6 NONAME
+	vs_image_scale_4tap_RGBA @ 7 NONAME
+	vs_image_scale_4tap_UYVY @ 8 NONAME
+	vs_image_scale_4tap_Y @ 9 NONAME
+	vs_image_scale_4tap_YUYV @ 10 NONAME
+	vs_image_scale_linear_RGB @ 11 NONAME
+	vs_image_scale_linear_RGB555 @ 12 NONAME
+	vs_image_scale_linear_RGB565 @ 13 NONAME
+	vs_image_scale_linear_RGBA @ 14 NONAME
+	vs_image_scale_linear_UYVY @ 15 NONAME
+	vs_image_scale_linear_Y @ 16 NONAME
+	vs_image_scale_linear_YUYV @ 17 NONAME
+	vs_image_scale_nearest_RGB @ 18 NONAME
+	vs_image_scale_nearest_RGB555 @ 19 NONAME
+	vs_image_scale_nearest_RGB565 @ 20 NONAME
+	vs_image_scale_nearest_RGBA @ 21 NONAME
+	vs_image_scale_nearest_UYVY @ 22 NONAME
+	vs_image_scale_nearest_Y @ 23 NONAME
+	vs_image_scale_nearest_YUYV @ 24 NONAME
+	vs_scanline_downsample_RGB @ 25 NONAME
+	vs_scanline_downsample_RGB555 @ 26 NONAME
+	vs_scanline_downsample_RGB565 @ 27 NONAME
+	vs_scanline_downsample_RGBA @ 28 NONAME
+	vs_scanline_downsample_UYVY @ 29 NONAME
+	vs_scanline_downsample_Y @ 30 NONAME
+	vs_scanline_downsample_YUYV @ 31 NONAME
+	vs_scanline_merge_4tap_RGB @ 32 NONAME
+	vs_scanline_merge_4tap_RGB555 @ 33 NONAME
+	vs_scanline_merge_4tap_RGB565 @ 34 NONAME
+	vs_scanline_merge_4tap_RGBA @ 35 NONAME
+	vs_scanline_merge_4tap_UYVY @ 36 NONAME
+	vs_scanline_merge_4tap_Y @ 37 NONAME
+	vs_scanline_merge_4tap_YUYV @ 38 NONAME
+	vs_scanline_merge_linear_RGB @ 39 NONAME
+	vs_scanline_merge_linear_RGB555 @ 40 NONAME
+	vs_scanline_merge_linear_RGB565 @ 41 NONAME
+	vs_scanline_merge_linear_RGBA @ 42 NONAME
+	vs_scanline_merge_linear_UYVY @ 43 NONAME
+	vs_scanline_merge_linear_Y @ 44 NONAME
+	vs_scanline_merge_linear_YUYV @ 45 NONAME
+	vs_scanline_resample_4tap_RGB @ 46 NONAME
+	vs_scanline_resample_4tap_RGB555 @ 47 NONAME
+	vs_scanline_resample_4tap_RGB565 @ 48 NONAME
+	vs_scanline_resample_4tap_RGBA @ 49 NONAME
+	vs_scanline_resample_4tap_UYVY @ 50 NONAME
+	vs_scanline_resample_4tap_Y @ 51 NONAME
+	vs_scanline_resample_4tap_YUYV @ 52 NONAME
+	vs_scanline_resample_linear_RGB @ 53 NONAME
+	vs_scanline_resample_linear_RGB555 @ 54 NONAME
+	vs_scanline_resample_linear_RGB565 @ 55 NONAME
+	vs_scanline_resample_linear_RGBA @ 56 NONAME
+	vs_scanline_resample_linear_UYVY @ 57 NONAME
+	vs_scanline_resample_linear_Y @ 58 NONAME
+	vs_scanline_resample_linear_YUYV @ 59 NONAME
+	vs_scanline_resample_nearest_RGB @ 60 NONAME
+	vs_scanline_resample_nearest_RGB555 @ 61 NONAME
+	vs_scanline_resample_nearest_RGB565 @ 62 NONAME
+	vs_scanline_resample_nearest_RGBA @ 63 NONAME
+	vs_scanline_resample_nearest_UYVY @ 64 NONAME
+	vs_scanline_resample_nearest_Y @ 65 NONAME
+	vs_scanline_resample_nearest_YUYV @ 66 NONAME
+	vs_image_scale_4tap_Y16 @ 67 NONAME
+	vs_image_scale_linear_Y16 @ 68 NONAME
+	vs_image_scale_nearest_Y16 @ 69 NONAME
+	vs_scanline_downsample_Y16 @ 70 NONAME
+	vs_scanline_merge_4tap_Y16 @ 71 NONAME
+	vs_scanline_merge_linear_Y16 @ 72 NONAME
+	vs_scanline_resample_4tap_Y16 @ 73 NONAME
+	vs_scanline_resample_linear_Y16 @ 74 NONAME
+	vs_scanline_resample_nearest_Y16 @ 75 NONAME
 
--- a/gst_plugins_base/bwins/libgstvideou.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/bwins/libgstvideou.def	Fri Apr 16 15:15:52 2010 +0300
@@ -9,16 +9,19 @@
 	gst_video_format_get_pixel_stride @ 8 NONAME
 	gst_video_format_get_row_stride @ 9 NONAME
 	gst_video_format_get_size @ 10 NONAME
-	gst_video_format_has_alpha @ 11 NONAME
-	gst_video_format_is_rgb @ 12 NONAME
-	gst_video_format_is_yuv @ 13 NONAME
-	gst_video_format_new_caps @ 14 NONAME
-	gst_video_format_parse_caps @ 15 NONAME
-	gst_video_format_to_fourcc @ 16 NONAME
-	gst_video_frame_rate @ 17 NONAME
-	gst_video_get_size @ 18 NONAME
-	gst_video_parse_caps_framerate @ 19 NONAME
-	gst_video_parse_caps_pixel_aspect_ratio @ 20 NONAME
-	gst_video_sink_center_rect @ 21 NONAME
-	gst_video_sink_get_type @ 22 NONAME
+	gst_video_format_get_type @ 11 NONAME
+	gst_video_format_has_alpha @ 12 NONAME
+	gst_video_format_is_rgb @ 13 NONAME
+	gst_video_format_is_yuv @ 14 NONAME
+	gst_video_format_new_caps @ 15 NONAME
+	gst_video_format_new_caps_interlaced @ 16 NONAME
+	gst_video_format_parse_caps @ 17 NONAME
+	gst_video_format_parse_caps_interlaced @ 18 NONAME
+	gst_video_format_to_fourcc @ 19 NONAME
+	gst_video_frame_rate @ 20 NONAME
+	gst_video_get_size @ 21 NONAME
+	gst_video_parse_caps_framerate @ 22 NONAME
+	gst_video_parse_caps_pixel_aspect_ratio @ 23 NONAME
+	gst_video_sink_center_rect @ 24 NONAME
+	gst_video_sink_get_type @ 25 NONAME
 
--- a/gst_plugins_base/bwins/liboilu.def	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-EXPORTS
-	merge_linear_argb_ref @ 1 NONAME
-	oil_class_optimize @ 2 NONAME
-	oil_cpu_get_flags @ 3 NONAME
-	oil_impl_is_runnable @ 4 NONAME
-	oil_merge_linear_argb @ 5 NONAME
-	oil_merge_linear_u8 @ 6 NONAME
-	oil_resample_linear_argb @ 7 NONAME
-	oil_resample_linear_u8 @ 8 NONAME
-	oil_scalarmultiply_f32_ns @ 9 NONAME
-	oil_splat_u8 @ 10 NONAME
-	oil_splat_u8_ns @ 11 NONAME
-	resample_linear_argb_ref @ 12 NONAME
-	resample_linear_u8_ref @ 13 NONAME
-
--- a/gst_plugins_base/config.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/config.h	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,19 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* The implementation that should be used for integer audio resampling witll
+   be benchmarked at runtime */
+#define AUDIORESAMPLE_FORMAT_AUTO 1
+
+/* The float implementation should be used for integer audio resampling */
+/* #undef AUDIORESAMPLE_FORMAT_FLOAT */
+
+/* The int implementation should be used for integer audio resampling */
+/* #undef AUDIORESAMPLE_FORMAT_INT */
+
 /* defined if cdda headers are in a cdda/ directory */
 /* #undef CDPARANOIA_HEADERS_IN_DIR */
 
@@ -52,11 +65,19 @@
 #define GST_PACKAGE_ORIGIN "Unknown package origin"
 
 /* Define to enable ALSA (used by alsa). */
-#undef HAVE_ALSA 
+/* #undef HAVE_ALSA */
 
 /* Define to enable CDParanoia (used by cdparanoia). */
 /* #undef HAVE_CDPARANOIA */
 
+/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
 /* Define if the host CPU is an Alpha */
 /* #undef HAVE_CPU_ALPHA */
 
@@ -139,7 +160,7 @@
 #define HAVE_GMTIME_R 1
 
 /* Define to enable GNOME VFS (used by gnomevfs). */
-#undef HAVE_GNOME_VFS 
+/* #undef HAVE_GNOME_VFS */
 
 /* Define to enable Video 4 Linux (used by video4linux). */
 #undef HAVE_GST_V4L 
@@ -153,9 +174,15 @@
 /* Define to 1 if you have the `asound' library (-lasound). */
 /* #undef HAVE_LIBASOUND */
 
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
 /* Define to 1 if you have the `resolv' library (-lresolv). */
 /* #undef HAVE_LIBRESOLV */
 
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
 /* Define to enable libvisual visualization library (used by libvisual). */
 /* #undef HAVE_LIBVISUAL */
 
@@ -175,12 +202,10 @@
 #define HAVE_MEMORY_H 1
 
 /* Define to enable Xiph Ogg library (used by ogg). */
-#undef HAVE_OGG 
+/* #undef HAVE_OGG */
 
 /* Define to enable Pango font rendering (used by pango). */
-#ifndef __SYMBIAN32__
-#define HAVE_PANGO
-#endif 
+/* #undef HAVE_PANGO */
 
 /* defined if the compiler implements __PRETTY_FUNCTION__ */
 #define HAVE_PRETTY_FUNCTION 1
@@ -227,15 +252,13 @@
 #define HAVE_UNISTD_H 1
 
 /* Define if valgrind should be used */
-#ifndef __SYMBIAN32__
-#define HAVE_VALGRIND 1
-#endif
+/* #undef HAVE_VALGRIND */
 
 /* Define to enable Xiph Vorbis audio codec (used by vorbis). */
-#define HAVE_VORBIS 
+/* #undef HAVE_VORBIS */
 
 /* defined if vorbis_synthesis_restart is present */
-#define HAVE_VORBIS_SYNTHESIS_RESTART 1
+/* #undef HAVE_VORBIS_SYNTHESIS_RESTART */
 
 /* Define to 1 if you have the <winsock2.h> header file. */
 /* #undef HAVE_WINSOCK2_H */
@@ -247,13 +270,20 @@
 #define HAVE_XSHM 
 
 /* Define to enable X11 XVideo extensions (used by xvimagesink). */
-#define HAVE_XVIDEO 
+/* #undef HAVE_XVIDEO */
 
 /* the host CPU */
 #define HOST_CPU "i686"
 
+/* directory in which the detected libvisual's plugins are located */
+/* #undef LIBVISUAL_PLUGINSBASEDIR */
+
 /* gettext locale dir */
-#define LOCALEDIR "/home/rakhi/openlibs//share/locale"
+#define LOCALEDIR "/home/puneet/puneet_libs/share/locale"
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
 
 /* Define if you have no native hstrerror() function. */
 /* #undef NO_HSTRERROR */
@@ -271,13 +301,13 @@
 #define PACKAGE_NAME "GStreamer Base Plug-ins"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer Base Plug-ins 0.10.19"
+#define PACKAGE_STRING "GStreamer Base Plug-ins 0.10.23"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "gst-plugins-base"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.19"
+#define PACKAGE_VERSION "0.10.24"
 
 /* directory where plugins are located */
 #ifdef __SYMBIAN32__
@@ -314,11 +344,19 @@
 #define STDC_HEADERS 1
 
 /* Version number of package */
-#define VERSION "0.10.19"
+#define VERSION "0.10.24"
 
-/* Define to 1 if your processor stores words with the most significant byte
-   first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
 
 /* Define to 1 if the X Window System is missing or not being used. */
 /* #undef X_DISPLAY_MISSING */
--- a/gst_plugins_base/eabi/libgstappu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstappu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -9,25 +9,27 @@
 	gst_app_sink_get_type @ 8 NONAME
 	gst_app_sink_is_eos @ 9 NONAME
 	gst_app_sink_pull_buffer @ 10 NONAME
-	gst_app_sink_pull_preroll @ 11 NONAME
-	gst_app_sink_set_caps @ 12 NONAME
-	gst_app_sink_set_drop @ 13 NONAME
-	gst_app_sink_set_emit_signals @ 14 NONAME
-	gst_app_sink_set_max_buffers @ 15 NONAME
-	gst_app_src_end_of_stream @ 16 NONAME
-	gst_app_src_get_caps @ 17 NONAME
-	gst_app_src_get_emit_signals @ 18 NONAME
-	gst_app_src_get_latency @ 19 NONAME
-	gst_app_src_get_max_bytes @ 20 NONAME
-	gst_app_src_get_size @ 21 NONAME
-	gst_app_src_get_stream_type @ 22 NONAME
-	gst_app_src_get_type @ 23 NONAME
-	gst_app_src_push_buffer @ 24 NONAME
-	gst_app_src_set_callbacks @ 25 NONAME
-	gst_app_src_set_caps @ 26 NONAME
-	gst_app_src_set_emit_signals @ 27 NONAME
-	gst_app_src_set_latency @ 28 NONAME
-	gst_app_src_set_max_bytes @ 29 NONAME
-	gst_app_src_set_size @ 30 NONAME
-	gst_app_src_set_stream_type @ 31 NONAME
+	gst_app_sink_pull_buffer_list @ 11 NONAME
+	gst_app_sink_pull_preroll @ 12 NONAME
+	gst_app_sink_set_callbacks @ 13 NONAME
+	gst_app_sink_set_caps @ 14 NONAME
+	gst_app_sink_set_drop @ 15 NONAME
+	gst_app_sink_set_emit_signals @ 16 NONAME
+	gst_app_sink_set_max_buffers @ 17 NONAME
+	gst_app_src_end_of_stream @ 18 NONAME
+	gst_app_src_get_caps @ 19 NONAME
+	gst_app_src_get_emit_signals @ 20 NONAME
+	gst_app_src_get_latency @ 21 NONAME
+	gst_app_src_get_max_bytes @ 22 NONAME
+	gst_app_src_get_size @ 23 NONAME
+	gst_app_src_get_stream_type @ 24 NONAME
+	gst_app_src_get_type @ 25 NONAME
+	gst_app_src_push_buffer @ 26 NONAME
+	gst_app_src_set_callbacks @ 27 NONAME
+	gst_app_src_set_caps @ 28 NONAME
+	gst_app_src_set_emit_signals @ 29 NONAME
+	gst_app_src_set_latency @ 30 NONAME
+	gst_app_src_set_max_bytes @ 31 NONAME
+	gst_app_src_set_size @ 32 NONAME
+	gst_app_src_set_stream_type @ 33 NONAME
 
--- a/gst_plugins_base/eabi/libgstaudioresampleu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstaudioresampleu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,52 +1,4 @@
 EXPORTS
 	_GST_PLUGIN_DESC @ 1 NONAME
-	audioresample_buffer_new @ 2 NONAME
-	audioresample_buffer_new_and_alloc @ 3 NONAME
-	audioresample_buffer_new_subbuffer @ 4 NONAME
-	audioresample_buffer_new_with_data @ 5 NONAME
-	audioresample_buffer_queue_flush @ 6 NONAME
-	audioresample_buffer_queue_free @ 7 NONAME
-	audioresample_buffer_queue_get_depth @ 8 NONAME
-	audioresample_buffer_queue_get_offset @ 9 NONAME
-	audioresample_buffer_queue_new @ 10 NONAME
-	audioresample_buffer_queue_peek @ 11 NONAME
-	audioresample_buffer_queue_pull @ 12 NONAME
-	audioresample_buffer_queue_push @ 13 NONAME
-	audioresample_buffer_ref @ 14 NONAME
-	audioresample_buffer_unref @ 15 NONAME
-	functable_calculate @ 16 NONAME
-	functable_calculate_multiply @ 17 NONAME
-	functable_evaluate @ 18 NONAME
-	functable_fir @ 19 NONAME
-	functable_fir2 @ 20 NONAME
-	functable_free @ 21 NONAME
-	functable_func_boxcar @ 22 NONAME
-	functable_func_hanning @ 23 NONAME
-	functable_func_sinc @ 24 NONAME
-	functable_new @ 25 NONAME
-	functable_set_length @ 26 NONAME
-	functable_set_multiplier @ 27 NONAME
-	functable_set_offset @ 28 NONAME
-	gst_audioresample_get_type @ 29 NONAME
-	resample_add_input_data @ 30 NONAME
-	resample_format_size @ 31 NONAME
-	resample_free @ 32 NONAME
-	resample_get_input_size_for_output @ 33 NONAME
-	resample_get_output_data @ 34 NONAME
-	resample_get_output_size @ 35 NONAME
-	resample_get_output_size_for_input @ 36 NONAME
-	resample_init @ 37 NONAME
-	resample_input_eos @ 38 NONAME
-	resample_input_flush @ 39 NONAME
-	resample_input_pushthrough @ 40 NONAME
-	resample_new @ 41 NONAME
-	resample_scale_chunk @ 42 NONAME
-	resample_scale_functable @ 43 NONAME
-	resample_scale_ref @ 44 NONAME
-	resample_set_filter_length @ 45 NONAME
-	resample_set_format @ 46 NONAME
-	resample_set_input_rate @ 47 NONAME
-	resample_set_method @ 48 NONAME
-	resample_set_n_channels @ 49 NONAME
-	resample_set_output_rate @ 50 NONAME
+	gst_audio_resample_get_type @ 2 NONAME
 
--- a/gst_plugins_base/eabi/libgstaudiou.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstaudiou.def	Fri Apr 16 15:15:52 2010 +0300
@@ -54,4 +54,19 @@
 	gst_ring_buffer_set_sample @ 53 NONAME
 	gst_ring_buffer_start @ 54 NONAME
 	gst_ring_buffer_stop @ 55 NONAME
+	gst_audio_check_channel_positions @ 56 NONAME
+	gst_audio_clock_adjust @ 57 NONAME
+	gst_audio_clock_get_time @ 58 NONAME
+	gst_audio_clock_reset @ 59 NONAME
+	gst_base_audio_sink_slave_method_get_type @ 60 NONAME
+	gst_base_audio_src_get_slave_method @ 61 NONAME
+	gst_base_audio_src_set_slave_method @ 62 NONAME
+	gst_base_audio_src_slave_method_get_type @ 63 NONAME
+	gst_buffer_format_get_type @ 64 NONAME
+	gst_buffer_format_type_get_type @ 65 NONAME
+	gst_ring_buffer_activate @ 66 NONAME
+	gst_ring_buffer_convert @ 67 NONAME
+	gst_ring_buffer_is_active @ 68 NONAME
+	gst_ring_buffer_seg_state_get_type @ 69 NONAME
+	gst_ring_buffer_state_get_type @ 70 NONAME
 
--- a/gst_plugins_base/eabi/libgstcddau.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstcddau.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,5 @@
 EXPORTS
-	__gst_cdda_rfc822_binary @ 1 NONAME
-	gst_cdda_base_src_add_track @ 2 NONAME
-	gst_cdda_base_src_get_type @ 3 NONAME
+	gst_cdda_base_src_add_track @ 1 NONAME
+	gst_cdda_base_src_get_type @ 2 NONAME
+	gst_cdda_base_src_mode_get_type @ 3 NONAME
 
--- a/gst_plugins_base/eabi/libgstdecodebin2u.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstdecodebin2u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -6,13 +6,16 @@
 	gst_factory_list_get_elements @ 5 NONAME
 	gst_factory_list_is_type @ 6 NONAME
 	gst_play_flags_get_type @ 7 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT @ 8 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 9 NONAME
-	gst_play_marshal_BOXED__INT @ 10 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT @ 11 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED @ 12 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 13 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT @ 14 NONAME
-	gst_play_marshal_OBJECT__BOXED @ 15 NONAME
-	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 16 NONAME
+	gst_decode_bin_plugin_init @ 8 NONAME
+	gst_decode_pad_get_type @ 9 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_BOXED @ 10 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 11 NONAME
+	gst_play_marshal_BOXED__INT @ 12 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED @ 13 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED_BOXED @ 14 NONAME
+	gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT @ 15 NONAME
+	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 16 NONAME
+	gst_play_marshal_OBJECT__BOXED @ 17 NONAME
+	gst_play_marshal_OBJECT__INT @ 18 NONAME
+	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 19 NONAME
 
--- a/gst_plugins_base/eabi/libgstdecodebinu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstdecodebinu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,12 +1,13 @@
 EXPORTS
 	_GST_PLUGIN_DESC @ 1 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT @ 2 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_BOXED @ 2 NONAME
 	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 3 NONAME
 	gst_play_marshal_BOXED__INT @ 4 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT @ 5 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED @ 6 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 7 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT @ 8 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED @ 5 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED_BOXED @ 6 NONAME
+	gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT @ 7 NONAME
+	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 8 NONAME
 	gst_play_marshal_OBJECT__BOXED @ 9 NONAME
-	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 10 NONAME
+	gst_play_marshal_OBJECT__INT @ 10 NONAME
+	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 11 NONAME
 
--- a/gst_plugins_base/eabi/libgstgdpu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstgdpu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -4,4 +4,3 @@
 	gst_gdp_depay_plugin_init @ 3 NONAME
 	gst_gdp_pay_get_type @ 4 NONAME
 	gst_gdp_pay_plugin_init @ 5 NONAME
-
--- a/gst_plugins_base/eabi/libgstinterfacesu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstinterfacesu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -88,4 +88,31 @@
 	gst_x_overlay_handle_events @ 87 NONAME
 	gst_x_overlay_prepare_xwindow_id @ 88 NONAME
 	gst_x_overlay_set_xwindow_id @ 89 NONAME
+	gst_navigation_command_get_type @ 90 NONAME
+	gst_navigation_event_get_type @ 91 NONAME
+	gst_navigation_event_parse_command @ 92 NONAME
+	gst_navigation_event_parse_key_event @ 93 NONAME
+	gst_navigation_event_parse_mouse_button_event @ 94 NONAME
+	gst_navigation_event_parse_mouse_move_event @ 95 NONAME
+	gst_navigation_event_type_get_type @ 96 NONAME
+	gst_navigation_message_get_type @ 97 NONAME
+	gst_navigation_message_new_angles_changed @ 98 NONAME
+	gst_navigation_message_new_commands_changed @ 99 NONAME
+	gst_navigation_message_new_mouse_over @ 100 NONAME
+	gst_navigation_message_parse_angles_changed @ 101 NONAME
+	gst_navigation_message_parse_mouse_over @ 102 NONAME
+	gst_navigation_message_type_get_type @ 103 NONAME
+	gst_navigation_query_get_type @ 104 NONAME
+	gst_navigation_query_new_angles @ 105 NONAME
+	gst_navigation_query_new_commands @ 106 NONAME
+	gst_navigation_query_parse_angles @ 107 NONAME
+	gst_navigation_query_parse_commands_length @ 108 NONAME
+	gst_navigation_query_parse_commands_nth @ 109 NONAME
+	gst_navigation_query_set_angles @ 110 NONAME
+	gst_navigation_query_set_commands @ 111 NONAME
+	gst_navigation_query_set_commandsv @ 112 NONAME
+	gst_navigation_query_type_get_type @ 113 NONAME
+	gst_navigation_send_command @ 114 NONAME
+	gst_color_balance_get_balance_type @ 115 NONAME
+	gst_mixer_get_mixer_type @ 116 NONAME
 
--- a/gst_plugins_base/eabi/libgstnetbufferu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstnetbufferu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -7,4 +7,7 @@
 	gst_netaddress_set_ip6_address @ 6 NONAME
 	gst_netbuffer_get_type @ 7 NONAME
 	gst_netbuffer_new @ 8 NONAME
+	gst_netaddress_get_address_bytes @ 9 NONAME
+	gst_netaddress_set_address_bytes @ 10 NONAME
+	gst_netaddress_to_string @ 11 NONAME
 
--- a/gst_plugins_base/eabi/libgstplaybinu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstplaybinu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -10,32 +10,36 @@
 	gst_play_bin_plugin_init @ 9 NONAME
 	gst_play_flags_get_type @ 10 NONAME
 	gst_play_frame_conv_convert @ 11 NONAME
-	gst_play_marshal_BOOLEAN__OBJECT_OBJECT @ 12 NONAME
+	gst_play_marshal_BOOLEAN__OBJECT_BOXED @ 12 NONAME
 	gst_play_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT @ 13 NONAME
 	gst_play_marshal_BOXED__INT @ 14 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT @ 15 NONAME
-	gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED @ 16 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 17 NONAME
-	gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT @ 18 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED @ 15 NONAME
+	gst_play_marshal_BOXED__OBJECT_BOXED_BOXED @ 16 NONAME
+	gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT @ 17 NONAME
+	gst_play_marshal_ENUM__OBJECT_OBJECT_BOXED @ 18 NONAME
 	gst_play_marshal_OBJECT__BOXED @ 19 NONAME
-	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 20 NONAME
-	gst_play_sink_get_flags @ 21 NONAME
-	gst_play_sink_get_last_frame @ 22 NONAME
-	gst_play_sink_get_mute @ 23 NONAME
-	gst_play_sink_get_type @ 24 NONAME
-	gst_play_sink_get_volume @ 25 NONAME
-	gst_play_sink_reconfigure @ 26 NONAME
-	gst_play_sink_release_pad @ 27 NONAME
-	gst_play_sink_request_pad @ 28 NONAME
-	gst_play_sink_set_audio_sink @ 29 NONAME
-	gst_play_sink_set_flags @ 30 NONAME
-	gst_play_sink_set_mute @ 31 NONAME
-	gst_play_sink_set_video_sink @ 32 NONAME
-	gst_play_sink_set_vis_plugin @ 33 NONAME
-	gst_play_sink_set_volume @ 34 NONAME
-	gst_stream_info_get_type @ 35 NONAME
-	gst_stream_info_is_mute @ 36 NONAME
-	gst_stream_info_new @ 37 NONAME
-	gst_stream_info_set_mute @ 38 NONAME
-	gst_stream_selector_get_type @ 39 NONAME
+	gst_play_marshal_OBJECT__INT @ 20 NONAME
+	gst_play_marshal_VOID__OBJECT_BOOLEAN @ 21 NONAME
+	gst_play_sink_get_flags @ 22 NONAME
+	gst_play_sink_get_font_desc @ 23 NONAME
+	gst_play_sink_get_last_frame @ 24 NONAME
+	gst_play_sink_get_mute @ 25 NONAME
+	gst_play_sink_get_sink @ 26 NONAME
+	gst_play_sink_get_type @ 27 NONAME
+	gst_play_sink_get_vis_plugin @ 28 NONAME
+	gst_play_sink_get_volume @ 29 NONAME
+	gst_play_sink_reconfigure @ 30 NONAME
+	gst_play_sink_release_pad @ 31 NONAME
+	gst_play_sink_request_pad @ 32 NONAME
+	gst_play_sink_set_flags @ 33 NONAME
+	gst_play_sink_set_font_desc @ 34 NONAME
+	gst_play_sink_set_mute @ 35 NONAME
+	gst_play_sink_set_sink @ 36 NONAME
+	gst_play_sink_set_vis_plugin @ 37 NONAME
+	gst_play_sink_set_volume @ 38 NONAME
+	gst_stream_info_get_type @ 39 NONAME
+	gst_stream_info_is_mute @ 40 NONAME
+	gst_stream_info_new @ 41 NONAME
+	gst_stream_info_set_mute @ 42 NONAME
+	gst_stream_selector_get_type @ 43 NONAME
 
--- a/gst_plugins_base/eabi/libgstrtpu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstrtpu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -101,4 +101,21 @@
 	gst_rtp_buffer_validate_data @ 100 NONAME
 	gst_rtp_payload_info_for_name @ 101 NONAME
 	gst_rtp_payload_info_for_pt @ 102 NONAME
+	gst_rtcp_packet_fb_get_media_ssrc @ 103 NONAME
+	gst_rtcp_packet_fb_get_sender_ssrc @ 104 NONAME
+	gst_rtcp_packet_fb_get_type @ 105 NONAME
+	gst_rtcp_packet_fb_set_media_ssrc @ 106 NONAME
+	gst_rtcp_packet_fb_set_sender_ssrc @ 107 NONAME
+	gst_rtcp_packet_fb_set_type @ 108 NONAME
+	gst_basertppayload_push_list @ 109 NONAME
+	gst_rtp_buffer_list_get_payload_len @ 110 NONAME
+	gst_rtp_buffer_list_get_payload_type @ 111 NONAME
+	gst_rtp_buffer_list_get_seq @ 112 NONAME
+	gst_rtp_buffer_list_get_ssrc @ 113 NONAME
+	gst_rtp_buffer_list_get_timestamp @ 114 NONAME
+	gst_rtp_buffer_list_set_payload_type @ 115 NONAME
+	gst_rtp_buffer_list_set_seq @ 116 NONAME
+	gst_rtp_buffer_list_set_timestamp @ 117 NONAME
+	gst_rtp_buffer_list_validate @ 118 NONAME
+	gst_rtp_buffer_list_set_ssrc @ 119 NONAME
 
--- a/gst_plugins_base/eabi/libgsttagu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgsttagu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -16,4 +16,7 @@
 	gst_tag_to_vorbis_comments @ 15 NONAME
 	gst_tag_to_vorbis_tag @ 16 NONAME
 	gst_vorbis_tag_add @ 17 NONAME
+	gst_tag_demux_result_get_type @ 18 NONAME
+	gst_tag_image_data_to_image_buffer @ 19 NONAME
+	gst_tag_list_add_id3_image @ 20 NONAME
 
--- a/gst_plugins_base/eabi/libgsttcpu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgsttcpu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -15,8 +15,8 @@
 	gst_tcp_gdp_write_caps @ 14 NONAME
 	gst_tcp_host_to_ip @ 15 NONAME
 	gst_tcp_marshal_BOXED__INT @ 16 NONAME
-	gst_tcp_marshal_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64 @ 17 NONAME
-	gst_tcp_marshal_VOID__INT_BOXED @ 18 NONAME
+	gst_tcp_marshal_VOID__INT_BOXED @ 17 NONAME
+	gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64 @ 18 NONAME
 	gst_tcp_marshal_VOID__STRING_UINT @ 19 NONAME
 	gst_tcp_protocol_get_type @ 20 NONAME
 	gst_tcp_read_buffer @ 21 NONAME
--- a/gst_plugins_base/eabi/libgstvideoscaleu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstvideoscaleu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -47,4 +47,31 @@
 	vs_scanline_resample_nearest_UYVY @ 46 NONAME
 	vs_scanline_resample_nearest_Y @ 47 NONAME
 	vs_scanline_resample_nearest_YUYV @ 48 NONAME
+	vs_image_scale_4tap_RGB @ 49 NONAME
+	vs_image_scale_4tap_RGB555 @ 50 NONAME
+	vs_image_scale_4tap_RGB565 @ 51 NONAME
+	vs_image_scale_4tap_RGBA @ 52 NONAME
+	vs_image_scale_4tap_UYVY @ 53 NONAME
+	vs_image_scale_4tap_YUYV @ 54 NONAME
+	vs_scanline_merge_4tap_RGB @ 55 NONAME
+	vs_scanline_merge_4tap_RGB555 @ 56 NONAME
+	vs_scanline_merge_4tap_RGB565 @ 57 NONAME
+	vs_scanline_merge_4tap_RGBA @ 58 NONAME
+	vs_scanline_merge_4tap_UYVY @ 59 NONAME
+	vs_scanline_merge_4tap_YUYV @ 60 NONAME
+	vs_scanline_resample_4tap_RGB @ 61 NONAME
+	vs_scanline_resample_4tap_RGB555 @ 62 NONAME
+	vs_scanline_resample_4tap_RGB565 @ 63 NONAME
+	vs_scanline_resample_4tap_RGBA @ 64 NONAME
+	vs_scanline_resample_4tap_UYVY @ 65 NONAME
+	vs_scanline_resample_4tap_YUYV @ 66 NONAME
+	vs_image_scale_4tap_Y16 @ 67 NONAME
+	vs_image_scale_linear_Y16 @ 68 NONAME
+	vs_image_scale_nearest_Y16 @ 69 NONAME
+	vs_scanline_downsample_Y16 @ 70 NONAME
+	vs_scanline_merge_4tap_Y16 @ 71 NONAME
+	vs_scanline_merge_linear_Y16 @ 72 NONAME
+	vs_scanline_resample_4tap_Y16 @ 73 NONAME
+	vs_scanline_resample_linear_Y16 @ 74 NONAME
+	vs_scanline_resample_nearest_Y16 @ 75 NONAME
 
--- a/gst_plugins_base/eabi/libgstvideotestsrcu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstvideotestsrcu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,4 +1,3 @@
 EXPORTS
 	_GST_PLUGIN_DESC @ 1 NONAME
-	gst_video_test_src_get_type @ 2 NONAME
-
+	gst_video_test_src_get_type @ 2 NONAME
\ No newline at end of file
--- a/gst_plugins_base/eabi/libgstvideou.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/eabi/libgstvideou.def	Fri Apr 16 15:15:52 2010 +0300
@@ -21,4 +21,7 @@
 	gst_video_parse_caps_pixel_aspect_ratio @ 20 NONAME
 	gst_video_sink_center_rect @ 21 NONAME
 	gst_video_sink_get_type @ 22 NONAME
+	gst_video_format_get_type @ 23 NONAME
+	gst_video_format_new_caps_interlaced @ 24 NONAME
+	gst_video_format_parse_caps_interlaced @ 25 NONAME
 
--- a/gst_plugins_base/eabi/liboilu.def	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-EXPORTS
-	oil_class_optimize @ 1 NONAME
-	oil_cpu_get_flags @ 2 NONAME
-	oil_impl_is_runnable @ 3 NONAME
-	oil_merge_linear_argb @ 4 NONAME
-	oil_merge_linear_u8 @ 5 NONAME
-	oil_resample_linear_argb @ 6 NONAME
-	oil_resample_linear_u8 @ 7 NONAME
-	oil_scalarmultiply_f32_ns @ 8 NONAME
-	oil_splat_u8 @ 9 NONAME
-	oil_splat_u8_ns @ 10 NONAME
-
--- a/gst_plugins_base/ext/alsa/gstalsa.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,556 +0,0 @@
-/* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "gstalsa.h"
-
-#include <gst/audio/multichannel.h>
-
-static GstCaps *
-gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
-    GstCaps * in_caps)
-{
-  GstCaps *caps;
-  guint min, max;
-  gint err, dir, min_rate, max_rate, i;
-
-  GST_LOG_OBJECT (obj, "probing sample rates ...");
-
-  if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
-    goto min_rate_err;
-
-  if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
-    goto max_rate_err;
-
-  min_rate = min;
-  max_rate = max;
-
-  if (min_rate < 4000)
-    min_rate = 4000;            /* random 'sensible minimum' */
-
-  if (max_rate <= 0)
-    max_rate = G_MAXINT;        /* or maybe just use 192400 or so? */
-  else if (max_rate > 0 && max_rate < 4000)
-    max_rate = MAX (4000, min_rate);
-
-  GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
-  GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
-
-  caps = gst_caps_make_writable (in_caps);
-
-  for (i = 0; i < gst_caps_get_size (caps); ++i) {
-    GstStructure *s;
-
-    s = gst_caps_get_structure (caps, i);
-    if (min_rate == max_rate) {
-      gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
-    } else {
-      gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
-          min_rate, max_rate, NULL);
-    }
-  }
-
-  return caps;
-
-  /* ERRORS */
-min_rate_err:
-  {
-    GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
-        snd_strerror (err));
-    gst_caps_unref (in_caps);
-    return NULL;
-  }
-max_rate_err:
-  {
-    GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
-        snd_strerror (err));
-    gst_caps_unref (in_caps);
-    return NULL;
-  }
-}
-
-static const struct
-{
-  const int width;
-  const int depth;
-  const int sformat;
-  const int uformat;
-} pcmformats[] = {
-  {
-  8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, {
-  16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, {
-  32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, {
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)   /* no endian-unspecific enum available */
-  24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, {
-#else
-  24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, {
-#endif
-  32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32}
-};
-
-static GstCaps *
-gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
-    GstCaps * in_caps)
-{
-  snd_pcm_format_mask_t *mask;
-  GstStructure *s;
-  GstCaps *caps;
-  gint i;
-
-  snd_pcm_format_mask_malloc (&mask);
-  snd_pcm_hw_params_get_format_mask (hw_params, mask);
-
-  caps = gst_caps_new_empty ();
-
-  for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
-    GstStructure *scopy;
-    gint w, width = 0, depth = 0;
-
-    s = gst_caps_get_structure (in_caps, i);
-    if (!gst_structure_has_name (s, "audio/x-raw-int")) {
-      GST_WARNING_OBJECT (obj, "skipping non-int format");
-      continue;
-    }
-    if (!gst_structure_get_int (s, "width", &width) ||
-        !gst_structure_get_int (s, "depth", &depth))
-      continue;
-    if (width == 0 || (width % 8) != 0)
-      continue;                 /* Only full byte widths are valid */
-    for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
-      if (pcmformats[w].width == width && pcmformats[w].depth == depth)
-        break;
-    if (w == G_N_ELEMENTS (pcmformats))
-      continue;                 /* Unknown format */
-
-    if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
-        snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
-      /* template contains { true, false } or just one, leave it as it is */
-      scopy = gst_structure_copy (s);
-    } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
-      scopy = gst_structure_copy (s);
-      gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
-    } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
-      scopy = gst_structure_copy (s);
-      gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
-    } else {
-      scopy = NULL;
-    }
-    if (scopy) {
-      if (width > 8) {
-        /* TODO: proper endianness detection, for now it's CPU endianness only */
-        gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
-      }
-      gst_caps_append_structure (caps, scopy);
-    }
-  }
-
-  snd_pcm_format_mask_free (mask);
-  gst_caps_unref (in_caps);
-  return caps;
-}
-
-/* we don't have channel mappings for more than this many channels */
-#define GST_ALSA_MAX_CHANNELS 8
-
-static GstStructure *
-get_channel_free_structure (const GstStructure * in_structure)
-{
-  GstStructure *s = gst_structure_copy (in_structure);
-
-  gst_structure_remove_field (s, "channels");
-  return s;
-}
-
-static void
-caps_add_channel_configuration (GstCaps * caps,
-    const GstStructure * in_structure, gint min_chans, gint max_chans)
-{
-  GstAudioChannelPosition pos[8] = {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-    GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-    GST_AUDIO_CHANNEL_POSITION_LFE,
-    GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
-  };
-  GstStructure *s = NULL;
-  gint c;
-
-  if (min_chans == max_chans && max_chans <= 2) {
-    s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
-    gst_caps_append_structure (caps, s);
-    return;
-  }
-
-  g_assert (min_chans >= 1);
-
-  /* mono and stereo don't need channel configurations */
-  if (min_chans == 2) {
-    s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
-    gst_caps_append_structure (caps, s);
-  } else if (min_chans == 1 && max_chans >= 2) {
-    s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
-    gst_caps_append_structure (caps, s);
-  }
-
-  /* don't know whether to use 2.1 or 3.0 here - but I suspect
-   * alsa might work around that/fix it somehow. Can we tell alsa
-   * what our channel layout is like? */
-  if (max_chans >= 3 && min_chans <= 3) {
-    GstAudioChannelPosition pos_21[3] = {
-      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-      GST_AUDIO_CHANNEL_POSITION_LFE
-    };
-
-    s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
-    gst_audio_set_channel_positions (s, pos_21);
-    gst_caps_append_structure (caps, s);
-  }
-
-  /* everything else (4, 6, 8 channels) needs a channel layout */
-  for (c = MAX (4, min_chans); c <= 8; c += 2) {
-    if (max_chans >= c) {
-      s = get_channel_free_structure (in_structure);
-      gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
-      gst_audio_set_channel_positions (s, pos);
-      gst_caps_append_structure (caps, s);
-    }
-  }
-
-  for (c = MAX (9, min_chans); c <= max_chans; ++c) {
-    GstAudioChannelPosition *ch_layout;
-    guint i;
-
-    ch_layout = g_new (GstAudioChannelPosition, c);
-    for (i = 0; i < c; ++i) {
-      ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
-    }
-    s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
-    gst_audio_set_channel_positions (s, ch_layout);
-    gst_caps_append_structure (caps, s);
-    g_free (ch_layout);
-  }
-}
-
-static GstCaps *
-gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
-    GstCaps * in_caps)
-{
-  GstCaps *caps;
-  guint min, max;
-  gint min_chans, max_chans;
-  gint err, i;
-
-  GST_LOG_OBJECT (obj, "probing channels ...");
-
-  if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
-    goto min_chan_error;
-
-  if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
-    goto max_chan_error;
-
-  /* note: the above functions may return (guint) -1 */
-  min_chans = min;
-  max_chans = max;
-
-  if (min_chans < 0) {
-    min_chans = 1;
-    max_chans = GST_ALSA_MAX_CHANNELS;
-  } else if (max_chans < 0) {
-    max_chans = GST_ALSA_MAX_CHANNELS;
-  }
-
-  if (min_chans > max_chans) {
-    gint temp;
-
-    GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
-        "please fix your soundcard drivers", min, max);
-    temp = min_chans;
-    min_chans = max_chans;
-    max_chans = temp;
-  }
-
-  /* pro cards seem to return large numbers for min_channels */
-  if (min_chans > GST_ALSA_MAX_CHANNELS) {
-    GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
-    if (max_chans < min_chans) {
-      max_chans = min_chans;
-    } else {
-      /* only support [max_chans; max_chans] for these cards for now
-       * to avoid inflating the source caps with loads of structures ... */
-      min_chans = max_chans;
-    }
-  } else {
-    min_chans = MAX (min_chans, 1);
-    max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
-  }
-
-  GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
-  GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
-
-  caps = gst_caps_new_empty ();
-
-  for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
-    GstStructure *s;
-    GType field_type;
-    gint c_min = min_chans;
-    gint c_max = max_chans;
-
-    s = gst_caps_get_structure (in_caps, i);
-    /* the template caps might limit the number of channels (like alsasrc),
-     * in which case we don't want to return a superset, so hack around this
-     * for the two common cases where the channels are either a fixed number
-     * or a min/max range). Example: alsasrc template has channels = [1,2] and 
-     * the detection will claim to support 8 channels for device 'plughw:0' */
-    field_type = gst_structure_get_field_type (s, "channels");
-    if (field_type == G_TYPE_INT) {
-      gst_structure_get_int (s, "channels", &c_min);
-      gst_structure_get_int (s, "channels", &c_max);
-    } else if (field_type == GST_TYPE_INT_RANGE) {
-      const GValue *val;
-
-      val = gst_structure_get_value (s, "channels");
-      c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
-      c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
-    } else {
-      c_min = min_chans;
-      c_max = max_chans;
-    }
-
-    caps_add_channel_configuration (caps, s, c_min, c_max);
-  }
-
-  gst_caps_unref (in_caps);
-
-  return caps;
-
-  /* ERRORS */
-min_chan_error:
-  {
-    GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
-        snd_strerror (err));
-    return NULL;
-  }
-max_chan_error:
-  {
-    GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
-        snd_strerror (err));
-    return NULL;
-  }
-}
-
-snd_pcm_t *
-gst_alsa_open_iec958_pcm (GstObject * obj)
-{
-  char *iec958_pcm_name = NULL;
-  snd_pcm_t *pcm = NULL;
-  int res;
-  char devstr[256];             /* Storage for local 'default' device string */
-
-  /*
-   * Try and open our default iec958 device. Fall back to searching on card x
-   * if this fails, which should only happen on older alsa setups
-   */
-
-  /* The string will be one of these:
-   * SPDIF_CON: Non-audio flag not set:
-   *    spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
-   * SPDIF_CON: Non-audio flag set:
-   *    spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
-   */
-  sprintf (devstr,
-      "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
-      IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
-      IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
-      0, IEC958_AES3_CON_FS_48000);
-
-  GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
-  iec958_pcm_name = devstr;
-
-  res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
-  if (G_UNLIKELY (res < 0)) {
-    GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
-        snd_strerror (res));
-    pcm = NULL;
-  }
-
-  return pcm;
-}
-
-
-/*
- * gst_alsa_probe_supported_formats:
- *
- * Takes the template caps and returns the subset which is actually
- * supported by this device.
- *
- */
-
-GstCaps *
-gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle,
-    const GstCaps * template_caps)
-{
-  snd_pcm_hw_params_t *hw_params;
-  snd_pcm_stream_t stream_type;
-  GstCaps *caps;
-  gint err;
-
-  snd_pcm_hw_params_malloc (&hw_params);
-  if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
-    goto error;
-
-  stream_type = snd_pcm_stream (handle);
-
-  caps = gst_caps_copy (template_caps);
-
-  if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps)))
-    goto subroutine_error;
-
-  if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
-    goto subroutine_error;
-
-  if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
-    goto subroutine_error;
-
-  /* Try opening IEC958 device to see if we can support that format (playback
-   * only for now but we could add SPDIF capture later) */
-  if (stream_type == SND_PCM_STREAM_PLAYBACK) {
-    snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj);
-
-    if (G_LIKELY (pcm)) {
-      gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
-      snd_pcm_close (pcm);
-    }
-  }
-
-  snd_pcm_hw_params_free (hw_params);
-  return caps;
-
-  /* ERRORS */
-error:
-  {
-    GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
-    snd_pcm_hw_params_free (hw_params);
-    return NULL;
-  }
-subroutine_error:
-  {
-    GST_ERROR_OBJECT (obj, "failed to query formats");
-    snd_pcm_hw_params_free (hw_params);
-    return NULL;
-  }
-}
-
-static gchar *
-gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
-    gint device_num, snd_pcm_stream_t stream)
-{
-  snd_ctl_card_info_t *info = NULL;
-  snd_ctl_t *ctl = NULL;
-  gchar *ret = NULL;
-  gint dev = -1;
-
-  GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
-
-  if (snd_ctl_open (&ctl, devcard, 0) < 0)
-    return NULL;
-
-  snd_ctl_card_info_malloc (&info);
-  if (snd_ctl_card_info (ctl, info) < 0)
-    goto done;
-
-  while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
-    if (dev == device_num) {
-      snd_pcm_info_t *pcminfo;
-
-      snd_pcm_info_malloc (&pcminfo);
-      snd_pcm_info_set_device (pcminfo, dev);
-      snd_pcm_info_set_subdevice (pcminfo, 0);
-      snd_pcm_info_set_stream (pcminfo, stream);
-      if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
-        snd_pcm_info_free (pcminfo);
-        break;
-      }
-
-      ret = g_strdup (snd_pcm_info_get_name (pcminfo));
-      snd_pcm_info_free (pcminfo);
-      GST_LOG_OBJECT (obj, "name from pcminfo: %s", GST_STR_NULL (ret));
-    }
-  }
-
-  if (ret == NULL) {
-    char *name = NULL;
-    gint card;
-
-    GST_LOG_OBJECT (obj, "no luck so far, trying backup");
-    card = snd_ctl_card_info_get_card (info);
-    snd_card_get_name (card, &name);
-    ret = g_strdup (name);
-    free (name);
-  }
-
-done:
-  snd_ctl_card_info_free (info);
-  snd_ctl_close (ctl);
-
-  return ret;
-}
-
-gchar *
-gst_alsa_find_device_name (GstObject * obj, const gchar * device,
-    snd_pcm_t * handle, snd_pcm_stream_t stream)
-{
-  gchar *ret = NULL;
-
-  if (device != NULL) {
-    gchar *dev, *comma;
-    gint devnum;
-
-    GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
-
-    /* only want name:card bit, but not devices and subdevices */
-    dev = g_strdup (device);
-    if ((comma = strchr (dev, ','))) {
-      *comma = '\0';
-      devnum = atoi (comma + 1);
-      ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
-    }
-    g_free (dev);
-  }
-
-  if (ret == NULL && handle != NULL) {
-    snd_pcm_info_t *info;
-
-    GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
-    snd_pcm_info_malloc (&info);
-    snd_pcm_info (handle, info);
-    ret = g_strdup (snd_pcm_info_get_name (info));
-    snd_pcm_info_free (info);
-  }
-
-  GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
-      GST_STR_NULL (device), GST_STR_NULL (ret));
-
-  return ret;
-}
--- a/gst_plugins_base/ext/alsa/gstalsa.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_H__
-#define __GST_ALSA_H__
-
-
-#define ALSA_PCM_NEW_HW_PARAMS_API
-#define ALSA_PCM_NEW_SW_PARAMS_API
-
-#include <alsa/asoundlib.h>
-#include <alsa/control.h>
-#include <alsa/error.h>
-#include <gst/gst.h>
-
-#define GST_CHECK_ALSA_VERSION(major,minor,micro) \
-    (SND_LIB_MAJOR > (major) || \
-     (SND_LIB_MAJOR == (major) && SND_LIB_MINOR > (minor)) || \
-     (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \
-      SND_LIB_SUBMINOR >= (micro)))
-
-GST_DEBUG_CATEGORY_EXTERN (alsa_debug);
-#define GST_CAT_DEFAULT alsa_debug
-
-snd_pcm_t * gst_alsa_open_iec958_pcm (GstObject * obj);
-
-GstCaps * gst_alsa_probe_supported_formats (GstObject      * obj,
-                                            snd_pcm_t      * handle,
-                                            const GstCaps  * template_caps);
-
-gchar   * gst_alsa_find_device_name (GstObject        * obj,
-                                     const gchar      * device,
-                                     snd_pcm_t        * handle,
-                                     snd_pcm_stream_t   stream);
-
-#endif /* __GST_ALSA_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsadeviceprobe.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/* Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- * Copyright (C) 2005 Tim-Philipp Müller <tim centricular net>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsadeviceprobe.h"
-#include "gst/interfaces/propertyprobe.h"
-
-static const GList *
-gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe)
-{
-  GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
-  static GList *list = NULL;
-
-  /* well, not perfect, but better than no locking at all.
-   * In the worst case we leak a list node, so who cares? */
-  GST_CLASS_LOCK (GST_OBJECT_CLASS (klass));
-
-  if (!list) {
-    GParamSpec *pspec;
-
-    pspec = g_object_class_find_property (klass, "device");
-    list = g_list_append (NULL, pspec);
-  }
-
-  GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass));
-
-  return list;
-}
-
-static GList *
-gst_alsa_get_device_list (snd_pcm_stream_t stream)
-{
-  snd_ctl_t *handle;
-  int card, err, dev;
-  snd_ctl_card_info_t *info;
-  snd_pcm_info_t *pcminfo;
-  gboolean mixer = (stream == -1);
-  GList *list = NULL;
-
-  if (stream == -1)
-    stream = 0;
-
-  snd_ctl_card_info_malloc (&info);
-  snd_pcm_info_malloc (&pcminfo);
-  card = -1;
-
-  if (snd_card_next (&card) < 0 || card < 0) {
-    /* no soundcard found */
-    return NULL;
-  }
-
-  while (card >= 0) {
-    gchar name[32];
-
-    g_snprintf (name, sizeof (name), "hw:%d", card);
-    if ((err = snd_ctl_open (&handle, name, 0)) < 0) {
-      goto next_card;
-    }
-    if ((err = snd_ctl_card_info (handle, info)) < 0) {
-      snd_ctl_close (handle);
-      goto next_card;
-    }
-
-    if (mixer) {
-      list = g_list_append (list, g_strdup (name));
-    } else {
-      dev = -1;
-      while (1) {
-        gchar *gst_device;
-
-        snd_ctl_pcm_next_device (handle, &dev);
-
-        if (dev < 0)
-          break;
-        snd_pcm_info_set_device (pcminfo, dev);
-        snd_pcm_info_set_subdevice (pcminfo, 0);
-        snd_pcm_info_set_stream (pcminfo, stream);
-        if ((err = snd_ctl_pcm_info (handle, pcminfo)) < 0) {
-          continue;
-        }
-
-        gst_device = g_strdup_printf ("hw:%d,%d", card, dev);
-        list = g_list_append (list, gst_device);
-      }
-    }
-    snd_ctl_close (handle);
-  next_card:
-    if (snd_card_next (&card) < 0) {
-      break;
-    }
-  }
-
-  snd_ctl_card_info_free (info);
-  snd_pcm_info_free (pcminfo);
-
-  return list;
-}
-
-static void
-gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  if (!g_str_equal (pspec->name, "device")) {
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-  }
-}
-
-static gboolean
-gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  /* don't cache probed data */
-  return TRUE;
-}
-
-static GValueArray *
-gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstElementClass *klass;
-  const GList *templates;
-  snd_pcm_stream_t mode = -1;
-  GValueArray *array;
-  GValue value = { 0, };
-  GList *l, *list;
-
-  if (!g_str_equal (pspec->name, "device")) {
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-    return NULL;
-  }
-
-  klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));
-
-  /* I'm pretty sure ALSA has a good way to do this. However, their cool
-   * auto-generated documentation is pretty much useless if you try to
-   * do function-wise look-ups. */
-  /* we assume one pad template at max [zero=mixer] */
-  templates = gst_element_class_get_pad_template_list (klass);
-  if (templates) {
-    if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC)
-      mode = SND_PCM_STREAM_CAPTURE;
-    else
-      mode = SND_PCM_STREAM_PLAYBACK;
-  }
-
-  list = gst_alsa_get_device_list (mode);
-
-  if (list == NULL) {
-    GST_LOG_OBJECT (probe, "No devices found");
-    return NULL;
-  }
-
-  array = g_value_array_new (g_list_length (list));
-  g_value_init (&value, G_TYPE_STRING);
-  for (l = list; l != NULL; l = l->next) {
-    GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data);
-    g_value_take_string (&value, (gchar *) l->data);
-    l->data = NULL;
-    g_value_array_append (array, &value);
-  }
-  g_value_unset (&value);
-  g_list_free (list);
-
-  return array;
-}
-
-static void
-gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface)
-{
-  iface->get_properties = gst_alsa_device_property_probe_get_properties;
-  iface->probe_property = gst_alsa_device_property_probe_probe_property;
-  iface->needs_probe = gst_alsa_device_property_probe_needs_probe;
-  iface->get_values = gst_alsa_device_property_probe_get_values;
-}
-
-void
-gst_alsa_type_add_device_property_probe_interface (GType type)
-{
-  static const GInterfaceInfo probe_iface_info = {
-    (GInterfaceInitFunc) gst_alsa_property_probe_interface_init,
-    NULL,
-    NULL,
-  };
-
-  g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
-      &probe_iface_info);
-}
--- a/gst_plugins_base/ext/alsa/gstalsadeviceprobe.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/* Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __GST_ALSA_DEVICE_PROBE_H__
-#define __GST_ALSA_DEVICE_PROBE_H__
-
-#include "gstalsa.h"
-
-G_BEGIN_DECLS
-
-void      gst_alsa_type_add_device_property_probe_interface (GType type);
-
-G_END_DECLS
-
-#endif /* __GST_ALSA_DEVICE_PROBE_H__ */
-
--- a/gst_plugins_base/ext/alsa/gstalsamixer.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,887 +0,0 @@
-/* ALSA mixer implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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.
- */
-
-/**
- * SECTION:element-alsamixer
- * @short_description: control properties of an audio device
- * @see_also: alsasink, alsasrc
- *
- * <refsect2>
- * <para>
- * This element controls various aspects such as the volume and balance
- * of an audio device using the ALSA api.
- * </para>
- * <para>
- * The application should query and use the interfaces provided by this 
- * element to control the device.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsamixer.h"
-
-static void gst_alsa_mixer_update_option (GstAlsaMixer * mixer,
-    GstAlsaMixerOptions * alsa_opts);
-static void gst_alsa_mixer_update_track (GstAlsaMixer * mixer,
-    GstAlsaMixerTrack * alsa_track);
-static int gst_alsa_mixer_handle_callback (snd_mixer_t * handle,
-    unsigned int mask, snd_mixer_elem_t * elem);
-
-/* First some utils, then the mixer implementation */
-static gboolean
-gst_alsa_mixer_open (GstAlsaMixer * mixer)
-{
-  gint err;
-  snd_ctl_t *ctl;
-  snd_ctl_card_info_t *card_info;
-
-  g_return_val_if_fail (mixer->handle == NULL, FALSE);
-
-  /* open and initialize the mixer device */
-  err = snd_mixer_open (&mixer->handle, 0);
-  if (err < 0 || mixer->handle == NULL)
-    goto open_failed;
-
-  if ((err = snd_mixer_attach (mixer->handle, mixer->device)) < 0) {
-    GST_WARNING ("Cannot open mixer for sound device '%s': %s", mixer->device,
-        snd_strerror (err));
-    goto error;
-  }
-
-  if ((err = snd_mixer_selem_register (mixer->handle, NULL, NULL)) < 0) {
-    GST_WARNING ("Cannot register mixer elements: %s", snd_strerror (err));
-    goto error;
-  }
-
-  if ((err = snd_mixer_load (mixer->handle)) < 0) {
-    GST_WARNING ("Cannot load mixer settings: %s", snd_strerror (err));
-    goto error;
-  }
-
-  snd_mixer_set_callback_private (mixer->handle, mixer);
-  snd_mixer_set_callback (mixer->handle, gst_alsa_mixer_handle_callback);
-
-  /* now get the device name, any of this is not fatal */
-  g_free (mixer->cardname);
-  if ((err = snd_ctl_open (&ctl, mixer->device, 0)) < 0) {
-    GST_WARNING ("Cannot open CTL: %s", snd_strerror (err));
-    goto no_card_name;
-  }
-
-  snd_ctl_card_info_malloc (&card_info);
-  if ((err = snd_ctl_card_info (ctl, card_info)) < 0) {
-    GST_WARNING ("Cannot get card info: %s", snd_strerror (err));
-    snd_ctl_close (ctl);
-    goto no_card_name;
-  }
-
-  mixer->cardname = g_strdup (snd_ctl_card_info_get_name (card_info));
-  GST_DEBUG ("Card name = %s", GST_STR_NULL (mixer->cardname));
-  snd_ctl_card_info_free (card_info);
-  snd_ctl_close (ctl);
-
-no_card_name:
-  if (mixer->cardname == NULL) {
-    mixer->cardname = g_strdup ("Unknown");
-    GST_DEBUG ("Cannot find card name");
-  }
-
-  GST_INFO ("Successfully opened mixer for device '%s'.", mixer->device);
-
-  return TRUE;
-
-  /* ERROR */
-open_failed:
-  {
-    GST_WARNING ("Cannot open mixer: %s", snd_strerror (err));
-    mixer->handle = NULL;
-    return FALSE;
-  }
-error:
-  {
-    snd_mixer_close (mixer->handle);
-    mixer->handle = NULL;
-    return FALSE;
-  }
-}
-
-static snd_mixer_elem_t *
-gst_alsa_mixer_find_master_mixer (GstAlsaMixer * mixer, snd_mixer_t * handle)
-{
-  snd_mixer_elem_t *element;
-  gint i, count;
-
-  count = snd_mixer_get_count (handle);
-
-  /* Check if we have a playback mixer labelled as 'Master' */
-  element = snd_mixer_first_elem (handle);
-  for (i = 0; i < count; i++) {
-    if (snd_mixer_selem_has_playback_volume (element) &&
-        strcmp (snd_mixer_selem_get_name (element), "Master") == 0) {
-      return element;
-    }
-    element = snd_mixer_elem_next (element);
-  }
-
-  /* If not, check if we have a playback mixer labelled as 'Front' */
-  element = snd_mixer_first_elem (handle);
-  for (i = 0; i < count; i++) {
-    if (snd_mixer_selem_has_playback_volume (element) &&
-        strcmp (snd_mixer_selem_get_name (element), "Front") == 0) {
-      return element;
-    }
-    element = snd_mixer_elem_next (element);
-  }
-
-  /* If not, check if we have a playback mixer labelled as 'PCM' */
-  element = snd_mixer_first_elem (handle);
-  for (i = 0; i < count; i++) {
-    if (snd_mixer_selem_has_playback_volume (element) &&
-        strcmp (snd_mixer_selem_get_name (element), "PCM") == 0) {
-      return element;
-    }
-    element = snd_mixer_elem_next (element);
-  }
-
-  /* If not, check if we have a playback mixer with both volume and switch */
-  element = snd_mixer_first_elem (handle);
-  for (i = 0; i < count; i++) {
-    if (snd_mixer_selem_has_playback_volume (element) &&
-        snd_mixer_selem_has_playback_switch (element)) {
-      return element;
-    }
-    element = snd_mixer_elem_next (element);
-  }
-
-  /* If not, take any playback mixer with a volume control */
-  element = snd_mixer_first_elem (handle);
-  for (i = 0; i < count; i++) {
-    if (snd_mixer_selem_has_playback_volume (element)) {
-      return element;
-    }
-    element = snd_mixer_elem_next (element);
-  }
-
-  /* Looks like we're out of luck ... */
-  return NULL;
-}
-
-static void
-gst_alsa_mixer_update (GstAlsaMixer * mixer, snd_mixer_elem_t * elem)
-{
-  GList *item;
-
-  g_return_if_fail (mixer != NULL);
-
-  g_static_rec_mutex_lock (mixer->rec_mutex);
-
-  for (item = mixer->tracklist; item != NULL; item = item->next) {
-    if (GST_IS_ALSA_MIXER_TRACK (item->data)) {
-      if (elem && (GST_ALSA_MIXER_TRACK (item->data)->element != elem))
-        continue;
-
-      gst_alsa_mixer_update_track (mixer, GST_ALSA_MIXER_TRACK (item->data));
-    } else if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) {
-      if (elem && (GST_ALSA_MIXER_OPTIONS (item->data)->element != elem))
-        continue;
-
-      gst_alsa_mixer_update_option (mixer, GST_ALSA_MIXER_OPTIONS (item->data));
-    }
-  }
-
-  g_static_rec_mutex_unlock (mixer->rec_mutex);
-}
-
-static int
-gst_alsa_mixer_elem_handle_callback (snd_mixer_elem_t * elem, unsigned int mask)
-{
-  GstAlsaMixer *mixer =
-      (GstAlsaMixer *) snd_mixer_elem_get_callback_private (elem);
-
-  GST_LOG ("ALSA elem cb");
-
-  g_return_val_if_fail (mixer != NULL, 1);
-
-  gst_alsa_mixer_update (mixer, elem);
-
-  return 0;
-}
-
-static int
-gst_alsa_mixer_handle_callback (snd_mixer_t * handle, unsigned int mask,
-    snd_mixer_elem_t * elem)
-{
-  GstAlsaMixer *mixer =
-      (GstAlsaMixer *) snd_mixer_get_callback_private (handle);
-
-  GST_LOG ("ALSA cb");
-
-  g_return_val_if_fail (mixer != NULL, 1);
-
-  /* Hopefully won't be call recursively and will handle pending elem events */
-  snd_mixer_handle_events (mixer->handle);
-
-  gst_alsa_mixer_update (mixer, elem);
-
-  return 0;
-}
-
-static void
-gst_alsa_mixer_ensure_track_list (GstAlsaMixer * mixer)
-{
-  gint i, count;
-  snd_mixer_elem_t *element, *master;
-  GList *item;
-
-  g_return_if_fail (mixer->handle != NULL);
-
-  if (mixer->tracklist)
-    return;
-
-  g_static_rec_mutex_lock (mixer->rec_mutex);
-
-  master = gst_alsa_mixer_find_master_mixer (mixer, mixer->handle);
-
-  count = snd_mixer_get_count (mixer->handle);
-  element = snd_mixer_first_elem (mixer->handle);
-
-  /* build track list
-   *
-   * Some ALSA tracks may have playback and capture capabilities.
-   * Here we model them as two separate GStreamer tracks.
-   */
-
-  for (i = 0; i < count; i++) {
-    GstMixerTrack *play_track = NULL;
-    GstMixerTrack *cap_track = NULL;
-    const gchar *name;
-    GList *item;
-    gint samename = 0;
-
-    name = snd_mixer_selem_get_name (element);
-
-    /* prevent dup names */
-    for (item = mixer->tracklist; item != NULL; item = item->next) {
-      snd_mixer_elem_t *temp;
-
-      if (GST_IS_ALSA_MIXER_OPTIONS (item->data))
-        temp = GST_ALSA_MIXER_OPTIONS (item->data)->element;
-      else
-        temp = GST_ALSA_MIXER_TRACK (item->data)->element;
-
-      if (strcmp (name, snd_mixer_selem_get_name (temp)) == 0)
-        samename++;
-    }
-
-    GST_LOG ("[%s] probing element #%u, mixer->dir=%u", name, i, mixer->dir);
-
-    if (mixer->dir & GST_ALSA_MIXER_PLAYBACK) {
-      gboolean has_playback_switch, has_playback_volume;
-
-      has_playback_switch = snd_mixer_selem_has_playback_switch (element);
-      has_playback_volume = snd_mixer_selem_has_playback_volume (element);
-
-      GST_LOG ("[%s] PLAYBACK: has_playback_volume=%d, has_playback_switch=%d"
-          "%s", name, has_playback_volume, has_playback_switch,
-          (element == master) ? " MASTER" : "");
-
-      if (has_playback_volume) {
-        gint flags = GST_MIXER_TRACK_OUTPUT;
-
-        if (element == master)
-          flags |= GST_MIXER_TRACK_MASTER;
-
-        play_track = gst_alsa_mixer_track_new (element, samename, i,
-            flags, FALSE, NULL, FALSE);
-
-      } else if (has_playback_switch) {
-        /* simple mute switch */
-        play_track = gst_alsa_mixer_track_new (element, samename, i,
-            GST_MIXER_TRACK_OUTPUT, TRUE, NULL, FALSE);
-      }
-
-      if (snd_mixer_selem_is_enumerated (element)) {
-        GstMixerOptions *opts = gst_alsa_mixer_options_new (element, i);
-
-        GST_LOG ("[%s] is enumerated (%d)", name, i);
-        mixer->tracklist = g_list_append (mixer->tracklist, opts);
-      }
-    }
-
-    if (mixer->dir & GST_ALSA_MIXER_CAPTURE) {
-      gboolean has_capture_switch, has_common_switch;
-      gboolean has_capture_volume, has_common_volume;
-
-      has_capture_switch = snd_mixer_selem_has_capture_switch (element);
-      has_common_switch = snd_mixer_selem_has_common_switch (element);
-      has_capture_volume = snd_mixer_selem_has_capture_volume (element);
-      has_common_volume = snd_mixer_selem_has_common_volume (element);
-
-      GST_LOG ("[%s] CAPTURE: has_capture_volume=%d, has_common_volume=%d, "
-          "has_capture_switch=%d, has_common_switch=%d, play_track=%p", name,
-          has_capture_volume, has_common_volume, has_capture_switch,
-          has_common_switch, play_track);
-
-      if (has_capture_volume && !(play_track && has_common_volume)) {
-        cap_track = gst_alsa_mixer_track_new (element, samename, i,
-            GST_MIXER_TRACK_INPUT, FALSE, NULL, play_track != NULL);
-      } else if (has_capture_switch && !(play_track && has_common_switch)) {
-        cap_track = gst_alsa_mixer_track_new (element, samename, i,
-            GST_MIXER_TRACK_INPUT, TRUE, NULL, play_track != NULL);
-      }
-    }
-
-
-    if (play_track && cap_track) {
-      GST_ALSA_MIXER_TRACK (play_track)->shared_mute =
-          GST_ALSA_MIXER_TRACK (cap_track);
-      GST_ALSA_MIXER_TRACK (cap_track)->shared_mute =
-          GST_ALSA_MIXER_TRACK (play_track);
-    }
-
-    if (play_track)
-      mixer->tracklist = g_list_append (mixer->tracklist, play_track);
-
-    if (cap_track)
-      mixer->tracklist = g_list_append (mixer->tracklist, cap_track);
-
-    element = snd_mixer_elem_next (element);
-  }
-
-  for (item = mixer->tracklist; item != NULL; item = item->next) {
-    snd_mixer_elem_t *temp;
-
-    if (GST_IS_ALSA_MIXER_OPTIONS (item->data))
-      temp = GST_ALSA_MIXER_OPTIONS (item->data)->element;
-    else
-      temp = GST_ALSA_MIXER_TRACK (item->data)->element;
-
-    snd_mixer_elem_set_callback (temp, gst_alsa_mixer_elem_handle_callback);
-    snd_mixer_elem_set_callback_private (temp, mixer);
-  }
-
-  g_static_rec_mutex_unlock (mixer->rec_mutex);
-}
-
-static void
-task_monitor_alsa (gpointer data)
-{
-  struct pollfd *pfds;
-  unsigned int nfds, rnfds;
-  unsigned short revents;
-  GstAlsaMixer *mixer = (GstAlsaMixer *) data;
-
-  g_static_rec_mutex_lock (mixer->rec_mutex);
-
-  nfds = snd_mixer_poll_descriptors_count (mixer->handle);
-  if (nfds <= 0) {
-    GST_ERROR ("snd_mixer_poll_descriptors_count <= 0: %d", nfds);
-    /* FIXME: sleep ? stop monitoring ? */
-    return;
-  }
-
-  pfds = g_newa (struct pollfd, nfds + 1);
-  rnfds = snd_mixer_poll_descriptors (mixer->handle, pfds, nfds);
-  g_assert (rnfds <= nfds);
-
-  pfds[rnfds].fd = mixer->pfd[0];
-  pfds[rnfds].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
-  pfds[rnfds].revents = 0;
-
-  g_static_rec_mutex_unlock (mixer->rec_mutex);
-
-  GST_LOG ("task loop");
-  poll (pfds, rnfds + 1, -1);
-
-  g_static_rec_mutex_lock (mixer->rec_mutex);
-
-  snd_mixer_poll_descriptors_revents (mixer->handle, pfds, nfds, &revents);
-  if (revents & POLLIN || revents & POLLPRI) {
-    GST_DEBUG ("Handling events");
-    snd_mixer_handle_events (mixer->handle);
-  }
-
-  g_static_rec_mutex_unlock (mixer->rec_mutex);
-}
-
-/* API */
-
-GstAlsaMixer *
-gst_alsa_mixer_new (const char *device, GstAlsaMixerDirection dir)
-{
-  GstAlsaMixer *ret = NULL;
-
-  g_return_val_if_fail (device != NULL, NULL);
-
-  ret = g_new0 (GstAlsaMixer, 1);
-
-  if (pipe (ret->pfd) == -1)
-    goto error;
-
-  ret->rec_mutex = g_new (GStaticRecMutex, 1);
-  g_static_rec_mutex_init (ret->rec_mutex);
-
-  ret->task_mutex = g_new (GStaticRecMutex, 1);
-  g_static_rec_mutex_init (ret->task_mutex);
-
-  ret->task = gst_task_create (task_monitor_alsa, ret);
-  gst_task_set_lock (ret->task, ret->task_mutex);
-
-  ret->device = g_strdup (device);
-  ret->dir = dir;
-
-  if (!gst_alsa_mixer_open (ret))
-    goto error;
-
-  if (gst_task_start (ret->task) == FALSE) {
-    GST_WARNING ("Could not start alsamixer task");
-  }
-
-  return ret;
-
-  /* ERRORS */
-error:
-  {
-    gst_alsa_mixer_free (ret);
-    return NULL;
-  }
-}
-
-void
-gst_alsa_mixer_free (GstAlsaMixer * mixer)
-{
-  g_return_if_fail (mixer != NULL);
-
-  if (mixer->task) {
-    if (write (mixer->pfd[1], "stop", 5) <= 0) {
-      GST_ERROR ("Cannot send " "stop" " to alsamixer task");
-      close (mixer->pfd[1]);
-      mixer->pfd[1] = -1;
-    }
-
-    if (gst_task_join (mixer->task) == FALSE) {
-      GST_ERROR ("Cannot join alsamixer task");
-    }
-
-    gst_object_unref (mixer->task);
-    mixer->task = NULL;
-  }
-
-  g_static_rec_mutex_free (mixer->task_mutex);
-  g_free (mixer->task_mutex);
-  mixer->task_mutex = NULL;
-
-  if (mixer->pfd[0] > 0) {
-    close (mixer->pfd[0]);
-    mixer->pfd[0] = -1;
-  }
-
-  if (mixer->pfd[1] > 0) {
-    close (mixer->pfd[1]);
-    mixer->pfd[1] = -1;
-  }
-
-  if (mixer->interface) {
-    g_object_unref (G_OBJECT (mixer->interface));
-    mixer->interface = NULL;
-  }
-
-  if (mixer->device) {
-    g_free (mixer->device);
-    mixer->device = NULL;
-  }
-
-  if (mixer->cardname) {
-    g_free (mixer->cardname);
-    mixer->cardname = NULL;
-  }
-
-  if (mixer->tracklist) {
-    g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
-    g_list_free (mixer->tracklist);
-    mixer->tracklist = NULL;
-  }
-
-  if (mixer->handle) {
-    snd_mixer_close (mixer->handle);
-    mixer->handle = NULL;
-  }
-
-  g_static_rec_mutex_free (mixer->rec_mutex);
-  g_free (mixer->rec_mutex);
-  mixer->rec_mutex = NULL;
-
-  g_free (mixer);
-}
-
-const GList *
-gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer)
-{
-  g_return_val_if_fail (mixer->handle != NULL, NULL);
-
-  gst_alsa_mixer_ensure_track_list (mixer);
-
-  return (const GList *) mixer->tracklist;
-}
-
-void
-gst_alsa_mixer_get_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
-    gint * volumes)
-{
-  gint i;
-  GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-
-  g_return_if_fail (mixer->handle != NULL);
-
-  gst_alsa_mixer_track_update (alsa_track);
-
-  if (track->flags & GST_MIXER_TRACK_OUTPUT) {  /* return playback volume */
-
-    /* Is emulated mute flag activated? */
-    if (track->flags & GST_MIXER_TRACK_MUTE &&
-        !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) {
-      for (i = 0; i < track->num_channels; i++)
-        volumes[i] = alsa_track->volumes[i];
-    } else {
-      for (i = 0; i < track->num_channels; i++) {
-        long tmp = 0;
-
-        snd_mixer_selem_get_playback_volume (alsa_track->element, i, &tmp);
-        alsa_track->volumes[i] = volumes[i] = (gint) tmp;
-      }
-    }
-
-  } else if (track->flags & GST_MIXER_TRACK_INPUT) {    /* return capture volume */
-
-    /* Is emulated record flag activated? */
-    if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH ||
-        track->flags & GST_MIXER_TRACK_RECORD) {
-      for (i = 0; i < track->num_channels; i++) {
-        long tmp = 0;
-
-        snd_mixer_selem_get_capture_volume (alsa_track->element, i, &tmp);
-        alsa_track->volumes[i] = volumes[i] = (gint) tmp;
-      }
-    } else {
-      for (i = 0; i < track->num_channels; i++)
-        volumes[i] = alsa_track->volumes[i];
-    }
-  }
-}
-
-static gboolean
-check_if_volumes_are_the_same (guint num_channels, gint * volumes)
-{
-  guint i;
-
-  if (num_channels <= 1)
-    return TRUE;
-
-  for (i = 1; i < num_channels; i++) {
-    if (volumes[i] != volumes[0])
-      return FALSE;
-  }
-
-  return TRUE;
-}
-
-void
-gst_alsa_mixer_set_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
-    gint * volumes)
-{
-  GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-  gint i;
-
-  g_return_if_fail (mixer->handle != NULL);
-
-  gst_alsa_mixer_track_update (alsa_track);
-
-  if (track->flags & GST_MIXER_TRACK_OUTPUT) {
-
-    /* Is emulated mute flag activated? */
-    if (track->flags & GST_MIXER_TRACK_MUTE &&
-        !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) {
-      for (i = 0; i < track->num_channels; i++)
-        alsa_track->volumes[i] = volumes[i];
-    } else {
-      if (check_if_volumes_are_the_same (track->num_channels, volumes)) {
-        snd_mixer_selem_set_playback_volume_all (alsa_track->element,
-            volumes[0]);
-        for (i = 0; i < track->num_channels; i++)
-          alsa_track->volumes[i] = volumes[0];
-      } else {
-        for (i = 0; i < track->num_channels; i++) {
-          alsa_track->volumes[i] = volumes[i];
-          snd_mixer_selem_set_playback_volume (alsa_track->element, i,
-              volumes[i]);
-        }
-      }
-    }
-
-  } else if (track->flags & GST_MIXER_TRACK_INPUT) {
-
-    /* Is emulated record flag activated? */
-    if (track->flags & GST_MIXER_TRACK_RECORD ||
-        alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) {
-      if (check_if_volumes_are_the_same (track->num_channels, volumes)) {
-        snd_mixer_selem_set_capture_volume_all (alsa_track->element,
-            volumes[0]);
-        for (i = 0; i < track->num_channels; i++)
-          alsa_track->volumes[i] = volumes[0];
-      } else {
-        for (i = 0; i < track->num_channels; i++) {
-          alsa_track->volumes[i] = volumes[i];
-          snd_mixer_selem_set_capture_volume (alsa_track->element, i,
-              volumes[i]);
-        }
-      }
-    } else {
-      for (i = 0; i < track->num_channels; i++)
-        alsa_track->volumes[i] = volumes[i];
-    }
-  }
-}
-
-void
-gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, GstMixerTrack * track,
-    gboolean mute)
-{
-  GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-
-  g_return_if_fail (mixer->handle != NULL);
-
-  gst_alsa_mixer_track_update (alsa_track);
-
-  if (!!(mute) == !!(track->flags & GST_MIXER_TRACK_MUTE))
-    return;
-
-  if (mute) {
-    track->flags |= GST_MIXER_TRACK_MUTE;
-
-    if (alsa_track->shared_mute)
-      ((GstMixerTrack *) (alsa_track->shared_mute))->flags |=
-          GST_MIXER_TRACK_MUTE;
-  } else {
-    track->flags &= ~GST_MIXER_TRACK_MUTE;
-
-    if (alsa_track->shared_mute)
-      ((GstMixerTrack *) (alsa_track->shared_mute))->flags &=
-          ~GST_MIXER_TRACK_MUTE;
-  }
-
-  if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH) {
-    snd_mixer_selem_set_playback_switch_all (alsa_track->element, mute ? 0 : 1);
-  } else {
-    gint i;
-    GstAlsaMixerTrack *ctrl_track;
-
-    if ((track->flags & GST_MIXER_TRACK_INPUT)
-        && alsa_track->shared_mute != NULL)
-      ctrl_track = alsa_track->shared_mute;
-    else
-      ctrl_track = alsa_track;
-
-    for (i = 0; i < ((GstMixerTrack *) ctrl_track)->num_channels; i++) {
-      long vol =
-          mute ? ((GstMixerTrack *) ctrl_track)->min_volume : ctrl_track->
-          volumes[i];
-      snd_mixer_selem_set_playback_volume (ctrl_track->element, i, vol);
-    }
-  }
-}
-
-void
-gst_alsa_mixer_set_record (GstAlsaMixer * mixer,
-    GstMixerTrack * track, gboolean record)
-{
-  GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-
-  g_return_if_fail (mixer->handle != NULL);
-
-  gst_alsa_mixer_track_update (alsa_track);
-
-  if (!!(record) == !!(track->flags & GST_MIXER_TRACK_RECORD))
-    return;
-
-  if (record) {
-    track->flags |= GST_MIXER_TRACK_RECORD;
-  } else {
-    track->flags &= ~GST_MIXER_TRACK_RECORD;
-  }
-
-  if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) {
-    snd_mixer_selem_set_capture_switch_all (alsa_track->element,
-        record ? 1 : 0);
-
-    /* update all tracks in same exlusive cswitch group */
-    if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH_EXCL) {
-      GList *item;
-
-      for (item = mixer->tracklist; item != NULL; item = item->next) {
-
-        if (GST_IS_ALSA_MIXER_TRACK (item->data)) {
-          GstAlsaMixerTrack *item_alsa_track =
-              GST_ALSA_MIXER_TRACK (item->data);
-
-          if (item_alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH_EXCL &&
-              item_alsa_track->capture_group == alsa_track->capture_group) {
-            gst_alsa_mixer_track_update (item_alsa_track);
-          }
-        }
-      }
-    }
-  } else {
-    gint i;
-
-    for (i = 0; i < track->num_channels; i++) {
-      long vol = record ? alsa_track->volumes[i] : track->min_volume;
-
-      snd_mixer_selem_set_capture_volume (alsa_track->element, i, vol);
-    }
-  }
-}
-
-void
-gst_alsa_mixer_set_option (GstAlsaMixer * mixer,
-    GstMixerOptions * opts, gchar * value)
-{
-  gint idx = -1, n = 0;
-  GList *item;
-  GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
-
-  g_return_if_fail (mixer->handle != NULL);
-
-  for (item = opts->values; item != NULL; item = item->next, n++) {
-    if (!strcmp (item->data, value)) {
-      idx = n;
-      break;
-    }
-  }
-  if (idx == -1)
-    return;
-
-  snd_mixer_selem_set_enum_item (alsa_opts->element, 0, idx);
-}
-
-const gchar *
-gst_alsa_mixer_get_option (GstAlsaMixer * mixer, GstMixerOptions * opts)
-{
-  gint ret;
-  guint idx;
-  GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
-
-  g_return_val_if_fail (mixer->handle != NULL, NULL);
-
-  ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
-  if (ret == 0)
-    return g_list_nth_data (opts->values, idx);
-  else
-    return snd_strerror (ret);  /* feeble attempt at error handling */
-}
-
-GstMixerFlags
-gst_alsa_mixer_get_mixer_flags (GstAlsaMixer * mixer)
-{
-  g_return_val_if_fail (mixer != NULL, GST_MIXER_FLAG_NONE);
-
-  return GST_MIXER_FLAG_AUTO_NOTIFICATIONS;
-}
-
-static void
-gst_alsa_mixer_update_option (GstAlsaMixer * mixer,
-    GstAlsaMixerOptions * alsa_opts)
-{
-  gint ret;
-  guint idx;
-  /* const */ gchar *option;
-
-  if (mixer->interface == NULL) {
-    GST_WARNING ("Cannot send update notifications, no GstMixer * given");
-    return;
-  }
-
-  ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
-  if (ret == 0) {
-    option = g_list_nth_data (GST_MIXER_OPTIONS (alsa_opts)->values, idx);
-    gst_mixer_option_changed (mixer->interface, GST_MIXER_OPTIONS (alsa_opts),
-        option);
-  }
-}
-
-static void
-gst_alsa_mixer_update_track (GstAlsaMixer * mixer,
-    GstAlsaMixerTrack * alsa_track)
-{
-  GstMixerTrack *track = (GstMixerTrack *) alsa_track;
-  gboolean old_mute;
-  gboolean old_record;
-  gint i, n_channels;
-  gint *old_volumes;
-
-  GST_DEBUG ("Updating track %" GST_PTR_FORMAT, alsa_track);
-
-  if (mixer->interface == NULL) {
-    GST_WARNING ("Cannot send update notifications, no GstMixer * given");
-    return;
-  }
-
-  old_mute = !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE));
-  old_record = !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD));
-  old_volumes = g_new (gint, track->num_channels);
-  n_channels = track->num_channels;
-  memcpy (old_volumes, alsa_track->volumes,
-      sizeof (gint) * track->num_channels);
-
-  gst_alsa_mixer_track_update (alsa_track);
-
-  if (old_record !=
-      !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD))) {
-    gst_mixer_record_toggled (mixer->interface, track,
-        !!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD));
-  }
-  if (old_mute != !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE))) {
-    gst_mixer_mute_toggled (mixer->interface, track,
-        !!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE));
-  }
-
-  n_channels = MIN (n_channels, track->num_channels);
-  for (i = 0; i < n_channels; i++) {
-    if (old_volumes[i] != alsa_track->volumes[i]) {
-      gst_mixer_volume_changed (mixer->interface, track, alsa_track->volumes);
-      break;
-    }
-  }
-  g_free (old_volumes);
-}
-
-/* utility function for gstalsamixerelement to set the interface */
-void
-_gst_alsa_mixer_set_interface (GstAlsaMixer * mixer, GstMixer * interface)
-{
-  g_return_if_fail (mixer != NULL && mixer->interface == NULL);
-  g_return_if_fail (interface != NULL);
-
-  mixer->interface = g_object_ref (G_OBJECT (interface));
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixer.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-/* ALSA mixer interface implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_H__
-#define __GST_ALSA_MIXER_H__
-
-
-#include "gstalsa.h"
-
-#include <gst/interfaces/mixer.h>
-#include "gstalsamixeroptions.h"
-#include "gstalsamixertrack.h"
-
-
-G_BEGIN_DECLS
-
-/* This does not get you what you think it does, use obj->mixer   */
-/* #define GST_ALSA_MIXER(obj)             ((GstAlsaMixer*)(obj)) */
-
-typedef struct _GstAlsaMixer GstAlsaMixer;
-
-typedef enum {
-  GST_ALSA_MIXER_CAPTURE = 1<<0,
-  GST_ALSA_MIXER_PLAYBACK = 1<<1,
-  GST_ALSA_MIXER_ALL = GST_ALSA_MIXER_CAPTURE | GST_ALSA_MIXER_PLAYBACK
-} GstAlsaMixerDirection;
-
-/**
- * GstAlsaMixer:
- *
- * Opaque data structure
- */
-struct _GstAlsaMixer
-{
-  GList *               tracklist;      /* list of available tracks */
-
-  snd_mixer_t *         handle;
-
-  GstTask *		task;
-  GStaticRecMutex *	task_mutex;
-  GStaticRecMutex *	rec_mutex;
-
-  int			pfd[2];
-
-  GstMixer *		interface;
-  gchar *               device;
-  gchar *               cardname;
-
-  GstAlsaMixerDirection dir;
-};
-
-
-GstAlsaMixer*   gst_alsa_mixer_new              (const gchar *device,
-                                                 GstAlsaMixerDirection dir);
-void            gst_alsa_mixer_free             (GstAlsaMixer *mixer);
-
-const GList*    gst_alsa_mixer_list_tracks      (GstAlsaMixer * mixer);
-void            gst_alsa_mixer_set_volume       (GstAlsaMixer * mixer,
-                                                 GstMixerTrack * track,
-                                                 gint * volumes);
-void            gst_alsa_mixer_get_volume       (GstAlsaMixer * mixer,
-                                                 GstMixerTrack * track,
-                                                 gint * volumes);
-void            gst_alsa_mixer_set_record       (GstAlsaMixer * mixer,
-                                                 GstMixerTrack * track,
-                                                 gboolean record);
-void            gst_alsa_mixer_set_mute         (GstAlsaMixer * mixer,
-                                                 GstMixerTrack * track,
-                                                 gboolean mute);
-void            gst_alsa_mixer_set_option       (GstAlsaMixer * mixer,
-                                                 GstMixerOptions * opts,
-                                                 gchar * value);
-const gchar*    gst_alsa_mixer_get_option       (GstAlsaMixer * mixer,
-                                                 GstMixerOptions * opts);
-void		_gst_alsa_mixer_set_interface   (GstAlsaMixer * mixer,
-						 GstMixer * interface);
-GstMixerFlags   gst_alsa_mixer_get_mixer_flags  (GstAlsaMixer *mixer);
-
-#define GST_IMPLEMENT_ALSA_MIXER_METHODS(Type, interface_as_function)           \
-static gboolean                                                                 \
-interface_as_function ## _supported (Type *this, GType iface_type)              \
-{                                                                               \
-  g_assert (iface_type == GST_TYPE_MIXER);                                      \
-                                                                                \
-  return (this->mixer != NULL);                                                 \
-}                                                                               \
-                                                                                \
-static const GList*                                                             \
-interface_as_function ## _list_tracks (GstMixer * mixer)                        \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_val_if_fail (this != NULL, NULL);                                    \
-  g_return_val_if_fail (this->mixer != NULL, NULL);                             \
-                                                                                \
-  return gst_alsa_mixer_list_tracks (this->mixer);                              \
-}                                                                               \
-                                                                                \
-static void                                                                     \
-interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track,  \
-    gint * volumes)                                                             \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_if_fail (this != NULL);                                              \
-  g_return_if_fail (this->mixer != NULL);                                       \
-                                                                                \
-  gst_alsa_mixer_set_volume (this->mixer, track, volumes);                      \
-}                                                                               \
-                                                                                \
-static void                                                                     \
-interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track,  \
-    gint * volumes)                                                             \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_if_fail (this != NULL);                                              \
-  g_return_if_fail (this->mixer != NULL);                                       \
-                                                                                \
-  gst_alsa_mixer_get_volume (this->mixer, track, volumes);                      \
-}                                                                               \
-                                                                                \
-static void                                                                     \
-interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track,  \
-    gboolean record)                                                            \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_if_fail (this != NULL);                                              \
-  g_return_if_fail (this->mixer != NULL);                                       \
-                                                                                \
-  gst_alsa_mixer_set_record (this->mixer, track, record);                       \
-}                                                                               \
-                                                                                \
-static void                                                                     \
-interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track,    \
-    gboolean mute)                                                              \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_if_fail (this != NULL);                                              \
-  g_return_if_fail (this->mixer != NULL);                                       \
-                                                                                \
-  gst_alsa_mixer_set_mute (this->mixer, track, mute);                           \
-}                                                                               \
-                                                                                \
-static void                                                                     \
-interface_as_function ## _set_option (GstMixer * mixer, GstMixerOptions * opts, \
-    gchar * value)                                                              \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_if_fail (this != NULL);                                              \
-  g_return_if_fail (this->mixer != NULL);                                       \
-                                                                                \
-  gst_alsa_mixer_set_option (this->mixer, opts, value);                         \
-}                                                                               \
-                                                                                \
-static const gchar*                                                             \
-interface_as_function ## _get_option (GstMixer * mixer, GstMixerOptions * opts) \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_val_if_fail (this != NULL, NULL);                                    \
-  g_return_val_if_fail (this->mixer != NULL, NULL);                             \
-                                                                                \
-  return gst_alsa_mixer_get_option (this->mixer, opts);                         \
-}                                                                               \
-                                                                                \
-static GstMixerFlags                                                            \
-interface_as_function ## _get_mixer_flags (GstMixer * mixer)                    \
-{                                                                               \
-  Type *this = (Type*) mixer;                                                   \
-                                                                                \
-  g_return_val_if_fail (this != NULL, GST_MIXER_FLAG_NONE);                     \
-  g_return_val_if_fail (this->mixer != NULL, GST_MIXER_FLAG_NONE);              \
-                                                                                \
-  return gst_alsa_mixer_get_mixer_flags (this->mixer);                          \
-}                                                                               \
-                                                                                \
-static void                                                                     \
-interface_as_function ## _interface_init (GstMixerClass * klass)                \
-{                                                                               \
-  GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;                                  \
-                                                                                \
-  /* set up the interface hooks */                                              \
-  klass->list_tracks = interface_as_function ## _list_tracks;                   \
-  klass->set_volume = interface_as_function ## _set_volume;                     \
-  klass->get_volume = interface_as_function ## _get_volume;                     \
-  klass->set_mute = interface_as_function ## _set_mute;                         \
-  klass->set_record = interface_as_function ## _set_record;                     \
-  klass->set_option = interface_as_function ## _set_option;                     \
-  klass->get_option = interface_as_function ## _get_option;                     \
-  klass->get_mixer_flags = interface_as_function ## _get_mixer_flags;           \
-}
-
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsamixerelement.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,248 +0,0 @@
-/* ALSA mixer implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsamixerelement.h"
-#include "gstalsadeviceprobe.h"
-
-#define DEFAULT_PROP_DEVICE          "default"
-#define DEFAULT_PROP_DEVICE_NAME     ""
-
-enum
-{
-  PROP_0,
-  PROP_DEVICE,
-  PROP_DEVICE_NAME
-};
-
-static const GstElementDetails gst_alsa_mixer_element_details =
-GST_ELEMENT_DETAILS ("Alsa mixer",
-    "Generic/Audio",
-    "Control sound input and output levels with ALSA",
-    "Leif Johnson <leif@ambient.2y.net>");
-
-static void gst_alsa_mixer_element_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaMixerElement, gst_alsa_mixer_element,
-    GstElement, GST_TYPE_ELEMENT, gst_alsa_mixer_element_init_interfaces);
-
-/* massive macro that takes care of all the GstMixer stuff */
-GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaMixerElement, gst_alsa_mixer_element);
-
-static void gst_alsa_mixer_element_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-static void gst_alsa_mixer_element_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_alsa_mixer_element_finalize (GObject * object);
-
-static GstStateChangeReturn gst_alsa_mixer_element_change_state (GstElement
-    * element, GstStateChange transition);
-
-static gboolean
-gst_alsa_mixer_element_interface_supported (GstAlsaMixerElement * this,
-    GType interface_type)
-{
-  if (interface_type == GST_TYPE_MIXER) {
-    return gst_alsa_mixer_element_supported (this, interface_type);
-  }
-
-  g_return_val_if_reached (FALSE);
-}
-
-static void
-gst_implements_interface_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = (gpointer) gst_alsa_mixer_element_interface_supported;
-}
-
-static void
-gst_alsa_mixer_element_init_interfaces (GType type)
-{
-  static const GInterfaceInfo implements_iface_info = {
-    (GInterfaceInitFunc) gst_implements_interface_init,
-    NULL,
-    NULL,
-  };
-  static const GInterfaceInfo mixer_iface_info = {
-    (GInterfaceInitFunc) gst_alsa_mixer_element_interface_init,
-    NULL,
-    NULL,
-  };
-
-  g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
-      &implements_iface_info);
-  g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
-
-  gst_alsa_type_add_device_property_probe_interface (type);
-}
-
-static void
-gst_alsa_mixer_element_base_init (gpointer klass)
-{
-  gst_element_class_set_details (GST_ELEMENT_CLASS (klass),
-      &gst_alsa_mixer_element_details);
-}
-
-static void
-gst_alsa_mixer_element_class_init (GstAlsaMixerElementClass * klass)
-{
-  GstElementClass *element_class;
-  GObjectClass *gobject_class;
-
-  element_class = (GstElementClass *) klass;
-  gobject_class = (GObjectClass *) klass;
-
-  gobject_class->finalize = gst_alsa_mixer_element_finalize;
-  gobject_class->get_property = gst_alsa_mixer_element_get_property;
-  gobject_class->set_property = gst_alsa_mixer_element_set_property;
-
-  g_object_class_install_property (gobject_class, PROP_DEVICE,
-      g_param_spec_string ("device", "Device",
-          "ALSA device, as defined in an asound configuration file",
-          DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
-
-  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
-      g_param_spec_string ("device-name", "Device name",
-          "Human-readable name of the sound device",
-          DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE));
-
-  element_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_alsa_mixer_element_change_state);
-}
-
-static void
-gst_alsa_mixer_element_finalize (GObject * obj)
-{
-  GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (obj);
-
-  g_free (this->device);
-
-  G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_alsa_mixer_element_init (GstAlsaMixerElement * this,
-    GstAlsaMixerElementClass * klass)
-{
-  this->mixer = NULL;
-  this->device = g_strdup (DEFAULT_PROP_DEVICE);
-}
-
-static void
-gst_alsa_mixer_element_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:{
-      GST_OBJECT_LOCK (this);
-      g_free (this->device);
-      this->device = g_value_dup_string (value);
-      /* make sure we never set NULL, this is nice when we want to open the
-       * device. */
-      if (this->device == NULL)
-        this->device = g_strdup (DEFAULT_PROP_DEVICE);
-      GST_OBJECT_UNLOCK (this);
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_alsa_mixer_element_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:{
-      GST_OBJECT_LOCK (this);
-      g_value_set_string (value, this->device);
-      GST_OBJECT_UNLOCK (this);
-      break;
-    }
-    case PROP_DEVICE_NAME:{
-      GST_OBJECT_LOCK (this);
-      if (this->mixer) {
-        g_value_set_string (value, this->mixer->cardname);
-      } else {
-        g_value_set_string (value, NULL);
-      }
-      GST_OBJECT_UNLOCK (this);
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static GstStateChangeReturn
-gst_alsa_mixer_element_change_state (GstElement * element,
-    GstStateChange transition)
-{
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      if (!this->mixer) {
-        this->mixer = gst_alsa_mixer_new (this->device, GST_ALSA_MIXER_ALL);
-        if (!this->mixer)
-          goto open_failed;
-        _gst_alsa_mixer_set_interface (this->mixer, GST_MIXER (element));
-      }
-      break;
-    default:
-      break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      if (this->mixer) {
-        gst_alsa_mixer_free (this->mixer);
-        this->mixer = NULL;
-      }
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-
-  /* ERRORS */
-open_failed:
-  {
-    GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ_WRITE, (NULL),
-        ("Failed to open alsa mixer device '%s'", this->device));
-    return GST_STATE_CHANGE_FAILURE;
-  }
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixerelement.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* ALSA mixer interface implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_ELEMENT_H__
-#define __GST_ALSA_MIXER_ELEMENT_H__
-
-
-#include "gstalsa.h"
-#include "gstalsamixer.h"
-
-G_BEGIN_DECLS
-
-#define GST_ALSA_MIXER_ELEMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElement))
-#define GST_ALSA_MIXER_ELEMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElementClass))
-#define GST_IS_ALSA_MIXER_ELEMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_ELEMENT))
-#define GST_IS_ALSA_MIXER_ELEMENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_ELEMENT))
-#define GST_TYPE_ALSA_MIXER_ELEMENT             (gst_alsa_mixer_element_get_type())
-
-typedef struct _GstAlsaMixerElement GstAlsaMixerElement;
-typedef struct _GstAlsaMixerElementClass GstAlsaMixerElementClass;
-
-/**
- * GstAlsaMixerElement
- *
- * Opaque datastructure.
- */
-struct _GstAlsaMixerElement {
-  GstElement            parent;
-
-  GstAlsaMixer          *mixer;
-  gchar                 *device;
-};
-
-struct _GstAlsaMixerElementClass {
-  GstElementClass       parent;
-};
-
-
-GType           gst_alsa_mixer_element_get_type         (void);
-
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_ELEMENT_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsamixeroptions.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/* ALSA mixer object implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsamixeroptions.h"
-
-static void gst_alsa_mixer_options_init (GstAlsaMixerOptions * alsa_opts);
-static void gst_alsa_mixer_options_class_init (gpointer g_class,
-    gpointer class_data);
-
-static GstMixerOptionsClass *parent_class = NULL;
-
-GType
-gst_alsa_mixer_options_get_type (void)
-{
-  static GType opts_type = 0;
-
-  if (!opts_type) {
-    static const GTypeInfo opts_info = {
-      sizeof (GstAlsaMixerOptionsClass),
-      NULL,
-      NULL,
-      gst_alsa_mixer_options_class_init,
-      NULL,
-      NULL,
-      sizeof (GstAlsaMixerOptions),
-      0,
-      (GInstanceInitFunc) gst_alsa_mixer_options_init,
-    };
-
-    opts_type =
-        g_type_register_static (GST_TYPE_MIXER_OPTIONS, "GstAlsaMixerOptions",
-        &opts_info, 0);
-  }
-
-  return opts_type;
-}
-
-static void
-gst_alsa_mixer_options_class_init (gpointer g_class, gpointer class_data)
-{
-  parent_class = g_type_class_peek_parent (g_class);
-}
-
-static void
-gst_alsa_mixer_options_init (GstAlsaMixerOptions * alsa_opts)
-{
-}
-
-GstMixerOptions *
-gst_alsa_mixer_options_new (snd_mixer_elem_t * element, gint track_num)
-{
-  GstMixerOptions *opts;
-  GstAlsaMixerOptions *alsa_opts;
-  GstMixerTrack *track;
-  const gchar *label;
-  gint num, i;
-  gchar str[256];
-
-  label = snd_mixer_selem_get_name (element);
-
-  opts = g_object_new (GST_ALSA_MIXER_OPTIONS_TYPE,
-      "untranslated-label", label, NULL);
-  alsa_opts = (GstAlsaMixerOptions *) opts;
-  track = (GstMixerTrack *) opts;
-
-  /* set basic information */
-  track->label = g_strdup (label);      /* FIXME: translate this? */
-  track->num_channels = 0;
-  track->flags = 0;
-  alsa_opts->element = element;
-  alsa_opts->track_num = track_num;
-
-  /* get enumerations for switch/options object */
-  num = snd_mixer_selem_get_enum_items (element);
-  for (i = 0; i < num; i++) {
-    if (snd_mixer_selem_get_enum_item_name (element, i, 255, str) < 0) {
-      g_object_unref (G_OBJECT (alsa_opts));
-      return NULL;
-    }
-
-    opts->values = g_list_append (opts->values, g_strdup (str));
-  }
-
-  return opts;
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixeroptions.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* ALSA mixer options object.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_OPTIONS_H__
-#define __GST_ALSA_MIXER_OPTIONS_H__
-
-
-#include "gstalsa.h"
-#include <gst/interfaces/mixeroptions.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_ALSA_MIXER_OPTIONS_TYPE             (gst_alsa_mixer_options_get_type ())
-#define GST_ALSA_MIXER_OPTIONS(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_OPTIONS,GstAlsaMixerOptions))
-#define GST_ALSA_MIXER_OPTIONS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_OPTIONS,GstAlsaMixerOptionsClass))
-#define GST_IS_ALSA_MIXER_OPTIONS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_OPTIONS))
-#define GST_IS_ALSA_MIXER_OPTIONS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_OPTIONS))
-#define GST_TYPE_ALSA_MIXER_OPTIONS             (gst_alsa_mixer_options_get_type())
-
-
-typedef struct _GstAlsaMixerOptions GstAlsaMixerOptions;
-typedef struct _GstAlsaMixerOptionsClass GstAlsaMixerOptionsClass;
-
-
-struct _GstAlsaMixerOptions {
-  GstMixerOptions        parent;
-  snd_mixer_elem_t      *element; /* the ALSA mixer element for this track */
-  gint                  track_num;
-};
-
-struct _GstAlsaMixerOptionsClass {
-  GstMixerOptionsClass parent;
-};
-
-
-GType           gst_alsa_mixer_options_get_type (void);
-GstMixerOptions *gst_alsa_mixer_options_new     (snd_mixer_elem_t *     element,
-                                                 gint                   track_num);
-
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_OPTIONS_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsamixertrack.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/* ALSA mixer track implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst-i18n-plugin.h>
-
-#include "gstalsamixertrack.h"
-
-static void gst_alsa_mixer_track_init (GstAlsaMixerTrack * alsa_track);
-static void gst_alsa_mixer_track_class_init (gpointer g_class,
-    gpointer class_data);
-
-static GstMixerTrackClass *parent_class = NULL;
-
-GType
-gst_alsa_mixer_track_get_type (void)
-{
-  static GType track_type = 0;
-
-  if (!track_type) {
-    static const GTypeInfo track_info = {
-      sizeof (GstAlsaMixerTrackClass),
-      NULL,
-      NULL,
-      gst_alsa_mixer_track_class_init,
-      NULL,
-      NULL,
-      sizeof (GstAlsaMixerTrack),
-      0,
-      (GInstanceInitFunc) gst_alsa_mixer_track_init,
-      NULL
-    };
-
-    track_type =
-        g_type_register_static (GST_TYPE_MIXER_TRACK, "GstAlsaMixerTrack",
-        &track_info, 0);
-  }
-
-  return track_type;
-}
-
-static void
-gst_alsa_mixer_track_class_init (gpointer g_class, gpointer class_data)
-{
-  parent_class = g_type_class_peek_parent (g_class);
-}
-
-static void
-gst_alsa_mixer_track_init (GstAlsaMixerTrack * alsa_track)
-{
-}
-
-static void
-gst_alsa_mixer_track_update_alsa_capabilities (GstAlsaMixerTrack * alsa_track)
-{
-  alsa_track->alsa_flags = 0;
-  alsa_track->capture_group = -1;
-
-  if (snd_mixer_selem_has_common_volume (alsa_track->element))
-    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_VOLUME;
-
-  if (snd_mixer_selem_has_playback_volume (alsa_track->element))
-    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PVOLUME;
-
-  if (snd_mixer_selem_has_capture_volume (alsa_track->element))
-    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CVOLUME;
-
-  if (snd_mixer_selem_has_common_switch (alsa_track->element))
-    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_SWITCH;
-
-  if (snd_mixer_selem_has_playback_switch (alsa_track->element))
-    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PSWITCH;
-
-  if (snd_mixer_selem_has_capture_switch (alsa_track->element)) {
-    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH;
-
-    if (snd_mixer_selem_has_capture_switch_exclusive (alsa_track->element)) {
-      alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH_EXCL;
-      alsa_track->capture_group =
-          snd_mixer_selem_get_capture_group (alsa_track->element);
-    }
-  }
-
-  GST_LOG ("[%s] alsa_flags=0x%08x, capture_group=%d",
-      snd_mixer_selem_get_name (alsa_track->element),
-      alsa_track->alsa_flags, alsa_track->capture_group);
-}
-
-inline static gboolean
-alsa_track_has_cap (GstAlsaMixerTrack * alsa_track, guint32 flag)
-{
-  return ((alsa_track->alsa_flags & flag) != 0);
-}
-
-GstMixerTrack *
-gst_alsa_mixer_track_new (snd_mixer_elem_t * element,
-    gint num, gint track_num, gint flags, gboolean sw,
-    GstAlsaMixerTrack * shared_mute_track, gboolean append_capture)
-{
-  GstAlsaMixerTrack *alsa_track;
-  GstMixerTrack *track;
-  const gchar *name;
-  const gchar *label;
-  gint i;
-  long min = 0, max = 0;
-  const struct
-  {
-    const gchar orig[12];
-    const gchar trans[12];
-  } alsa_track_labels[] = {
-    {
-    "Master", N_("Master")}, {
-    "Bass", N_("Bass")}, {
-    "Treble", N_("Treble")}, {
-    "PCM", N_("PCM")}, {
-    "Synth", N_("Synth")}, {
-    "Line", N_("Line-in")}, {
-    "CD", N_("CD")}, {
-    "Mic", N_("Microphone")}, {
-    "PC Speaker", N_("PC Speaker")}, {
-    "Playback", N_("Playback")}, {
-    "Capture", N_("Capture")}
-  };
-
-  name = snd_mixer_selem_get_name (element);
-
-  GST_LOG ("[%s] num=%d,track_num=%d,flags=0x%08x,sw=%s,shared_mute_track=%p",
-      name, num, track_num, flags, (sw) ? "true" : "false", shared_mute_track);
-
-  track = (GstMixerTrack *) g_object_new (GST_ALSA_MIXER_TRACK_TYPE,
-      "untranslated-label", name, NULL);
-
-  alsa_track = (GstAlsaMixerTrack *) track;
-
-  GST_LOG ("[%s] created new mixer track %p", name, track);
-
-  /* This reflects the assumptions used for GstAlsaMixerTrack */
-  if (!(!!(flags & GST_MIXER_TRACK_OUTPUT) ^ !!(flags & GST_MIXER_TRACK_INPUT))) {
-    GST_ERROR ("Mixer track must be either output or input!");
-    g_return_val_if_reached (NULL);
-  }
-
-  track->flags = flags;
-  alsa_track->element = element;
-  alsa_track->shared_mute = shared_mute_track;
-  alsa_track->track_num = track_num;
-  alsa_track->alsa_channels = 0;
-
-  gst_alsa_mixer_track_update_alsa_capabilities (alsa_track);
-
-  if (flags & GST_MIXER_TRACK_OUTPUT) {
-    while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS &&
-        snd_mixer_selem_has_playback_channel (element,
-            alsa_track->alsa_channels)) {
-      alsa_track->alsa_channels++;
-    }
-    GST_LOG ("[%s] %d output channels", name, alsa_track->alsa_channels);
-  } else if (flags & GST_MIXER_TRACK_INPUT) {
-    while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS &&
-        snd_mixer_selem_has_capture_channel (element,
-            alsa_track->alsa_channels)) {
-      alsa_track->alsa_channels++;
-    }
-    GST_LOG ("[%s] %d input channels", name, alsa_track->alsa_channels);
-  } else {
-    g_assert_not_reached ();
-  }
-
-  if (sw)
-    track->num_channels = 0;
-  else
-    track->num_channels = alsa_track->alsa_channels;
-
-  /* translate the name if we can */
-  label = name;
-  for (i = 0; i < G_N_ELEMENTS (alsa_track_labels); ++i) {
-    if (g_utf8_collate (label, alsa_track_labels[i].orig) == 0) {
-      label = _(alsa_track_labels[i].trans);
-      break;
-    }
-  }
-
-  if (num == 0) {
-    track->label = g_strdup_printf ("%s%s%s", label,
-        append_capture ? " " : "", append_capture ? _("Capture") : "");
-  } else {
-    track->label = g_strdup_printf ("%s%s%s %d", label,
-        append_capture ? " " : "", append_capture ? _("Capture") : "", num);
-  }
-
-  /* set volume information */
-  if (track->num_channels > 0) {
-    if ((flags & GST_MIXER_TRACK_OUTPUT))
-      snd_mixer_selem_get_playback_volume_range (element, &min, &max);
-    else
-      snd_mixer_selem_get_capture_volume_range (element, &min, &max);
-  }
-  track->min_volume = (gint) min;
-  track->max_volume = (gint) max;
-
-  for (i = 0; i < track->num_channels; i++) {
-    long tmp = 0;
-
-    if (flags & GST_MIXER_TRACK_OUTPUT)
-      snd_mixer_selem_get_playback_volume (element, i, &tmp);
-    else
-      snd_mixer_selem_get_capture_volume (element, i, &tmp);
-
-    alsa_track->volumes[i] = (gint) tmp;
-  }
-
-  gst_alsa_mixer_track_update (alsa_track);
-
-  return track;
-}
-
-void
-gst_alsa_mixer_track_update (GstAlsaMixerTrack * alsa_track)
-{
-  GstMixerTrack *track = (GstMixerTrack *) alsa_track;
-  gint i;
-  gint audible = !(track->flags & GST_MIXER_TRACK_MUTE);
-
-  if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PVOLUME)) {
-    /* update playback volume */
-    for (i = 0; i < track->num_channels; i++) {
-      long vol = 0;
-
-      snd_mixer_selem_get_playback_volume (alsa_track->element, i, &vol);
-      alsa_track->volumes[i] = (gint) vol;
-    }
-  }
-
-  if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CVOLUME)) {
-    /* update capture volume */
-    for (i = 0; i < track->num_channels; i++) {
-      long vol = 0;
-
-      snd_mixer_selem_get_capture_volume (alsa_track->element, i, &vol);
-      alsa_track->volumes[i] = (gint) vol;
-    }
-  }
-
-  /* Any updates in flags? */
-  if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PSWITCH)) {
-    int v = 0;
-
-    audible = 0;
-    for (i = 0; i < alsa_track->alsa_channels; ++i) {
-      snd_mixer_selem_get_playback_switch (alsa_track->element, i, &v);
-      audible += v;
-    }
-
-  } else if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PVOLUME) &&
-      track->flags & GST_MIXER_TRACK_MUTE) {
-    /* check if user has raised volume with a parallel running application */
-
-    for (i = 0; i < track->num_channels; i++) {
-      long vol = 0;
-
-      snd_mixer_selem_get_playback_volume (alsa_track->element, i, &vol);
-
-      if (vol > track->min_volume) {
-        audible = 1;
-        break;
-      }
-    }
-  }
-
-  if (!!(audible) != !(track->flags & GST_MIXER_TRACK_MUTE)) {
-    if (audible) {
-      track->flags &= ~GST_MIXER_TRACK_MUTE;
-
-      if (alsa_track->shared_mute)
-        ((GstMixerTrack *) (alsa_track->shared_mute))->flags &=
-            ~GST_MIXER_TRACK_MUTE;
-    } else {
-      track->flags |= GST_MIXER_TRACK_MUTE;
-
-      if (alsa_track->shared_mute)
-        ((GstMixerTrack *) (alsa_track->shared_mute))->flags |=
-            GST_MIXER_TRACK_MUTE;
-    }
-  }
-
-  if (track->flags & GST_MIXER_TRACK_INPUT) {
-    gint recording = track->flags & GST_MIXER_TRACK_RECORD;
-
-    if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CSWITCH)) {
-      int v = 0;
-
-      recording = 0;
-      for (i = 0; i < alsa_track->alsa_channels; ++i) {
-        snd_mixer_selem_get_capture_switch (alsa_track->element, i, &v);
-        recording += v;
-      }
-
-    } else if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CVOLUME) &&
-        !(track->flags & GST_MIXER_TRACK_RECORD)) {
-      /* check if user has raised volume with a parallel running application */
-
-      for (i = 0; i < track->num_channels; i++) {
-        long vol = 0;
-
-        snd_mixer_selem_get_capture_volume (alsa_track->element, i, &vol);
-
-        if (vol > track->min_volume) {
-          recording = 1;
-          break;
-        }
-      }
-    }
-
-    if (recording)
-      track->flags |= GST_MIXER_TRACK_RECORD;
-    else
-      track->flags &= ~GST_MIXER_TRACK_RECORD;
-  }
-
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixertrack.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/* ALSA mixer track object.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_TRACK_H__
-#define __GST_ALSA_MIXER_TRACK_H__
-
-
-#include "gstalsa.h"
-#include <gst/interfaces/mixertrack.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_ALSA_MIXER_TRACK_TYPE               (gst_alsa_mixer_track_get_type ())
-#define GST_ALSA_MIXER_TRACK(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_TRACK,GstAlsaMixerTrack))
-#define GST_ALSA_MIXER_TRACK_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_TRACK,GstAlsaMixerTrackClass))
-#define GST_IS_ALSA_MIXER_TRACK(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_TRACK))
-#define GST_IS_ALSA_MIXER_TRACK_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_TRACK))
-#define GST_TYPE_ALSA_MIXER_TRACK               (gst_alsa_mixer_track_get_type())
-
-typedef struct _GstAlsaMixerTrack GstAlsaMixerTrack;
-typedef struct _GstAlsaMixerTrackClass GstAlsaMixerTrackClass;
-
-#define GST_ALSA_MIXER_TRACK_VOLUME         (1<<0)           /* common volume */
-#define GST_ALSA_MIXER_TRACK_PVOLUME        (1<<1)
-#define GST_ALSA_MIXER_TRACK_CVOLUME        (1<<2)
-#define GST_ALSA_MIXER_TRACK_SWITCH         (1<<3)           /* common switch */
-#define GST_ALSA_MIXER_TRACK_PSWITCH        (1<<4)
-#define GST_ALSA_MIXER_TRACK_CSWITCH        (1<<5)
-#define GST_ALSA_MIXER_TRACK_CSWITCH_EXCL   (1<<6)
-
-#define GST_ALSA_MAX_CHANNELS   (SND_MIXER_SCHN_LAST+1)
-
-struct _GstAlsaMixerTrack {
-  GstMixerTrack          parent;
-  snd_mixer_elem_t      *element;    /* the ALSA mixer element for this track */
-  GstAlsaMixerTrack     *shared_mute;  
-  gint                  track_num;
-  guint32               alsa_flags;                /* alsa track capabilities */
-  gint                  alsa_channels;  
-  gint                  capture_group;  
-  gint                  volumes[GST_ALSA_MAX_CHANNELS];
-};
-
-struct _GstAlsaMixerTrackClass {
-  GstMixerTrackClass parent;
-};
-
-GType           gst_alsa_mixer_track_get_type   (void);
-GstMixerTrack * gst_alsa_mixer_track_new        (snd_mixer_elem_t *     element,
-                                                 gint                   num,
-                                                 gint                   track_num,
-                                                 gint                   flags,
-                                                 gboolean               sw,  /* is simple switch? */
-                                                 GstAlsaMixerTrack *    shared_mute_track,
-                                                 gboolean               label_append_capture);
-void            gst_alsa_mixer_track_update      (GstAlsaMixerTrack * alsa_track);
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_TRACK_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsaplugin.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsasink.h"
-#include "gstalsasrc.h"
-#include "gstalsamixerelement.h"
-
-#include <gst/gst-i18n-plugin.h>
-
-GST_DEBUG_CATEGORY (alsa_debug);
-
-/* ALSA debugging wrapper */
-static void
-gst_alsa_error_wrapper (const char *file, int line, const char *function,
-    int err, const char *fmt, ...)
-{
-#ifndef GST_DISABLE_GST_DEBUG
-  va_list args;
-  gchar *str;
-
-  va_start (args, fmt);
-  str = g_strdup_vprintf (fmt, args);
-  va_end (args);
-  /* FIXME: use GST_LEVEL_ERROR here? Currently warning is used because we're 
-   * able to catch enough of the errors that would be printed otherwise
-   */
-  gst_debug_log (alsa_debug, GST_LEVEL_WARNING, file, function, line, NULL,
-      "alsalib error: %s%s%s", str, err ? ": " : "",
-      err ? snd_strerror (err) : "");
-  g_free (str);
-#endif
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  int err;
-
-  if (!gst_element_register (plugin, "alsamixer", GST_RANK_NONE,
-          GST_TYPE_ALSA_MIXER_ELEMENT))
-    return FALSE;
-  if (!gst_element_register (plugin, "alsasrc", GST_RANK_PRIMARY,
-          GST_TYPE_ALSA_SRC))
-    return FALSE;
-  if (!gst_element_register (plugin, "alsasink", GST_RANK_PRIMARY,
-          GST_TYPE_ALSA_SINK))
-    return FALSE;
-
-  GST_DEBUG_CATEGORY_INIT (alsa_debug, "alsa", 0, "alsa plugins");
-
-#if ENABLE_NLS
-  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
-      LOCALEDIR);
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif
-
-  err = snd_lib_error_set_handler (gst_alsa_error_wrapper);
-  if (err != 0)
-    GST_WARNING ("failed to set alsa error handler");
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "alsa",
-    "ALSA plugin library",
-    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/alsa/gstalsasink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,983 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * gstalsasink.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.
- */
-
-/**
- * SECTION:element-alsasink
- * @short_description: play audio to an ALSA device
- * @see_also: alsasrc, alsamixer
- *
- * <refsect2>
- * <para>
- * This element renders raw audio samples using the ALSA api.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * Play an Ogg/Vorbis file.
- * </para>
- * <programlisting>
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <alsa/asoundlib.h>
-
-#include "gstalsa.h"
-#include "gstalsasink.h"
-#include "gstalsadeviceprobe.h"
-
-#include <gst/gst-i18n-plugin.h>
-
-/* elementfactory information */
-static const GstElementDetails gst_alsasink_details =
-GST_ELEMENT_DETAILS ("Audio sink (ALSA)",
-    "Sink/Audio",
-    "Output to a sound card via ALSA",
-    "Wim Taymans <wim@fluendo.com>");
-
-#define DEFAULT_DEVICE		"default"
-#define DEFAULT_DEVICE_NAME	""
-#define SPDIF_PERIOD_SIZE 1536
-#define SPDIF_BUFFER_SIZE 15360
-
-enum
-{
-  PROP_0,
-  PROP_DEVICE,
-  PROP_DEVICE_NAME
-};
-
-static void gst_alsasink_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink,
-    GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces);
-
-static void gst_alsasink_finalise (GObject * object);
-static void gst_alsasink_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_alsasink_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink);
-
-static gboolean gst_alsasink_open (GstAudioSink * asink);
-static gboolean gst_alsasink_prepare (GstAudioSink * asink,
-    GstRingBufferSpec * spec);
-static gboolean gst_alsasink_unprepare (GstAudioSink * asink);
-static gboolean gst_alsasink_close (GstAudioSink * asink);
-static guint gst_alsasink_write (GstAudioSink * asink, gpointer data,
-    guint length);
-static guint gst_alsasink_delay (GstAudioSink * asink);
-static void gst_alsasink_reset (GstAudioSink * asink);
-
-static gint output_ref;         /* 0    */
-static snd_output_t *output;    /* NULL */
-static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
-
-
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-# define ALSA_SINK_FACTORY_ENDIANNESS	"LITTLE_ENDIAN, BIG_ENDIAN"
-#else
-# define ALSA_SINK_FACTORY_ENDIANNESS	"BIG_ENDIAN, LITTLE_ENDIAN"
-#endif
-
-static GstStaticPadTemplate alsasink_sink_factory =
-    GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 32, "
-        "depth = (int) 32, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 24, "
-        "depth = (int) 24, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 32, "
-        "depth = (int) 24, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 16, "
-        "depth = (int) 16, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 8, "
-        "depth = (int) 8, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
-        "audio/x-iec958")
-    );
-
-static void
-gst_alsasink_finalise (GObject * object)
-{
-  GstAlsaSink *sink = GST_ALSA_SINK (object);
-
-  g_free (sink->device);
-  g_mutex_free (sink->alsa_lock);
-
-  g_static_mutex_lock (&output_mutex);
-  --output_ref;
-  if (output_ref == 0) {
-    snd_output_close (output);
-    output = NULL;
-  }
-  g_static_mutex_unlock (&output_mutex);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_alsasink_init_interfaces (GType type)
-{
-  gst_alsa_type_add_device_property_probe_interface (type);
-}
-
-static void
-gst_alsasink_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_alsasink_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&alsasink_sink_factory));
-}
-static void
-gst_alsasink_class_init (GstAlsaSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSinkClass *gstbasesink_class;
-  GstBaseAudioSinkClass *gstbaseaudiosink_class;
-  GstAudioSinkClass *gstaudiosink_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesink_class = (GstBaseSinkClass *) klass;
-  gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
-  gstaudiosink_class = (GstAudioSinkClass *) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink_finalise);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink_get_property);
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink_set_property);
-
-  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps);
-
-  gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open);
-  gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare);
-  gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink_unprepare);
-  gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close);
-  gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write);
-  gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay);
-  gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset);
-
-  g_object_class_install_property (gobject_class, PROP_DEVICE,
-      g_param_spec_string ("device", "Device",
-          "ALSA device, as defined in an asound configuration file",
-          DEFAULT_DEVICE, G_PARAM_READWRITE));
-
-  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
-      g_param_spec_string ("device-name", "Device name",
-          "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
-          G_PARAM_READABLE));
-}
-
-static void
-gst_alsasink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstAlsaSink *sink;
-
-  sink = GST_ALSA_SINK (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      g_free (sink->device);
-      sink->device = g_value_dup_string (value);
-      /* setting NULL restores the default device */
-      if (sink->device == NULL) {
-        sink->device = g_strdup (DEFAULT_DEVICE);
-      }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_alsasink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstAlsaSink *sink;
-
-  sink = GST_ALSA_SINK (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      g_value_set_string (value, sink->device);
-      break;
-    case PROP_DEVICE_NAME:
-      g_value_take_string (value,
-          gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
-              sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class)
-{
-  GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
-
-  alsasink->device = g_strdup (DEFAULT_DEVICE);
-  alsasink->handle = NULL;
-  alsasink->cached_caps = NULL;
-  alsasink->alsa_lock = g_mutex_new ();
-
-  g_static_mutex_lock (&output_mutex);
-  if (output_ref == 0) {
-    snd_output_stdio_attach (&output, stdout, 0);
-    ++output_ref;
-  }
-  g_static_mutex_unlock (&output_mutex);
-}
-
-#define CHECK(call, error) \
-G_STMT_START {                  \
-if ((err = call) < 0)           \
-  goto error;                   \
-} G_STMT_END;
-
-static GstCaps *
-gst_alsasink_getcaps (GstBaseSink * bsink)
-{
-  GstElementClass *element_class;
-  GstPadTemplate *pad_template;
-  GstAlsaSink *sink = GST_ALSA_SINK (bsink);
-  GstCaps *caps;
-
-  if (sink->handle == NULL) {
-    GST_DEBUG_OBJECT (sink, "device not open, using template caps");
-    return NULL;                /* base class will get template caps for us */
-  }
-
-  if (sink->cached_caps) {
-    GST_LOG_OBJECT (sink, "Returning cached caps");
-    return gst_caps_ref (sink->cached_caps);
-  }
-
-  element_class = GST_ELEMENT_GET_CLASS (sink);
-  pad_template = gst_element_class_get_pad_template (element_class, "sink");
-  g_return_val_if_fail (pad_template != NULL, NULL);
-
-  caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
-      gst_pad_template_get_caps (pad_template));
-
-  if (caps) {
-    sink->cached_caps = gst_caps_ref (caps);
-  }
-
-  GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
-
-  return caps;
-}
-
-static int
-set_hwparams (GstAlsaSink * alsa)
-{
-  guint rrate;
-  gint err, dir;
-  snd_pcm_hw_params_t *params;
-  guint period_time, buffer_time;
-
-  snd_pcm_hw_params_malloc (&params);
-
-  GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
-      "SPDIF (%d)", alsa->channels, alsa->rate,
-      snd_pcm_format_name (alsa->format), alsa->iec958);
-
-  /* start with requested values, if we cannot configure alsa for those values,
-   * we set these values to -1, which will leave the default alsa values */
-  buffer_time = alsa->buffer_time;
-  period_time = alsa->period_time;
-
-retry:
-  /* choose all parameters */
-  CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
-  /* set the interleaved read/write format */
-  CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
-      wrong_access);
-  /* set the sample format */
-  if (alsa->iec958) {
-    /* Try to use big endian first else fallback to le and swap bytes */
-    if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
-      alsa->format = SND_PCM_FORMAT_S16_LE;
-      alsa->need_swap = TRUE;
-      GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
-    } else {
-      alsa->need_swap = FALSE;
-    }
-  }
-  CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
-      no_sample_format);
-  /* set the count of channels */
-  CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
-      no_channels);
-  /* set the stream rate */
-  rrate = alsa->rate;
-  CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
-      no_rate);
-  if (rrate != alsa->rate)
-    goto rate_match;
-
-  /* get and dump some limits */
-  {
-    guint min, max;
-
-    snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
-    snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
-
-    GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
-        alsa->buffer_time, min, max);
-
-    snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
-    snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
-
-    GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
-        alsa->period_time, min, max);
-
-    snd_pcm_hw_params_get_periods_min (params, &min, &dir);
-    snd_pcm_hw_params_get_periods_max (params, &max, &dir);
-
-    GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
-  }
-
-  /* now try to configure the buffer time and period time, if one
-   * of those fail, we fall back to the defaults and emit a warning. */
-  if (buffer_time != -1 && !alsa->iec958) {
-    /* set the buffer time */
-    if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
-                &buffer_time, &dir)) < 0) {
-      GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
-          ("Unable to set buffer time %i for playback: %s",
-              buffer_time, snd_strerror (err)));
-      /* disable buffer_time the next round */
-      buffer_time = -1;
-      goto retry;
-    }
-    GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
-  }
-  if (period_time != -1 && !alsa->iec958) {
-    /* set the period time */
-    if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
-                &period_time, &dir)) < 0) {
-      GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
-          ("Unable to set period time %i for playback: %s",
-              period_time, snd_strerror (err)));
-      /* disable period_time the next round */
-      period_time = -1;
-      goto retry;
-    }
-    GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
-  }
-
-  /* Set buffer size and period size manually for SPDIF */
-  if (G_UNLIKELY (alsa->iec958)) {
-    snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
-    snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
-
-    CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
-            &buffer_size), buffer_size);
-    CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
-            &period_size, NULL), period_size);
-  }
-
-  /* write the parameters to device */
-  CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
-
-  /* now get the configured values */
-  CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
-      buffer_size);
-  CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
-      period_size);
-
-  GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
-      alsa->period_size);
-
-  snd_pcm_hw_params_free (params);
-  return 0;
-
-  /* ERRORS */
-no_config:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Broken configuration for playback: no configurations available: %s",
-            snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-wrong_access:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Access type not available for playback: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-no_sample_format:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Sample format not available for playback: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-no_channels:
-  {
-    gchar *msg = NULL;
-
-    if ((alsa->channels) == 1)
-      msg = g_strdup (_("Could not open device for playback in mono mode."));
-    if ((alsa->channels) == 2)
-      msg = g_strdup (_("Could not open device for playback in stereo mode."));
-    if ((alsa->channels) > 2)
-      msg =
-          g_strdup_printf (_
-          ("Could not open device for playback in %d-channel mode."),
-          alsa->channels);
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
-    g_free (msg);
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-no_rate:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Rate %iHz not available for playback: %s",
-            alsa->rate, snd_strerror (err)));
-    return err;
-  }
-rate_match:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
-    snd_pcm_hw_params_free (params);
-    return -EINVAL;
-  }
-buffer_size:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to get buffer size for playback: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-period_size:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to get period size for playback: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-set_hw_params:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set hw params for playback: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-}
-
-static int
-set_swparams (GstAlsaSink * alsa)
-{
-  int err;
-  snd_pcm_sw_params_t *params;
-
-  snd_pcm_sw_params_malloc (&params);
-
-  /* get the current swparams */
-  CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
-  /* start the transfer when the buffer is almost full: */
-  /* (buffer_size / avail_min) * avail_min */
-  CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
-          (alsa->buffer_size / alsa->period_size) * alsa->period_size),
-      start_threshold);
-
-  /* allow the transfer when at least period_size samples can be processed */
-  CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
-          alsa->period_size), set_avail);
-
-#if GST_CHECK_ALSA_VERSION(1,0,16)
-  /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
-#else
-  /* align all transfers to 1 sample */
-  CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
-#endif
-
-  /* write the parameters to the playback device */
-  CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
-
-  snd_pcm_sw_params_free (params);
-  return 0;
-
-  /* ERRORS */
-no_config:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to determine current swparams for playback: %s",
-            snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-start_threshold:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set start threshold mode for playback: %s",
-            snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-set_avail:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set avail min for playback: %s", snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-#if !GST_CHECK_ALSA_VERSION(1,0,16)
-set_align:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set transfer align for playback: %s", snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-#endif
-set_sw_params:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set sw params for playback: %s", snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-}
-
-static gboolean
-alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec)
-{
-  /* Initialize our boolean */
-  alsa->iec958 = FALSE;
-
-  switch (spec->type) {
-    case GST_BUFTYPE_LINEAR:
-      GST_DEBUG_OBJECT (alsa,
-          "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
-          spec->width, spec->sign, spec->bigend);
-
-      alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
-          spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
-      break;
-    case GST_BUFTYPE_FLOAT:
-      switch (spec->format) {
-        case GST_FLOAT32_LE:
-          alsa->format = SND_PCM_FORMAT_FLOAT_LE;
-          break;
-        case GST_FLOAT32_BE:
-          alsa->format = SND_PCM_FORMAT_FLOAT_BE;
-          break;
-        case GST_FLOAT64_LE:
-          alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
-          break;
-        case GST_FLOAT64_BE:
-          alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
-          break;
-        default:
-          goto error;
-      }
-      break;
-    case GST_BUFTYPE_A_LAW:
-      alsa->format = SND_PCM_FORMAT_A_LAW;
-      break;
-    case GST_BUFTYPE_MU_LAW:
-      alsa->format = SND_PCM_FORMAT_MU_LAW;
-      break;
-    case GST_BUFTYPE_IEC958:
-      alsa->format = SND_PCM_FORMAT_S16_BE;
-      alsa->iec958 = TRUE;
-      break;
-    default:
-      goto error;
-
-  }
-  alsa->rate = spec->rate;
-  alsa->channels = spec->channels;
-  alsa->buffer_time = spec->buffer_time;
-  alsa->period_time = spec->latency_time;
-  alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
-
-  return TRUE;
-
-  /* ERRORS */
-error:
-  {
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasink_open (GstAudioSink * asink)
-{
-  GstAlsaSink *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SINK (asink);
-
-  CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
-          SND_PCM_NONBLOCK), open_error);
-  GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
-
-  return TRUE;
-
-  /* ERRORS */
-open_error:
-  {
-    if (err == -EBUSY) {
-      GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
-          (_("Could not open audio device for playback. "
-                  "Device is being used by another application.")),
-          ("Device '%s' is busy", alsa->device));
-    } else {
-      GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
-          (_("Could not open audio device for playback.")),
-          ("Playback open error on device '%s': %s", alsa->device,
-              snd_strerror (err)));
-    }
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
-{
-  GstAlsaSink *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SINK (asink);
-
-  if (spec->format == GST_IEC958) {
-    snd_pcm_close (alsa->handle);
-    alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
-    if (G_UNLIKELY (!alsa->handle)) {
-      goto no_iec958;
-    }
-  }
-
-  if (!alsasink_parse_spec (alsa, spec))
-    goto spec_parse;
-
-  CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
-
-  CHECK (set_hwparams (alsa), hw_params_failed);
-  CHECK (set_swparams (alsa), sw_params_failed);
-
-  alsa->bytes_per_sample = spec->bytes_per_sample;
-  spec->segsize = alsa->period_size * spec->bytes_per_sample;
-  spec->segtotal = alsa->buffer_size / alsa->period_size;
-
-  {
-    snd_output_t *out_buf = NULL;
-    char *msg = NULL;
-
-    snd_output_buffer_open (&out_buf);
-    snd_pcm_dump_hw_setup (alsa->handle, out_buf);
-    snd_output_buffer_string (out_buf, &msg);
-    GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
-    snd_output_close (out_buf);
-    snd_output_buffer_open (&out_buf);
-    snd_pcm_dump_sw_setup (alsa->handle, out_buf);
-    snd_output_buffer_string (out_buf, &msg);
-    GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
-    snd_output_close (out_buf);
-  }
-
-  return TRUE;
-
-  /* ERRORS */
-no_iec958:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
-        ("Could not open IEC958 (SPDIF) device for playback"));
-    return FALSE;
-  }
-spec_parse:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Error parsing spec"));
-    return FALSE;
-  }
-non_block:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not set device to blocking: %s", snd_strerror (err)));
-    return FALSE;
-  }
-hw_params_failed:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Setting of hwparams failed: %s", snd_strerror (err)));
-    return FALSE;
-  }
-sw_params_failed:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Setting of swparams failed: %s", snd_strerror (err)));
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasink_unprepare (GstAudioSink * asink)
-{
-  GstAlsaSink *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SINK (asink);
-
-  CHECK (snd_pcm_drop (alsa->handle), drop);
-
-  CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
-
-  CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
-
-  return TRUE;
-
-  /* ERRORS */
-drop:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not drop samples: %s", snd_strerror (err)));
-    return FALSE;
-  }
-hw_free:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not free hw params: %s", snd_strerror (err)));
-    return FALSE;
-  }
-non_block:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not set device to nonblocking: %s", snd_strerror (err)));
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasink_close (GstAudioSink * asink)
-{
-  GstAlsaSink *alsa = GST_ALSA_SINK (asink);
-  gint err;
-
-  if (alsa->handle) {
-    CHECK (snd_pcm_close (alsa->handle), close_error);
-    alsa->handle = NULL;
-  }
-  gst_caps_replace (&alsa->cached_caps, NULL);
-
-  return TRUE;
-
-  /* ERRORS */
-close_error:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
-        ("Playback close error: %s", snd_strerror (err)));
-    return FALSE;
-  }
-}
-
-
-/*
- *   Underrun and suspend recovery
- */
-static gint
-xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
-{
-  GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
-
-  if (err == -EPIPE) {          /* under-run */
-    err = snd_pcm_prepare (handle);
-    if (err < 0)
-      GST_WARNING_OBJECT (alsa,
-          "Can't recovery from underrun, prepare failed: %s",
-          snd_strerror (err));
-    return 0;
-  } else if (err == -ESTRPIPE) {
-    while ((err = snd_pcm_resume (handle)) == -EAGAIN)
-      g_usleep (100);           /* wait until the suspend flag is released */
-
-    if (err < 0) {
-      err = snd_pcm_prepare (handle);
-      if (err < 0)
-        GST_WARNING_OBJECT (alsa,
-            "Can't recovery from suspend, prepare failed: %s",
-            snd_strerror (err));
-    }
-    return 0;
-  }
-  return err;
-}
-
-static guint
-gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
-{
-  GstAlsaSink *alsa;
-  gint err;
-  gint cptr;
-  gint16 *ptr = data;
-
-  alsa = GST_ALSA_SINK (asink);
-
-  if (alsa->iec958 && alsa->need_swap) {
-    guint i;
-
-    GST_DEBUG_OBJECT (asink, "swapping bytes");
-    for (i = 0; i < length / 2; i++) {
-      ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
-    }
-  }
-
-  GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
-
-  cptr = length / alsa->bytes_per_sample;
-
-  GST_ALSA_SINK_LOCK (asink);
-  while (cptr > 0) {
-    err = snd_pcm_writei (alsa->handle, ptr, cptr);
-
-    GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
-    if (err < 0) {
-      GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
-      if (err == -EAGAIN) {
-        continue;
-      } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
-        goto write_error;
-      }
-      continue;
-    }
-
-    ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
-    cptr -= err;
-  }
-  GST_ALSA_SINK_UNLOCK (asink);
-
-  return length - (cptr * alsa->bytes_per_sample);
-
-write_error:
-  {
-    GST_ALSA_SINK_UNLOCK (asink);
-    return length;              /* skip one period */
-  }
-}
-
-static guint
-gst_alsasink_delay (GstAudioSink * asink)
-{
-  GstAlsaSink *alsa;
-  snd_pcm_sframes_t delay;
-  int res;
-
-  alsa = GST_ALSA_SINK (asink);
-
-  res = snd_pcm_delay (alsa->handle, &delay);
-  if (G_UNLIKELY (res < 0)) {
-    /* on errors, report 0 delay */
-    GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
-    delay = 0;
-  }
-  if (G_UNLIKELY (delay < 0)) {
-    /* make sure we never return a negative delay */
-    GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
-    delay = 0;
-  }
-
-  return delay;
-}
-
-static void
-gst_alsasink_reset (GstAudioSink * asink)
-{
-  GstAlsaSink *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SINK (asink);
-
-  GST_ALSA_SINK_LOCK (asink);
-  GST_DEBUG_OBJECT (alsa, "drop");
-  CHECK (snd_pcm_drop (alsa->handle), drop_error);
-  GST_DEBUG_OBJECT (alsa, "prepare");
-  CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
-  GST_DEBUG_OBJECT (alsa, "reset done");
-  GST_ALSA_SINK_UNLOCK (asink);
-
-  return;
-
-  /* ERRORS */
-drop_error:
-  {
-    GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
-        snd_strerror (err));
-    GST_ALSA_SINK_UNLOCK (asink);
-    return;
-  }
-prepare_error:
-  {
-    GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
-        snd_strerror (err));
-    GST_ALSA_SINK_UNLOCK (asink);
-    return;
-  }
-}
--- a/gst_plugins_base/ext/alsa/gstalsasink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* GStreamer
- * Copyright (C)  2005 Wim Taymans <wim@fluendo.com>
- *
- * gstalsasink.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_ALSASINK_H__
-#define __GST_ALSASINK_H__
-
-#include <gst/gst.h>
-#include <gst/audio/gstaudiosink.h>
-#include <alsa/asoundlib.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_ALSA_SINK            (gst_alsasink_get_type())
-#define GST_ALSA_SINK(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SINK,GstAlsaSink))
-#define GST_ALSA_SINK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SINK,GstAlsaSinkClass))
-#define GST_IS_ALSA_SINK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SINK))
-#define GST_IS_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SINK))
-#define GST_ALSA_SINK_CAST(obj)       ((GstAlsaSink *) (obj))
-
-typedef struct _GstAlsaSink GstAlsaSink;
-typedef struct _GstAlsaSinkClass GstAlsaSinkClass;
-
-#define GST_ALSA_SINK_GET_LOCK(obj)	(GST_ALSA_SINK_CAST (obj)->alsa_lock)
-#define GST_ALSA_SINK_LOCK(obj)	        (g_mutex_lock (GST_ALSA_SINK_GET_LOCK (obj)))
-#define GST_ALSA_SINK_UNLOCK(obj)	(g_mutex_unlock (GST_ALSA_SINK_GET_LOCK (obj)))
-
-/**
- * GstAlsaSink:
- *
- * Opaque data structure
- */
-struct _GstAlsaSink {
-  GstAudioSink    sink;
-
-  gchar                 *device;
-
-  snd_pcm_t             *handle;
-  snd_pcm_hw_params_t   *hwparams;
-  snd_pcm_sw_params_t   *swparams;
-
-  snd_pcm_access_t access;
-  snd_pcm_format_t format;
-  guint rate;
-  guint channels;
-  gint bytes_per_sample;
-  gboolean iec958;
-  gboolean need_swap;
-
-  guint buffer_time;
-  guint period_time;
-  snd_pcm_uframes_t buffer_size;
-  snd_pcm_uframes_t period_size;
-
-  GstCaps *cached_caps;
-
-  GMutex *alsa_lock;
-};
-
-struct _GstAlsaSinkClass {
-  GstAudioSinkClass parent_class;
-};
-
-GType gst_alsasink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_ALSASINK_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsasrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,881 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- *
- * gstalsasrc.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.
- */
-
-/**
- * SECTION:element-alsasrc
- * @short_description: capture audio from an alsa device
- * @see_also: alsasink, alsamixer
- *
- * <refsect2>
- * <para>
- * This element reads data from an audio card using the ALSA API.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * Record from a sound card using ALSA and encode to Ogg/Vorbis.
- * </para>
- * <programlisting>
- * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <alsa/asoundlib.h>
-
-#include "gstalsasrc.h"
-#include "gstalsadeviceprobe.h"
-
-#include <gst/gst-i18n-plugin.h>
-
-/* elementfactory information */
-static const GstElementDetails gst_alsasrc_details =
-GST_ELEMENT_DETAILS ("Audio source (ALSA)",
-    "Source/Audio",
-    "Read from a sound card via ALSA",
-    "Wim Taymans <wim@fluendo.com>");
-
-#define DEFAULT_PROP_DEVICE		"default"
-#define DEFAULT_PROP_DEVICE_NAME	""
-
-enum
-{
-  PROP_0,
-  PROP_DEVICE,
-  PROP_DEVICE_NAME,
-};
-
-static void gst_alsasrc_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
-    GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces);
-
-GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
-
-static void gst_alsasrc_finalize (GObject * object);
-static void gst_alsasrc_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_alsasrc_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
-
-static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
-static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
-    GstRingBufferSpec * spec);
-static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
-static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
-static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
-static guint gst_alsasrc_delay (GstAudioSrc * asrc);
-static void gst_alsasrc_reset (GstAudioSrc * asrc);
-
-/* AlsaSrc signals and args */
-enum
-{
-  LAST_SIGNAL
-};
-
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-# define ALSA_SRC_FACTORY_ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
-#else
-# define ALSA_SRC_FACTORY_ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
-#endif
-
-static GstStaticPadTemplate alsasrc_src_factory =
-    GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 32, "
-        "depth = (int) 32, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 32, "
-        "depth = (int) 24, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 24, "
-        "depth = (int) 24, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 16, "
-        "depth = (int) 16, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 8, "
-        "depth = (int) 8, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
-    );
-
-static void
-gst_alsasrc_finalize (GObject * object)
-{
-  GstAlsaSrc *src = GST_ALSA_SRC (object);
-
-  g_free (src->device);
-  g_mutex_free (src->alsa_lock);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type)
-{
-  /* only support this one interface (wrapped by GstImplementsInterface) */
-  g_assert (interface_type == GST_TYPE_MIXER);
-
-  return gst_alsasrc_mixer_supported (this, interface_type);
-}
-
-static void
-gst_implements_interface_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = (gpointer) gst_alsasrc_interface_supported;
-}
-
-static void
-gst_alsasrc_init_interfaces (GType type)
-{
-  static const GInterfaceInfo implements_iface_info = {
-    (GInterfaceInitFunc) gst_implements_interface_init,
-    NULL,
-    NULL,
-  };
-  static const GInterfaceInfo mixer_iface_info = {
-    (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init,
-    NULL,
-    NULL,
-  };
-
-  g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
-      &implements_iface_info);
-  g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
-
-  gst_alsa_type_add_device_property_probe_interface (type);
-}
-
-static void
-gst_alsasrc_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_alsasrc_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&alsasrc_src_factory));
-}
-
-static void
-gst_alsasrc_class_init (GstAlsaSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
-  GstBaseAudioSrcClass *gstbaseaudiosrc_class;
-  GstAudioSrcClass *gstaudiosrc_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesrc_class = (GstBaseSrcClass *) klass;
-  gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
-  gstaudiosrc_class = (GstAudioSrcClass *) klass;
-
-  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasrc_finalize);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
-
-  gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
-
-  gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
-  gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
-  gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
-  gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
-  gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
-  gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
-  gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
-
-  g_object_class_install_property (gobject_class, PROP_DEVICE,
-      g_param_spec_string ("device", "Device",
-          "ALSA device, as defined in an asound configuration file",
-          DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
-
-  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
-      g_param_spec_string ("device-name", "Device name",
-          "Human-readable name of the sound device",
-          DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE));
-}
-
-static void
-gst_alsasrc_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstAlsaSrc *src;
-
-  src = GST_ALSA_SRC (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      g_free (src->device);
-      src->device = g_value_dup_string (value);
-      if (src->device == NULL) {
-        src->device = g_strdup (DEFAULT_PROP_DEVICE);
-      }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_alsasrc_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstAlsaSrc *src;
-
-  src = GST_ALSA_SRC (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      g_value_set_string (value, src->device);
-      break;
-    case PROP_DEVICE_NAME:
-      g_value_take_string (value,
-          gst_alsa_find_device_name (GST_OBJECT_CAST (src),
-              src->device, src->handle, SND_PCM_STREAM_CAPTURE));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
-{
-  GST_DEBUG_OBJECT (alsasrc, "initializing");
-
-  alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
-  alsasrc->cached_caps = NULL;
-
-  alsasrc->alsa_lock = g_mutex_new ();
-}
-
-#define CHECK(call, error) \
-G_STMT_START {                  \
-if ((err = call) < 0)           \
-  goto error;                   \
-} G_STMT_END;
-
-
-static GstCaps *
-gst_alsasrc_getcaps (GstBaseSrc * bsrc)
-{
-  GstElementClass *element_class;
-  GstPadTemplate *pad_template;
-  GstAlsaSrc *src;
-  GstCaps *caps;
-
-  src = GST_ALSA_SRC (bsrc);
-
-  if (src->handle == NULL) {
-    GST_DEBUG_OBJECT (src, "device not open, using template caps");
-    return NULL;                /* base class will get template caps for us */
-  }
-
-  if (src->cached_caps) {
-    GST_LOG_OBJECT (src, "Returning cached caps");
-    return gst_caps_ref (src->cached_caps);
-  }
-
-  element_class = GST_ELEMENT_GET_CLASS (src);
-  pad_template = gst_element_class_get_pad_template (element_class, "src");
-  g_return_val_if_fail (pad_template != NULL, NULL);
-
-  caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
-      gst_pad_template_get_caps (pad_template));
-
-  if (caps) {
-    src->cached_caps = gst_caps_ref (caps);
-  }
-
-  GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
-
-  return caps;
-}
-
-static int
-set_hwparams (GstAlsaSrc * alsa)
-{
-  guint rrate;
-  gint err, dir;
-  snd_pcm_hw_params_t *params;
-
-  snd_pcm_hw_params_malloc (&params);
-
-  /* choose all parameters */
-  CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
-  /* set the interleaved read/write format */
-  CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
-      wrong_access);
-  /* set the sample format */
-  CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
-      no_sample_format);
-  /* set the count of channels */
-  CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
-      no_channels);
-  /* set the stream rate */
-  rrate = alsa->rate;
-  CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
-      no_rate);
-  if (rrate != alsa->rate)
-    goto rate_match;
-
-  if (alsa->buffer_time != -1) {
-    /* set the buffer time */
-    CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
-            &alsa->buffer_time, &dir), buffer_time);
-  }
-  if (alsa->period_time != -1) {
-    /* set the period time */
-    CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
-            &alsa->period_time, &dir), period_time);
-  }
-
-  /* write the parameters to device */
-  CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
-
-  CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
-      buffer_size);
-
-  CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
-      period_size);
-
-  snd_pcm_hw_params_free (params);
-  return 0;
-
-  /* ERRORS */
-no_config:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Broken configuration for recording: no configurations available: %s",
-            snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-wrong_access:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Access type not available for recording: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-no_sample_format:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Sample format not available for recording: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-no_channels:
-  {
-    gchar *msg = NULL;
-
-    if ((alsa->channels) == 1)
-      msg = g_strdup (_("Could not open device for recording in mono mode."));
-    if ((alsa->channels) == 2)
-      msg = g_strdup (_("Could not open device for recording in stereo mode."));
-    if ((alsa->channels) > 2)
-      msg =
-          g_strdup_printf (_
-          ("Could not open device for recording in %d-channel mode"),
-          alsa->channels);
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
-    g_free (msg);
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-no_rate:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Rate %iHz not available for recording: %s",
-            alsa->rate, snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-rate_match:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
-    snd_pcm_hw_params_free (params);
-    return -EINVAL;
-  }
-buffer_time:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set buffer time %i for recording: %s",
-            alsa->buffer_time, snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-buffer_size:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to get buffer size for recording: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-period_time:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set period time %i for recording: %s", alsa->period_time,
-            snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-period_size:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to get period size for recording: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-set_hw_params:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set hw params for recording: %s", snd_strerror (err)));
-    snd_pcm_hw_params_free (params);
-    return err;
-  }
-}
-
-static int
-set_swparams (GstAlsaSrc * alsa)
-{
-  int err;
-  snd_pcm_sw_params_t *params;
-
-  snd_pcm_sw_params_malloc (&params);
-
-  /* get the current swparams */
-  CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
-  /* allow the transfer when at least period_size samples can be processed */
-  CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
-          alsa->period_size), set_avail);
-  /* start the transfer on first read */
-  CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
-          0), start_threshold);
-
-#if GST_CHECK_ALSA_VERSION(1,0,16)
-  /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
-#else
-  /* align all transfers to 1 sample */
-  CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
-#endif
-
-  /* write the parameters to the recording device */
-  CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
-
-  snd_pcm_sw_params_free (params);
-  return 0;
-
-  /* ERRORS */
-no_config:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to determine current swparams for playback: %s",
-            snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-start_threshold:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set start threshold mode for playback: %s",
-            snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-set_avail:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set avail min for playback: %s", snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-#if !GST_CHECK_ALSA_VERSION(1,0,16)
-set_align:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set transfer align for playback: %s", snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-#endif
-set_sw_params:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Unable to set sw params for playback: %s", snd_strerror (err)));
-    snd_pcm_sw_params_free (params);
-    return err;
-  }
-}
-
-static gboolean
-alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
-{
-  switch (spec->type) {
-    case GST_BUFTYPE_LINEAR:
-      alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
-          spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
-      break;
-    case GST_BUFTYPE_FLOAT:
-      switch (spec->format) {
-        case GST_FLOAT32_LE:
-          alsa->format = SND_PCM_FORMAT_FLOAT_LE;
-          break;
-        case GST_FLOAT32_BE:
-          alsa->format = SND_PCM_FORMAT_FLOAT_BE;
-          break;
-        case GST_FLOAT64_LE:
-          alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
-          break;
-        case GST_FLOAT64_BE:
-          alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
-          break;
-        default:
-          goto error;
-      }
-      break;
-    case GST_BUFTYPE_A_LAW:
-      alsa->format = SND_PCM_FORMAT_A_LAW;
-      break;
-    case GST_BUFTYPE_MU_LAW:
-      alsa->format = SND_PCM_FORMAT_MU_LAW;
-      break;
-    default:
-      goto error;
-
-  }
-  alsa->rate = spec->rate;
-  alsa->channels = spec->channels;
-  alsa->buffer_time = spec->buffer_time;
-  alsa->period_time = spec->latency_time;
-  alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
-
-  return TRUE;
-
-  /* ERRORS */
-error:
-  {
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasrc_open (GstAudioSrc * asrc)
-{
-  GstAlsaSrc *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SRC (asrc);
-
-  CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
-          SND_PCM_NONBLOCK), open_error);
-
-  if (!alsa->mixer)
-    alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE);
-
-  return TRUE;
-
-  /* ERRORS */
-open_error:
-  {
-    if (err == -EBUSY) {
-      GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
-          (_("Could not open audio device for recording. "
-                  "Device is being used by another application.")),
-          ("Device '%s' is busy", alsa->device));
-    } else {
-      GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
-          (_("Could not open audio device for recording.")),
-          ("Recording open error on device '%s': %s", alsa->device,
-              snd_strerror (err)));
-    }
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
-{
-  GstAlsaSrc *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SRC (asrc);
-
-  if (!alsasrc_parse_spec (alsa, spec))
-    goto spec_parse;
-
-  CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
-
-  CHECK (set_hwparams (alsa), hw_params_failed);
-  CHECK (set_swparams (alsa), sw_params_failed);
-  CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
-
-  alsa->bytes_per_sample = spec->bytes_per_sample;
-  spec->segsize = alsa->period_size * spec->bytes_per_sample;
-  spec->segtotal = alsa->buffer_size / alsa->period_size;
-  spec->silence_sample[0] = 0;
-  spec->silence_sample[1] = 0;
-  spec->silence_sample[2] = 0;
-  spec->silence_sample[3] = 0;
-
-  return TRUE;
-
-  /* ERRORS */
-spec_parse:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Error parsing spec"));
-    return FALSE;
-  }
-non_block:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not set device to blocking: %s", snd_strerror (err)));
-    return FALSE;
-  }
-hw_params_failed:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Setting of hwparams failed: %s", snd_strerror (err)));
-    return FALSE;
-  }
-sw_params_failed:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Setting of swparams failed: %s", snd_strerror (err)));
-    return FALSE;
-  }
-prepare_failed:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Prepare failed: %s", snd_strerror (err)));
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasrc_unprepare (GstAudioSrc * asrc)
-{
-  GstAlsaSrc *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SRC (asrc);
-
-  CHECK (snd_pcm_drop (alsa->handle), drop);
-
-  CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
-
-  CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
-
-  return TRUE;
-
-  /* ERRORS */
-drop:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not drop samples: %s", snd_strerror (err)));
-    return FALSE;
-  }
-hw_free:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not free hw params: %s", snd_strerror (err)));
-    return FALSE;
-  }
-non_block:
-  {
-    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
-        ("Could not set device to nonblocking: %s", snd_strerror (err)));
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_alsasrc_close (GstAudioSrc * asrc)
-{
-  GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
-
-  snd_pcm_close (alsa->handle);
-
-  if (alsa->mixer) {
-    gst_alsa_mixer_free (alsa->mixer);
-    alsa->mixer = NULL;
-  }
-
-  gst_caps_replace (&alsa->cached_caps, NULL);
-
-  return TRUE;
-}
-
-/*
- *   Underrun and suspend recovery
- */
-static gint
-xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
-{
-  GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
-
-  if (err == -EPIPE) {          /* under-run */
-    err = snd_pcm_prepare (handle);
-    if (err < 0)
-      GST_WARNING_OBJECT (alsa,
-          "Can't recovery from underrun, prepare failed: %s",
-          snd_strerror (err));
-    return 0;
-  } else if (err == -ESTRPIPE) {
-    while ((err = snd_pcm_resume (handle)) == -EAGAIN)
-      g_usleep (100);           /* wait until the suspend flag is released */
-
-    if (err < 0) {
-      err = snd_pcm_prepare (handle);
-      if (err < 0)
-        GST_WARNING_OBJECT (alsa,
-            "Can't recovery from suspend, prepare failed: %s",
-            snd_strerror (err));
-    }
-    return 0;
-  }
-  return err;
-}
-
-static guint
-gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
-{
-  GstAlsaSrc *alsa;
-  gint err;
-  gint cptr;
-  gint16 *ptr;
-
-  alsa = GST_ALSA_SRC (asrc);
-
-  cptr = length / alsa->bytes_per_sample;
-  ptr = data;
-
-  GST_ALSA_SRC_LOCK (asrc);
-  while (cptr > 0) {
-    if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) {
-      if (err == -EAGAIN) {
-        GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
-        continue;
-      } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
-        goto read_error;
-      }
-      continue;
-    }
-
-    ptr += err * alsa->channels;
-    cptr -= err;
-  }
-  GST_ALSA_SRC_UNLOCK (asrc);
-
-  return length - cptr;
-
-read_error:
-  {
-    GST_ALSA_SRC_UNLOCK (asrc);
-    return length;              /* skip one period */
-  }
-}
-
-static guint
-gst_alsasrc_delay (GstAudioSrc * asrc)
-{
-  GstAlsaSrc *alsa;
-  snd_pcm_sframes_t delay;
-  int res;
-
-  alsa = GST_ALSA_SRC (asrc);
-
-  res = snd_pcm_delay (alsa->handle, &delay);
-  if (G_UNLIKELY (res < 0)) {
-    GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
-    delay = 0;
-  }
-
-  return CLAMP (delay, 0, alsa->buffer_size);
-}
-
-static void
-gst_alsasrc_reset (GstAudioSrc * asrc)
-{
-  GstAlsaSrc *alsa;
-  gint err;
-
-  alsa = GST_ALSA_SRC (asrc);
-
-  GST_ALSA_SRC_LOCK (asrc);
-  GST_DEBUG_OBJECT (alsa, "drop");
-  CHECK (snd_pcm_drop (alsa->handle), drop_error);
-  GST_DEBUG_OBJECT (alsa, "prepare");
-  CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
-  GST_DEBUG_OBJECT (alsa, "reset done");
-  GST_ALSA_SRC_UNLOCK (asrc);
-
-  return;
-
-  /* ERRORS */
-drop_error:
-  {
-    GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
-        snd_strerror (err));
-    GST_ALSA_SRC_UNLOCK (asrc);
-    return;
-  }
-prepare_error:
-  {
-    GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
-        snd_strerror (err));
-    GST_ALSA_SRC_UNLOCK (asrc);
-    return;
-  }
-}
--- a/gst_plugins_base/ext/alsa/gstalsasrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* GStreamer
- * Copyright (C)  2005 Wim Taymans <wim@fluendo.com>
- *
- * gstalsasrc.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_ALSASRC_H__
-#define __GST_ALSASRC_H__
-
-#include <gst/audio/gstaudiosrc.h>
-#include "gstalsa.h"
-#include "gstalsamixer.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_ALSA_SRC            (gst_alsasrc_get_type())
-#define GST_ALSA_SRC(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SRC,GstAlsaSrc))
-#define GST_ALSA_SRC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SRC,GstAlsaSrcClass))
-#define GST_IS_ALSA_SRC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SRC))
-#define GST_IS_ALSA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SRC))
-#define GST_ALSA_SRC_CAST(obj)       ((GstAlsaSrc *)(obj))
-
-#define GST_ALSA_SRC_GET_LOCK(obj)  (GST_ALSA_SRC_CAST (obj)->alsa_lock)
-#define GST_ALSA_SRC_LOCK(obj)      (g_mutex_lock (GST_ALSA_SRC_GET_LOCK (obj)))
-#define GST_ALSA_SRC_UNLOCK(obj)    (g_mutex_unlock (GST_ALSA_SRC_GET_LOCK (obj)))
-
-typedef struct _GstAlsaSrc GstAlsaSrc;
-typedef struct _GstAlsaSrcClass GstAlsaSrcClass;
-
-/**
- * GstAlsaSrc:
- *
- * Opaque data structure
- */
-struct _GstAlsaSrc {
-  GstAudioSrc           src;
-
-  gchar                 *device;
-
-  snd_pcm_t             *handle;
-  snd_pcm_hw_params_t   *hwparams;
-  snd_pcm_sw_params_t   *swparams;
-
-  GstCaps               *cached_caps;
-
-  snd_pcm_access_t      access;
-  snd_pcm_format_t      format;
-  guint                 rate;
-  guint                 channels;
-  gint                  bytes_per_sample;
-
-  guint                 buffer_time;
-  guint                 period_time;
-  snd_pcm_uframes_t     buffer_size;
-  snd_pcm_uframes_t     period_size;
-
-  GstAlsaMixer          *mixer;
-
-  GMutex                *alsa_lock;
-};
-
-struct _GstAlsaSrcClass {
-  GstAudioSrcClass parent_class;
-};
-
-GType gst_alsasrc_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_ALSASRC_H__ */
--- a/gst_plugins_base/ext/cdparanoia/gstcdparanoiasrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *               <2005> Wim Taymans <wim@fluendo.com>
- *               <2005> Tim-Philipp Müller <tim centricular net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <errno.h>
-
-#include "gstcdparanoiasrc.h"
-#include "gst/gst-i18n-plugin.h"
-
-enum
-{
-  TRANSPORT_ERROR,
-  UNCORRECTED_ERROR,
-  NUM_SIGNALS
-};
-
-enum
-{
-  PROP_0,
-  PROP_READ_SPEED,
-  PROP_PARANOIA_MODE,
-  PROP_SEARCH_OVERLAP,
-  PROP_GENERIC_DEVICE
-};
-
-#define DEFAULT_READ_SPEED              -1
-#define DEFAULT_SEARCH_OVERLAP          -1
-#define DEFAULT_PARANOIA_MODE            PARANOIA_MODE_FRAGMENT
-#define DEFAULT_GENERIC_DEVICE           NULL
-
-GST_DEBUG_CATEGORY_STATIC (gst_cd_paranoia_src_debug);
-#define GST_CAT_DEFAULT gst_cd_paranoia_src_debug
-
-GST_BOILERPLATE (GstCdParanoiaSrc, gst_cd_paranoia_src, GstCddaBaseSrc,
-    GST_TYPE_CDDA_BASE_SRC);
-
-static void gst_cd_paranoia_src_finalize (GObject * obj);
-static void gst_cd_paranoia_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void gst_cd_paranoia_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static GstBuffer *gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * src,
-    gint sector);
-static gboolean gst_cd_paranoia_src_open (GstCddaBaseSrc * src,
-    const gchar * device);
-static void gst_cd_paranoia_src_close (GstCddaBaseSrc * src);
-
-static const GstElementDetails cdparanoia_details =
-GST_ELEMENT_DETAILS ("CD Audio (cdda) Source, Paranoia IV",
-    "Source/File",
-    "Read audio from CD in paranoid mode",
-    "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
-
-/* We use these to serialize calls to paranoia_read() among several
- * cdparanoiasrc instances. We do this because it's the only reasonably
- * easy way to find out the calling object from within the paranoia
- * callback, and we need the object instance in there to emit our signals */
-static GstCdParanoiaSrc *cur_cb_source;
-static GStaticMutex cur_cb_mutex = G_STATIC_MUTEX_INIT;
-
-static gint cdpsrc_signals[NUM_SIGNALS];        /* all 0 */
-
-#define GST_TYPE_CD_PARANOIA_MODE (gst_cd_paranoia_mode_get_type())
-static GType
-gst_cd_paranoia_mode_get_type (void)
-{
-  static const GFlagsValue paranoia_modes[] = {
-    {PARANOIA_MODE_DISABLE, "PARANOIA_MODE_DISABLE", "disable"},
-    {PARANOIA_MODE_FRAGMENT, "PARANOIA_MODE_FRAGMENT", "fragment"},
-    {PARANOIA_MODE_OVERLAP, "PARANOIA_MODE_OVERLAP", "overlap"},
-    {PARANOIA_MODE_SCRATCH, "PARANOIA_MODE_SCRATCH", "scratch"},
-    {PARANOIA_MODE_REPAIR, "PARANOIA_MODE_REPAIR", "repair"},
-    {PARANOIA_MODE_FULL, "PARANOIA_MODE_FULL", "full"},
-    {0, NULL, NULL},
-  };
-
-  static GType type;            /* 0 */
-
-  if (!type) {
-    type = g_flags_register_static ("GstCdParanoiaMode", paranoia_modes);
-  }
-
-  return type;
-}
-
-static void
-gst_cd_paranoia_src_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &cdparanoia_details);
-}
-
-static void
-gst_cd_paranoia_src_init (GstCdParanoiaSrc * src, GstCdParanoiaSrcClass * klass)
-{
-  src->d = NULL;
-  src->p = NULL;
-  src->next_sector = -1;
-
-  src->search_overlap = DEFAULT_SEARCH_OVERLAP;
-  src->paranoia_mode = DEFAULT_PARANOIA_MODE;
-  src->read_speed = DEFAULT_READ_SPEED;
-  src->generic_device = g_strdup (DEFAULT_GENERIC_DEVICE);
-}
-
-static void
-gst_cd_paranoia_src_class_init (GstCdParanoiaSrcClass * klass)
-{
-  GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  gobject_class->set_property = gst_cd_paranoia_src_set_property;
-  gobject_class->get_property = gst_cd_paranoia_src_get_property;
-  gobject_class->finalize = gst_cd_paranoia_src_finalize;
-
-  cddabasesrc_class->open = gst_cd_paranoia_src_open;
-  cddabasesrc_class->close = gst_cd_paranoia_src_close;
-  cddabasesrc_class->read_sector = gst_cd_paranoia_src_read_sector;
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GENERIC_DEVICE,
-      g_param_spec_string ("generic-device", "Generic device",
-          "Use specified generic scsi device", DEFAULT_GENERIC_DEVICE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED,
-      g_param_spec_int ("read-speed", "Read speed",
-          "Read from device at specified speed", -1, G_MAXINT,
-          DEFAULT_READ_SPEED, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PARANOIA_MODE,
-      g_param_spec_flags ("paranoia-mode", "Paranoia mode",
-          "Type of checking to perform", GST_TYPE_CD_PARANOIA_MODE,
-          DEFAULT_PARANOIA_MODE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH_OVERLAP,
-      g_param_spec_int ("search-overlap", "Search overlap",
-          "Force minimum overlap search during verification to n sectors", -1,
-          75, DEFAULT_SEARCH_OVERLAP, G_PARAM_READWRITE));
-
-  /* FIXME: we don't really want signals for this, but messages on the bus,
-   * but then we can't check any longer whether anyone is interested in them */
-  cdpsrc_signals[TRANSPORT_ERROR] =
-      g_signal_new ("transport-error", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstCdParanoiaSrcClass, transport_error),
-      NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
-  cdpsrc_signals[UNCORRECTED_ERROR] =
-      g_signal_new ("uncorrected-error", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstCdParanoiaSrcClass, uncorrected_error),
-      NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
-}
-
-static gboolean
-gst_cd_paranoia_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
-{
-  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc);
-  gint i;
-
-  GST_DEBUG_OBJECT (src, "trying to open device %s (generic-device=%s) ...",
-      device, GST_STR_NULL (src->generic_device));
-
-  /* find the device */
-  if (src->generic_device != NULL) {
-    src->d = cdda_identify_scsi (src->generic_device, device, FALSE, NULL);
-  } else {
-    if (device != NULL) {
-      src->d = cdda_identify (device, FALSE, NULL);
-    } else {
-      src->d = cdda_identify ("/dev/cdrom", FALSE, NULL);
-    }
-  }
-
-  /* fail if the device couldn't be found */
-  if (src->d == NULL)
-    goto no_device;
-
-  /* set verbosity mode */
-  cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
-
-  /* open the disc */
-  if (cdda_open (src->d))
-    goto open_failed;
-
-  if (src->read_speed != -1) {
-    cdda_speed_set (src->d, src->read_speed);
-  }
-
-  for (i = 1; i < src->d->tracks + 1; i++) {
-    GstCddaBaseSrcTrack track = { 0, };
-
-    track.num = i;
-    track.is_audio = IS_AUDIO (src->d, i - 1);
-    track.start = cdda_track_firstsector (src->d, i);
-    track.end = cdda_track_lastsector (src->d, i);
-    track.tags = NULL;
-
-    gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track);
-  }
-
-  /* create the paranoia struct and set it up */
-  src->p = paranoia_init (src->d);
-  if (src->p == NULL)
-    goto init_failed;
-
-  paranoia_modeset (src->p, src->paranoia_mode);
-
-  if (src->search_overlap != -1)
-    paranoia_overlapset (src->p, src->search_overlap);
-
-  src->next_sector = -1;
-
-  return TRUE;
-
-  /* ERRORS */
-no_device:
-  {
-    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
-        (_("Could not open CD device for reading.")), ("cdda_identify failed"));
-    return FALSE;
-  }
-open_failed:
-  {
-    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
-        (_("Could not open CD device for reading.")), ("cdda_open failed"));
-    cdda_close (src->d);
-    src->d = NULL;
-    return FALSE;
-  }
-init_failed:
-  {
-    GST_ELEMENT_ERROR (src, LIBRARY, INIT,
-        ("failed to initialize paranoia"), ("failed to initialize paranoia"));
-    return FALSE;
-  }
-}
-
-static void
-gst_cd_paranoia_src_close (GstCddaBaseSrc * cddabasesrc)
-{
-  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc);
-
-  if (src->p) {
-    paranoia_free (src->p);
-    src->p = NULL;
-  }
-
-  if (src->d) {
-    cdda_close (src->d);
-    src->d = NULL;
-  }
-
-  src->next_sector = -1;
-}
-
-static void
-gst_cd_paranoia_dummy_callback (long inpos, int function)
-{
-  /* Used by instanced where no one is interested what's happening here */
-}
-
-static void
-gst_cd_paranoia_paranoia_callback (long inpos, int function)
-{
-  GstCdParanoiaSrc *src = cur_cb_source;
-  gint sector = (gint) (inpos / CD_FRAMEWORDS);
-
-  switch (function) {
-    case PARANOIA_CB_SKIP:
-      GST_INFO_OBJECT (src, "Skip at sector %d", sector);
-      g_signal_emit (src, cdpsrc_signals[UNCORRECTED_ERROR], 0, sector);
-      break;
-    case PARANOIA_CB_READERR:
-      GST_INFO_OBJECT (src, "Transport error at sector %d", sector);
-      g_signal_emit (src, cdpsrc_signals[TRANSPORT_ERROR], 0, sector);
-      break;
-    default:
-      break;
-  }
-}
-
-static gboolean
-gst_cd_paranoia_src_signal_is_being_watched (GstCdParanoiaSrc * src, gint sig)
-{
-  return g_signal_has_handler_pending (src, cdpsrc_signals[sig], 0, FALSE);
-}
-
-static GstBuffer *
-gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
-{
-  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc);
-  GstBuffer *buf;
-  gboolean do_serialize;
-  gint16 *cdda_buf;
-
-#if 0
-  /* Do we really need to output this? (tpm) */
-  /* Due to possible autocorrections of start sectors of audio tracks on 
-   * multisession cds, we can maybe not compute the correct discid.
-   * So issue a warning.
-   * See cdparanoia/interface/common-interface.c:FixupTOC */
-  if (src->d && src->d->cd_extra) {
-    g_message
-        ("DiscID on multisession discs might be broken. Use at own risk.");
-  }
-#endif
-
-  if (src->next_sector == -1 || src->next_sector != sector) {
-    if (paranoia_seek (src->p, sector, SEEK_SET) == -1)
-      goto seek_failed;
-
-    GST_DEBUG_OBJECT (src, "successfully seeked to sector %d", sector);
-    src->next_sector = sector;
-  }
-
-  do_serialize =
-      gst_cd_paranoia_src_signal_is_being_watched (src, TRANSPORT_ERROR) ||
-      gst_cd_paranoia_src_signal_is_being_watched (src, UNCORRECTED_ERROR);
-
-  if (do_serialize) {
-    GST_LOG_OBJECT (src, "Signal handlers connected, serialising access");
-    g_static_mutex_lock (&cur_cb_mutex);
-    GST_LOG_OBJECT (src, "Got lock");
-    cur_cb_source = src;
-
-    cdda_buf = paranoia_read (src->p, gst_cd_paranoia_paranoia_callback);
-
-    cur_cb_source = NULL;
-    GST_LOG_OBJECT (src, "Releasing lock");
-    g_static_mutex_unlock (&cur_cb_mutex);
-  } else {
-    cdda_buf = paranoia_read (src->p, gst_cd_paranoia_dummy_callback);
-  }
-
-  if (cdda_buf == NULL)
-    goto read_failed;
-
-  buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW);
-  memcpy (GST_BUFFER_DATA (buf), cdda_buf, CD_FRAMESIZE_RAW);
-
-  /* cdda base class will take care of timestamping etc. */
-  ++src->next_sector;
-
-  return buf;
-
-  /* ERRORS */
-seek_failed:
-  {
-    GST_WARNING_OBJECT (src, "seek to sector %d failed!", sector);
-    GST_ELEMENT_ERROR (src, RESOURCE, SEEK,
-        (_("Could not seek CD.")),
-        ("paranoia_seek to %d failed: %s", sector, g_strerror (errno)));
-    return NULL;
-  }
-read_failed:
-  {
-    GST_WARNING_OBJECT (src, "read at sector %d failed!", sector);
-    GST_ELEMENT_ERROR (src, RESOURCE, READ,
-        (_("Could not read CD.")),
-        ("paranoia_read at %d failed: %s", sector, g_strerror (errno)));
-    return NULL;
-  }
-}
-
-static void
-gst_cd_paranoia_src_finalize (GObject * obj)
-{
-  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (obj);
-
-  g_free (src->generic_device);
-
-  G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_cd_paranoia_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object);
-
-  GST_OBJECT_LOCK (src);
-
-  switch (prop_id) {
-    case PROP_GENERIC_DEVICE:{
-      g_free (src->generic_device);
-      src->generic_device = g_value_dup_string (value);
-      if (src->generic_device && src->generic_device[0] == '\0') {
-        g_free (src->generic_device);
-        src->generic_device = NULL;
-      }
-      break;
-    }
-    case PROP_READ_SPEED:{
-      src->read_speed = g_value_get_int (value);
-      if (src->read_speed == 0)
-        src->read_speed = -1;
-      break;
-    }
-    case PROP_PARANOIA_MODE:{
-      src->paranoia_mode = g_value_get_flags (value) & PARANOIA_MODE_FULL;
-      break;
-    }
-    case PROP_SEARCH_OVERLAP:{
-      src->search_overlap = g_value_get_int (value);
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  GST_OBJECT_UNLOCK (src);
-}
-
-static void
-gst_cd_paranoia_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object);
-
-  GST_OBJECT_LOCK (src);
-
-  switch (prop_id) {
-    case PROP_READ_SPEED:
-      g_value_set_int (value, src->read_speed);
-      break;
-    case PROP_PARANOIA_MODE:
-      g_value_set_flags (value, src->paranoia_mode);
-      break;
-    case PROP_GENERIC_DEVICE:
-      g_value_set_string (value, src->generic_device);
-      break;
-    case PROP_SEARCH_OVERLAP:
-      g_value_set_int (value, src->search_overlap);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  GST_OBJECT_UNLOCK (src);
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (gst_cd_paranoia_src_debug, "cdparanoiasrc", 0,
-      "CD Paranoia Source");
-
-  if (!gst_element_register (plugin, "cdparanoiasrc", GST_RANK_SECONDARY,
-          GST_TYPE_CD_PARANOIA_SRC))
-    return FALSE;
-
-#ifdef ENABLE_NLS
-  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
-      LOCALEDIR);
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif
-
-
-  return TRUE;
-}
-
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "cdparanoia",
-    "Read audio from CD in paranoid mode",
-    plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/cdparanoia/gstcdparanoiasrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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_CD_PARANOIA_SRC_H__
-#define __GST_CD_PARANOIA_SRC_H__
-
-#include "gst/cdda/gstcddabasesrc.h"
-
-G_BEGIN_DECLS
-
-#define size16 gint16
-#define size32 gint32
-
-#ifdef CDPARANOIA_HEADERS_IN_DIR
-  #include <cdda/cdda_interface.h>
-  #include <cdda/cdda_paranoia.h>
-#else
-  #include <cdda_interface.h>
-  #include <cdda_paranoia.h>
-#endif
-
-#define GST_TYPE_CD_PARANOIA_SRC            (gst_cd_paranoia_src_get_type())
-#define GST_CD_PARANOIA_SRC(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrc))
-#define GST_CD_PARANOIA_SRC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrcClass))
-#define GST_IS_CD_PARANOIA_SRC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CD_PARANOIA_SRC))
-#define GST_IS_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CD_PARANOIA_SRC))
-#define GST_CD_PARANOIA_SRC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASAE_SRC, GstCdParanoiaSrcClass))
-
-typedef struct _GstCdParanoiaSrc GstCdParanoiaSrc;
-typedef struct _GstCdParanoiaSrcClass GstCdParanoiaSrcClass;
-
-/**
- * GstCdParanoiaSrc:
- *
- * The cdparanoia object structure.
- */
-struct _GstCdParanoiaSrc {
-  GstCddaBaseSrc   cddabasesrc;
-
-  /*< private >*/
-  cdrom_drive     *d;
-  cdrom_paranoia  *p;
-
-  gint             next_sector; /* -1 or next sector we expect to
-                                 * read, so we know when to do a seek */
-
-  gint             paranoia_mode;
-  gint             read_speed;
-  gint             search_overlap;
-
-  gchar           *generic_device;
-};
-
-struct _GstCdParanoiaSrcClass {
-  GstCddaBaseSrcClass parent_class;
-
-  /* signal callbacks */
-  /**
-   * GstCdParanoiaSrcClass::transport-error:
-   * @src: the GstCddaBaseSrc source element object
-   * @sector: the sector at which the error happened
-   *
-   * This signal is emitted when a sector could not be read
-   * because of a transport error.
-   */
-  void (*transport_error)	(GstCdParanoiaSrc * src, gint sector);
-  /**
-   * GstCdParanoiaSrcClass::uncorrected-error:
-   * @src: the GstCddaBaseSrc source element object
-   * @sector: the sector at which the error happened
-   *
-   * This signal is emitted when a sector could not be read
-   * because of a transport error.
-   */
-  void (*uncorrected_error)	(GstCdParanoiaSrc * src, gint sector);
-};
-
-GType    gst_cd_paranoia_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_CD_PARANOIA_SRC_H__ */
-
--- a/gst_plugins_base/ext/gio/gstgio.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstgio.h"
-#include "gstgiosink.h"
-#include "gstgiosrc.h"
-#include "gstgiostreamsink.h"
-#include "gstgiostreamsrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_debug);
-#define GST_CAT_DEFAULT gst_gio_debug
-
-/* @func_name: Name of the GIO function, for debugging messages.
- * @err: Error location.  *err may be NULL, but err must be non-NULL.
- * @ret: Flow return location.  May be NULL.  Is set to either #GST_FLOW_ERROR
- * or #GST_FLOW_WRONG_STATE.
- *
- * Returns: TRUE to indicate a handled error.  Error at given location err will
- * be freed and *err will be set to NULL.  A FALSE return indicates an unhandled
- * error: The err location is unchanged and guaranteed to be != NULL.  ret, if
- * given, is set to GST_FLOW_ERROR.
- */
-gboolean
-gst_gio_error (gpointer element, const gchar * func_name, GError ** err,
-    GstFlowReturn * ret)
-{
-  gboolean handled = TRUE;
-
-  if (ret)
-    *ret = GST_FLOW_ERROR;
-
-  if (GST_GIO_ERROR_MATCHES (*err, CANCELLED)) {
-    GST_DEBUG_OBJECT (element, "blocking I/O call cancelled (%s)", func_name);
-    if (ret)
-      *ret = GST_FLOW_WRONG_STATE;
-  } else if (*err != NULL) {
-    handled = FALSE;
-  } else {
-    GST_ELEMENT_ERROR (element, LIBRARY, FAILED, (NULL),
-        ("%s call failed without error set", func_name));
-  }
-
-  if (handled)
-    g_clear_error (err);
-
-  return handled;
-}
-
-GstFlowReturn
-gst_gio_seek (gpointer element, GSeekable * stream, guint64 offset,
-    GCancellable * cancel)
-{
-  gboolean success;
-  GstFlowReturn ret;
-  GError *err = NULL;
-
-  GST_LOG_OBJECT (element, "seeking to offset %" G_GINT64_FORMAT, offset);
-
-  success = g_seekable_seek (stream, offset, G_SEEK_SET, cancel, &err);
-
-  if (success)
-    ret = GST_FLOW_OK;
-  else if (!gst_gio_error (element, "g_seekable_seek", &err, &ret)) {
-    GST_ELEMENT_ERROR (element, RESOURCE, SEEK, (NULL),
-        ("Could not seek: %s", err->message));
-    g_clear_error (&err);
-  }
-
-  return ret;
-}
-
-static gchar **
-gst_gio_get_supported_protocols (void)
-{
-  return g_strdupv ((gchar **)
-      g_vfs_get_supported_uri_schemes (g_vfs_get_default ()));
-}
-
-static GstURIType
-gst_gio_uri_handler_get_type_sink (void)
-{
-  return GST_URI_SINK;
-}
-
-static GstURIType
-gst_gio_uri_handler_get_type_src (void)
-{
-  return GST_URI_SRC;
-}
-
-static gchar **
-gst_gio_uri_handler_get_protocols (void)
-{
-  static gchar **protocols = NULL;
-
-  if (!protocols)
-    protocols = gst_gio_get_supported_protocols ();
-
-  return protocols;
-}
-
-static const gchar *
-gst_gio_uri_handler_get_uri (GstURIHandler * handler)
-{
-  GstElement *element = GST_ELEMENT (handler);
-  const gchar *uri;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
-  g_object_get (G_OBJECT (element), "location", &uri, NULL);
-
-  return uri;
-}
-
-static gboolean
-gst_gio_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
-{
-  GstElement *element = GST_ELEMENT (handler);
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  if (GST_STATE (element) == GST_STATE_PLAYING ||
-      GST_STATE (element) == GST_STATE_PAUSED)
-    return FALSE;
-
-  g_object_set (G_OBJECT (element), "location", uri, NULL);
-
-  return TRUE;
-}
-
-static void
-gst_gio_uri_handler_init (gpointer g_iface, gpointer iface_data)
-{
-  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
-  gboolean sink = GPOINTER_TO_INT (iface_data); /* See in do_init below. */
-
-  if (sink)
-    iface->get_type = gst_gio_uri_handler_get_type_sink;
-  else
-    iface->get_type = gst_gio_uri_handler_get_type_src;
-  iface->get_protocols = gst_gio_uri_handler_get_protocols;
-  iface->get_uri = gst_gio_uri_handler_get_uri;
-  iface->set_uri = gst_gio_uri_handler_set_uri;
-}
-
-void
-gst_gio_uri_handler_do_init (GType type)
-{
-  GInterfaceInfo uri_handler_info = {
-    gst_gio_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  /* Store information for uri_handler_init to use for distinguishing the
-   * element types.  This lets us use a single interface implementation for both
-   * classes. */
-  uri_handler_info.interface_data = GINT_TO_POINTER (g_type_is_a (type,
-          GST_TYPE_BASE_SINK));
-
-  g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_handler_info);
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  gboolean ret = TRUE;
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_debug, "gio", 0, "GIO elements");
-
-  /* FIXME: Rank is MARGINAL for now, should be at least SECONDARY+1 in the future
-   * to replace gnomevfssink/src. For testing purposes PRIMARY+1 one makes sense
-   * so it gets autoplugged and preferred over filesrc/sink. */
-
-  ret &= gst_element_register (plugin, "giosink", GST_RANK_MARGINAL,
-      GST_TYPE_GIO_SINK);
-
-  ret &= gst_element_register (plugin, "giosrc", GST_RANK_MARGINAL,
-      GST_TYPE_GIO_SRC);
-
-  ret &= gst_element_register (plugin, "giostreamsink", GST_RANK_NONE,
-      GST_TYPE_GIO_STREAM_SINK);
-
-  ret &= gst_element_register (plugin, "giostreamsrc", GST_RANK_NONE,
-      GST_TYPE_GIO_STREAM_SRC);
-
-  return ret;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "gio",
-    "GIO elements", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
-    GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/gio/gstgio.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_H__
-#define __GST_GIO_H__
-
-#include <gio/gio.h>
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_GIO_ERROR_MATCHES(err, code) g_error_matches (err, G_IO_ERROR, G_IO_ERROR_##code)
-
-#define GST_GIO_STREAM_IS_SEEKABLE(stream) (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)))
-
-gboolean gst_gio_error (gpointer element, const gchar *func_name,
-    GError **err, GstFlowReturn *ret);
-GstFlowReturn gst_gio_seek (gpointer element, GSeekable *stream, guint64 offset,
-    GCancellable *cancel);
-void gst_gio_uri_handler_do_init (GType type);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_H__ */
--- a/gst_plugins_base/ext/gio/gstgiobasesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiobasesink.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_base_sink_debug);
-#define GST_CAT_DEFAULT gst_gio_base_sink_debug
-
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS_ANY);
-
-GST_BOILERPLATE (GstGioBaseSink, gst_gio_base_sink, GstBaseSink,
-    GST_TYPE_BASE_SINK);
-
-static void gst_gio_base_sink_finalize (GObject * object);
-static gboolean gst_gio_base_sink_start (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_stop (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_unlock (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_unlock_stop (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_event (GstBaseSink * base_sink,
-    GstEvent * event);
-static GstFlowReturn gst_gio_base_sink_render (GstBaseSink * base_sink,
-    GstBuffer * buffer);
-static gboolean gst_gio_base_sink_query (GstPad * pad, GstQuery * query);
-
-static void
-gst_gio_base_sink_base_init (gpointer gclass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_base_sink_debug, "gio_base_sink", 0,
-      "GIO base sink");
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory));
-}
-
-static void
-gst_gio_base_sink_class_init (GstGioBaseSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSinkClass *gstbasesink_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesink_class = (GstBaseSinkClass *) klass;
-
-  gobject_class->finalize = gst_gio_base_sink_finalize;
-
-  gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_sink_start);
-  gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_sink_stop);
-  gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_sink_unlock);
-  gstbasesink_class->unlock_stop =
-      GST_DEBUG_FUNCPTR (gst_gio_base_sink_unlock_stop);
-  gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_gio_base_sink_event);
-  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_gio_base_sink_render);
-}
-
-static void
-gst_gio_base_sink_init (GstGioBaseSink * sink, GstGioBaseSinkClass * gclass)
-{
-  gst_pad_set_query_function (GST_BASE_SINK_PAD (sink),
-      GST_DEBUG_FUNCPTR (gst_gio_base_sink_query));
-
-  gst_base_sink_set_sync (GST_BASE_SINK (sink), FALSE);
-
-  sink->cancel = g_cancellable_new ();
-}
-
-static void
-gst_gio_base_sink_finalize (GObject * object)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (object);
-
-  if (sink->cancel) {
-    g_object_unref (sink->cancel);
-    sink->cancel = NULL;
-  }
-
-  if (sink->stream) {
-    g_object_unref (sink->stream);
-    sink->stream = NULL;
-  }
-
-  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static gboolean
-gst_gio_base_sink_start (GstBaseSink * base_sink)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-
-  if (!G_IS_OUTPUT_STREAM (sink->stream)) {
-    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
-        ("No stream given yet"));
-    return FALSE;
-  }
-
-  sink->position = 0;
-
-  GST_DEBUG_OBJECT (sink, "started stream");
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_stop (GstBaseSink * base_sink)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-  gboolean success;
-  GError *err = NULL;
-
-  if (G_IS_OUTPUT_STREAM (sink->stream)) {
-    GST_DEBUG_OBJECT (sink, "closing stream");
-
-    /* FIXME: can block but unfortunately we can't use async operations
-     * here because they require a running main loop */
-    success = g_output_stream_close (sink->stream, sink->cancel, &err);
-
-    if (!success && !gst_gio_error (sink, "g_output_stream_close", &err, NULL)) {
-      GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
-          ("g_ooutput_stream_close failed: %s", err->message));
-      g_clear_error (&err);
-    } else if (!success) {
-      GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
-          ("g_output_stream_close failed"));
-    } else {
-      GST_DEBUG_OBJECT (sink, "g_outut_stream_close succeeded");
-    }
-
-    g_object_unref (sink->stream);
-    sink->stream = NULL;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_unlock (GstBaseSink * base_sink)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-
-  GST_LOG_OBJECT (sink, "triggering cancellation");
-
-  g_cancellable_cancel (sink->cancel);
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_unlock_stop (GstBaseSink * base_sink)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-
-  GST_LOG_OBJECT (sink, "resetting cancellable");
-
-  g_cancellable_reset (sink->cancel);
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_event (GstBaseSink * base_sink, GstEvent * event)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  if (sink->stream == NULL)
-    return TRUE;
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
-      if (G_IS_OUTPUT_STREAM (sink->stream)) {
-        GstFormat format;
-        gint64 offset;
-
-        gst_event_parse_new_segment (event, NULL, NULL, &format, &offset, NULL,
-            NULL);
-
-        if (format != GST_FORMAT_BYTES) {
-          GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format",
-              gst_format_get_name (format));
-          break;
-        }
-
-        if (GST_GIO_STREAM_IS_SEEKABLE (sink->stream)) {
-          ret = gst_gio_seek (sink, G_SEEKABLE (sink->stream), offset,
-              sink->cancel);
-          if (ret == GST_FLOW_OK)
-            sink->position = offset;
-        } else {
-          ret = GST_FLOW_NOT_SUPPORTED;
-        }
-      }
-      break;
-
-    case GST_EVENT_EOS:
-    case GST_EVENT_FLUSH_START:
-      if (G_IS_OUTPUT_STREAM (sink->stream)) {
-        gboolean success;
-        GError *err = NULL;
-
-        success = g_output_stream_flush (sink->stream, sink->cancel, &err);
-
-        if (!success && !gst_gio_error (sink, "g_output_stream_flush", &err,
-                &ret)) {
-          GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
-              ("flush failed: %s", err->message));
-          g_clear_error (&err);
-        }
-      }
-      break;
-
-    default:
-      break;
-  }
-
-  return (ret == GST_FLOW_OK);
-}
-
-static GstFlowReturn
-gst_gio_base_sink_render (GstBaseSink * base_sink, GstBuffer * buffer)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-  gssize written;
-  gboolean success;
-  GError *err = NULL;
-
-  g_return_val_if_fail (G_IS_OUTPUT_STREAM (sink->stream), GST_FLOW_ERROR);
-
-  GST_LOG_OBJECT (sink, "writing %u bytes to offset %" G_GUINT64_FORMAT,
-      GST_BUFFER_SIZE (buffer), sink->position);
-
-  written = g_output_stream_write (sink->stream,
-      GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), sink->cancel, &err);
-
-  success = (written >= 0);
-
-  if (G_UNLIKELY (success && written < GST_BUFFER_SIZE (buffer))) {
-    /* FIXME: Can this happen?  Should we handle it gracefully?  gnomevfssink
-     * doesn't... */
-    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
-        ("Could not write to stream: (short write, only %"
-            G_GUINT64_FORMAT " bytes of %d bytes written)",
-            written, GST_BUFFER_SIZE (buffer)));
-    return GST_FLOW_ERROR;
-  }
-
-  if (success) {
-    sink->position += written;
-    return GST_FLOW_OK;
-
-  } else {
-    GstFlowReturn ret;
-
-    if (!gst_gio_error (sink, "g_output_stream_write", &err, &ret)) {
-      GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
-          ("Could not write to stream: %s", err->message));
-      g_clear_error (&err);
-    }
-
-    return ret;
-  }
-}
-
-static gboolean
-gst_gio_base_sink_query (GstPad * pad, GstQuery * query)
-{
-  GstGioBaseSink *sink = GST_GIO_BASE_SINK (GST_PAD_PARENT (pad));
-  GstFormat format;
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-      gst_query_parse_position (query, &format, NULL);
-      switch (format) {
-        case GST_FORMAT_BYTES:
-        case GST_FORMAT_DEFAULT:
-          gst_query_set_position (query, GST_FORMAT_BYTES, sink->position);
-          return TRUE;
-        default:
-          return FALSE;
-      }
-    case GST_QUERY_FORMATS:
-      gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
-      return TRUE;
-    default:
-      return gst_pad_query_default (pad, query);
-  }
-}
-
-void
-gst_gio_base_sink_set_stream (GstGioBaseSink * sink, GOutputStream * stream)
-{
-  g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
-  g_return_if_fail ((GST_STATE (sink) != GST_STATE_PLAYING &&
-          GST_STATE (sink) != GST_STATE_PAUSED));
-
-  if (G_IS_OUTPUT_STREAM (sink->stream)) {
-    gboolean success;
-    GError *err = NULL;
-
-    GST_DEBUG_OBJECT (sink, "closing old stream");
-
-    /* FIXME: can block but unfortunately we can't use async operations
-     * here because they require a running main loop */
-    success = g_output_stream_close (sink->stream, sink->cancel, &err);
-
-    if (!success && !gst_gio_error (sink, "g_output_stream_close", &err, NULL)) {
-      GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
-          ("g_output_stream_close failed: %s", err->message));
-      g_clear_error (&err);
-    } else if (!success) {
-      GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
-          ("g_output_stream_close failed"));
-    } else {
-      GST_DEBUG_OBJECT (sink, "g_output_stream_close succeeded");
-    }
-
-    g_object_unref (sink->stream);
-    sink->stream = NULL;
-  }
-
-  sink->stream = stream;
-}
--- a/gst_plugins_base/ext/gio/gstgiobasesink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_BASE_SINK_H__
-#define __GST_GIO_BASE_SINK_H__
-
-#include "gstgio.h"
-
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_BASE_SINK \
-  (gst_gio_base_sink_get_type())
-#define GST_GIO_BASE_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SINK,GstGioBaseSink))
-#define GST_GIO_BASE_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SINK,GstGioBaseSinkClass))
-#define GST_IS_GIO_BASE_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_BASE_SINK))
-#define GST_IS_GIO_BASE_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_BASE_SINK))
-
-typedef struct _GstGioBaseSink      GstGioBaseSink;
-typedef struct _GstGioBaseSinkClass GstGioBaseSinkClass;
-
-struct _GstGioBaseSink
-{
-  GstBaseSink sink;
-
-  GCancellable *cancel;
-  guint64 position;
-  GOutputStream *stream;
-};
-
-struct _GstGioBaseSinkClass 
-{
-  GstBaseSinkClass parent_class;
-};
-
-GType gst_gio_base_sink_get_type (void);
-
-void gst_gio_base_sink_set_stream (GstGioBaseSink *sink, GOutputStream *stream);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_BASE_SINK_H__ */
--- a/gst_plugins_base/ext/gio/gstgiobasesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,383 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiobasesrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug);
-#define GST_CAT_DEFAULT gst_gio_base_src_debug
-
-static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS_ANY);
-
-GST_BOILERPLATE (GstGioBaseSrc, gst_gio_base_src, GstBaseSrc,
-    GST_TYPE_BASE_SRC);
-
-static void gst_gio_base_src_finalize (GObject * object);
-static gboolean gst_gio_base_src_start (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_stop (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_get_size (GstBaseSrc * base_src,
-    guint64 * size);
-static gboolean gst_gio_base_src_is_seekable (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_unlock (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_unlock_stop (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_check_get_range (GstBaseSrc * base_src);
-static GstFlowReturn gst_gio_base_src_create (GstBaseSrc * base_src,
-    guint64 offset, guint size, GstBuffer ** buf);
-
-static void
-gst_gio_base_src_base_init (gpointer gclass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_base_src_debug, "gio_base_src", 0,
-      "GIO base source");
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_factory));
-}
-
-static void
-gst_gio_base_src_class_init (GstGioBaseSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesrc_class = (GstBaseSrcClass *) klass;
-
-  gobject_class->finalize = gst_gio_base_src_finalize;
-
-  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_src_start);
-  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_src_stop);
-  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gio_base_src_get_size);
-  gstbasesrc_class->is_seekable =
-      GST_DEBUG_FUNCPTR (gst_gio_base_src_is_seekable);
-  gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock);
-  gstbasesrc_class->unlock_stop =
-      GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock_stop);
-  gstbasesrc_class->check_get_range =
-      GST_DEBUG_FUNCPTR (gst_gio_base_src_check_get_range);
-  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gio_base_src_create);
-}
-
-static void
-gst_gio_base_src_init (GstGioBaseSrc * src, GstGioBaseSrcClass * gclass)
-{
-  src->cancel = g_cancellable_new ();
-}
-
-static void
-gst_gio_base_src_finalize (GObject * object)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (object);
-
-  if (src->cancel) {
-    g_object_unref (src->cancel);
-    src->cancel = NULL;
-  }
-
-  if (src->stream) {
-    g_object_unref (src->stream);
-    src->stream = NULL;
-  }
-
-  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static gboolean
-gst_gio_base_src_start (GstBaseSrc * base_src)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
-  if (!G_IS_INPUT_STREAM (src->stream)) {
-    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
-        ("No stream given yet"));
-    return FALSE;
-  }
-
-  src->position = 0;
-
-  GST_DEBUG_OBJECT (src, "started stream");
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_stop (GstBaseSrc * base_src)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-  gboolean success;
-  GError *err = NULL;
-
-  if (G_IS_INPUT_STREAM (src->stream)) {
-    GST_DEBUG_OBJECT (src, "closing stream");
-
-    /* FIXME: can block but unfortunately we can't use async operations
-     * here because they require a running main loop */
-    success = g_input_stream_close (src->stream, src->cancel, &err);
-
-    if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
-      GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
-          ("g_input_stream_close failed: %s", err->message));
-      g_clear_error (&err);
-    } else if (!success) {
-      GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
-          ("g_input_stream_close failed"));
-    } else {
-      GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
-    }
-
-    g_object_unref (src->stream);
-    src->stream = NULL;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
-  if (G_IS_FILE_INPUT_STREAM (src->stream)) {
-    GFileInfo *info;
-    GError *err = NULL;
-
-    info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream),
-        G_FILE_ATTRIBUTE_STANDARD_SIZE, src->cancel, &err);
-
-    if (info != NULL) {
-      *size = g_file_info_get_size (info);
-      g_object_unref (info);
-      GST_DEBUG_OBJECT (src, "found size: %" G_GUINT64_FORMAT, *size);
-      return TRUE;
-    }
-
-    if (!gst_gio_error (src, "g_file_input_stream_query_info", &err, NULL)) {
-
-      if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
-        GST_DEBUG_OBJECT (src, "size information not available");
-      else
-        GST_WARNING_OBJECT (src, "size information retrieval failed: %s",
-            err->message);
-
-      g_clear_error (&err);
-    }
-  } else if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) {
-    goffset old;
-    goffset stream_size;
-    gboolean ret;
-    GSeekable *seekable = G_SEEKABLE (src->stream);
-    GError *err = NULL;
-
-    old = g_seekable_tell (seekable);
-
-    ret = g_seekable_seek (seekable, 0, G_SEEK_END, src->cancel, &err);
-    if (!ret) {
-      if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) {
-        if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
-          GST_DEBUG_OBJECT (src,
-              "Seeking to the end of stream is not supported");
-        else
-          GST_WARNING_OBJECT (src, "Seeking to end of stream failed: %s",
-              err->message);
-        g_clear_error (&err);
-      } else {
-        GST_WARNING_OBJECT (src, "Seeking to end of stream failed");
-      }
-
-      return FALSE;
-    }
-
-    stream_size = g_seekable_tell (seekable);
-
-    ret = g_seekable_seek (seekable, old, G_SEEK_SET, src->cancel, &err);
-    if (!ret) {
-      if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) {
-        if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
-          GST_ERROR_OBJECT (src, "Seeking to the old position not supported");
-        else
-          GST_ERROR_OBJECT (src, "Seeking to the old position failed: %s",
-              err->message);
-        g_clear_error (&err);
-      } else {
-        GST_ERROR_OBJECT (src, "Seeking to the old position faile");
-      }
-
-      return FALSE;
-    }
-
-    if (stream_size >= 0) {
-      *size = stream_size;
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-static gboolean
-gst_gio_base_src_is_seekable (GstBaseSrc * base_src)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-  gboolean seekable;
-
-  seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream);
-
-  GST_DEBUG_OBJECT (src, "can seek: %d", seekable);
-
-  return seekable;
-}
-
-static gboolean
-gst_gio_base_src_unlock (GstBaseSrc * base_src)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
-  GST_LOG_OBJECT (src, "triggering cancellation");
-
-  g_cancellable_cancel (src->cancel);
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_unlock_stop (GstBaseSrc * base_src)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
-  GST_LOG_OBJECT (src, "resetting cancellable");
-
-  g_cancellable_reset (src->cancel);
-
-  return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_check_get_range (GstBaseSrc * base_src)
-{
-  /* FIXME: Implement dry-run variant using guesswork like gnomevfssrc? */
-
-  return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS,
-      check_get_range, (base_src), FALSE);
-}
-
-static GstFlowReturn
-gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size,
-    GstBuffer ** buf_return)
-{
-  GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-  GstBuffer *buf;
-  gssize read;
-  gboolean success, eos;
-  GstFlowReturn ret = GST_FLOW_OK;
-  GError *err = NULL;
-
-  g_return_val_if_fail (G_IS_INPUT_STREAM (src->stream), GST_FLOW_ERROR);
-
-  if (G_UNLIKELY (offset != src->position)) {
-    if (!GST_GIO_STREAM_IS_SEEKABLE (src->stream))
-      return GST_FLOW_NOT_SUPPORTED;
-
-    ret = gst_gio_seek (src, G_SEEKABLE (src->stream), offset, src->cancel);
-
-    if (ret == GST_FLOW_OK)
-      src->position = offset;
-    else
-      return ret;
-  }
-
-  buf = gst_buffer_new_and_alloc (size);
-
-  GST_LOG_OBJECT (src, "reading %u bytes from offset %" G_GUINT64_FORMAT,
-      size, offset);
-
-  read =
-      g_input_stream_read (G_INPUT_STREAM (src->stream), GST_BUFFER_DATA (buf),
-      size, src->cancel, &err);
-
-  success = (read >= 0);
-  eos = (size > 0 && read == 0);
-
-  if (!success && !gst_gio_error (src, "g_input_stream_read", &err, &ret)) {
-    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
-        ("Could not read from stream: %s", err->message));
-    g_clear_error (&err);
-  }
-
-  if (success && !eos) {
-    src->position += read;
-    GST_BUFFER_OFFSET (buf) = offset;
-    GST_BUFFER_SIZE (buf) = read;
-    *buf_return = buf;
-  } else {
-    /* !success || eos */
-    gst_buffer_unref (buf);
-  }
-
-  if (eos)
-    ret = GST_FLOW_UNEXPECTED;
-
-  return ret;
-}
-
-void
-gst_gio_base_src_set_stream (GstGioBaseSrc * src, GInputStream * stream)
-{
-  gboolean success;
-  GError *err = NULL;
-
-  g_return_if_fail (G_IS_INPUT_STREAM (stream));
-  g_return_if_fail ((GST_STATE (src) != GST_STATE_PLAYING &&
-          GST_STATE (src) != GST_STATE_PAUSED));
-
-  if (G_IS_INPUT_STREAM (src->stream)) {
-    GST_DEBUG_OBJECT (src, "closing old stream");
-
-    /* FIXME: can block but unfortunately we can't use async operations
-     * here because they require a running main loop */
-    success = g_input_stream_close (src->stream, src->cancel, &err);
-
-    if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
-      GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
-          ("g_input_stream_close failed: %s", err->message));
-      g_clear_error (&err);
-    } else if (!success) {
-      GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
-          ("g_input_stream_close failed"));
-    } else {
-      GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
-    }
-
-    g_object_unref (src->stream);
-    src->stream = NULL;
-  }
-
-  src->stream = stream;
-}
--- a/gst_plugins_base/ext/gio/gstgiobasesrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_BASE_SRC_H__
-#define __GST_GIO_BASE_SRC_H__
-
-#include "gstgio.h"
-
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_BASE_SRC \
-  (gst_gio_base_src_get_type())
-#define GST_GIO_BASE_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrc))
-#define GST_GIO_BASE_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass))
-#define GST_IS_GIO_BASE_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_BASE_SRC))
-#define GST_IS_GIO_BASE_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_BASE_SRC))
-
-typedef struct _GstGioBaseSrc      GstGioBaseSrc;
-typedef struct _GstGioBaseSrcClass GstGioBaseSrcClass;
-
-struct _GstGioBaseSrc
-{
-  GstBaseSrc src;
-  
-  GCancellable *cancel;
-  guint64 position;
-  GInputStream *stream;
-};
-
-struct _GstGioBaseSrcClass 
-{
-  GstBaseSrcClass parent_class;
-};
-
-GType gst_gio_base_src_get_type (void);
-
-void gst_gio_base_src_set_stream (GstGioBaseSrc *src, GInputStream *stream);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_BASE_SRC_H__ */
--- a/gst_plugins_base/ext/gio/gstgiosink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-/**
- * SECTION:element-giosink
- * @short_description: Write a stream to any GIO-supported location
- * @see_also: #GstFileSink, #GstGnomeVFSSink, #GstGioSrc
- *
- * <refsect2>
- * <para>
- * This plugin writes incoming data to a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GIO library or it's VFS backends. Common protocols are 'file', 'ftp',
- * or 'smb'.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=input.xyz ! giosink location=file:///home/joe/out.xyz
- * </programlisting>
- * The above pipeline will simply copy a local file. Instead of giosink,
- * we could just as well have used the filesink element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! giosink location=smb://othercomputer/foo.flac
- * </programlisting>
- * The above pipeline will re-encode an mp3 file into FLAC format and store
- * it on a remote host using the Samba protocol.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v audiotestsrc num-buffers=100 ! vorbisenc ! oggmux ! giosink location=file:///home/foo/bar.ogg
- * </programlisting>
- * The above pipeline will encode a 440Hz sine wave to Ogg Vorbis and stores
- * it in the home directory of user foo.
- * </para>
- * </refsect2>
- */
-
-/* FIXME: We would like to mount the enclosing volume of an URL
- *        if it isn't mounted yet but this is possible async-only.
- *        Unfortunately this requires a running main loop from the
- *        default context and we can't guarantuee this!
- *
- *        We would also like to do authentication while mounting.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiosink.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_sink_debug);
-#define GST_CAT_DEFAULT gst_gio_sink_debug
-
-/* Filter signals and args */
-enum
-{
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0,
-  ARG_LOCATION
-};
-
-GST_BOILERPLATE_FULL (GstGioSink, gst_gio_sink, GstGioBaseSink,
-    GST_TYPE_GIO_BASE_SINK, gst_gio_uri_handler_do_init);
-
-static void gst_gio_sink_finalize (GObject * object);
-static void gst_gio_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gio_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static gboolean gst_gio_sink_start (GstBaseSink * base_sink);
-
-static void
-gst_gio_sink_base_init (gpointer gclass)
-{
-  static GstElementDetails element_details = {
-    "GIO sink",
-    "Sink/File",
-    "Write to any GIO-supported location",
-    "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
-        "Sebastian Dröge <slomo@circular-chaos.org>"
-  };
-  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_sink_debug, "gio_sink", 0, "GIO sink");
-
-  gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_sink_class_init (GstGioSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSinkClass *gstbasesink_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesink_class = (GstBaseSinkClass *) klass;
-
-  gobject_class->finalize = gst_gio_sink_finalize;
-  gobject_class->set_property = gst_gio_sink_set_property;
-  gobject_class->get_property = gst_gio_sink_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_LOCATION,
-      g_param_spec_string ("location", "Location", "URI location to write to",
-          NULL, G_PARAM_READWRITE));
-
-  gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gio_sink_start);
-}
-
-static void
-gst_gio_sink_init (GstGioSink * sink, GstGioSinkClass * gclass)
-{
-}
-
-static void
-gst_gio_sink_finalize (GObject * object)
-{
-  GstGioSink *sink = GST_GIO_SINK (object);
-
-  if (sink->location) {
-    g_free (sink->location);
-    sink->location = NULL;
-  }
-
-  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGioSink *sink = GST_GIO_SINK (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      if (GST_STATE (sink) == GST_STATE_PLAYING ||
-          GST_STATE (sink) == GST_STATE_PAUSED)
-        break;
-
-      g_free (sink->location);
-      sink->location = g_strdup (g_value_get_string (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gio_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstGioSink *sink = GST_GIO_SINK (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      g_value_set_string (value, sink->location);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_gio_sink_start (GstBaseSink * base_sink)
-{
-  GstGioSink *sink = GST_GIO_SINK (base_sink);
-  GFile *file;
-  GOutputStream *stream;
-  GCancellable *cancel = GST_GIO_BASE_SINK (sink)->cancel;
-  gboolean success;
-  GError *err = NULL;
-
-  if (sink->location == NULL) {
-    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
-        ("No location given"));
-    return FALSE;
-  }
-
-  file = g_file_new_for_uri (sink->location);
-
-  if (file == NULL) {
-    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
-        ("Malformed URI or protocol not supported (%s)", sink->location));
-    return FALSE;
-  }
-
-  stream =
-      G_OUTPUT_STREAM (g_file_create (file, G_FILE_CREATE_NONE, cancel, &err));
-
-  success = (stream != NULL);
-
-  g_object_unref (file);
-
-  if (!success && !gst_gio_error (sink, "g_file_create", &err, NULL)) {
-
-    /*if (GST_GIO_ERROR_MATCHES (err, EXISTS)) */
-    /* FIXME: Retry with replace if overwrite == TRUE! */
-
-    if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND))
-      GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL),
-          ("Could not open location %s for writing: %s",
-              sink->location, err->message));
-    else
-      GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_READ, (NULL),
-          ("Could not open location %s for writing: %s",
-              sink->location, err->message));
-
-    g_clear_error (&err);
-  }
-
-  if (!success)
-    return FALSE;
-
-  GST_DEBUG_OBJECT (sink, "opened location %s", sink->location);
-
-  gst_gio_base_sink_set_stream (GST_GIO_BASE_SINK (sink), stream);
-
-  return GST_BASE_SINK_CLASS (parent_class)->start (base_sink);
-}
--- a/gst_plugins_base/ext/gio/gstgiosink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_SINK_H__
-#define __GST_GIO_SINK_H__
-
-#include "gstgio.h"
-#include "gstgiobasesink.h"
-
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_SINK \
-  (gst_gio_sink_get_type())
-#define GST_GIO_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_SINK,GstGioSink))
-#define GST_GIO_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_SINK,GstGioSinkClass))
-#define GST_IS_GIO_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_SINK))
-#define GST_IS_GIO_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_SINK))
-
-typedef struct _GstGioSink      GstGioSink;
-typedef struct _GstGioSinkClass GstGioSinkClass;
-
-/**
- * GstGioSink:
- *
- * Opaque data structure.
- */
-struct _GstGioSink
-{
-  GstGioBaseSink sink;
-
-  /*< private >*/
-  gchar *location;
-
-  GMainLoop *loop;
-  gboolean mount_successful;
-};
-
-struct _GstGioSinkClass 
-{
-  GstGioBaseSinkClass parent_class;
-};
-
-GType gst_gio_sink_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_SINK_H__ */
--- a/gst_plugins_base/ext/gio/gstgiosrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-/**
- * SECTION:element-giosrc
- * @short_description: Read from any GIO-supported location
- * @see_also: #GstFileSrc, #GstGnomeVFSSrc, #GstGioSink
- *
- * <refsect2>
- * <para>
- * This plugin reads data from a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GIO library or it's VFS backends. Common protocols are 'file', 'http',
- * 'ftp', or 'smb'.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v giosrc location=file:///home/joe/foo.xyz ! fakesink
- * </programlisting>
- * The above pipeline will simply read a local file and do nothing with the
- * data read. Instead of giosrc, we could just as well have used the
- * filesrc element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v giosrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz
- * </programlisting>
- * The above pipeline will copy a file from a remote host to the local file
- * system using the Samba protocol.
- * </para>
- * <para>
- * Yet another example pipeline:
- * <programlisting>
- * gst-launch -v giosrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink
- * </programlisting>
- * The above pipeline will read and decode and play an mp3 file from a
- * web server using the http protocol.
- * </para>
- * </refsect2>
- */
-
-/* FIXME: We would like to mount the enclosing volume of an URL
- *        if it isn't mounted yet but this is possible async-only.
- *        Unfortunately this requires a running main loop from the
- *        default context and we can't guarantuee this!
- *
- *        We would also like to do authentication while mounting.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiosrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_src_debug);
-#define GST_CAT_DEFAULT gst_gio_src_debug
-
-enum
-{
-  ARG_0,
-  ARG_LOCATION
-};
-
-GST_BOILERPLATE_FULL (GstGioSrc, gst_gio_src, GstGioBaseSrc,
-    GST_TYPE_GIO_BASE_SRC, gst_gio_uri_handler_do_init);
-
-static void gst_gio_src_finalize (GObject * object);
-static void gst_gio_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gio_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static gboolean gst_gio_src_start (GstBaseSrc * base_src);
-
-static void
-gst_gio_src_base_init (gpointer gclass)
-{
-  static GstElementDetails element_details = {
-    "GIO source",
-    "Source/File",
-    "Read from any GIO-supported location",
-    "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
-        "Sebastian Dröge <slomo@circular-chaos.org>"
-  };
-  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_src_debug, "gio_src", 0, "GIO source");
-
-  gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_src_class_init (GstGioSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesrc_class = (GstBaseSrcClass *) klass;
-
-  gobject_class->finalize = gst_gio_src_finalize;
-  gobject_class->set_property = gst_gio_src_set_property;
-  gobject_class->get_property = gst_gio_src_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_LOCATION,
-      g_param_spec_string ("location", "Location", "URI location to read from",
-          NULL, G_PARAM_READWRITE));
-
-  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_src_start);
-}
-
-static void
-gst_gio_src_init (GstGioSrc * src, GstGioSrcClass * gclass)
-{
-}
-
-static void
-gst_gio_src_finalize (GObject * object)
-{
-  GstGioSrc *src = GST_GIO_SRC (object);
-
-  if (src->location) {
-    g_free (src->location);
-    src->location = NULL;
-  }
-
-  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGioSrc *src = GST_GIO_SRC (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      if (GST_STATE (src) == GST_STATE_PLAYING ||
-          GST_STATE (src) == GST_STATE_PAUSED)
-        break;
-
-      g_free (src->location);
-      src->location = g_strdup (g_value_get_string (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gio_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstGioSrc *src = GST_GIO_SRC (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      g_value_set_string (value, src->location);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_gio_src_start (GstBaseSrc * base_src)
-{
-  GstGioSrc *src = GST_GIO_SRC (base_src);
-  GFile *file;
-  GError *err = NULL;
-  GInputStream *stream;
-  GCancellable *cancel = GST_GIO_BASE_SRC (src)->cancel;
-
-  if (src->location == NULL) {
-    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No location given"));
-    return FALSE;
-  }
-
-  file = g_file_new_for_uri (src->location);
-
-  if (file == NULL) {
-    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
-        ("Malformed URI or protocol not supported (%s)", src->location));
-    return FALSE;
-  }
-
-  stream = G_INPUT_STREAM (g_file_read (file, cancel, &err));
-
-  g_object_unref (file);
-
-  if (stream == NULL && !gst_gio_error (src, "g_file_read", &err, NULL)) {
-
-    if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND)) {
-      GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
-          ("Could not open location %s for reading: %s",
-              src->location, err->message));
-    } else {
-      GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
-          ("Could not open location %s for reading: %s",
-              src->location, err->message));
-    }
-
-    g_clear_error (&err);
-    return FALSE;
-  } else if (stream == NULL) {
-    return FALSE;
-  }
-
-  gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src), stream);
-
-  GST_DEBUG_OBJECT (src, "opened location %s", src->location);
-
-  return GST_BASE_SRC_CLASS (parent_class)->start (base_src);
-}
--- a/gst_plugins_base/ext/gio/gstgiosrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_SRC_H__
-#define __GST_GIO_SRC_H__
-
-#include "gstgio.h"
-#include "gstgiobasesrc.h"
-
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_SRC \
-  (gst_gio_src_get_type())
-#define GST_GIO_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_SRC,GstGioSrc))
-#define GST_GIO_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_SRC,GstGioSrcClass))
-#define GST_IS_GIO_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_SRC))
-#define GST_IS_GIO_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_SRC))
-
-typedef struct _GstGioSrc      GstGioSrc;
-typedef struct _GstGioSrcClass GstGioSrcClass;
-
-/**
- * GstGioSrc:
- *
- * Opaque data structure.
- */
-struct _GstGioSrc
-{
-  GstGioBaseSrc src;
-  
-  /*< private >*/
-  gchar *location;
-
-  GMainLoop *loop;
-  gboolean mount_successful;
-};
-
-struct _GstGioSrcClass 
-{
-  GstGioBaseSrcClass parent_class;
-};
-
-GType gst_gio_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_SRC_H__ */
--- a/gst_plugins_base/ext/gio/gstgiostreamsink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-/**
- * SECTION:element-giostreamsink
- * @short_description: Write to a GIO GOutputStream
- *
- * <refsect2>
- * <para>
- * This plugin writes incoming data to a custom GIO #GOutputStream.
- * </para>
- * <para>
- * It can, for example, be used to write a stream to memory with a
- * #GMemoryOuputStream or to write to a file with a #GFileOuputStream.
- * </para>
- * <title>Example code</title>
- * <para>
- * The following example writes the received data to a #GMemoryOutputStream.
- * <programlisting>
-
-#include &lt;gst/gst.h&gt;
-#include &lt;gio/gio.h&gt;
-
-...
-
-GstElement *sink;
-GMemoryOuputStream *stream;
-// out_data will contain the received data
-guint8 *out_data;
-
-...
-
-stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0,
-          (GReallocFunc) g_realloc, (GDestroyNotify) g_free));
-sink = gst_element_factory_make ("giostreamsink", "sink");
-g_object_set (G_OBJECT (sink), "stream", stream, NULL);
-
-...
-
-// after processing get the written data
-out_data = g_memory_ouput_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream));
-
-...
-
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiostreamsink.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_sink_debug);
-#define GST_CAT_DEFAULT gst_gio_stream_sink_debug
-
-/* Filter signals and args */
-enum
-{
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0,
-  ARG_STREAM
-};
-
-GST_BOILERPLATE (GstGioStreamSink, gst_gio_stream_sink, GstGioBaseSink,
-    GST_TYPE_GIO_BASE_SINK);
-
-static void gst_gio_stream_sink_finalize (GObject * object);
-static void gst_gio_stream_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gio_stream_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-static void
-gst_gio_stream_sink_base_init (gpointer gclass)
-{
-  static GstElementDetails element_details = {
-    "GIO stream sink",
-    "Sink",
-    "Write to any GIO stream",
-    "Sebastian Dröge <slomo@circular-chaos.org>"
-  };
-  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_stream_sink_debug, "gio_stream_sink", 0,
-      "GIO stream sink");
-
-  gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_stream_sink_class_init (GstGioStreamSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSinkClass *gstbasesink_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesink_class = (GstBaseSinkClass *) klass;
-
-  gobject_class->finalize = gst_gio_stream_sink_finalize;
-  gobject_class->set_property = gst_gio_stream_sink_set_property;
-  gobject_class->get_property = gst_gio_stream_sink_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_STREAM,
-      g_param_spec_object ("stream", "Stream", "Stream to write to",
-          G_TYPE_OUTPUT_STREAM, G_PARAM_READWRITE));
-}
-
-static void
-gst_gio_stream_sink_init (GstGioStreamSink * sink,
-    GstGioStreamSinkClass * gclass)
-{
-}
-
-static void
-gst_gio_stream_sink_finalize (GObject * object)
-{
-  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_stream_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object);
-
-  switch (prop_id) {
-    case ARG_STREAM:{
-      GObject *stream;
-
-      if (GST_STATE (sink) == GST_STATE_PLAYING ||
-          GST_STATE (sink) == GST_STATE_PAUSED)
-        break;
-
-      stream = g_value_dup_object (value);
-      if (G_IS_OUTPUT_STREAM (stream))
-        gst_gio_base_sink_set_stream (GST_GIO_BASE_SINK (sink),
-            G_OUTPUT_STREAM (stream));
-
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gio_stream_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object);
-
-  switch (prop_id) {
-    case ARG_STREAM:
-      g_value_set_object (value, GST_GIO_BASE_SINK (sink)->stream);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
--- a/gst_plugins_base/ext/gio/gstgiostreamsink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_STREAM_SINK_H__
-#define __GST_GIO_STREAM_SINK_H__
-
-#include "gstgio.h"
-#include "gstgiobasesink.h"
-
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_STREAM_SINK \
-  (gst_gio_stream_sink_get_type())
-#define GST_GIO_STREAM_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_STREAM_SINK,GstGioStreamSink))
-#define GST_GIO_STREAM_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_STREAM_SINK,GstGioStreamSinkClass))
-#define GST_IS_GIO_STREAM_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_STREAM_SINK))
-#define GST_IS_GIO_STREAM_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_STREAM_SINK))
-
-typedef struct _GstGioStreamSink      GstGioStreamSink;
-typedef struct _GstGioStreamSinkClass GstGioStreamSinkClass;
-
-/**
- * GstGioStreamSink:
- *
- * Opaque data structure.
- */
-struct _GstGioStreamSink
-{
-  GstGioBaseSink sink;
-};
-
-struct _GstGioStreamSinkClass 
-{
-  GstGioBaseSinkClass parent_class;
-};
-
-GType gst_gio_stream_sink_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_STREAM_SINK_H__ */
--- a/gst_plugins_base/ext/gio/gstgiostreamsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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.
- */
-
-/**
- * SECTION:element-giostreamsrc
- * @short_description: Reads data from a GIO GInputStream
- *
- * <refsect2>
- * <para>
- * This plugin reads data from a custom GIO #GInputStream.
- * </para>
- * <para>
- * It can, for example, be used to read data from memory with a
- * #GMemoryInputStream or to read from a file with a
- * #GFileInputStream.
- * </para>
- * <title>Example code</title>
- * <para>
- * The following example reads data from a #GMemoryOutputStream.
- * <programlisting>
-
-#include &lt;gst/gst.h&gt;
-#include &lt;gio/gio.h&gt;
-
-...
-
-GstElement *src;
-GMemoryInputStream *stream;
-// in_data will contain the data to send
-guint8 *in_data;
-gint i;
-
-...
-in_data = g_new (guint8, 512);
-for (i = 0; i < 512; i++)
-  in_data[i] = i % 256;
-
-stream = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (in_data, 512,
-          (GDestroyNotify) g_free));
-src = gst_element_factory_make ("giostreamsrc", "src");
-g_object_set (G_OBJECT (src), "stream", stream, NULL);
-
-...
-
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiostreamsrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_src_debug);
-#define GST_CAT_DEFAULT gst_gio_stream_src_debug
-
-enum
-{
-  ARG_0,
-  ARG_STREAM
-};
-
-GST_BOILERPLATE (GstGioStreamSrc, gst_gio_stream_src, GstGioBaseSrc,
-    GST_TYPE_GIO_BASE_SRC);
-
-static void gst_gio_stream_src_finalize (GObject * object);
-static void gst_gio_stream_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gio_stream_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-static void
-gst_gio_stream_src_base_init (gpointer gclass)
-{
-  static GstElementDetails element_details = {
-    "GIO stream source",
-    "Source",
-    "Read from any GIO stream",
-    "Sebastian Dröge <slomo@circular-chaos.org>"
-  };
-  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gio_stream_src_debug, "gio_stream_src", 0,
-      "GIO source");
-
-  gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesrc_class = (GstBaseSrcClass *) klass;
-
-  gobject_class->finalize = gst_gio_stream_src_finalize;
-  gobject_class->set_property = gst_gio_stream_src_set_property;
-  gobject_class->get_property = gst_gio_stream_src_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_STREAM,
-      g_param_spec_object ("stream", "Stream", "Stream to read from",
-          G_TYPE_INPUT_STREAM, G_PARAM_READWRITE));
-}
-
-static void
-gst_gio_stream_src_init (GstGioStreamSrc * src, GstGioStreamSrcClass * gclass)
-{
-}
-
-static void
-gst_gio_stream_src_finalize (GObject * object)
-{
-  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_stream_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
-
-  switch (prop_id) {
-    case ARG_STREAM:{
-      GObject *stream;
-
-      if (GST_STATE (src) == GST_STATE_PLAYING ||
-          GST_STATE (src) == GST_STATE_PAUSED)
-        break;
-
-      stream = g_value_dup_object (value);
-      if (G_IS_INPUT_STREAM (stream))
-        gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src),
-            G_INPUT_STREAM (stream));
-
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gio_stream_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
-
-  switch (prop_id) {
-    case ARG_STREAM:
-      g_value_set_object (value, GST_GIO_BASE_SRC (src)->stream);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
--- a/gst_plugins_base/ext/gio/gstgiostreamsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- * 
- * 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_GIO_STREAM_SRC_H__
-#define __GST_GIO_STREAM_SRC_H__
-
-#include "gstgio.h"
-#include "gstgiobasesrc.h"
-
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_STREAM_SRC \
-  (gst_gio_stream_src_get_type())
-#define GST_GIO_STREAM_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_STREAM_SRC,GstGioStreamSrc))
-#define GST_GIO_STREAM_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_STREAM_SRC,GstGioStreamSrcClass))
-#define GST_IS_GIO_STREAM_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_STREAM_SRC))
-#define GST_IS_GIO_STREAM_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_STREAM_SRC))
-
-typedef struct _GstGioStreamSrc      GstGioStreamSrc;
-typedef struct _GstGioStreamSrcClass GstGioStreamSrcClass;
-
-/**
- * GstGioStreamSrc:
- *
- * Opaque data structure.
- */
-struct _GstGioStreamSrc
-{
-  GstGioBaseSrc src;
-};
-
-struct _GstGioStreamSrcClass 
-{
-  GstGioBaseSrcClass parent_class;
-};
-
-GType gst_gio_stream_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_STREAM_SRC_H__ */
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfs.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * gnomevfs.c: register gnomevfs elements
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "gst/gst-i18n-plugin.h"
-
-#include "gstgnomevfs.h"
-#include "gstgnomevfssrc.h"
-#include "gstgnomevfssink.h"
-
-#include <libgnomevfs/gnome-vfs.h>
-#include <gst/gst.h>
-
-#include <string.h>
-
-gchar *
-gst_gnome_vfs_location_to_uri_string (const gchar * location)
-{
-  gchar *newloc, *ret;
-
-  if (location == NULL)
-    return NULL;
-
-  /* already an URI string? */
-  if (strstr (location, "://"))
-    return g_strdup (location);
-
-  newloc = gnome_vfs_escape_path_string (location);
-
-  if (newloc && *newloc == '/') {
-    ret = g_strdup_printf ("file://%s", newloc);
-  } else {
-    gchar *curdir;
-
-    curdir = g_get_current_dir ();
-    ret = g_strdup_printf ("file://%s/%s", curdir, newloc);
-    g_free (curdir);
-  }
-
-  g_free (newloc);
-  return ret;
-}
-
-GType
-gst_gnome_vfs_uri_get_type (void)
-{
-  static GType type;            /* 0 */
-
-  if (type == 0) {
-    type = g_boxed_type_register_static ("GnomeVFSURI",
-        (GBoxedCopyFunc) gnome_vfs_uri_ref,
-        (GBoxedFreeFunc) gnome_vfs_uri_unref);
-  }
-
-  return type;
-}
-
-static gpointer
-gst_gnome_vfs_handle_copy (gpointer handle)
-{
-  return handle;
-}
-
-static void
-gst_gnome_vfs_handle_free (gpointer handle)
-{
-  return;
-}
-
-GType
-gst_gnome_vfs_handle_get_type (void)
-{
-  static GType type;            /* 0 */
-
-  if (type == 0) {
-    /* hackish, but makes it show up nicely in gst-inspect */
-    type = g_boxed_type_register_static ("GnomeVFSHandle",
-        (GBoxedCopyFunc) gst_gnome_vfs_handle_copy,
-        (GBoxedFreeFunc) gst_gnome_vfs_handle_free);
-  }
-
-  return type;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  /* gnome vfs engine init */
-  if (!gnome_vfs_initialized ()) {
-    if (!gnome_vfs_init ()) {
-      GST_WARNING ("Failed to initialize GnomeVFS - not registering plugin!");
-      return FALSE;
-    }
-  }
-
-  if (!gst_element_register (plugin, "gnomevfssrc", GST_RANK_SECONDARY,
-          gst_gnome_vfs_src_get_type ()))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "gnomevfssink", GST_RANK_SECONDARY,
-          gst_gnome_vfs_sink_get_type ()))
-    return FALSE;
-
-#ifdef ENABLE_NLS
-/* FIXME: add category
-  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, LOCALEDIR);
- */
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif /* ENABLE_NLS */
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "gnomevfs",
-    "elements to read from and write to  Gnome-VFS uri's",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfs.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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_GNOME_VFS_H__
-#define __GST_GNOME_VFS_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNOME_VFS_URI     (gst_gnome_vfs_uri_get_type ())
-#define GST_TYPE_GNOME_VFS_HANDLE  (gst_gnome_vfs_handle_get_type ())
-
-GType gst_gnome_vfs_uri_get_type (void);
-GType gst_gnome_vfs_handle_get_type (void);
-
-gchar * gst_gnome_vfs_location_to_uri_string (const gchar * location);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_H__ */
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,641 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *                    2001 Bastien Nocera <hadess@hadess.net>
- *                    2003 Colin Walters <walters@verbum.org>
- *                    2005 Tim-Philipp Müller <tim centricular net>
- *
- * gstgnomevfssink.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.
- */
-
-/**
- * SECTION:element-gnomevfssink
- * @short_description: Write a stream to a GnomeVFS URI
- * @see_also: #GstFileSink, #GstGnomeVFSSrc
- *
- * <refsect2>
- * <para>
- * This plugin writes incoming data to a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GnomeVFS library. Common protocols are 'file', 'ftp', or 'smb'.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=input.xyz ! gnomevfssink location=file:///home/joe/out.xyz
- * </programlisting>
- * The above pipeline will simply copy a local file. Instead of gnomevfssink,
- * we could just as well have used the filesink element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! gnomevfssink location=smb://othercomputer/foo.flac
- * </programlisting>
- * The above pipeline will re-encode an mp3 file into FLAC format and store
- * it on a remote host using the Samba protocol.
- * </para>
- * <para>
- * Applications can connect to the allow-overwrite signal to receive a callback when an
- * existing file will be overwritten. The return value of the signal will determine if
- * gnomevfssink will overwrite the resource or abort with an error.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-02-28 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstgnomevfssink.h"
-
-#include "gst/gst-i18n-plugin.h"
-
-#include <gst/gst.h>
-#include <libgnomevfs/gnome-vfs.h>
-#include <string.h>
-#include <errno.h>
-
-static const GstElementDetails gst_gnome_vfs_sink_details =
-GST_ELEMENT_DETAILS ("GnomeVFS Sink",
-    "Sink/File",
-    "Write a stream to a GnomeVFS URI",
-    "Bastien Nocera <hadess@hadess.net>");
-
-enum
-{
-  SIGNAL_ERASE_ASK,
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0,
-  ARG_LOCATION,
-  ARG_URI,
-  ARG_HANDLE
-};
-
-static void gst_gnome_vfs_sink_finalize (GObject * obj);
-
-static void gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface,
-    gpointer iface_data);
-
-static void gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-static gboolean gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink);
-static void gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink);
-static gboolean gst_gnome_vfs_sink_start (GstBaseSink * basesink);
-static gboolean gst_gnome_vfs_sink_stop (GstBaseSink * basesink);
-static GstFlowReturn gst_gnome_vfs_sink_render (GstBaseSink * basesink,
-    GstBuffer * buffer);
-static gboolean gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink,
-    GstEvent * event);
-static gboolean gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query);
-
-static guint gst_gnome_vfs_sink_signals[LAST_SIGNAL];   /* all 0 */
-
-static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS_ANY);
-
-GST_DEBUG_CATEGORY_STATIC (gst_gnome_vfs_sink_debug);
-#define GST_CAT_DEFAULT gst_gnome_vfs_sink_debug
-
-static void
-gst_gnome_vfs_sink_do_init (GType type)
-{
-  static const GInterfaceInfo urihandler_info = {
-    gst_gnome_vfs_sink_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
-
-  GST_DEBUG_CATEGORY_INIT (gst_gnome_vfs_sink_debug, "gnomevfssink", 0,
-      "Gnome VFS sink element");
-}
-
-GST_BOILERPLATE_FULL (GstGnomeVFSSink, gst_gnome_vfs_sink, GstBaseSink,
-    GST_TYPE_BASE_SINK, gst_gnome_vfs_sink_do_init);
-
-static void
-gst_gnome_vfs_sink_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sinktemplate));
-
-  gst_element_class_set_details (element_class, &gst_gnome_vfs_sink_details);
-}
-
-static gboolean
-_gst_boolean_allow_overwrite_accumulator (GSignalInvocationHint * ihint,
-    GValue * return_accu, const GValue * handler_return, gpointer dummy)
-{
-  gboolean allow_overwrite;
-
-  allow_overwrite = g_value_get_boolean (handler_return);
-  if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
-    g_value_set_boolean (return_accu, allow_overwrite);
-
-  /* stop emission if signal doesn't allow overwriting */
-  return allow_overwrite;
-}
-
-static void
-gst_gnome_vfs_sink_class_init (GstGnomeVFSSinkClass * klass)
-{
-  GstBaseSinkClass *basesink_class;
-  GObjectClass *gobject_class;
-
-  gobject_class = (GObjectClass *) klass;
-  basesink_class = (GstBaseSinkClass *) klass;
-
-  gobject_class->set_property = gst_gnome_vfs_sink_set_property;
-  gobject_class->get_property = gst_gnome_vfs_sink_get_property;
-  gobject_class->finalize = gst_gnome_vfs_sink_finalize;
-
-  g_object_class_install_property (gobject_class, ARG_LOCATION,
-      g_param_spec_string ("location", "File Location",
-          "Location of the file to write", NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_URI,
-      g_param_spec_boxed ("uri", "GnomeVFSURI", "URI for GnomeVFS",
-          GST_TYPE_GNOME_VFS_URI, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_HANDLE,
-      g_param_spec_boxed ("handle",
-          "GnomeVFSHandle", "Handle for GnomeVFS",
-          GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE));
-
-  /**
-   * GstGnomeVFSSink::allow-overwrite
-   * @sink: the object which received the signal
-   * @uri: the URI to be overwritten
-   *
-   * This signal is fired when gnomevfssink is about to overwrite an
-   * existing resource. The application can connect to this signal and ask
-   * the user if the resource may be overwritten. 
-   *
-   * Returns: A boolean indicating that the resource may be overwritten.
-   */
-  gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK] =
-      g_signal_new ("allow-overwrite", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_CLEANUP, G_STRUCT_OFFSET (GstGnomeVFSSinkClass, erase_ask),
-      _gst_boolean_allow_overwrite_accumulator, NULL,
-      gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_GNOME_VFS_URI);
-
-  basesink_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_stop);
-  basesink_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_start);
-  basesink_class->event = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_handle_event);
-  basesink_class->render = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_render);
-  basesink_class->get_times = NULL;
-}
-
-static void
-gst_gnome_vfs_sink_finalize (GObject * obj)
-{
-  GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (obj);
-
-  if (sink->uri) {
-    gnome_vfs_uri_unref (sink->uri);
-    sink->uri = NULL;
-  }
-
-  if (sink->uri_name) {
-    g_free (sink->uri_name);
-    sink->uri_name = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_gnome_vfs_sink_init (GstGnomeVFSSink * sink, GstGnomeVFSSinkClass * klass)
-{
-  gst_pad_set_query_function (GST_BASE_SINK_PAD (sink),
-      GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_query));
-
-  sink->uri = NULL;
-  sink->uri_name = NULL;
-  sink->handle = NULL;
-  sink->own_handle = FALSE;
-  sink->current_pos = 0;
-
-  GST_BASE_SINK (sink)->sync = FALSE;
-}
-
-static void
-gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGnomeVFSSink *sink;
-  GstState cur_state;
-
-  sink = GST_GNOME_VFS_SINK (object);
-
-  gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0);
-
-  if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) {
-    GST_WARNING_OBJECT (sink, "cannot set property when PAUSED or PLAYING");
-    return;
-  }
-
-  GST_OBJECT_LOCK (sink);
-
-  switch (prop_id) {
-    case ARG_LOCATION:{
-      const gchar *new_location;
-
-      if (sink->uri) {
-        gnome_vfs_uri_unref (sink->uri);
-        sink->uri = NULL;
-      }
-      if (sink->uri_name) {
-        g_free (sink->uri_name);
-        sink->uri_name = NULL;
-      }
-
-      new_location = g_value_get_string (value);
-      if (new_location) {
-        sink->uri_name = gst_gnome_vfs_location_to_uri_string (new_location);
-        sink->uri = gnome_vfs_uri_new (sink->uri_name);
-      }
-      break;
-    }
-    case ARG_URI:{
-      if (sink->uri) {
-        gnome_vfs_uri_unref (sink->uri);
-        sink->uri = NULL;
-      }
-      if (sink->uri_name) {
-        g_free (sink->uri_name);
-        sink->uri_name = NULL;
-      }
-      if (g_value_get_boxed (value)) {
-        sink->uri = (GnomeVFSURI *) g_value_dup_boxed (value);
-        sink->uri_name = gnome_vfs_uri_to_string (sink->uri, 0);
-      }
-      break;
-    }
-    case ARG_HANDLE:{
-      if (sink->uri) {
-        gnome_vfs_uri_unref (sink->uri);
-        sink->uri = NULL;
-      }
-      if (sink->uri_name) {
-        g_free (sink->uri_name);
-        sink->uri_name = NULL;
-      }
-      sink->handle = g_value_get_boxed (value);
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  GST_OBJECT_UNLOCK (sink);
-}
-
-static void
-gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstGnomeVFSSink *sink;
-
-  sink = GST_GNOME_VFS_SINK (object);
-
-  GST_OBJECT_LOCK (sink);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      g_value_set_string (value, sink->uri_name);
-      break;
-    case ARG_URI:
-      g_value_set_boxed (value, sink->uri);
-      break;
-    case ARG_HANDLE:
-      g_value_set_boxed (value, sink->handle);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  GST_OBJECT_UNLOCK (sink);
-}
-
-static gboolean
-gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink)
-{
-  GnomeVFSResult result;
-
-  if (sink->uri) {
-    /* open the file, all permissions, umask will apply */
-    result = gnome_vfs_create_uri (&(sink->handle), sink->uri,
-        GNOME_VFS_OPEN_WRITE, TRUE,
-        GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE |
-        GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE |
-        GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE);
-
-    /* if the file existed and the property says to ask, then ask! */
-    if (result == GNOME_VFS_ERROR_FILE_EXISTS) {
-      gboolean erase_anyway = FALSE;
-
-      g_signal_emit (G_OBJECT (sink),
-          gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK], 0, sink->uri,
-          &erase_anyway);
-      if (erase_anyway) {
-        result = gnome_vfs_create_uri (&(sink->handle), sink->uri,
-            GNOME_VFS_OPEN_WRITE, FALSE,
-            GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE |
-            GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE |
-            GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE);
-      }
-    }
-
-    GST_DEBUG_OBJECT (sink, "open: %s", gnome_vfs_result_to_string (result));
-
-    if (result != GNOME_VFS_OK) {
-      gchar *filename = gnome_vfs_uri_to_string (sink->uri,
-          GNOME_VFS_URI_HIDE_PASSWORD);
-
-      GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
-          (_("Could not open vfs file \"%s\" for writing: %s."),
-              filename, gnome_vfs_result_to_string (result)), GST_ERROR_SYSTEM);
-      g_free (filename);
-      return FALSE;
-    }
-    sink->own_handle = TRUE;
-  } else if (!sink->handle) {
-    GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, (_("No filename given")),
-        (NULL));
-    return FALSE;
-  } else {
-    sink->own_handle = FALSE;
-  }
-
-  sink->current_pos = 0;
-
-  return TRUE;
-}
-
-static void
-gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink)
-{
-  GnomeVFSResult result;
-
-  if (sink->own_handle) {
-    /* close the file */
-    result = gnome_vfs_close (sink->handle);
-
-    if (result != GNOME_VFS_OK) {
-      gchar *filename = gnome_vfs_uri_to_string (sink->uri,
-          GNOME_VFS_URI_HIDE_PASSWORD);
-
-      GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE,
-          (_("Could not close vfs file \"%s\"."), filename), GST_ERROR_SYSTEM);
-      g_free (filename);
-    }
-
-    sink->own_handle = FALSE;
-    sink->handle = NULL;
-  }
-}
-
-static gboolean
-gst_gnome_vfs_sink_start (GstBaseSink * basesink)
-{
-  gboolean ret;
-
-  ret = gst_gnome_vfs_sink_open_file (GST_GNOME_VFS_SINK (basesink));
-
-  return ret;
-}
-
-static gboolean
-gst_gnome_vfs_sink_stop (GstBaseSink * basesink)
-{
-  GST_DEBUG_OBJECT (basesink, "closing ...");
-  gst_gnome_vfs_sink_close_file (GST_GNOME_VFS_SINK (basesink));
-  return TRUE;
-}
-
-static gboolean
-gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
-{
-  GstGnomeVFSSink *sink;
-  gboolean ret = TRUE;
-
-  sink = GST_GNOME_VFS_SINK (basesink);
-
-  GST_DEBUG_OBJECT (sink, "processing %s event", GST_EVENT_TYPE_NAME (event));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:{
-      GnomeVFSResult res;
-      GstFormat format;
-      gint64 offset;
-
-      gst_event_parse_new_segment (event, NULL, NULL, &format, &offset,
-          NULL, NULL);
-
-      if (format != GST_FORMAT_BYTES) {
-        GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format",
-            gst_format_get_name (format));
-        break;
-      }
-
-      GST_LOG_OBJECT (sink, "seeking to offset %" G_GINT64_FORMAT, offset);
-      res = gnome_vfs_seek (sink->handle, GNOME_VFS_SEEK_START, offset);
-
-      if (res != GNOME_VFS_OK) {
-        GST_ERROR_OBJECT (sink, "Failed to seek to offset %"
-            G_GINT64_FORMAT ": %s", offset, gnome_vfs_result_to_string (res));
-        ret = FALSE;
-      } else {
-        sink->current_pos = offset;
-      }
-
-      break;
-    }
-
-    case GST_EVENT_FLUSH_START:
-    case GST_EVENT_EOS:{
-      /* No need to flush with GnomeVfs */
-      break;
-    }
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-static gboolean
-gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query)
-{
-  GstGnomeVFSSink *sink;
-  GstFormat format;
-
-  sink = GST_GNOME_VFS_SINK (GST_PAD_PARENT (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-      gst_query_parse_position (query, &format, NULL);
-      switch (format) {
-        case GST_FORMAT_DEFAULT:
-        case GST_FORMAT_BYTES:
-          gst_query_set_position (query, GST_FORMAT_BYTES, sink->current_pos);
-          return TRUE;
-        default:
-          return FALSE;
-      }
-
-    case GST_QUERY_FORMATS:
-      gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
-      return TRUE;
-
-    default:
-      return gst_pad_query_default (pad, query);
-  }
-}
-
-static GstFlowReturn
-gst_gnome_vfs_sink_render (GstBaseSink * basesink, GstBuffer * buf)
-{
-  GnomeVFSFileSize written, cur_pos;
-  GstGnomeVFSSink *sink;
-  GnomeVFSResult result;
-  GstFlowReturn ret;
-
-  sink = GST_GNOME_VFS_SINK (basesink);
-
-  if (gnome_vfs_tell (sink->handle, &cur_pos) == GNOME_VFS_OK) {
-    /* bring up to date with current position for proper reporting */
-    sink->current_pos = cur_pos;
-  }
-
-  result = gnome_vfs_write (sink->handle, GST_BUFFER_DATA (buf),
-      GST_BUFFER_SIZE (buf), &written);
-
-  switch (result) {
-    case GNOME_VFS_OK:{
-      GST_DEBUG_OBJECT (sink, "wrote %" G_GINT64_FORMAT " bytes at %"
-          G_GINT64_FORMAT, (gint64) written, (gint64) cur_pos);
-
-      if (written < GST_BUFFER_SIZE (buf)) {
-        /* FIXME: what to do here? (tpm) */
-        g_warning ("%s: %d bytes should be written, only %"
-            G_GUINT64_FORMAT " bytes written", G_STRLOC,
-            GST_BUFFER_SIZE (buf), written);
-      }
-
-      sink->current_pos += GST_BUFFER_SIZE (buf);
-      ret = GST_FLOW_OK;
-      break;
-    }
-    case GNOME_VFS_ERROR_NO_SPACE:{
-      /* TODO: emit signal/send msg on out-of-diskspace and
-       * handle this gracefully (see open bug) (tpm) */
-      GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL),
-          ("bufsize=%u, written=%u", GST_BUFFER_SIZE (buf), (guint) written));
-      ret = GST_FLOW_ERROR;
-      break;
-    }
-    default:{
-      gchar *filename = gnome_vfs_uri_to_string (sink->uri,
-          GNOME_VFS_URI_HIDE_PASSWORD);
-
-      GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
-          (_("Error while writing to file \"%s\"."), filename),
-          ("%s, bufsize=%u, written=%u", gnome_vfs_result_to_string (result),
-              GST_BUFFER_SIZE (buf), (guint) written));
-
-      g_free (filename);
-      ret = GST_FLOW_ERROR;
-      break;
-    }
-  }
-
-  return GST_FLOW_OK;
-}
-
-/*** GSTURIHANDLER INTERFACE *************************************************/
-
-static GstURIType
-gst_gnome_vfs_sink_uri_get_type (void)
-{
-  return GST_URI_SINK;
-}
-
-static gchar **
-gst_gnome_vfs_sink_uri_get_protocols (void)
-{
-  static gchar **protocols = NULL;
-
-  if (!protocols)
-    protocols = gst_gnomevfs_get_supported_uris ();
-
-  return protocols;
-}
-
-static const gchar *
-gst_gnome_vfs_sink_uri_get_uri (GstURIHandler * handler)
-{
-  GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler);
-
-  return sink->uri_name;
-}
-
-static gboolean
-gst_gnome_vfs_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
-{
-  GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler);
-  GstState cur_state;
-
-  gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0);
-
-  if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) {
-    GST_WARNING_OBJECT (sink, "cannot set uri when PAUSED or PLAYING");
-    return FALSE;
-  }
-
-  g_object_set (sink, "location", uri, NULL);
-
-  return TRUE;
-}
-
-static void
-gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface, gpointer iface_data)
-{
-  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
-
-  iface->get_type = gst_gnome_vfs_sink_uri_get_type;
-  iface->get_protocols = gst_gnome_vfs_sink_uri_get_protocols;
-  iface->get_uri = gst_gnome_vfs_sink_uri_get_uri;
-  iface->set_uri = gst_gnome_vfs_sink_uri_set_uri;
-}
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *                    2001 Bastien Nocera <hadess@hadess.net>
- *                    2003 Colin Walters <walters@verbum.org>
- *                    2005 Tim-Philipp Müller <tim centricular net>
- *
- * 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_GNOME_VFS_SINK_H__
-#define __GST_GNOME_VFS_SINK_H__
-
-#include "gstgnomevfs.h"
-#include "gstgnomevfsuri.h"
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNOME_VFS_SINK \
-  (gst_gnome_vfs_sink_get_type())
-#define GST_GNOME_VFS_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSink))
-#define GST_GNOME_VFS_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSinkClass))
-#define GST_IS_GNOME_VFS_SINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SINK))
-#define GST_IS_GNOME_VFS_SINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SINK))
-
-typedef struct _GstGnomeVFSSink GstGnomeVFSSink;
-typedef struct _GstGnomeVFSSinkClass GstGnomeVFSSinkClass;
-
-/**
- * GstGnomeVFSSink:
- *
- * Opaque data structure.
- */
-struct _GstGnomeVFSSink
-{
-  GstBaseSink basesink;
-
-  /*< private >*/
-
-  /* uri */
-  GnomeVFSURI *uri;
-  gchar *uri_name;
-
-  /* handle */
-  GnomeVFSHandle *handle;
-
-  /* whether we opened the handle ourselves */
-  gboolean own_handle;
-
-  guint64  current_pos;
-};
-
-struct _GstGnomeVFSSinkClass
-{
-  GstBaseSinkClass basesink_class;
-
-  /* signals */
-  gboolean (*erase_ask) (GstElement * element, GnomeVFSURI * uri);
-};
-
-GType gst_gnome_vfs_sink_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_SINK_H__ */
-
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,880 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *                    2001 Bastien Nocera <hadess@hadess.net>
- *                    2002 Kristian Rietveld <kris@gtk.org>
- *                    2002,2003 Colin Walters <walters@gnu.org>
- *
- * gnomevfssrc.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.
- */
-
-/**
- * SECTION:element-gnomevfssrc
- * @short_description: Read from any GnomeVFS-supported location
- * @see_also: #GstFileSrc, #GstGnomeVFSSink
- *
- * <refsect2>
- * <para>
- * This plugin reads data from a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GnomeVFS library. Common protocols are 'file', 'http', 'ftp', or 'smb'.
- * </para>
- * <para>
- * In case the element-gnomevfssrc::iradio-mode property is set and the
- * location is a http resource, gnomevfssrc will send special icecast http
- * headers to the server to request additional icecast metainformation. If
- * the server is not an icecast server, it will display the same behaviour
- * as if the element-gnomevfssrc::iradio-mode property was not set. However,
- * if the server is in fact an icecast server, gnomevfssrc will output
- * data with a media type of application/x-icy, in which case you will
- * need to use the #ICYDemux element as follow-up element to extract
- * the icecast meta data and to determine the underlying media type.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v gnomevfssrc location=file:///home/joe/foo.xyz ! fakesink
- * </programlisting>
- * The above pipeline will simply read a local file and do nothing with the
- * data read. Instead of gnomevfssrc, we could just as well have used the
- * filesrc element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v gnomevfssrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz
- * </programlisting>
- * The above pipeline will copy a file from a remote host to the local file
- * system using the Samba protocol.
- * </para>
- * <para>
- * Yet another example pipeline:
- * <programlisting>
- * gst-launch -v gnomevfssrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink
- * </programlisting>
- * The above pipeline will read and decode and play an mp3 file from a
- * web server using the http protocol.
- * </para>
- * </refsect2>
- *
- */
-
-
-#define BROKEN_SIG 1
-/*#undef BROKEN_SIG */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst/gst-i18n-plugin.h"
-
-#include "gstgnomevfssrc.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <string.h>
-
-#include <gst/gst.h>
-#include <gst/tag/tag.h>
-
-/* gnome-vfs.h doesn't include the following header, which we need: */
-#include <libgnomevfs/gnome-vfs-standard-callbacks.h>
-
-GST_DEBUG_CATEGORY_STATIC (gnomevfssrc_debug);
-#define GST_CAT_DEFAULT gnomevfssrc_debug
-
-static const GstElementDetails gst_gnome_vfs_src_details =
-GST_ELEMENT_DETAILS ("GnomeVFS Source",
-    "Source/File",
-    "Read from any GnomeVFS-supported file",
-    "Bastien Nocera <hadess@hadess.net>\n"
-    "Ronald S. Bultje <rbultje@ronald.bitfreak.net>");
-
-static GStaticMutex count_lock = G_STATIC_MUTEX_INIT;
-static gint ref_count = 0;
-static gboolean vfs_owner = FALSE;
-
-static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS_ANY);
-
-enum
-{
-  ARG_0,
-  ARG_HANDLE,
-  ARG_LOCATION,
-  ARG_IRADIO_MODE,
-  ARG_IRADIO_NAME,
-  ARG_IRADIO_GENRE,
-  ARG_IRADIO_URL,
-  ARG_IRADIO_TITLE
-};
-
-static void gst_gnome_vfs_src_base_init (gpointer g_class);
-static void gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass);
-static void gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc);
-static void gst_gnome_vfs_src_finalize (GObject * object);
-static void gst_gnome_vfs_src_uri_handler_init (gpointer g_iface,
-    gpointer iface_data);
-
-static void gst_gnome_vfs_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_check_get_range (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_get_size (GstBaseSrc * src, guint64 * size);
-static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc,
-    guint64 offset, guint size, GstBuffer ** buffer);
-
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_gnome_vfs_src_get_type (void)
-{
-  static GType gnomevfssrc_type = 0;
-
-  if (!gnomevfssrc_type) {
-    static const GTypeInfo gnomevfssrc_info = {
-      sizeof (GstGnomeVFSSrcClass),
-      gst_gnome_vfs_src_base_init,
-      NULL,
-      (GClassInitFunc) gst_gnome_vfs_src_class_init,
-      NULL,
-      NULL,
-      sizeof (GstGnomeVFSSrc),
-      0,
-      (GInstanceInitFunc) gst_gnome_vfs_src_init,
-    };
-    static const GInterfaceInfo urihandler_info = {
-      gst_gnome_vfs_src_uri_handler_init,
-      NULL,
-      NULL
-    };
-
-    gnomevfssrc_type =
-        g_type_register_static (GST_TYPE_BASE_SRC,
-        "GstGnomeVFSSrc", &gnomevfssrc_info, 0);
-    g_type_add_interface_static (gnomevfssrc_type, GST_TYPE_URI_HANDLER,
-        &urihandler_info);
-  }
-  return gnomevfssrc_type;
-}
-
-static void
-gst_gnome_vfs_src_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_set_details (element_class, &gst_gnome_vfs_src_details);
-
-  GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0,
-      "Gnome-VFS Source");
-}
-
-static void
-gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
-  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->finalize = gst_gnome_vfs_src_finalize;
-  gobject_class->set_property = gst_gnome_vfs_src_set_property;
-  gobject_class->get_property = gst_gnome_vfs_src_get_property;
-
-  /* properties */
-  gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass),
-      "location", ARG_LOCATION, G_PARAM_READWRITE, NULL);
-  g_object_class_install_property (gobject_class,
-      ARG_HANDLE,
-      g_param_spec_boxed ("handle",
-          "GnomeVFSHandle", "Handle for GnomeVFS",
-          GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE));
-
-  /* icecast stuff */
-  g_object_class_install_property (gobject_class,
-      ARG_IRADIO_MODE,
-      g_param_spec_boolean ("iradio-mode",
-          "iradio-mode",
-          "Enable internet radio mode (extraction of shoutcast/icecast metadata)",
-          FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-      ARG_IRADIO_NAME,
-      g_param_spec_string ("iradio-name",
-          "iradio-name", "Name of the stream", NULL, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-      ARG_IRADIO_GENRE,
-      g_param_spec_string ("iradio-genre",
-          "iradio-genre", "Genre of the stream", NULL, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-      ARG_IRADIO_URL,
-      g_param_spec_string ("iradio-url",
-          "iradio-url",
-          "Homepage URL for radio stream", NULL, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-      ARG_IRADIO_TITLE,
-      g_param_spec_string ("iradio-title",
-          "iradio-title",
-          "Name of currently playing song", NULL, G_PARAM_READABLE));
-
-  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start);
-  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop);
-  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size);
-  gstbasesrc_class->is_seekable =
-      GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable);
-  gstbasesrc_class->check_get_range =
-      GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_check_get_range);
-  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_create);
-}
-
-static void
-gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc)
-{
-  gnomevfssrc->uri = NULL;
-  gnomevfssrc->uri_name = NULL;
-  gnomevfssrc->handle = NULL;
-  gnomevfssrc->curoffset = 0;
-  gnomevfssrc->seekable = FALSE;
-
-  gnomevfssrc->icy_caps = NULL;
-  gnomevfssrc->iradio_mode = FALSE;
-  gnomevfssrc->http_callbacks_pushed = FALSE;
-  gnomevfssrc->iradio_name = NULL;
-  gnomevfssrc->iradio_genre = NULL;
-  gnomevfssrc->iradio_url = NULL;
-  gnomevfssrc->iradio_title = NULL;
-
-  g_static_mutex_lock (&count_lock);
-  if (ref_count == 0) {
-    /* gnome vfs engine init */
-    if (gnome_vfs_initialized () == FALSE) {
-      gnome_vfs_init ();
-      vfs_owner = TRUE;
-    }
-  }
-  ref_count++;
-  g_static_mutex_unlock (&count_lock);
-}
-
-static void
-gst_gnome_vfs_src_finalize (GObject * object)
-{
-  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (object);
-
-  g_static_mutex_lock (&count_lock);
-  ref_count--;
-  if (ref_count == 0 && vfs_owner) {
-    if (gnome_vfs_initialized () == TRUE) {
-      gnome_vfs_shutdown ();
-    }
-  }
-  g_static_mutex_unlock (&count_lock);
-
-  if (src->uri) {
-    gnome_vfs_uri_unref (src->uri);
-    src->uri = NULL;
-  }
-
-  g_free (src->uri_name);
-  src->uri_name = NULL;
-
-  g_free (src->iradio_name);
-  src->iradio_name = NULL;
-
-  g_free (src->iradio_genre);
-  src->iradio_genre = NULL;
-
-  g_free (src->iradio_url);
-  src->iradio_url = NULL;
-
-  g_free (src->iradio_title);
-  src->iradio_title = NULL;
-
-  if (src->icy_caps) {
-    gst_caps_unref (src->icy_caps);
-    src->icy_caps = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/*
- * URI interface support.
- */
-
-static GstURIType
-gst_gnome_vfs_src_uri_get_type (void)
-{
-  return GST_URI_SRC;
-}
-
-static gchar **
-gst_gnome_vfs_src_uri_get_protocols (void)
-{
-  static gchar **protocols = NULL;
-
-  if (!protocols)
-    protocols = gst_gnomevfs_get_supported_uris ();
-
-  return protocols;
-}
-
-static const gchar *
-gst_gnome_vfs_src_uri_get_uri (GstURIHandler * handler)
-{
-  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler);
-
-  return src->uri_name;
-}
-
-static gboolean
-gst_gnome_vfs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
-{
-  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler);
-
-  if (GST_STATE (src) == GST_STATE_PLAYING ||
-      GST_STATE (src) == GST_STATE_PAUSED)
-    return FALSE;
-
-  g_object_set (G_OBJECT (src), "location", uri, NULL);
-
-  return TRUE;
-}
-
-static void
-gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
-{
-  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
-
-  iface->get_type = gst_gnome_vfs_src_uri_get_type;
-  iface->get_protocols = gst_gnome_vfs_src_uri_get_protocols;
-  iface->get_uri = gst_gnome_vfs_src_uri_get_uri;
-  iface->set_uri = gst_gnome_vfs_src_uri_set_uri;
-}
-
-static void
-gst_gnome_vfs_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGnomeVFSSrc *src;
-
-  src = GST_GNOME_VFS_SRC (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:{
-      const gchar *new_location;
-
-      /* the element must be stopped or paused in order to do this */
-      if (GST_STATE (src) == GST_STATE_PLAYING ||
-          GST_STATE (src) == GST_STATE_PAUSED)
-        break;
-
-      if (src->uri) {
-        gnome_vfs_uri_unref (src->uri);
-        src->uri = NULL;
-      }
-      if (src->uri_name) {
-        g_free (src->uri_name);
-        src->uri_name = NULL;
-      }
-
-      new_location = g_value_get_string (value);
-      if (new_location) {
-        src->uri_name = gst_gnome_vfs_location_to_uri_string (new_location);
-        src->uri = gnome_vfs_uri_new (src->uri_name);
-      }
-      break;
-    }
-    case ARG_HANDLE:
-      if (GST_STATE (src) == GST_STATE_NULL ||
-          GST_STATE (src) == GST_STATE_READY) {
-        if (src->uri) {
-          gnome_vfs_uri_unref (src->uri);
-          src->uri = NULL;
-        }
-        if (src->uri_name) {
-          g_free (src->uri_name);
-          src->uri_name = NULL;
-        }
-        src->handle = g_value_get_boxed (value);
-      }
-      break;
-    case ARG_IRADIO_MODE:
-      src->iradio_mode = g_value_get_boolean (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
-{
-  GstGnomeVFSSrc *src;
-
-  src = GST_GNOME_VFS_SRC (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      g_value_set_string (value, src->uri_name);
-      break;
-    case ARG_HANDLE:
-      g_value_set_boxed (value, src->handle);
-      break;
-    case ARG_IRADIO_MODE:
-      g_value_set_boolean (value, src->iradio_mode);
-      break;
-    case ARG_IRADIO_NAME:
-      g_value_set_string (value, src->iradio_name);
-      break;
-    case ARG_IRADIO_GENRE:
-      g_value_set_string (value, src->iradio_genre);
-      break;
-    case ARG_IRADIO_URL:
-      g_value_set_string (value, src->iradio_url);
-      break;
-    case ARG_IRADIO_TITLE:
-      g_value_set_string (value, src->iradio_title);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static char *
-gst_gnome_vfs_src_unicodify (const char *str)
-{
-  const gchar *env_vars[] = { "GST_ICY_TAG_ENCODING",
-    "GST_TAG_ENCODING", NULL
-  };
-
-  return gst_tag_freeform_string_to_utf8 (str, -1, env_vars);
-}
-
-static void
-gst_gnome_vfs_src_send_additional_headers_callback (gconstpointer in,
-    gsize in_size, gpointer out, gsize out_size, gpointer callback_data)
-{
-  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data);
-  GnomeVFSModuleCallbackAdditionalHeadersOut *out_args =
-      (GnomeVFSModuleCallbackAdditionalHeadersOut *) out;
-
-  if (!src->iradio_mode)
-    return;
-  GST_DEBUG_OBJECT (src, "sending headers\n");
-
-  out_args->headers = g_list_append (out_args->headers,
-      g_strdup ("icy-metadata:1\r\n"));
-}
-
-static void
-gst_gnome_vfs_src_received_headers_callback (gconstpointer in,
-    gsize in_size, gpointer out, gsize out_size, gpointer callback_data)
-{
-  GList *i;
-  gint icy_metaint;
-  GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data);
-  GnomeVFSModuleCallbackReceivedHeadersIn *in_args =
-      (GnomeVFSModuleCallbackReceivedHeadersIn *) in;
-
-  /* This is only used for internet radio stuff right now */
-  if (!src->iradio_mode)
-    return;
-
-  for (i = in_args->headers; i; i = i->next) {
-    char *data = (char *) i->data;
-    char *key = data;
-    char *value = strchr (data, ':');
-
-    if (!value)
-      continue;
-
-    value++;
-    g_strstrip (value);
-    if (!strlen (value))
-      continue;
-
-    /* Icecast stuff */
-    if (strncmp (data, "icy-metaint:", 12) == 0) {      /* ugh */
-      if (sscanf (data + 12, "%d", &icy_metaint) == 1) {
-        if (icy_metaint > 0)
-          src->icy_caps = gst_caps_new_simple ("application/x-icy",
-              "metadata-interval", G_TYPE_INT, icy_metaint, NULL);
-      }
-      continue;
-    }
-
-    if (!strncmp (data, "icy-", 4))
-      key = data + 4;
-    else
-      continue;
-
-    GST_DEBUG_OBJECT (src, "key: %s", key);
-    if (!strncmp (key, "name", 4)) {
-      g_free (src->iradio_name);
-      src->iradio_name = gst_gnome_vfs_src_unicodify (value);
-      if (src->iradio_name)
-        g_object_notify (G_OBJECT (src), "iradio-name");
-    } else if (!strncmp (key, "genre", 5)) {
-      g_free (src->iradio_genre);
-      src->iradio_genre = gst_gnome_vfs_src_unicodify (value);
-      if (src->iradio_genre)
-        g_object_notify (G_OBJECT (src), "iradio-genre");
-    } else if (!strncmp (key, "url", 3)) {
-      g_free (src->iradio_url);
-      src->iradio_url = gst_gnome_vfs_src_unicodify (value);
-      if (src->iradio_url)
-        g_object_notify (G_OBJECT (src), "iradio-url");
-    }
-  }
-}
-
-static void
-gst_gnome_vfs_src_push_callbacks (GstGnomeVFSSrc * src)
-{
-  if (src->http_callbacks_pushed)
-    return;
-
-  GST_DEBUG_OBJECT (src, "pushing callbacks");
-  gnome_vfs_module_callback_push
-      (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS,
-      gst_gnome_vfs_src_send_additional_headers_callback, src, NULL);
-  gnome_vfs_module_callback_push
-      (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS,
-      gst_gnome_vfs_src_received_headers_callback, src, NULL);
-
-  src->http_callbacks_pushed = TRUE;
-}
-
-static void
-gst_gnome_vfs_src_pop_callbacks (GstGnomeVFSSrc * src)
-{
-  if (!src->http_callbacks_pushed)
-    return;
-
-  GST_DEBUG_OBJECT (src, "popping callbacks");
-  gnome_vfs_module_callback_pop
-      (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS);
-  gnome_vfs_module_callback_pop
-      (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS);
-
-  src->http_callbacks_pushed = FALSE;
-}
-
-/*
- * Read a new buffer from src->reqoffset, takes care of events
- * and seeking and such.
- */
-static GstFlowReturn
-gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
-    GstBuffer ** buffer)
-{
-  GnomeVFSResult res;
-  GstBuffer *buf;
-  GnomeVFSFileSize readbytes;
-  guint8 *data;
-  GstGnomeVFSSrc *src;
-
-  src = GST_GNOME_VFS_SRC (basesrc);
-
-  GST_DEBUG ("now at %llu, reading from %lld, size %u", src->curoffset, offset,
-      size);
-
-  /* seek if required */
-  if (G_UNLIKELY (src->curoffset != offset)) {
-    GST_DEBUG ("need to seek");
-    if (src->seekable) {
-      GST_DEBUG ("seeking to %lld", offset);
-      res = gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_START, offset);
-      if (res != GNOME_VFS_OK)
-        goto seek_failed;
-      src->curoffset = offset;
-    } else {
-      goto cannot_seek;
-    }
-  }
-
-  buf = gst_buffer_new_and_alloc (size);
-
-  if (src->icy_caps)
-    gst_buffer_set_caps (buf, src->icy_caps);
-
-  data = GST_BUFFER_DATA (buf);
-  GST_BUFFER_OFFSET (buf) = src->curoffset;
-
-  res = gnome_vfs_read (src->handle, data, size, &readbytes);
-
-  if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK
-              && readbytes == 0)))
-    goto eos;
-
-  GST_BUFFER_SIZE (buf) = readbytes;
-
-  if (G_UNLIKELY (res != GNOME_VFS_OK))
-    goto read_failed;
-
-  src->curoffset += readbytes;
-
-  /* we're done, return the buffer */
-  *buffer = buf;
-
-  return GST_FLOW_OK;
-
-seek_failed:
-  {
-    GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL),
-        ("Failed to seek to requested position %" G_GINT64_FORMAT ": %s",
-            offset, gnome_vfs_result_to_string (res)));
-    return GST_FLOW_ERROR;
-  }
-cannot_seek:
-  {
-    GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL),
-        ("Requested seek from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT
-            " on non-seekable stream", src->curoffset, offset));
-    return GST_FLOW_ERROR;
-  }
-read_failed:
-  {
-    gst_buffer_unref (buf);
-    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
-        ("Failed to read data: %s", gnome_vfs_result_to_string (res)));
-    return GST_FLOW_ERROR;
-  }
-eos:
-  {
-    gst_buffer_unref (buf);
-    GST_DEBUG_OBJECT (src, "Reading data gave EOS");
-    return GST_FLOW_UNEXPECTED;
-  }
-}
-
-static gboolean
-gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc)
-{
-  GstGnomeVFSSrc *src;
-
-  src = GST_GNOME_VFS_SRC (basesrc);
-
-  return src->seekable;
-}
-
-static gboolean
-gst_gnome_vfs_src_check_get_range (GstBaseSrc * basesrc)
-{
-  GstGnomeVFSSrc *src;
-  const gchar *protocol;
-
-  src = GST_GNOME_VFS_SRC (basesrc);
-
-  if (src->uri == NULL) {
-    GST_WARNING_OBJECT (src, "no URI set yet");
-    return FALSE;
-  }
-
-  if (gnome_vfs_uri_is_local (src->uri)) {
-    GST_LOG_OBJECT (src, "local URI (%s), assuming random access is possible",
-        GST_STR_NULL (src->uri_name));
-    return TRUE;
-  }
-
-  /* blacklist certain protocols we know won't work getrange-based */
-  protocol = gnome_vfs_uri_get_scheme (src->uri);
-  if (protocol == NULL)
-    goto undecided;
-
-  if (strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0) {
-    GST_LOG_OBJECT (src, "blacklisted protocol '%s', no random access possible"
-        " (URI=%s)", protocol, GST_STR_NULL (src->uri_name));
-    return FALSE;
-  }
-
-  /* fall through to undecided */
-
-undecided:
-  {
-    /* don't know what to do, let the basesrc class decide for us */
-    GST_LOG_OBJECT (src, "undecided about URI '%s', let base class handle it",
-        GST_STR_NULL (src->uri_name));
-
-    if (GST_BASE_SRC_CLASS (parent_class)->check_get_range)
-      return GST_BASE_SRC_CLASS (parent_class)->check_get_range (basesrc);
-
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_gnome_vfs_src_get_size (GstBaseSrc * basesrc, guint64 * size)
-{
-  GstGnomeVFSSrc *src;
-  GnomeVFSFileInfo *info;
-  GnomeVFSFileInfoOptions options;
-  GnomeVFSResult res;
-
-  src = GST_GNOME_VFS_SRC (basesrc);
-
-  *size = -1;
-  info = gnome_vfs_file_info_new ();
-  options = GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS;
-  res = gnome_vfs_get_file_info_from_handle (src->handle, info, options);
-  if (res == GNOME_VFS_OK) {
-    if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) {
-      *size = info->size;
-      GST_DEBUG_OBJECT (src, "from handle: %" G_GUINT64_FORMAT " bytes", *size);
-    } else if (src->own_handle && gnome_vfs_uri_is_local (src->uri)) {
-      GST_DEBUG_OBJECT (src,
-          "file size not known, file local, trying fallback");
-      res = gnome_vfs_get_file_info_uri (src->uri, info, options);
-      if (res == GNOME_VFS_OK &&
-          (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) {
-        *size = info->size;
-        GST_DEBUG_OBJECT (src, "from uri: %" G_GUINT64_FORMAT " bytes", *size);
-      }
-    }
-  } else {
-    GST_WARNING_OBJECT (src, "getting info failed: %s",
-        gnome_vfs_result_to_string (res));
-  }
-  gnome_vfs_file_info_unref (info);
-
-  if (*size == (GnomeVFSFileSize) - 1)
-    return FALSE;
-
-  GST_DEBUG_OBJECT (src, "return size %" G_GUINT64_FORMAT, *size);
-
-  return TRUE;
-}
-
-/* open the file, do stuff necessary to go to PAUSED state */
-static gboolean
-gst_gnome_vfs_src_start (GstBaseSrc * basesrc)
-{
-  GnomeVFSResult res;
-  GstGnomeVFSSrc *src;
-
-  src = GST_GNOME_VFS_SRC (basesrc);
-
-  gst_gnome_vfs_src_push_callbacks (src);
-
-  if (src->uri != NULL) {
-    GnomeVFSOpenMode mode = GNOME_VFS_OPEN_READ;
-
-    /* this can block... */
-    res = gnome_vfs_open_uri (&src->handle, src->uri, mode);
-    if (res != GNOME_VFS_OK)
-      goto open_failed;
-    src->own_handle = TRUE;
-  } else if (!src->handle) {
-    goto no_filename;
-  } else {
-    src->own_handle = FALSE;
-  }
-
-  if (gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_CURRENT, 0) == GNOME_VFS_OK) {
-    src->seekable = TRUE;
-  } else {
-    src->seekable = FALSE;
-  }
-
-  return TRUE;
-
-  /* ERRORS */
-open_failed:
-  {
-    gchar *filename = gnome_vfs_uri_to_string (src->uri,
-        GNOME_VFS_URI_HIDE_PASSWORD);
-
-    gst_gnome_vfs_src_pop_callbacks (src);
-
-    if (res == GNOME_VFS_ERROR_NOT_FOUND ||
-        res == GNOME_VFS_ERROR_HOST_NOT_FOUND ||
-        res == GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE) {
-      GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
-          ("Could not open vfs file \"%s\" for reading: %s (%d)",
-              filename, gnome_vfs_result_to_string (res), res));
-    } else {
-      GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
-          ("Could not open vfs file \"%s\" for reading: %s (%d)",
-              filename, gnome_vfs_result_to_string (res), res));
-    }
-    g_free (filename);
-    return FALSE;
-  }
-no_filename:
-  {
-    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given"));
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_gnome_vfs_src_stop (GstBaseSrc * basesrc)
-{
-  GstGnomeVFSSrc *src;
-
-  src = GST_GNOME_VFS_SRC (basesrc);
-
-  gst_gnome_vfs_src_pop_callbacks (src);
-
-  if (src->own_handle) {
-    GnomeVFSResult res;
-
-    res = gnome_vfs_close (src->handle);
-    if (res != GNOME_VFS_OK) {
-      GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, (NULL),
-          ("Could not close vfs handle: %s", gnome_vfs_result_to_string (res)));
-    }
-    src->handle = NULL;
-  }
-  src->curoffset = 0;
-
-  if (src->icy_caps) {
-    gst_caps_unref (src->icy_caps);
-    src->icy_caps = NULL;
-  }
-
-  return TRUE;
-}
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *                    2001 Bastien Nocera <hadess@hadess.net>
- *                    2002 Kristian Rietveld <kris@gtk.org>
- *                    2002,2003 Colin Walters <walters@gnu.org>
- *
- * 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_GNOME_VFS_SRC_H__
-#define __GST_GNOME_VFS_SRC_H__
-
-#include <gst/base/gstbasesrc.h>
-
-#include "gstgnomevfs.h"
-#include "gstgnomevfsuri.h"
-#include <libgnomevfs/gnome-vfs.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNOME_VFS_SRC \
-  (gst_gnome_vfs_src_get_type())
-#define GST_GNOME_VFS_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrc))
-#define GST_GNOME_VFS_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrcClass))
-#define GST_IS_GNOME_VFS_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SRC))
-#define GST_IS_GNOME_VFS_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SRC))
-
-typedef struct _GstGnomeVFSSrc      GstGnomeVFSSrc;
-typedef struct _GstGnomeVFSSrcClass GstGnomeVFSSrcClass;
-
-/**
- * GstGnomeVFSSrc:
- *
- * Opaque data structure.
- */
-struct _GstGnomeVFSSrc
-{
-  GstBaseSrc basesrc;
-
-  /* uri, file, ... */
-  GnomeVFSURI *uri;
-  gchar *uri_name;
-  GnomeVFSHandle *handle;
-  gboolean own_handle;
-  GnomeVFSFileOffset curoffset; /* current offset in file */
-  gboolean seekable;
-
-  /* shoutcast/icecast metadata extraction handling */
-  gboolean iradio_mode;
-  gboolean http_callbacks_pushed;
-
-  GstCaps *icy_caps;
-
-  gchar *iradio_name;
-  gchar *iradio_genre;
-  gchar *iradio_url;
-  gchar *iradio_title;
-};
-
-struct _GstGnomeVFSSrcClass
-{
-  GstBaseSrcClass  basesrc_class;
-};
-
-GType gst_gnome_vfs_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_SRC_H__ */
-
-
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfsuri.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *                    2001 Bastien Nocera <hadess@hadess.net>
- *                    2003 Colin Walters <walters@verbum.org>
- *
- * gstgnomevfssink.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.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <libgnomevfs/gnome-vfs.h>
-#include "gstgnomevfsuri.h"
-
-#include <gst/gst.h>
-
-gchar **
-gst_gnomevfs_get_supported_uris (void)
-{
-  /* no dav/davs in the list, because they don't appear to be reliable enough */
-  const gchar *uris[] = {
-    "http://localhost/bla",
-    "https://localhost/bla",
-    "file:///bla",
-    "smb://localhost/bla",
-    "ftp://localhost/bla",
-    "sftp://localhost/bla",
-    "nfs://localhost/bla",
-    "ssh://localhost/bla",
-    "burn://"
-  };
-  GnomeVFSURI *uri;
-  gchar **result;
-  gint n, r = 0;
-
-  result = g_new0 (gchar *, G_N_ELEMENTS (uris) + 1);
-  for (n = 0; n < G_N_ELEMENTS (uris); n++) {
-    uri = gnome_vfs_uri_new (uris[n]);
-    if (uri != NULL) {
-      gchar *protocol = g_strdup (uris[n]);
-      gint n;
-
-      gnome_vfs_uri_unref (uri);
-      for (n = 0; protocol[n] != '\0'; n++) {
-        if (protocol[n] == ':') {
-          protocol[n] = '\0';
-          break;
-        }
-      }
-
-      GST_DEBUG ("adding protocol '%s'", protocol);
-      result[r++] = protocol;
-    } else {
-      GST_DEBUG ("could not create GnomeVfsUri from '%s'", uris[n]);
-    }
-  }
-  result[r] = NULL;
-
-  return result;
-}
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfsuri.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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_GNOME_VFS_URI_H__
-#define __GST_GNOME_VFS_URI_H__
-
-#include <libgnomevfs/gnome-vfs.h>
-
-G_BEGIN_DECLS
-
-gchar **gst_gnomevfs_get_supported_uris (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_URI_H__ */
--- a/gst_plugins_base/ext/libvisual/visual.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,957 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
-#include <gst/video/video.h>
-#include <gst/audio/audio.h>
-#include <libvisual/libvisual.h>
-
-#define GST_TYPE_VISUAL (gst_visual_get_type())
-#define GST_IS_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VISUAL))
-#define GST_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VISUAL,GstVisual))
-#define GST_IS_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VISUAL))
-#define GST_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VISUAL,GstVisualClass))
-#define GST_VISUAL_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VISUAL, GstVisualClass))
-
-typedef struct _GstVisual GstVisual;
-typedef struct _GstVisualClass GstVisualClass;
-
-GST_DEBUG_CATEGORY_STATIC (libvisual_debug);
-#define GST_CAT_DEFAULT (libvisual_debug)
-
-struct _GstVisual
-{
-  GstElement element;
-
-  /* pads */
-  GstPad *sinkpad;
-  GstPad *srcpad;
-  GstClockTime next_ts;
-  GstSegment segment;
-
-  /* libvisual stuff */
-  VisAudio *audio;
-  VisVideo *video;
-  VisActor *actor;
-
-  /* audio/video state */
-  gint channels;
-  gint rate;                    /* Input samplerate */
-  gint bps;
-
-  /* framerate numerator & denominator */
-  gint fps_n;
-  gint fps_d;
-  gint width;
-  gint height;
-  GstClockTime duration;
-  guint outsize;
-
-  /* samples per frame based on caps */
-  guint spf;
-
-  /* state stuff */
-  GstAdapter *adapter;
-  guint count;
-
-  /* QoS stuff *//* with LOCK */
-  gdouble proportion;
-  GstClockTime earliest_time;
-};
-
-struct _GstVisualClass
-{
-  GstElementClass parent_class;
-
-  VisPluginRef *plugin;
-};
-
-GType gst_visual_get_type (void);
-
-
-static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN "; "
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-        GST_VIDEO_CAPS_RGB "; "
-#else
-        GST_VIDEO_CAPS_BGR "; "
-#endif
-        GST_VIDEO_CAPS_RGB_16)
-    );
-
-static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "width = (int) 16, "
-        "depth = (int) 16, "
-        "endianness = (int) BYTE_ORDER, "
-        "signed = (boolean) TRUE, " "channels = (int) { 1, 2 }, "
-#if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
-        "rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }"
-#else
-        "rate = (int) [ 1000, MAX ]"
-#endif
-    )
-    );
-
-
-static void gst_visual_class_init (gpointer g_class, gpointer class_data);
-static void gst_visual_init (GstVisual * visual);
-static void gst_visual_dispose (GObject * object);
-
-static GstStateChangeReturn gst_visual_change_state (GstElement * element,
-    GstStateChange transition);
-static GstFlowReturn gst_visual_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_visual_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_visual_src_event (GstPad * pad, GstEvent * event);
-
-static gboolean gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_visual_src_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_visual_getcaps (GstPad * pad);
-static void libvisual_log_handler (const char *message, const char *funcname,
-    void *priv);
-
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_visual_get_type (void)
-{
-  static GType type = 0;
-
-  if (G_UNLIKELY (type == 0)) {
-    static const GTypeInfo info = {
-      sizeof (GstVisualClass),
-      NULL,
-      NULL,
-      gst_visual_class_init,
-      NULL,
-      NULL,
-      sizeof (GstVisual),
-      0,
-      (GInstanceInitFunc) gst_visual_init,
-    };
-
-    type = g_type_register_static (GST_TYPE_ELEMENT, "GstVisual", &info, 0);
-  }
-  return type;
-}
-
-static void
-libvisual_log_handler (const char *message, const char *funcname, void *priv)
-{
-  GST_CAT_LEVEL_LOG (libvisual_debug, (GstDebugLevel) (priv), NULL, "%s - %s",
-      funcname, message);
-}
-
-static void
-gst_visual_class_init (gpointer g_class, gpointer class_data)
-{
-  GstVisualClass *klass = GST_VISUAL_CLASS (g_class);
-  GstElementClass *element = GST_ELEMENT_CLASS (g_class);
-  GObjectClass *object = G_OBJECT_CLASS (g_class);
-
-  klass->plugin = class_data;
-
-  element->change_state = gst_visual_change_state;
-
-  if (class_data == NULL) {
-    parent_class = g_type_class_peek_parent (g_class);
-  } else {
-    GstElementDetails details = {
-      NULL,
-      "Visualization",
-      klass->plugin->info->about,
-      "Benjamin Otte <otte@gnome.org>"
-    };
-
-    details.longname = g_strdup_printf ("libvisual %s plugin v.%s",
-        klass->plugin->info->name, klass->plugin->info->version);
-
-    /* FIXME: improve to only register what plugin supports? */
-    gst_element_class_add_pad_template (element,
-        gst_static_pad_template_get (&src_template));
-    gst_element_class_add_pad_template (element,
-        gst_static_pad_template_get (&sink_template));
-    gst_element_class_set_details (element, &details);
-    g_free (details.longname);
-  }
-
-  object->dispose = gst_visual_dispose;
-}
-
-static void
-gst_visual_init (GstVisual * visual)
-{
-  /* create the sink and src pads */
-  visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
-  gst_pad_set_setcaps_function (visual->sinkpad, gst_visual_sink_setcaps);
-  gst_pad_set_chain_function (visual->sinkpad, gst_visual_chain);
-  gst_pad_set_event_function (visual->sinkpad, gst_visual_sink_event);
-  gst_element_add_pad (GST_ELEMENT (visual), visual->sinkpad);
-
-  visual->srcpad = gst_pad_new_from_static_template (&src_template, "src");
-  gst_pad_set_setcaps_function (visual->srcpad, gst_visual_src_setcaps);
-  gst_pad_set_getcaps_function (visual->srcpad, gst_visual_getcaps);
-  gst_pad_set_event_function (visual->srcpad, gst_visual_src_event);
-  gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad);
-
-  visual->adapter = gst_adapter_new ();
-}
-
-static void
-gst_visual_clear_actors (GstVisual * visual)
-{
-  if (visual->actor) {
-    visual_object_unref (VISUAL_OBJECT (visual->actor));
-    visual->actor = NULL;
-  }
-  if (visual->video) {
-    visual_object_unref (VISUAL_OBJECT (visual->video));
-    visual->video = NULL;
-  }
-  if (visual->audio) {
-    visual_object_unref (VISUAL_OBJECT (visual->audio));
-    visual->audio = NULL;
-  }
-}
-
-static void
-gst_visual_dispose (GObject * object)
-{
-  GstVisual *visual = GST_VISUAL (object);
-
-  if (visual->adapter) {
-    g_object_unref (visual->adapter);
-    visual->adapter = NULL;
-  }
-  gst_visual_clear_actors (visual);
-
-  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
-}
-
-static void
-gst_visual_reset (GstVisual * visual)
-{
-  visual->next_ts = -1;
-  gst_adapter_clear (visual->adapter);
-  gst_segment_init (&visual->segment, GST_FORMAT_UNDEFINED);
-
-  GST_OBJECT_LOCK (visual);
-  visual->proportion = 1.0;
-  visual->earliest_time = -1;
-  GST_OBJECT_UNLOCK (visual);
-}
-
-static GstCaps *
-gst_visual_getcaps (GstPad * pad)
-{
-  GstCaps *ret;
-  GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
-  int depths;
-
-  if (!visual->actor) {
-    ret = gst_caps_copy (gst_pad_get_pad_template_caps (visual->srcpad));
-    goto beach;
-  }
-
-  ret = gst_caps_new_empty ();
-  depths = visual_actor_get_supported_depth (visual->actor);
-  if (depths < 0) {
-    /* FIXME: set an error */
-    goto beach;
-  }
-  if (depths == VISUAL_VIDEO_DEPTH_GL) {
-    /* We can't handle GL only plugins */
-    goto beach;
-  }
-
-  GST_DEBUG_OBJECT (visual, "libvisual plugin supports depths %u (0x%04x)",
-      depths, depths);
-  /* if (depths & VISUAL_VIDEO_DEPTH_32BIT) Always supports 32bit output */
-  gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN));
-
-  if (depths & VISUAL_VIDEO_DEPTH_24BIT) {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-    gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_RGB));
-#else
-    gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_BGR));
-#endif
-  }
-  if (depths & VISUAL_VIDEO_DEPTH_16BIT) {
-    gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_RGB_16));
-  }
-
-beach:
-
-  GST_DEBUG_OBJECT (visual, "returning caps %" GST_PTR_FORMAT, ret);
-  gst_object_unref (visual);
-  return ret;
-}
-
-static gboolean
-gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
-  GstStructure *structure;
-  gint depth, pitch;
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  GST_DEBUG_OBJECT (visual, "src pad got caps %" GST_PTR_FORMAT, caps);
-
-  if (!gst_structure_get_int (structure, "width", &visual->width))
-    goto error;
-  if (!gst_structure_get_int (structure, "height", &visual->height))
-    goto error;
-  if (!gst_structure_get_int (structure, "bpp", &depth))
-    goto error;
-  if (!gst_structure_get_fraction (structure, "framerate", &visual->fps_n,
-          &visual->fps_d))
-    goto error;
-
-  visual_video_set_depth (visual->video,
-      visual_video_depth_enum_from_value (depth));
-  visual_video_set_dimension (visual->video, visual->width, visual->height);
-  pitch = GST_ROUND_UP_4 (visual->width * visual->video->bpp);
-  visual_video_set_pitch (visual->video, pitch);
-  visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE);
-
-  /* precalc some values */
-  visual->outsize = visual->video->height * pitch;
-  visual->spf =
-      gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n);
-  visual->duration =
-      gst_util_uint64_scale_int (GST_SECOND, visual->fps_d, visual->fps_n);
-
-  gst_object_unref (visual);
-  return TRUE;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (visual, "error parsing caps");
-    gst_object_unref (visual);
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
-  GstStructure *structure;
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  gst_structure_get_int (structure, "channels", &visual->channels);
-  gst_structure_get_int (structure, "rate", &visual->rate);
-
-  /* this is how many samples we need to fill one frame at the requested
-   * framerate. */
-  if (visual->fps_n != 0) {
-    visual->spf =
-        gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n);
-  }
-  visual->bps = visual->channels * sizeof (gint16);
-
-  gst_object_unref (visual);
-  return TRUE;
-}
-
-static gboolean
-gst_vis_src_negotiate (GstVisual * visual)
-{
-  GstCaps *othercaps, *target, *intersect;
-  GstStructure *structure;
-  GstCaps *caps;
-
-  caps = gst_pad_get_caps (visual->srcpad);
-
-  /* see what the peer can do */
-  othercaps = gst_pad_peer_get_caps (visual->srcpad);
-  if (othercaps) {
-    intersect = gst_caps_intersect (othercaps, caps);
-    gst_caps_unref (othercaps);
-    gst_caps_unref (caps);
-
-    if (gst_caps_is_empty (intersect))
-      goto no_format;
-
-    target = gst_caps_copy_nth (intersect, 0);
-    gst_caps_unref (intersect);
-  } else {
-    /* need a copy, we'll be modifying it when fixating */
-    target = gst_caps_copy (caps);
-    gst_caps_unref (caps);
-  }
-
-  /* fixate in case something is not fixed. This does nothing if the value is
-   * already fixed. For video we always try to fixate to something like
-   * 320x240x30 by convention. */
-  structure = gst_caps_get_structure (target, 0);
-  gst_structure_fixate_field_nearest_int (structure, "width", 320);
-  gst_structure_fixate_field_nearest_int (structure, "height", 240);
-  gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
-
-  gst_pad_set_caps (visual->srcpad, target);
-  gst_caps_unref (target);
-
-  return TRUE;
-
-  /* ERRORS */
-no_format:
-  {
-    GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
-        ("could not negotiate output format"));
-    gst_caps_unref (intersect);
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_visual_sink_event (GstPad * pad, GstEvent * event)
-{
-  GstVisual *visual;
-  gboolean res;
-
-  visual = GST_VISUAL (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      res = gst_pad_push_event (visual->srcpad, event);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      /* reset QoS and adapter. */
-      gst_visual_reset (visual);
-      res = gst_pad_push_event (visual->srcpad, event);
-      break;
-    case GST_EVENT_NEWSEGMENT:
-    {
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-      gboolean update;
-
-      /* the newsegment values are used to clip the input samples
-       * and to convert the incomming timestamps to running time so
-       * we can do QoS */
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      /* now configure the values */
-      gst_segment_set_newsegment_full (&visual->segment, update,
-          rate, arate, format, start, stop, time);
-
-      /* and forward */
-      res = gst_pad_push_event (visual->srcpad, event);
-      break;
-    }
-    default:
-      res = gst_pad_push_event (visual->srcpad, event);
-      break;
-  }
-
-  gst_object_unref (visual);
-  return res;
-}
-
-static gboolean
-gst_visual_src_event (GstPad * pad, GstEvent * event)
-{
-  GstVisual *visual;
-  gboolean res;
-
-  visual = GST_VISUAL (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_QOS:
-    {
-      gdouble proportion;
-      GstClockTimeDiff diff;
-      GstClockTime timestamp;
-
-      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
-
-      /* save stuff for the _chain function */
-      GST_OBJECT_LOCK (visual);
-      visual->proportion = proportion;
-      if (diff >= 0)
-        /* we're late, this is a good estimate for next displayable
-         * frame (see part-qos.txt) */
-        visual->earliest_time = timestamp + 2 * diff + visual->duration;
-      else
-        visual->earliest_time = timestamp + diff;
-
-      GST_OBJECT_UNLOCK (visual);
-
-      res = gst_pad_push_event (visual->sinkpad, event);
-      break;
-    }
-    default:
-      res = gst_pad_push_event (visual->sinkpad, event);
-      break;
-  }
-
-  gst_object_unref (visual);
-  return res;
-}
-
-/* allocate and output buffer, if no format was negotiated, this
- * function will negotiate one. After calling this function, a
- * reverse negotiation could have happened. */
-static GstFlowReturn
-get_buffer (GstVisual * visual, GstBuffer ** outbuf)
-{
-  GstFlowReturn ret;
-
-  /* we don't know an output format yet, pick one */
-  if (GST_PAD_CAPS (visual->srcpad) == NULL) {
-    if (!gst_vis_src_negotiate (visual))
-      return GST_FLOW_NOT_NEGOTIATED;
-  }
-
-  GST_DEBUG_OBJECT (visual, "allocating output buffer with caps %"
-      GST_PTR_FORMAT, GST_PAD_CAPS (visual->srcpad));
-
-  /* now allocate a buffer with the last negotiated format. 
-   * Downstream could renegotiate a new format, which will trigger
-   * our setcaps function on the source pad. */
-  ret =
-      gst_pad_alloc_buffer_and_set_caps (visual->srcpad,
-      GST_BUFFER_OFFSET_NONE, visual->outsize,
-      GST_PAD_CAPS (visual->srcpad), outbuf);
-
-  /* no buffer allocated, we don't care why. */
-  if (ret != GST_FLOW_OK)
-    return ret;
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_visual_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstBuffer *outbuf = NULL;
-  guint i;
-  GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
-  GstFlowReturn ret = GST_FLOW_OK;
-  guint avail;
-
-  GST_DEBUG_OBJECT (visual, "chain function called");
-
-  /* If we don't have an output format yet, preallocate a buffer to try and
-   * set one */
-  if (GST_PAD_CAPS (visual->srcpad) == NULL) {
-    ret = get_buffer (visual, &outbuf);
-    if (ret != GST_FLOW_OK) {
-      gst_buffer_unref (buffer);
-      goto beach;
-    }
-  }
-
-  /* resync on DISCONT */
-  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
-    gst_adapter_clear (visual->adapter);
-    visual->next_ts = -1;
-  }
-
-  /* Match timestamps from the incoming audio */
-  if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
-    visual->next_ts = GST_BUFFER_TIMESTAMP (buffer);
-
-  GST_DEBUG_OBJECT (visual,
-      "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
-      GST_BUFFER_SIZE (buffer) / visual->bps, GST_BUFFER_TIMESTAMP (buffer));
-
-  gst_adapter_push (visual->adapter, buffer);
-
-  while (TRUE) {
-    gboolean need_skip;
-    const guint16 *data;
-
-    GST_DEBUG_OBJECT (visual, "processing buffer");
-
-    avail = gst_adapter_available (visual->adapter);
-    GST_DEBUG_OBJECT (visual, "avail now %u", avail);
-
-    /* we need at least 512 samples */
-    if (avail < 512 * visual->bps)
-      break;
-
-    /* we need at least enough samples to make one frame */
-    if (avail < visual->spf * visual->bps)
-      break;
-
-    if (visual->next_ts != -1) {
-      gint64 qostime;
-
-      /* QoS is done on running time */
-      qostime = gst_segment_to_running_time (&visual->segment, GST_FORMAT_TIME,
-          visual->next_ts);
-
-      GST_OBJECT_LOCK (visual);
-      /* check for QoS, don't compute buffers that are known to be late */
-      need_skip = visual->earliest_time != -1 &&
-          qostime <= visual->earliest_time;
-      GST_OBJECT_UNLOCK (visual);
-
-      if (need_skip) {
-        GST_WARNING_OBJECT (visual,
-            "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (qostime), GST_TIME_ARGS (visual->earliest_time));
-        goto skip;
-      }
-    }
-
-    /* Read 512 samples per channel */
-    data =
-        (const guint16 *) gst_adapter_peek (visual->adapter, 512 * visual->bps);
-
-#if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
-    {
-      VisBuffer *lbuf, *rbuf;
-      guint16 ldata[512], rdata[512];
-      VisAudioSampleRateType rate;
-
-      lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL);
-      rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL);
-
-      if (visual->channels == 2) {
-        for (i = 0; i < 512; i++) {
-          ldata[i] = *data++;
-          rdata[i] = *data++;
-        }
-      } else {
-        for (i = 0; i < 512; i++) {
-          ldata[i] = *data;
-          rdata[i] = *data++;
-        }
-      }
-
-      switch (visual->rate) {
-        case 8000:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_8000;
-          break;
-        case 11250:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_11250;
-          break;
-        case 22500:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_22500;
-          break;
-        case 32000:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_32000;
-          break;
-        case 44100:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_44100;
-          break;
-        case 48000:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_48000;
-          break;
-        case 96000:
-          rate = VISUAL_AUDIO_SAMPLE_RATE_96000;
-          break;
-        default:
-          visual_object_unref (VISUAL_OBJECT (lbuf));
-          visual_object_unref (VISUAL_OBJECT (rbuf));
-          GST_ERROR_OBJECT (visual, "unsupported rate %d", visual->rate);
-          ret = GST_FLOW_ERROR;
-          goto beach;
-          break;
-      }
-
-      visual_audio_samplepool_input_channel (visual->audio->samplepool,
-          lbuf,
-          rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_CHANNEL_LEFT);
-      visual_audio_samplepool_input_channel (visual->audio->samplepool,
-          rbuf,
-          rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_CHANNEL_RIGHT);
-
-      visual_object_unref (VISUAL_OBJECT (lbuf));
-      visual_object_unref (VISUAL_OBJECT (rbuf));
-
-    }
-#else
-    if (visual->channels == 2) {
-      for (i = 0; i < 512; i++) {
-        visual->audio->plugpcm[0][i] = *data++;
-        visual->audio->plugpcm[1][i] = *data++;
-      }
-    } else {
-      for (i = 0; i < 512; i++) {
-        visual->audio->plugpcm[0][i] = *data;
-        visual->audio->plugpcm[1][i] = *data++;
-      }
-    }
-#endif
-
-    /* alloc a buffer if we don't have one yet, this happens
-     * when we pushed a buffer in this while loop before */
-    if (outbuf == NULL) {
-      ret = get_buffer (visual, &outbuf);
-      if (ret != GST_FLOW_OK) {
-        goto beach;
-      }
-    }
-    visual_video_set_buffer (visual->video, GST_BUFFER_DATA (outbuf));
-    visual_audio_analyze (visual->audio);
-    visual_actor_run (visual->actor, visual->audio);
-    visual_video_set_buffer (visual->video, NULL);
-    GST_DEBUG_OBJECT (visual, "rendered one frame");
-
-    GST_BUFFER_TIMESTAMP (outbuf) = visual->next_ts;
-    GST_BUFFER_DURATION (outbuf) = visual->duration;
-
-    ret = gst_pad_push (visual->srcpad, outbuf);
-    outbuf = NULL;
-
-  skip:
-    /* interpollate next timestamp */
-    if (visual->next_ts != -1)
-      visual->next_ts += visual->duration;
-
-    GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
-        visual->spf);
-
-    /* Flush out the number of samples per frame */
-    gst_adapter_flush (visual->adapter, visual->spf * visual->bps);
-
-    /* quit the loop if something was wrong */
-    if (ret != GST_FLOW_OK)
-      break;
-  }
-
-beach:
-
-  if (outbuf != NULL)
-    gst_buffer_unref (outbuf);
-
-  gst_object_unref (visual);
-
-  return ret;
-}
-
-static GstStateChangeReturn
-gst_visual_change_state (GstElement * element, GstStateChange transition)
-{
-  GstVisual *visual = GST_VISUAL (element);
-  GstStateChangeReturn ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      visual->actor =
-          visual_actor_new (GST_VISUAL_GET_CLASS (visual)->plugin->info->
-          plugname);
-      visual->video = visual_video_new ();
-      visual->audio = visual_audio_new ();
-      /* can't have a play without actors */
-      if (!visual->actor || !visual->video)
-        goto no_actors;
-
-      if (visual_actor_realize (visual->actor) != 0)
-        goto no_realize;
-
-      visual_actor_set_video (visual->actor, visual->video);
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      gst_visual_reset (visual);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      gst_visual_clear_actors (visual);
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-
-  /* ERRORS */
-no_actors:
-  {
-    GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
-        ("could not create actors"));
-    gst_visual_clear_actors (visual);
-    return GST_STATE_CHANGE_FAILURE;
-  }
-no_realize:
-  {
-    GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
-        ("could not realize actor"));
-    gst_visual_clear_actors (visual);
-    return GST_STATE_CHANGE_FAILURE;
-  }
-}
-
-static void
-make_valid_name (char *name)
-{
-  /*
-   * Replace invalid chars with _ in the type name
-   */
-  static const gchar extra_chars[] = "-_+";
-  gchar *p = name;
-
-  for (; *p; p++) {
-    int valid = ((p[0] >= 'A' && p[0] <= 'Z') ||
-        (p[0] >= 'a' && p[0] <= 'z') ||
-        (p[0] >= '0' && p[0] <= '9') || strchr (extra_chars, p[0]));
-    if (!valid)
-      *p = '_';
-  }
-}
-
-static gboolean
-gst_visual_actor_plugin_is_gl (VisObject * plugin, const gchar * name)
-{
-  gboolean is_gl;
-  gint depth;
-
-#if !defined(VISUAL_API_VERSION)
-
-  depth = VISUAL_PLUGIN_ACTOR (plugin)->depth;
-  is_gl = (depth == VISUAL_VIDEO_DEPTH_GL);
-
-#elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
-
-  depth = VISUAL_ACTOR_PLUGIN (plugin)->vidoptions.depth;
-  /* FIXME: how to figure this out correctly in 0.4? */
-  is_gl = (depth & VISUAL_VIDEO_DEPTH_GL) == VISUAL_VIDEO_DEPTH_GL;
-
-#else
-# error what libvisual version is this?
-#endif
-
-  if (!is_gl) {
-    GST_DEBUG ("plugin %s is not a GL plugin (%d), registering", name, depth);
-  } else {
-    GST_DEBUG ("plugin %s is a GL plugin (%d), ignoring", name, depth);
-  }
-
-  return is_gl;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  guint i, count;
-  VisList *list;
-
-  GST_DEBUG_CATEGORY_INIT (libvisual_debug, "libvisual", 0,
-      "libvisual audio visualisations");
-
-  visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_LOW);
-  visual_log_set_info_handler (libvisual_log_handler, (void *) GST_LEVEL_INFO);
-  visual_log_set_warning_handler (libvisual_log_handler,
-      (void *) GST_LEVEL_WARNING);
-  visual_log_set_critical_handler (libvisual_log_handler,
-      (void *) GST_LEVEL_ERROR);
-  visual_log_set_error_handler (libvisual_log_handler,
-      (void *) GST_LEVEL_ERROR);
-
-  if (!visual_is_initialized ())
-    if (visual_init (NULL, NULL) != 0)
-      return FALSE;
-
-  list = visual_actor_get_list ();
-
-#if !defined(VISUAL_API_VERSION)
-  count = visual_list_count (list);
-#elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
-  count = visual_collection_size (VISUAL_COLLECTION (list));
-#endif
-
-  for (i = 0; i < count; i++) {
-    VisPluginRef *ref = visual_list_get (list, i);
-    VisPluginData *visplugin = NULL;
-    gboolean skip = FALSE;
-    GType type;
-    gchar *name;
-    GTypeInfo info = {
-      sizeof (GstVisualClass),
-      NULL,
-      NULL,
-      gst_visual_class_init,
-      NULL,
-      ref,
-      sizeof (GstVisual),
-      0,
-      NULL
-    };
-
-    visplugin = visual_plugin_load (ref);
-
-    if (ref->info->plugname == NULL)
-      continue;
-
-    /* Blacklist some plugins */
-    if (strcmp (ref->info->plugname, "gstreamer") == 0 ||
-        strcmp (ref->info->plugname, "gdkpixbuf") == 0) {
-      skip = TRUE;
-    } else {
-      /* Ignore plugins that only support GL output for now */
-      skip = gst_visual_actor_plugin_is_gl (visplugin->info->plugin,
-          visplugin->info->plugname);
-    }
-
-    visual_plugin_unload (visplugin);
-
-    if (!skip) {
-      name = g_strdup_printf ("GstVisual%s", ref->info->plugname);
-      make_valid_name (name);
-      type = g_type_register_static (GST_TYPE_VISUAL, name, &info, 0);
-      g_free (name);
-
-      name = g_strdup_printf ("libvisual_%s", ref->info->plugname);
-      make_valid_name (name);
-      if (!gst_element_register (plugin, name, GST_RANK_NONE, type)) {
-        g_free (name);
-        return FALSE;
-      }
-      g_free (name);
-    }
-  }
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "libvisual",
-    "libvisual visualization plugins",
-    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/ogg/gstogg.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-
-extern gboolean gst_ogg_demux_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogg_mux_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogm_parse_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogg_parse_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogg_avi_parse_plugin_init (GstPlugin * plugin);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  gst_ogg_demux_plugin_init (plugin);
-  gst_ogg_mux_plugin_init (plugin);
-  gst_ogm_parse_plugin_init (plugin);
-  gst_ogg_parse_plugin_init (plugin);
-  gst_ogg_avi_parse_plugin_init (plugin);
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "ogg",
-    "ogg stream manipulation (info about ogg: http://xiph.org)",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/ogg/gstoggaviparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,478 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Wim Taymans <wim@fluendo.com>
- *
- * gstoggaviparse.c: ogg avi stream parser
- *
- * 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.
- */
-
-/*
- * Ogg in AVI is mostly done for vorbis audio. In the codec_data we receive the
- * first 3 packets of the raw vorbis data. On the sinkpad we receive full-blown Ogg
- * pages. 
- * Before extracting the packets out of the ogg pages, we push the raw vorbis
- * header packets to the decoder.
- * We don't use the incomming timestamps but use the ganulepos on the ogg pages
- * directly.
- * This parser only does ogg/vorbis for now.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <gst/gst.h>
-#include <ogg/ogg.h>
-#include <string.h>
-
-static const GstElementDetails gst_ogg_avi_parse_details =
-GST_ELEMENT_DETAILS ("Ogg AVI parser",
-    "Codec/Parser",
-    "parse an ogg avi stream into pages (info about ogg: http://xiph.org)",
-    "Wim Taymans <wim@fluendo.com>");
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_avi_parse_debug);
-#define GST_CAT_DEFAULT gst_ogg_avi_parse_debug
-
-#define GST_TYPE_OGG_AVI_PARSE (gst_ogg_avi_parse_get_type())
-#define GST_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse))
-#define GST_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse))
-#define GST_IS_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_AVI_PARSE))
-#define GST_IS_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_AVI_PARSE))
-
-static GType gst_ogg_avi_parse_get_type (void);
-
-typedef struct _GstOggAviParse GstOggAviParse;
-typedef struct _GstOggAviParseClass GstOggAviParseClass;
-
-struct _GstOggAviParse
-{
-  GstElement element;
-
-  GstPad *sinkpad;
-  GstPad *srcpad;
-
-  gboolean discont;
-  gint serial;
-
-  ogg_sync_state sync;
-  ogg_stream_state stream;
-};
-
-struct _GstOggAviParseClass
-{
-  GstElementClass parent_class;
-};
-
-static void gst_ogg_avi_parse_base_init (gpointer g_class);
-static void gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass);
-static void gst_ogg_avi_parse_init (GstOggAviParse * ogg);
-static GstElementClass *parent_class = NULL;
-
-static GType
-gst_ogg_avi_parse_get_type (void)
-{
-  static GType ogg_avi_parse_type = 0;
-
-  if (!ogg_avi_parse_type) {
-    static const GTypeInfo ogg_avi_parse_info = {
-      sizeof (GstOggAviParseClass),
-      gst_ogg_avi_parse_base_init,
-      NULL,
-      (GClassInitFunc) gst_ogg_avi_parse_class_init,
-      NULL,
-      NULL,
-      sizeof (GstOggAviParse),
-      0,
-      (GInstanceInitFunc) gst_ogg_avi_parse_init,
-    };
-
-    ogg_avi_parse_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstOggAviParse",
-        &ogg_avi_parse_info, 0);
-  }
-  return ogg_avi_parse_type;
-}
-
-enum
-{
-  PROP_0
-};
-
-static GstStaticPadTemplate ogg_avi_parse_src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-vorbis")
-    );
-
-static GstStaticPadTemplate ogg_avi_parse_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-ogg-avi")
-    );
-
-static void gst_ogg_avi_parse_finalize (GObject * object);
-static GstStateChangeReturn gst_ogg_avi_parse_change_state (GstElement *
-    element, GstStateChange transition);
-static gboolean gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps);
-
-static void
-gst_ogg_avi_parse_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_ogg_avi_parse_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&ogg_avi_parse_sink_template_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&ogg_avi_parse_src_template_factory));
-}
-
-static void
-gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gstelement_class->change_state = gst_ogg_avi_parse_change_state;
-
-  gobject_class->finalize = gst_ogg_avi_parse_finalize;
-}
-
-static void
-gst_ogg_avi_parse_init (GstOggAviParse * ogg)
-{
-  /* create the sink and source pads */
-  ogg->sinkpad =
-      gst_pad_new_from_static_template (&ogg_avi_parse_sink_template_factory,
-      "sink");
-  gst_pad_set_setcaps_function (ogg->sinkpad, gst_ogg_avi_parse_setcaps);
-  gst_pad_set_event_function (ogg->sinkpad, gst_ogg_avi_parse_event);
-  gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_avi_parse_chain);
-  gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
-
-  ogg->srcpad =
-      gst_pad_new_from_static_template (&ogg_avi_parse_src_template_factory,
-      "src");
-  gst_pad_use_fixed_caps (ogg->srcpad);
-  gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad);
-}
-
-static void
-gst_ogg_avi_parse_finalize (GObject * object)
-{
-  GstOggAviParse *ogg = GST_OGG_AVI_PARSE (object);
-
-  GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg);
-
-  ogg_sync_clear (&ogg->sync);
-  ogg_stream_clear (&ogg->stream);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstOggAviParse *ogg;
-  GstStructure *structure;
-  const GValue *codec_data;
-  GstBuffer *buffer;
-  guint8 *data;
-  guint size;
-  guint32 sizes[3];
-  GstCaps *outcaps;
-  gint i, offs;
-
-  ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  /* take codec data */
-  codec_data = gst_structure_get_value (structure, "codec_data");
-  if (codec_data == NULL)
-    goto no_data;
-
-  /* only buffers are valid */
-  if (G_VALUE_TYPE (codec_data) != GST_TYPE_BUFFER)
-    goto wrong_format;
-
-  /* Now parse the data */
-  buffer = gst_value_get_buffer (codec_data);
-
-  /* first 22 bytes are bits_per_sample, channel_mask, GUID
-   * Then we get 3 LE guint32 with the 3 header sizes
-   * then we get the bytes of the 3 headers. */
-  data = GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer);
-
-  GST_LOG_OBJECT (ogg, "configuring codec_data of size %u", size);
-
-  /* skip headers */
-  data += 22;
-  size -= 22;
-
-  /* we need at least 12 bytes for the packet sizes of the 3 headers */
-  if (size < 12)
-    goto buffer_too_small;
-
-  /* read sizes of the 3 headers */
-  sizes[0] = GST_READ_UINT32_LE (data);
-  sizes[1] = GST_READ_UINT32_LE (data + 4);
-  sizes[2] = GST_READ_UINT32_LE (data + 8);
-
-  GST_DEBUG_OBJECT (ogg, "header sizes: %u %u %u", sizes[0], sizes[1],
-      sizes[2]);
-
-  data += 12;
-  size -= 12;
-
-  /* and we need at least enough data for all the headers */
-  if (size < sizes[0] + sizes[1] + sizes[2])
-    goto buffer_too_small;
-
-  /* set caps */
-  outcaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
-  gst_pad_set_caps (ogg->srcpad, outcaps);
-
-  /* copy header data */
-  offs = 34;
-  for (i = 0; i < 3; i++) {
-    GstBuffer *out;
-
-    /* now output the raw vorbis header packets */
-    out = gst_buffer_create_sub (buffer, offs, sizes[i]);
-    gst_buffer_set_caps (out, outcaps);
-    gst_pad_push (ogg->srcpad, out);
-
-    offs += sizes[i];
-  }
-  gst_caps_unref (outcaps);
-
-  return TRUE;
-
-  /* ERRORS */
-no_data:
-  {
-    GST_DEBUG_OBJECT (ogg, "no codec_data found in caps");
-    return FALSE;
-  }
-wrong_format:
-  {
-    GST_DEBUG_OBJECT (ogg, "codec_data is not a buffer");
-    return FALSE;
-  }
-buffer_too_small:
-  {
-    GST_DEBUG_OBJECT (ogg, "codec_data is too small");
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event)
-{
-  GstOggAviParse *ogg;
-  gboolean ret;
-
-  ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      ret = gst_pad_push_event (ogg->srcpad, event);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      ogg_sync_reset (&ogg->sync);
-      ogg_stream_reset (&ogg->stream);
-      ogg->discont = TRUE;
-      ret = gst_pad_push_event (ogg->srcpad, event);
-      break;
-    default:
-      ret = gst_pad_push_event (ogg->srcpad, event);
-      break;
-  }
-  return ret;
-}
-
-static GstFlowReturn
-gst_ogg_avi_parse_push_packet (GstOggAviParse * ogg, ogg_packet * packet)
-{
-  GstBuffer *buffer;
-  GstFlowReturn result;
-
-  /* allocate space for header and body */
-  buffer = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (GST_BUFFER_DATA (buffer), packet->packet, packet->bytes);
-
-  GST_LOG_OBJECT (ogg, "created buffer %p from page", buffer);
-
-  GST_BUFFER_OFFSET_END (buffer) = packet->granulepos;
-
-  if (ogg->discont) {
-    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
-    ogg->discont = FALSE;
-  }
-
-  result = gst_pad_push (ogg->srcpad, buffer);
-
-  return result;
-}
-
-static GstFlowReturn
-gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-  GstOggAviParse *ogg;
-  guint8 *data;
-  guint size;
-  gchar *oggbuf;
-  gint ret = -1;
-
-  ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));
-
-  data = GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer);
-
-  GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size);
-
-  if (GST_BUFFER_IS_DISCONT (buffer)) {
-    ogg_sync_reset (&ogg->sync);
-    ogg->discont = TRUE;
-  }
-
-  /* write data to sync layer */
-  oggbuf = ogg_sync_buffer (&ogg->sync, size);
-  memcpy (oggbuf, data, size);
-  ogg_sync_wrote (&ogg->sync, size);
-  gst_buffer_unref (buffer);
-
-  /* try to get as many packets out of the stream as possible */
-  do {
-    ogg_page page;
-
-    /* try to swap out a page */
-    ret = ogg_sync_pageout (&ogg->sync, &page);
-    if (ret == 0) {
-      GST_DEBUG_OBJECT (ogg, "need more data");
-      break;
-    } else if (ret == -1) {
-      GST_DEBUG_OBJECT (ogg, "discont in pages");
-      ogg->discont = TRUE;
-    } else {
-      /* new unknown stream, init the ogg stream with the serial number of the
-       * page. */
-      if (ogg->serial == -1) {
-        ogg->serial = ogg_page_serialno (&page);
-        ogg_stream_init (&ogg->stream, ogg->serial);
-      }
-
-      /* submit page */
-      if (ogg_stream_pagein (&ogg->stream, &page) != 0) {
-        GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream");
-        ogg_sync_reset (&ogg->sync);
-        ogg->discont = TRUE;
-        continue;
-      }
-
-      /* try to get as many packets as possible out of the page */
-      do {
-        ogg_packet packet;
-
-        ret = ogg_stream_packetout (&ogg->stream, &packet);
-        GST_LOG_OBJECT (ogg, "packetout gave %d", ret);
-        switch (ret) {
-          case 0:
-            break;
-          case -1:
-            /* out of sync, We mark a DISCONT. */
-            ogg->discont = TRUE;
-            break;
-          case 1:
-            result = gst_ogg_avi_parse_push_packet (ogg, &packet);
-            if (GST_FLOW_IS_FATAL (result))
-              goto done;
-            break;
-          default:
-            GST_WARNING_OBJECT (ogg,
-                "invalid return value %d for ogg_stream_packetout, resetting stream",
-                ret);
-            break;
-        }
-      }
-      while (ret != 0);
-    }
-  }
-  while (ret != 0);
-
-done:
-  return result;
-}
-
-static GstStateChangeReturn
-gst_ogg_avi_parse_change_state (GstElement * element, GstStateChange transition)
-{
-  GstOggAviParse *ogg;
-  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
-
-  ogg = GST_OGG_AVI_PARSE (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      ogg_sync_init (&ogg->sync);
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      ogg_sync_reset (&ogg->sync);
-      ogg_stream_reset (&ogg->stream);
-      ogg->serial = -1;
-      ogg->discont = TRUE;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  result = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      ogg_sync_clear (&ogg->sync);
-      break;
-    default:
-      break;
-  }
-  return result;
-}
-
-gboolean
-gst_ogg_avi_parse_plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (gst_ogg_avi_parse_debug, "oggaviparse", 0,
-      "ogg avi parser");
-
-  return gst_element_register (plugin, "oggaviparse", GST_RANK_PRIMARY,
-      GST_TYPE_OGG_AVI_PARSE);
-}
--- a/gst_plugins_base/ext/ogg/gstoggdemux.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3323 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- *
- * gstoggdemux.c: ogg stream demuxer
- *
- * 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.
- */
-
-/**
- * SECTION:element-oggdemux
- * @short_description: a demuxer for ogg files
- *
- * <refsect2>
- * <para>
- * This element demuxes ogg files into their encoded audio and video components.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=test.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
- * </programlisting>
- * Decodes the vorbis audio stored inside an ogg container.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-12-30 (0.10.5)
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <string.h>
-#include <gst/gst-i18n-plugin.h>
-#include <gst/base/gsttypefindhelper.h>
-
-#include "gstoggdemux.h"
-
-static const GstElementDetails gst_ogg_demux_details =
-GST_ELEMENT_DETAILS ("Ogg demuxer",
-    "Codec/Demuxer",
-    "demux ogg streams (info about ogg: http://xiph.org)",
-    "Wim Taymans <wim@fluendo.com>");
-
-#define CHUNKSIZE (8500)        /* this is out of vorbisfile */
-#define SKELETON_FISHEAD_SIZE 64
-#define SKELETON_FISBONE_MIN_SIZE 52
-
-#define GST_FLOW_LIMIT GST_FLOW_CUSTOM_ERROR
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_debug);
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_setup_debug);
-#define GST_CAT_DEFAULT gst_ogg_demux_debug
-
-static ogg_page *
-gst_ogg_page_copy (ogg_page * page)
-{
-  ogg_page *p = g_new0 (ogg_page, 1);
-
-  /* make a copy of the page */
-  p->header = g_memdup (page->header, page->header_len);
-  p->header_len = page->header_len;
-  p->body = g_memdup (page->body, page->body_len);
-  p->body_len = page->body_len;
-
-  return p;
-}
-
-static void
-gst_ogg_page_free (ogg_page * page)
-{
-  g_free (page->header);
-  g_free (page->body);
-  g_free (page);
-}
-
-static GstStaticPadTemplate internaltemplate =
-GST_STATIC_PAD_TEMPLATE ("internal",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS_ANY);
-
-static gboolean gst_ogg_demux_collect_chain_info (GstOggDemux * ogg,
-    GstOggChain * chain);
-static gboolean gst_ogg_demux_activate_chain (GstOggDemux * ogg,
-    GstOggChain * chain, GstEvent * event);
-static void gst_ogg_chain_mark_discont (GstOggChain * chain);
-
-static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg,
-    GstEvent * event);
-static gboolean gst_ogg_demux_receive_event (GstElement * element,
-    GstEvent * event);
-
-static void gst_ogg_pad_class_init (GstOggPadClass * klass);
-static void gst_ogg_pad_init (GstOggPad * pad);
-static void gst_ogg_pad_dispose (GObject * object);
-static void gst_ogg_pad_finalize (GObject * object);
-
-#if 0
-static const GstFormat *gst_ogg_pad_formats (GstPad * pad);
-static const GstEventMask *gst_ogg_pad_event_masks (GstPad * pad);
-#endif
-static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad);
-static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query);
-static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_ogg_pad_getcaps (GstPad * pad);
-static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain,
-    glong serialno);
-
-static gboolean gst_ogg_pad_query_convert (GstOggPad * pad,
-    GstFormat src_format, gint64 src_val,
-    GstFormat * dest_format, gint64 * dest_val);
-static GstClockTime gst_annodex_granule_to_time (gint64 granulepos,
-    gint64 granulerate_n, gint64 granulerate_d, guint8 granuleshift);
-
-static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg,
-    GstOggPad * pad, GstFlowReturn ret);
-
-static GstPadClass *ogg_pad_parent_class = NULL;
-
-static GType
-gst_ogg_pad_get_type (void)
-{
-  static GType ogg_pad_type = 0;
-
-  if (!ogg_pad_type) {
-    static const GTypeInfo ogg_pad_info = {
-      sizeof (GstOggPadClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_ogg_pad_class_init,
-      NULL,
-      NULL,
-      sizeof (GstOggPad),
-      0,
-      (GInstanceInitFunc) gst_ogg_pad_init,
-    };
-
-    ogg_pad_type =
-        g_type_register_static (GST_TYPE_PAD, "GstOggPad", &ogg_pad_info, 0);
-  }
-  return ogg_pad_type;
-}
-
-static void
-gst_ogg_pad_class_init (GstOggPadClass * klass)
-{
-  GObjectClass *gobject_class;
-
-  gobject_class = (GObjectClass *) klass;
-
-  ogg_pad_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->dispose = gst_ogg_pad_dispose;
-  gobject_class->finalize = gst_ogg_pad_finalize;
-}
-
-static void
-gst_ogg_pad_init (GstOggPad * pad)
-{
-  gst_pad_set_event_function (GST_PAD (pad),
-      GST_DEBUG_FUNCPTR (gst_ogg_pad_event));
-  gst_pad_set_getcaps_function (GST_PAD (pad),
-      GST_DEBUG_FUNCPTR (gst_ogg_pad_getcaps));
-  gst_pad_set_query_type_function (GST_PAD (pad),
-      GST_DEBUG_FUNCPTR (gst_ogg_pad_query_types));
-  gst_pad_set_query_function (GST_PAD (pad),
-      GST_DEBUG_FUNCPTR (gst_ogg_pad_src_query));
-
-  pad->mode = GST_OGG_PAD_MODE_INIT;
-
-  pad->first_granule = -1;
-  pad->current_granule = -1;
-
-  pad->start_time = GST_CLOCK_TIME_NONE;
-  pad->first_time = GST_CLOCK_TIME_NONE;
-
-  pad->have_type = FALSE;
-  pad->continued = NULL;
-  pad->headers = NULL;
-}
-
-static void
-gst_ogg_pad_dispose (GObject * object)
-{
-  GstOggPad *pad = GST_OGG_PAD (object);
-  GstPad **elem_pad_p;
-  GstElement **element_p;
-  GstPad **elem_out_p;
-
-  if (pad->element)
-    gst_element_set_state (pad->element, GST_STATE_NULL);
-
-  elem_pad_p = &pad->elem_pad;
-  element_p = &pad->element;
-  elem_out_p = &pad->elem_out;
-  gst_object_replace ((GstObject **) elem_pad_p, NULL);
-  gst_object_replace ((GstObject **) element_p, NULL);
-  gst_object_replace ((GstObject **) elem_out_p, NULL);
-
-  pad->chain = NULL;
-  pad->ogg = NULL;
-
-  g_list_foreach (pad->headers, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (pad->headers);
-  pad->headers = NULL;
-
-  /* clear continued pages */
-  g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL);
-  g_list_free (pad->continued);
-  pad->continued = NULL;
-
-  ogg_stream_reset (&pad->stream);
-
-  G_OBJECT_CLASS (ogg_pad_parent_class)->dispose (object);
-}
-
-static void
-gst_ogg_pad_finalize (GObject * object)
-{
-  GstOggPad *pad = GST_OGG_PAD (object);
-
-  ogg_stream_clear (&pad->stream);
-
-  G_OBJECT_CLASS (ogg_pad_parent_class)->finalize (object);
-}
-
-#if 0
-static const GstFormat *
-gst_ogg_pad_formats (GstPad * pad)
-{
-  static GstFormat src_formats[] = {
-    GST_FORMAT_DEFAULT,         /* time */
-    GST_FORMAT_TIME,            /* granulepos */
-    0
-  };
-  static GstFormat sink_formats[] = {
-    GST_FORMAT_BYTES,
-    GST_FORMAT_DEFAULT,         /* bytes */
-    0
-  };
-
-  return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
-}
-#endif
-
-#if 0
-static const GstEventMask *
-gst_ogg_pad_event_masks (GstPad * pad)
-{
-  static const GstEventMask src_event_masks[] = {
-    {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
-    {0,}
-  };
-
-  return src_event_masks;
-}
-#endif
-
-static const GstQueryType *
-gst_ogg_pad_query_types (GstPad * pad)
-{
-  static const GstQueryType query_types[] = {
-    GST_QUERY_DURATION,
-    GST_QUERY_SEEKING,
-    0
-  };
-
-  return query_types;
-}
-
-static GstCaps *
-gst_ogg_pad_getcaps (GstPad * pad)
-{
-  return gst_caps_ref (GST_PAD_CAPS (pad));
-}
-
-static gboolean
-gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
-{
-  gboolean res = TRUE;
-  GstOggDemux *ogg;
-  GstOggPad *cur;
-
-  ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
-  cur = GST_OGG_PAD (pad);
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_DURATION:
-    {
-      GstFormat format;
-
-      gst_query_parse_duration (query, &format, NULL);
-      /* can only get position in time */
-      if (format != GST_FORMAT_TIME)
-        goto wrong_format;
-
-      /* can only return the total time position */
-      /* FIXME, return time for this specific stream */
-      gst_query_set_duration (query, GST_FORMAT_TIME, ogg->total_time);
-      break;
-    }
-    case GST_QUERY_SEEKING:
-    {
-      GstFormat format;
-
-      gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
-      if (format == GST_FORMAT_TIME) {
-        gst_query_set_seeking (query, GST_FORMAT_TIME, ogg->seekable,
-            0, ogg->total_time);
-      } else {
-        res = FALSE;
-      }
-      break;
-    }
-
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-done:
-  gst_object_unref (ogg);
-
-  return res;
-
-  /* ERRORS */
-wrong_format:
-  {
-    GST_DEBUG_OBJECT (ogg, "only query duration on TIME is supported");
-    res = FALSE;
-    goto done;
-  }
-}
-
-static gboolean
-gst_ogg_demux_receive_event (GstElement * element, GstEvent * event)
-{
-  gboolean res;
-  GstOggDemux *ogg;
-
-  ogg = GST_OGG_DEMUX (element);
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_SEEK:
-      /* can't seek if we are not seekable, FIXME could pass the
-       * seek query upstream after converting it to bytes using
-       * the average bitrate of the stream. */
-      if (!ogg->seekable) {
-        GST_DEBUG_OBJECT (ogg, "seek on non seekable stream");
-        goto error;
-      }
-
-      /* now do the seek */
-      res = gst_ogg_demux_perform_seek (ogg, event);
-      gst_event_unref (event);
-      break;
-    default:
-      GST_DEBUG_OBJECT (ogg, "We only handle seek events here");
-      goto error;
-  }
-
-  return res;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (ogg, "error handling event");
-    gst_event_unref (event);
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_ogg_pad_event (GstPad * pad, GstEvent * event)
-{
-  gboolean res;
-  GstOggDemux *ogg;
-  GstOggPad *cur;
-
-  ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
-  cur = GST_OGG_PAD (pad);
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_SEEK:
-      /* can't seek if we are not seekable, FIXME could pass the
-       * seek query upstream after converting it to bytes using
-       * the average bitrate of the stream. */
-      if (!ogg->seekable) {
-        GST_DEBUG_OBJECT (ogg, "seek on non seekable stream");
-        goto error;
-      }
-
-      /* now do the seek */
-      res = gst_ogg_demux_perform_seek (ogg, event);
-      gst_event_unref (event);
-      break;
-    default:
-      res = gst_pad_event_default (pad, event);
-      break;
-  }
-done:
-  gst_object_unref (ogg);
-
-  return res;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (ogg, "error handling event");
-    gst_event_unref (event);
-    res = FALSE;
-    goto done;
-  }
-}
-
-static void
-gst_ogg_pad_reset (GstOggPad * pad)
-{
-  ogg_stream_reset (&pad->stream);
-
-  /* clear continued pages */
-  g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL);
-  g_list_free (pad->continued);
-  pad->continued = NULL;
-
-  pad->last_ret = GST_FLOW_OK;
-}
-
-/* the filter function for selecting the elements we can use in
- * autoplugging */
-static gboolean
-gst_ogg_demux_factory_filter (GstPluginFeature * feature, GstCaps * caps)
-{
-  guint rank;
-  const gchar *klass;
-
-  /* we only care about element factories */
-  if (!GST_IS_ELEMENT_FACTORY (feature))
-    return FALSE;
-
-  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
-  /* only demuxers and decoders can play */
-  if (strstr (klass, "Demux") == NULL &&
-      strstr (klass, "Decoder") == NULL && strstr (klass, "Parse") == NULL) {
-    return FALSE;
-  }
-
-  /* only select elements with autoplugging rank */
-  rank = gst_plugin_feature_get_rank (feature);
-  if (rank < GST_RANK_MARGINAL)
-    return FALSE;
-
-  GST_DEBUG ("checking factory %s", GST_PLUGIN_FEATURE_NAME (feature));
-  /* now see if it is compatible with the caps */
-  {
-    GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
-    const GList *templates;
-    GList *walk;
-
-    /* get the templates from the element factory */
-    templates = gst_element_factory_get_static_pad_templates (factory);
-
-    for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
-      GstStaticPadTemplate *templ = walk->data;
-
-      /* we only care about the sink templates */
-      if (templ->direction == GST_PAD_SINK) {
-        GstCaps *intersect;
-        GstCaps *scaps;
-        gboolean empty;
-
-        /* try to intersect the caps with the caps of the template */
-        scaps = gst_static_caps_get (&templ->static_caps);
-        intersect = gst_caps_intersect (caps, scaps);
-        gst_caps_unref (scaps);
-
-        empty = gst_caps_is_empty (intersect);
-        gst_caps_unref (intersect);
-
-        /* check if the intersection is empty */
-        if (!empty) {
-          /* non empty intersection, we can use this element */
-          goto found;
-        }
-      }
-    }
-  }
-  return FALSE;
-
-found:
-  return TRUE;
-}
-
-/* function used to sort element features */
-static gint
-compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
-{
-  gint diff;
-
-  diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
-  if (diff != 0)
-    return diff;
-  return strcmp (gst_plugin_feature_get_name (f2),
-      gst_plugin_feature_get_name (f1));
-}
-
-/* called when the skeleton fishead is found. Caller ensures the packet is
- * precisely the correct size; we don't re-check this here. */
-static void
-gst_ogg_pad_parse_skeleton_fishead (GstOggPad * pad, ogg_packet * packet)
-{
-  GstOggDemux *ogg = pad->ogg;
-  guint8 *data = packet->packet;
-  guint16 major, minor;
-  gint64 prestime_n, prestime_d;
-  gint64 basetime_n, basetime_d;
-
-  /* skip "fishead\0" */
-  data += 8;
-  major = GST_READ_UINT16_LE (data);
-  data += 2;
-  minor = GST_READ_UINT16_LE (data);
-  data += 2;
-  prestime_n = (gint64) GST_READ_UINT64_LE (data);
-  data += 8;
-  prestime_d = (gint64) GST_READ_UINT64_LE (data);
-  data += 8;
-  basetime_n = (gint64) GST_READ_UINT64_LE (data);
-  data += 8;
-  basetime_d = (gint64) GST_READ_UINT64_LE (data);
-  data += 8;
-
-  ogg->basetime = gst_util_uint64_scale (GST_SECOND, basetime_n, basetime_d);
-  ogg->have_fishead = TRUE;
-  pad->is_skeleton = TRUE;
-  pad->start_time = GST_CLOCK_TIME_NONE;
-  pad->first_granule = -1;
-  pad->first_time = GST_CLOCK_TIME_NONE;
-  GST_INFO_OBJECT (ogg, "skeleton fishead parsed (basetime: %"
-      GST_TIME_FORMAT ")", GST_TIME_ARGS (ogg->basetime));
-}
-
-/* function called when a skeleton fisbone is found. Caller ensures that
- * the packet length is sufficient */
-static void
-gst_ogg_pad_parse_skeleton_fisbone (GstOggPad * pad, ogg_packet * packet)
-{
-  GstOggPad *fisbone_pad;
-  gint64 start_granule;
-  guint32 serialno;
-  guint8 *data = packet->packet;
-
-  /* skip "fisbone\0" */
-  data += 8;
-  /* skip headers offset */
-  data += 4;
-  serialno = GST_READ_UINT32_LE (data);
-
-  fisbone_pad = gst_ogg_chain_get_stream (pad->chain, serialno);
-  if (fisbone_pad) {
-    if (fisbone_pad->have_fisbone)
-      /* already parsed */
-      return;
-
-    fisbone_pad->have_fisbone = TRUE;
-
-    data += 4;
-    /* skip number of headers */
-    data += 4;
-    fisbone_pad->granulerate_n = GST_READ_UINT64_LE (data);
-    data += 8;
-    fisbone_pad->granulerate_d = GST_READ_UINT64_LE (data);
-    data += 8;
-    start_granule = GST_READ_UINT64_LE (data);
-    data += 8;
-    fisbone_pad->preroll = GST_READ_UINT32_LE (data);
-    data += 4;
-    fisbone_pad->granuleshift = GST_READ_UINT8 (data);
-    data += 1;
-    /* padding */
-    data += 3;
-
-    fisbone_pad->start_time = gst_annodex_granule_to_time (start_granule,
-        fisbone_pad->granulerate_n, fisbone_pad->granulerate_d,
-        fisbone_pad->granuleshift);
-
-    GST_INFO_OBJECT (pad->ogg, "skeleton fisbone parsed "
-        "(serialno: %08x start time: %" GST_TIME_FORMAT
-        " granulerate_n: %" G_GINT64_FORMAT " granulerate_d: %" G_GINT64_FORMAT
-        " preroll: %" G_GUINT32_FORMAT " granuleshift: %d)",
-        serialno, GST_TIME_ARGS (fisbone_pad->start_time),
-        fisbone_pad->granulerate_n, fisbone_pad->granulerate_d,
-        fisbone_pad->preroll, fisbone_pad->granuleshift);
-  } else {
-    GST_WARNING_OBJECT (pad->ogg,
-        "found skeleton fisbone for an unknown stream %" G_GUINT32_FORMAT,
-        serialno);
-  }
-}
-
-/* function called to convert a granulepos to a timestamp */
-static gboolean
-gst_ogg_pad_query_convert (GstOggPad * pad, GstFormat src_format,
-    gint64 src_val, GstFormat * dest_format, gint64 * dest_val)
-{
-  gboolean res;
-
-  if (src_val == -1) {
-    *dest_val = -1;
-    return TRUE;
-  }
-
-  if (!pad->have_fisbone && pad->elem_pad == NULL)
-    return FALSE;
-
-  switch (src_format) {
-    case GST_FORMAT_DEFAULT:
-      if (pad->have_fisbone && *dest_format == GST_FORMAT_TIME) {
-        *dest_val = gst_annodex_granule_to_time (src_val,
-            pad->granulerate_n, pad->granulerate_d, pad->granuleshift);
-
-        res = TRUE;
-      } else {
-        if (pad->elem_pad == NULL)
-          res = FALSE;
-        else
-          res = gst_pad_query_convert (pad->elem_pad, src_format, src_val,
-              dest_format, dest_val);
-      }
-
-      break;
-    default:
-      if (pad->elem_pad == NULL)
-        res = FALSE;
-      else
-        res = gst_pad_query_convert (pad->elem_pad, src_format, src_val,
-            dest_format, dest_val);
-  }
-
-  return res;
-}
-
-/* function called by the internal decoder elements when it outputs
- * a buffer. We use it to get the first timestamp of the stream 
- */
-static GstFlowReturn
-gst_ogg_pad_internal_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstOggPad *oggpad;
-  GstOggDemux *ogg;
-  GstClockTime timestamp;
-
-  oggpad = gst_pad_get_element_private (pad);
-  ogg = GST_OGG_DEMUX (oggpad->ogg);
-
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  GST_DEBUG_OBJECT (oggpad, "received buffer from internal pad, TS=%"
-      GST_TIME_FORMAT "=%" G_GINT64_FORMAT, GST_TIME_ARGS (timestamp),
-      timestamp);
-
-  if (oggpad->start_time == GST_CLOCK_TIME_NONE) {
-    oggpad->start_time = timestamp;
-    GST_DEBUG_OBJECT (oggpad, "new start time: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (timestamp));
-  }
-
-  gst_buffer_unref (buffer);
-
-  return GST_FLOW_OK;
-}
-
-static void
-internal_element_pad_added_cb (GstElement * element, GstPad * pad,
-    GstOggPad * oggpad)
-{
-  if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
-    if (!(gst_pad_link (pad, oggpad->elem_out) == GST_PAD_LINK_OK)) {
-      GST_ERROR ("Really couldn't find a valid pad");
-    }
-    oggpad->dynamic = FALSE;
-    g_signal_handler_disconnect (element, oggpad->padaddedid);
-    oggpad->padaddedid = 0;
-  }
-}
-
-/* runs typefind on the packet, which is assumed to be the first
- * packet in the stream.
- * 
- * Based on the type returned from the typefind function, an element
- * is created to help in conversion between granulepos and timestamps
- * so that we can do decent seeking.
- */
-static gboolean
-gst_ogg_pad_typefind (GstOggPad * pad, ogg_packet * packet)
-{
-  GstBuffer *buf;
-  GstCaps *caps;
-  GstElement *element = NULL;
-
-#ifndef GST_DISABLE_GST_DEBUG
-  GstOggDemux *ogg = pad->ogg;
-#endif
-
-  if (GST_PAD_CAPS (pad) != NULL)
-    return TRUE;
-
-  /* The ogg spec defines that the first packet of an ogg stream must identify
-   * the stream. Therefore ogg can use a simplified approach to typefinding
-   * and only needs to check the first packet */
-  buf = gst_buffer_new ();
-  GST_BUFFER_DATA (buf) = packet->packet;
-  GST_BUFFER_SIZE (buf) = packet->bytes;
-  GST_BUFFER_OFFSET (buf) = 0;
-
-  caps = gst_type_find_helper_for_buffer (GST_OBJECT (pad), buf, NULL);
-  gst_buffer_unref (buf);
-
-  if (caps == NULL) {
-    GST_WARNING_OBJECT (ogg,
-        "couldn't find caps for stream with serial %08x", pad->serialno);
-    caps = gst_caps_new_simple ("application/octet-stream", NULL);
-  } else {
-    /* ogg requires you to use a decoder element to define the
-     * meaning of granulepos etc so we make one. We also do this if
-     * we are in the streaming mode to calculate the first timestamp. */
-    GList *factories;
-
-    GST_LOG_OBJECT (ogg, "found caps: %" GST_PTR_FORMAT, caps);
-
-    /* first filter out the interesting element factories */
-    factories = gst_default_registry_feature_filter (
-        (GstPluginFeatureFilter) gst_ogg_demux_factory_filter, FALSE, caps);
-
-    /* sort them according to their ranks */
-    factories = g_list_sort (factories, (GCompareFunc) compare_ranks);
-
-    /* then pick the first factory to create an element */
-    if (factories) {
-      element =
-          gst_element_factory_create (GST_ELEMENT_FACTORY (factories->data),
-          NULL);
-      if (element) {
-        GstPadTemplate *template;
-
-        /* this is ours */
-        gst_object_ref (element);
-        gst_object_sink (GST_OBJECT (element));
-
-        /* FIXME, it might not be named "sink" */
-        pad->elem_pad = gst_element_get_pad (element, "sink");
-        gst_element_set_state (element, GST_STATE_PAUSED);
-        template = gst_static_pad_template_get (&internaltemplate);
-        pad->elem_out = gst_pad_new_from_template (template, "internal");
-        gst_pad_set_chain_function (pad->elem_out, gst_ogg_pad_internal_chain);
-        gst_pad_set_element_private (pad->elem_out, pad);
-        gst_pad_set_active (pad->elem_out, TRUE);
-        gst_object_unref (template);
-
-        /* and this pad may not be named src.. */
-        /* And it might also not exist at this time... */
-        {
-          GstPad *p;
-
-          p = gst_element_get_pad (element, "src");
-          if (p) {
-            gst_pad_link (p, pad->elem_out);
-            gst_object_unref (p);
-          } else {
-            pad->dynamic = TRUE;
-            pad->padaddedid = g_signal_connect (G_OBJECT (element),
-                "pad-added", G_CALLBACK (internal_element_pad_added_cb), pad);
-          }
-        }
-      }
-    }
-    g_list_free (factories);
-  }
-  pad->element = element;
-
-  gst_pad_set_caps (GST_PAD (pad), caps);
-  gst_caps_unref (caps);
-
-  return TRUE;
-}
-
-/* send packet to internal element */
-static GstFlowReturn
-gst_ogg_demux_chain_elem_pad (GstOggPad * pad, ogg_packet * packet)
-{
-  GstBuffer *buf;
-  GstFlowReturn ret;
-
-#ifndef GST_DISABLE_GST_DEBUG
-  GstOggDemux *ogg = pad->ogg;
-#endif
-
-  /* initialize our internal decoder with packets */
-  if (!pad->elem_pad)
-    goto no_decoder;
-
-  GST_DEBUG_OBJECT (ogg, "%p init decoder serial %08x", pad, pad->serialno);
-
-  buf = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
-  GST_BUFFER_OFFSET (buf) = -1;
-  GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
-
-  ret = gst_pad_chain (pad->elem_pad, buf);
-  if (GST_FLOW_IS_FATAL (ret))
-    goto decoder_error;
-
-  return ret;
-
-no_decoder:
-  {
-    GST_WARNING_OBJECT (ogg,
-        "pad %p does not have elem_pad, no decoder ?", pad);
-    return GST_FLOW_ERROR;
-  }
-decoder_error:
-  {
-    GST_WARNING_OBJECT (ogg, "internal decoder error");
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* queue data, basically takes the packet, puts it in a buffer and store the
- * buffer in the headers list.
- */
-static GstFlowReturn
-gst_ogg_demux_queue_data (GstOggPad * pad, ogg_packet * packet)
-{
-  GstBuffer *buf;
-
-#ifndef GST_DISABLE_GST_DEBUG
-  GstOggDemux *ogg = pad->ogg;
-#endif
-
-  GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08x", pad, pad->serialno);
-
-  buf = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (buf->data, packet->packet, packet->bytes);
-  GST_BUFFER_OFFSET (buf) = -1;
-  GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
-  pad->headers = g_list_append (pad->headers, buf);
-
-  /* we are ok now */
-  return GST_FLOW_OK;
-}
-
-/* send packet to internal element */
-static GstFlowReturn
-gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet)
-{
-  GstBuffer *buf;
-  GstFlowReturn ret, cret;
-  GstOggDemux *ogg = pad->ogg;
-  GstFormat format;
-  gint64 current_time;
-  GstOggChain *chain;
-
-  GST_DEBUG_OBJECT (ogg,
-      "%p streaming to peer serial %08x", pad, pad->serialno);
-
-  ret =
-      gst_pad_alloc_buffer_and_set_caps (GST_PAD_CAST (pad),
-      GST_BUFFER_OFFSET_NONE, packet->bytes, GST_PAD_CAPS (pad), &buf);
-
-  /* combine flows */
-  cret = gst_ogg_demux_combine_flows (ogg, pad, ret);
-  if (ret != GST_FLOW_OK)
-    goto no_buffer;
-
-  /* copy packet in buffer */
-  memcpy (buf->data, packet->packet, packet->bytes);
-
-  GST_BUFFER_OFFSET (buf) = -1;
-  GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
-
-  /* Mark discont on the buffer */
-  if (pad->discont) {
-    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
-    pad->discont = FALSE;
-  }
-
-  ret = gst_pad_push (GST_PAD_CAST (pad), buf);
-
-  /* combine flows */
-  cret = gst_ogg_demux_combine_flows (ogg, pad, ret);
-
-  /* we're done with skeleton stuff */
-  if (pad->is_skeleton)
-    goto done;
-
-  /* check if valid granulepos, then we can calculate the current
-   * position */
-  if (packet->granulepos < 0)
-    goto done;
-
-  /* store current granule pos */
-  ogg->current_granule = packet->granulepos;
-
-  /* convert to time */
-  format = GST_FORMAT_TIME;
-  if (!gst_ogg_pad_query_convert (pad,
-          GST_FORMAT_DEFAULT, packet->granulepos, &format,
-          (gint64 *) & current_time))
-    goto convert_failed;
-
-  /* convert to stream time */
-  if ((chain = pad->chain))
-    current_time = current_time - chain->segment_start + chain->begin_time;
-
-  /* and store as the current position */
-  gst_segment_set_last_stop (&ogg->segment, GST_FORMAT_TIME, current_time);
-
-  GST_DEBUG_OBJECT (ogg, "ogg current time %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (current_time));
-
-done:
-  /* return combined flow result */
-  return cret;
-
-  /* special cases */
-no_buffer:
-  {
-    GST_DEBUG_OBJECT (ogg,
-        "%p could not get buffer from peer %08x, %d (%s), combined %d (%s)",
-        pad, pad->serialno, ret, gst_flow_get_name (ret),
-        cret, gst_flow_get_name (cret));
-    goto done;
-  }
-convert_failed:
-  {
-    GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
-    goto done;
-  }
-}
-
-/* submit a packet to the oggpad, this function will run the
- * typefind code for the pad if this is the first packet for this
- * stream 
- */
-static GstFlowReturn
-gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
-{
-  gint64 granule;
-  GstFlowReturn ret;
-
-  GstOggDemux *ogg = pad->ogg;
-
-  GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08x", pad, pad->serialno);
-
-  if (!pad->have_type) {
-    if (!ogg->have_fishead && packet->bytes == SKELETON_FISHEAD_SIZE &&
-        !memcmp (packet->packet, "fishead\0", 8)) {
-      gst_ogg_pad_parse_skeleton_fishead (pad, packet);
-    }
-    gst_ogg_pad_typefind (pad, packet);
-    pad->have_type = TRUE;
-  }
-
-  if (ogg->have_fishead && packet->bytes >= SKELETON_FISBONE_MIN_SIZE &&
-      !memcmp (packet->packet, "fisbone\0", 8)) {
-    gst_ogg_pad_parse_skeleton_fisbone (pad, packet);
-  }
-
-  granule = packet->granulepos;
-  if (granule != -1) {
-    GST_DEBUG_OBJECT (ogg, "%p has granulepos %" G_GINT64_FORMAT, pad, granule);
-    ogg->current_granule = granule;
-    pad->current_granule = granule;
-    /* granulepos 0 and -1 are considered header packets.
-     * Note that since theora is busted, it can create non-header
-     * packets with 0 granulepos. We will correct for this when our
-     * internal decoder produced a frame and we don't have a
-     * granulepos because in that case the granulpos must have been 0 */
-    if (pad->first_granule == -1 && granule != 0) {
-      GST_DEBUG_OBJECT (ogg, "%p found first granulepos %" G_GINT64_FORMAT, pad,
-          granule);
-      pad->first_granule = granule;
-    }
-  }
-
-  if (granule != -1 && memcmp (packet->packet, "KW-DIRAC", 8) == 0) {
-    return GST_FLOW_OK;
-  }
-
-  /* no start time known, stream to internal plugin to
-   * get time. always stream to the skeleton decoder */
-  if (pad->start_time == GST_CLOCK_TIME_NONE || pad->is_skeleton) {
-    ret = gst_ogg_demux_chain_elem_pad (pad, packet);
-  }
-  /* we know the start_time of the pad data, see if we
-   * can activate the complete chain if this is a dynamic
-   * chain. */
-  if (pad->start_time != GST_CLOCK_TIME_NONE) {
-    GstOggChain *chain = pad->chain;
-
-    /* correction for busted ogg, if the internal decoder outputed
-     * a timestamp but we did not get a granulepos, it must have
-     * been 0 and the time is therefore also 0 */
-    if (pad->first_granule == -1) {
-      GST_DEBUG_OBJECT (ogg, "%p found start time without granulepos", pad);
-      pad->first_granule = 0;
-      pad->first_time = 0;
-    }
-
-    /* check if complete chain has start time */
-    if (chain == ogg->building_chain) {
-
-      /* see if we have enough info to activate the chain, we have enough info
-       * when all streams have a valid start time. */
-      if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
-        GstEvent *event;
-
-        GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (chain->segment_start));
-        GST_DEBUG_OBJECT (ogg, "segment_stop:  %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (chain->segment_stop));
-        GST_DEBUG_OBJECT (ogg, "segment_time:  %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (chain->begin_time));
-
-        /* create the newsegment event we are going to send out */
-        event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-            GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
-            chain->begin_time);
-
-        gst_ogg_demux_activate_chain (ogg, chain, event);
-
-        ogg->building_chain = NULL;
-      }
-    }
-  }
-
-  /* if we are building a chain, store buffer for when we activate
-   * it. This path is taken if we operate in streaming mode. */
-  if (ogg->building_chain) {
-    ret = gst_ogg_demux_queue_data (pad, packet);
-  }
-  /* else we are completely streaming to the peer */
-  else {
-    ret = gst_ogg_demux_chain_peer (pad, packet);
-  }
-  return ret;
-}
-
-/* flush at most @npackets from the stream layer. All packets if 
- * @npackets is 0;
- */
-static GstFlowReturn
-gst_ogg_pad_stream_out (GstOggPad * pad, gint npackets)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-  gboolean done = FALSE;
-  GstOggDemux *ogg;
-
-  ogg = pad->ogg;
-
-  while (!done) {
-    int ret;
-    ogg_packet packet;
-
-    ret = ogg_stream_packetout (&pad->stream, &packet);
-    switch (ret) {
-      case 0:
-        GST_LOG_OBJECT (ogg, "packetout done");
-        done = TRUE;
-        break;
-      case -1:
-        GST_LOG_OBJECT (ogg, "packetout discont");
-        gst_ogg_chain_mark_discont (pad->chain);
-        break;
-      case 1:
-        GST_LOG_OBJECT (ogg, "packetout gave packet of size %ld", packet.bytes);
-        result = gst_ogg_pad_submit_packet (pad, &packet);
-        if (GST_FLOW_IS_FATAL (result))
-          goto could_not_submit;
-        break;
-      default:
-        GST_WARNING_OBJECT (ogg,
-            "invalid return value %d for ogg_stream_packetout, resetting stream",
-            ret);
-        gst_ogg_pad_reset (pad);
-        break;
-    }
-    if (npackets > 0) {
-      npackets--;
-      done = (npackets == 0);
-    }
-  }
-  return result;
-
-  /* ERRORS */
-could_not_submit:
-  {
-    GST_WARNING_OBJECT (ogg,
-        "could not submit packet for stream %08x, error: %d", pad->serialno,
-        result);
-    gst_ogg_pad_reset (pad);
-    return result;
-  }
-}
-
-/* submit a page to an oggpad, this function will then submit all
- * the packets in the page.
- */
-static GstFlowReturn
-gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-  GstOggDemux *ogg;
-  gboolean continued = FALSE;
-
-  ogg = pad->ogg;
-
-  /* for negative rates we read pages backwards and must therefore be carefull
-   * with continued pages */
-  if (ogg->segment.rate < 0.0) {
-    gint npackets;
-
-    continued = ogg_page_continued (page);
-
-    /* number of completed packets in the page */
-    npackets = ogg_page_packets (page);
-    if (!continued) {
-      /* page is not continued so it contains at least one packet start. It's
-       * possible that no packet ends on this page (npackets == 0). In that
-       * case, the next (continued) page(s) we kept contain the remainder of the
-       * packets. We mark npackets=1 to make us start decoding the pages in the
-       * remainder of the algorithm. */
-      if (npackets == 0)
-        npackets = 1;
-    }
-    GST_LOG_OBJECT (ogg, "continued: %d, %d packets", continued, npackets);
-
-    if (npackets == 0) {
-      GST_LOG_OBJECT (ogg, "no decodable packets, we need a previous page");
-      goto done;
-    }
-  }
-
-  if (ogg_stream_pagein (&pad->stream, page) != 0)
-    goto choked;
-
-  /* flush all packets in the stream layer, this might not give a packet if
-   * the page had no packets finishing on the page (npackets == 0). */
-  result = gst_ogg_pad_stream_out (pad, 0);
-
-  if (pad->continued) {
-    ogg_packet packet;
-
-    /* now send the continued pages to the stream layer */
-    while (pad->continued) {
-      ogg_page *p = (ogg_page *) pad->continued->data;
-
-      GST_LOG_OBJECT (ogg, "submitting continued page %p", p);
-      if (ogg_stream_pagein (&pad->stream, p) != 0)
-        goto choked;
-
-      pad->continued = g_list_delete_link (pad->continued, pad->continued);
-
-      /* free the page */
-      gst_ogg_page_free (p);
-    }
-
-    GST_LOG_OBJECT (ogg, "flushing last continued packet");
-    /* flush 1 continued packet in the stream layer */
-    result = gst_ogg_pad_stream_out (pad, 1);
-
-    /* flush all remaining packets, we pushed them in the previous round.
-     * We don't use _reset() because we still want to get the discont when
-     * we submit a next page. */
-    while (ogg_stream_packetout (&pad->stream, &packet) != 0);
-  }
-
-done:
-  /* keep continued pages (only in reverse mode) */
-  if (continued) {
-    ogg_page *p = gst_ogg_page_copy (page);
-
-    GST_LOG_OBJECT (ogg, "keeping continued page %p", p);
-    pad->continued = g_list_prepend (pad->continued, p);
-  }
-
-  return result;
-
-choked:
-  {
-    GST_WARNING_OBJECT (ogg,
-        "ogg stream choked on page (serial %08x), resetting stream",
-        pad->serialno);
-    gst_ogg_pad_reset (pad);
-    /* we continue to recover */
-    return GST_FLOW_OK;
-  }
-}
-
-
-static GstOggChain *
-gst_ogg_chain_new (GstOggDemux * ogg)
-{
-  GstOggChain *chain = g_new0 (GstOggChain, 1);
-
-  GST_DEBUG_OBJECT (ogg, "creating new chain %p", chain);
-  chain->ogg = ogg;
-  chain->offset = -1;
-  chain->bytes = -1;
-  chain->have_bos = FALSE;
-  chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *));
-  chain->begin_time = GST_CLOCK_TIME_NONE;
-  chain->segment_start = GST_CLOCK_TIME_NONE;
-  chain->segment_stop = GST_CLOCK_TIME_NONE;
-  chain->total_time = GST_CLOCK_TIME_NONE;
-
-  return chain;
-}
-
-static void
-gst_ogg_chain_free (GstOggChain * chain)
-{
-  gint i;
-
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    gst_object_unref (pad);
-  }
-  g_array_free (chain->streams, TRUE);
-  g_free (chain);
-}
-
-static void
-gst_ogg_chain_mark_discont (GstOggChain * chain)
-{
-  gint i;
-
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    pad->discont = TRUE;
-  }
-}
-
-static void
-gst_ogg_chain_reset (GstOggChain * chain)
-{
-  gint i;
-
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    gst_ogg_pad_reset (pad);
-  }
-}
-
-static GstOggPad *
-gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno)
-{
-  GstOggPad *ret;
-  GstTagList *list;
-  gchar *name;
-
-  GST_DEBUG_OBJECT (chain->ogg, "creating new stream %08lx in chain %p",
-      serialno, chain);
-
-  ret = g_object_new (GST_TYPE_OGG_PAD, NULL);
-  /* we own this one */
-  gst_object_ref (ret);
-  gst_object_sink (ret);
-
-  GST_PAD_DIRECTION (ret) = GST_PAD_SRC;
-  ret->discont = TRUE;
-
-  ret->chain = chain;
-  ret->ogg = chain->ogg;
-
-  ret->serialno = serialno;
-  if (ogg_stream_init (&ret->stream, serialno) != 0)
-    goto init_failed;
-
-  name = g_strdup_printf ("serial_%08lx", serialno);
-  gst_object_set_name (GST_OBJECT (ret), name);
-  g_free (name);
-
-  /* FIXME: either do something with it or remove it */
-  list = gst_tag_list_new ();
-  gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_SERIAL, serialno,
-      NULL);
-  gst_tag_list_free (list);
-
-  GST_DEBUG_OBJECT (chain->ogg,
-      "created new ogg src %p for stream with serial %08lx", ret, serialno);
-
-  g_array_append_val (chain->streams, ret);
-
-  return ret;
-
-  /* ERRORS */
-init_failed:
-  {
-    GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.",
-        serialno);
-    gst_object_unref (ret);
-    return NULL;
-  }
-}
-
-static GstOggPad *
-gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno)
-{
-  gint i;
-
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    if (pad->serialno == serialno)
-      return pad;
-  }
-  return NULL;
-}
-
-static gboolean
-gst_ogg_chain_has_stream (GstOggChain * chain, glong serialno)
-{
-  return gst_ogg_chain_get_stream (chain, serialno) != NULL;
-}
-
-#define CURRENT_CHAIN(ogg) (&g_array_index ((ogg)->chains, GstOggChain, (ogg)->current_chain))
-
-/* signals and args */
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0
-      /* FILL ME */
-};
-
-static GstStaticPadTemplate ogg_demux_src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src_%d",
-    GST_PAD_SRC,
-    GST_PAD_SOMETIMES,
-    GST_STATIC_CAPS_ANY);
-
-static GstStaticPadTemplate ogg_demux_sink_template_factory =
-    GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/ogg; application/x-annodex")
-    );
-
-static void gst_ogg_demux_finalize (GObject * object);
-
-//static const GstEventMask *gst_ogg_demux_get_event_masks (GstPad * pad);
-//static const GstQueryType *gst_ogg_demux_get_query_types (GstPad * pad);
-static GstFlowReturn gst_ogg_demux_read_chain (GstOggDemux * ogg,
-    GstOggChain ** chain);
-static GstFlowReturn gst_ogg_demux_read_end_chain (GstOggDemux * ogg,
-    GstOggChain * chain);
-
-static gboolean gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event);
-static void gst_ogg_demux_loop (GstOggPad * pad);
-static GstFlowReturn gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_ogg_demux_sink_activate (GstPad * sinkpad);
-static gboolean gst_ogg_demux_sink_activate_pull (GstPad * sinkpad,
-    gboolean active);
-static gboolean gst_ogg_demux_sink_activate_push (GstPad * sinkpad,
-    gboolean active);
-static GstStateChangeReturn gst_ogg_demux_change_state (GstElement * element,
-    GstStateChange transition);
-static void gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event);
-
-static void gst_ogg_print (GstOggDemux * demux);
-
-GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT);
-
-static void
-gst_ogg_demux_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_ogg_demux_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&ogg_demux_sink_template_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&ogg_demux_src_template_factory));
-}
-static void
-gst_ogg_demux_class_init (GstOggDemuxClass * klass)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  gstelement_class->change_state = gst_ogg_demux_change_state;
-  gstelement_class->send_event = gst_ogg_demux_receive_event;
-
-  gobject_class->finalize = gst_ogg_demux_finalize;
-}
-
-static void
-gst_ogg_demux_init (GstOggDemux * ogg, GstOggDemuxClass * g_class)
-{
-  /* create the sink pad */
-  ogg->sinkpad =
-      gst_pad_new_from_static_template (&ogg_demux_sink_template_factory,
-      "sink");
-
-  gst_pad_set_event_function (ogg->sinkpad, gst_ogg_demux_sink_event);
-  gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_demux_chain);
-  gst_pad_set_activate_function (ogg->sinkpad, gst_ogg_demux_sink_activate);
-  gst_pad_set_activatepull_function (ogg->sinkpad,
-      gst_ogg_demux_sink_activate_pull);
-  gst_pad_set_activatepush_function (ogg->sinkpad,
-      gst_ogg_demux_sink_activate_push);
-  gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
-
-  ogg->chain_lock = g_mutex_new ();
-  ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *));
-
-  ogg->newsegment = NULL;
-}
-
-static void
-gst_ogg_demux_finalize (GObject * object)
-{
-  GstOggDemux *ogg;
-
-  ogg = GST_OGG_DEMUX (object);
-
-  g_array_free (ogg->chains, TRUE);
-  g_mutex_free (ogg->chain_lock);
-  ogg_sync_clear (&ogg->sync);
-
-  if (ogg->newsegment)
-    gst_event_unref (ogg->newsegment);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
-{
-  gboolean res;
-  GstOggDemux *ogg;
-
-  ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
-      /* FIXME */
-      GST_DEBUG_OBJECT (ogg, "got a new segment event");
-      ogg_sync_reset (&ogg->sync);
-      gst_event_unref (event);
-      res = TRUE;
-      break;
-    case GST_EVENT_EOS:
-    default:
-      res = gst_pad_event_default (pad, event);
-      break;
-  }
-  gst_object_unref (ogg);
-
-  return res;
-}
-
-/* submit the given buffer to the ogg sync.
- *
- * Returns the number of bytes submited.
- */
-static GstFlowReturn
-gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
-{
-  gint size;
-  guint8 *data;
-  gchar *oggbuffer;
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  size = GST_BUFFER_SIZE (buffer);
-  data = GST_BUFFER_DATA (buffer);
-
-  GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size);
-  if (G_UNLIKELY (size == 0))
-    goto done;
-
-  oggbuffer = ogg_sync_buffer (&ogg->sync, size);
-  if (G_UNLIKELY (oggbuffer == NULL))
-    goto no_buffer;
-
-  memcpy (oggbuffer, data, size);
-  if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0))
-    goto write_failed;
-
-done:
-  gst_buffer_unref (buffer);
-
-  return ret;
-
-  /* ERRORS */
-no_buffer:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
-        (NULL), ("failed to get ogg sync buffer"));
-    ret = GST_FLOW_ERROR;
-    goto done;
-  }
-write_failed:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
-        (NULL), ("failed to write %d bytes to the sync buffer", size));
-    ret = GST_FLOW_ERROR;
-    goto done;
-  }
-}
-
-/* in random access mode this code updates the current read position
- * and resets the ogg sync buffer so that the next read will happen
- * from this new location.
- */
-static void
-gst_ogg_demux_seek (GstOggDemux * ogg, gint64 offset)
-{
-  GST_LOG_OBJECT (ogg, "seeking to %" G_GINT64_FORMAT, offset);
-
-  ogg->offset = offset;
-  ogg_sync_reset (&ogg->sync);
-}
-
-/* read more data from the current offset and submit to
- * the ogg sync layer.
- */
-static GstFlowReturn
-gst_ogg_demux_get_data (GstOggDemux * ogg)
-{
-  GstFlowReturn ret;
-  GstBuffer *buffer;
-
-  GST_LOG_OBJECT (ogg, "get data %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
-      ogg->offset, ogg->length);
-  if (ogg->offset == ogg->length)
-    goto eos;
-
-  ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
-  if (ret != GST_FLOW_OK)
-    goto error;
-
-  ret = gst_ogg_demux_submit_buffer (ogg, buffer);
-
-  return ret;
-
-  /* ERROR */
-eos:
-  {
-    GST_LOG_OBJECT (ogg, "reached EOS");
-    return GST_FLOW_UNEXPECTED;
-  }
-error:
-  {
-    GST_WARNING_OBJECT (ogg, "got %d (%s) from pull range", ret,
-        gst_flow_get_name (ret));
-    return ret;
-  }
-}
-
-/* Read the next page from the current offset.
- * boundary: number of bytes ahead we allow looking for;
- * -1 if no boundary
- *
- * @offset will contain the offset the next page starts at when this function
- * returns GST_FLOW_OK.
- *
- * GST_FLOW_UNEXPECTED is returned on EOS.
- *
- * GST_FLOW_LIMIT is returned when we did not find a page before the
- * boundary. If @boundary is -1, this is never returned.
- *
- * Any other error returned while retrieving data from the peer is returned as
- * is.
- */
-static GstFlowReturn
-gst_ogg_demux_get_next_page (GstOggDemux * ogg, ogg_page * og, gint64 boundary,
-    gint64 * offset)
-{
-  gint64 end_offset = 0;
-  GstFlowReturn ret;
-
-  GST_LOG_OBJECT (ogg,
-      "get next page, current offset %" G_GINT64_FORMAT ", bytes boundary %"
-      G_GINT64_FORMAT, ogg->offset, boundary);
-
-  if (boundary > 0)
-    end_offset = ogg->offset + boundary;
-
-  while (TRUE) {
-    glong more;
-
-    if (boundary > 0 && ogg->offset >= end_offset)
-      goto boundary_reached;
-
-    more = ogg_sync_pageseek (&ogg->sync, og);
-
-    GST_LOG_OBJECT (ogg, "pageseek gave %ld", more);
-
-    if (more < 0) {
-      /* skipped n bytes */
-      GST_LOG_OBJECT (ogg, "skipped %ld bytes", more);
-      ogg->offset -= more;
-    } else if (more == 0) {
-      /* we need more data */
-      if (boundary == 0)
-        goto boundary_reached;
-
-      GST_LOG_OBJECT (ogg, "need more data");
-      ret = gst_ogg_demux_get_data (ogg);
-      if (ret != GST_FLOW_OK)
-        break;
-    } else {
-      gint64 res_offset = ogg->offset;
-
-      /* got a page.  Return the offset at the page beginning,
-         advance the internal offset past the page end */
-      if (offset)
-        *offset = res_offset;
-      ret = GST_FLOW_OK;
-
-      ogg->offset += more;
-      /* need to reset as we do not keep track of the bytes we
-       * sent to the sync layer */
-      ogg_sync_reset (&ogg->sync);
-
-      GST_LOG_OBJECT (ogg,
-          "got page at %" G_GINT64_FORMAT ", serial %08x, end at %"
-          G_GINT64_FORMAT ", granule %" G_GINT64_FORMAT, res_offset,
-          ogg_page_serialno (og), ogg->offset, ogg_page_granulepos (og));
-      break;
-    }
-  }
-  GST_LOG_OBJECT (ogg, "returning %d", ret);
-
-  return ret;
-
-  /* ERRORS */
-boundary_reached:
-  {
-    GST_LOG_OBJECT (ogg,
-        "offset %" G_GINT64_FORMAT " >= end_offset %" G_GINT64_FORMAT,
-        ogg->offset, end_offset);
-    return GST_FLOW_LIMIT;
-  }
-}
-
-/* from the current offset, find the previous page, seeking backwards
- * until we find the page. 
- */
-static GstFlowReturn
-gst_ogg_demux_get_prev_page (GstOggDemux * ogg, ogg_page * og, gint64 * offset)
-{
-  GstFlowReturn ret;
-  gint64 begin = ogg->offset;
-  gint64 end = begin;
-  gint64 cur_offset = -1;
-
-  while (cur_offset == -1) {
-    begin -= CHUNKSIZE;
-    if (begin < 0)
-      begin = 0;
-
-    /* seek CHUNKSIZE back */
-    gst_ogg_demux_seek (ogg, begin);
-
-    /* now continue reading until we run out of data, if we find a page
-     * start, we save it. It might not be the final page as there could be
-     * another page after this one. */
-    while (ogg->offset < end) {
-      gint64 new_offset;
-
-      ret =
-          gst_ogg_demux_get_next_page (ogg, og, end - ogg->offset, &new_offset);
-      /* we hit the upper limit, offset contains the last page start */
-      if (ret == GST_FLOW_LIMIT)
-        break;
-      /* something went wrong */
-      if (ret == GST_FLOW_UNEXPECTED)
-        new_offset = 0;
-      else if (ret != GST_FLOW_OK)
-        return ret;
-
-      /* offset is next page start */
-      cur_offset = new_offset;
-    }
-  }
-
-  /* we have the offset.  Actually snork and hold the page now */
-  gst_ogg_demux_seek (ogg, cur_offset);
-  ret = gst_ogg_demux_get_next_page (ogg, og, -1, NULL);
-  if (ret != GST_FLOW_OK)
-    /* this shouldn't be possible */
-    return ret;
-
-  if (offset)
-    *offset = cur_offset;
-
-  return ret;
-}
-
-static gboolean
-gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg)
-{
-  gint i;
-  GstOggChain *chain = ogg->current_chain;
-
-  if (chain == NULL)
-    return TRUE;
-
-  GST_DEBUG_OBJECT (ogg, "deactivating chain %p", chain);
-
-  /* send EOS on all the pads */
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    gst_pad_push_event (GST_PAD_CAST (pad), gst_event_new_eos ());
-
-    GST_DEBUG_OBJECT (ogg, "removing pad %" GST_PTR_FORMAT, pad);
-
-    /* deactivate first */
-    gst_pad_set_active (GST_PAD_CAST (pad), FALSE);
-
-    gst_element_remove_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad));
-  }
-  /* if we cannot seek back to the chain, we can destroy the chain 
-   * completely */
-  if (!ogg->seekable) {
-    gst_ogg_chain_free (chain);
-  }
-  ogg->current_chain = NULL;
-
-  return TRUE;
-}
-
-static gboolean
-gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
-    GstEvent * event)
-{
-  gint i;
-
-  if (chain == ogg->current_chain) {
-    if (event)
-      gst_event_unref (event);
-    return TRUE;
-  }
-
-  gst_ogg_demux_deactivate_current_chain (ogg);
-
-  /* FIXME, should not be called with NULL */
-  if (chain == NULL) {
-    ogg->current_chain = chain;
-    return TRUE;
-  }
-
-  GST_DEBUG_OBJECT (ogg, "activating chain %p", chain);
-
-  /* first add the pads */
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad;
-
-    pad = g_array_index (chain->streams, GstOggPad *, i);
-    GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
-
-    /* mark discont */
-    pad->discont = TRUE;
-    pad->last_ret = GST_FLOW_OK;
-
-    /* activate first */
-    gst_pad_set_active (GST_PAD_CAST (pad), TRUE);
-
-    gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad));
-  }
-
-  gst_element_no_more_pads (GST_ELEMENT (ogg));
-  ogg->current_chain = chain;
-
-  /* FIXME, must be sent from the streaming thread */
-  if (event)
-    gst_ogg_demux_send_event (ogg, event);
-
-  GST_DEBUG_OBJECT (ogg, "starting chain");
-
-  /* then send out any queued buffers */
-  for (i = 0; i < chain->streams->len; i++) {
-    GList *headers;
-    GstOggPad *pad;
-
-    pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    for (headers = pad->headers; headers; headers = g_list_next (headers)) {
-      GstBuffer *buffer = GST_BUFFER (headers->data);
-
-      if (pad->discont) {
-        GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
-        pad->discont = FALSE;
-      }
-
-      /* we don't care about the return value here */
-      gst_pad_push (GST_PAD_CAST (pad), buffer);
-    }
-    /* and free the headers */
-    g_list_free (pad->headers);
-    pad->headers = NULL;
-  }
-  return TRUE;
-}
-
-/* 
- * do seek to time @position, return FALSE or chain and TRUE
- */
-static gboolean
-gst_ogg_demux_do_seek (GstOggDemux * ogg, gint64 position, gboolean accurate,
-    GstOggChain ** rchain)
-{
-  GstOggChain *chain = NULL;
-  gint64 begin, end;
-  gint64 begintime, endtime;
-  gint64 target;
-  gint64 best;
-  gint64 total;
-  gint64 result = 0;
-  GstFlowReturn ret;
-  gint i;
-
-  /* first find the chain to search in */
-  total = ogg->total_time;
-  if (ogg->chains->len == 0)
-    goto no_chains;
-
-  for (i = ogg->chains->len - 1; i >= 0; i--) {
-    chain = g_array_index (ogg->chains, GstOggChain *, i);
-    total -= chain->total_time;
-    if (position >= total)
-      break;
-  }
-
-  begin = chain->offset;
-  end = chain->end_offset;
-  begintime = chain->begin_time;
-  endtime = chain->begin_time + chain->total_time;
-  target = position - total + begintime;
-  if (accurate) {
-    /* FIXME, seek 4 seconds early to catch keyframes, better implement
-     * keyframe detection. */
-    target = target - (gint64) 4 *GST_SECOND;
-  }
-  target = MAX (target, 0);
-  best = begin;
-
-  GST_DEBUG_OBJECT (ogg,
-      "seeking to %" GST_TIME_FORMAT " in chain %p",
-      GST_TIME_ARGS (position), chain);
-  GST_DEBUG_OBJECT (ogg,
-      "chain offset %" G_GINT64_FORMAT ", end offset %" G_GINT64_FORMAT, begin,
-      end);
-  GST_DEBUG_OBJECT (ogg,
-      "chain begin time %" GST_TIME_FORMAT ", end time %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (begintime), GST_TIME_ARGS (endtime));
-  GST_DEBUG_OBJECT (ogg, "target %" GST_TIME_FORMAT, GST_TIME_ARGS (target));
-
-  /* perform the seek */
-  while (begin < end) {
-    gint64 bisect;
-
-    if ((end - begin < CHUNKSIZE) || (endtime == begintime)) {
-      bisect = begin;
-    } else {
-      /* take a (pretty decent) guess, avoiding overflow */
-      gint64 rate = (end - begin) * GST_MSECOND / (endtime - begintime);
-
-      bisect = (target - begintime) / GST_MSECOND * rate + begin - CHUNKSIZE;
-
-      if (bisect <= begin)
-        bisect = begin;
-      GST_DEBUG_OBJECT (ogg, "Initial guess: %" G_GINT64_FORMAT, bisect);
-    }
-    gst_ogg_demux_seek (ogg, bisect);
-
-    while (begin < end) {
-      ogg_page og;
-
-      GST_DEBUG_OBJECT (ogg,
-          "after seek, bisect %" G_GINT64_FORMAT ", begin %" G_GINT64_FORMAT
-          ", end %" G_GINT64_FORMAT, bisect, begin, end);
-
-      ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, &result);
-      GST_LOG_OBJECT (ogg, "looking for next page returned %" G_GINT64_FORMAT,
-          result);
-
-      if (ret == GST_FLOW_LIMIT) {
-        /* we hit the upper limit, go back a bit */
-        if (bisect <= begin + 1) {
-          end = begin;          /* found it */
-        } else {
-          if (bisect == 0)
-            goto seek_error;
-
-          bisect -= CHUNKSIZE;
-          if (bisect <= begin)
-            bisect = begin + 1;
-
-          gst_ogg_demux_seek (ogg, bisect);
-        }
-      } else if (ret == GST_FLOW_OK) {
-        /* found offset of next ogg page */
-        gint64 granulepos;
-        GstClockTime granuletime;
-        GstFormat format;
-        GstOggPad *pad;
-
-        GST_LOG_OBJECT (ogg, "found next ogg page at %" G_GINT64_FORMAT,
-            result);
-        granulepos = ogg_page_granulepos (&og);
-        if (granulepos == -1) {
-          GST_LOG_OBJECT (ogg, "granulepos of next page is -1");
-          continue;
-        }
-
-        pad = gst_ogg_chain_get_stream (chain, ogg_page_serialno (&og));
-        if (pad == NULL || pad->is_skeleton)
-          continue;
-
-        format = GST_FORMAT_TIME;
-        if (!gst_ogg_pad_query_convert (pad,
-                GST_FORMAT_DEFAULT, granulepos, &format,
-                (gint64 *) & granuletime)) {
-          GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
-          granuletime = target;
-        } else {
-          if (granuletime < pad->start_time)
-            continue;
-          GST_LOG_OBJECT (ogg, "granulepos %" G_GINT64_FORMAT " maps to time %"
-              GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (granuletime));
-
-          granuletime -= pad->start_time;
-        }
-
-        GST_DEBUG_OBJECT (ogg,
-            "found page with granule %" G_GINT64_FORMAT " and time %"
-            GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (granuletime));
-
-        if (granuletime < target) {
-          best = result;        /* raw offset of packet with granulepos */
-          begin = ogg->offset;  /* raw offset of next page */
-          begintime = granuletime;
-
-          if (target - begintime > GST_SECOND)
-            break;
-
-          bisect = begin;       /* *not* begin + 1 */
-        } else {
-          if (bisect <= begin + 1) {
-            end = begin;        /* found it */
-          } else {
-            if (end == ogg->offset) {   /* we're pretty close - we'd be stuck in */
-              end = result;
-              bisect -= CHUNKSIZE;      /* an endless loop otherwise. */
-              if (bisect <= begin)
-                bisect = begin + 1;
-              gst_ogg_demux_seek (ogg, bisect);
-            } else {
-              end = result;
-              endtime = granuletime;
-              break;
-            }
-          }
-        }
-      } else
-        goto seek_error;
-    }
-  }
-
-  ogg->offset = best;
-  *rchain = chain;
-
-  return TRUE;
-
-no_chains:
-  {
-    GST_DEBUG_OBJECT (ogg, "no chains");
-    return FALSE;
-  }
-seek_error:
-  {
-    GST_DEBUG_OBJECT (ogg, "got a seek error");
-    return FALSE;
-  }
-}
-
-/* does not take ownership of the event */
-static gboolean
-gst_ogg_demux_perform_seek (GstOggDemux * ogg, GstEvent * event)
-{
-  GstOggChain *chain = NULL;
-  gboolean res;
-  gboolean flush, accurate;
-  GstFormat format;
-  gdouble rate;
-  GstSeekFlags flags;
-  GstSeekType cur_type, stop_type;
-  gint64 cur, stop;
-  gboolean update;
-
-  if (event) {
-    GST_DEBUG_OBJECT (ogg, "seek with event");
-
-    gst_event_parse_seek (event, &rate, &format, &flags,
-        &cur_type, &cur, &stop_type, &stop);
-
-    /* we can only seek on time */
-    if (format != GST_FORMAT_TIME) {
-      GST_DEBUG_OBJECT (ogg, "can only seek on TIME");
-      goto error;
-    }
-  } else {
-    GST_DEBUG_OBJECT (ogg, "seek without event");
-
-    flags = 0;
-    rate = 1.0;
-  }
-
-  GST_DEBUG_OBJECT (ogg, "seek, rate %g", rate);
-
-  flush = flags & GST_SEEK_FLAG_FLUSH;
-  accurate = flags & GST_SEEK_FLAG_ACCURATE;
-
-  /* first step is to unlock the streaming thread if it is
-   * blocked in a chain call, we do this by starting the flush. because
-   * we cannot yet hold any streaming lock, we have to protect the chains
-   * with their own lock. */
-  if (flush) {
-    gint i;
-
-    gst_pad_push_event (ogg->sinkpad, gst_event_new_flush_start ());
-
-    GST_CHAIN_LOCK (ogg);
-    for (i = 0; i < ogg->chains->len; i++) {
-      GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-      gint j;
-
-      for (j = 0; j < chain->streams->len; j++) {
-        GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
-
-        gst_pad_push_event (GST_PAD (pad), gst_event_new_flush_start ());
-      }
-    }
-    GST_CHAIN_UNLOCK (ogg);
-  } else {
-    gst_pad_pause_task (ogg->sinkpad);
-  }
-
-  /* now grab the stream lock so that streaming cannot continue, for
-   * non flushing seeks when the element is in PAUSED this could block
-   * forever. */
-  GST_PAD_STREAM_LOCK (ogg->sinkpad);
-
-  if (ogg->segment_running && !flush) {
-    /* create the segment event to close the current segment */
-    if ((chain = ogg->current_chain)) {
-      GstEvent *newseg;
-
-      newseg = gst_event_new_new_segment (TRUE, ogg->segment.rate,
-          GST_FORMAT_TIME, ogg->segment.start + chain->segment_start,
-          ogg->segment.last_stop + chain->segment_start, ogg->segment.time);
-
-      /* send segment on old chain, FIXME, must be sent from streaming thread. */
-      gst_ogg_demux_send_event (ogg, newseg);
-    }
-  }
-
-  if (event) {
-    gst_segment_set_seek (&ogg->segment, rate, format, flags,
-        cur_type, cur, stop_type, stop, &update);
-  }
-
-  GST_DEBUG_OBJECT (ogg, "segment positions set to %" GST_TIME_FORMAT "-%"
-      GST_TIME_FORMAT, GST_TIME_ARGS (ogg->segment.start),
-      GST_TIME_ARGS (ogg->segment.stop));
-
-  /* we need to stop flushing on the srcpad as we're going to use it
-   * next. We can do this as we have the STREAM lock now. */
-  gst_pad_push_event (ogg->sinkpad, gst_event_new_flush_stop ());
-
-  {
-    gint i;
-
-    /* reset all ogg streams now, need to do this from within the lock to
-     * make sure the streaming thread is not messing with the stream */
-    for (i = 0; i < ogg->chains->len; i++) {
-      GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
-      gst_ogg_chain_reset (chain);
-    }
-  }
-
-  res = gst_ogg_demux_do_seek (ogg, ogg->segment.last_stop, accurate, &chain);
-
-  /* seek failed, make sure we continue the current chain */
-  if (!res) {
-    chain = ogg->current_chain;
-  }
-
-  if (!chain)
-    goto no_chain;
-
-  /* now we have a new position, prepare for streaming again */
-  {
-    GstEvent *event;
-    gint64 stop;
-    gint64 start;
-    gint64 last_stop, begin_time;
-
-    /* we have to send the flush to the old chain, not the new one */
-    if (flush)
-      gst_ogg_demux_send_event (ogg, gst_event_new_flush_stop ());
-
-    /* we need this to see how far inside the chain we need to start */
-    if (chain->begin_time != GST_CLOCK_TIME_NONE)
-      begin_time = chain->begin_time;
-    else
-      begin_time = 0;
-
-    /* segment.start gives the start over all chains, we calculate the amount
-     * of time into this chain we need to start */
-    start = ogg->segment.start - begin_time;
-    if (chain->segment_start != GST_CLOCK_TIME_NONE)
-      start += chain->segment_start;
-
-    if ((stop = ogg->segment.stop) == -1)
-      stop = ogg->segment.duration;
-
-    /* segment.stop gives the stop time over all chains, calculate the amount of
-     * time we need to stop in this chain */
-    if (stop != -1) {
-      if (stop > begin_time)
-        stop -= begin_time;
-      else
-        stop = 0;
-      stop += chain->segment_start;
-      /* we must stop when this chain ends and switch to the next chain to play
-       * the remainder of the segment. */
-      stop = MIN (stop, chain->segment_stop);
-    }
-
-    last_stop = ogg->segment.last_stop - begin_time;
-    if (chain->segment_start != GST_CLOCK_TIME_NONE)
-      last_stop += chain->segment_start;
-
-    /* create the segment event we are going to send out */
-    if (ogg->segment.rate >= 0.0)
-      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-          ogg->segment.format, last_stop, stop, ogg->segment.time);
-    else
-      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-          ogg->segment.format, start, last_stop, ogg->segment.time);
-
-    if (chain != ogg->current_chain) {
-      /* switch to different chain, send segment on new chain */
-      gst_ogg_demux_activate_chain (ogg, chain, event);
-    } else {
-      /* mark discont and send segment on current chain */
-      gst_ogg_chain_mark_discont (chain);
-      /* This event should be sent from the streaming thread (sink pad task) */
-      if (ogg->newsegment)
-        gst_event_unref (ogg->newsegment);
-      ogg->newsegment = event;
-    }
-
-    /* notify start of new segment */
-    if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) {
-      gst_element_post_message (GST_ELEMENT (ogg),
-          gst_message_new_segment_start (GST_OBJECT (ogg),
-              GST_FORMAT_TIME, ogg->segment.last_stop));
-    }
-
-    ogg->segment_running = TRUE;
-    /* restart our task since it might have been stopped when we did the 
-     * flush. */
-    gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
-        ogg->sinkpad);
-  }
-
-  /* streaming can continue now */
-  GST_PAD_STREAM_UNLOCK (ogg->sinkpad);
-
-  return res;
-
-error:
-  {
-    GST_DEBUG_OBJECT (ogg, "seek failed");
-    return FALSE;
-  }
-no_chain:
-  {
-    GST_DEBUG_OBJECT (ogg, "no chain to seek in");
-    GST_PAD_STREAM_UNLOCK (ogg->sinkpad);
-    return FALSE;
-  }
-}
-
-/* finds each bitstream link one at a time using a bisection search
- * (has to begin by knowing the offset of the lb's initial page).
- * Recurses for each link so it can alloc the link storage after
- * finding them all, then unroll and fill the cache at the same time 
- */
-static GstFlowReturn
-gst_ogg_demux_bisect_forward_serialno (GstOggDemux * ogg,
-    gint64 begin, gint64 searched, gint64 end, GstOggChain * chain, glong m)
-{
-  gint64 endsearched = end;
-  gint64 next = end;
-  ogg_page og;
-  GstFlowReturn ret;
-  gint64 offset;
-  GstOggChain *nextchain;
-
-  GST_LOG_OBJECT (ogg,
-      "bisect begin: %" G_GINT64_FORMAT ", searched: %" G_GINT64_FORMAT
-      ", end %" G_GINT64_FORMAT ", chain: %p", begin, searched, end, chain);
-
-  /* the below guards against garbage seperating the last and
-   * first pages of two links. */
-  while (searched < endsearched) {
-    gint64 bisect;
-
-    if (endsearched - searched < CHUNKSIZE) {
-      bisect = searched;
-    } else {
-      bisect = (searched + endsearched) / 2;
-    }
-
-    gst_ogg_demux_seek (ogg, bisect);
-    ret = gst_ogg_demux_get_next_page (ogg, &og, -1, &offset);
-
-    if (ret == GST_FLOW_UNEXPECTED) {
-      endsearched = bisect;
-    } else if (ret == GST_FLOW_OK) {
-      glong serial = ogg_page_serialno (&og);
-
-      if (!gst_ogg_chain_has_stream (chain, serial)) {
-        endsearched = bisect;
-        next = offset;
-      } else {
-        searched = offset + og.header_len + og.body_len;
-      }
-    } else
-      return ret;
-  }
-
-  GST_LOG_OBJECT (ogg, "current chain ends at %" G_GINT64_FORMAT, searched);
-
-  chain->end_offset = searched;
-  ret = gst_ogg_demux_read_end_chain (ogg, chain);
-  if (ret != GST_FLOW_OK)
-    return ret;
-
-  GST_LOG_OBJECT (ogg, "found begin at %" G_GINT64_FORMAT, next);
-
-  gst_ogg_demux_seek (ogg, next);
-  ret = gst_ogg_demux_read_chain (ogg, &nextchain);
-  if (ret == GST_FLOW_UNEXPECTED) {
-    nextchain = NULL;
-    ret = GST_FLOW_OK;
-    GST_LOG_OBJECT (ogg, "no next chain");
-  } else if (ret != GST_FLOW_OK)
-    goto done;
-
-  if (searched < end && nextchain != NULL) {
-    ret = gst_ogg_demux_bisect_forward_serialno (ogg, next, ogg->offset,
-        end, nextchain, m + 1);
-    if (ret != GST_FLOW_OK)
-      goto done;
-  }
-  GST_LOG_OBJECT (ogg, "adding chain %p", chain);
-
-  g_array_insert_val (ogg->chains, 0, chain);
-
-done:
-  return ret;
-}
-
-/* read a chain from the ogg file. This code will
- * read all BOS pages and will create and return a GstOggChain 
- * structure with the results. 
- * 
- * This function will also read N pages from each stream in the
- * chain and submit them to the decoders. When the decoder has
- * decoded the first buffer, we know the timestamp of the first
- * page in the chain.
- */
-static GstFlowReturn
-gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
-{
-  GstFlowReturn ret;
-  GstOggChain *chain = NULL;
-  gint64 offset = ogg->offset;
-  ogg_page op;
-  gboolean done;
-  gint i;
-
-  GST_LOG_OBJECT (ogg, "reading chain at %" G_GINT64_FORMAT, offset);
-
-  /* first read the BOS pages, do typefind on them, create
-   * the decoders, send data to the decoders. */
-  while (TRUE) {
-    GstOggPad *pad;
-    glong serial;
-
-    ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
-    if (ret != GST_FLOW_OK) {
-      GST_WARNING_OBJECT (ogg, "problem reading BOS page: ret=%d", ret);
-      break;
-    }
-    if (!ogg_page_bos (&op)) {
-      GST_WARNING_OBJECT (ogg, "page is not BOS page");
-      break;
-    }
-
-    if (chain == NULL) {
-      chain = gst_ogg_chain_new (ogg);
-      chain->offset = offset;
-    }
-
-    serial = ogg_page_serialno (&op);
-    if (gst_ogg_chain_get_stream (chain, serial) != NULL) {
-      GST_WARNING_OBJECT (ogg, "found serial %08lx BOS page twice, ignoring",
-          serial);
-      continue;
-    }
-
-    pad = gst_ogg_chain_new_stream (chain, serial);
-    gst_ogg_pad_submit_page (pad, &op);
-  }
-
-  if (ret != GST_FLOW_OK || chain == NULL) {
-    if (ret != GST_FLOW_UNEXPECTED) {
-      GST_WARNING_OBJECT (ogg, "failed to read chain");
-    } else {
-      GST_DEBUG_OBJECT (ogg, "done reading chains");
-    }
-    if (chain) {
-      gst_ogg_chain_free (chain);
-    }
-    if (res_chain)
-      *res_chain = NULL;
-    return ret;
-  }
-
-  chain->have_bos = TRUE;
-  GST_LOG_OBJECT (ogg, "read bos pages, init decoder now");
-
-  /* now read pages until we receive a buffer from each of the
-   * stream decoders, this will tell us the timestamp of the
-   * first packet in the chain then */
-
-  /* save the offset to the first non bos page in the chain: if searching for
-   * pad->first_time we read past the end of the chain, we'll seek back to this
-   * position
-   */
-  offset = ogg->offset;
-
-  done = FALSE;
-  while (!done) {
-    glong serial;
-    gboolean known_serial = FALSE;
-    GstFlowReturn ret;
-
-    serial = ogg_page_serialno (&op);
-    done = TRUE;
-    for (i = 0; i < chain->streams->len; i++) {
-      GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-      GST_LOG_OBJECT (ogg, "serial %08x time %" GST_TIME_FORMAT, pad->serialno,
-          GST_TIME_ARGS (pad->start_time));
-
-      if (pad->serialno == serial) {
-        known_serial = TRUE;
-
-        /* submit the page now, this will fill in the start_time when the
-         * internal decoder finds it */
-        gst_ogg_pad_submit_page (pad, &op);
-
-        if (!pad->is_skeleton && pad->start_time == -1 && ogg_page_eos (&op)) {
-          /* got EOS on a pad before we could find its start_time.
-           * We have no chance of finding a start_time for every pad so
-           * stop searching for the other start_time(s).
-           */
-          done = TRUE;
-          break;
-        }
-      }
-      /* the timestamp will be filled in when we submit the pages */
-      if (!pad->is_skeleton)
-        done &= (pad->start_time != GST_CLOCK_TIME_NONE);
-
-      GST_LOG_OBJECT (ogg, "done %08x now %d", pad->serialno, done);
-    }
-
-    /* we read a page not belonging to the current chain: seek back to the
-     * beginning of the chain
-     */
-    if (!known_serial) {
-      GST_LOG_OBJECT (ogg, "unknown serial %08lx", serial);
-      gst_ogg_demux_seek (ogg, offset);
-      break;
-    }
-
-    if (!done) {
-      ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
-      if (ret != GST_FLOW_OK)
-        break;
-    }
-  }
-  GST_LOG_OBJECT (ogg, "done reading chain");
-  /* now we can fill in the missing info using queries */
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-    GstFormat target;
-
-    if (pad->is_skeleton)
-      continue;
-
-    GST_LOG_OBJECT (ogg, "convert first granule %" G_GUINT64_FORMAT " to time ",
-        pad->first_granule);
-
-    target = GST_FORMAT_TIME;
-    if (!gst_ogg_pad_query_convert (pad,
-            GST_FORMAT_DEFAULT, pad->first_granule, &target,
-            (gint64 *) & pad->first_time)) {
-      GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
-    } else {
-      GST_LOG_OBJECT (ogg, "converted to first time %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (pad->first_time));
-    }
-
-    pad->mode = GST_OGG_PAD_MODE_STREAMING;
-  }
-
-  if (res_chain)
-    *res_chain = chain;
-
-  return GST_FLOW_OK;
-}
-
-/* read the last pages from the ogg stream to get the final
- * page end_offsets.
- */
-static GstFlowReturn
-gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain)
-{
-  gint64 begin = chain->end_offset;
-  gint64 end = begin;
-  gint64 last_granule = -1;
-  GstOggPad *last_pad = NULL;
-  GstFormat target;
-  GstFlowReturn ret;
-  gboolean done = FALSE;
-  ogg_page og;
-  gint i;
-
-  while (!done) {
-    begin -= CHUNKSIZE;
-    if (begin < 0)
-      begin = 0;
-
-    gst_ogg_demux_seek (ogg, begin);
-
-    /* now continue reading until we run out of data, if we find a page
-     * start, we save it. It might not be the final page as there could be
-     * another page after this one. */
-    while (ogg->offset < end) {
-      ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, NULL);
-
-      if (ret == GST_FLOW_LIMIT)
-        break;
-      if (ret != GST_FLOW_OK)
-        return ret;
-
-      for (i = 0; i < chain->streams->len; i++) {
-        GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-        if (pad->is_skeleton)
-          continue;
-
-        if (pad->serialno == ogg_page_serialno (&og)) {
-          gint64 granulepos = ogg_page_granulepos (&og);
-
-          if (last_granule < granulepos) {
-            last_granule = granulepos;
-            last_pad = pad;
-          }
-          done = TRUE;
-          break;
-        }
-      }
-    }
-  }
-
-  target = GST_FORMAT_TIME;
-  if (last_granule == -1 || !gst_ogg_pad_query_convert (last_pad,
-          GST_FORMAT_DEFAULT, last_granule, &target,
-          (gint64 *) & chain->segment_stop)) {
-    GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
-    chain->segment_stop = GST_CLOCK_TIME_NONE;
-  }
-
-  return GST_FLOW_OK;
-}
-
-/* find a pad with a given serial number
- */
-static GstOggPad *
-gst_ogg_demux_find_pad (GstOggDemux * ogg, int serialno)
-{
-  GstOggPad *pad;
-  gint i;
-
-  /* first look in building chain if any */
-  if (ogg->building_chain) {
-    pad = gst_ogg_chain_get_stream (ogg->building_chain, serialno);
-    if (pad)
-      return pad;
-  }
-
-  /* then look in current chain if any */
-  if (ogg->current_chain) {
-    pad = gst_ogg_chain_get_stream (ogg->current_chain, serialno);
-    if (pad)
-      return pad;
-  }
-
-  for (i = 0; i < ogg->chains->len; i++) {
-    GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
-    pad = gst_ogg_chain_get_stream (chain, serialno);
-    if (pad)
-      return pad;
-  }
-  return NULL;
-}
-
-/* find a chain with a given serial number
- */
-static GstOggChain *
-gst_ogg_demux_find_chain (GstOggDemux * ogg, int serialno)
-{
-  GstOggPad *pad;
-
-  pad = gst_ogg_demux_find_pad (ogg, serialno);
-  if (pad) {
-    return pad->chain;
-  }
-  return NULL;
-}
-
-/* returns TRUE if all streams have valid start time */
-static gboolean
-gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
-{
-  gint i;
-  gboolean res = TRUE;
-
-  chain->total_time = GST_CLOCK_TIME_NONE;
-  chain->segment_start = G_MAXUINT64;
-
-  GST_DEBUG_OBJECT (ogg, "trying to collect chain info");
-
-  for (i = 0; i < chain->streams->len; i++) {
-    GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-    if (pad->is_skeleton)
-      continue;
-
-    /*  can do this if the pad start time is not defined */
-    if (pad->start_time == GST_CLOCK_TIME_NONE)
-      res = FALSE;
-    else
-      chain->segment_start = MIN (chain->segment_start, pad->start_time);
-  }
-
-  if (chain->segment_stop != GST_CLOCK_TIME_NONE
-      && chain->segment_start != G_MAXUINT64)
-    chain->total_time = chain->segment_stop - chain->segment_start;
-
-  GST_DEBUG_OBJECT (ogg, "return %d", res);
-
-  return res;
-}
-
-static void
-gst_ogg_demux_collect_info (GstOggDemux * ogg)
-{
-  gint i;
-
-  /* collect all info */
-  ogg->total_time = 0;
-
-  for (i = 0; i < ogg->chains->len; i++) {
-    GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
-    chain->begin_time = ogg->total_time;
-
-    gst_ogg_demux_collect_chain_info (ogg, chain);
-
-    ogg->total_time += chain->total_time;
-  }
-  gst_segment_set_duration (&ogg->segment, GST_FORMAT_TIME, ogg->total_time);
-}
-
-/* find all the chains in the ogg file, this reads the first and
- * last page of the ogg stream, if they match then the ogg file has
- * just one chain, else we do a binary search for all chains.
- */
-static GstFlowReturn
-gst_ogg_demux_find_chains (GstOggDemux * ogg)
-{
-  ogg_page og;
-  GstPad *peer;
-  GstFormat format;
-  gboolean res;
-  gulong serialno;
-  GstOggChain *chain;
-  GstFlowReturn ret;
-
-  /* get peer to figure out length */
-  if ((peer = gst_pad_get_peer (ogg->sinkpad)) == NULL)
-    goto no_peer;
-
-  /* find length to read last page, we store this for later use. */
-  format = GST_FORMAT_BYTES;
-  res = gst_pad_query_duration (peer, &format, &ogg->length);
-  gst_object_unref (peer);
-  if (!res || ogg->length <= 0)
-    goto no_length;
-
-  GST_DEBUG_OBJECT (ogg, "file length %" G_GINT64_FORMAT, ogg->length);
-
-  /* read chain from offset 0, this is the first chain of the
-   * ogg file. */
-  gst_ogg_demux_seek (ogg, 0);
-  ret = gst_ogg_demux_read_chain (ogg, &chain);
-  if (ret != GST_FLOW_OK)
-    goto no_first_chain;
-
-  /* read page from end offset, we use this page to check if its serial
-   * number is contained in the first chain. If this is the case then
-   * this ogg is not a chained ogg and we can skip the scanning. */
-  gst_ogg_demux_seek (ogg, ogg->length);
-  ret = gst_ogg_demux_get_prev_page (ogg, &og, NULL);
-  if (ret != GST_FLOW_OK)
-    goto no_last_page;
-
-  serialno = ogg_page_serialno (&og);
-
-  if (!gst_ogg_chain_has_stream (chain, serialno)) {
-    /* the last page is not in the first stream, this means we should
-     * find all the chains in this chained ogg. */
-    ret =
-        gst_ogg_demux_bisect_forward_serialno (ogg, 0, 0, ogg->length, chain,
-        0);
-  } else {
-    /* we still call this function here but with an empty range so that
-     * we can reuse the setup code in this routine. */
-    ret =
-        gst_ogg_demux_bisect_forward_serialno (ogg, 0, ogg->length, ogg->length,
-        chain, 0);
-  }
-  if (ret != GST_FLOW_OK)
-    goto done;
-
-  /* all fine, collect and print */
-  gst_ogg_demux_collect_info (ogg);
-
-  /* dump our chains and streams */
-  gst_ogg_print (ogg);
-
-done:
-  return ret;
-
-  /*** error cases ***/
-no_peer:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("we don't have a peer"));
-    return GST_FLOW_NOT_LINKED;
-  }
-no_length:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("can't get file length"));
-    return GST_FLOW_NOT_SUPPORTED;
-  }
-no_first_chain:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("can't get first chain"));
-    return GST_FLOW_ERROR;
-  }
-no_last_page:
-  {
-    GST_DEBUG_OBJECT (ogg, "can't get last page");
-    if (chain)
-      gst_ogg_chain_free (chain);
-    return ret;
-  }
-}
-
-static GstFlowReturn
-gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
-{
-  GstOggPad *pad;
-  gint64 granule;
-  guint serialno;
-  GstFlowReturn result = GST_FLOW_OK;
-
-  serialno = ogg_page_serialno (page);
-  granule = ogg_page_granulepos (page);
-
-  GST_LOG_OBJECT (ogg,
-      "processing ogg page (serial %08x, pageno %ld, granulepos %"
-      G_GINT64_FORMAT ", bos %d)",
-      serialno, ogg_page_pageno (page), granule, ogg_page_bos (page));
-
-  if (ogg_page_bos (page)) {
-    GstOggChain *chain;
-
-    /* first page */
-    /* see if we know about the chain already */
-    chain = gst_ogg_demux_find_chain (ogg, serialno);
-    if (chain) {
-      GstEvent *event;
-
-      /* create the newsegment event we are going to send out */
-      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-          GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
-          chain->begin_time);
-
-      GST_DEBUG_OBJECT (ogg,
-          "segment: start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
-          ", time %" GST_TIME_FORMAT, GST_TIME_ARGS (chain->segment_start),
-          GST_TIME_ARGS (chain->segment_stop),
-          GST_TIME_ARGS (chain->begin_time));
-
-      /* activate it as it means we have a non-header */
-      gst_ogg_demux_activate_chain (ogg, chain, event);
-      pad = gst_ogg_demux_find_pad (ogg, serialno);
-    } else {
-      GstClockTime chain_time;
-      GstOggChain *current_chain;
-      gint64 current_time;
-
-      /* this can only happen in non-seekabe mode */
-      if (ogg->seekable)
-        goto unknown_chain;
-
-      current_chain = ogg->current_chain;
-      current_time = ogg->segment.last_stop;
-
-      if (current_chain) {
-        /* remove existing pads */
-        gst_ogg_demux_deactivate_current_chain (ogg);
-      }
-      /* time of new chain is current time */
-      chain_time = current_time;
-
-      if (ogg->building_chain == NULL) {
-        GstOggChain *newchain;
-
-        newchain = gst_ogg_chain_new (ogg);
-        newchain->offset = 0;
-        /* set new chain begin time aligned with end time of old chain */
-        newchain->begin_time = chain_time;
-        GST_DEBUG_OBJECT (ogg, "new chain, begin time %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (chain_time));
-
-        /* and this is the one we are building now */
-        ogg->building_chain = newchain;
-      }
-      pad = gst_ogg_chain_new_stream (ogg->building_chain, serialno);
-    }
-  } else {
-    pad = gst_ogg_demux_find_pad (ogg, serialno);
-  }
-  if (pad) {
-    result = gst_ogg_pad_submit_page (pad, page);
-  } else {
-    /* no pad, this is pretty fatal. This means an ogg page without bos
-     * has been seen for this serialno. could just ignore it too... */
-    goto unknown_pad;
-  }
-  return result;
-
-  /* ERRORS */
-unknown_chain:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
-        (NULL), ("unknown ogg chain for serial %08x detected", serialno));
-    return GST_FLOW_ERROR;
-  }
-unknown_pad:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
-        (NULL), ("unknown ogg pad for serial %08x detected", serialno));
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* streaming mode, receive a buffer, parse it, create pads for
- * the serialno, submit pages and packets to the oggpads
- */
-static GstFlowReturn
-gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstOggDemux *ogg;
-  gint ret;
-  GstFlowReturn result = GST_FLOW_OK;
-
-  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
-
-  GST_DEBUG_OBJECT (ogg, "chain");
-  result = gst_ogg_demux_submit_buffer (ogg, buffer);
-
-  while (result == GST_FLOW_OK) {
-    ogg_page page;
-
-    ret = ogg_sync_pageout (&ogg->sync, &page);
-    if (ret == 0)
-      /* need more data */
-      break;
-    if (ret == -1) {
-      /* discontinuity in the pages */
-      GST_DEBUG_OBJECT (ogg, "discont in page found, continuing");
-    } else {
-      result = gst_ogg_demux_handle_page (ogg, &page);
-    }
-  }
-  return result;
-}
-
-static void
-gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event)
-{
-  GstOggChain *chain = ogg->current_chain;
-
-  if (chain) {
-    gint i;
-
-    for (i = 0; i < chain->streams->len; i++) {
-      GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
-      gst_event_ref (event);
-      GST_DEBUG_OBJECT (ogg, "Pushing event on pad %p", pad);
-      gst_pad_push_event (GST_PAD (pad), event);
-    }
-  }
-  gst_event_unref (event);
-}
-
-static GstFlowReturn
-gst_ogg_demux_combine_flows (GstOggDemux * ogg, GstOggPad * pad,
-    GstFlowReturn ret)
-{
-  GstOggChain *chain;
-
-  /* store the value */
-  pad->last_ret = ret;
-
-  /* any other error that is not-linked can be returned right
-   * away */
-  if (ret != GST_FLOW_NOT_LINKED)
-    goto done;
-
-  /* only return NOT_LINKED if all other pads returned NOT_LINKED */
-  chain = ogg->current_chain;
-  if (chain) {
-    gint i;
-
-    for (i = 0; i < chain->streams->len; i++) {
-      GstOggPad *opad = g_array_index (chain->streams, GstOggPad *, i);
-
-      ret = opad->last_ret;
-      /* some other return value (must be SUCCESS but we can return
-       * other values as well) */
-      if (ret != GST_FLOW_NOT_LINKED)
-        goto done;
-    }
-    /* if we get here, all other pads were unlinked and we return
-     * NOT_LINKED then */
-  }
-done:
-  return ret;
-}
-
-static GstFlowReturn
-gst_ogg_demux_loop_forward (GstOggDemux * ogg)
-{
-  GstFlowReturn ret;
-  GstBuffer *buffer;
-
-  if (ogg->offset == ogg->length) {
-    GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT
-        " == %" G_GINT64_FORMAT, ogg->offset, ogg->length);
-    ret = GST_FLOW_UNEXPECTED;
-    goto done;
-  }
-
-  GST_LOG_OBJECT (ogg, "pull data %" G_GINT64_FORMAT, ogg->offset);
-  ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
-  if (ret != GST_FLOW_OK) {
-    GST_LOG_OBJECT (ogg, "Failed pull_range");
-    goto done;
-  }
-
-  ogg->offset += GST_BUFFER_SIZE (buffer);
-
-  if (G_UNLIKELY (ogg->newsegment)) {
-    gst_ogg_demux_send_event (ogg, ogg->newsegment);
-    ogg->newsegment = NULL;
-  }
-
-  ret = gst_ogg_demux_chain (ogg->sinkpad, buffer);
-  if (ret != GST_FLOW_OK) {
-    GST_LOG_OBJECT (ogg, "Failed demux_chain");
-    goto done;
-  }
-
-  /* check for the end of the segment */
-  if (ogg->segment.stop != -1 && ogg->segment.last_stop != -1) {
-    if (ogg->segment.last_stop > ogg->segment.stop) {
-      ret = GST_FLOW_UNEXPECTED;
-      goto done;
-    }
-  }
-done:
-  return ret;
-}
-
-/* reverse mode.
- *
- * We read the pages backwards and send the packets forwards. The first packet
- * in the page will be pushed with the DISCONT flag set.
- *
- * Special care has to be taken for continued pages, which we can only decode
- * when we have the previous page(s).
- */
-static GstFlowReturn
-gst_ogg_demux_loop_reverse (GstOggDemux * ogg)
-{
-  GstFlowReturn ret;
-  ogg_page page;
-  gint64 offset;
-
-  if (ogg->offset == 0) {
-    GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT
-        " == 0", ogg->offset);
-    ret = GST_FLOW_UNEXPECTED;
-    goto done;
-  }
-
-  GST_LOG_OBJECT (ogg, "read page from %" G_GINT64_FORMAT, ogg->offset);
-  ret = gst_ogg_demux_get_prev_page (ogg, &page, &offset);
-  if (ret != GST_FLOW_OK)
-    goto done;
-
-  ogg->offset = offset;
-
-  if (G_UNLIKELY (ogg->newsegment)) {
-    gst_ogg_demux_send_event (ogg, ogg->newsegment);
-    ogg->newsegment = NULL;
-  }
-
-  ret = gst_ogg_demux_handle_page (ogg, &page);
-  if (ret != GST_FLOW_OK)
-    goto done;
-
-  /* check for the end of the segment */
-  if (ogg->segment.start != -1 && ogg->segment.last_stop != -1) {
-    if (ogg->segment.last_stop <= ogg->segment.start) {
-      ret = GST_FLOW_UNEXPECTED;
-      goto done;
-    }
-  }
-done:
-  return ret;
-}
-
-/* random access code
- *
- * - first find all the chains and streams by scanning the file.
- * - then get and chain buffers, just like the streaming case.
- * - when seeking, we can use the chain info to perform the seek.
- */
-static void
-gst_ogg_demux_loop (GstOggPad * pad)
-{
-  GstOggDemux *ogg;
-  GstFlowReturn ret;
-  GstEvent *event;
-
-  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
-
-  if (ogg->need_chains) {
-    gboolean res;
-
-    /* this is the only place where we write chains and thus need to lock. */
-    GST_CHAIN_LOCK (ogg);
-    ret = gst_ogg_demux_find_chains (ogg);
-    GST_CHAIN_UNLOCK (ogg);
-    if (ret != GST_FLOW_OK)
-      goto chain_read_failed;
-
-    ogg->need_chains = FALSE;
-
-    GST_OBJECT_LOCK (ogg);
-    ogg->running = TRUE;
-    event = ogg->event;
-    ogg->event = NULL;
-    GST_OBJECT_UNLOCK (ogg);
-
-    /* and seek to configured positions without FLUSH */
-    res = gst_ogg_demux_perform_seek (ogg, event);
-    if (event)
-      gst_event_unref (event);
-
-    if (!res)
-      goto seek_failed;
-  }
-
-  if (ogg->segment.rate >= 0.0)
-    ret = gst_ogg_demux_loop_forward (ogg);
-  else
-    ret = gst_ogg_demux_loop_reverse (ogg);
-
-  if (ret != GST_FLOW_OK)
-    goto pause;
-
-  return;
-
-  /* ERRORS */
-chain_read_failed:
-  {
-    /* error was posted */
-    goto pause;
-  }
-seek_failed:
-  {
-    GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL),
-        ("failed to start demuxing ogg"));
-    ret = GST_FLOW_ERROR;
-    goto pause;
-  }
-pause:
-  {
-    const gchar *reason = gst_flow_get_name (ret);
-
-    GST_LOG_OBJECT (ogg, "pausing task, reason %s", reason);
-    ogg->segment_running = FALSE;
-    gst_pad_pause_task (ogg->sinkpad);
-
-    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
-      if (ret == GST_FLOW_UNEXPECTED) {
-        /* perform EOS logic */
-        if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) {
-          gint64 stop;
-
-          /* for segment playback we need to post when (in stream time)
-           * we stopped, this is either stop (when set) or the duration. */
-          if ((stop = ogg->segment.stop) == -1)
-            stop = ogg->segment.duration;
-
-          GST_LOG_OBJECT (ogg, "Sending segment done, at end of segment");
-          gst_element_post_message (GST_ELEMENT (ogg),
-              gst_message_new_segment_done (GST_OBJECT (ogg), GST_FORMAT_TIME,
-                  stop));
-        } else {
-          /* normal playback, send EOS to all linked pads */
-          GST_LOG_OBJECT (ogg, "Sending EOS, at end of stream");
-          gst_ogg_demux_send_event (ogg, gst_event_new_eos ());
-        }
-      } else {
-        GST_ELEMENT_ERROR (ogg, STREAM, FAILED,
-            (_("Internal data stream error.")),
-            ("stream stopped, reason %s", reason));
-        gst_ogg_demux_send_event (ogg, gst_event_new_eos ());
-      }
-    }
-    return;
-  }
-}
-
-static void
-gst_ogg_demux_clear_chains (GstOggDemux * ogg)
-{
-  gint i;
-
-  gst_ogg_demux_deactivate_current_chain (ogg);
-
-  GST_CHAIN_LOCK (ogg);
-  for (i = 0; i < ogg->chains->len; i++) {
-    GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
-    gst_ogg_chain_free (chain);
-  }
-  ogg->chains = g_array_set_size (ogg->chains, 0);
-  GST_CHAIN_UNLOCK (ogg);
-}
-
-/* this function is called when the pad is activated and should start
- * processing data.
- *
- * We check if we can do random access to decide if we work push or
- * pull based.
- */
-static gboolean
-gst_ogg_demux_sink_activate (GstPad * sinkpad)
-{
-  if (gst_pad_check_pull_range (sinkpad)) {
-    GST_DEBUG_OBJECT (sinkpad, "activating pull");
-    return gst_pad_activate_pull (sinkpad, TRUE);
-  } else {
-    GST_DEBUG_OBJECT (sinkpad, "activating push");
-    return gst_pad_activate_push (sinkpad, TRUE);
-  }
-}
-
-/* this function gets called when we activate ourselves in push mode.
- * We cannot seek (ourselves) in the stream */
-static gboolean
-gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
-{
-  GstOggDemux *ogg;
-
-  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
-
-  ogg->seekable = FALSE;
-
-  return TRUE;
-}
-
-/* this function gets called when we activate ourselves in pull mode.
- * We can perform  random access to the resource and we start a task
- * to start reading */
-static gboolean
-gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
-{
-  GstOggDemux *ogg;
-
-  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
-
-  if (active) {
-    ogg->need_chains = TRUE;
-    ogg->seekable = TRUE;
-
-    return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
-        sinkpad);
-  } else {
-    return gst_pad_stop_task (sinkpad);
-  }
-}
-
-static GstStateChangeReturn
-gst_ogg_demux_change_state (GstElement * element, GstStateChange transition)
-{
-  GstOggDemux *ogg;
-  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
-
-  ogg = GST_OGG_DEMUX (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      ogg->basetime = 0;
-      ogg->have_fishead = FALSE;
-      ogg_sync_init (&ogg->sync);
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      ogg_sync_reset (&ogg->sync);
-      ogg->current_granule = -1;
-      ogg->running = FALSE;
-      ogg->segment_running = FALSE;
-      gst_segment_init (&ogg->segment, GST_FORMAT_TIME);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  result = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      gst_ogg_demux_clear_chains (ogg);
-      GST_OBJECT_LOCK (ogg);
-      ogg->running = FALSE;
-      ogg->segment_running = FALSE;
-      ogg->have_fishead = FALSE;
-      GST_OBJECT_UNLOCK (ogg);
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      ogg_sync_clear (&ogg->sync);
-      break;
-    default:
-      break;
-  }
-  return result;
-}
-
-static GstClockTime
-gst_annodex_granule_to_time (gint64 granulepos, gint64 granulerate_n,
-    gint64 granulerate_d, guint8 granuleshift)
-{
-  gint64 keyindex, keyoffset;
-  gint64 granulerate;
-  GstClockTime res;
-
-  if (granulepos == 0 || granulerate_n == 0 || granulerate_d == 0)
-    return 0;
-
-  if (granuleshift != 0) {
-    keyindex = granulepos >> granuleshift;
-    keyoffset = granulepos - (keyindex << granuleshift);
-    granulepos = keyindex + keyoffset;
-  }
-
-  /* GST_SECOND / (granulerate_n / granulerate_d) */
-  granulerate = gst_util_uint64_scale (GST_SECOND,
-      granulerate_d, granulerate_n);
-  res = gst_util_uint64_scale (granulepos, granulerate, 1);
-  return res;
-}
-
-gboolean
-gst_ogg_demux_plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_debug, "oggdemux", 0, "ogg demuxer");
-  GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_setup_debug, "oggdemux_setup", 0,
-      "ogg demuxer setup stage when parsing pipeline");
-
-#if ENABLE_NLS
-  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
-      LOCALEDIR);
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif
-
-  return gst_element_register (plugin, "oggdemux", GST_RANK_PRIMARY,
-      GST_TYPE_OGG_DEMUX);
-}
-
-/* prints all info about the element */
-#undef GST_CAT_DEFAULT
-#define GST_CAT_DEFAULT gst_ogg_demux_setup_debug
-
-#ifdef GST_DISABLE_GST_DEBUG
-
-static void
-gst_ogg_print (GstOggDemux * ogg)
-{
-  /* NOP */
-}
-
-#else /* !GST_DISABLE_GST_DEBUG */
-
-static void
-gst_ogg_print (GstOggDemux * ogg)
-{
-  guint j, i;
-
-  GST_INFO_OBJECT (ogg, "%u chains", ogg->chains->len);
-  GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (ogg->total_time));
-
-  for (i = 0; i < ogg->chains->len; i++) {
-    GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
-    GST_INFO_OBJECT (ogg, " chain %d (%u streams):", i, chain->streams->len);
-    GST_INFO_OBJECT (ogg, "  offset: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT,
-        chain->offset, chain->end_offset);
-    GST_INFO_OBJECT (ogg, "  begin time: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (chain->begin_time));
-    GST_INFO_OBJECT (ogg, "  total time: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (chain->total_time));
-    GST_INFO_OBJECT (ogg, "  segment start: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (chain->segment_start));
-    GST_INFO_OBJECT (ogg, "  segment stop:  %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (chain->segment_stop));
-
-    for (j = 0; j < chain->streams->len; j++) {
-      GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
-
-      GST_INFO_OBJECT (ogg, "  stream %08x:", stream->serialno);
-      GST_INFO_OBJECT (ogg, "   start time:       %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (stream->start_time));
-      GST_INFO_OBJECT (ogg, "   first granulepos: %" G_GINT64_FORMAT,
-          stream->first_granule);
-      GST_INFO_OBJECT (ogg, "   first time:       %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (stream->first_time));
-    }
-  }
-}
-#endif /* GST_DISABLE_GST_DEBUG */
--- a/gst_plugins_base/ext/ogg/gstoggdemux.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- *
- * gstoggdemux.c: ogg stream demuxer
- *
- * 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_OGG_DEMUX_H__
-#define __GST_OGG_DEMUX_H__
-
-#include <ogg/ogg.h>
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_OGG_PAD (gst_ogg_pad_get_type())
-#define GST_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PAD, GstOggPad))
-#define GST_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PAD, GstOggPad))
-#define GST_IS_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_PAD))
-#define GST_IS_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_PAD))
-
-typedef struct _GstOggPad GstOggPad;
-typedef struct _GstOggPadClass GstOggPadClass;
-
-#define GST_TYPE_OGG_DEMUX (gst_ogg_demux_get_type())
-#define GST_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_DEMUX, GstOggDemux))
-#define GST_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_DEMUX, GstOggDemux))
-#define GST_IS_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_DEMUX))
-#define GST_IS_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_DEMUX))
-
-static GType gst_ogg_demux_get_type (void);
-
-typedef struct _GstOggDemux GstOggDemux;
-typedef struct _GstOggDemuxClass GstOggDemuxClass;
-typedef struct _GstOggChain GstOggChain;
-
-/* all information needed for one ogg chain (relevant for chained bitstreams) */
-struct _GstOggChain
-{
-  GstOggDemux *ogg;
-
-  gint64 offset;                /* starting offset of chain */
-  gint64 end_offset;            /* end offset of chain */
-  gint64 bytes;                 /* number of bytes */
-
-  gboolean have_bos;
-
-  GArray *streams;
-
-  GstClockTime total_time;      /* the total time of this chain, this is the MAX of
-                                   the totals of all streams */
-  GstClockTime begin_time;      /* when this chain starts in the stream */
-
-  GstClockTime segment_start;   /* the timestamp of the first sample, this is the MIN of
-                                   the start times of all streams. */
-  GstClockTime segment_stop;    /* the timestamp of the last page, this is the MAX of the
-                                   streams. */
-};
-
-/* different modes for the pad */
-typedef enum
-{
-  GST_OGG_PAD_MODE_INIT,        /* we are feeding our internal decoder to get info */
-  GST_OGG_PAD_MODE_STREAMING,   /* we are streaming buffers to the outside */
-} GstOggPadMode;
-
-/* all information needed for one ogg stream */
-struct _GstOggPad
-{
-  GstPad pad;                   /* subclass GstPad */
-
-  gboolean have_type;
-  GstOggPadMode mode;
-
-  GstPad *elem_pad;             /* sinkpad of internal element */
-  GstElement *element;          /* internal element */
-  GstPad *elem_out;             /* our sinkpad to receive buffers form the internal element */
-
-  GstOggChain *chain;           /* the chain we are part of */
-  GstOggDemux *ogg;             /* the ogg demuxer we are part of */
-
-  GList *headers;
-
-  gboolean is_skeleton;
-  gboolean have_fisbone;
-  gint64 granulerate_n;
-  gint64 granulerate_d;
-  guint32 preroll;
-  guint granuleshift;
-
-  gint serialno;
-  gint64 packetno;
-  gint64 current_granule;
-
-  GstClockTime start_time;      /* the timestamp of the first sample */
-
-  gint64 first_granule;         /* the granulepos of first page == first sample in next page */
-  GstClockTime first_time;      /* the timestamp of the second page or granuletime of first page */
-
-  ogg_stream_state stream;
-  GList *continued;
-
-  gboolean discont;
-  GstFlowReturn last_ret;       /* last return of _pad_push() */
-
-  gboolean dynamic;             /* True if the internal element had dynamic pads */
-  guint padaddedid;             /* The signal id for element::pad-added */
-};
-
-struct _GstOggPadClass
-{
-  GstPadClass parent_class;
-};
-
-#define GST_CHAIN_LOCK(ogg)     g_mutex_lock((ogg)->chain_lock)
-#define GST_CHAIN_UNLOCK(ogg)   g_mutex_unlock((ogg)->chain_lock)
-
-/**
- * GstOggDemux:
- *
- * The ogg demuxer object structure.
- */
-struct _GstOggDemux
-{
-  GstElement element;
-
-  GstPad *sinkpad;
-
-  gint64 length;
-  gint64 offset;
-
-  gboolean seekable;
-  gboolean running;
-
-  gboolean need_chains;
-
-  /* state */
-  GMutex *chain_lock;           /* we need the lock to protect the chains */
-  GArray *chains;               /* list of chains we know */
-  GstClockTime total_time;
-
-  GstOggChain *current_chain;
-  GstOggChain *building_chain;
-
-  /* playback start/stop positions */
-  GstSegment segment;
-  gboolean segment_running;
-
-  GstEvent *event;
-  GstEvent *newsegment;         /* pending newsegment to be sent from _loop */
-
-  gint64 current_granule;
-
-  /* annodex stuff */
-  gboolean have_fishead;
-  gint64 basetime;
-
-  /* ogg stuff */
-  ogg_sync_state sync;
-};
-
-struct _GstOggDemuxClass
-{
-  GstElementClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GST_OGG_DEMUX_H__ */
--- a/gst_plugins_base/ext/ogg/gstoggmux.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1627 +0,0 @@
-/* OGG muxer plugin for GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
-
-#include "gstoggmux.h"
-
-/* memcpy - if someone knows a way to get rid of it, please speak up
- * note: the ogg docs even say you need this... */
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>             /* rand, srand, atoi */
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_mux_debug);
-#define GST_CAT_DEFAULT gst_ogg_mux_debug
-
-/* This isn't generally what you'd want with an end-time macro, because
-   technically the end time of a buffer with invalid duration is invalid. But
-   for sorting ogg pages this is what we want. */
-#define GST_BUFFER_END_TIME(buf) \
-    (GST_BUFFER_DURATION_IS_VALID (buf) \
-    ? GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf) \
-    : GST_BUFFER_TIMESTAMP (buf))
-
-#define GST_GP_FORMAT "[gp %8" G_GINT64_FORMAT "]"
-
-typedef enum
-{
-  GST_OGG_FLAG_BOS = GST_ELEMENT_FLAG_LAST,
-  GST_OGG_FLAG_EOS
-}
-GstOggFlag;
-
-/* elementfactory information */
-static const GstElementDetails gst_ogg_mux_details =
-GST_ELEMENT_DETAILS ("Ogg muxer",
-    "Codec/Muxer",
-    "mux ogg streams (info about ogg: http://xiph.org)",
-    "Wim Taymans <wim@fluendo.com>");
-
-/* OggMux signals and args */
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-/* set to 0.5 seconds by default */
-#define DEFAULT_MAX_DELAY       G_GINT64_CONSTANT(500000000)
-#define DEFAULT_MAX_PAGE_DELAY  G_GINT64_CONSTANT(500000000)
-enum
-{
-  ARG_0,
-  ARG_MAX_DELAY,
-  ARG_MAX_PAGE_DELAY,
-};
-
-static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/ogg")
-    );
-
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d",
-    GST_PAD_SINK,
-    GST_PAD_REQUEST,
-    GST_STATIC_CAPS ("video/x-theora; "
-        "audio/x-vorbis; audio/x-flac; audio/x-speex; "
-        "application/x-ogm-video; application/x-ogm-audio; video/x-dirac; "
-        "video/x-smoke; text/x-cmml, encoded = (boolean) TRUE")
-    );
-
-static void gst_ogg_mux_base_init (gpointer g_class);
-static void gst_ogg_mux_class_init (GstOggMuxClass * klass);
-static void gst_ogg_mux_init (GstOggMux * ogg_mux);
-static void gst_ogg_mux_finalize (GObject * object);
-
-static GstFlowReturn
-gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux);
-static gboolean gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event);
-static GstPad *gst_ogg_mux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name);
-static void gst_ogg_mux_release_pad (GstElement * element, GstPad * pad);
-
-static void gst_ogg_mux_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_ogg_mux_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-static GstStateChangeReturn gst_ogg_mux_change_state (GstElement * element,
-    GstStateChange transition);
-
-static GstElementClass *parent_class = NULL;
-
-/*static guint gst_ogg_mux_signals[LAST_SIGNAL] = { 0 }; */
-
-GType
-gst_ogg_mux_get_type (void)
-{
-  static GType ogg_mux_type = 0;
-
-  if (G_UNLIKELY (ogg_mux_type == 0)) {
-    static const GTypeInfo ogg_mux_info = {
-      sizeof (GstOggMuxClass),
-      gst_ogg_mux_base_init,
-      NULL,
-      (GClassInitFunc) gst_ogg_mux_class_init,
-      NULL,
-      NULL,
-      sizeof (GstOggMux),
-      0,
-      (GInstanceInitFunc) gst_ogg_mux_init,
-    };
-
-    ogg_mux_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstOggMux", &ogg_mux_info,
-        0);
-  }
-  return ogg_mux_type;
-}
-
-static void
-gst_ogg_mux_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory));
-
-  gst_element_class_set_details (element_class, &gst_ogg_mux_details);
-}
-
-static void
-gst_ogg_mux_class_init (GstOggMuxClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->finalize = gst_ogg_mux_finalize;
-  gobject_class->get_property = gst_ogg_mux_get_property;
-  gobject_class->set_property = gst_ogg_mux_set_property;
-
-  gstelement_class->request_new_pad = gst_ogg_mux_request_new_pad;
-  gstelement_class->release_pad = gst_ogg_mux_release_pad;
-
-  g_object_class_install_property (gobject_class, ARG_MAX_DELAY,
-      g_param_spec_uint64 ("max-delay", "Max delay",
-          "Maximum delay in multiplexing streams", 0, G_MAXUINT64,
-          DEFAULT_MAX_DELAY, (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_MAX_PAGE_DELAY,
-      g_param_spec_uint64 ("max-page-delay", "Max page delay",
-          "Maximum delay for sending out a page", 0, G_MAXUINT64,
-          DEFAULT_MAX_PAGE_DELAY, (GParamFlags) G_PARAM_READWRITE));
-
-  gstelement_class->change_state = gst_ogg_mux_change_state;
-
-}
-
-#if 0
-static const GstEventMask *
-gst_ogg_mux_get_sink_event_masks (GstPad * pad)
-{
-  static const GstEventMask gst_ogg_mux_sink_event_masks[] = {
-    {GST_EVENT_EOS, 0},
-    {GST_EVENT_DISCONTINUOUS, 0},
-    {0,}
-  };
-
-  return gst_ogg_mux_sink_event_masks;
-}
-#endif
-
-static void
-gst_ogg_mux_clear (GstOggMux * ogg_mux)
-{
-  ogg_mux->pulling = NULL;
-  ogg_mux->need_headers = TRUE;
-  ogg_mux->max_delay = DEFAULT_MAX_DELAY;
-  ogg_mux->max_page_delay = DEFAULT_MAX_PAGE_DELAY;
-  ogg_mux->delta_pad = NULL;
-  ogg_mux->offset = 0;
-  ogg_mux->next_ts = 0;
-  ogg_mux->last_ts = GST_CLOCK_TIME_NONE;
-}
-
-static void
-gst_ogg_mux_init (GstOggMux * ogg_mux)
-{
-  GstElementClass *klass = GST_ELEMENT_GET_CLASS (ogg_mux);
-
-  ogg_mux->srcpad =
-      gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
-          "src"), "src");
-  gst_pad_set_event_function (ogg_mux->srcpad, gst_ogg_mux_handle_src_event);
-  gst_element_add_pad (GST_ELEMENT (ogg_mux), ogg_mux->srcpad);
-
-  GST_OBJECT_FLAG_SET (GST_ELEMENT (ogg_mux), GST_OGG_FLAG_BOS);
-
-  /* seed random number generator for creation of serial numbers */
-  srand (time (NULL));
-
-  ogg_mux->collect = gst_collect_pads_new ();
-  gst_collect_pads_set_function (ogg_mux->collect,
-      (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_ogg_mux_collected),
-      ogg_mux);
-
-  gst_ogg_mux_clear (ogg_mux);
-}
-
-static void
-gst_ogg_mux_finalize (GObject * object)
-{
-  GstOggMux *ogg_mux;
-
-  ogg_mux = GST_OGG_MUX (object);
-
-  if (ogg_mux->collect) {
-    gst_object_unref (ogg_mux->collect);
-    ogg_mux->collect = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_ogg_mux_ogg_pad_destroy_notify (GstCollectData * data)
-{
-  GstOggPad *oggpad = (GstOggPad *) data;
-  GstBuffer *buf;
-
-  ogg_stream_clear (&oggpad->stream);
-
-  if (oggpad->pagebuffers) {
-    while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) {
-      gst_buffer_unref (buf);
-    }
-    g_queue_free (oggpad->pagebuffers);
-    oggpad->pagebuffers = NULL;
-  }
-}
-
-static GstPadLinkReturn
-gst_ogg_mux_sinkconnect (GstPad * pad, GstPad * peer)
-{
-  GstOggMux *ogg_mux;
-
-  ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad));
-
-  GST_DEBUG_OBJECT (ogg_mux, "sinkconnect triggered on %s", GST_PAD_NAME (pad));
-
-  gst_object_unref (ogg_mux);
-
-  return GST_PAD_LINK_OK;
-}
-
-static GstPad *
-gst_ogg_mux_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * req_name)
-{
-  GstOggMux *ogg_mux;
-  GstPad *newpad;
-  GstElementClass *klass;
-
-  g_return_val_if_fail (templ != NULL, NULL);
-
-  if (templ->direction != GST_PAD_SINK)
-    goto wrong_direction;
-
-  g_return_val_if_fail (GST_IS_OGG_MUX (element), NULL);
-  ogg_mux = GST_OGG_MUX (element);
-
-  klass = GST_ELEMENT_GET_CLASS (element);
-
-  if (templ != gst_element_class_get_pad_template (klass, "sink_%d"))
-    goto wrong_template;
-
-  {
-    gint serial;
-    gchar *name;
-
-    if (req_name == NULL || strlen (req_name) < 6) {
-      /* no name given when requesting the pad, use random serial number */
-      serial = rand ();
-    } else {
-      /* parse serial number from requested padname */
-      serial = atoi (&req_name[5]);
-    }
-    /* create new pad with the name */
-    GST_DEBUG_OBJECT (ogg_mux, "Creating new pad for serial %d", serial);
-    name = g_strdup_printf ("sink_%d", serial);
-    newpad = gst_pad_new_from_template (templ, name);
-    g_free (name);
-
-    /* construct our own wrapper data structure for the pad to
-     * keep track of its status */
-    {
-      GstOggPad *oggpad;
-
-      oggpad = (GstOggPad *)
-          gst_collect_pads_add_pad_full (ogg_mux->collect, newpad,
-          sizeof (GstOggPad), gst_ogg_mux_ogg_pad_destroy_notify);
-      ogg_mux->active_pads++;
-
-      oggpad->serial = serial;
-      ogg_stream_init (&oggpad->stream, serial);
-      oggpad->packetno = 0;
-      oggpad->pageno = 0;
-      oggpad->eos = FALSE;
-      /* we assume there will be some control data first for this pad */
-      oggpad->state = GST_OGG_PAD_STATE_CONTROL;
-      oggpad->new_page = TRUE;
-      oggpad->first_delta = FALSE;
-      oggpad->prev_delta = FALSE;
-      oggpad->pagebuffers = g_queue_new ();
-    }
-  }
-
-  /* setup some pad functions */
-  gst_pad_set_link_function (newpad, gst_ogg_mux_sinkconnect);
-  /* dd the pad to the element */
-  gst_element_add_pad (element, newpad);
-
-  return newpad;
-
-  /* ERRORS */
-wrong_direction:
-  {
-    g_warning ("ogg_mux: request pad that is not a SINK pad\n");
-    return NULL;
-  }
-wrong_template:
-  {
-    g_warning ("ogg_mux: this is not our template!\n");
-    return NULL;
-  }
-}
-
-static void
-gst_ogg_mux_release_pad (GstElement * element, GstPad * pad)
-{
-  GstOggMux *ogg_mux;
-
-  ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad));
-
-  gst_collect_pads_remove_pad (ogg_mux->collect, pad);
-  gst_element_remove_pad (element, pad);
-
-  gst_object_unref (ogg_mux);
-}
-
-/* handle events */
-static gboolean
-gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event)
-{
-  GstEventType type;
-
-  type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
-
-  switch (type) {
-    case GST_EVENT_SEEK:
-      /* disable seeking for now */
-      return FALSE;
-    default:
-      break;
-  }
-
-  return gst_pad_event_default (pad, event);
-}
-
-static GstBuffer *
-gst_ogg_mux_buffer_from_page (GstOggMux * mux, ogg_page * page, gboolean delta)
-{
-  GstBuffer *buffer;
-
-  /* allocate space for header and body */
-  buffer = gst_buffer_new_and_alloc (page->header_len + page->body_len);
-  memcpy (GST_BUFFER_DATA (buffer), page->header, page->header_len);
-  memcpy (GST_BUFFER_DATA (buffer) + page->header_len,
-      page->body, page->body_len);
-
-  /* Here we set granulepos as our OFFSET_END to give easy direct access to
-   * this value later. Before we push it, we reset this to OFFSET + SIZE
-   * (see gst_ogg_mux_push_buffer). */
-  GST_BUFFER_OFFSET_END (buffer) = ogg_page_granulepos (page);
-  if (delta)
-    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
-
-  GST_LOG_OBJECT (mux, GST_GP_FORMAT
-      " created buffer %p from ogg page", ogg_page_granulepos (page), buffer);
-
-  return buffer;
-}
-
-static GstFlowReturn
-gst_ogg_mux_push_buffer (GstOggMux * mux, GstBuffer * buffer)
-{
-  GstCaps *caps;
-
-  /* fix up OFFSET and OFFSET_END again */
-  GST_BUFFER_OFFSET (buffer) = mux->offset;
-  mux->offset += GST_BUFFER_SIZE (buffer);
-  GST_BUFFER_OFFSET_END (buffer) = mux->offset;
-
-  /* Ensure we have monotonically increasing timestamps in the output. */
-  if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
-    if (mux->last_ts != GST_CLOCK_TIME_NONE &&
-        GST_BUFFER_TIMESTAMP (buffer) < mux->last_ts)
-      GST_BUFFER_TIMESTAMP (buffer) = mux->last_ts;
-    else
-      mux->last_ts = GST_BUFFER_TIMESTAMP (buffer);
-  }
-
-  caps = gst_pad_get_negotiated_caps (mux->srcpad);
-  gst_buffer_set_caps (buffer, caps);
-  gst_caps_unref (caps);
-
-  return gst_pad_push (mux->srcpad, buffer);
-}
-
-/* if all queues have at least one page, dequeue the page with the lowest
- * timestamp */
-static gboolean
-gst_ogg_mux_dequeue_page (GstOggMux * mux, GstFlowReturn * flowret)
-{
-  GSList *walk;
-  GstOggPad *opad = NULL;       /* "oldest" pad */
-  GstClockTime oldest = GST_CLOCK_TIME_NONE;
-  GstBuffer *buf = NULL;
-  gboolean ret = FALSE;
-
-  *flowret = GST_FLOW_OK;
-
-  walk = mux->collect->data;
-  while (walk) {
-    GstOggPad *pad = (GstOggPad *) walk->data;
-
-    /* We need each queue to either be at EOS, or have one or more pages
-     * available with a set granulepos (i.e. not -1), otherwise we don't have
-     * enough data yet to determine which stream needs to go next for correct
-     * time ordering. */
-    if (pad->pagebuffers->length == 0) {
-      if (pad->eos) {
-        GST_LOG_OBJECT (pad->collect.pad,
-            "pad is EOS, skipping for dequeue decision");
-      } else {
-        GST_LOG_OBJECT (pad->collect.pad,
-            "no pages in this queue, can't dequeue");
-        return FALSE;
-      }
-    } else {
-      /* We then need to check for a non-negative granulepos */
-      int i;
-      gboolean valid = FALSE;
-
-      for (i = 0; i < pad->pagebuffers->length; i++) {
-        buf = g_queue_peek_nth (pad->pagebuffers, i);
-        /* Here we check the OFFSET_END, which is actually temporarily the
-         * granulepos value for this buffer */
-        if (GST_BUFFER_OFFSET_END (buf) != -1) {
-          valid = TRUE;
-          break;
-        }
-      }
-      if (!valid) {
-        GST_LOG_OBJECT (pad->collect.pad,
-            "No page timestamps in queue, can't dequeue");
-        return FALSE;
-      }
-    }
-
-    walk = g_slist_next (walk);
-  }
-
-  walk = mux->collect->data;
-  while (walk) {
-    GstOggPad *pad = (GstOggPad *) walk->data;
-
-    /* any page with a granulepos of -1 can be pushed immediately.
-     * TODO: it CAN be, but it seems silly to do so? */
-    buf = g_queue_peek_head (pad->pagebuffers);
-    while (buf && GST_BUFFER_OFFSET_END (buf) == -1) {
-      GST_LOG_OBJECT (pad->collect.pad, "[gp        -1] pushing page");
-      g_queue_pop_head (pad->pagebuffers);
-      *flowret = gst_ogg_mux_push_buffer (mux, buf);
-      buf = g_queue_peek_head (pad->pagebuffers);
-      ret = TRUE;
-    }
-
-    if (buf) {
-      /* if no oldest buffer yet, take this one */
-      if (oldest == GST_CLOCK_TIME_NONE) {
-        GST_LOG_OBJECT (mux, "no oldest yet, taking buffer %p from pad %"
-            GST_PTR_FORMAT " with gp time %" GST_TIME_FORMAT,
-            buf, pad->collect.pad, GST_TIME_ARGS (GST_BUFFER_OFFSET (buf)));
-        oldest = GST_BUFFER_OFFSET (buf);
-        opad = pad;
-      } else {
-        /* if we have an oldest, compare with this one */
-        if (GST_BUFFER_OFFSET (buf) < oldest) {
-          GST_LOG_OBJECT (mux, "older buffer %p, taking from pad %"
-              GST_PTR_FORMAT " with gp time %" GST_TIME_FORMAT,
-              buf, pad->collect.pad, GST_TIME_ARGS (GST_BUFFER_OFFSET (buf)));
-          oldest = GST_BUFFER_OFFSET (buf);
-          opad = pad;
-        }
-      }
-    }
-    walk = g_slist_next (walk);
-  }
-
-  if (oldest != GST_CLOCK_TIME_NONE) {
-    g_assert (opad);
-    buf = g_queue_pop_head (opad->pagebuffers);
-    GST_LOG_OBJECT (opad->collect.pad,
-        GST_GP_FORMAT " pushing oldest page buffer %p (granulepos time %"
-        GST_TIME_FORMAT ")", GST_BUFFER_OFFSET_END (buf), buf,
-        GST_TIME_ARGS (GST_BUFFER_OFFSET (buf)));
-    *flowret = gst_ogg_mux_push_buffer (mux, buf);
-    ret = TRUE;
-  }
-
-  return ret;
-}
-
-/* put the given ogg page on a per-pad queue, timestamping it correctly.
- * after that, dequeue and push as many pages as possible.
- * Caller should make sure:
- * pad->timestamp     was set with the timestamp of the first packet put
- *                    on the page
- * pad->timestamp_end was set with the timestamp + duration of the last packet
- *                    put on the page
- * pad->gp_time       was set with the time matching the gp of the last
- *                    packet put on the page
- *
- * will also reset timestamp and timestamp_end, so caller func can restart
- * counting.
- */
-static GstFlowReturn
-gst_ogg_mux_pad_queue_page (GstOggMux * mux, GstOggPad * pad, ogg_page * page,
-    gboolean delta)
-{
-  GstFlowReturn ret;
-  GstBuffer *buffer = gst_ogg_mux_buffer_from_page (mux, page, delta);
-
-  /* take the timestamp of the first packet on this page */
-  GST_BUFFER_TIMESTAMP (buffer) = pad->timestamp;
-  GST_BUFFER_DURATION (buffer) = pad->timestamp_end - pad->timestamp;
-  /* take the gp time of the last completed packet on this page */
-  GST_BUFFER_OFFSET (buffer) = pad->gp_time;
-
-  /* the next page will start where the current page's end time leaves off */
-  pad->timestamp = pad->timestamp_end;
-
-  g_queue_push_tail (pad->pagebuffers, buffer);
-  GST_LOG_OBJECT (pad->collect.pad, GST_GP_FORMAT
-      " queued buffer page %p (gp time %"
-      GST_TIME_FORMAT ", timestamp %" GST_TIME_FORMAT
-      "), %d page buffers queued", ogg_page_granulepos (page),
-      buffer, GST_TIME_ARGS (GST_BUFFER_OFFSET (buffer)),
-      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
-      g_queue_get_length (pad->pagebuffers));
-
-  while (gst_ogg_mux_dequeue_page (mux, &ret)) {
-    if (ret != GST_FLOW_OK)
-      break;
-  }
-
-  return ret;
-}
-
-/*
- * Given two pads, compare the buffers queued on it.
- * Returns:
- *  0 if they have an equal priority
- * -1 if the first is better
- *  1 if the second is better
- * Priority decided by: a) validity, b) older timestamp, c) smaller number
- * of muxed pages
- */
-static gint
-gst_ogg_mux_compare_pads (GstOggMux * ogg_mux, GstOggPad * first,
-    GstOggPad * second)
-{
-  guint64 firsttime, secondtime;
-
-  /* if the first pad doesn't contain anything or is even NULL, return
-   * the second pad as best candidate and vice versa */
-  if (first == NULL || (first->buffer == NULL && first->next_buffer == NULL))
-    return 1;
-  if (second == NULL || (second->buffer == NULL && second->next_buffer == NULL))
-    return -1;
-
-  /* no timestamp on first buffer, it must go first */
-  if (first->buffer)
-    firsttime = GST_BUFFER_TIMESTAMP (first->buffer);
-  else
-    firsttime = GST_BUFFER_TIMESTAMP (first->next_buffer);
-  if (firsttime == GST_CLOCK_TIME_NONE)
-    return -1;
-
-  /* no timestamp on second buffer, it must go first */
-  if (second->buffer)
-    secondtime = GST_BUFFER_TIMESTAMP (second->buffer);
-  else
-    secondtime = GST_BUFFER_TIMESTAMP (second->next_buffer);
-  if (secondtime == GST_CLOCK_TIME_NONE)
-    return 1;
-
-  /* first buffer has higher timestamp, second one should go first */
-  if (secondtime < firsttime)
-    return 1;
-  /* second buffer has higher timestamp, first one should go first */
-  else if (secondtime > firsttime)
-    return -1;
-  else {
-    /* buffers with equal timestamps, prefer the pad that has the
-     * least number of pages muxed */
-    if (second->pageno < first->pageno)
-      return 1;
-    else if (second->pageno > first->pageno)
-      return -1;
-  }
-
-  /* same priority if all of the above failed */
-  return 0;
-}
-
-/* make sure at least one buffer is queued on all pads, two if possible
- * 
- * if pad->buffer == NULL, pad->next_buffer !=  NULL, then
- *   we do not know if the buffer is the last or not
- * if pad->buffer != NULL, pad->next_buffer != NULL, then
- *   pad->buffer is not the last buffer for the pad
- * if pad->buffer != NULL, pad->next_buffer == NULL, then
- *   pad->buffer if the last buffer for the pad
- * 
- * returns a pointer to an oggpad that holds the best buffer, or
- * NULL when no pad was usable. "best" means the buffer marked
- * with the lowest timestamp. If best->buffer == NULL then nothing
- * should be done until more data arrives */
-static GstOggPad *
-gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
-{
-  GstOggPad *bestpad = NULL, *still_hungry = NULL;
-  GSList *walk;
-
-  /* try to make sure we have a buffer from each usable pad first */
-  walk = ogg_mux->collect->data;
-  while (walk) {
-    GstOggPad *pad;
-    GstCollectData *data;
-
-    data = (GstCollectData *) walk->data;
-    pad = (GstOggPad *) data;
-
-    walk = g_slist_next (walk);
-
-    GST_LOG_OBJECT (data->pad, "looking at pad for buffer");
-
-    /* try to get a new buffer for this pad if needed and possible */
-    if (pad->buffer == NULL) {
-      GstBuffer *buf;
-      gboolean incaps;
-
-      /* shift the buffer along if needed (it's okay if next_buffer is NULL) */
-      if (pad->buffer == NULL) {
-        GST_LOG_OBJECT (data->pad, "shifting buffer %" GST_PTR_FORMAT,
-            pad->next_buffer);
-        pad->buffer = pad->next_buffer;
-        pad->next_buffer = NULL;
-      }
-
-      buf = gst_collect_pads_pop (ogg_mux->collect, data);
-      GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
-
-      /* On EOS we get a NULL buffer */
-      if (buf != NULL) {
-        if (ogg_mux->delta_pad == NULL &&
-            GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT))
-          ogg_mux->delta_pad = pad;
-
-        incaps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
-        /* if we need headers */
-        if (pad->state == GST_OGG_PAD_STATE_CONTROL) {
-          /* and we have one */
-          if (incaps) {
-            GST_DEBUG_OBJECT (ogg_mux,
-                "got incaps buffer in control state, ignoring");
-            /* just ignore */
-            gst_buffer_unref (buf);
-            buf = NULL;
-          } else {
-            GST_DEBUG_OBJECT (ogg_mux,
-                "got data buffer in control state, switching " "to data mode");
-            /* this is a data buffer so switch to data state */
-            pad->state = GST_OGG_PAD_STATE_DATA;
-          }
-        }
-      } else {
-        GST_DEBUG_OBJECT (data->pad, "EOS on pad");
-        if (!pad->eos) {
-          ogg_page page;
-          GstFlowReturn ret;
-
-          /* it's no longer active */
-          ogg_mux->active_pads--;
-
-          /* Just gone to EOS. Flush existing page(s) */
-          pad->eos = TRUE;
-
-          while (ogg_stream_flush (&pad->stream, &page)) {
-            /* Place page into the per-pad queue */
-            ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
-                pad->first_delta);
-            /* increment the page number counter */
-            pad->pageno++;
-            /* mark other pages as delta */
-            pad->first_delta = TRUE;
-          }
-        }
-      }
-
-      pad->next_buffer = buf;
-    }
-
-    /* we should have a buffer now, see if it is the best pad to
-     * pull on */
-    if (pad->buffer || pad->next_buffer) {
-      if (gst_ogg_mux_compare_pads (ogg_mux, bestpad, pad) > 0) {
-        GST_LOG_OBJECT (data->pad,
-            "new best pad, with buffers %" GST_PTR_FORMAT
-            " and %" GST_PTR_FORMAT, pad->buffer, pad->next_buffer);
-
-        bestpad = pad;
-      }
-    } else if (!pad->eos) {
-      GST_LOG_OBJECT (data->pad, "hungry pad");
-      still_hungry = pad;
-    }
-  }
-
-  if (still_hungry)
-    /* drop back into collectpads... */
-    return still_hungry;
-  else
-    return bestpad;
-}
-
-static GList *
-gst_ogg_mux_get_headers (GstOggPad * pad)
-{
-  GList *res = NULL;
-  GstOggMux *ogg_mux;
-  GstStructure *structure;
-  GstCaps *caps;
-  GstPad *thepad;
-
-  thepad = pad->collect.pad;
-
-  ogg_mux = GST_OGG_MUX (GST_PAD_PARENT (thepad));
-
-  GST_LOG_OBJECT (thepad, "getting headers");
-
-  caps = gst_pad_get_negotiated_caps (thepad);
-  if (caps != NULL) {
-    const GValue *streamheader;
-
-    structure = gst_caps_get_structure (caps, 0);
-    if (strcmp (gst_structure_get_name (structure), "video/x-dirac") == 0) {
-      GstBuffer *buf = gst_buffer_new_and_alloc (16);
-      int fps_n = 12;
-      int fps_d = 1;
-
-      gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
-
-      memcpy (GST_BUFFER_DATA (buf), "KW-DIRAC", 8);
-      GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 8, fps_n);
-      GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 12, fps_d);
-
-      res = g_list_append (res, buf);
-
-      //res = g_list_append (res, gst_buffer_ref(pad->buffer));
-    } else {
-      streamheader = gst_structure_get_value (structure, "streamheader");
-      if (streamheader != NULL) {
-        GST_LOG_OBJECT (thepad, "got header");
-        if (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) {
-          GArray *bufarr = g_value_peek_pointer (streamheader);
-          gint i;
-
-          GST_LOG_OBJECT (thepad, "got fixed list");
-
-          for (i = 0; i < bufarr->len; i++) {
-            GValue *bufval = &g_array_index (bufarr, GValue, i);
-
-            GST_LOG_OBJECT (thepad, "item %d", i);
-            if (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER) {
-              GstBuffer *buf = g_value_peek_pointer (bufval);
-
-              GST_LOG_OBJECT (thepad, "adding item %d to header list", i);
-
-              gst_buffer_ref (buf);
-              res = g_list_append (res, buf);
-            }
-          }
-        } else {
-          GST_LOG_OBJECT (thepad, "streamheader is not fixed list");
-        }
-      } else {
-        GST_LOG_OBJECT (thepad, "caps don't have streamheader");
-      }
-    }
-    gst_caps_unref (caps);
-  } else {
-    GST_LOG_OBJECT (thepad, "got empty caps as negotiated format");
-  }
-  return res;
-}
-
-static GstCaps *
-gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
-{
-  GstStructure *structure;
-  GValue array = { 0 };
-  GList *walk = buffers;
-
-  caps = gst_caps_make_writable (caps);
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  /* put buffers in a fixed list */
-  g_value_init (&array, GST_TYPE_ARRAY);
-
-  while (walk) {
-    GstBuffer *buf = GST_BUFFER (walk->data);
-    GstBuffer *copy;
-    GValue value = { 0 };
-
-    walk = walk->next;
-
-    /* mark buffer */
-    GST_LOG ("Setting IN_CAPS on buffer of length %d", GST_BUFFER_SIZE (buf));
-    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
-
-    g_value_init (&value, GST_TYPE_BUFFER);
-    copy = gst_buffer_copy (buf);
-    gst_value_set_buffer (&value, copy);
-    gst_buffer_unref (copy);
-    gst_value_array_append_value (&array, &value);
-    g_value_unset (&value);
-  }
-  gst_structure_set_value (structure, "streamheader", &array);
-  g_value_unset (&array);
-
-  return caps;
-}
-
-/*
- * For each pad we need to write out one (small) header in one
- * page that allows decoders to identify the type of the stream.
- * After that we need to write out all extra info for the decoders.
- * In the case of a codec that also needs data as configuration, we can
- * find that info in the streamcaps. 
- * After writing the headers we must start a new page for the data.
- */
-static GstFlowReturn
-gst_ogg_mux_send_headers (GstOggMux * mux)
-{
-  GSList *walk;
-  GList *hbufs, *hwalk;
-  GstCaps *caps;
-  GstFlowReturn ret;
-
-  hbufs = NULL;
-  ret = GST_FLOW_OK;
-
-  GST_LOG_OBJECT (mux, "collecting headers");
-
-  walk = mux->collect->data;
-  while (walk) {
-    GstOggPad *pad;
-    GstPad *thepad;
-
-    pad = (GstOggPad *) walk->data;
-    thepad = pad->collect.pad;
-
-    walk = g_slist_next (walk);
-
-    GST_LOG_OBJECT (mux, "looking at pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
-
-    /* if the pad has no buffer, we don't care */
-    if (pad->buffer == NULL && pad->next_buffer == NULL)
-      continue;
-
-    /* now figure out the headers */
-    pad->headers = gst_ogg_mux_get_headers (pad);
-  }
-
-  GST_LOG_OBJECT (mux, "creating BOS pages");
-  walk = mux->collect->data;
-  while (walk) {
-    GstOggPad *pad;
-    GstBuffer *buf;
-    ogg_packet packet;
-    ogg_page page;
-    GstPad *thepad;
-    GstCaps *caps;
-    GstStructure *structure;
-    GstBuffer *hbuf;
-
-    pad = (GstOggPad *) walk->data;
-    thepad = pad->collect.pad;
-    caps = gst_pad_get_negotiated_caps (thepad);
-    structure = gst_caps_get_structure (caps, 0);
-
-    walk = walk->next;
-
-    pad->packetno = 0;
-
-    GST_LOG_OBJECT (thepad, "looping over headers");
-
-    if (pad->headers) {
-      buf = GST_BUFFER (pad->headers->data);
-      pad->headers = g_list_remove (pad->headers, buf);
-    } else if (pad->buffer) {
-      buf = pad->buffer;
-      gst_buffer_ref (buf);
-    } else if (pad->next_buffer) {
-      buf = pad->next_buffer;
-      gst_buffer_ref (buf);
-    } else {
-      /* fixme -- should be caught in the previous list traversal. */
-      GST_OBJECT_LOCK (pad);
-      g_critical ("No headers or buffers on pad %s:%s",
-          GST_DEBUG_PAD_NAME (pad));
-      GST_OBJECT_UNLOCK (pad);
-      continue;
-    }
-
-    /* create a packet from the buffer */
-    packet.packet = GST_BUFFER_DATA (buf);
-    packet.bytes = GST_BUFFER_SIZE (buf);
-    packet.granulepos = GST_BUFFER_OFFSET_END (buf);
-    if (packet.granulepos == -1)
-      packet.granulepos = 0;
-    /* mark BOS and packet number */
-    packet.b_o_s = (pad->packetno == 0);
-    packet.packetno = pad->packetno++;
-    /* mark EOS */
-    packet.e_o_s = 0;
-
-    /* swap the packet in */
-    ogg_stream_packetin (&pad->stream, &packet);
-    gst_buffer_unref (buf);
-
-    GST_LOG_OBJECT (thepad, "flushing out BOS page");
-    if (!ogg_stream_flush (&pad->stream, &page))
-      g_critical ("Could not flush BOS page");
-
-    hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
-
-    GST_LOG_OBJECT (mux, "swapped out page with mime type %s",
-        gst_structure_get_name (structure));
-
-    /* quick hack: put Theora and Dirac video pages at the front.
-     * Ideally, we would have a settable enum for which Ogg
-     * profile we work with, and order based on that.
-     * (FIXME: if there is more than one video stream, shouldn't we only put
-     * one's BOS into the first page, followed by an audio stream's BOS, and
-     * only then followed by the remaining video and audio streams?) */
-    if (gst_structure_has_name (structure, "video/x-theora")) {
-      GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Theora");
-      hbufs = g_list_prepend (hbufs, hbuf);
-    } else if (gst_structure_has_name (structure, "video/x-dirac")) {
-      GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Dirac");
-      hbufs = g_list_prepend (hbufs, hbuf);
-    } else {
-      hbufs = g_list_append (hbufs, hbuf);
-    }
-    gst_caps_unref (caps);
-  }
-
-  GST_LOG_OBJECT (mux, "creating next headers");
-  walk = mux->collect->data;
-  while (walk) {
-    GstOggPad *pad;
-    GstPad *thepad;
-
-    pad = (GstOggPad *) walk->data;
-    thepad = pad->collect.pad;
-
-    walk = walk->next;
-
-    GST_LOG_OBJECT (mux, "looping over headers for pad %s:%s",
-        GST_DEBUG_PAD_NAME (thepad));
-
-    hwalk = pad->headers;
-    while (hwalk) {
-      GstBuffer *buf = GST_BUFFER (hwalk->data);
-      ogg_packet packet;
-      ogg_page page;
-
-      hwalk = hwalk->next;
-
-      /* create a packet from the buffer */
-      packet.packet = GST_BUFFER_DATA (buf);
-      packet.bytes = GST_BUFFER_SIZE (buf);
-      packet.granulepos = GST_BUFFER_OFFSET_END (buf);
-      if (packet.granulepos == -1)
-        packet.granulepos = 0;
-      /* mark BOS and packet number */
-      packet.b_o_s = (pad->packetno == 0);
-      packet.packetno = pad->packetno++;
-      /* mark EOS */
-      packet.e_o_s = 0;
-
-      /* swap the packet in */
-      ogg_stream_packetin (&pad->stream, &packet);
-      gst_buffer_unref (buf);
-
-      /* if last header, flush page */
-      if (hwalk == NULL) {
-        GST_LOG_OBJECT (mux,
-            "flushing page as packet %" G_GUINT64_FORMAT " is first or "
-            "last packet", pad->packetno);
-        while (ogg_stream_flush (&pad->stream, &page)) {
-          GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
-
-          GST_LOG_OBJECT (mux, "swapped out page");
-          hbufs = g_list_append (hbufs, hbuf);
-        }
-      } else {
-        GST_LOG_OBJECT (mux, "try to swap out page");
-        /* just try to swap out a page then */
-        while (ogg_stream_pageout (&pad->stream, &page) > 0) {
-          GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
-
-          GST_LOG_OBJECT (mux, "swapped out page");
-          hbufs = g_list_append (hbufs, hbuf);
-        }
-      }
-    }
-    g_list_free (pad->headers);
-    pad->headers = NULL;
-  }
-  /* hbufs holds all buffers for the headers now */
-
-  /* create caps with the buffers */
-  caps = gst_pad_get_caps (mux->srcpad);
-  if (caps) {
-    caps = gst_ogg_mux_set_header_on_caps (caps, hbufs);
-    gst_pad_set_caps (mux->srcpad, caps);
-    gst_caps_unref (caps);
-  }
-  /* and send the buffers */
-  hwalk = hbufs;
-  while (hwalk) {
-    GstBuffer *buf = GST_BUFFER (hwalk->data);
-
-    hwalk = hwalk->next;
-
-    if ((ret = gst_ogg_mux_push_buffer (mux, buf)) != GST_FLOW_OK)
-      break;
-  }
-  g_list_free (hbufs);
-
-  return ret;
-}
-
-/* this function is called to process data on the best pending pad.
- *
- * basic idea:
- *
- * 1) store the selected pad and keep on pulling until we fill a
- *    complete ogg page or the ogg page is filled above the max-delay
- *    threshold. This is needed because the ogg spec says that
- *    you should fill a complete page with data from the same logical
- *    stream. When the page is filled, go back to 1).
- * 2) before filling a page, read ahead one more buffer to see if this
- *    packet is the last of the stream. We need to do this because the ogg
- *    spec mandates that the last packet should have the EOS flag set before
- *    sending it to ogg. if pad->buffer is NULL we need to wait to find out
- *    whether there are any more buffers.
- * 3) pages get queued on a per-pad queue. Every time a page is queued, a
- *    dequeue is called, which will dequeue the oldest page on any pad, provided
- *    that ALL pads have at least one marked page in the queue (or remaining
- *    pads are at EOS)
- */
-static GstFlowReturn
-gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPad * best)
-{
-  gboolean delta_unit;
-  GstFlowReturn ret;
-  gint64 granulepos = 0;
-  GstClockTime timestamp, gp_time;
-
-  GST_LOG_OBJECT (ogg_mux, "best pad %" GST_PTR_FORMAT
-      ", currently pulling from %" GST_PTR_FORMAT, best->collect.pad,
-      ogg_mux->pulling);
-
-  /* best->buffer is non-NULL, either the pad is EOS's or there is a next 
-   * buffer */
-  if (best->next_buffer == NULL && !best->eos) {
-    GST_WARNING_OBJECT (ogg_mux, "no subsequent buffer and EOS not reached");
-    return GST_FLOW_WRONG_STATE;
-  }
-
-  /* if we were already pulling from one pad, but the new "best" buffer is
-   * from another pad, we need to check if we have reason to flush a page
-   * for the pad we were pulling from before */
-  if (ogg_mux->pulling && best &&
-      ogg_mux->pulling != best && ogg_mux->pulling->buffer) {
-    GstOggPad *pad = ogg_mux->pulling;
-
-    GstClockTime last_ts = GST_BUFFER_END_TIME (pad->buffer);
-
-    /* if the next packet in the current page is going to make the page
-     * too long, we need to flush */
-    if (last_ts > ogg_mux->next_ts + ogg_mux->max_delay) {
-      ogg_page page;
-
-      GST_LOG_OBJECT (pad->collect.pad,
-          GST_GP_FORMAT " stored packet %" G_GINT64_FORMAT
-          " will make page too long, flushing",
-          GST_BUFFER_OFFSET_END (pad->buffer), pad->stream.packetno);
-
-      while (ogg_stream_flush (&pad->stream, &page)) {
-        /* end time of this page is the timestamp of the next buffer */
-        ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer);
-        /* Place page into the per-pad queue */
-        ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
-            pad->first_delta);
-        /* increment the page number counter */
-        pad->pageno++;
-        /* mark other pages as delta */
-        pad->first_delta = TRUE;
-      }
-      pad->new_page = TRUE;
-      ogg_mux->pulling = NULL;
-    }
-  }
-
-  /* if we don't know which pad to pull on, use the best one */
-  if (ogg_mux->pulling == NULL) {
-    ogg_mux->pulling = best;
-    GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "pulling from best pad");
-
-    /* remember timestamp and gp time of first buffer for this new pad */
-    if (ogg_mux->pulling != NULL) {
-      ogg_mux->next_ts = GST_BUFFER_TIMESTAMP (ogg_mux->pulling->buffer);
-      GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "updated times, next ts %"
-          GST_TIME_FORMAT, GST_TIME_ARGS (ogg_mux->next_ts));
-    } else {
-      /* no pad to pull on, send EOS */
-      gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ());
-      return GST_FLOW_WRONG_STATE;
-    }
-  }
-
-  if (ogg_mux->need_headers) {
-    ret = gst_ogg_mux_send_headers (ogg_mux);
-    ogg_mux->need_headers = FALSE;
-  }
-
-  /* we are pulling from a pad, continue to do so until a page
-   * has been filled and queued */
-  if (ogg_mux->pulling != NULL) {
-    ogg_packet packet;
-    ogg_page page;
-    GstBuffer *buf, *tmpbuf;
-    GstOggPad *pad = ogg_mux->pulling;
-    gint64 duration;
-    gboolean force_flush;
-
-    GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "pulling from pad");
-
-    /* now see if we have a buffer */
-    buf = pad->buffer;
-    if (buf == NULL) {
-      GST_DEBUG_OBJECT (ogg_mux, "pad was EOS");
-      ogg_mux->pulling = NULL;
-      return GST_FLOW_OK;
-    }
-
-    delta_unit = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
-    duration = GST_BUFFER_DURATION (buf);
-
-    /* if the current "next timestamp" on the pad is unset, then this is the
-     * first packet on the new page.  Update our pad's page timestamp */
-    if (ogg_mux->pulling->timestamp == GST_CLOCK_TIME_NONE) {
-      ogg_mux->pulling->timestamp = GST_BUFFER_TIMESTAMP (buf);
-      GST_LOG_OBJECT (ogg_mux->pulling->collect.pad,
-          "updated pad timestamp to %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-    }
-    /* create a packet from the buffer */
-    packet.packet = GST_BUFFER_DATA (buf);
-    packet.bytes = GST_BUFFER_SIZE (buf);
-    packet.granulepos = GST_BUFFER_OFFSET_END (buf);
-    if (packet.granulepos == -1)
-      packet.granulepos = 0;
-    /* mark BOS and packet number */
-    packet.b_o_s = (pad->packetno == 0);
-    packet.packetno = pad->packetno++;
-    GST_LOG_OBJECT (pad->collect.pad, GST_GP_FORMAT
-        " packet %" G_GINT64_FORMAT " (%ld bytes) created from buffer",
-        packet.granulepos, packet.packetno, packet.bytes);
-
-    packet.e_o_s = (pad->eos ? 1 : 0);
-    tmpbuf = NULL;
-
-    /* we flush when we see a new keyframe */
-    force_flush = (pad->prev_delta && !delta_unit);
-    if (duration != -1) {
-      pad->duration += duration;
-      /* if page duration exceeds max, flush page */
-      if (pad->duration > ogg_mux->max_page_delay) {
-        force_flush = TRUE;
-        pad->duration = 0;
-      }
-    }
-
-    if (GST_BUFFER_IS_DISCONT (buf)) {
-      packet.packetno++;
-      /* No public API for this; hack things in */
-      pad->stream.pageno++;
-      force_flush = TRUE;
-    }
-
-    /* flush the currently built page if necessary */
-    if (force_flush) {
-      GST_LOG_OBJECT (pad->collect.pad,
-          GST_GP_FORMAT " forced flush of page before this packet",
-          GST_BUFFER_OFFSET_END (pad->buffer));
-      while (ogg_stream_flush (&pad->stream, &page)) {
-        /* end time of this page is the timestamp of the next buffer */
-        ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer);
-        ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
-            pad->first_delta);
-
-        /* increment the page number counter */
-        pad->pageno++;
-        /* mark other pages as delta */
-        pad->first_delta = TRUE;
-      }
-      pad->new_page = TRUE;
-    }
-
-    /* if this is the first packet of a new page figure out the delta flag */
-    if (pad->new_page) {
-      if (delta_unit) {
-        /* mark the page as delta */
-        pad->first_delta = TRUE;
-      } else {
-        /* got a keyframe */
-        if (ogg_mux->delta_pad == pad) {
-          /* if we get it on the pad with deltaunits,
-           * we mark the page as non delta */
-          pad->first_delta = FALSE;
-        } else if (ogg_mux->delta_pad != NULL) {
-          /* if there are pads with delta frames, we
-           * must mark this one as delta */
-          pad->first_delta = TRUE;
-        } else {
-          pad->first_delta = FALSE;
-        }
-      }
-      pad->new_page = FALSE;
-    }
-
-    /* save key unit to track delta->key unit transitions */
-    pad->prev_delta = delta_unit;
-
-    /* swap the packet in */
-    if (packet.e_o_s == 1)
-      GST_DEBUG_OBJECT (pad->collect.pad, "swapping in EOS packet");
-    if (packet.b_o_s == 1)
-      GST_DEBUG_OBJECT (pad->collect.pad, "swapping in BOS packet");
-
-    ogg_stream_packetin (&pad->stream, &packet);
-
-    gp_time = GST_BUFFER_OFFSET (pad->buffer);
-    granulepos = GST_BUFFER_OFFSET_END (pad->buffer);
-    timestamp = GST_BUFFER_TIMESTAMP (pad->buffer);
-
-    GST_LOG_OBJECT (pad->collect.pad,
-        GST_GP_FORMAT " packet %" G_GINT64_FORMAT ", gp time %"
-        GST_TIME_FORMAT ", timestamp %" GST_TIME_FORMAT " packetin'd",
-        granulepos, packet.packetno, GST_TIME_ARGS (gp_time),
-        GST_TIME_ARGS (timestamp));
-    /* don't need the old buffer anymore */
-    gst_buffer_unref (pad->buffer);
-    /* store new readahead buffer */
-    pad->buffer = tmpbuf;
-
-    /* let ogg write out the pages now. The packet we got could end
-     * up in more than one page so we need to write them all */
-    if (ogg_stream_pageout (&pad->stream, &page) > 0) {
-      /* we have a new page, so we need to timestamp it correctly.
-       * if this fresh packet ends on this page, then the page's granulepos
-       * comes from that packet, and we should set this buffer's timestamp */
-
-      GST_LOG_OBJECT (pad->collect.pad,
-          GST_GP_FORMAT " packet %" G_GINT64_FORMAT ", time %"
-          GST_TIME_FORMAT ") caused new page",
-          granulepos, packet.packetno, GST_TIME_ARGS (timestamp));
-      GST_LOG_OBJECT (pad->collect.pad,
-          GST_GP_FORMAT " new page %ld", ogg_page_granulepos (&page),
-          pad->stream.pageno);
-
-      if (ogg_page_granulepos (&page) == granulepos) {
-        /* the packet we streamed in finishes on the current page,
-         * because the page's granulepos is the granulepos of the last
-         * packet completed on that page,
-         * so update the timestamp that we will give to the page */
-        GST_LOG_OBJECT (pad->collect.pad,
-            GST_GP_FORMAT
-            " packet finishes on current page, updating gp time to %"
-            GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (gp_time));
-        pad->gp_time = gp_time;
-      } else {
-        GST_LOG_OBJECT (pad->collect.pad,
-            GST_GP_FORMAT
-            " packet spans beyond current page, keeping old gp time %"
-            GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (pad->gp_time));
-      }
-
-      /* push the page */
-      /* end time of this page is the timestamp of the next buffer */
-      pad->timestamp_end = timestamp;
-      ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, pad->first_delta);
-      pad->pageno++;
-      /* mark next pages as delta */
-      pad->first_delta = TRUE;
-
-      /* use an inner loop here to flush the remaining pages and
-       * mark them as delta frames as well */
-      while (ogg_stream_pageout (&pad->stream, &page) > 0) {
-        if (ogg_page_granulepos (&page) == granulepos) {
-          /* the page has taken up the new packet completely, which means
-           * the packet ends the page and we can update the gp time
-           * before pushing out */
-          pad->gp_time = gp_time;
-        }
-
-        /* we have a complete page now, we can push the page
-         * and make sure to pull on a new pad the next time around */
-        ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
-            pad->first_delta);
-        /* increment the page number counter */
-        pad->pageno++;
-      }
-      /* need a new page as well */
-      pad->new_page = TRUE;
-      pad->duration = 0;
-      /* we're done pulling on this pad, make sure to choose a new
-       * pad for pulling in the next iteration */
-      ogg_mux->pulling = NULL;
-    }
-
-    /* Update the gp time, if necessary, since any future page will have at
-     * least this gp time.
-     */
-    if (pad->gp_time < gp_time) {
-      pad->gp_time = gp_time;
-      GST_LOG_OBJECT (pad->collect.pad,
-          "Updated running gp time of pad %" GST_PTR_FORMAT
-          " to %" GST_TIME_FORMAT, pad->collect.pad, GST_TIME_ARGS (gp_time));
-    }
-  }
-
-  return GST_FLOW_OK;
-}
-
-/** all_pads_eos:
- *
- * Checks if all pads are EOS'd by peeking.
- *
- * Returns TRUE if all pads are EOS.
- */
-static gboolean
-all_pads_eos (GstCollectPads * pads)
-{
-  GSList *walk;
-  gboolean alleos = TRUE;
-
-  walk = pads->data;
-  while (walk) {
-    GstBuffer *buf;
-    GstCollectData *data = (GstCollectData *) walk->data;
-
-    buf = gst_collect_pads_peek (pads, data);
-    if (buf) {
-      alleos = FALSE;
-      gst_buffer_unref (buf);
-      goto beach;
-    }
-    walk = walk->next;
-  }
-beach:
-  return alleos;
-}
-
-/* This function is called when there is data on all pads.
- * 
- * It finds a pad to pull on, this is done by looking at the buffers
- * to decide which one to use, and using the 'oldest' one first. It then calls
- * gst_ogg_mux_process_best_pad() to process as much data as possible.
- * 
- * If all the pads have received EOS, it flushes out all data by continually
- * getting the best pad and calling gst_ogg_mux_process_best_pad() until they
- * are all empty, and then sends EOS.
- */
-static GstFlowReturn
-gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux)
-{
-  GstOggPad *best;
-  GstFlowReturn ret;
-  gint activebefore;
-
-  GST_LOG_OBJECT (ogg_mux, "collected");
-
-  activebefore = ogg_mux->active_pads;
-
-  /* queue buffers on all pads; find a buffer with the lowest timestamp */
-  best = gst_ogg_mux_queue_pads (ogg_mux);
-  if (best && !best->buffer) {
-    GST_DEBUG_OBJECT (ogg_mux, "No buffer available on best pad");
-    return GST_FLOW_OK;
-  }
-
-  if (!best) {
-    return GST_FLOW_WRONG_STATE;
-  }
-
-  ret = gst_ogg_mux_process_best_pad (ogg_mux, best);
-
-  if (ogg_mux->active_pads < activebefore) {
-    /* If the active pad count went down, this mean at least one pad has gone
-     * EOS. Since CollectPads only calls _collected() once when all pads are
-     * EOS, and our code doesn't _pop() from all pads we need to check that by
-     * peeking on all pads, else we won't be called again and the muxing will
-     * not terminate (push out EOS). */
-
-    /* if all the pads have been removed, flush all pending data */
-    if ((ret == GST_FLOW_OK) && all_pads_eos (pads)) {
-      GST_LOG_OBJECT (ogg_mux, "no pads remaining, flushing data");
-
-      do {
-        best = gst_ogg_mux_queue_pads (ogg_mux);
-        if (best)
-          ret = gst_ogg_mux_process_best_pad (ogg_mux, best);
-      } while ((ret == GST_FLOW_OK) && (best != NULL));
-
-      GST_DEBUG_OBJECT (ogg_mux, "Pushing EOS");
-      gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ());
-    }
-  }
-
-  return ret;
-}
-
-static void
-gst_ogg_mux_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
-{
-  GstOggMux *ogg_mux;
-
-  ogg_mux = GST_OGG_MUX (object);
-
-  switch (prop_id) {
-    case ARG_MAX_DELAY:
-      g_value_set_uint64 (value, ogg_mux->max_delay);
-      break;
-    case ARG_MAX_PAGE_DELAY:
-      g_value_set_uint64 (value, ogg_mux->max_page_delay);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_ogg_mux_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-  GstOggMux *ogg_mux;
-
-  ogg_mux = GST_OGG_MUX (object);
-
-  switch (prop_id) {
-    case ARG_MAX_DELAY:
-      ogg_mux->max_delay = g_value_get_uint64 (value);
-      break;
-    case ARG_MAX_PAGE_DELAY:
-      ogg_mux->max_page_delay = g_value_get_uint64 (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-/* reset all variables in the ogg pads. */
-static void
-gst_ogg_mux_init_collectpads (GstCollectPads * collect)
-{
-  GSList *walk;
-
-  walk = collect->data;
-  while (walk) {
-    GstOggPad *oggpad = (GstOggPad *) walk->data;
-
-    ogg_stream_init (&oggpad->stream, oggpad->serial);
-    oggpad->packetno = 0;
-    oggpad->pageno = 0;
-    oggpad->eos = FALSE;
-    /* we assume there will be some control data first for this pad */
-    oggpad->state = GST_OGG_PAD_STATE_CONTROL;
-    oggpad->new_page = TRUE;
-    oggpad->first_delta = FALSE;
-    oggpad->prev_delta = FALSE;
-    oggpad->pagebuffers = g_queue_new ();
-
-    walk = g_slist_next (walk);
-  }
-}
-
-/* Clear all buffers from the collectpads object */
-static void
-gst_ogg_mux_clear_collectpads (GstCollectPads * collect)
-{
-  GSList *walk;
-
-  for (walk = collect->data; walk; walk = g_slist_next (walk)) {
-    GstOggPad *oggpad = (GstOggPad *) walk->data;
-    GstBuffer *buf;
-
-    ogg_stream_clear (&oggpad->stream);
-
-    while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) {
-      gst_buffer_unref (buf);
-    }
-    g_queue_free (oggpad->pagebuffers);
-    oggpad->pagebuffers = NULL;
-  }
-}
-
-static GstStateChangeReturn
-gst_ogg_mux_change_state (GstElement * element, GstStateChange transition)
-{
-  GstOggMux *ogg_mux;
-  GstStateChangeReturn ret;
-
-  ogg_mux = GST_OGG_MUX (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      gst_ogg_mux_clear (ogg_mux);
-      gst_ogg_mux_init_collectpads (ogg_mux->collect);
-      gst_collect_pads_start (ogg_mux->collect);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      gst_collect_pads_stop (ogg_mux->collect);
-      break;
-    default:
-      break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      gst_ogg_mux_clear_collectpads (ogg_mux->collect);
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-gboolean
-gst_ogg_mux_plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (gst_ogg_mux_debug, "oggmux", 0, "ogg muxer");
-
-  return gst_element_register (plugin, "oggmux", GST_RANK_NONE,
-      GST_TYPE_OGG_MUX);
-}
--- a/gst_plugins_base/ext/ogg/gstoggmux.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/* OGG muxer plugin for GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * 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_OGG_MUX_H__
-#define __GST_OGGEMUX_H__
-
-#include <ogg/ogg.h>
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_OGG_MUX (gst_ogg_mux_get_type())
-#define GST_OGG_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_MUX, GstOggMux))
-#define GST_OGG_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_MUX, GstOggMux))
-#define GST_IS_OGG_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_MUX))
-#define GST_IS_OGG_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_MUX))
-
-typedef struct _GstOggMux GstOggMux;
-typedef struct _GstOggMuxClass GstOggMuxClass;
-
-typedef enum
-{
-  GST_OGG_PAD_STATE_CONTROL = 0,
-  GST_OGG_PAD_STATE_DATA = 1
-}
-GstOggPadState;
-
-/* all information needed for one ogg stream */
-typedef struct
-{
-  GstCollectData collect;       /* we extend the CollectData */
-
-  /* These two buffers make a very simple queue - they enter as 'next_buffer'
-   * and (usually) leave as 'buffer', except at EOS, when buffer will be NULL */
-  GstBuffer *buffer;            /* the first waiting buffer for the pad */
-  GstBuffer *next_buffer;       /* the second waiting buffer for the pad */
-
-  gint serial;
-  ogg_stream_state stream;
-  gint64 packetno;              /* number of next packet */
-  gint64 pageno;                /* number of next page */
-  guint64 duration;             /* duration of current page */
-  gboolean eos;
-  gint64 offset;
-  GstClockTime timestamp;       /* timestamp of the first packet on the next
-                                 * page to be dequeued */
-  GstClockTime timestamp_end;   /* end timestamp of last complete packet on
-                                   the next page to be dequeued */
-  GstClockTime gp_time;         /* time corresponding to the gp value of the
-                                   last complete packet on the next page to be
-                                   dequeued */
-
-  GstOggPadState state;         /* state of the pad */
-
-  GList *headers;
-
-  GQueue *pagebuffers;          /* List of pages in buffers ready for pushing */
-
-  gboolean new_page;            /* starting a new page */
-  gboolean first_delta;         /* was the first packet in the page a delta */
-  gboolean prev_delta;          /* was the previous buffer a delta frame */
-}
-GstOggPad;
-
-struct _GstOggMux
-{
-  GstElement element;
-
-  /* source pad */
-  GstPad *srcpad;
-
-  /* sinkpads */
-  GstCollectPads *collect;
-
-  /* number of pads which have not received EOS */
-  gint active_pads;
-
-  /* the pad we are currently using to fill a page */
-  GstOggPad *pulling;
-
-  /* next timestamp for the page */
-  GstClockTime next_ts;
-
-  /* Last timestamp actually output on src pad */
-  GstClockTime last_ts;
-
-  /* offset in stream */
-  guint64 offset;
-
-  /* need_headers */
-  gboolean need_headers;
-
-  guint64 max_delay;
-  guint64 max_page_delay;
-
-  GstOggPad *delta_pad;         /* when a delta frame is detected on a stream, we mark
-                                   pages as delta frames up to the page that has the
-                                   keyframe */
-
-};
-
-struct _GstOggMuxClass
-{
-  GstElementClass parent_class;
-};
-
-GType gst_ogg_mux_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_OGG_MUX_H__ */
--- a/gst_plugins_base/ext/ogg/gstoggparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,695 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Michael Smith <msmith@fluendo.com>
- *
- * gstoggparse.c: ogg stream parser
- *
- * 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 ogg parser is essentially a subset of the ogg demuxer - rather than
- * fully demuxing into packets, we only parse out the pages, create one
- * GstBuffer per page, set all the appropriate flags on those pages, set caps
- * appropriately (particularly the 'streamheader' which gives all the header
- * pages required for initialing decode).
- *
- * It's dramatically simpler than the full demuxer as it does not  support 
- * seeking.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <gst/gst.h>
-#include <ogg/ogg.h>
-#include <string.h>
-
-static const GstElementDetails gst_ogg_parse_details =
-GST_ELEMENT_DETAILS ("Ogg parser",
-    "Codec/Parser",
-    "parse ogg streams into pages (info about ogg: http://xiph.org)",
-    "Michael Smith <msmith@fluendo.com>");
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_parse_debug);
-#define GST_CAT_DEFAULT gst_ogg_parse_debug
-
-#define GST_TYPE_OGG_PARSE (gst_ogg_parse_get_type())
-#define GST_OGG_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PARSE, GstOggParse))
-#define GST_OGG_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PARSE, GstOggParse))
-#define GST_IS_OGG_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_PARSE))
-#define GST_IS_OGG_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_PARSE))
-
-static GType gst_ogg_parse_get_type (void);
-
-typedef struct _GstOggParse GstOggParse;
-typedef struct _GstOggParseClass GstOggParseClass;
-
-/* Each ogg logical stream has a GstOggStream associated with it */
-typedef struct
-{
-  /*ogg_stream_state stream; *//* We need this to get the packets out in order
-     to do codec identification, for various
-     codec-specific tasks */
-
-  gboolean in_headers;          /* Initially true, false once we've read all the
-                                   headers for this logical stream */
-
-  guint32 serialno;             /* Unique serial number of this stream */
-
-  GSList *headers;              /* List of ogg pages that we'll set on caps */
-  GSList *unknown_pages;        /* List of pages we haven't yet classified */
-} GstOggStream;
-
-struct _GstOggParse
-{
-  GstElement element;
-
-  GstPad *sinkpad;              /* Sink pad we're reading data from */
-
-  GstPad *srcpad;               /* Source pad we're writing to */
-
-  GSList *oggstreams;           /* list of GstOggStreams for known streams */
-
-  gint64 offset;                /* Current stream offset */
-
-  gboolean in_headers;          /* Set if we're reading headers for streams */
-
-  gboolean last_page_not_bos;   /* Set if we've seen a non-BOS page */
-
-  ogg_sync_state sync;          /* Ogg page synchronisation */
-
-  GstCaps *caps;                /* Our src caps */
-};
-
-struct _GstOggParseClass
-{
-  GstElementClass parent_class;
-};
-
-static void gst_ogg_parse_base_init (gpointer g_class);
-static void gst_ogg_parse_class_init (GstOggParseClass * klass);
-static void gst_ogg_parse_init (GstOggParse * ogg);
-static GstElementClass *parent_class = NULL;
-
-static GType
-gst_ogg_parse_get_type (void)
-{
-  static GType ogg_parse_type = 0;
-
-  if (!ogg_parse_type) {
-    static const GTypeInfo ogg_parse_info = {
-      sizeof (GstOggParseClass),
-      gst_ogg_parse_base_init,
-      NULL,
-      (GClassInitFunc) gst_ogg_parse_class_init,
-      NULL,
-      NULL,
-      sizeof (GstOggParse),
-      0,
-      (GInstanceInitFunc) gst_ogg_parse_init,
-    };
-
-    ogg_parse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstOggParse",
-        &ogg_parse_info, 0);
-  }
-  return ogg_parse_type;
-}
-
-static void
-free_stream (GstOggStream * stream)
-{
-  g_slist_foreach (stream->headers, (GFunc) gst_mini_object_unref, NULL);
-  g_slist_foreach (stream->unknown_pages, (GFunc) gst_mini_object_unref, NULL);
-
-  g_free (stream);
-}
-
-static void
-gst_ogg_parse_delete_all_streams (GstOggParse * ogg)
-{
-  g_slist_foreach (ogg->oggstreams, (GFunc) free_stream, NULL);
-  g_slist_free (ogg->oggstreams);
-  ogg->oggstreams = NULL;
-}
-
-static GstOggStream *
-gst_ogg_parse_new_stream (GstOggParse * parser, guint32 serialno)
-{
-  GstOggStream *ret;
-
-  GST_DEBUG_OBJECT (parser, "creating new stream %08x", serialno);
-
-  ret = g_new0 (GstOggStream, 1);
-
-  ret->serialno = serialno;
-  ret->in_headers = 1;
-
-  /*
-     if (ogg_stream_init (&ret->stream, serialno) != 0) {
-     GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.",
-     serialno);
-     return NULL;
-     }
-   */
-
-  parser->oggstreams = g_slist_append (parser->oggstreams, ret);
-
-  return ret;
-}
-
-static GstOggStream *
-gst_ogg_parse_find_stream (GstOggParse * parser, guint32 serialno)
-{
-  GSList *l;
-
-  for (l = parser->oggstreams; l != NULL; l = l->next) {
-    GstOggStream *stream = (GstOggStream *) l->data;
-
-    if (stream->serialno == serialno)
-      return stream;
-  }
-  return NULL;
-}
-
-/* signals and args */
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0
-      /* FILL ME */
-};
-
-static GstStaticPadTemplate ogg_parse_src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/ogg")
-    );
-
-static GstStaticPadTemplate ogg_parse_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/ogg")
-    );
-
-static void gst_ogg_parse_dispose (GObject * object);
-static GstStateChangeReturn gst_ogg_parse_change_state (GstElement * element,
-    GstStateChange transition);
-static GstFlowReturn gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer);
-
-static void
-gst_ogg_parse_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_ogg_parse_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&ogg_parse_sink_template_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&ogg_parse_src_template_factory));
-}
-
-static void
-gst_ogg_parse_class_init (GstOggParseClass * klass)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gstelement_class->change_state = gst_ogg_parse_change_state;
-
-  gobject_class->dispose = gst_ogg_parse_dispose;
-}
-
-static void
-gst_ogg_parse_init (GstOggParse * ogg)
-{
-  /* create the sink and source pads */
-  ogg->sinkpad =
-      gst_pad_new_from_static_template (&ogg_parse_sink_template_factory,
-      "sink");
-  ogg->srcpad =
-      gst_pad_new_from_static_template (&ogg_parse_src_template_factory, "src");
-
-  /* TODO: Are there any events we must handle? */
-  /* gst_pad_set_event_function (ogg->sinkpad, gst_ogg_parse_handle_event); */
-  gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_parse_chain);
-
-  gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
-  gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad);
-
-  ogg->oggstreams = NULL;
-}
-
-static void
-gst_ogg_parse_dispose (GObject * object)
-{
-  GstOggParse *ogg = GST_OGG_PARSE (object);
-
-  GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg);
-
-  ogg_sync_clear (&ogg->sync);
-  gst_ogg_parse_delete_all_streams (ogg);
-
-  if (ogg->caps) {
-    gst_caps_unref (ogg->caps);
-    ogg->caps = NULL;
-  }
-
-  if (G_OBJECT_CLASS (parent_class)->dispose)
-    G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-/* submit the given buffer to the ogg sync.
- *
- * Returns the number of bytes submited.
- */
-static gint
-gst_ogg_parse_submit_buffer (GstOggParse * ogg, GstBuffer * buffer)
-{
-  guint size;
-  guint8 *data;
-  gchar *oggbuffer;
-
-  size = GST_BUFFER_SIZE (buffer);
-  data = GST_BUFFER_DATA (buffer);
-
-  /* We now have a buffer, submit it to the ogg sync layer */
-  oggbuffer = ogg_sync_buffer (&ogg->sync, size);
-  memcpy (oggbuffer, data, size);
-  ogg_sync_wrote (&ogg->sync, size);
-
-  /* We've copied all the neccesary data, so we're done with the buffer */
-  gst_buffer_unref (buffer);
-
-  return size;
-}
-
-static void
-gst_ogg_parse_append_header (GValue * array, GstBuffer * buf)
-{
-  GValue value = { 0 };
-  /* We require a copy to avoid circular refcounts */
-  GstBuffer *buffer = gst_buffer_copy (buf);
-
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
-
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buffer);
-  gst_value_array_append_value (array, &value);
-  g_value_unset (&value);
-
-}
-
-typedef enum
-{
-  PAGE_HEADER,                  /* Header page */
-  PAGE_DATA,                    /* Data page */
-  PAGE_PENDING,                 /* We don't know yet, we'll have to see some future pages */
-} page_type;
-
-static page_type
-gst_ogg_parse_is_header (GstOggParse * ogg, GstOggStream * stream,
-    ogg_page * page)
-{
-  ogg_int64_t gpos = ogg_page_granulepos (page);
-
-  if (gpos < 0)
-    return PAGE_PENDING;
-
-  /* This is good enough for now, but technically requires codec-specific
-   * behaviour to be perfect. This is where we need the mooted library for 
-   * this stuff, which nobody has written.
-   */
-  if (gpos > 0)
-    return PAGE_DATA;
-  else
-    return PAGE_HEADER;
-}
-
-static GstBuffer *
-gst_ogg_parse_buffer_from_page (ogg_page * page,
-    guint64 offset, gboolean delta, GstClockTime timestamp)
-{
-  int size = page->header_len + page->body_len;
-  GstBuffer *buf = gst_buffer_new_and_alloc (size);
-
-  memcpy (GST_BUFFER_DATA (buf), page->header, page->header_len);
-  memcpy (GST_BUFFER_DATA (buf) + page->header_len, page->body, page->body_len);
-
-  GST_BUFFER_TIMESTAMP (buf) = timestamp;
-  GST_BUFFER_OFFSET (buf) = offset;
-  GST_BUFFER_OFFSET_END (buf) = offset + size;
-
-  return buf;
-}
-
-
-/* Reads in buffers, parses them, reframes into one-buffer-per-ogg-page, submits
- * pages to output pad.
- */
-static GstFlowReturn
-gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstOggParse *ogg;
-  GstFlowReturn result = GST_FLOW_OK;
-  gint ret = -1;
-  guint32 serialno;
-  GstBuffer *pagebuffer;
-  GstClockTime buffertimestamp = GST_BUFFER_TIMESTAMP (buffer);
-
-  ogg = GST_OGG_PARSE (GST_OBJECT_PARENT (pad));
-
-  GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d",
-      GST_BUFFER_SIZE (buffer));
-
-  gst_ogg_parse_submit_buffer (ogg, buffer);
-
-  while (ret != 0 && result == GST_FLOW_OK) {
-    ogg_page page;
-
-    /* We use ogg_sync_pageseek() rather than ogg_sync_pageout() so that we can
-     * track how many bytes the ogg layer discarded (in the case of sync errors,
-     * etc.); this allows us to accurately track the current stream offset
-     */
-    ret = ogg_sync_pageseek (&ogg->sync, &page);
-    if (ret == 0) {
-      /* need more data, that's fine... */
-      break;
-    } else if (ret < 0) {
-      /* discontinuity; track how many bytes we skipped (-ret) */
-      ogg->offset -= ret;
-    } else {
-#ifndef GST_DISABLE_GST_DEBUG
-      gint64 granule = ogg_page_granulepos (&page);
-      int bos = ogg_page_bos (&page);
-#endif
-      guint64 startoffset = ogg->offset;
-
-      GST_LOG_OBJECT (ogg, "Timestamping outgoing buffer as %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (buffertimestamp));
-      /* Turn our page into a GstBuffer TODO: better timestamps? Requires format
-       * parsing. */
-      pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset, FALSE,
-          buffertimestamp);
-
-      /* We read out 'ret' bytes, so we set the next offset appropriately */
-      ogg->offset += ret;
-
-      serialno = ogg_page_serialno (&page);
-
-      GST_LOG_OBJECT (ogg,
-          "processing ogg page (serial %08x, pageno %ld, "
-          "granule pos %" G_GUINT64_FORMAT ", bos %d, offset %"
-          G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ")",
-          serialno, ogg_page_pageno (&page),
-          granule, bos, startoffset, ogg->offset);
-
-      if (ogg_page_bos (&page)) {
-        /* If we've seen this serialno before, this is technically an error,
-         * we log this case but accept it - this one replaces the previous
-         * stream with this serialno. We can do this since we're streaming, and
-         * not supporting seeking...
-         */
-        GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno);
-
-        if (stream != NULL) {
-          GST_LOG_OBJECT (ogg, "Incorrect stream; repeats serial number %u "
-              "at offset %lld", serialno, ogg->offset);
-        }
-
-        if (ogg->last_page_not_bos) {
-          GST_LOG_OBJECT (ogg, "Deleting all referenced streams, found a new "
-              "chain starting with serial %u", serialno);
-          gst_ogg_parse_delete_all_streams (ogg);
-        }
-
-        stream = gst_ogg_parse_new_stream (ogg, serialno);
-
-        ogg->last_page_not_bos = FALSE;
-
-        gst_buffer_ref (pagebuffer);
-        stream->headers = g_slist_append (stream->headers, pagebuffer);
-
-        if (!ogg->in_headers) {
-          GST_LOG_OBJECT (ogg, "Found start of new chain at offset %llu",
-              startoffset);
-          ogg->in_headers = 1;
-        }
-
-        /* For now, we just keep the header buffer in the stream->headers list;
-         * it actually gets output once we've collected the entire set
-         */
-      } else {
-        /* Non-BOS page. Either: we're outside headers, and this isn't a 
-         * header (normal data), outside headers and this is (error!), inside
-         * headers, this is (append header), or inside headers and this isn't 
-         * (we've found the end of headers; flush the lot!)
-         *
-         * Before that, we flag that the last page seen (this one) was not a 
-         * BOS page; that way we know that when we next see a BOS page it's a
-         * new chain, and we can flush all existing streams.
-         */
-        page_type type;
-        GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno);
-
-        if (!stream) {
-          GST_LOG_OBJECT (ogg, "Non-BOS page unexpectedly found at %lld",
-              ogg->offset);
-          goto failure;
-        }
-
-        ogg->last_page_not_bos = TRUE;
-
-        type = gst_ogg_parse_is_header (ogg, stream, &page);
-
-        if (type == PAGE_PENDING && ogg->in_headers) {
-          gst_buffer_ref (pagebuffer);
-
-          stream->unknown_pages = g_slist_append (stream->unknown_pages,
-              pagebuffer);
-        } else if (type == PAGE_HEADER) {
-          if (!ogg->in_headers) {
-            GST_LOG_OBJECT (ogg, "Header page unexpectedly found outside "
-                "headers at offset %lld", ogg->offset);
-            goto failure;
-          } else {
-            /* Append the header to the buffer list, after any unknown previous
-             * pages
-             */
-            stream->headers = g_slist_concat (stream->headers,
-                stream->unknown_pages);
-            g_slist_free (stream->unknown_pages);
-            gst_buffer_ref (pagebuffer);
-            stream->headers = g_slist_append (stream->headers, pagebuffer);
-          }
-        } else {                /* PAGE_DATA, or PAGE_PENDING but outside headers */
-          if (ogg->in_headers) {
-            /* First non-header page... set caps, flush headers.
-             *
-             * First up, we build a single GValue list of all the pagebuffers
-             * we're using for the headers, in order.
-             * Then we set this on the caps structure. Then we can start pushing
-             * buffers for the headers, and finally we send this non-header
-             * page.
-             */
-            GstCaps *caps;
-            GstStructure *structure;
-            GValue array = { 0 };
-            gint count = 0;
-            gboolean found_pending_headers = FALSE;
-            GSList *l;
-
-            g_value_init (&array, GST_TYPE_ARRAY);
-
-            for (l = ogg->oggstreams; l != NULL; l = l->next) {
-              GstOggStream *stream = (GstOggStream *) l->data;
-
-              if (g_slist_length (stream->headers) == 0) {
-                GST_LOG_OBJECT (ogg, "No primary header found for stream %u",
-                    stream->serialno);
-                goto failure;
-              }
-
-              gst_ogg_parse_append_header (&array,
-                  GST_BUFFER (stream->headers->data));
-              count++;
-            }
-
-            for (l = ogg->oggstreams; l != NULL; l = l->next) {
-              GstOggStream *stream = (GstOggStream *) l->data;
-              int j;
-
-              for (j = 1; j < g_slist_length (stream->headers); j++) {
-                gst_ogg_parse_append_header (&array,
-                    GST_BUFFER (g_slist_nth_data (stream->headers, j)));
-                count++;
-              }
-            }
-
-            caps = gst_pad_get_caps (ogg->srcpad);
-            caps = gst_caps_make_writable (caps);
-
-            structure = gst_caps_get_structure (caps, 0);
-            gst_structure_set_value (structure, "streamheader", &array);
-
-            gst_pad_set_caps (ogg->srcpad, caps);
-
-            g_value_unset (&array);
-
-            if (ogg->caps)
-              gst_caps_unref (ogg->caps);
-            ogg->caps = caps;
-
-            GST_LOG_OBJECT (ogg, "Set \"streamheader\" caps with %d buffers "
-                "(one per page)", count);
-
-            /* Now, we do the same thing, but push buffers... */
-            for (l = ogg->oggstreams; l != NULL; l = l->next) {
-              GstOggStream *stream = (GstOggStream *) l->data;
-              GstBuffer *buf = GST_BUFFER (stream->headers->data);
-
-              gst_buffer_set_caps (buf, caps);
-
-              result = gst_pad_push (ogg->srcpad, buf);
-              if (result != GST_FLOW_OK)
-                return result;
-            }
-            for (l = ogg->oggstreams; l != NULL; l = l->next) {
-              GstOggStream *stream = (GstOggStream *) l->data;
-              int j;
-
-              for (j = 1; j < g_slist_length (stream->headers); j++) {
-                GstBuffer *buf =
-                    GST_BUFFER (g_slist_nth_data (stream->headers, j));
-                gst_buffer_set_caps (buf, caps);
-
-                result = gst_pad_push (ogg->srcpad, buf);
-                if (result != GST_FLOW_OK)
-                  return result;
-              }
-            }
-
-            ogg->in_headers = 0;
-
-            /* And finally the pending data pages */
-            for (l = ogg->oggstreams; l != NULL; l = l->next) {
-              GstOggStream *stream = (GstOggStream *) l->data;
-              GSList *k;
-
-              if (stream->unknown_pages == NULL)
-                continue;
-
-              if (found_pending_headers) {
-                GST_WARNING_OBJECT (ogg, "Incorrectly muxed headers found at "
-                    "approximate offset %lld", ogg->offset);
-              }
-              found_pending_headers = TRUE;
-
-              GST_LOG_OBJECT (ogg, "Pushing %d pending pages after headers",
-                  g_slist_length (stream->unknown_pages) + 1);
-
-              for (k = stream->unknown_pages; k != NULL; k = k->next) {
-                GstBuffer *buf;
-
-                buf = GST_BUFFER (k->data);
-                gst_buffer_set_caps (buf, caps);
-                result = gst_pad_push (ogg->srcpad, buf);
-                if (result != GST_FLOW_OK)
-                  return result;
-              }
-              g_slist_foreach (stream->unknown_pages,
-                  (GFunc) gst_mini_object_unref, NULL);
-              g_slist_free (stream->unknown_pages);
-              stream->unknown_pages = NULL;
-            }
-
-            gst_buffer_set_caps (pagebuffer, caps);
-
-            result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
-            if (result != GST_FLOW_OK)
-              return result;
-          } else {
-            /* Normal data page, submit buffer */
-            gst_buffer_set_caps (pagebuffer, ogg->caps);
-            result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
-            if (result != GST_FLOW_OK)
-              return result;
-          }
-        }
-      }
-    }
-  }
-
-  return result;
-
-failure:
-  gst_pad_push_event (GST_PAD (ogg->srcpad), gst_event_new_eos ());
-  return GST_FLOW_ERROR;
-}
-
-static GstStateChangeReturn
-gst_ogg_parse_change_state (GstElement * element, GstStateChange transition)
-{
-  GstOggParse *ogg;
-  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
-
-  ogg = GST_OGG_PARSE (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      ogg_sync_init (&ogg->sync);
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      ogg_sync_reset (&ogg->sync);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  result = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      ogg_sync_clear (&ogg->sync);
-      break;
-    default:
-      break;
-  }
-  return result;
-}
-
-gboolean
-gst_ogg_parse_plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (gst_ogg_parse_debug, "oggparse", 0, "ogg parser");
-
-  return gst_element_register (plugin, "oggparse", GST_RANK_NONE,
-      GST_TYPE_OGG_PARSE);
-}
--- a/gst_plugins_base/ext/ogg/gstogmparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,956 +0,0 @@
-/* GStreamer OGM parsing
- * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include <gst/gst.h>
-#include <gst/tag/tag.h>
-#include <gst/riff/riff-media.h>
-#include <gst/riff/riff-read.h>
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogm_parse_debug);
-#define GST_CAT_DEFAULT gst_ogm_parse_debug
-
-#define GST_TYPE_OGM_VIDEO_PARSE (gst_ogm_video_parse_get_type())
-#define GST_IS_OGM_VIDEO_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_VIDEO_PARSE))
-
-#define GST_TYPE_OGM_AUDIO_PARSE (gst_ogm_audio_parse_get_type())
-#define GST_IS_OGM_AUDIO_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_AUDIO_PARSE))
-
-#define GST_TYPE_OGM_TEXT_PARSE (gst_ogm_text_parse_get_type())
-#define GST_IS_OGM_TEXT_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_TEXT_PARSE))
-
-#define GST_TYPE_OGM_PARSE (gst_ogm_parse_get_type())
-#define GST_OGM_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_OGM_PARSE, GstOgmParse))
-#define GST_OGM_PARSE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_OGM_PARSE, GstOgmParse))
-#define GST_IS_OGM_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_PARSE))
-#define GST_IS_OGM_PARSE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_OGM_PARSE))
-#define GST_OGM_PARSE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_OGM_PARSE, GstOgmParseClass))
-
-static const GstElementDetails gst_ogm_audio_parse_details =
-GST_ELEMENT_DETAILS ("OGM audio stream parser",
-    "Codec/Decoder/Audio",
-    "parse an OGM audio header and stream",
-    "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-static const GstElementDetails gst_ogm_video_parse_details =
-GST_ELEMENT_DETAILS ("OGM video stream parser",
-    "Codec/Decoder/Video",
-    "parse an OGM video header and stream",
-    "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-static const GstElementDetails gst_ogm_text_parse_details =
-GST_ELEMENT_DETAILS ("OGM text stream parser",
-    "Codec/Decoder/Subtitle",
-    "parse an OGM text header and stream",
-    "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-typedef struct _stream_header_video
-{
-  gint32 width;
-  gint32 height;
-} stream_header_video;
-
-typedef struct _stream_header_audio
-{
-  gint16 channels;
-  gint16 blockalign;
-  gint32 avgbytespersec;
-} stream_header_audio;
-
-/* sizeof(stream_header) might differ due to structure packing and
- * alignment differences on some architectures, so not using that */
-#define OGM_STREAM_HEADER_SIZE (8+4+4+8+8+4+4+4+8)
-
-typedef struct _stream_header
-{
-  gchar streamtype[8];
-  gchar subtype[4 + 1];
-
-  /* size of the structure */
-  gint32 size;
-
-  /* in reference time */
-  gint64 time_unit;
-
-  gint64 samples_per_unit;
-
-  /* in media time */
-  gint32 default_len;
-
-  gint32 buffersize;
-  gint32 bits_per_sample;
-
-  union
-  {
-    stream_header_video video;
-    stream_header_audio audio;
-    /* text has no additional data */
-  } s;
-} stream_header;
-
-typedef struct _GstOgmParse
-{
-  GstElement element;
-
-  /* pads */
-  GstPad *srcpad, *sinkpad;
-  GstPadTemplate *srcpadtempl;
-
-  /* we need to cache events that we receive before creating the source pad */
-  GList *cached_events;
-
-  /* audio or video */
-  stream_header hdr;
-
-  /* expected next granulepos (used for timestamp guessing) */
-  guint64 next_granulepos;
-} GstOgmParse;
-
-typedef struct _GstOgmParseClass
-{
-  GstElementClass parent_class;
-} GstOgmParseClass;
-
-static GstStaticPadTemplate sink_factory_video =
-GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-ogm-video"));
-static GstStaticPadTemplate sink_factory_audio =
-GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-ogm-audio"));
-static GstStaticPadTemplate sink_factory_text =
-GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-ogm-text"));
-static GstPadTemplate *video_src_templ, *audio_src_templ, *text_src_templ;
-
-static GType gst_ogm_audio_parse_get_type (void);
-static GType gst_ogm_video_parse_get_type (void);
-static GType gst_ogm_text_parse_get_type (void);
-static GType gst_ogm_parse_get_type (void);
-
-static void gst_ogm_audio_parse_base_init (GstOgmParseClass * klass);
-static void gst_ogm_video_parse_base_init (GstOgmParseClass * klass);
-static void gst_ogm_text_parse_base_init (GstOgmParseClass * klass);
-static void gst_ogm_parse_class_init (GstOgmParseClass * klass);
-static void gst_ogm_parse_init (GstOgmParse * ogm);
-static void gst_ogm_video_parse_init (GstOgmParse * ogm);
-static void gst_ogm_audio_parse_init (GstOgmParse * ogm);
-static void gst_ogm_text_parse_init (GstOgmParse * ogm);
-
-static const GstQueryType *gst_ogm_parse_get_sink_querytypes (GstPad * pad);
-static gboolean gst_ogm_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_ogm_parse_sink_query (GstPad * pad, GstQuery * query);
-static gboolean gst_ogm_parse_sink_convert (GstPad * pad, GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-
-static GstFlowReturn gst_ogm_parse_chain (GstPad * pad, GstBuffer * buffer);
-
-static GstStateChangeReturn gst_ogm_parse_change_state (GstElement * element,
-    GstStateChange transition);
-
-static GstElementClass *parent_class = NULL;
-
-static GType
-gst_ogm_parse_get_type (void)
-{
-  static GType ogm_parse_type = 0;
-
-  if (!ogm_parse_type) {
-    static const GTypeInfo ogm_parse_info = {
-      sizeof (GstOgmParseClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_ogm_parse_class_init,
-      NULL,
-      NULL,
-      sizeof (GstOgmParse),
-      0,
-      (GInstanceInitFunc) gst_ogm_parse_init,
-    };
-
-    ogm_parse_type =
-        g_type_register_static (GST_TYPE_ELEMENT,
-        "GstOgmParse", &ogm_parse_info, 0);
-  }
-
-  return ogm_parse_type;
-}
-
-static GType
-gst_ogm_audio_parse_get_type (void)
-{
-  static GType ogm_audio_parse_type = 0;
-
-  if (!ogm_audio_parse_type) {
-    static const GTypeInfo ogm_audio_parse_info = {
-      sizeof (GstOgmParseClass),
-      (GBaseInitFunc) gst_ogm_audio_parse_base_init,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      sizeof (GstOgmParse),
-      0,
-      (GInstanceInitFunc) gst_ogm_audio_parse_init,
-    };
-
-    ogm_audio_parse_type =
-        g_type_register_static (GST_TYPE_OGM_PARSE,
-        "GstOgmAudioParse", &ogm_audio_parse_info, 0);
-  }
-
-  return ogm_audio_parse_type;
-}
-
-static GType
-gst_ogm_video_parse_get_type (void)
-{
-  static GType ogm_video_parse_type = 0;
-
-  if (!ogm_video_parse_type) {
-    static const GTypeInfo ogm_video_parse_info = {
-      sizeof (GstOgmParseClass),
-      (GBaseInitFunc) gst_ogm_video_parse_base_init,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      sizeof (GstOgmParse),
-      0,
-      (GInstanceInitFunc) gst_ogm_video_parse_init,
-    };
-
-    ogm_video_parse_type =
-        g_type_register_static (GST_TYPE_OGM_PARSE,
-        "GstOgmVideoParse", &ogm_video_parse_info, 0);
-  }
-
-  return ogm_video_parse_type;
-}
-
-static GType
-gst_ogm_text_parse_get_type (void)
-{
-  static GType ogm_text_parse_type = 0;
-
-  if (!ogm_text_parse_type) {
-    static const GTypeInfo ogm_text_parse_info = {
-      sizeof (GstOgmParseClass),
-      (GBaseInitFunc) gst_ogm_text_parse_base_init,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      sizeof (GstOgmParse),
-      0,
-      (GInstanceInitFunc) gst_ogm_text_parse_init,
-    };
-
-    ogm_text_parse_type =
-        g_type_register_static (GST_TYPE_OGM_PARSE,
-        "GstOgmTextParse", &ogm_text_parse_info, 0);
-  }
-
-  return ogm_text_parse_type;
-}
-
-static void
-gst_ogm_audio_parse_base_init (GstOgmParseClass * klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *caps = gst_riff_create_audio_template_caps ();
-
-  gst_element_class_set_details (element_class, &gst_ogm_audio_parse_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory_audio));
-  audio_src_templ = gst_pad_template_new ("src",
-      GST_PAD_SRC, GST_PAD_SOMETIMES, caps);
-  gst_element_class_add_pad_template (element_class, audio_src_templ);
-}
-
-static void
-gst_ogm_video_parse_base_init (GstOgmParseClass * klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *caps = gst_riff_create_video_template_caps ();
-
-  gst_element_class_set_details (element_class, &gst_ogm_video_parse_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory_video));
-  video_src_templ = gst_pad_template_new ("src",
-      GST_PAD_SRC, GST_PAD_SOMETIMES, caps);
-  gst_element_class_add_pad_template (element_class, video_src_templ);
-}
-
-static void
-gst_ogm_text_parse_base_init (GstOgmParseClass * klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *caps = gst_caps_new_simple ("text/plain", NULL, NULL);
-
-  gst_element_class_set_details (element_class, &gst_ogm_text_parse_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory_text));
-  text_src_templ = gst_pad_template_new ("src",
-      GST_PAD_SRC, GST_PAD_SOMETIMES, caps);
-  gst_element_class_add_pad_template (element_class, text_src_templ);
-}
-
-static void
-gst_ogm_parse_class_init (GstOgmParseClass * klass)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gstelement_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_change_state);
-}
-
-static void
-gst_ogm_parse_init (GstOgmParse * ogm)
-{
-  memset (&ogm->hdr, 0, sizeof (ogm->hdr));
-  ogm->next_granulepos = 0;
-  ogm->srcpad = NULL;
-  ogm->cached_events = NULL;
-}
-
-static void
-gst_ogm_audio_parse_init (GstOgmParse * ogm)
-{
-  ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_audio, "sink");
-  gst_pad_set_query_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query));
-  gst_pad_set_chain_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_chain));
-  gst_pad_set_event_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event));
-  gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad);
-
-  ogm->srcpad = NULL;
-  ogm->srcpadtempl = audio_src_templ;
-}
-
-static void
-gst_ogm_video_parse_init (GstOgmParse * ogm)
-{
-  ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_video, "sink");
-  gst_pad_set_query_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query));
-  gst_pad_set_chain_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_chain));
-  gst_pad_set_event_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event));
-  gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad);
-
-  ogm->srcpad = NULL;
-  ogm->srcpadtempl = video_src_templ;
-}
-
-static void
-gst_ogm_text_parse_init (GstOgmParse * ogm)
-{
-  ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_text, "sink");
-  gst_pad_set_query_type_function (ogm->sinkpad,
-      gst_ogm_parse_get_sink_querytypes);
-  gst_pad_set_query_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query));
-  gst_pad_set_chain_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_chain));
-  gst_pad_set_event_function (ogm->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event));
-  gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad);
-
-  ogm->srcpad = NULL;
-  ogm->srcpadtempl = text_src_templ;
-}
-
-static const GstQueryType *
-gst_ogm_parse_get_sink_querytypes (GstPad * pad)
-{
-  static const GstQueryType types[] = {
-    GST_QUERY_POSITION,
-    0
-  };
-
-  return types;
-}
-
-static gboolean
-gst_ogm_parse_sink_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = FALSE;
-  GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad));
-
-  switch (src_format) {
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          switch (ogm->hdr.streamtype[0]) {
-            case 'a':
-              *dest_value = GST_SECOND * src_value / ogm->hdr.samples_per_unit;
-              res = TRUE;
-              break;
-            case 'v':
-            case 't':
-              *dest_value = (GST_SECOND / 10000000) *
-                  ogm->hdr.time_unit * src_value;
-              res = TRUE;
-              break;
-            default:
-              break;
-          }
-          break;
-        default:
-          break;
-      }
-      break;
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          switch (ogm->hdr.streamtype[0]) {
-            case 'a':
-              *dest_value = ogm->hdr.samples_per_unit * src_value / GST_SECOND;
-              res = TRUE;
-              break;
-            case 'v':
-            case 't':
-              *dest_value = src_value /
-                  ((GST_SECOND / 10000000) * ogm->hdr.time_unit);
-              res = TRUE;
-              break;
-            default:
-              break;
-          }
-          break;
-        default:
-          break;
-      }
-      break;
-    default:
-      break;
-  }
-
-  gst_object_unref (ogm);
-  return res;
-}
-
-static gboolean
-gst_ogm_parse_sink_query (GstPad * pad, GstQuery * query)
-{
-  GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad));
-  GstFormat format;
-  gboolean res = FALSE;
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    {
-      gint64 val;
-
-      gst_query_parse_position (query, &format, NULL);
-
-      if (format != GST_FORMAT_DEFAULT && format != GST_FORMAT_TIME)
-        break;
-
-      if ((res = gst_ogm_parse_sink_convert (pad,
-                  GST_FORMAT_DEFAULT, ogm->next_granulepos, &format, &val))) {
-        /* don't know the total length here.. */
-        gst_query_set_position (query, format, val);
-      }
-      break;
-    }
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      /* peel off input */
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if ((res = gst_ogm_parse_sink_convert (pad, src_fmt, src_val,
-                  &dest_fmt, &dest_val))) {
-        gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      }
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-
-  gst_object_unref (ogm);
-  return res;
-}
-
-static GstFlowReturn
-gst_ogm_parse_stream_header (GstOgmParse * ogm, const guint8 * data, guint size)
-{
-  GstCaps *caps = NULL;
-
-  /* stream header */
-  if (size < OGM_STREAM_HEADER_SIZE)
-    goto buffer_too_small;
-
-  if (!memcmp (data, "video\000\000\000", 8)) {
-    ogm->hdr.s.video.width = GST_READ_UINT32_LE (&data[44]);
-    ogm->hdr.s.video.height = GST_READ_UINT32_LE (&data[48]);
-  } else if (!memcmp (data, "audio\000\000\000", 8)) {
-    ogm->hdr.s.audio.channels = GST_READ_UINT32_LE (&data[44]);
-    ogm->hdr.s.audio.blockalign = GST_READ_UINT32_LE (&data[46]);
-    ogm->hdr.s.audio.avgbytespersec = GST_READ_UINT32_LE (&data[48]);
-  } else if (!memcmp (data, "text\000\000\000\000", 8)) {
-    /* nothing here */
-  } else {
-    goto cannot_decode;
-  }
-  memcpy (ogm->hdr.streamtype, &data[0], 8);
-  memcpy (ogm->hdr.subtype, &data[8], 4);
-  ogm->hdr.subtype[4] = '\0';
-  ogm->hdr.size = GST_READ_UINT32_LE (&data[12]);
-  ogm->hdr.time_unit = GST_READ_UINT64_LE (&data[16]);
-  ogm->hdr.samples_per_unit = GST_READ_UINT64_LE (&data[24]);
-  ogm->hdr.default_len = GST_READ_UINT32_LE (&data[32]);
-  ogm->hdr.buffersize = GST_READ_UINT32_LE (&data[36]);
-  ogm->hdr.bits_per_sample = GST_READ_UINT32_LE (&data[40]);
-
-  switch (ogm->hdr.streamtype[0]) {
-    case 'a':{
-      guint codec_id = 0;
-
-      if (sscanf (ogm->hdr.subtype, "%04x", &codec_id) != 1) {
-        GST_WARNING_OBJECT (ogm, "cannot parse subtype %s", ogm->hdr.subtype);
-      }
-
-      caps =
-          gst_riff_create_audio_caps (codec_id, NULL, NULL, NULL, NULL, NULL);
-
-      if (caps == NULL) {
-        GST_WARNING_OBJECT (ogm, "no audio caps for codec %u found", codec_id);
-        caps = gst_caps_new_simple ("audio/x-ogm-unknown", "codec_id",
-            G_TYPE_INT, (gint) codec_id, NULL);
-      }
-
-      gst_caps_set_simple (caps,
-          "channels", G_TYPE_INT, ogm->hdr.s.audio.channels,
-          "rate", G_TYPE_INT, ogm->hdr.samples_per_unit, NULL);
-
-      GST_LOG_OBJECT (ogm, "Type: %s, subtype: 0x%04x, channels: %d, "
-          "samplerate: %d, blockalign: %d, bps: %d, caps = %" GST_PTR_FORMAT,
-          ogm->hdr.streamtype, codec_id, ogm->hdr.s.audio.channels,
-          (gint) ogm->hdr.samples_per_unit, ogm->hdr.s.audio.blockalign,
-          ogm->hdr.s.audio.avgbytespersec, caps);
-      break;
-    }
-    case 'v':{
-      guint32 fourcc;
-
-      fourcc = GST_MAKE_FOURCC (ogm->hdr.subtype[0],
-          ogm->hdr.subtype[1], ogm->hdr.subtype[2], ogm->hdr.subtype[3]);
-
-      caps = gst_riff_create_video_caps (fourcc, NULL, NULL, NULL, NULL, NULL);
-
-      if (caps == NULL) {
-        GST_WARNING_OBJECT (ogm, "could not find video caps for fourcc %"
-            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-        caps = gst_caps_new_simple ("video/x-ogm-unknown", "fourcc",
-            GST_TYPE_FOURCC, fourcc, NULL);
-        break;
-      }
-
-      GST_LOG_OBJECT (ogm, "Type: %s, subtype: %" GST_FOURCC_FORMAT
-          ", size: %dx%d, timeunit: %" G_GINT64_FORMAT
-          " (fps: %lf), s/u: %" G_GINT64_FORMAT ", "
-          "def.len: %d, bufsize: %d, bps: %d, caps = %" GST_PTR_FORMAT,
-          ogm->hdr.streamtype, GST_FOURCC_ARGS (fourcc),
-          ogm->hdr.s.video.width, ogm->hdr.s.video.height,
-          ogm->hdr.time_unit, 10000000. / ogm->hdr.time_unit,
-          ogm->hdr.samples_per_unit, ogm->hdr.default_len,
-          ogm->hdr.buffersize, ogm->hdr.bits_per_sample, caps);
-
-      gst_caps_set_simple (caps,
-          "width", G_TYPE_INT, ogm->hdr.s.video.width,
-          "height", G_TYPE_INT, ogm->hdr.s.video.height,
-          "framerate", GST_TYPE_FRACTION, 10000000, ogm->hdr.time_unit, NULL);
-      break;
-    }
-    case 't':{
-      GST_LOG_OBJECT (ogm, "Type: %s, s/u: %" G_GINT64_FORMAT
-          ", timeunit=%" G_GINT64_FORMAT,
-          ogm->hdr.streamtype, ogm->hdr.samples_per_unit, ogm->hdr.time_unit);
-      caps = gst_caps_new_simple ("text/plain", NULL);
-      break;
-    }
-    default:
-      g_assert_not_reached ();
-  }
-
-  if (caps == NULL)
-    goto cannot_decode;
-
-  if (ogm->srcpad) {
-    GstCaps *current_caps = GST_PAD_CAPS (ogm->srcpad);
-
-    if (current_caps && caps && !gst_caps_is_equal (current_caps, caps)) {
-      GST_WARNING_OBJECT (ogm, "Already an existing pad %s:%s",
-          GST_DEBUG_PAD_NAME (ogm->srcpad));
-      gst_pad_set_active (ogm->srcpad, FALSE);
-      gst_element_remove_pad (GST_ELEMENT (ogm), ogm->srcpad);
-      ogm->srcpad = NULL;
-    } else {
-      GST_DEBUG_OBJECT (ogm, "Existing pad has the same caps, do nothing");
-    }
-  }
-
-  if (ogm->srcpad == NULL) {
-    GList *l, *cached_events;
-
-    ogm->srcpad = gst_pad_new_from_template (ogm->srcpadtempl, "src");
-    gst_pad_use_fixed_caps (ogm->srcpad);
-    gst_pad_set_caps (ogm->srcpad, caps);
-    gst_pad_set_active (ogm->srcpad, TRUE);
-    gst_element_add_pad (GST_ELEMENT (ogm), ogm->srcpad);
-    GST_INFO_OBJECT (ogm, "Added pad %s:%s with caps %" GST_PTR_FORMAT,
-        GST_DEBUG_PAD_NAME (ogm->srcpad), caps);
-
-    GST_OBJECT_LOCK (ogm);
-    cached_events = ogm->cached_events;
-    ogm->cached_events = NULL;
-    GST_OBJECT_UNLOCK (ogm);
-
-    for (l = cached_events; l; l = l->next) {
-      GstEvent *event = GST_EVENT_CAST (l->data);
-
-      GST_DEBUG_OBJECT (ogm, "Pushing cached event %" GST_PTR_FORMAT, event);
-      gst_pad_push_event (ogm->srcpad, event);
-    }
-    g_list_free (cached_events);
-  }
-
-  gst_caps_unref (caps);
-
-  return GST_FLOW_OK;
-
-/* ERRORS */
-buffer_too_small:
-  {
-    GST_ELEMENT_ERROR (ogm, STREAM, WRONG_TYPE, ("Buffer too small"), (NULL));
-    return GST_FLOW_ERROR;
-  }
-cannot_decode:
-  {
-    GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), ("unknown ogm format"));
-    return GST_FLOW_ERROR;
-  }
-}
-
-static GstFlowReturn
-gst_ogm_parse_comment_packet (GstOgmParse * ogm, GstBuffer * buf)
-{
-  GstFlowReturn ret;
-
-  if (ogm->srcpad == NULL) {
-    GST_DEBUG ("no source pad");
-    return GST_FLOW_WRONG_STATE;
-  }
-
-  /* if this is not a subtitle stream, push the vorbiscomment packet
-   * on downstream, the respective decoder will handle it; if it is
-   * a subtitle stream, we will have to handle the comment ourself */
-  if (ogm->hdr.streamtype[0] == 't') {
-    GstTagList *tags;
-
-    tags = gst_tag_list_from_vorbiscomment_buffer (buf,
-        (guint8 *) "\003vorbis", 7, NULL);
-
-    if (tags) {
-      GST_DEBUG_OBJECT (ogm, "tags = %" GST_PTR_FORMAT, tags);
-      gst_element_found_tags_for_pad (GST_ELEMENT (ogm), ogm->srcpad, tags);
-    } else {
-      GST_DEBUG_OBJECT (ogm, "failed to extract tags from vorbis comment");
-    }
-    /* do not push packet downstream, just let parent unref it */
-    ret = GST_FLOW_OK;
-  } else {
-    buf = gst_buffer_copy (buf);
-    gst_buffer_set_caps (buf, GST_PAD_CAPS (ogm->srcpad));
-    ret = gst_pad_push (ogm->srcpad, buf);
-  }
-
-  return ret;
-}
-
-static void
-gst_ogm_text_parse_strip_trailing_zeroes (GstOgmParse * ogm, GstBuffer * buf)
-{
-  const guint8 *data;
-  guint size;
-
-  g_assert (gst_buffer_is_metadata_writable (buf));
-
-  /* zeroes are not valid UTF-8 characters, so strip them from output */
-  data = GST_BUFFER_DATA (buf);
-  size = GST_BUFFER_SIZE (buf);
-  while (size > 0 && data[size - 1] == '\0') {
-    --size;
-  }
-
-  GST_BUFFER_SIZE (buf) = size;
-}
-
-static GstFlowReturn
-gst_ogm_parse_data_packet (GstOgmParse * ogm, GstBuffer * buf)
-{
-  GstFlowReturn ret;
-  const guint8 *data;
-  GstBuffer *sbuf;
-  gboolean keyframe;
-  guint size, len, n, xsize = 0;
-
-  data = GST_BUFFER_DATA (buf);
-  size = GST_BUFFER_SIZE (buf);
-
-  if ((data[0] & 0x01) != 0)
-    goto invalid_startcode;
-
-  /* data - push on */
-  len = ((data[0] & 0xc0) >> 6) | ((data[0] & 0x02) << 1);
-  keyframe = (((data[0] & 0x08) >> 3) != 0);
-
-  if ((1 + len) > size)
-    goto buffer_too_small;
-
-  for (n = len; n > 0; n--) {
-    xsize = (xsize << 8) | data[n];
-  }
-
-  GST_LOG_OBJECT (ogm, "[0x%02x] samples: %d, hdrbytes: %d, datasize: %d",
-      data[0], xsize, len, size - len - 1);
-
-  sbuf = gst_buffer_create_sub (buf, len + 1, size - len - 1);
-
-  if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
-    ogm->next_granulepos = GST_BUFFER_OFFSET_END (buf);
-
-  switch (ogm->hdr.streamtype[0]) {
-    case 't':
-    case 'v':{
-      GstClockTime ts, next_ts;
-      guint samples;
-
-      samples = (ogm->hdr.streamtype[0] == 'v') ? 1 : xsize;
-
-      if (!keyframe) {
-        GST_BUFFER_FLAG_SET (sbuf, GST_BUFFER_FLAG_DELTA_UNIT);
-      }
-
-      /* shouldn't this be granulepos - samples? (tpm) */
-      ts = gst_util_uint64_scale (ogm->next_granulepos,
-          ogm->hdr.time_unit * GST_SECOND, 10000000);
-      next_ts = gst_util_uint64_scale (ogm->next_granulepos + samples,
-          ogm->hdr.time_unit * GST_SECOND, 10000000);
-
-      GST_BUFFER_TIMESTAMP (sbuf) = ts;
-      GST_BUFFER_DURATION (sbuf) = next_ts - ts;
-
-      ogm->next_granulepos += samples;
-
-      if (ogm->hdr.streamtype[0] == 't') {
-        gst_ogm_text_parse_strip_trailing_zeroes (ogm, sbuf);
-      }
-      break;
-    }
-    case 'a':{
-      GstClockTime ts, next_ts;
-
-      /* shouldn't this be granulepos - samples? (tpm) */
-      ts = gst_util_uint64_scale_int (ogm->next_granulepos,
-          GST_SECOND, ogm->hdr.samples_per_unit);
-      next_ts = gst_util_uint64_scale_int (ogm->next_granulepos + xsize,
-          GST_SECOND, ogm->hdr.samples_per_unit);
-
-      GST_BUFFER_TIMESTAMP (sbuf) = ts;
-      GST_BUFFER_DURATION (sbuf) = next_ts - ts;
-
-      ogm->next_granulepos += xsize;
-      break;
-    }
-    default:
-      g_assert_not_reached ();
-      break;
-  }
-
-  if (ogm->srcpad) {
-    gst_buffer_set_caps (sbuf, GST_PAD_CAPS (ogm->srcpad));
-    GST_LOG_OBJECT (ogm, "Pushing buffer with ts=%" GST_TIME_FORMAT,
-        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sbuf)));
-    ret = gst_pad_push (ogm->srcpad, sbuf);
-    if (ret != GST_FLOW_OK) {
-      GST_DEBUG_OBJECT (ogm, "Flow on %s:%s = %s",
-          GST_DEBUG_PAD_NAME (ogm->srcpad), gst_flow_get_name (ret));
-    }
-  } else {
-    ret = GST_FLOW_WRONG_STATE;
-  }
-
-  return ret;
-
-/* ERRORS */
-invalid_startcode:
-  {
-    GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL),
-        ("unexpected packet startcode 0x%02x", data[0]));
-    return GST_FLOW_ERROR;
-  }
-buffer_too_small:
-  {
-    GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL),
-        ("buffer too small, len+1=%u, size=%u", len + 1, size));
-    return GST_FLOW_ERROR;
-  }
-}
-
-static GstFlowReturn
-gst_ogm_parse_chain (GstPad * pad, GstBuffer * buf)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstOgmParse *ogm = GST_OGM_PARSE (GST_PAD_PARENT (pad));
-  guint8 *data = GST_BUFFER_DATA (buf);
-  guint size = GST_BUFFER_SIZE (buf);
-
-  if (size < 1)
-    goto buffer_too_small;
-
-  GST_LOG_OBJECT (ogm, "Packet with start code 0x%02x", data[0]);
-
-  switch (data[0]) {
-    case 0x01:{
-      ret = gst_ogm_parse_stream_header (ogm, data + 1, size - 1);
-      break;
-    }
-    case 0x03:{
-      ret = gst_ogm_parse_comment_packet (ogm, buf);
-      break;
-    }
-    default:{
-      ret = gst_ogm_parse_data_packet (ogm, buf);
-      break;
-    }
-  }
-
-  gst_buffer_unref (buf);
-
-  if (ret != GST_FLOW_OK) {
-    GST_DEBUG_OBJECT (ogm, "Flow: %s", gst_flow_get_name (ret));
-  }
-
-  return ret;
-
-/* ERRORS */
-buffer_too_small:
-  {
-    GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), ("buffer too small"));
-    gst_buffer_unref (buf);
-    return GST_FLOW_ERROR;
-  }
-}
-
-static gboolean
-gst_ogm_parse_sink_event (GstPad * pad, GstEvent * event)
-{
-  GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad));
-  gboolean res;
-
-  GST_LOG_OBJECT (ogm, "processing %s event", GST_EVENT_TYPE_NAME (event));
-
-  GST_OBJECT_LOCK (ogm);
-  if (ogm->srcpad == NULL) {
-    ogm->cached_events = g_list_append (ogm->cached_events, event);
-    GST_OBJECT_UNLOCK (ogm);
-    res = TRUE;
-  } else {
-    GST_OBJECT_UNLOCK (ogm);
-    res = gst_pad_event_default (pad, event);
-  }
-
-  gst_object_unref (ogm);
-  return res;
-}
-
-static GstStateChangeReturn
-gst_ogm_parse_change_state (GstElement * element, GstStateChange transition)
-{
-  GstStateChangeReturn ret;
-  GstOgmParse *ogm = GST_OGM_PARSE (element);
-
-  ret = parent_class->change_state (element, transition);
-  if (ret != GST_STATE_CHANGE_SUCCESS)
-    return ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      if (ogm->srcpad) {
-        gst_pad_set_active (ogm->srcpad, FALSE);
-        gst_element_remove_pad (element, ogm->srcpad);
-        ogm->srcpad = NULL;
-      }
-      memset (&ogm->hdr, 0, sizeof (ogm->hdr));
-      ogm->next_granulepos = 0;
-      g_list_foreach (ogm->cached_events, (GFunc) gst_mini_object_unref, NULL);
-      g_list_free (ogm->cached_events);
-      ogm->cached_events = NULL;
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-gboolean
-gst_ogm_parse_plugin_init (GstPlugin * plugin)
-{
-  gst_riff_init ();
-
-  GST_DEBUG_CATEGORY_INIT (gst_ogm_parse_debug, "ogmparse", 0, "ogm parser");
-
-  return gst_element_register (plugin, "ogmaudioparse", GST_RANK_PRIMARY,
-      GST_TYPE_OGM_AUDIO_PARSE) &&
-      gst_element_register (plugin, "ogmvideoparse", GST_RANK_PRIMARY,
-      GST_TYPE_OGM_VIDEO_PARSE) &&
-      gst_element_register (plugin, "ogmtextparse", GST_RANK_PRIMARY,
-      GST_TYPE_OGM_TEXT_PARSE);
-}
--- a/gst_plugins_base/ext/pango/gstclockoverlay.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> Tim-Philipp Müller <tim@centricular.net>
- *
- * 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.
- */
-
-/**
- * SECTION:element-clockoverlay
- * @see_also: #GstTextOverlay, #GstTimeOverlay
- *
- * <refsect2>
- * <para>
- * This element overlays the current clock time on top of a video
- * stream. You can position the text and configure the font details
- * using the properties of the #GstTextOverlay class. By default, the
- * time is displayed in the top left corner of the picture, with some
- * padding to the left and to the top.
- * </para>
- * <para>
- * Here is a simple pipeline that displays the current time in the top left
- * corner of the video picture:
- * <programlisting>
- * gst-launch -v videotestsrc ! clockoverlay ! xvimagesink
- * </programlisting>
- * </para>
- * <para>
- * Here is another pipeline that displays the current time with some leading
- * text in the bottom right corner of the video picture, with the background
- * of the text being shaded in order to make it more legible on top of a
- * bright video background:
- * <programlisting>
- * gst-launch -v videotestsrc ! clockoverlay halign=right valign=bottom text="Edge City" shaded-background=true ! ffmpegcolorspace ! ximagesink
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gstclockoverlay.h>
-#include <gst/video/video.h>
-#include <time.h>
-
-static const GstElementDetails clock_overlay_details =
-GST_ELEMENT_DETAILS ("Clock overlay",
-    "Filter/Editor/Video",
-    "Overlays the current clock time on a video stream",
-    "Tim-Philipp Müller <tim@centricular.net>");
-
-GST_BOILERPLATE (GstClockOverlay, gst_clock_overlay, GstTextOverlay,
-    GST_TYPE_TEXT_OVERLAY)
-
-     static void gst_clock_overlay_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &clock_overlay_details);
-}
-
-static gchar *
-gst_clock_overlay_render_time (GstClockOverlay * overlay)
-{
-  struct tm *t;
-  time_t now;
-
-#ifdef HAVE_LOCALTIME_R
-  struct tm dummy;
-#endif
-
-  now = time (NULL);
-
-#ifdef HAVE_LOCALTIME_R
-  t = localtime_r (&now, &dummy);
-#else
-  /* on win32 this apparently returns a per-thread struct which would be fine */
-  t = localtime (&now);
-#endif
-
-  if (t == NULL)
-    return g_strdup ("--:--:--");
-
-  return g_strdup_printf ("%02u:%02u:%02u", t->tm_hour, t->tm_min, t->tm_sec);
-}
-
-/* Called with lock held */
-static gchar *
-gst_clock_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
-  gchar *time_str, *txt, *ret;
-
-  overlay->need_render = TRUE;
-
-  txt = g_strdup (overlay->default_text);
-
-  time_str = gst_clock_overlay_render_time (GST_CLOCK_OVERLAY (overlay));
-  if (txt != NULL && *txt != '\0') {
-    ret = g_strdup_printf ("%s %s", txt, time_str);
-  } else {
-    ret = time_str;
-    time_str = NULL;
-  }
-
-  g_free (txt);
-  g_free (time_str);
-
-  return ret;
-}
-
-static void
-gst_clock_overlay_class_init (GstClockOverlayClass * klass)
-{
-  GstTextOverlayClass *gsttextoverlay_class;
-
-  gsttextoverlay_class = (GstTextOverlayClass *) klass;
-
-  gsttextoverlay_class->get_text = gst_clock_overlay_get_text;
-}
-
-static void
-gst_clock_overlay_init (GstClockOverlay * overlay, GstClockOverlayClass * klass)
-{
-  PangoFontDescription *font_description;
-  GstTextOverlay *textoverlay;
-  PangoContext *context;
-
-  textoverlay = GST_TEXT_OVERLAY (overlay);
-
-  context = GST_TEXT_OVERLAY_CLASS (klass)->pango_context;
-
-  pango_context_set_language (context, pango_language_from_string ("en_US"));
-  pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
-
-  font_description = pango_font_description_new ();
-  pango_font_description_set_family_static (font_description, "Monospace");
-  pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL);
-  pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL);
-  pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL);
-  pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL);
-  pango_font_description_set_size (font_description, 18 * PANGO_SCALE);
-  pango_context_set_font_description (context, font_description);
-  pango_font_description_free (font_description);
-
-  textoverlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP;
-  textoverlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT;
-}
--- a/gst_plugins_base/ext/pango/gstclockoverlay.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> Tim-Philipp Müller <tim@centricular.net>
- *
- * 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_CLOCK_OVERLAY_H__
-#define __GST_CLOCK_OVERLAY_H__
-
-#include "gsttextoverlay.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_CLOCK_OVERLAY \
-  (gst_clock_overlay_get_type())
-#define GST_CLOCK_OVERLAY(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CLOCK_OVERLAY,GstClockOverlay))
-#define GST_CLOCK_OVERLAY_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CLOCK_OVERLAY,GstClockOverlayClass))
-#define GST_IS_CLOCK_OVERLAY(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CLOCK_OVERLAY))
-#define GST_IS_CLOCK_OVERLAY_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CLOCK_OVERLAY))
-
-typedef struct _GstClockOverlay GstClockOverlay;
-typedef struct _GstClockOverlayClass GstClockOverlayClass;
-
-/**
- * GstClockOverlay:
- *
- * Opaque clockoverlay data structure.
- */
-struct _GstClockOverlay {
-  GstTextOverlay textoverlay;
-};
-
-struct _GstClockOverlayClass {
-  GstTextOverlayClass parent_class;
-};
-
-GType gst_clock_overlay_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_CLOCK_OVERLAY_H__ */
-
--- a/gst_plugins_base/ext/pango/gsttextoverlay.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1698 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- * Copyright (C) <2006> Julien Moutte <julien@moutte.net>
- * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
- *
- * 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.
- */
-
-/**
- * SECTION:element-textoverlay
- * @see_also: #GstTextRender, #GstClockOverlay, #GstTimeOverlay, #GstSubParse
- *
- * <refsect2>
- * <para>
- * This plugin renders text on top of a video stream. This can be either
- * static text or text from buffers received on the text sink pad, e.g.
- * as produced by the subparse element. If the text sink pad is not linked,
- * the text set via the "text" property will be rendered. If the text sink
- * pad is linked, text will be rendered as it is received on that pad,
- * honouring and matching the buffer timestamps of both input streams.
- * </para>
- * <para>
- * The text can contain newline characters and text wrapping is enabled by
- * default.
- * </para>
- * <para>
- * Here is a simple pipeline that displays a static text in the top left
- * corner of the video picture:
- * <programlisting>
- * gst-launch -v videotestsrc ! textoverlay text="Room A" valign=top halign=left ! xvimagesink
- * </programlisting>
- * </para>
- * <para>
- * Here is another pipeline that displays subtitles from an .srt subtitle
- * file, centered at the bottom of the picture and with a rectangular shading
- * around the text in the background:
- * <programlisting>
- * gst-launch -v filesrc location=subtitles.srt ! subparse ! txt.   videotestsrc ! timeoverlay ! textoverlay name=txt shaded-background=yes ! xvimagesink
- * </programlisting>
- * If you do not have such a subtitle file, create one looking like this
- * in a text editor:
- * <programlisting>
- * 1
- * 00:00:03,000 --> 00:00:05,000
- * Hello? (3-5s)
- *  
- * 2
- * 00:00:08,000 --> 00:00:13,000
- * Yes, this is a subtitle. Don&apos;t
- * you like it? (8-13s)
- *  
- * 3
- * 00:00:18,826 --> 00:01:02,886
- * Uh? What are you talking about?
- * I don&apos;t understand  (18-62s)
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-/* FIXME: alloc segment as part of instance struct */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gst/video/video.h>
-
-#include "gsttextoverlay.h"
-#include "gsttimeoverlay.h"
-#include "gstclockoverlay.h"
-#include "gsttextrender.h"
-
-/* FIXME:
- *  - use proper strides and offset for I420
- *  - if text is wider than the video picture, it does not get
- *    clipped properly during blitting (if wrapping is disabled)
- *  - make 'shading_value' a property (or enum:  light/normal/dark/verydark)?
- */
-
-GST_DEBUG_CATEGORY (pango_debug);
-#define GST_CAT_DEFAULT pango_debug
-
-static const GstElementDetails text_overlay_details =
-GST_ELEMENT_DETAILS ("Text overlay",
-    "Filter/Editor/Video",
-    "Adds text strings on top of a video buffer",
-    "David Schleef <ds@schleef.org>");
-
-
-#define DEFAULT_PROP_TEXT 	""
-#define DEFAULT_PROP_SHADING	FALSE
-#define DEFAULT_PROP_VALIGNMENT	GST_TEXT_OVERLAY_VALIGN_BASELINE
-#define DEFAULT_PROP_HALIGNMENT	GST_TEXT_OVERLAY_HALIGN_CENTER
-#define DEFAULT_PROP_VALIGN	"baseline"
-#define DEFAULT_PROP_HALIGN	"center"
-#define DEFAULT_PROP_XPAD	25
-#define DEFAULT_PROP_YPAD	25
-#define DEFAULT_PROP_DELTAX	0
-#define DEFAULT_PROP_DELTAY	0
-#define DEFAULT_PROP_WRAP_MODE  GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR
-#define DEFAULT_PROP_FONT_DESC	""
-#define DEFAULT_PROP_SILENT	FALSE
-#define DEFAULT_PROP_LINE_ALIGNMENT GST_TEXT_OVERLAY_LINE_ALIGN_CENTER
-
-/* make a property of me */
-#define DEFAULT_SHADING_VALUE    -80
-
-enum
-{
-  PROP_0,
-  PROP_TEXT,
-  PROP_SHADING,
-  PROP_VALIGN,                  /* deprecated */
-  PROP_HALIGN,                  /* deprecated */
-  PROP_HALIGNMENT,
-  PROP_VALIGNMENT,
-  PROP_XPAD,
-  PROP_YPAD,
-  PROP_DELTAX,
-  PROP_DELTAY,
-  PROP_WRAP_MODE,
-  PROP_FONT_DESC,
-  PROP_SILENT,
-  PROP_LINE_ALIGNMENT
-};
-
-
-static GstStaticPadTemplate src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
-    );
-
-static GstStaticPadTemplate video_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("video_sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
-    );
-
-static GstStaticPadTemplate text_sink_template_factory =
-    GST_STATIC_PAD_TEMPLATE ("text_sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("text/x-pango-markup; text/plain")
-    );
-
-
-#define GST_TYPE_TEXT_OVERLAY_VALIGN (gst_text_overlay_valign_get_type())
-static GType
-gst_text_overlay_valign_get_type (void)
-{
-  static GType text_overlay_valign_type = 0;
-  static const GEnumValue text_overlay_valign[] = {
-    {GST_TEXT_OVERLAY_VALIGN_BASELINE, "baseline", "baseline"},
-    {GST_TEXT_OVERLAY_VALIGN_BOTTOM, "bottom", "bottom"},
-    {GST_TEXT_OVERLAY_VALIGN_TOP, "top", "top"},
-    {0, NULL, NULL},
-  };
-
-  if (!text_overlay_valign_type) {
-    text_overlay_valign_type =
-        g_enum_register_static ("GstTextOverlayVAlign", text_overlay_valign);
-  }
-  return text_overlay_valign_type;
-}
-
-#define GST_TYPE_TEXT_OVERLAY_HALIGN (gst_text_overlay_halign_get_type())
-static GType
-gst_text_overlay_halign_get_type (void)
-{
-  static GType text_overlay_halign_type = 0;
-  static const GEnumValue text_overlay_halign[] = {
-    {GST_TEXT_OVERLAY_HALIGN_LEFT, "left", "left"},
-    {GST_TEXT_OVERLAY_HALIGN_CENTER, "center", "center"},
-    {GST_TEXT_OVERLAY_HALIGN_RIGHT, "right", "right"},
-    {0, NULL, NULL},
-  };
-
-  if (!text_overlay_halign_type) {
-    text_overlay_halign_type =
-        g_enum_register_static ("GstTextOverlayHAlign", text_overlay_halign);
-  }
-  return text_overlay_halign_type;
-}
-
-
-#define GST_TYPE_TEXT_OVERLAY_WRAP_MODE (gst_text_overlay_wrap_mode_get_type())
-static GType
-gst_text_overlay_wrap_mode_get_type (void)
-{
-  static GType text_overlay_wrap_mode_type = 0;
-  static const GEnumValue text_overlay_wrap_mode[] = {
-    {GST_TEXT_OVERLAY_WRAP_MODE_NONE, "none", "none"},
-    {GST_TEXT_OVERLAY_WRAP_MODE_WORD, "word", "word"},
-    {GST_TEXT_OVERLAY_WRAP_MODE_CHAR, "char", "char"},
-    {GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR, "wordchar", "wordchar"},
-    {0, NULL, NULL},
-  };
-
-  if (!text_overlay_wrap_mode_type) {
-    text_overlay_wrap_mode_type =
-        g_enum_register_static ("GstTextOverlayWrapMode",
-        text_overlay_wrap_mode);
-  }
-  return text_overlay_wrap_mode_type;
-}
-
-#define GST_TYPE_TEXT_OVERLAY_LINE_ALIGN (gst_text_overlay_line_align_get_type())
-static GType
-gst_text_overlay_line_align_get_type (void)
-{
-  static GType text_overlay_line_align_type = 0;
-  static const GEnumValue text_overlay_line_align[] = {
-    {GST_TEXT_OVERLAY_LINE_ALIGN_LEFT, "left", "left"},
-    {GST_TEXT_OVERLAY_LINE_ALIGN_CENTER, "center", "center"},
-    {GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT, "right", "right"},
-    {0, NULL, NULL}
-  };
-
-  if (!text_overlay_line_align_type) {
-    text_overlay_line_align_type =
-        g_enum_register_static ("GstTextOverlayLineAlign",
-        text_overlay_line_align);
-  }
-  return text_overlay_line_align_type;
-}
-
-/* These macros are adapted from videotestsrc.c */
-#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
-#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
-#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
-
-#define I420_Y_OFFSET(w,h) (0)
-#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
-#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
-
-#define I420_SIZE(w,h)     (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
-
-#define GST_TEXT_OVERLAY_GET_COND(ov) (((GstTextOverlay *)ov)->cond)
-#define GST_TEXT_OVERLAY_WAIT(ov)     (g_cond_wait (GST_TEXT_OVERLAY_GET_COND (ov), GST_OBJECT_GET_LOCK (ov)))
-#define GST_TEXT_OVERLAY_SIGNAL(ov)   (g_cond_signal (GST_TEXT_OVERLAY_GET_COND (ov)))
-#define GST_TEXT_OVERLAY_BROADCAST(ov)(g_cond_broadcast (GST_TEXT_OVERLAY_GET_COND (ov)))
-
-static GstStateChangeReturn gst_text_overlay_change_state (GstElement * element,
-    GstStateChange transition);
-
-static GstCaps *gst_text_overlay_getcaps (GstPad * pad);
-static gboolean gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_text_overlay_setcaps_txt (GstPad * pad, GstCaps * caps);
-static gboolean gst_text_overlay_src_event (GstPad * pad, GstEvent * event);
-
-static gboolean gst_text_overlay_video_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_text_overlay_video_chain (GstPad * pad,
-    GstBuffer * buffer);
-
-static gboolean gst_text_overlay_text_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_text_overlay_text_chain (GstPad * pad,
-    GstBuffer * buffer);
-static GstPadLinkReturn gst_text_overlay_text_pad_link (GstPad * pad,
-    GstPad * peer);
-static void gst_text_overlay_text_pad_unlink (GstPad * pad);
-static void gst_text_overlay_pop_text (GstTextOverlay * overlay);
-
-static void gst_text_overlay_finalize (GObject * object);
-static void gst_text_overlay_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_text_overlay_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-GST_BOILERPLATE (GstTextOverlay, gst_text_overlay, GstElement, GST_TYPE_ELEMENT)
-
-     static void gst_text_overlay_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_template_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&video_sink_template_factory));
-
-  /* ugh */
-  if (!GST_IS_TIME_OVERLAY_CLASS (g_class) &&
-      !GST_IS_CLOCK_OVERLAY_CLASS (g_class)) {
-    gst_element_class_add_pad_template (element_class,
-        gst_static_pad_template_get (&text_sink_template_factory));
-  }
-
-  gst_element_class_set_details (element_class, &text_overlay_details);
-}
-
-static gchar *
-gst_text_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
-  return g_strdup (overlay->default_text);
-}
-
-static void
-gst_text_overlay_class_init (GstTextOverlayClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  gobject_class->finalize = gst_text_overlay_finalize;
-  gobject_class->set_property = gst_text_overlay_set_property;
-  gobject_class->get_property = gst_text_overlay_get_property;
-
-  gstelement_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_text_overlay_change_state);
-
-  klass->get_text = gst_text_overlay_get_text;
-  klass->pango_context = pango_ft2_get_context (72, 72);
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TEXT,
-      g_param_spec_string ("text", "text",
-          "Text to be display.", DEFAULT_PROP_TEXT, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SHADING,
-      g_param_spec_boolean ("shaded-background", "shaded background",
-          "Whether to shade the background under the text area",
-          DEFAULT_PROP_SHADING, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGNMENT,
-      g_param_spec_enum ("valignment", "vertical alignment",
-          "Vertical alignment of the text",
-          GST_TYPE_TEXT_OVERLAY_VALIGN, DEFAULT_PROP_VALIGNMENT,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGNMENT,
-      g_param_spec_enum ("halignment", "horizontal alignment",
-          "Horizontal alignment of the text", GST_TYPE_TEXT_OVERLAY_HALIGN,
-          DEFAULT_PROP_HALIGNMENT, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGN,
-      g_param_spec_string ("valign", "vertical alignment",
-          "Vertical alignment of the text (deprecated; use valignment)",
-          DEFAULT_PROP_VALIGN, G_PARAM_WRITABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGN,
-      g_param_spec_string ("halign", "horizontal alignment",
-          "Horizontal alignment of the text (deprecated; use halignment)",
-          DEFAULT_PROP_HALIGN, G_PARAM_WRITABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_XPAD,
-      g_param_spec_int ("xpad", "horizontal paddding",
-          "Horizontal paddding when using left/right alignment", 0, G_MAXINT,
-          DEFAULT_PROP_XPAD, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_YPAD,
-      g_param_spec_int ("ypad", "vertical padding",
-          "Vertical padding when using top/bottom alignment", 0, G_MAXINT,
-          DEFAULT_PROP_YPAD, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELTAX,
-      g_param_spec_int ("deltax", "X position modifier",
-          "Shift X position to the left or to the right. Unit is pixels.",
-          G_MININT, G_MAXINT, DEFAULT_PROP_DELTAX, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELTAY,
-      g_param_spec_int ("deltay", "Y position modifier",
-          "Shift Y position up or down. Unit is pixels.", G_MININT, G_MAXINT,
-          DEFAULT_PROP_DELTAY, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WRAP_MODE,
-      g_param_spec_enum ("wrap-mode", "wrap mode",
-          "Whether to wrap the text and if so how.",
-          GST_TYPE_TEXT_OVERLAY_WRAP_MODE, DEFAULT_PROP_WRAP_MODE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC,
-      g_param_spec_string ("font-desc", "font description",
-          "Pango font description of font to be used for rendering. "
-          "See documentation of pango_font_description_from_string "
-          "for syntax.", DEFAULT_PROP_FONT_DESC, G_PARAM_WRITABLE));
-  /**
-   * GstTextOverlay:line-alignment
-   *
-   * Alignment of text lines relative to each other (for multi-line text)
-   *
-   * Since: 0.10.15
-   **/
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LINE_ALIGNMENT,
-      g_param_spec_enum ("line-alignment", "line alignment",
-          "Alignment of text lines relative to each other.",
-          GST_TYPE_TEXT_OVERLAY_LINE_ALIGN, DEFAULT_PROP_LINE_ALIGNMENT,
-          G_PARAM_READWRITE));
-  /**
-   * GstTextOverlay:silent
-   *
-   * If set, no text is rendered. Useful to switch off text rendering
-   * temporarily without removing the textoverlay element from the pipeline.
-   *
-   * Since: 0.10.15
-   **/
-  /* FIXME 0.11: rename to "visible" or "text-visible" or "render-text" */
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
-      g_param_spec_boolean ("silent", "silent",
-          "Whether to render the text string",
-          DEFAULT_PROP_SILENT, G_PARAM_READWRITE));
-}
-
-static void
-gst_text_overlay_finalize (GObject * object)
-{
-  GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
-
-  g_free (overlay->default_text);
-  g_free (overlay->bitmap.buffer);
-
-  if (overlay->layout) {
-    g_object_unref (overlay->layout);
-    overlay->layout = NULL;
-  }
-
-  if (overlay->segment) {
-    gst_segment_free (overlay->segment);
-    overlay->segment = NULL;
-  }
-
-  if (overlay->text_buffer) {
-    gst_buffer_unref (overlay->text_buffer);
-    overlay->text_buffer = NULL;
-  }
-
-  if (overlay->cond) {
-    g_cond_free (overlay->cond);
-    overlay->cond = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_text_overlay_init (GstTextOverlay * overlay, GstTextOverlayClass * klass)
-{
-  GstPadTemplate *template;
-
-  /* video sink */
-  template = gst_static_pad_template_get (&video_sink_template_factory);
-  overlay->video_sinkpad = gst_pad_new_from_template (template, "video_sink");
-  gst_object_unref (template);
-  gst_pad_set_getcaps_function (overlay->video_sinkpad,
-      GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps));
-  gst_pad_set_setcaps_function (overlay->video_sinkpad,
-      GST_DEBUG_FUNCPTR (gst_text_overlay_setcaps));
-  gst_pad_set_event_function (overlay->video_sinkpad,
-      GST_DEBUG_FUNCPTR (gst_text_overlay_video_event));
-  gst_pad_set_chain_function (overlay->video_sinkpad,
-      GST_DEBUG_FUNCPTR (gst_text_overlay_video_chain));
-  gst_element_add_pad (GST_ELEMENT (overlay), overlay->video_sinkpad);
-
-  if (!GST_IS_TIME_OVERLAY_CLASS (klass) && !GST_IS_CLOCK_OVERLAY_CLASS (klass)) {
-    /* text sink */
-    template = gst_static_pad_template_get (&text_sink_template_factory);
-    overlay->text_sinkpad = gst_pad_new_from_template (template, "text_sink");
-    gst_object_unref (template);
-    gst_pad_set_setcaps_function (overlay->text_sinkpad,
-        GST_DEBUG_FUNCPTR (gst_text_overlay_setcaps_txt));
-    gst_pad_set_event_function (overlay->text_sinkpad,
-        GST_DEBUG_FUNCPTR (gst_text_overlay_text_event));
-    gst_pad_set_chain_function (overlay->text_sinkpad,
-        GST_DEBUG_FUNCPTR (gst_text_overlay_text_chain));
-    gst_pad_set_link_function (overlay->text_sinkpad,
-        GST_DEBUG_FUNCPTR (gst_text_overlay_text_pad_link));
-    gst_pad_set_unlink_function (overlay->text_sinkpad,
-        GST_DEBUG_FUNCPTR (gst_text_overlay_text_pad_unlink));
-    gst_element_add_pad (GST_ELEMENT (overlay), overlay->text_sinkpad);
-  }
-
-  /* (video) source */
-  template = gst_static_pad_template_get (&src_template_factory);
-  overlay->srcpad = gst_pad_new_from_template (template, "src");
-  gst_object_unref (template);
-  gst_pad_set_getcaps_function (overlay->srcpad,
-      GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps));
-  gst_pad_set_event_function (overlay->srcpad,
-      GST_DEBUG_FUNCPTR (gst_text_overlay_src_event));
-  gst_element_add_pad (GST_ELEMENT (overlay), overlay->srcpad);
-
-  overlay->line_align = DEFAULT_PROP_LINE_ALIGNMENT;
-  overlay->layout =
-      pango_layout_new (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_context);
-  pango_layout_set_alignment (overlay->layout,
-      (PangoAlignment) overlay->line_align);
-  memset (&overlay->bitmap, 0, sizeof (overlay->bitmap));
-
-  overlay->halign = DEFAULT_PROP_HALIGNMENT;
-  overlay->valign = DEFAULT_PROP_VALIGNMENT;
-  overlay->xpad = DEFAULT_PROP_XPAD;
-  overlay->ypad = DEFAULT_PROP_YPAD;
-  overlay->deltax = DEFAULT_PROP_DELTAX;
-  overlay->deltay = DEFAULT_PROP_DELTAY;
-
-  overlay->wrap_mode = DEFAULT_PROP_WRAP_MODE;
-
-  overlay->want_shading = DEFAULT_PROP_SHADING;
-  overlay->shading_value = DEFAULT_SHADING_VALUE;
-  overlay->silent = DEFAULT_PROP_SILENT;
-
-  overlay->default_text = g_strdup (DEFAULT_PROP_TEXT);
-  overlay->need_render = TRUE;
-
-  overlay->fps_n = 0;
-  overlay->fps_d = 1;
-
-  overlay->text_buffer = NULL;
-  overlay->text_linked = FALSE;
-  overlay->video_flushing = FALSE;
-  overlay->text_flushing = FALSE;
-  overlay->text_eos = FALSE;
-  overlay->cond = g_cond_new ();
-  overlay->segment = gst_segment_new ();
-  if (overlay->segment) {
-    gst_segment_init (overlay->segment, GST_FORMAT_TIME);
-  } else {
-    GST_WARNING_OBJECT (overlay, "segment creation failed");
-    g_assert_not_reached ();
-  }
-}
-
-static void
-gst_text_overlay_update_wrap_mode (GstTextOverlay * overlay)
-{
-  if (overlay->wrap_mode == GST_TEXT_OVERLAY_WRAP_MODE_NONE) {
-    GST_DEBUG_OBJECT (overlay, "Set wrap mode NONE");
-    pango_layout_set_width (overlay->layout, -1);
-  } else {
-    GST_DEBUG_OBJECT (overlay, "Set layout width %d", overlay->width);
-    GST_DEBUG_OBJECT (overlay, "Set wrap mode    %d", overlay->wrap_mode);
-    pango_layout_set_width (overlay->layout, overlay->width * PANGO_SCALE);
-    pango_layout_set_wrap (overlay->layout, (PangoWrapMode) overlay->wrap_mode);
-  }
-}
-
-static gboolean
-gst_text_overlay_setcaps_txt (GstPad * pad, GstCaps * caps)
-{
-  GstTextOverlay *overlay;
-  GstStructure *structure;
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  structure = gst_caps_get_structure (caps, 0);
-  overlay->have_pango_markup =
-      gst_structure_has_name (structure, "text/x-pango-markup");
-
-  gst_object_unref (overlay);
-
-  return TRUE;
-}
-
-/* FIXME: upstream nego (e.g. when the video window is resized) */
-
-static gboolean
-gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstTextOverlay *overlay;
-  GstStructure *structure;
-  gboolean ret = FALSE;
-  const GValue *fps;
-
-  if (!GST_PAD_IS_SINK (pad))
-    return TRUE;
-
-  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  overlay->width = 0;
-  overlay->height = 0;
-  structure = gst_caps_get_structure (caps, 0);
-  fps = gst_structure_get_value (structure, "framerate");
-
-  if (gst_structure_get_int (structure, "width", &overlay->width) &&
-      gst_structure_get_int (structure, "height", &overlay->height) &&
-      fps != NULL) {
-    ret = gst_pad_set_caps (overlay->srcpad, caps);
-  }
-
-  overlay->fps_n = gst_value_get_fraction_numerator (fps);
-  overlay->fps_d = gst_value_get_fraction_denominator (fps);
-
-  if (ret) {
-    GST_OBJECT_LOCK (overlay);
-    gst_text_overlay_update_wrap_mode (overlay);
-    GST_OBJECT_UNLOCK (overlay);
-  }
-
-  gst_object_unref (overlay);
-
-  return ret;
-}
-
-static void
-gst_text_overlay_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
-
-  GST_OBJECT_LOCK (overlay);
-  switch (prop_id) {
-    case PROP_TEXT:
-      g_free (overlay->default_text);
-      overlay->default_text = g_value_dup_string (value);
-      overlay->need_render = TRUE;
-      break;
-    case PROP_SHADING:
-      overlay->want_shading = g_value_get_boolean (value);
-      break;
-    case PROP_XPAD:
-      overlay->xpad = g_value_get_int (value);
-      break;
-    case PROP_YPAD:
-      overlay->ypad = g_value_get_int (value);
-      break;
-    case PROP_DELTAX:
-      overlay->deltax = g_value_get_int (value);
-      break;
-    case PROP_DELTAY:
-      overlay->deltay = g_value_get_int (value);
-      break;
-    case PROP_HALIGN:{
-      const gchar *s = g_value_get_string (value);
-
-      if (s && g_ascii_strcasecmp (s, "left") == 0)
-        overlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT;
-      else if (s && g_ascii_strcasecmp (s, "center") == 0)
-        overlay->halign = GST_TEXT_OVERLAY_HALIGN_CENTER;
-      else if (s && g_ascii_strcasecmp (s, "right") == 0)
-        overlay->halign = GST_TEXT_OVERLAY_HALIGN_RIGHT;
-      else
-        g_warning ("Invalid value '%s' for textoverlay property 'halign'",
-            GST_STR_NULL (s));
-      break;
-    }
-    case PROP_VALIGN:{
-      const gchar *s = g_value_get_string (value);
-
-      if (s && g_ascii_strcasecmp (s, "baseline") == 0)
-        overlay->valign = GST_TEXT_OVERLAY_VALIGN_BASELINE;
-      else if (s && g_ascii_strcasecmp (s, "bottom") == 0)
-        overlay->valign = GST_TEXT_OVERLAY_VALIGN_BOTTOM;
-      else if (s && g_ascii_strcasecmp (s, "top") == 0)
-        overlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP;
-      else
-        g_warning ("Invalid value '%s' for textoverlay property 'valign'",
-            GST_STR_NULL (s));
-      break;
-    }
-    case PROP_VALIGNMENT:
-      overlay->valign = g_value_get_enum (value);
-      break;
-    case PROP_HALIGNMENT:
-      overlay->halign = g_value_get_enum (value);
-      break;
-    case PROP_WRAP_MODE:
-      overlay->wrap_mode = g_value_get_enum (value);
-      gst_text_overlay_update_wrap_mode (overlay);
-      break;
-    case PROP_FONT_DESC:
-    {
-      PangoFontDescription *desc;
-      const gchar *fontdesc_str;
-
-      fontdesc_str = g_value_get_string (value);
-      desc = pango_font_description_from_string (fontdesc_str);
-      if (desc) {
-        GST_LOG_OBJECT (overlay, "font description set: %s", fontdesc_str);
-        pango_layout_set_font_description (overlay->layout, desc);
-        pango_font_description_free (desc);
-      } else {
-        GST_WARNING_OBJECT (overlay, "font description parse failed: %s",
-            fontdesc_str);
-      }
-      break;
-    }
-    case PROP_SILENT:
-      overlay->silent = g_value_get_boolean (value);
-      break;
-    case PROP_LINE_ALIGNMENT:
-      overlay->line_align = g_value_get_enum (value);
-      pango_layout_set_alignment (overlay->layout,
-          (PangoAlignment) overlay->line_align);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  overlay->need_render = TRUE;
-  GST_OBJECT_UNLOCK (overlay);
-}
-
-static void
-gst_text_overlay_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
-
-  GST_OBJECT_LOCK (overlay);
-  switch (prop_id) {
-    case PROP_TEXT:
-      g_value_set_string (value, overlay->default_text);
-      break;
-    case PROP_SHADING:
-      g_value_set_boolean (value, overlay->want_shading);
-      break;
-    case PROP_XPAD:
-      g_value_set_int (value, overlay->xpad);
-      break;
-    case PROP_YPAD:
-      g_value_set_int (value, overlay->ypad);
-      break;
-    case PROP_DELTAX:
-      g_value_set_int (value, overlay->deltax);
-      break;
-    case PROP_DELTAY:
-      g_value_set_int (value, overlay->deltay);
-      break;
-    case PROP_VALIGNMENT:
-      g_value_set_enum (value, overlay->valign);
-      break;
-    case PROP_HALIGNMENT:
-      g_value_set_enum (value, overlay->halign);
-      break;
-    case PROP_WRAP_MODE:
-      g_value_set_enum (value, overlay->wrap_mode);
-      break;
-    case PROP_SILENT:
-      g_value_set_boolean (value, overlay->silent);
-      break;
-    case PROP_LINE_ALIGNMENT:
-      g_value_set_enum (value, overlay->line_align);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  overlay->need_render = TRUE;
-  GST_OBJECT_UNLOCK (overlay);
-}
-
-static gboolean
-gst_text_overlay_src_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret = FALSE;
-  GstTextOverlay *overlay = NULL;
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_SEEK:
-      /* We don't handle seek if we have not text pad */
-      if (!overlay->text_linked) {
-        ret = gst_pad_push_event (overlay->video_sinkpad, event);
-        goto beach;
-      }
-
-      GST_DEBUG_OBJECT (overlay, "seek received, driving from here");
-
-      /* Flush downstream, FIXME, only for flushing seek */
-      gst_pad_push_event (overlay->srcpad, gst_event_new_flush_start ());
-
-      /* Mark ourself as flushing, unblock chains */
-      GST_OBJECT_LOCK (overlay);
-      overlay->video_flushing = TRUE;
-      overlay->text_flushing = TRUE;
-      gst_text_overlay_pop_text (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-
-      /* Seek on each sink pad */
-      gst_event_ref (event);
-      ret = gst_pad_push_event (overlay->video_sinkpad, event);
-      if (ret) {
-        ret = gst_pad_push_event (overlay->text_sinkpad, event);
-      } else {
-        gst_event_unref (event);
-      }
-      break;
-    default:
-      if (overlay->text_linked) {
-        gst_event_ref (event);
-        ret = gst_pad_push_event (overlay->video_sinkpad, event);
-        gst_pad_push_event (overlay->text_sinkpad, event);
-      } else {
-        ret = gst_pad_push_event (overlay->video_sinkpad, event);
-      }
-      break;
-  }
-
-beach:
-  gst_object_unref (overlay);
-
-  return ret;
-}
-
-static GstCaps *
-gst_text_overlay_getcaps (GstPad * pad)
-{
-  GstTextOverlay *overlay;
-  GstPad *otherpad;
-  GstCaps *caps;
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  if (pad == overlay->srcpad)
-    otherpad = overlay->video_sinkpad;
-  else
-    otherpad = overlay->srcpad;
-
-  /* we can do what the peer can */
-  caps = gst_pad_peer_get_caps (otherpad);
-  if (caps) {
-    GstCaps *temp;
-    const GstCaps *templ;
-
-    GST_DEBUG_OBJECT (pad, "peer caps  %" GST_PTR_FORMAT, caps);
-
-    /* filtered against our padtemplate */
-    templ = gst_pad_get_pad_template_caps (otherpad);
-    GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
-    temp = gst_caps_intersect (caps, templ);
-    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
-    gst_caps_unref (caps);
-    /* this is what we can do */
-    caps = temp;
-  } else {
-    /* no peer, our padtemplate is enough then */
-    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-  }
-
-  GST_DEBUG_OBJECT (overlay, "returning  %" GST_PTR_FORMAT, caps);
-
-  gst_object_unref (overlay);
-
-  return caps;
-}
-
-#define BOX_XPAD         6
-#define BOX_YPAD         6
-
-static inline void
-gst_text_overlay_shade_y (GstTextOverlay * overlay, guchar * dest,
-    guint dest_stride, gint x0, gint x1, gint y0, gint y1)
-{
-  gint i, j;
-
-  x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width);
-  x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width);
-
-  y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height);
-  y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height);
-
-  for (i = y0; i < y1; ++i) {
-    for (j = x0; j < x1; ++j) {
-      gint y = dest[(i * dest_stride) + j] + overlay->shading_value;
-
-      dest[(i * dest_stride) + j] = CLAMP (y, 0, 255);
-    }
-  }
-}
-
-/* FIXME:
- *  - use proper strides and offset for I420
- *  - don't draw over the edge of the picture (try a longer
- *    text with a huge font size)
- */
-
-static inline void
-gst_text_overlay_blit_yuv420 (GstTextOverlay * overlay, FT_Bitmap * bitmap,
-    guint8 * yuv_pixels, gint x0, gint y0)
-{
-  int y;                        /* text bitmap coordinates */
-  int x1, y1;                   /* video buffer coordinates */
-  int bit_rowinc, uv_rowinc;
-  guint8 *p, *bitp, *u_p;
-  int video_width, video_height;
-  int bitmap_x0 = 0;            //x0 < 1 ? -(x0 - 1) : 1;       /* 1 pixel border */
-  int bitmap_y0 = y0 < 1 ? -(y0 - 1) : 1;       /* 1 pixel border */
-  int bitmap_width = bitmap->width - bitmap_x0;
-  int bitmap_height = bitmap->rows - bitmap_y0;
-  int u_plane_size;
-  int skip_y, skip_x;
-  guint8 v;
-
-  video_width = I420_Y_ROWSTRIDE (overlay->width);
-  video_height = overlay->height;
-
-/*
-  if (x0 < 0 && abs (x0) < bitmap_width) {
-    bitmap_x0 = abs (x0);
-    x0 = 0;
-  }
-*/
-
-  if (x0 + bitmap_x0 + bitmap_width > overlay->width - 1)       /* 1 pixel border */
-    bitmap_width -= x0 + bitmap_x0 + bitmap_width - overlay->width + 1;
-  if (y0 + bitmap_y0 + bitmap_height > video_height - 1)        /* 1 pixel border */
-    bitmap_height -= y0 + bitmap_y0 + bitmap_height - video_height + 1;
-
-  uv_rowinc = video_width / 2 - bitmap_width / 2;
-  bit_rowinc = bitmap->pitch - bitmap_width;
-  u_plane_size = (video_width / 2) * (video_height / 2);
-
-  y1 = y0 + bitmap_y0;
-  x1 = x0 + bitmap_x0;
-  bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
-  for (y = bitmap_y0; y < bitmap_y0 + bitmap_height; y++) {
-    int n;
-
-    p = yuv_pixels + (y + y0) * I420_Y_ROWSTRIDE (overlay->width) + x1;
-    for (n = bitmap_width; n > 0; --n) {
-      v = *bitp;
-      if (v) {
-        p[-1] = CLAMP (p[-1] - v, 0, 255);
-        p[1] = CLAMP (p[1] - v, 0, 255);
-        p[-video_width] = CLAMP (p[-video_width] - v, 0, 255);
-        p[video_width] = CLAMP (p[video_width] - v, 0, 255);
-      }
-      p++;
-      bitp++;
-    }
-    bitp += bit_rowinc;
-  }
-
-  y = bitmap_y0;
-  y1 = y0 + bitmap_y0;
-  x1 = x0 + bitmap_x0;
-  bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
-  p = yuv_pixels + video_width * y1 + x1;
-  u_p =
-      yuv_pixels + video_width * video_height + (video_width >> 1) * (y1 >> 1) +
-      (x1 >> 1);
-  skip_y = 0;
-  skip_x = 0;
-
-  for (; y < bitmap_y0 + bitmap_height; y++) {
-    int n;
-
-    x1 = x0 + bitmap_x0;
-    skip_x = 0;
-    for (n = bitmap_width; n > 0; --n) {
-      v = *bitp;
-      if (v) {
-        *p = v;
-        if (!skip_y) {
-          u_p[0] = u_p[u_plane_size] = 0x80;
-        }
-      }
-      if (!skip_y) {
-        skip_x = !skip_x;
-        if (!skip_x)
-          u_p++;
-      }
-      p++;
-      bitp++;
-    }
-    /*if (!skip_x && !skip_y) u_p--; */
-    p += I420_Y_ROWSTRIDE (overlay->width) - bitmap_width;
-    bitp += bit_rowinc;
-    skip_y = !skip_y;
-    u_p += skip_y ? uv_rowinc : 0;
-  }
-}
-
-static void
-gst_text_overlay_resize_bitmap (GstTextOverlay * overlay, gint width,
-    gint height)
-{
-  FT_Bitmap *bitmap = &overlay->bitmap;
-  int pitch = (width | 3) + 1;
-  int size = pitch * height;
-
-  /* no need to keep reallocating; just keep the maximum size so far */
-  if (size <= overlay->bitmap_buffer_size) {
-    bitmap->rows = height;
-    bitmap->width = width;
-    bitmap->pitch = pitch;
-    memset (bitmap->buffer, 0, overlay->bitmap_buffer_size);
-    return;
-  }
-  if (!bitmap->buffer) {
-    /* initialize */
-    bitmap->pixel_mode = ft_pixel_mode_grays;
-    bitmap->num_grays = 256;
-  }
-  overlay->bitmap_buffer_size = size;
-  bitmap->buffer = g_realloc (bitmap->buffer, size);
-  memset (bitmap->buffer, 0, size);
-  bitmap->rows = height;
-  bitmap->width = width;
-  bitmap->pitch = pitch;
-}
-
-static void
-gst_text_overlay_render_text (GstTextOverlay * overlay,
-    const gchar * text, gint textlen)
-{
-  PangoRectangle ink_rect, logical_rect;
-  gchar *string;
-
-  if (!overlay->need_render) {
-    GST_DEBUG ("Using previously rendered text.");
-    return;
-  }
-
-  /* -1 is the whole string */
-  if (text != NULL && textlen < 0) {
-    textlen = strlen (text);
-  }
-
-  if (text != NULL) {
-    string = g_strndup (text, textlen);
-  } else {                      /* empty string */
-    string = g_strdup (" ");
-  }
-  g_strdelimit (string, "\r\t", ' ');
-  textlen = strlen (string);
-
-  /* FIXME: should we check for UTF-8 here? */
-
-  GST_DEBUG ("Rendering '%s'", string);
-  pango_layout_set_markup (overlay->layout, string, textlen);
-
-  pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect);
-  gst_text_overlay_resize_bitmap (overlay, ink_rect.width,
-      ink_rect.height + ink_rect.y);
-  pango_ft2_render_layout (&overlay->bitmap, overlay->layout, -ink_rect.x, 0);
-  overlay->baseline_y = ink_rect.y;
-
-  g_free (string);
-
-  overlay->need_render = FALSE;
-}
-
-static GstFlowReturn
-gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
-  gint xpos, ypos;
-
-  video_frame = gst_buffer_make_writable (video_frame);
-
-  switch (overlay->halign) {
-    case GST_TEXT_OVERLAY_HALIGN_LEFT:
-      xpos = overlay->xpad;
-      break;
-    case GST_TEXT_OVERLAY_HALIGN_CENTER:
-      xpos = (overlay->width - overlay->bitmap.width) / 2;
-      break;
-    case GST_TEXT_OVERLAY_HALIGN_RIGHT:
-      xpos = overlay->width - overlay->bitmap.width - overlay->xpad;
-      break;
-    default:
-      xpos = 0;
-  }
-  xpos += overlay->deltax;
-
-
-  switch (overlay->valign) {
-    case GST_TEXT_OVERLAY_VALIGN_BOTTOM:
-      ypos = overlay->height - overlay->bitmap.rows - overlay->ypad;
-      break;
-    case GST_TEXT_OVERLAY_VALIGN_BASELINE:
-      ypos = overlay->height - (overlay->bitmap.rows + overlay->ypad);
-      break;
-    case GST_TEXT_OVERLAY_VALIGN_TOP:
-      ypos = overlay->ypad;
-      break;
-    default:
-      ypos = overlay->ypad;
-      break;
-  }
-  ypos += overlay->deltay;
-
-  /* shaded background box */
-  if (overlay->want_shading) {
-    gst_text_overlay_shade_y (overlay,
-        GST_BUFFER_DATA (video_frame),
-        I420_Y_ROWSTRIDE (overlay->width),
-        xpos, xpos + overlay->bitmap.width, ypos, ypos + overlay->bitmap.rows);
-  }
-
-
-  if (overlay->bitmap.buffer) {
-    gst_text_overlay_blit_yuv420 (overlay, &overlay->bitmap,
-        GST_BUFFER_DATA (video_frame), xpos, ypos);
-  }
-
-  return gst_pad_push (overlay->srcpad, video_frame);
-}
-
-static GstPadLinkReturn
-gst_text_overlay_text_pad_link (GstPad * pad, GstPad * peer)
-{
-  GstTextOverlay *overlay;
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  GST_DEBUG_OBJECT (overlay, "Text pad linked");
-
-  overlay->text_linked = TRUE;
-
-  gst_object_unref (overlay);
-
-  return GST_PAD_LINK_OK;
-}
-
-static void
-gst_text_overlay_text_pad_unlink (GstPad * pad)
-{
-  GstTextOverlay *overlay;
-
-  /* don't use gst_pad_get_parent() here, will deadlock */
-  overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad));
-
-  GST_DEBUG_OBJECT (overlay, "Text pad unlinked");
-
-  overlay->text_linked = FALSE;
-
-  gst_segment_init (&overlay->text_segment, GST_FORMAT_UNDEFINED);
-}
-
-static gboolean
-gst_text_overlay_text_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret = FALSE;
-  GstTextOverlay *overlay = NULL;
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  GST_LOG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:{
-      GstFormat fmt;
-      gboolean update;
-      gdouble rate, applied_rate;
-      gint64 cur, stop, time;
-
-      overlay->text_eos = FALSE;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-          &fmt, &cur, &stop, &time);
-
-      if (fmt == GST_FORMAT_TIME) {
-        GST_OBJECT_LOCK (overlay);
-        gst_segment_set_newsegment_full (&overlay->text_segment, update, rate,
-            applied_rate, GST_FORMAT_TIME, cur, stop, time);
-        GST_DEBUG_OBJECT (overlay, "TEXT SEGMENT now: %" GST_SEGMENT_FORMAT,
-            &overlay->text_segment);
-        GST_OBJECT_UNLOCK (overlay);
-      } else {
-        GST_ELEMENT_WARNING (overlay, STREAM, MUX, (NULL),
-            ("received non-TIME newsegment event on text input"));
-      }
-
-      gst_event_unref (event);
-      ret = TRUE;
-
-      /* wake up the video chain, it might be waiting for a text buffer or
-       * a text segment update */
-      GST_OBJECT_LOCK (overlay);
-      GST_TEXT_OVERLAY_BROADCAST (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      break;
-    }
-    case GST_EVENT_FLUSH_STOP:
-      GST_OBJECT_LOCK (overlay);
-      overlay->text_flushing = FALSE;
-      gst_text_overlay_pop_text (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      gst_event_unref (event);
-      ret = TRUE;
-      break;
-    case GST_EVENT_FLUSH_START:
-      GST_OBJECT_LOCK (overlay);
-      overlay->text_flushing = TRUE;
-      GST_TEXT_OVERLAY_BROADCAST (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      gst_event_unref (event);
-      ret = TRUE;
-      break;
-    case GST_EVENT_EOS:
-      GST_OBJECT_LOCK (overlay);
-      overlay->text_flushing = TRUE;
-      overlay->text_eos = TRUE;
-      GST_INFO_OBJECT (overlay, "EOS");
-      /* wake up the video chain, it might be waiting for a text buffer or
-       * a text segment update */
-      GST_TEXT_OVERLAY_BROADCAST (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      gst_event_unref (event);
-      ret = TRUE;
-      break;
-    default:
-      ret = gst_pad_event_default (pad, event);
-      break;
-  }
-
-  gst_object_unref (overlay);
-
-  return ret;
-}
-
-static gboolean
-gst_text_overlay_video_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret = FALSE;
-  GstTextOverlay *overlay = NULL;
-
-  overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
-  GST_DEBUG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
-    {
-      GstFormat format;
-      gdouble rate;
-      gint64 start, stop, time;
-      gboolean update;
-
-      GST_DEBUG_OBJECT (overlay, "received new segment");
-
-      gst_event_parse_new_segment (event, &update, &rate, &format, &start,
-          &stop, &time);
-
-      if (format == GST_FORMAT_TIME) {
-        GST_DEBUG_OBJECT (overlay, "VIDEO SEGMENT now: %" GST_SEGMENT_FORMAT,
-            overlay->segment);
-
-        gst_segment_set_newsegment (overlay->segment, update, rate, format,
-            start, stop, time);
-      } else {
-        GST_ELEMENT_WARNING (overlay, STREAM, MUX, (NULL),
-            ("received non-TIME newsegment event on video input"));
-      }
-
-      ret = gst_pad_event_default (pad, event);
-      break;
-    }
-    case GST_EVENT_EOS:
-      GST_OBJECT_LOCK (overlay);
-      overlay->video_flushing = TRUE;
-      overlay->text_flushing = TRUE;
-      gst_text_overlay_pop_text (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      ret = gst_pad_event_default (pad, event);
-      break;
-    case GST_EVENT_FLUSH_START:
-      GST_OBJECT_LOCK (overlay);
-      overlay->video_flushing = TRUE;
-      GST_TEXT_OVERLAY_BROADCAST (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      ret = gst_pad_event_default (pad, event);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      GST_OBJECT_LOCK (overlay);
-      overlay->video_flushing = FALSE;
-      GST_OBJECT_UNLOCK (overlay);
-      ret = gst_pad_event_default (pad, event);
-      break;
-    default:
-      ret = gst_pad_event_default (pad, event);
-      break;
-  }
-
-  gst_object_unref (overlay);
-
-  return ret;
-}
-
-/* Called with lock held */
-static void
-gst_text_overlay_pop_text (GstTextOverlay * overlay)
-{
-  g_return_if_fail (GST_IS_TEXT_OVERLAY (overlay));
-
-  if (overlay->text_buffer) {
-    /* update text_segment's last stop */
-    if (overlay->text_segment.format == GST_FORMAT_TIME &&
-        GST_BUFFER_TIMESTAMP_IS_VALID (overlay->text_buffer)) {
-      overlay->text_segment.last_stop =
-          GST_BUFFER_TIMESTAMP (overlay->text_buffer);
-      if (GST_BUFFER_DURATION_IS_VALID (overlay->text_buffer)) {
-        overlay->text_segment.last_stop +=
-            GST_BUFFER_DURATION (overlay->text_buffer);
-      }
-    }
-    GST_DEBUG_OBJECT (overlay, "releasing text buffer %p",
-        overlay->text_buffer);
-    gst_buffer_unref (overlay->text_buffer);
-    overlay->text_buffer = NULL;
-  }
-
-  /* Let the text task know we used that buffer */
-  GST_TEXT_OVERLAY_BROADCAST (overlay);
-}
-
-/* We receive text buffers here. If they are out of segment we just ignore them.
-   If the buffer is in our segment we keep it internally except if another one
-   is already waiting here, in that case we wait that it gets kicked out */
-static GstFlowReturn
-gst_text_overlay_text_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstTextOverlay *overlay = NULL;
-  gboolean in_seg = FALSE;
-  gint64 clip_start = 0, clip_stop = 0;
-
-  overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad));
-
-  GST_OBJECT_LOCK (overlay);
-
-  if (overlay->text_eos) {
-    GST_OBJECT_UNLOCK (overlay);
-    ret = GST_FLOW_UNEXPECTED;
-    GST_LOG_OBJECT (overlay, "text EOS");
-    goto beach;
-  }
-
-  if (overlay->text_flushing) {
-    GST_OBJECT_UNLOCK (overlay);
-    ret = GST_FLOW_WRONG_STATE;
-    GST_LOG_OBJECT (overlay, "text flushing");
-    goto beach;
-  }
-
-  GST_LOG_OBJECT (overlay, "%" GST_SEGMENT_FORMAT "  BUFFER: ts=%"
-      GST_TIME_FORMAT ", end=%" GST_TIME_FORMAT, overlay->segment,
-      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
-      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) +
-          GST_BUFFER_DURATION (buffer)));
-
-  in_seg = gst_segment_clip (overlay->segment, GST_FORMAT_TIME,
-      GST_BUFFER_TIMESTAMP (buffer),
-      GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer),
-      &clip_start, &clip_stop);
-
-  if (in_seg) {
-    GST_BUFFER_TIMESTAMP (buffer) = clip_start;
-    GST_BUFFER_DURATION (buffer) = clip_stop - clip_start;
-
-    /* Wait for the previous buffer to go away */
-    while (overlay->text_buffer != NULL) {
-      GST_DEBUG ("Pad %s:%s has a buffer queued, waiting",
-          GST_DEBUG_PAD_NAME (pad));
-      GST_TEXT_OVERLAY_WAIT (overlay);
-      GST_DEBUG ("Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad));
-      if (overlay->text_flushing) {
-        GST_OBJECT_UNLOCK (overlay);
-        ret = GST_FLOW_WRONG_STATE;
-        goto beach;
-      }
-    }
-
-    overlay->text_buffer = buffer;
-    /* That's a new text buffer we need to render */
-    overlay->need_render = TRUE;
-
-    /* in case the video chain is waiting for a text buffer, wake it up */
-    GST_TEXT_OVERLAY_BROADCAST (overlay);
-  }
-
-  GST_OBJECT_UNLOCK (overlay);
-
-beach:
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_text_overlay_video_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstTextOverlayClass *klass;
-  GstTextOverlay *overlay;
-  GstFlowReturn ret = GST_FLOW_OK;
-  gboolean in_seg = FALSE;
-  gint64 start, stop, clip_start = 0, clip_stop = 0;
-  gchar *text = NULL;
-
-  overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad));
-  klass = GST_TEXT_OVERLAY_GET_CLASS (overlay);
-
-  if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
-    goto missing_timestamp;
-
-  /* ignore buffers that are outside of the current segment */
-  start = GST_BUFFER_TIMESTAMP (buffer);
-
-  if (!GST_BUFFER_DURATION_IS_VALID (buffer)) {
-    stop = GST_CLOCK_TIME_NONE;
-  } else {
-    stop = start + GST_BUFFER_DURATION (buffer);
-  }
-
-  GST_LOG_OBJECT (overlay, "%" GST_SEGMENT_FORMAT "  BUFFER: ts=%"
-      GST_TIME_FORMAT ", end=%" GST_TIME_FORMAT, overlay->segment,
-      GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
-
-  /* segment_clip() will adjust start unconditionally to segment_start if
-   * no stop time is provided, so handle this ourselves */
-  if (stop == GST_CLOCK_TIME_NONE && start < overlay->segment->start)
-    goto out_of_segment;
-
-  in_seg = gst_segment_clip (overlay->segment, GST_FORMAT_TIME, start, stop,
-      &clip_start, &clip_stop);
-
-  if (!in_seg)
-    goto out_of_segment;
-
-  /* if the buffer is only partially in the segment, fix up stamps */
-  if (clip_start != start || (stop != -1 && clip_stop != stop)) {
-    GST_DEBUG_OBJECT (overlay, "clipping buffer timestamp/duration to segment");
-    buffer = gst_buffer_make_metadata_writable (buffer);
-    GST_BUFFER_TIMESTAMP (buffer) = clip_start;
-    if (stop != -1)
-      GST_BUFFER_DURATION (buffer) = clip_stop - clip_start;
-  }
-
-  /* now, after we've done the clipping, fix up end time if there's no
-   * duration (we only use those estimated values internally though, we
-   * don't want to set bogus values on the buffer itself) */
-  if (stop == -1) {
-    GstStructure *s;
-    gint fps_num, fps_denom;
-
-    s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
-    if (gst_structure_get_fraction (s, "framerate", &fps_num, &fps_denom)) {
-      GST_DEBUG_OBJECT (overlay, "estimating duration based on framerate");
-      stop = start + gst_util_uint64_scale_int (GST_SECOND, fps_denom, fps_num);
-    } else {
-      GST_WARNING_OBJECT (overlay, "no duration, assuming minimal duration");
-      stop = start + 1;         /* we need to assume some interval */
-    }
-  }
-
-wait_for_text_buf:
-
-  GST_OBJECT_LOCK (overlay);
-
-  if (overlay->video_flushing)
-    goto flushing;
-
-  if (overlay->silent) {
-    GST_OBJECT_UNLOCK (overlay);
-    ret = gst_pad_push (overlay->srcpad, buffer);
-
-    /* Update last_stop */
-    gst_segment_set_last_stop (overlay->segment, GST_FORMAT_TIME, clip_start);
-
-    return ret;
-  }
-
-  /* Text pad not linked, rendering internal text */
-  if (!overlay->text_linked) {
-    if (klass->get_text) {
-      text = klass->get_text (overlay, buffer);
-    } else {
-      text = g_strdup (overlay->default_text);
-    }
-
-    GST_LOG_OBJECT (overlay, "Text pad not linked, rendering default "
-        "text: '%s'", GST_STR_NULL (text));
-
-    GST_OBJECT_UNLOCK (overlay);
-
-    if (text != NULL && *text != '\0') {
-      /* Render and push */
-      gst_text_overlay_render_text (overlay, text, -1);
-      ret = gst_text_overlay_push_frame (overlay, buffer);
-    } else {
-      /* Invalid or empty string */
-      ret = gst_pad_push (overlay->srcpad, buffer);
-    }
-  } else {
-    /* Text pad linked, check if we have a text buffer queued */
-    if (overlay->text_buffer) {
-      gboolean pop_text = FALSE;
-      gint64 text_start, text_end;
-
-      /* if the text buffer isn't stamped right, pop it off the
-       * queue and display it for the current video frame only */
-      if (!GST_BUFFER_TIMESTAMP_IS_VALID (overlay->text_buffer) ||
-          !GST_BUFFER_DURATION_IS_VALID (overlay->text_buffer)) {
-        GST_WARNING_OBJECT (overlay,
-            "Got text buffer with invalid timestamp or duration");
-        text_start = start;
-        text_end = stop;
-        pop_text = TRUE;
-      } else {
-        text_start = GST_BUFFER_TIMESTAMP (overlay->text_buffer);
-        text_end = text_start + GST_BUFFER_DURATION (overlay->text_buffer);
-      }
-
-      GST_LOG_OBJECT (overlay, "T: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (text_start), GST_TIME_ARGS (text_end));
-      GST_LOG_OBJECT (overlay, "V: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
-
-      /* Text too old or in the future */
-      if (text_end <= start) {
-        /* text buffer too old, get rid of it and do nothing  */
-        GST_LOG_OBJECT (overlay, "text buffer too old, popping");
-        pop_text = FALSE;
-        gst_text_overlay_pop_text (overlay);
-        GST_OBJECT_UNLOCK (overlay);
-        goto wait_for_text_buf;
-      } else if (stop <= text_start) {
-        GST_LOG_OBJECT (overlay, "text in future, pushing video buf");
-        GST_OBJECT_UNLOCK (overlay);
-        /* Push the video frame */
-        ret = gst_pad_push (overlay->srcpad, buffer);
-      } else {
-        gchar *in_text;
-        gsize in_size;
-
-        in_text = (gchar *) GST_BUFFER_DATA (overlay->text_buffer);
-        in_size = GST_BUFFER_SIZE (overlay->text_buffer);
-
-        /* g_markup_escape_text() absolutely requires valid UTF8 input, it
-         * might crash otherwise. We don't fall back on GST_SUBTITLE_ENCODING
-         * here on purpose, this is something that needs fixing upstream */
-        if (!g_utf8_validate (in_text, in_size, NULL)) {
-          const gchar *end = NULL;
-
-          GST_WARNING_OBJECT (overlay, "received invalid UTF-8");
-          in_text = g_strndup (in_text, in_size);
-          while (!g_utf8_validate (in_text, in_size, &end) && end)
-            *((gchar *) end) = '*';
-        }
-
-        /* Get the string */
-        if (overlay->have_pango_markup) {
-          text = g_strndup (in_text, in_size);
-        } else {
-          text = g_markup_escape_text (in_text, in_size);
-        }
-
-        if (text != NULL && *text != '\0') {
-          gint text_len = strlen (text);
-
-          while (text_len > 0 && (text[text_len - 1] == '\n' ||
-                  text[text_len - 1] == '\r')) {
-            --text_len;
-          }
-          GST_DEBUG_OBJECT (overlay, "Rendering text '%*s'", text_len, text);
-          gst_text_overlay_render_text (overlay, text, text_len);
-        } else {
-          GST_DEBUG_OBJECT (overlay, "No text to render (empty buffer)");
-          gst_text_overlay_render_text (overlay, " ", 1);
-        }
-
-        if (in_text != (gchar *) GST_BUFFER_DATA (overlay->text_buffer))
-          g_free (in_text);
-
-        GST_OBJECT_UNLOCK (overlay);
-        ret = gst_text_overlay_push_frame (overlay, buffer);
-
-        if (text_end <= stop) {
-          GST_LOG_OBJECT (overlay, "text buffer not needed any longer");
-          pop_text = TRUE;
-        }
-      }
-      if (pop_text) {
-        GST_OBJECT_LOCK (overlay);
-        gst_text_overlay_pop_text (overlay);
-        GST_OBJECT_UNLOCK (overlay);
-      }
-    } else {
-      gboolean wait_for_text_buf = TRUE;
-
-      if (overlay->text_eos)
-        wait_for_text_buf = FALSE;
-
-      /* Text pad linked, but no text buffer available - what now? */
-      if (overlay->text_segment.format == GST_FORMAT_TIME) {
-        if (GST_BUFFER_TIMESTAMP (buffer) < overlay->text_segment.start ||
-            GST_BUFFER_TIMESTAMP (buffer) < overlay->text_segment.last_stop) {
-          wait_for_text_buf = FALSE;
-        }
-      }
-
-      if (wait_for_text_buf) {
-        GST_DEBUG_OBJECT (overlay, "no text buffer, need to wait for one");
-        GST_TEXT_OVERLAY_WAIT (overlay);
-        GST_DEBUG_OBJECT (overlay, "resuming");
-        GST_OBJECT_UNLOCK (overlay);
-        goto wait_for_text_buf;
-      } else {
-        GST_OBJECT_UNLOCK (overlay);
-        GST_LOG_OBJECT (overlay, "no need to wait for a text buffer");
-        ret = gst_pad_push (overlay->srcpad, buffer);
-      }
-    }
-  }
-
-  g_free (text);
-
-  /* Update last_stop */
-  gst_segment_set_last_stop (overlay->segment, GST_FORMAT_TIME, clip_start);
-
-  return ret;
-
-missing_timestamp:
-  {
-    GST_WARNING_OBJECT (overlay, "buffer without timestamp, discarding");
-    gst_buffer_unref (buffer);
-    return GST_FLOW_OK;
-  }
-
-flushing:
-  {
-    GST_OBJECT_UNLOCK (overlay);
-    GST_DEBUG_OBJECT (overlay, "flushing, discarding buffer");
-    gst_buffer_unref (buffer);
-    return GST_FLOW_WRONG_STATE;
-  }
-
-out_of_segment:
-  {
-    GST_DEBUG_OBJECT (overlay, "buffer out of segment, discarding");
-    gst_buffer_unref (buffer);
-    return GST_FLOW_OK;
-  }
-}
-
-static GstStateChangeReturn
-gst_text_overlay_change_state (GstElement * element, GstStateChange transition)
-{
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstTextOverlay *overlay = GST_TEXT_OVERLAY (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      GST_OBJECT_LOCK (overlay);
-      overlay->text_flushing = TRUE;
-      overlay->video_flushing = TRUE;
-      /* pop_text will broadcast on the GCond and thus also make the video
-       * chain exit if it's waiting for a text buffer */
-      gst_text_overlay_pop_text (overlay);
-      GST_OBJECT_UNLOCK (overlay);
-      break;
-    default:
-      break;
-  }
-
-  ret = parent_class->change_state (element, transition);
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      GST_OBJECT_LOCK (overlay);
-      overlay->text_flushing = FALSE;
-      overlay->video_flushing = FALSE;
-      GST_OBJECT_UNLOCK (overlay);
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  if (!gst_element_register (plugin, "textoverlay", GST_RANK_NONE,
-          GST_TYPE_TEXT_OVERLAY) ||
-      !gst_element_register (plugin, "timeoverlay", GST_RANK_NONE,
-          GST_TYPE_TIME_OVERLAY) ||
-      !gst_element_register (plugin, "clockoverlay", GST_RANK_NONE,
-          GST_TYPE_CLOCK_OVERLAY) ||
-      !gst_element_register (plugin, "textrender", GST_RANK_NONE,
-          GST_TYPE_TEXT_RENDER)) {
-    return FALSE;
-  }
-
-  /*texttestsrc_plugin_init(module, plugin); */
-
-  GST_DEBUG_CATEGORY_INIT (pango_debug, "pango", 0, "Pango elements");
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
-    "pango", "Pango-based text rendering and overlay", plugin_init,
-    VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/pango/gsttextoverlay.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-#ifndef __GST_TEXT_OVERLAY_H__
-#define __GST_TEXT_OVERLAY_H__
-
-#include <gst/gst.h>
-#include <pango/pangoft2.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TEXT_OVERLAY            (gst_text_overlay_get_type())
-#define GST_TEXT_OVERLAY(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),\
-                                         GST_TYPE_TEXT_OVERLAY, GstTextOverlay))
-#define GST_TEXT_OVERLAY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),\
-                                         GST_TYPE_TEXT_OVERLAY,GstTextOverlayClass))
-#define GST_TEXT_OVERLAY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),\
-                                         GST_TYPE_TEXT_OVERLAY, GstTextOverlayClass))
-#define GST_IS_TEXT_OVERLAY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
-                                         GST_TYPE_TEXT_OVERLAY))
-#define GST_IS_TEXT_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
-                                         GST_TYPE_TEXT_OVERLAY))
-
-typedef struct _GstTextOverlay      GstTextOverlay;
-typedef struct _GstTextOverlayClass GstTextOverlayClass;
-
-/**
- * GstTextOverlayVAlign:
- * @GST_TEXT_OVERLAY_VALIGN_BASELINE: draw text on the baseline
- * @GST_TEXT_OVERLAY_VALIGN_BOTTOM: draw text on the bottom
- * @GST_TEXT_OVERLAY_VALIGN_TOP: draw test on top
- *
- * Vertical alignment of the text.
- */
-typedef enum {
-    GST_TEXT_OVERLAY_VALIGN_BASELINE,
-    GST_TEXT_OVERLAY_VALIGN_BOTTOM,
-    GST_TEXT_OVERLAY_VALIGN_TOP
-} GstTextOverlayVAlign;
-
-/**
- * GstTextOverlayHAlign:
- * @GST_TEXT_OVERLAY_HALIGN_LEFT: align text left
- * @GST_TEXT_OVERLAY_HALIGN_CENTER: align text center
- * @GST_TEXT_OVERLAY_HALIGN_RIGHT: align text right
- *
- * Horizontal alignment of the text.
- */
-typedef enum {
-    GST_TEXT_OVERLAY_HALIGN_LEFT,
-    GST_TEXT_OVERLAY_HALIGN_CENTER,
-    GST_TEXT_OVERLAY_HALIGN_RIGHT
-} GstTextOverlayHAlign;
-
-/**
- * GstTextOverlayWrapMode:
- * @GST_TEXT_OVERLAY_WRAP_MODE_NONE: no wrapping
- * @GST_TEXT_OVERLAY_WRAP_MODE_WORD: do word wrapping
- * @GST_TEXT_OVERLAY_WRAP_MODE_CHAR: do char wrapping
- * @GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR: do word and char wrapping
- *
- * Whether to wrap the text and if so how.
- */
-typedef enum {
-    GST_TEXT_OVERLAY_WRAP_MODE_NONE = -1,
-    GST_TEXT_OVERLAY_WRAP_MODE_WORD = PANGO_WRAP_WORD,
-    GST_TEXT_OVERLAY_WRAP_MODE_CHAR = PANGO_WRAP_CHAR,
-    GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR = PANGO_WRAP_WORD_CHAR
-} GstTextOverlayWrapMode;
-
-/**
- * GstTextOverlayLineAlign:
- * @GST_TEXT_OVERLAY_LINE_ALIGN_LEFT: lines are left-aligned
- * @GST_TEXT_OVERLAY_LINE_ALIGN_CENTER: lines are center-aligned
- * @GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT: lines are right-aligned
- *
- * Alignment of text lines relative to each other
- */
-typedef enum {
-    GST_TEXT_OVERLAY_LINE_ALIGN_LEFT = PANGO_ALIGN_LEFT,
-    GST_TEXT_OVERLAY_LINE_ALIGN_CENTER = PANGO_ALIGN_CENTER,
-    GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT = PANGO_ALIGN_RIGHT
-} GstTextOverlayLineAlign;
-
-/**
- * GstTextOverlay:
- *
- * Opaque textoverlay object structure
- */
-struct _GstTextOverlay {
-    GstElement               element;
-
-    GstPad                  *video_sinkpad;
-    GstPad                  *text_sinkpad;
-    GstPad                  *srcpad;
-
-    GstSegment              *segment;
-    GstSegment               text_segment;
-    GstBuffer               *text_buffer;
-    gboolean                text_linked;
-    gboolean                video_flushing;
-    gboolean                text_flushing;
-    gboolean                text_eos;
-
-    GCond                   *cond;  /* to signal removal of a queued text
-                                     * buffer, arrival of a text buffer,
-                                     * a text segment update, or a change
-                                     * in status (e.g. shutdown, flushing) */
-
-    gint                     width;
-    gint                     height;
-    gint                     fps_n;
-    gint                     fps_d;
-
-    GstTextOverlayVAlign     valign;
-    GstTextOverlayHAlign     halign;
-    GstTextOverlayWrapMode   wrap_mode;
-    GstTextOverlayLineAlign  line_align;
-
-    gint                     xpad;
-    gint                     ypad;
-    gint                     deltax;
-    gint                     deltay;
-    gchar                   *default_text;
-    gboolean                 want_shading;
-    gboolean                 silent;
-
-    PangoLayout             *layout;
-    FT_Bitmap                bitmap;
-    gint                     bitmap_buffer_size;
-    gint                     baseline_y;
-
-    gboolean                 need_render;
-
-    gint                     shading_value;  /* for timeoverlay subclass */
-
-    gboolean                 have_pango_markup;
-};
-
-struct _GstTextOverlayClass {
-    GstElementClass parent_class;
-
-    PangoContext *pango_context;
-
-    gchar *     (*get_text) (GstTextOverlay *overlay, GstBuffer *video_frame);
-};
-
-GType gst_text_overlay_get_type(void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GST_TEXT_OVERLAY_H */
--- a/gst_plugins_base/ext/pango/gsttextrender.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- *
- * 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.
- */
-
-
-/**
- * SECTION:element-textrender
- * @see_also: #GstTextOverlay
- *
- * <refsect2>
- * <para>
- * This plugin renders text received on the text sink pad to a video
- * buffer (retaining the alpha channel), so it can later be overlayed
- * on top of video streams using other elements.
- * </para>
- * <para>
- * The text can contain newline characters. (FIXME: What about text 
- * wrapping? It does not make sense in this context)
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=subtitles.srt ! subparse ! textrender ! xvimagesink
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gst/gst.h>
-#include <gst/video/video.h>
-
-#include "gsttextrender.h"
-
-GST_DEBUG_CATEGORY_EXTERN (pango_debug);
-#define GST_CAT_DEFAULT pango_debug
-
-static const GstElementDetails text_render_details =
-GST_ELEMENT_DETAILS ("Text renderer",
-    "Filter/Editor/Video",
-    "Renders a text string to an image bitmap",
-    "David Schleef <ds@schleef.org>, "
-    "Ronald S. Bultje <rbultje@ronald.bitfreak.net>");
-
-enum
-{
-  ARG_0,
-  ARG_FONT_DESC
-};
-
-
-static GstStaticPadTemplate src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV"))
-    );
-
-static GstStaticPadTemplate sink_template_factory =
-    GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("text/x-pango-markup; text/plain")
-    );
-
-GST_BOILERPLATE (GstTextRender, gst_text_render, GstElement, GST_TYPE_ELEMENT)
-
-     static void gst_text_render_finalize (GObject * object);
-     static void gst_text_render_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-
-     static void gst_text_render_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_template_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_template_factory));
-
-  gst_element_class_set_details (element_class, &text_render_details);
-}
-
-static void
-gst_text_render_class_init (GstTextRenderClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->finalize = gst_text_render_finalize;
-  gobject_class->set_property = gst_text_render_set_property;
-
-  klass->pango_context = pango_ft2_get_context (72, 72);
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FONT_DESC,
-      g_param_spec_string ("font-desc", "font description",
-          "Pango font description of font "
-          "to be used for rendering. "
-          "See documentation of "
-          "pango_font_description_from_string"
-          " for syntax.", "", G_PARAM_WRITABLE));
-}
-
-
-static void
-resize_bitmap (GstTextRender * render, gint width, gint height)
-{
-  FT_Bitmap *bitmap = &render->bitmap;
-  gint pitch = (width | 3) + 1;
-  gint size = pitch * height;
-
-  /* no need to keep reallocating; just keep the maximum size so far */
-  if (size <= render->bitmap_buffer_size) {
-    bitmap->rows = height;
-    bitmap->width = width;
-    bitmap->pitch = pitch;
-    memset (bitmap->buffer, 0, render->bitmap_buffer_size);
-    return;
-  }
-  if (!bitmap->buffer) {
-    /* initialize */
-    bitmap->pixel_mode = ft_pixel_mode_grays;
-    bitmap->num_grays = 256;
-  }
-  if (bitmap->buffer)
-    bitmap->buffer = g_realloc (bitmap->buffer, size);
-  else
-    bitmap->buffer = g_malloc (size);
-  bitmap->rows = height;
-  bitmap->width = width;
-  bitmap->pitch = pitch;
-  memset (bitmap->buffer, 0, size);
-  render->bitmap_buffer_size = size;
-}
-
-static void
-gst_text_render_render_text (GstTextRender * render)
-{
-  PangoRectangle ink_rect, logical_rect;
-
-  pango_layout_get_pixel_extents (render->layout, &ink_rect, &logical_rect);
-  resize_bitmap (render, ink_rect.width, ink_rect.height + ink_rect.y);
-  pango_ft2_render_layout (&render->bitmap, render->layout, -ink_rect.x, 0);
-  render->baseline_y = ink_rect.y;
-}
-
-static gboolean
-gst_text_render_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstTextRender *render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
-  GstStructure *structure;
-  gboolean ret = FALSE;
-  gint width = 0, height = 0;
-
-  structure = gst_caps_get_structure (caps, 0);
-  gst_structure_get_int (structure, "width", &width);
-  gst_structure_get_int (structure, "height", &height);
-
-  GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps);
-
-  if (width >= render->bitmap.width && height >= render->bitmap.rows) {
-    render->width = width;
-    render->height = height;
-    ret = TRUE;
-  }
-
-  gst_object_unref (render);
-  return ret;
-}
-
-static void
-gst_text_render_fixate_caps (GstPad * pad, GstCaps * caps)
-{
-  GstTextRender *render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
-  GstStructure *s = gst_caps_get_structure (caps, 0);
-
-  GST_DEBUG ("Fixating caps %" GST_PTR_FORMAT, caps);
-  gst_structure_fixate_field_nearest_int (s, "width", render->bitmap.width);
-  gst_structure_fixate_field_nearest_int (s, "height", render->bitmap.rows);
-  GST_DEBUG ("Fixated to    %" GST_PTR_FORMAT, caps);
-
-  gst_object_unref (render);
-}
-
-static void
-gst_text_renderer_bitmap_to_ayuv (GstTextRender * render, FT_Bitmap * bitmap,
-    guchar * pixbuf)
-{
-  int y;                        /* text bitmap coordinates */
-  int rowinc, bit_rowinc;
-  guchar *p, *bitp;
-  guchar v;
-
-  rowinc = render->width - bitmap->width;
-  bit_rowinc = bitmap->pitch - bitmap->width;
-
-  bitp = bitmap->buffer;
-  p = pixbuf;
-
-  for (y = 0; y < bitmap->rows; y++) {
-    int n;
-
-    for (n = bitmap->width; n > 0; --n) {
-      v = *bitp;
-      if (v) {
-        p[0] = v;
-        p[1] = 255;
-        p[2] = 0x80;
-        p[3] = 0x80;
-      }
-      p += 4;
-      bitp++;
-    }
-    p += rowinc * 4;
-    bitp += bit_rowinc;
-  }
-}
-
-
-static GstFlowReturn
-gst_text_render_chain (GstPad * pad, GstBuffer * inbuf)
-{
-  GstTextRender *render;
-  GstFlowReturn ret;
-  GstBuffer *outbuf;
-  GstCaps *caps = NULL;
-  guint8 *data = GST_BUFFER_DATA (inbuf);
-  guint size = GST_BUFFER_SIZE (inbuf);
-  gint n;
-
-  render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
-
-  /* somehow pango barfs over "\0" buffers... */
-  while (size > 0 &&
-      (data[size - 1] == '\r' ||
-          data[size - 1] == '\n' || data[size - 1] == '\0')) {
-    size--;
-  }
-
-  /* render text */
-  GST_DEBUG ("rendering '%*s'", size, data);
-  pango_layout_set_markup (render->layout, (gchar *) data, size);
-  gst_text_render_render_text (render);
-
-  caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC,
-      GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), "width", G_TYPE_INT,
-      render->bitmap.width, "height", G_TYPE_INT, render->bitmap.rows,
-      "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
-
-  if (!gst_pad_set_caps (render->srcpad, caps)) {
-    gst_caps_unref (caps);
-    GST_ELEMENT_ERROR (render, CORE, NEGOTIATION, (NULL), (NULL));
-    ret = GST_FLOW_ERROR;
-    goto done;
-  }
-
-  GST_DEBUG ("Allocating AYUV buffer WxH = %dx%d", render->width,
-      render->height);
-  ret =
-      gst_pad_alloc_buffer_and_set_caps (render->srcpad, GST_BUFFER_OFFSET_NONE,
-      render->width * render->height * 4, caps, &outbuf);
-
-  if (ret != GST_FLOW_OK)
-    goto done;
-
-  gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
-  data = GST_BUFFER_DATA (outbuf);
-
-  for (n = 0; n < render->width * render->height; n++) {
-    data[n * 4] = 0;
-    data[n * 4 + 1] = 0;
-    data[n * 4 + 2] = data[n * 4 + 3] = 128;
-  }
-
-  if (render->bitmap.buffer) {
-    gst_text_renderer_bitmap_to_ayuv (render, &render->bitmap, data);
-  }
-
-  ret = gst_pad_push (render->srcpad, outbuf);
-
-done:
-  if (caps)
-    gst_caps_unref (caps);
-  gst_buffer_unref (inbuf);
-  gst_object_unref (render);
-  return ret;
-}
-
-static void
-gst_text_render_finalize (GObject * object)
-{
-  GstTextRender *render = GST_TEXT_RENDER (object);
-
-  g_free (render->bitmap.buffer);
-
-  if (render->layout)
-    g_object_unref (render->layout);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_text_render_init (GstTextRender * render, GstTextRenderClass * klass)
-{
-  GstPadTemplate *template;
-
-  /* sink */
-  template = gst_static_pad_template_get (&sink_template_factory);
-  render->sinkpad = gst_pad_new_from_template (template, "sink");
-  gst_object_unref (template);
-  gst_pad_set_chain_function (render->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_text_render_chain));
-  gst_element_add_pad (GST_ELEMENT (render), render->sinkpad);
-
-  /* source */
-  template = gst_static_pad_template_get (&src_template_factory);
-  render->srcpad = gst_pad_new_from_template (template, "src");
-  gst_object_unref (template);
-  gst_pad_set_fixatecaps_function (render->srcpad,
-      GST_DEBUG_FUNCPTR (gst_text_render_fixate_caps));
-  gst_pad_set_setcaps_function (render->srcpad,
-      GST_DEBUG_FUNCPTR (gst_text_render_setcaps));
-  gst_element_add_pad (GST_ELEMENT (render), render->srcpad);
-
-  render->layout =
-      pango_layout_new (GST_TEXT_RENDER_GET_CLASS (render)->pango_context);
-  memset (&render->bitmap, 0, sizeof (render->bitmap));
-}
-
-static void
-gst_text_render_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstTextRender *render = GST_TEXT_RENDER (object);
-
-  switch (prop_id) {
-    case ARG_FONT_DESC:
-    {
-      PangoFontDescription *desc;
-
-      desc = pango_font_description_from_string (g_value_get_string (value));
-      if (desc) {
-        GST_LOG ("font description set: %s", g_value_get_string (value));
-        GST_OBJECT_LOCK (render);
-        pango_layout_set_font_description (render->layout, desc);
-        pango_font_description_free (desc);
-        gst_text_render_render_text (render);
-        GST_OBJECT_UNLOCK (render);
-      } else {
-        GST_WARNING ("font description parse failed: %s",
-            g_value_get_string (value));
-      }
-      break;
-    }
-
-    default:
-      break;
-  }
-}
--- a/gst_plugins_base/ext/pango/gsttextrender.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#ifndef __GST_TEXT_RENDER_H__
-#define __GST_TEXT_RENDER_H__
-
-#include <gst/gst.h>
-#include <pango/pangoft2.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TEXT_RENDER            (gst_text_render_get_type())
-#define GST_TEXT_RENDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),\
-                                        GST_TYPE_TEXT_RENDER, GstTextRender))
-#define GST_TEXT_RENDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),\
-                                        GST_TYPE_TEXT_RENDER, GstTextRenderClass))
-#define GST_TEXT_RENDER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),\
-                                        GST_TYPE_TEXT_RENDER, GstTextRenderClass))
-#define GST_IS_TEXT_RENDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
-                                        GST_TYPE_TEXT_RENDER))
-#define GST_IS_TEXT_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
-                                        GST_TYPE_TEXT_RENDER))
-
-typedef struct _GstTextRender      GstTextRender;
-typedef struct _GstTextRenderClass GstTextRenderClass;
-
-/**
- * GstTextRender:
- *
- * Opaque textrender data structure.
- */
-struct _GstTextRender {
-    GstElement            element;
-
-    GstPad               *sinkpad, *srcpad;
-    gint                  width;
-    gint                  height;
-    PangoLayout          *layout;
-    FT_Bitmap             bitmap;
-    gint                  bitmap_buffer_size;
-    gint                  baseline_y;
-};
-
-struct _GstTextRenderClass {
-    GstElementClass parent_class;
-
-    PangoContext *pango_context;
-};
-
-GType gst_text_render_get_type(void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GST_TEXT_RENDER_H */
--- a/gst_plugins_base/ext/pango/gsttimeoverlay.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> Tim-Philipp Müller <tim@centricular.net>
- *
- * 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.
- */
-
-/**
- * SECTION:element-timeoverlay
- * @see_also: #GstTextOverlay, #GstClockOverlay
- *
- * <refsect2>
- * <para>
- * This element overlays the buffer time stamps of a video stream on
- * top of itself. You can position the text and configure the font details
- * using the properties of the #GstTextOverlay class. By default, the
- * time stamp is displayed in the top left corner of the picture, with some
- * padding to the left and to the top.
- * </para>
- * <para>
- * Here is a simple pipeline that displays the time stamps in the top left
- * corner of the video picture:
- * <programlisting>
- * gst-launch -v videotestsrc ! timeoverlay ! xvimagesink
- * </programlisting>
- * </para>
- * <para>
- * Here is another pipeline that displays the time stamps with some leading
- * text in the bottom right corner of the video picture, with the background
- * of the text being shaded in order to make it more legible on top of a
- * bright video background:
- * <programlisting>
- * gst-launch -v videotestsrc ! timeoverlay halign=right valign=bottom text="Stream time:" shaded-background=true ! xvimagesink
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/video/video.h>
-
-#include <gsttimeoverlay.h>
-
-static const GstElementDetails time_overlay_details =
-GST_ELEMENT_DETAILS ("Time overlay",
-    "Filter/Editor/Video",
-    "Overlays buffer time stamps on a video stream",
-    "Tim-Philipp Müller <tim@centricular.net>");
-
-GST_BOILERPLATE (GstTimeOverlay, gst_time_overlay, GstTextOverlay,
-    GST_TYPE_TEXT_OVERLAY)
-
-     static void gst_time_overlay_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &time_overlay_details);
-}
-
-static gchar *
-gst_time_overlay_render_time (GstTimeOverlay * overlay, GstClockTime time)
-{
-  guint hours, mins, secs, msecs;
-
-  if (!GST_CLOCK_TIME_IS_VALID (time))
-    return g_strdup ("");
-
-  hours = (guint) (time / (GST_SECOND * 60 * 60));
-  mins = (guint) ((time / (GST_SECOND * 60)) % 60);
-  secs = (guint) ((time / GST_SECOND) % 60);
-  msecs = (guint) ((time % GST_SECOND) / (1000 * 1000));
-
-  return g_strdup_printf ("%u:%02u:%02u.%03u", hours, mins, secs, msecs);
-}
-
-/* Called with lock held */
-static gchar *
-gst_time_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
-  GstClockTime time = GST_BUFFER_TIMESTAMP (video_frame);
-  gchar *time_str, *txt, *ret;
-
-  overlay->need_render = TRUE;
-
-  if (!GST_CLOCK_TIME_IS_VALID (time)) {
-    GST_DEBUG ("buffer without valid timestamp");
-    return g_strdup ("");
-  }
-
-  GST_DEBUG ("buffer with timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
-
-  txt = g_strdup (overlay->default_text);
-
-  time_str = gst_time_overlay_render_time (GST_TIME_OVERLAY (overlay), time);
-  if (txt != NULL && *txt != '\0') {
-    ret = g_strdup_printf ("%s %s", txt, time_str);
-  } else {
-    ret = time_str;
-    time_str = NULL;
-  }
-
-  g_free (txt);
-  g_free (time_str);
-
-  return ret;
-}
-
-static void
-gst_time_overlay_class_init (GstTimeOverlayClass * klass)
-{
-  GstTextOverlayClass *gsttextoverlay_class;
-
-  gsttextoverlay_class = (GstTextOverlayClass *) klass;
-
-  gsttextoverlay_class->get_text = gst_time_overlay_get_text;
-}
-
-static void
-gst_time_overlay_init (GstTimeOverlay * overlay, GstTimeOverlayClass * klass)
-{
-  PangoFontDescription *font_description;
-  GstTextOverlay *textoverlay;
-  PangoContext *context;
-
-  textoverlay = GST_TEXT_OVERLAY (overlay);
-
-  context = GST_TEXT_OVERLAY_CLASS (klass)->pango_context;
-
-  pango_context_set_language (context, pango_language_from_string ("en_US"));
-  pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
-
-  font_description = pango_font_description_new ();
-  pango_font_description_set_family_static (font_description, "Monospace");
-  pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL);
-  pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL);
-  pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL);
-  pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL);
-  pango_font_description_set_size (font_description, 18 * PANGO_SCALE);
-  pango_context_set_font_description (context, font_description);
-  pango_font_description_free (font_description);
-
-  textoverlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP;
-  textoverlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT;
-}
--- a/gst_plugins_base/ext/pango/gsttimeoverlay.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> Tim-Philipp Müller <tim@centricular.net>
- *
- * 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_TIME_OVERLAY_H__
-#define __GST_TIME_OVERLAY_H__
-
-#include "gsttextoverlay.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TIME_OVERLAY \
-  (gst_time_overlay_get_type())
-#define GST_TIME_OVERLAY(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TIME_OVERLAY,GstTimeOverlay))
-#define GST_TIME_OVERLAY_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TIME_OVERLAY,GstTimeOverlayClass))
-#define GST_IS_TIME_OVERLAY(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIME_OVERLAY))
-#define GST_IS_TIME_OVERLAY_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TIME_OVERLAY))
-
-typedef struct _GstTimeOverlay GstTimeOverlay;
-typedef struct _GstTimeOverlayClass GstTimeOverlayClass;
-
-/**
- * GstTimeOverlay:
- *
- * Opaque timeoverlay data structure.
- */
-struct _GstTimeOverlay {
-  GstTextOverlay textoverlay;
-};
-
-struct _GstTimeOverlayClass {
-  GstTextOverlayClass parent_class;
-};
-
-GType gst_time_overlay_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_TIME_OVERLAY_H__ */
-
--- a/gst_plugins_base/ext/theora/gsttheoradec.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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_THEORADEC_H__
-#define __GST_THEORADEC_H__
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <theora/theora.h>
-#include <string.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_THEORA_DEC \
-  (gst_theora_dec_get_type())
-#define GST_THEORA_DEC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_DEC,GstTheoraDec))
-#define GST_THEORA_DEC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_DEC,GstTheoraDecClass))
-#define GST_IS_THEORA_DEC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_DEC))
-#define GST_IS_THEORA_DEC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_DEC))
-
-typedef struct _GstTheoraDec GstTheoraDec;
-typedef struct _GstTheoraDecClass GstTheoraDecClass;
-
-/**
- * GstTheoraDec:
- *
- * Opaque object data structure.
- */
-struct _GstTheoraDec
-{
-  GstElement element;
-
-  /* Pads */
-  GstPad *sinkpad;
-  GstPad *srcpad;
-
-  /* theora decoder state */
-  theora_state state;
-  theora_info info;
-  theora_comment comment;
-
-  gboolean have_header;
-  gboolean sent_newsegment;
-  gboolean is_old_bitstream;
-  guint64 granulepos;
-  guint64 granule_shift;
-
-  GstClockTime last_timestamp;
-  guint64 frame_nr; /* unused */
-  gboolean need_keyframe;
-  gint width, height;
-  gint offset_x, offset_y;
-
-  gboolean crop;
-
-  /* list of buffers that need timestamps */
-  GList *queued;
-  /* list of raw output buffers */
-  GList *output;
-  /* gather/decode queues for reverse playback */
-  GList *gather;
-  GList *decode;
-
-  GstTagList *tags;
-
-  /* segment info */ /* with STREAM_LOCK */
-  GstSegment segment;
-  gboolean discont;
-
-  /* QoS stuff */ /* with LOCK*/
-  gdouble proportion;
-  GstClockTime earliest_time;
-};
-
-struct _GstTheoraDecClass
-{
-  GstElementClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GST_THEORADEC_H__ */
--- a/gst_plugins_base/ext/theora/gsttheoraenc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.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_THEORAENC_H__
-#define __GST_THEORAENC_H__
-
-#include <gst/gst.h>
-#include <theora/theora.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_THEORA_ENC \
-  (gst_theora_enc_get_type())
-#define GST_THEORA_ENC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_ENC,GstTheoraEnc))
-#define GST_THEORA_ENC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_ENC,GstTheoraEncClass))
-#define GST_IS_THEORA_ENC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_ENC))
-#define GST_IS_THEORA_ENC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_ENC))
-
-typedef struct _GstTheoraEnc GstTheoraEnc;
-typedef struct _GstTheoraEncClass GstTheoraEncClass;
-
-/**
- * GstTheoraEncBorderMode:
- * @BORDER_NONE: no border
- * @BORDER_BLACK: black border
- * @BORDER_MIRROR: Mirror image in border
- *
- * Border color to add when sizes not multiple of 16. 
- */ 
-typedef enum
-{
-  BORDER_NONE,
-  BORDER_BLACK,
-  BORDER_MIRROR
-}
-GstTheoraEncBorderMode;
-
-/**
- * GstTheoraEnc:
- *
- * Opaque data structure.
- */
-struct _GstTheoraEnc
-{
-  GstElement element;
-
-  GstPad *sinkpad;
-  GstPad *srcpad;
-
-  ogg_stream_state to;
-
-  theora_state state;
-  theora_info info;
-  theora_comment comment;
-  gboolean initialised;
-
-  gboolean center;
-  GstTheoraEncBorderMode border;
-
-  gint video_bitrate;           /* bitrate target for Theora video */
-  gint video_quality;           /* Theora quality selector 0 = low, 63 = high */
-  gboolean quick;
-  gboolean keyframe_auto;
-  gint keyframe_freq;
-  gint keyframe_force;
-  gint keyframe_threshold;
-  gint keyframe_mindistance;
-  gint noise_sensitivity;
-  gint sharpness;
-
-  gint info_width, info_height;
-  gint width, height;
-  gint offset_x, offset_y;
-  gint fps_n, fps_d;
-  GstClockTime next_ts;
-
-  GstClockTime expected_ts;
-  gboolean next_discont;
-
-  guint packetno;
-  guint64 bytes_out;
-  guint64 granulepos_offset;
-  guint64 timestamp_offset;
-  gint granule_shift;  
-};
-
-struct _GstTheoraEncClass
-{
-  GstElementClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GST_THEORAENC_H__ */
-
--- a/gst_plugins_base/ext/theora/gsttheoraparse.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2006 Andy Wingo <wingo@pobox.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_THEORA_PARSE_H__
-#define __GST_THEORA_PARSE_H__
-
-
-#include <gst/gst.h>
-#include <theora/theora.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_THEORA_PARSE \
-  (gst_theora_parse_get_type())
-#define GST_THEORA_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_PARSE,GstTheoraParse))
-#define GST_THEORA_PARSE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_PARSE,GstTheoraParseClass))
-#define GST_IS_THEORA_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_PARSE))
-#define GST_IS_THEORA_PARSE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_PARSE))
-
-typedef struct _GstTheoraParse GstTheoraParse;
-typedef struct _GstTheoraParseClass GstTheoraParseClass;
-
-/**
- * GstTheoraParse:
- *
- * Opaque data structure.
- */
-struct _GstTheoraParse {
-  GstElement            element;
-
-  GstPad *              sinkpad;
-  GstPad *              srcpad;
-
-  guint                 packetno;
-  gboolean              send_streamheader;
-  gboolean              streamheader_received;
-  gboolean		is_old_bitstream;
-  GstBuffer *		streamheader[3];
-
-  GQueue *		event_queue;
-  GQueue *		buffer_queue;
-
-  theora_info		info;
-  theora_comment	comment;
-
-  gint64		prev_frame;
-  gint64		prev_keyframe;
-  guint32		fps_n;
-  guint32		fps_d;
-  gint			shift;
-  gint64		granule_offset;
-
-  GstClockTime		*times;
-  gint			npairs;
-};
-
-struct _GstTheoraParseClass {
-  GstElementClass parent_class;
-};
-
-GType gst_theora_parse_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_THEORA_PARSE_H__ */
--- a/gst_plugins_base/ext/theora/theora.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <gst/gst.h>
-
-extern GType gst_theora_dec_get_type (void);
-extern GType gst_theora_enc_get_type (void);
-extern GType gst_theora_parse_get_type (void);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  if (!gst_element_register (plugin, "theoradec", GST_RANK_PRIMARY,
-          gst_theora_dec_get_type ()))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "theoraenc", GST_RANK_NONE,
-          gst_theora_enc_get_type ()))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "theoraparse", GST_RANK_NONE,
-          gst_theora_parse_get_type ()))
-    return FALSE;
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "theora",
-    "Theora plugin library",
-    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/theora/theoradec.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1547 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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.
- */
-
-/**
- * SECTION:element-theoradec
- * @see_also: theoraenc, oggdemux
- *
- * <refsect2>
- * <para>
- * This element decodes theora streams into raw video
- * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
- * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>, based on the VP3 codec.
- * </para>
- * <para>
- * </para>
- * <title>Example pipeline</title>
- * <programlisting>
- * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! xvimagesink
- * </programlisting>
- * This example pipeline will decode an ogg stream and decodes the theora video. Refer to
- * the theoraenc example to create the ogg file.
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "gsttheoradec.h"
-#include <gst/tag/tag.h>
-
-#define GST_CAT_DEFAULT theoradec_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-#define THEORA_DEF_CROP         TRUE
-enum
-{
-  ARG_0,
-  ARG_CROP
-};
-
-static const GstElementDetails theora_dec_details =
-GST_ELEMENT_DETAILS ("Theora video decoder",
-    "Codec/Decoder/Video",
-    "decode raw theora streams to raw YUV video",
-    "Benjamin Otte <in7y118@public.uni-hamburg.de>, "
-    "Wim Taymans <wim@fluendo.com>");
-
-static GstStaticPadTemplate theora_dec_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-yuv, "
-        "format = (fourcc) I420, "
-        "framerate = (fraction) [0/1, MAX], "
-        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
-    );
-
-static GstStaticPadTemplate theora_dec_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-theora")
-    );
-
-GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT);
-
-static void theora_dec_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void theora_dec_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-
-static gboolean theora_dec_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn theora_dec_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn theora_dec_change_state (GstElement * element,
-    GstStateChange transition);
-static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event);
-static gboolean theora_dec_src_query (GstPad * pad, GstQuery * query);
-static gboolean theora_dec_src_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value);
-static gboolean theora_dec_sink_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value);
-static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query);
-
-#if 0
-static const GstFormat *theora_get_formats (GstPad * pad);
-#endif
-#if 0
-static const GstEventMask *theora_get_event_masks (GstPad * pad);
-#endif
-static const GstQueryType *theora_get_query_types (GstPad * pad);
-
-
-static void
-gst_theora_dec_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&theora_dec_src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&theora_dec_sink_factory));
-  gst_element_class_set_details (element_class, &theora_dec_details);
-}
-
-static void
-gst_theora_dec_class_init (GstTheoraDecClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->set_property = theora_dec_set_property;
-  gobject_class->get_property = theora_dec_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_CROP,
-      g_param_spec_boolean ("crop", "Crop",
-          "Crop the image to the visible region", THEORA_DEF_CROP,
-          (GParamFlags) G_PARAM_READWRITE));
-
-  gstelement_class->change_state = theora_dec_change_state;
-
-  GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
-}
-
-static void
-gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
-{
-  dec->sinkpad =
-      gst_pad_new_from_static_template (&theora_dec_sink_factory, "sink");
-  gst_pad_set_query_function (dec->sinkpad, theora_dec_sink_query);
-  gst_pad_set_event_function (dec->sinkpad, theora_dec_sink_event);
-  gst_pad_set_chain_function (dec->sinkpad, theora_dec_chain);
-  gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
-
-  dec->srcpad =
-      gst_pad_new_from_static_template (&theora_dec_src_factory, "src");
-  gst_pad_set_event_function (dec->srcpad, theora_dec_src_event);
-  gst_pad_set_query_type_function (dec->srcpad, theora_get_query_types);
-  gst_pad_set_query_function (dec->srcpad, theora_dec_src_query);
-  gst_pad_use_fixed_caps (dec->srcpad);
-
-  gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
-
-  dec->crop = THEORA_DEF_CROP;
-  dec->gather = NULL;
-  dec->decode = NULL;
-  dec->queued = NULL;
-}
-
-static void
-gst_theora_dec_reset (GstTheoraDec * dec)
-{
-  dec->need_keyframe = TRUE;
-  dec->sent_newsegment = FALSE;
-  dec->last_timestamp = -1;
-  dec->granulepos = -1;
-  dec->discont = TRUE;
-  dec->frame_nr = -1;
-  gst_segment_init (&dec->segment, GST_FORMAT_TIME);
-
-  GST_OBJECT_LOCK (dec);
-  dec->proportion = 1.0;
-  dec->earliest_time = -1;
-  GST_OBJECT_UNLOCK (dec);
-
-  g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->queued);
-  dec->queued = NULL;
-  g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->gather);
-  dec->gather = NULL;
-  g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->decode);
-  dec->decode = NULL;
-
-  if (dec->tags) {
-    gst_tag_list_free (dec->tags);
-    dec->tags = NULL;
-  }
-}
-
-static int
-_theora_ilog (unsigned int v)
-{
-  int ret = 0;
-
-  while (v) {
-    ret++;
-    v >>= 1;
-  }
-  return (ret);
-}
-
-/* Return the frame number (starting from zero) corresponding to this 
- * granulepos */
-static gint64
-_theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
-{
-  guint ilog;
-  gint framenum;
-
-  if (granulepos == -1)
-    return -1;
-
-  ilog = dec->granule_shift;
-
-  /* granulepos is last ilog bits for counting pframes since last iframe and 
-   * bits in front of that for the framenumber of the last iframe. */
-  framenum = granulepos >> ilog;
-  framenum += granulepos - (framenum << ilog);
-
-  /* This is 0-based for old bitstreams, 1-based for new. Fix up. */
-  if (!dec->is_old_bitstream)
-    framenum -= 1;
-
-  GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog);
-
-  return framenum;
-}
-
-/* Return the frame start time corresponding to this granulepos */
-static GstClockTime
-_theora_granule_start_time (GstTheoraDec * dec, gint64 granulepos)
-{
-  gint64 framecount;
-
-  /* invalid granule results in invalid time */
-  if (granulepos == -1)
-    return -1;
-
-  /* get framecount */
-  framecount = _theora_granule_frame (dec, granulepos);
-
-  return gst_util_uint64_scale_int (framecount * GST_SECOND,
-      dec->info.fps_denominator, dec->info.fps_numerator);
-}
-
-static gint64
-_inc_granulepos (GstTheoraDec * dec, gint64 granulepos)
-{
-  gint framecount;
-
-  if (granulepos == -1)
-    return -1;
-
-  framecount = _theora_granule_frame (dec, granulepos);
-
-  return (framecount + 1 +
-      (dec->is_old_bitstream ? 0 : 1)) << dec->granule_shift;
-}
-
-#if 0
-static const GstFormat *
-theora_get_formats (GstPad * pad)
-{
-  static GstFormat src_formats[] = {
-    GST_FORMAT_DEFAULT,         /* frames in this case */
-    GST_FORMAT_TIME,
-    GST_FORMAT_BYTES,
-    0
-  };
-  static GstFormat sink_formats[] = {
-    GST_FORMAT_DEFAULT,
-    GST_FORMAT_TIME,
-    0
-  };
-
-  return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
-}
-#endif
-
-#if 0
-static const GstEventMask *
-theora_get_event_masks (GstPad * pad)
-{
-  static const GstEventMask theora_src_event_masks[] = {
-    {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
-    {0,}
-  };
-
-  return theora_src_event_masks;
-}
-#endif
-
-static const GstQueryType *
-theora_get_query_types (GstPad * pad)
-{
-  static const GstQueryType theora_src_query_types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    0
-  };
-
-  return theora_src_query_types;
-}
-
-
-static gboolean
-theora_dec_src_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  GstTheoraDec *dec;
-  guint64 scale = 1;
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
-  /* we need the info part before we can done something */
-  if (!dec->have_header)
-    goto no_header;
-
-  switch (src_format) {
-    case GST_FORMAT_BYTES:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          *dest_value = gst_util_uint64_scale_int (src_value, 2,
-              dec->info.height * dec->info.width * 3);
-          break;
-        case GST_FORMAT_TIME:
-          /* seems like a rather silly conversion, implement me if you like */
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          scale = 3 * (dec->info.width * dec->info.height) / 2;
-        case GST_FORMAT_DEFAULT:
-          *dest_value = scale * gst_util_uint64_scale (src_value,
-              dec->info.fps_numerator, dec->info.fps_denominator * GST_SECOND);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          *dest_value = gst_util_uint64_scale (src_value,
-              GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator);
-          break;
-        case GST_FORMAT_BYTES:
-          *dest_value = gst_util_uint64_scale_int (src_value,
-              3 * dec->info.width * dec->info.height, 2);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-done:
-  gst_object_unref (dec);
-  return res;
-
-  /* ERRORS */
-no_header:
-  {
-    GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
-    res = FALSE;
-    goto done;
-  }
-}
-
-static gboolean
-theora_dec_sink_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  GstTheoraDec *dec;
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
-  /* we need the info part before we can done something */
-  if (!dec->have_header)
-    goto no_header;
-
-  switch (src_format) {
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          *dest_value = _theora_granule_start_time (dec, src_value);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-        {
-          guint rest;
-
-          /* framecount */
-          *dest_value = gst_util_uint64_scale (src_value,
-              dec->info.fps_numerator, GST_SECOND * dec->info.fps_denominator);
-
-          /* funny way of calculating granulepos in theora */
-          rest = *dest_value / dec->info.keyframe_frequency_force;
-          *dest_value -= rest;
-          *dest_value <<= dec->granule_shift;
-          *dest_value += rest;
-          break;
-        }
-        default:
-          res = FALSE;
-          break;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-done:
-  gst_object_unref (dec);
-  return res;
-
-  /* ERRORS */
-no_header:
-  {
-    GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
-    res = FALSE;
-    goto done;
-  }
-}
-
-static gboolean
-theora_dec_src_query (GstPad * pad, GstQuery * query)
-{
-  GstTheoraDec *dec;
-
-  gboolean res = FALSE;
-
-  dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    {
-      gint64 granulepos, value;
-      GstFormat my_format, format;
-      gint64 time;
-
-      /* we can convert a granule position to everything */
-      granulepos = dec->granulepos;
-
-      GST_LOG_OBJECT (dec,
-          "query %p: we have current granule: %lld", query, granulepos);
-
-      /* parse format */
-      gst_query_parse_position (query, &format, NULL);
-
-      /* and convert to the final format in two steps with time as the 
-       * intermediate step */
-      my_format = GST_FORMAT_TIME;
-      if (!(res =
-              theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT,
-                  granulepos, &my_format, &time)))
-        goto error;
-
-      time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
-
-      GST_LOG_OBJECT (dec,
-          "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
-
-      if (!(res =
-              theora_dec_src_convert (pad, my_format, time, &format, &value)))
-        goto error;
-
-      gst_query_set_position (query, format, value);
-
-      GST_LOG_OBJECT (dec,
-          "query %p: we return %lld (format %u)", query, value, format);
-
-      break;
-    }
-    case GST_QUERY_DURATION:
-    {
-      GstPad *peer;
-
-      if (!(peer = gst_pad_get_peer (dec->sinkpad)))
-        goto error;
-
-      /* forward to peer for total */
-      res = gst_pad_query (peer, query);
-      gst_object_unref (peer);
-      if (!res)
-        goto error;
-
-      break;
-    }
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt,
-                  &dest_val)))
-        goto error;
-
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-done:
-  gst_object_unref (dec);
-
-  return res;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (dec, "query failed");
-    goto done;
-  }
-}
-
-static gboolean
-theora_dec_sink_query (GstPad * pad, GstQuery * query)
-{
-  gboolean res = FALSE;
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              theora_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt,
-                  &dest_val)))
-        goto error;
-
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-
-error:
-  return res;
-}
-
-static gboolean
-theora_dec_src_event (GstPad * pad, GstEvent * event)
-{
-  gboolean res = TRUE;
-  GstTheoraDec *dec;
-
-  dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_SEEK:
-    {
-      GstFormat format, tformat;
-      gdouble rate;
-      GstEvent *real_seek;
-      GstSeekFlags flags;
-      GstSeekType cur_type, stop_type;
-      gint64 cur, stop;
-      gint64 tcur, tstop;
-
-      gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
-          &stop_type, &stop);
-      gst_event_unref (event);
-
-      /* we have to ask our peer to seek to time here as we know
-       * nothing about how to generate a granulepos from the src
-       * formats or anything.
-       * 
-       * First bring the requested format to time 
-       */
-      tformat = GST_FORMAT_TIME;
-      if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
-        goto convert_error;
-      if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
-        goto convert_error;
-
-      /* then seek with time on the peer */
-      real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
-          flags, cur_type, tcur, stop_type, tstop);
-
-      res = gst_pad_push_event (dec->sinkpad, real_seek);
-      break;
-    }
-    case GST_EVENT_QOS:
-    {
-      gdouble proportion;
-      GstClockTimeDiff diff;
-      GstClockTime timestamp;
-
-      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
-
-      /* we cannot randomly skip frame decoding since we don't have
-       * B frames. we can however use the timestamp and diff to not
-       * push late frames. This would at least save us the time to
-       * crop/memcpy the data. */
-      GST_OBJECT_LOCK (dec);
-      dec->proportion = proportion;
-      dec->earliest_time = timestamp + diff;
-      GST_OBJECT_UNLOCK (dec);
-
-      GST_DEBUG_OBJECT (dec, "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT,
-          GST_TIME_ARGS (timestamp), diff);
-
-      res = gst_pad_push_event (dec->sinkpad, event);
-      break;
-    }
-    default:
-      res = gst_pad_push_event (dec->sinkpad, event);
-      break;
-  }
-done:
-  gst_object_unref (dec);
-
-  return res;
-
-  /* ERRORS */
-convert_error:
-  {
-    GST_DEBUG_OBJECT (dec, "could not convert format");
-    goto done;
-  }
-}
-
-static gboolean
-theora_dec_sink_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret = FALSE;
-  GstTheoraDec *dec;
-
-  dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
-  GST_LOG_OBJECT (dec, "handling event");
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      gst_theora_dec_reset (dec);
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-    case GST_EVENT_EOS:
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-    case GST_EVENT_NEWSEGMENT:
-    {
-      gboolean update;
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      /* we need TIME format */
-      if (format != GST_FORMAT_TIME)
-        goto newseg_wrong_format;
-
-      /* now configure the values */
-      gst_segment_set_newsegment_full (&dec->segment, update,
-          rate, arate, format, start, stop, time);
-
-      /* We don't forward this unless/until the decoder is initialised */
-      if (dec->have_header) {
-        ret = gst_pad_push_event (dec->srcpad, event);
-        dec->sent_newsegment = TRUE;
-      } else {
-        gst_event_unref (event);
-        ret = TRUE;
-      }
-      break;
-    }
-    default:
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-  }
-done:
-  gst_object_unref (dec);
-
-  return ret;
-
-  /* ERRORS */
-newseg_wrong_format:
-  {
-    GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
-    gst_event_unref (event);
-    goto done;
-  }
-}
-
-static GstFlowReturn
-theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
-{
-  gchar *encoder = NULL;
-  GstBuffer *buf;
-  GstTagList *list;
-
-  GST_DEBUG_OBJECT (dec, "parsing comment packet");
-
-  buf = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
-
-  list =
-      gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
-      &encoder);
-
-  gst_buffer_unref (buf);
-
-  if (!list) {
-    GST_ERROR_OBJECT (dec, "couldn't decode comments");
-    list = gst_tag_list_new ();
-  }
-  if (encoder) {
-    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
-        GST_TAG_ENCODER, encoder, NULL);
-    g_free (encoder);
-  }
-  gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
-      GST_TAG_ENCODER_VERSION, dec->info.version_major,
-      GST_TAG_VIDEO_CODEC, "Theora", NULL);
-
-  if (dec->info.target_bitrate > 0) {
-    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
-        GST_TAG_BITRATE, dec->info.target_bitrate,
-        GST_TAG_NOMINAL_BITRATE, dec->info.target_bitrate, NULL);
-  }
-
-  dec->tags = list;
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
-{
-  GstCaps *caps;
-  gint par_num, par_den;
-  GstFlowReturn ret = GST_FLOW_OK;
-  gboolean eret;
-  GstEvent *event;
-  guint32 bitstream_version;
-
-  GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
-      dec->info.fps_numerator, dec->info.fps_denominator,
-      dec->info.aspect_numerator, dec->info.aspect_denominator);
-
-  /* calculate par
-   * the info.aspect_* values reflect PAR;
-   * 0:0 is allowed and can be interpreted as 1:1, so correct for it */
-  par_num = dec->info.aspect_numerator;
-  par_den = dec->info.aspect_denominator;
-  if (par_num == 0 && par_den == 0) {
-    par_num = par_den = 1;
-  }
-  /* theora has:
-   *
-   *  width/height : dimension of the encoded frame 
-   *  frame_width/frame_height : dimension of the visible part
-   *  offset_x/offset_y : offset in encoded frame where visible part starts
-   */
-  GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width,
-      dec->info.height, par_num, par_den);
-  GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d",
-      dec->info.frame_width, dec->info.frame_height,
-      dec->info.offset_x, dec->info.offset_y);
-  if (dec->info.pixelformat != OC_PF_420) {
-    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
-        (NULL), ("pixel formats other than 4:2:0 not yet supported"));
-
-    return GST_FLOW_ERROR;
-  }
-
-  if (dec->crop) {
-    /* add black borders to make width/height/offsets even. we need this because
-     * we cannot express an offset to the peer plugin. */
-    dec->width =
-        GST_ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
-    dec->height =
-        GST_ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
-    dec->offset_x = dec->info.offset_x & ~1;
-    dec->offset_y = dec->info.offset_y & ~1;
-  } else {
-    /* no cropping, use the encoded dimensions */
-    dec->width = dec->info.width;
-    dec->height = dec->info.height;
-    dec->offset_x = 0;
-    dec->offset_y = 0;
-  }
-
-  dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1);
-
-  /* With libtheora-1.0beta1 the granulepos scheme was changed:
-   * where earlier the granulepos refered to the index/beginning
-   * of a frame, it now refers to the end, which matches the use
-   * in vorbis/speex. We check the bitstream version from the header so
-   * we know which way to interpret the incoming granuepos
-   */
-  bitstream_version = (dec->info.version_major << 16) |
-      (dec->info.version_minor << 8) | dec->info.version_subminor;
-  dec->is_old_bitstream = (bitstream_version <= 0x00030200);
-
-  GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
-      dec->width, dec->height, dec->offset_x, dec->offset_y);
-
-  /* done */
-  theora_decode_init (&dec->state, &dec->info);
-
-  caps = gst_caps_new_simple ("video/x-raw-yuv",
-      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
-      "framerate", GST_TYPE_FRACTION,
-      dec->info.fps_numerator, dec->info.fps_denominator,
-      "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
-      "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
-  gst_pad_set_caps (dec->srcpad, caps);
-  gst_caps_unref (caps);
-
-  dec->have_header = TRUE;
-  if (!dec->sent_newsegment) {
-    GST_DEBUG_OBJECT (dec, "Sending newsegment event");
-
-    event = gst_event_new_new_segment_full (FALSE,
-        dec->segment.rate, dec->segment.applied_rate,
-        dec->segment.format, dec->segment.start, dec->segment.stop,
-        dec->segment.time);
-    eret = gst_pad_push_event (dec->srcpad, event);
-    if (!eret)
-      ret = GST_FLOW_ERROR;
-    dec->sent_newsegment = TRUE;
-  }
-
-  if (dec->tags) {
-    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec), dec->srcpad,
-        dec->tags);
-    dec->tags = NULL;
-  }
-
-  return ret;
-}
-
-static GstFlowReturn
-theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
-{
-  GstFlowReturn res;
-
-  GST_DEBUG_OBJECT (dec, "parsing header packet");
-
-  if (theora_decode_header (&dec->info, &dec->comment, packet))
-    goto header_read_error;
-
-  switch (packet->packet[0]) {
-    case 0x81:
-      res = theora_handle_comment_packet (dec, packet);
-      break;
-    case 0x82:
-      res = theora_handle_type_packet (dec, packet);
-      break;
-    default:
-      /* ignore */
-      g_warning ("unknown theora header packet found");
-    case 0x80:
-      /* nothing special, this is the identification header */
-      res = GST_FLOW_OK;
-      break;
-  }
-  return res;
-
-  /* ERRORS */
-header_read_error:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
-        (NULL), ("couldn't read header packet"));
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* returns TRUE if buffer is within segment, else FALSE.
- * if Buffer is on segment border, it's timestamp and duration will be clipped */
-static gboolean
-clip_buffer (GstTheoraDec * dec, GstBuffer * buf)
-{
-  gboolean res = TRUE;
-  GstClockTime in_ts, in_dur, stop;
-  gint64 cstart, cstop;
-
-  in_ts = GST_BUFFER_TIMESTAMP (buf);
-  in_dur = GST_BUFFER_DURATION (buf);
-
-  GST_LOG_OBJECT (dec,
-      "timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT,
-      GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur));
-
-  /* can't clip without TIME segment */
-  if (dec->segment.format != GST_FORMAT_TIME)
-    goto beach;
-
-  /* we need a start time */
-  if (!GST_CLOCK_TIME_IS_VALID (in_ts))
-    goto beach;
-
-  /* generate valid stop, if duration unknown, we have unknown stop */
-  stop =
-      GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE;
-
-  /* now clip */
-  if (!(res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
-              in_ts, stop, &cstart, &cstop)))
-    goto beach;
-
-  /* update timestamp and possibly duration if the clipped stop time is
-   * valid */
-  GST_BUFFER_TIMESTAMP (buf) = cstart;
-  if (GST_CLOCK_TIME_IS_VALID (cstop))
-    GST_BUFFER_DURATION (buf) = cstop - cstart;
-
-beach:
-  GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
-  return res;
-}
-
-/* FIXME, this needs to be moved to the demuxer */
-static GstFlowReturn
-theora_dec_push_forward (GstTheoraDec * dec, GstBuffer * buf)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-  GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf);
-
-  if (outtime == GST_CLOCK_TIME_NONE) {
-    dec->queued = g_list_append (dec->queued, buf);
-    GST_DEBUG_OBJECT (dec, "queued buffer");
-  } else {
-    if (dec->queued) {
-      gint64 size;
-      GList *walk;
-
-      GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (outtime));
-
-      size = g_list_length (dec->queued);
-      for (walk = dec->queued; walk; walk = g_list_next (walk)) {
-        GstBuffer *buffer = GST_BUFFER (walk->data);
-        GstClockTime time;
-
-        time = outtime - gst_util_uint64_scale_int (size * GST_SECOND,
-            dec->info.fps_denominator, dec->info.fps_numerator);
-
-        GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
-        GST_BUFFER_TIMESTAMP (buffer) = time;
-        /* Next timestamp - this one is duration */
-        GST_BUFFER_DURATION (buffer) =
-            (outtime - gst_util_uint64_scale_int ((size - 1) * GST_SECOND,
-                dec->info.fps_denominator, dec->info.fps_numerator)) - time;
-
-        if (dec->discont) {
-          GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
-          dec->discont = FALSE;
-        }
-        /* ignore the result.. */
-        if (clip_buffer (dec, buffer))
-          gst_pad_push (dec->srcpad, buffer);
-        else
-          gst_buffer_unref (buffer);
-        size--;
-      }
-      g_list_free (dec->queued);
-      dec->queued = NULL;
-    }
-    if (dec->discont) {
-      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
-      dec->discont = FALSE;
-    }
-    if (clip_buffer (dec, buf))
-      result = gst_pad_push (dec->srcpad, buf);
-    else
-      gst_buffer_unref (buf);
-  }
-  return result;
-}
-
-static GstFlowReturn
-theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-
-  dec->queued = g_list_prepend (dec->queued, buf);
-
-  return result;
-}
-
-static GstFlowReturn
-theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
-    GstClockTime outtime)
-{
-  /* normal data packet */
-  yuv_buffer yuv;
-  GstBuffer *out;
-  guint i;
-  gboolean keyframe;
-  gint out_size;
-  gint stride_y, stride_uv;
-  gint width, height;
-  gint cwidth, cheight;
-  GstFlowReturn result;
-
-  if (G_UNLIKELY (!dec->have_header))
-    goto not_initialized;
-
-  /* the second most significant bit of the first data byte is cleared 
-   * for keyframes. We can only check it if it's not a zero-length packet. */
-  keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0);
-  if (G_UNLIKELY (keyframe)) {
-    GST_DEBUG_OBJECT (dec, "we have a keyframe");
-    dec->need_keyframe = FALSE;
-  } else if (G_UNLIKELY (dec->need_keyframe)) {
-    goto dropping;
-  }
-
-  GST_DEBUG_OBJECT (dec, "parsing data packet");
-
-  /* this does the decoding */
-  if (G_UNLIKELY (theora_decode_packetin (&dec->state, packet)))
-    goto decode_error;
-
-  if (outtime != -1) {
-    gboolean need_skip;
-    GstClockTime qostime;
-
-    /* qos needs to be done on running time */
-    qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
-        outtime);
-
-    GST_OBJECT_LOCK (dec);
-    /* check for QoS, don't perform the last steps of getting and
-     * pushing the buffers that are known to be late. */
-    /* FIXME, we can also entirely skip decoding if the next valid buffer is 
-     * known to be after a keyframe (using the granule_shift) */
-    need_skip = dec->earliest_time != -1 && qostime <= dec->earliest_time;
-    GST_OBJECT_UNLOCK (dec);
-
-    if (need_skip)
-      goto dropping_qos;
-  }
-
-  /* this does postprocessing and set up the decoded frame
-   * pointers in our yuv variable */
-  if (G_UNLIKELY (theora_decode_YUVout (&dec->state, &yuv) < 0))
-    goto no_yuv;
-
-  if (G_UNLIKELY ((yuv.y_width != dec->info.width)
-          || (yuv.y_height != dec->info.height)))
-    goto wrong_dimensions;
-
-  width = dec->width;
-  height = dec->height;
-  cwidth = width / 2;
-  cheight = height / 2;
-
-  /* should get the stride from the caps, for now we round up to the nearest
-   * multiple of 4 because some element needs it. chroma needs special 
-   * treatment, see videotestsrc. */
-  stride_y = GST_ROUND_UP_4 (width);
-  stride_uv = GST_ROUND_UP_8 (width) / 2;
-
-  out_size = stride_y * height + stride_uv * cheight * 2;
-
-  /* now copy over the area contained in offset_x,offset_y,
-   * frame_width, frame_height */
-  result =
-      gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
-      out_size, GST_PAD_CAPS (dec->srcpad), &out);
-  if (G_UNLIKELY (result != GST_FLOW_OK))
-    goto no_buffer;
-
-  /* copy the visible region to the destination. This is actually pretty
-   * complicated and gstreamer doesn't support all the needed caps to do this
-   * correctly. For example, when we have an odd offset, we should only combine
-   * 1 row/column of luma samples with one chroma sample in colorspace conversion. 
-   * We compensate for this by adding a black border around the image when the
-   * offset or size is odd (see above).
-   */
-  {
-    guchar *dest_y, *src_y;
-    guchar *dest_u, *src_u;
-    guchar *dest_v, *src_v;
-    gint offset;
-
-    dest_y = GST_BUFFER_DATA (out);
-    dest_u = dest_y + stride_y * height;
-    dest_v = dest_u + stride_uv * cheight;
-
-    src_y = yuv.y + dec->offset_x + dec->offset_y * yuv.y_stride;
-
-    for (i = 0; i < height; i++) {
-      memcpy (dest_y, src_y, width);
-
-      dest_y += stride_y;
-      src_y += yuv.y_stride;
-    }
-
-    offset = dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
-
-    src_u = yuv.u + offset;
-    src_v = yuv.v + offset;
-
-    for (i = 0; i < cheight; i++) {
-      memcpy (dest_u, src_u, cwidth);
-      memcpy (dest_v, src_v, cwidth);
-
-      dest_u += stride_uv;
-      src_u += yuv.uv_stride;
-      dest_v += stride_uv;
-      src_v += yuv.uv_stride;
-    }
-  }
-
-  GST_BUFFER_OFFSET (out) = dec->frame_nr;
-  if (dec->frame_nr != -1)
-    dec->frame_nr++;
-  GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
-  if (dec->granulepos != -1) {
-    gint64 cf = _theora_granule_frame (dec, dec->granulepos) + 1;
-
-    GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (cf * GST_SECOND,
-        dec->info.fps_denominator, dec->info.fps_numerator) - outtime;
-  } else {
-    GST_BUFFER_DURATION (out) =
-        gst_util_uint64_scale_int (GST_SECOND, dec->info.fps_denominator,
-        dec->info.fps_numerator);
-  }
-  GST_BUFFER_TIMESTAMP (out) = outtime;
-
-  if (dec->segment.rate >= 0.0)
-    result = theora_dec_push_forward (dec, out);
-  else
-    result = theora_dec_push_reverse (dec, out);
-
-  return result;
-
-  /* ERRORS */
-not_initialized:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
-        (NULL), ("no header sent yet"));
-    return GST_FLOW_ERROR;
-  }
-dropping:
-  {
-    GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
-    dec->discont = TRUE;
-    return GST_FLOW_OK;
-  }
-dropping_qos:
-  {
-    if (dec->frame_nr != -1)
-      dec->frame_nr++;
-    dec->discont = TRUE;
-    GST_WARNING_OBJECT (dec, "dropping frame because of QoS");
-    return GST_FLOW_OK;
-  }
-decode_error:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
-        (NULL), ("theora decoder did not decode data packet"));
-    return GST_FLOW_ERROR;
-  }
-no_yuv:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
-        (NULL), ("couldn't read out YUV image"));
-    return GST_FLOW_ERROR;
-  }
-wrong_dimensions:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, FORMAT,
-        (NULL), ("dimensions of image do not match header"));
-    return GST_FLOW_ERROR;
-  }
-no_buffer:
-  {
-    GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
-        gst_flow_get_name (result));
-    return result;
-  }
-}
-
-static GstFlowReturn
-theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf)
-{
-  ogg_packet packet;
-  GstFlowReturn result = GST_FLOW_OK;
-
-  /* make ogg_packet out of the buffer */
-  packet.packet = GST_BUFFER_DATA (buf);
-  packet.bytes = GST_BUFFER_SIZE (buf);
-  packet.granulepos = GST_BUFFER_OFFSET_END (buf);
-  packet.packetno = 0;          /* we don't really care */
-  packet.b_o_s = dec->have_header ? 0 : 1;
-  /* EOS does not matter for the decoder */
-  packet.e_o_s = 0;
-
-  if (dec->have_header) {
-    if (packet.granulepos != -1) {
-      dec->granulepos = packet.granulepos;
-      dec->last_timestamp = _theora_granule_start_time (dec, packet.granulepos);
-    } else if (dec->last_timestamp != -1) {
-      dec->last_timestamp = _theora_granule_start_time (dec, dec->granulepos);
-    }
-    if (dec->last_timestamp == -1 && GST_BUFFER_TIMESTAMP_IS_VALID (buf))
-      dec->last_timestamp = GST_BUFFER_TIMESTAMP (buf);
-  } else {
-    dec->last_timestamp = -1;
-  }
-
-  GST_DEBUG_OBJECT (dec, "header=%02x packetno=%lld, granule pos=%"
-      G_GINT64_FORMAT ", outtime=%" GST_TIME_FORMAT,
-      packet.bytes ? packet.packet[0] : -1, packet.packetno, packet.granulepos,
-      GST_TIME_ARGS (dec->last_timestamp));
-
-  /* switch depending on packet type. A zero byte packet is always a data
-   * packet; we don't dereference it in that case. */
-  if (packet.bytes && packet.packet[0] & 0x80) {
-    if (dec->have_header) {
-      GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header");
-      goto done;
-    }
-    result = theora_handle_header_packet (dec, &packet);
-  } else {
-    result = theora_handle_data_packet (dec, &packet, dec->last_timestamp);
-  }
-
-done:
-  /* interpolate granule pos */
-  dec->granulepos = _inc_granulepos (dec, dec->granulepos);
-
-  return result;
-}
-
-/* For reverse playback we use a technique that can be used for
- * any keyframe based video codec.
- *
- * Input:
- *  Buffer decoding order:  7  8  9  4  5  6  1  2  3  EOS
- *  Keyframe flag:                      K        K
- *  Discont flag:           D        D        D
- *
- * - Each Discont marks a discont in the decoding order.
- * - The keyframes mark where we can start decoding.
- *
- * First we prepend incomming buffers to the gather queue, whenever we receive
- * a discont, we flush out the gather queue.
- *
- * The above data will be accumulated in the gather queue like this:
- *
- *   gather queue:  9  8  7
- *                        D
- *
- * Whe buffer 4 is received (with a DISCONT), we flush the gather queue like
- * this:
- *
- *   while (gather)
- *     take head of queue and prepend to decode queue.
- *     if we copied a keyframe, decode the decode queue.
- *
- * After we flushed the gather queue, we add 4 to the (now empty) gather queue.
- * We get the following situation:
- *
- *  gather queue:    4
- *  decode queue:    7  8  9
- *
- * After we received 5 (Keyframe) and 6:
- *
- *  gather queue:    6  5  4
- *  decode queue:    7  8  9
- *
- * When we receive 1 (DISCONT) which triggers a flush of the gather queue:
- *
- *   Copy head of the gather queue (6) to decode queue:
- *
- *    gather queue:    5  4
- *    decode queue:    6  7  8  9
- *
- *   Copy head of the gather queue (5) to decode queue. This is a keyframe so we
- *   can start decoding.
- *
- *    gather queue:    4
- *    decode queue:    5  6  7  8  9
- *
- *   Decode frames in decode queue, store raw decoded data in output queue, we
- *   can take the head of the decode queue and prepend the decoded result in the
- *   output queue:
- *
- *    gather queue:    4
- *    decode queue:    
- *    output queue:    9  8  7  6  5
- *
- *   Now output all the frames in the output queue, picking a frame from the
- *   head of the queue.
- *
- *   Copy head of the gather queue (4) to decode queue, we flushed the gather
- *   queue and can now store input buffer in the gather queue:
- *
- *    gather queue:    1
- *    decode queue:    4
- *
- *  When we receive EOS, the queue looks like:
- *
- *    gather queue:    3  2  1
- *    decode queue:    4
- *
- *  Fill decode queue, first keyframe we copy is 2:
- *
- *    gather queue:    1
- *    decode queue:    2  3  4
- *
- *  Decoded output:
- *
- *    gather queue:    1
- *    decode queue:    
- *    output queue:    4  3  2
- *
- *  Leftover buffer 1 cannot be decoded and must be discarded.
- */
-static GstFlowReturn
-theora_dec_flush_decode (GstTheoraDec * dec)
-{
-  GstFlowReturn res = GST_FLOW_OK;
-
-  while (dec->decode) {
-    GstBuffer *buf = GST_BUFFER_CAST (dec->decode->data);
-
-    GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT,
-        buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
-    /* decode buffer, prepend to output queue */
-    res = theora_dec_decode_buffer (dec, buf);
-
-    /* don't need it anymore now */
-    gst_buffer_unref (buf);
-
-    dec->decode = g_list_delete_link (dec->decode, dec->decode);
-  }
-  while (dec->queued) {
-    GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data);
-
-    /* iterate ouput queue an push downstream */
-    res = gst_pad_push (dec->srcpad, buf);
-
-    dec->queued = g_list_delete_link (dec->queued, dec->queued);
-  }
-
-  return res;
-}
-
-static GstFlowReturn
-theora_dec_chain_reverse (GstTheoraDec * dec, gboolean discont, GstBuffer * buf)
-{
-  GstFlowReturn res = GST_FLOW_OK;
-
-  /* if we have a discont, move buffers to the decode list */
-  if (G_UNLIKELY (discont)) {
-    GST_DEBUG_OBJECT (dec, "received discont,gathering buffers");
-    while (dec->gather) {
-      GstBuffer *gbuf;
-      guint8 *data;
-
-      gbuf = GST_BUFFER_CAST (dec->gather->data);
-      /* remove from the gather list */
-      dec->gather = g_list_delete_link (dec->gather, dec->gather);
-      /* copy to decode queue */
-      dec->decode = g_list_prepend (dec->decode, gbuf);
-
-      /* if we copied a keyframe, flush and decode the decode queue */
-      data = GST_BUFFER_DATA (gbuf);
-      if ((data[0] & 0x40) == 0) {
-        GST_DEBUG_OBJECT (dec, "copied keyframe");
-        res = theora_dec_flush_decode (dec);
-      }
-    }
-  }
-
-  /* add buffer to gather queue */
-  GST_DEBUG_OBJECT (dec, "gathering buffer %p, size %u", buf,
-      GST_BUFFER_SIZE (buf));
-  dec->gather = g_list_prepend (dec->gather, buf);
-
-  return res;
-}
-
-static GstFlowReturn
-theora_dec_chain_forward (GstTheoraDec * dec, gboolean discont,
-    GstBuffer * buffer)
-{
-  GstFlowReturn result;
-
-  result = theora_dec_decode_buffer (dec, buffer);
-
-  gst_buffer_unref (buffer);
-
-  return result;
-}
-
-static GstFlowReturn
-theora_dec_chain (GstPad * pad, GstBuffer * buf)
-{
-  GstTheoraDec *dec;
-  GstFlowReturn res;
-  gboolean discont;
-
-  dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
-  /* peel of DISCONT flag */
-  discont = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT);
-
-  /* resync on DISCONT */
-  if (G_UNLIKELY (discont)) {
-    GST_DEBUG_OBJECT (dec, "received DISCONT buffer");
-    dec->need_keyframe = TRUE;
-    dec->last_timestamp = -1;
-    dec->granulepos = -1;
-    dec->discont = TRUE;
-  }
-
-  if (dec->segment.rate > 0.0)
-    res = theora_dec_chain_forward (dec, discont, buf);
-  else
-    res = theora_dec_chain_reverse (dec, discont, buf);
-
-  gst_object_unref (dec);
-
-  return res;
-}
-
-static GstStateChangeReturn
-theora_dec_change_state (GstElement * element, GstStateChange transition)
-{
-  GstTheoraDec *dec = GST_THEORA_DEC (element);
-  GstStateChangeReturn ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      theora_info_init (&dec->info);
-      theora_comment_init (&dec->comment);
-      GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE in READY->PAUSED");
-      dec->have_header = FALSE;
-      gst_theora_dec_reset (dec);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  ret = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      theora_clear (&dec->state);
-      theora_comment_clear (&dec->comment);
-      theora_info_clear (&dec->info);
-      gst_theora_dec_reset (dec);
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-static void
-theora_dec_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstTheoraDec *dec = GST_THEORA_DEC (object);
-
-  switch (prop_id) {
-    case ARG_CROP:
-      dec->crop = g_value_get_boolean (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-theora_dec_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstTheoraDec *dec = GST_THEORA_DEC (object);
-
-  switch (prop_id) {
-    case ARG_CROP:
-      g_value_set_boolean (value, dec->crop);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
--- a/gst_plugins_base/ext/theora/theoraenc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1104 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.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.
- */
-
-/**
- * SECTION:element-theoraenc
- * @see_also: theoradec, oggmux
- *
- * <refsect2>
- * <para>
- * This element encodes raw video into a Theora stream.
- * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
- * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>, based on the VP3 codec.
- * </para>
- * <para>
- * The theora codec internally only supports encoding of images that are a
- * multiple of 16 pixels in both X and Y direction. It is however perfectly
- * possible to encode images with other dimensions because an arbitrary
- * rectangular cropping region can be set up. This element will automatically
- * set up a correct cropping region if the dimensions are not multiples of 16
- * pixels. The "border" and "center" properties control how this cropping
- * region will be set up.
- * </para>
- * <para>
- * To control the quality of the encoding, the "bitrate" and "quality"
- * properties can be used. These two properties are mutualy exclusive. Setting
- * the bitrate property will produce a constant bitrate (CBR) stream while
- * setting the quality property will produce a variable bitrate (VBR) stream.
- * </para>
- * <title>Example pipeline</title>
- * <programlisting>
- * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
- * </programlisting>
- * This example pipeline will encode a test video source to theora muxed in an
- * ogg container. Refer to the theoradec documentation to decode the create
- * stream.
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "gsttheoraenc.h"
-
-#include <string.h>
-#include <stdlib.h>             /* free */
-
-#include <gst/tag/tag.h>
-
-#define GST_CAT_DEFAULT theoraenc_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-/* With libtheora-1.0beta1 the granulepos scheme was changed:
- * where earlier the granulepos refered to the index/beginning
- * of a frame, it now refers to the end, which matches the use
- * in vorbis/speex. There don't seem to be defines for the
- * theora version we're compiling against, so we'll just use
- * a run-time check for now. See theora_enc_get_ogg_packet_end_time().
- */
-static gboolean use_old_granulepos;
-
-#define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
-static GType
-gst_border_mode_get_type (void)
-{
-  static GType border_mode_type = 0;
-  static const GEnumValue border_mode[] = {
-    {BORDER_NONE, "No Border", "none"},
-    {BORDER_BLACK, "Black Border", "black"},
-    {BORDER_MIRROR, "Mirror image in borders", "mirror"},
-    {0, NULL, NULL},
-  };
-
-  if (!border_mode_type) {
-    border_mode_type =
-        g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
-  }
-  return border_mode_type;
-}
-
-/* taken from theora/lib/toplevel.c */
-static int
-_ilog (unsigned int v)
-{
-  int ret = 0;
-
-  while (v) {
-    ret++;
-    v >>= 1;
-  }
-  return (ret);
-}
-
-#define THEORA_DEF_CENTER               TRUE
-#define THEORA_DEF_BORDER               BORDER_BLACK
-#define THEORA_DEF_BITRATE              0
-#define THEORA_DEF_QUALITY              16
-#define THEORA_DEF_QUICK                TRUE
-#define THEORA_DEF_KEYFRAME_AUTO        TRUE
-#define THEORA_DEF_KEYFRAME_FREQ        64
-#define THEORA_DEF_KEYFRAME_FREQ_FORCE  64
-#define THEORA_DEF_KEYFRAME_THRESHOLD   80
-#define THEORA_DEF_KEYFRAME_MINDISTANCE 8
-#define THEORA_DEF_NOISE_SENSITIVITY    1
-#define THEORA_DEF_SHARPNESS            0
-enum
-{
-  ARG_0,
-  ARG_CENTER,
-  ARG_BORDER,
-  ARG_BITRATE,
-  ARG_QUALITY,
-  ARG_QUICK,
-  ARG_KEYFRAME_AUTO,
-  ARG_KEYFRAME_FREQ,
-  ARG_KEYFRAME_FREQ_FORCE,
-  ARG_KEYFRAME_THRESHOLD,
-  ARG_KEYFRAME_MINDISTANCE,
-  ARG_NOISE_SENSITIVITY,
-  ARG_SHARPNESS,
-  /* FILL ME */
-};
-
-/* this function does a straight granulepos -> timestamp conversion */
-static GstClockTime
-granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
-{
-  guint64 iframe, pframe;
-  int shift = theoraenc->granule_shift;
-
-  if (granulepos < 0)
-    return GST_CLOCK_TIME_NONE;
-
-  iframe = granulepos >> shift;
-  pframe = granulepos - (iframe << shift);
-
-  /* num and den are 32 bit, so we can safely multiply with GST_SECOND */
-  return gst_util_uint64_scale ((guint64) (iframe + pframe),
-      GST_SECOND * theoraenc->info.fps_denominator,
-      theoraenc->info.fps_numerator);
-}
-
-static const GstElementDetails theora_enc_details =
-GST_ELEMENT_DETAILS ("Theora video encoder",
-    "Codec/Encoder/Video",
-    "encode raw YUV video to a theora stream",
-    "Wim Taymans <wim@fluendo.com>");
-
-static GstStaticPadTemplate theora_enc_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-yuv, "
-        "format = (fourcc) I420, "
-        "framerate = (fraction) [0/1, MAX], "
-        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
-    );
-
-static GstStaticPadTemplate theora_enc_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-theora")
-    );
-
-GST_BOILERPLATE (GstTheoraEnc, gst_theora_enc, GstElement, GST_TYPE_ELEMENT);
-
-static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn theora_enc_change_state (GstElement * element,
-    GstStateChange transition);
-static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
-static void theora_enc_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void theora_enc_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void theora_enc_finalize (GObject * object);
-
-static void
-gst_theora_enc_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&theora_enc_src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&theora_enc_sink_factory));
-  gst_element_class_set_details (element_class, &theora_enc_details);
-}
-
-static void
-gst_theora_enc_class_init (GstTheoraEncClass * klass)
-{
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->set_property = theora_enc_set_property;
-  gobject_class->get_property = theora_enc_get_property;
-  gobject_class->finalize = theora_enc_finalize;
-
-  g_object_class_install_property (gobject_class, ARG_CENTER,
-      g_param_spec_boolean ("center", "Center",
-          "Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
-          (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_BORDER,
-      g_param_spec_enum ("border", "Border",
-          "Border color to add when sizes not multiple of 16",
-          GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
-          (GParamFlags) G_PARAM_READWRITE));
-  /* general encoding stream options */
-  g_object_class_install_property (gobject_class, ARG_BITRATE,
-      g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
-          0, 2000, THEORA_DEF_BITRATE, (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_QUALITY,
-      g_param_spec_int ("quality", "Quality", "Video quality",
-          0, 63, THEORA_DEF_QUALITY, (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_QUICK,
-      g_param_spec_boolean ("quick", "Quick", "Quick encoding",
-          THEORA_DEF_QUICK, (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_KEYFRAME_AUTO,
-      g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
-          "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
-          (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ,
-      g_param_spec_int ("keyframe-freq", "Keyframe frequency",
-          "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
-          (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ_FORCE,
-      g_param_spec_int ("keyframe-force", "Keyframe force",
-          "Force keyframe every N frames", 1, 32768,
-          THEORA_DEF_KEYFRAME_FREQ_FORCE, (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_KEYFRAME_THRESHOLD,
-      g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
-          "Keyframe threshold", 0, 32768, THEORA_DEF_KEYFRAME_THRESHOLD,
-          (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_KEYFRAME_MINDISTANCE,
-      g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
-          "Keyframe mindistance", 1, 32768, THEORA_DEF_KEYFRAME_MINDISTANCE,
-          (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_NOISE_SENSITIVITY,
-      g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
-          "Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
-          (GParamFlags) G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_SHARPNESS,
-      g_param_spec_int ("sharpness", "Sharpness",
-          "Sharpness", 0, 2, THEORA_DEF_SHARPNESS,
-          (GParamFlags) G_PARAM_READWRITE));
-
-  gstelement_class->change_state = theora_enc_change_state;
-  GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
-
-  use_old_granulepos = (theora_version_number () <= 0x00030200);
-}
-
-static void
-gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
-{
-  enc->sinkpad =
-      gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
-  gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
-  gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
-  gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
-  gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
-
-  enc->srcpad =
-      gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
-  gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
-
-  enc->center = THEORA_DEF_CENTER;
-  enc->border = THEORA_DEF_BORDER;
-
-  enc->video_bitrate = THEORA_DEF_BITRATE;
-  enc->video_quality = THEORA_DEF_QUALITY;
-  enc->quick = THEORA_DEF_QUICK;
-  enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
-  enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
-  enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
-  enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
-  enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
-  enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
-  enc->sharpness = THEORA_DEF_SHARPNESS;
-
-  enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
-  GST_DEBUG_OBJECT (enc,
-      "keyframe_frequency_force is %d, granule shift is %d",
-      enc->info.keyframe_frequency_force, enc->granule_shift);
-  enc->expected_ts = GST_CLOCK_TIME_NONE;
-}
-
-static void
-theora_enc_finalize (GObject * object)
-{
-  GstTheoraEnc *enc = GST_THEORA_ENC (object);
-
-  GST_DEBUG_OBJECT (enc, "Finalizing");
-  theora_clear (&enc->state);
-  theora_comment_clear (&enc->comment);
-  theora_info_clear (&enc->info);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-theora_enc_reset (GstTheoraEnc * enc)
-{
-  theora_clear (&enc->state);
-  theora_encode_init (&enc->state, &enc->info);
-}
-
-static void
-theora_enc_clear (GstTheoraEnc * enc)
-{
-  enc->packetno = 0;
-  enc->bytes_out = 0;
-  enc->granulepos_offset = 0;
-  enc->timestamp_offset = 0;
-
-  enc->next_ts = GST_CLOCK_TIME_NONE;
-  enc->next_discont = FALSE;
-  enc->expected_ts = GST_CLOCK_TIME_NONE;
-}
-
-static gboolean
-theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstStructure *structure = gst_caps_get_structure (caps, 0);
-  GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
-  const GValue *par;
-  gint fps_n, fps_d;
-
-  gst_structure_get_int (structure, "width", &enc->width);
-  gst_structure_get_int (structure, "height", &enc->height);
-  gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
-  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
-
-  theora_info_clear (&enc->info);
-  theora_info_init (&enc->info);
-  /* Theora has a divisible-by-sixteen restriction for the encoded video size but
-   * we can define a visible area using the frame_width/frame_height */
-  enc->info_width = enc->info.width = (enc->width + 15) & ~15;
-  enc->info_height = enc->info.height = (enc->height + 15) & ~15;
-  enc->info.frame_width = enc->width;
-  enc->info.frame_height = enc->height;
-
-  /* center image if needed */
-  if (enc->center) {
-    /* make sure offset is even, for easier decoding */
-    enc->offset_x = GST_ROUND_UP_2 ((enc->info_width - enc->width) / 2);
-    enc->offset_y = GST_ROUND_UP_2 ((enc->info_height - enc->height) / 2);
-  } else {
-    enc->offset_x = 0;
-    enc->offset_y = 0;
-  }
-  enc->info.offset_x = enc->offset_x;
-  enc->info.offset_y = enc->offset_y;
-
-  enc->info.fps_numerator = enc->fps_n = fps_n;
-  enc->info.fps_denominator = enc->fps_d = fps_d;
-  if (par) {
-    enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
-    enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
-  } else {
-    /* setting them to 0 indicates that the decoder can chose a good aspect
-     * ratio, defaulting to 1/1 */
-    enc->info.aspect_numerator = 0;
-    enc->info.aspect_denominator = 0;
-  }
-
-  enc->info.colorspace = OC_CS_UNSPECIFIED;
-  enc->info.target_bitrate = enc->video_bitrate;
-  enc->info.quality = enc->video_quality;
-
-  enc->info.dropframes_p = 0;
-  enc->info.quick_p = (enc->quick ? 1 : 0);
-  enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
-  enc->info.keyframe_frequency = enc->keyframe_freq;
-  enc->info.keyframe_frequency_force = enc->keyframe_force;
-  enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
-  enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
-  enc->info.keyframe_mindistance = enc->keyframe_mindistance;
-  enc->info.noise_sensitivity = enc->noise_sensitivity;
-  enc->info.sharpness = enc->sharpness;
-
-  /* as done in theora */
-  enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
-  GST_DEBUG_OBJECT (enc,
-      "keyframe_frequency_force is %d, granule shift is %d",
-      enc->info.keyframe_frequency_force, enc->granule_shift);
-
-  theora_enc_reset (enc);
-  enc->initialised = TRUE;
-
-  gst_object_unref (enc);
-
-  return TRUE;
-}
-
-static guint64
-granulepos_add (guint64 granulepos, guint64 addend, gint shift)
-{
-  guint64 iframe, pframe;
-
-  iframe = granulepos >> shift;
-  pframe = granulepos - (iframe << shift);
-  iframe += addend;
-
-  return (iframe << shift) + pframe;
-}
-
-/* prepare a buffer for transmission by passing data through libtheora */
-static GstFlowReturn
-theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
-    GstClockTime timestamp, GstClockTime duration, GstBuffer ** buffer)
-{
-  GstBuffer *buf;
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  buf = gst_buffer_new_and_alloc (packet->bytes);
-  if (!buf) {
-    GST_WARNING_OBJECT (enc, "Could not allocate buffer");
-    ret = GST_FLOW_ERROR;
-    goto done;
-  }
-
-  memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
-  /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
-   * time representation */
-  GST_BUFFER_OFFSET_END (buf) =
-      granulepos_add (packet->granulepos, enc->granulepos_offset,
-      enc->granule_shift);
-  GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
-      GST_BUFFER_OFFSET_END (buf));
-
-  GST_BUFFER_TIMESTAMP (buf) = timestamp + enc->timestamp_offset;
-  GST_BUFFER_DURATION (buf) = duration;
-
-  if (enc->next_discont) {
-    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
-    enc->next_discont = FALSE;
-  }
-
-  /* the second most significant bit of the first data byte is cleared
-   * for keyframes */
-  if ((packet->packet[0] & 0x40) == 0) {
-    GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
-  } else {
-    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
-  }
-  enc->packetno++;
-
-done:
-  *buffer = buf;
-  return ret;
-}
-
-/* push out the buffer and do internal bookkeeping */
-static GstFlowReturn
-theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
-{
-  GstFlowReturn ret;
-
-  enc->bytes_out += GST_BUFFER_SIZE (buffer);
-
-  ret = gst_pad_push (enc->srcpad, buffer);
-
-  return ret;
-}
-
-static GstFlowReturn
-theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
-    GstClockTime timestamp, GstClockTime duration)
-{
-  GstBuffer *buf;
-  GstFlowReturn ret;
-
-  ret = theora_buffer_from_packet (enc, packet, timestamp, duration, &buf);
-  if (ret == GST_FLOW_OK)
-    ret = theora_push_buffer (enc, buf);
-
-  return ret;
-}
-
-static GstCaps *
-theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
-    GstBuffer * buf2, GstBuffer * buf3)
-{
-  GstStructure *structure;
-  GValue array = { 0 };
-  GValue value = { 0 };
-
-  caps = gst_caps_make_writable (caps);
-  structure = gst_caps_get_structure (caps, 0);
-
-  /* mark buffers */
-  GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
-  GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
-  GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
-
-  /* Copy buffers, because we can't use the originals -
-   * it creates a circular refcount with the caps<->buffers */
-  buf1 = gst_buffer_copy (buf1);
-  buf2 = gst_buffer_copy (buf2);
-  buf3 = gst_buffer_copy (buf3);
-
-  /* put copies of the buffers in a fixed list */
-  g_value_init (&array, GST_TYPE_ARRAY);
-
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buf1);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buf2);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buf3);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-
-  gst_structure_set_value (structure, "streamheader", &array);
-  g_value_unset (&array);
-
-  /* Unref our copies */
-  gst_buffer_unref (buf1);
-  gst_buffer_unref (buf2);
-  gst_buffer_unref (buf3);
-
-  return caps;
-}
-
-static GstClockTime
-theora_enc_get_ogg_packet_end_time (GstTheoraEnc * enc, ogg_packet * op)
-{
-  ogg_int64_t end_granule;
-
-  /* FIXME: remove this hack once we depend on libtheora >= 1.0beta1 */
-  if (G_UNLIKELY (use_old_granulepos)) {
-    /* This is where we hack around theora's broken idea of what granulepos
-     * is -- normally we wouldn't need to add the 1, because granulepos
-     * should be the presentation time of the last sample in the packet, but
-     * theora starts with 0 instead of 1... (update: this only applies to old
-     * bitstream/theora versions, this is fixed with bitstream version 3.2.1) */
-    end_granule = granulepos_add (op->granulepos, 1, enc->granule_shift);
-  } else {
-    end_granule = op->granulepos;
-  }
-  return theora_granule_time (&enc->state, end_granule) * GST_SECOND;
-}
-
-static gboolean
-theora_enc_sink_event (GstPad * pad, GstEvent * event)
-{
-  GstTheoraEnc *enc;
-  ogg_packet op;
-  gboolean res;
-
-  enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-      if (enc->initialised) {
-        /* push last packet with eos flag */
-        while (theora_encode_packetout (&enc->state, 1, &op)) {
-          GstClockTime next_time =
-              theora_enc_get_ogg_packet_end_time (enc, &op);
-
-          theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
-          enc->next_ts = next_time;
-        }
-      }
-      res = gst_pad_push_event (enc->srcpad, event);
-      break;
-    case GST_EVENT_CUSTOM_DOWNSTREAM:
-    {
-      const GstStructure *s;
-
-      s = gst_event_get_structure (event);
-
-      if (gst_structure_has_name (s, "GstForceKeyUnit")) {
-        GstClockTime next_ts;
-
-        /* make sure timestamps increment after resetting the decoder */
-        next_ts = enc->next_ts + enc->timestamp_offset;
-
-        theora_enc_reset (enc);
-        enc->granulepos_offset =
-            gst_util_uint64_scale (next_ts, enc->fps_n,
-            GST_SECOND * enc->fps_d);
-        enc->timestamp_offset = next_ts;
-        enc->next_ts = 0;
-      }
-      res = gst_pad_push_event (enc->srcpad, event);
-      break;
-    }
-    default:
-      res = gst_pad_push_event (enc->srcpad, event);
-      break;
-  }
-  return res;
-}
-
-static gboolean
-theora_enc_is_discontinuous (GstTheoraEnc * enc, GstBuffer * buffer)
-{
-  GstClockTime ts = GST_BUFFER_TIMESTAMP (buffer);
-  GstClockTimeDiff max_diff;
-  gboolean ret = FALSE;
-
-  /* Allow 3/4 a frame off */
-  max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
-      (enc->info.fps_numerator * 4);
-
-  if (ts != GST_CLOCK_TIME_NONE && enc->expected_ts != GST_CLOCK_TIME_NONE) {
-    if ((GstClockTimeDiff) (ts - enc->expected_ts) > max_diff) {
-      GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
-          " exceeds expected value %" GST_TIME_FORMAT
-          " by too much, marking discontinuity",
-          GST_TIME_ARGS (ts), GST_TIME_ARGS (enc->expected_ts));
-      ret = TRUE;
-    }
-  }
-
-  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
-    enc->expected_ts = ts + GST_BUFFER_DURATION (buffer);
-  else
-    enc->expected_ts = GST_CLOCK_TIME_NONE;
-
-  return ret;
-}
-
-static GstFlowReturn
-theora_enc_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstTheoraEnc *enc;
-  ogg_packet op;
-  GstClockTime in_time;
-  GstFlowReturn ret;
-
-  enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
-
-  in_time = GST_BUFFER_TIMESTAMP (buffer);
-
-  if (enc->packetno == 0) {
-    /* no packets written yet, setup headers */
-    GstCaps *caps;
-    GstBuffer *buf1, *buf2, *buf3;
-
-    enc->granulepos_offset = 0;
-    enc->timestamp_offset = 0;
-
-    GST_DEBUG_OBJECT (enc, "output headers");
-    /* Theora streams begin with three headers; the initial header (with
-       most of the codec setup parameters) which is mandated by the Ogg
-       bitstream spec.  The second header holds any comment fields.  The
-       third header holds the bitstream codebook.  We merely need to
-       make the headers, then pass them to libtheora one at a time;
-       libtheora handles the additional Ogg bitstream constraints */
-
-    /* first packet will get its own page automatically */
-    if (theora_encode_header (&enc->state, &op) != 0)
-      goto encoder_disabled;
-
-    ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
-        GST_CLOCK_TIME_NONE, &buf1);
-    if (ret != GST_FLOW_OK) {
-      goto header_buffer_alloc;
-    }
-
-    /* create the remaining theora headers */
-    theora_comment_clear (&enc->comment);
-    theora_comment_init (&enc->comment);
-
-    if (theora_encode_comment (&enc->comment, &op) != 0)
-      goto encoder_disabled;
-
-    ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
-        GST_CLOCK_TIME_NONE, &buf2);
-    /* Theora expects us to put this packet buffer into an ogg page,
-     * in which case it becomes the ogg library's responsibility to
-     * free it. Since we're copying and outputting a gst_buffer,
-     * we need to free it ourselves. */
-    if (op.packet)
-      free (op.packet);
-
-    if (ret != GST_FLOW_OK) {
-      gst_buffer_unref (buf1);
-      goto header_buffer_alloc;
-    }
-
-    if (theora_encode_tables (&enc->state, &op) != 0)
-      goto encoder_disabled;
-
-    ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
-        GST_CLOCK_TIME_NONE, &buf3);
-    if (ret != GST_FLOW_OK) {
-      gst_buffer_unref (buf1);
-      gst_buffer_unref (buf2);
-      goto header_buffer_alloc;
-    }
-
-    /* mark buffers and put on caps */
-    caps = gst_pad_get_caps (enc->srcpad);
-    caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
-    GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
-    gst_pad_set_caps (enc->srcpad, caps);
-
-    gst_buffer_set_caps (buf1, caps);
-    gst_buffer_set_caps (buf2, caps);
-    gst_buffer_set_caps (buf3, caps);
-
-    gst_caps_unref (caps);
-
-    /* push out the header buffers */
-    if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK) {
-      gst_buffer_unref (buf2);
-      gst_buffer_unref (buf3);
-      goto header_push;
-    }
-    if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK) {
-      gst_buffer_unref (buf3);
-      goto header_push;
-    }
-    if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK) {
-      goto header_push;
-    }
-
-    enc->granulepos_offset =
-        gst_util_uint64_scale (in_time, enc->fps_n, GST_SECOND * enc->fps_d);
-    enc->timestamp_offset = in_time;
-    enc->next_ts = 0;
-  }
-
-  {
-    yuv_buffer yuv;
-    gint res;
-    gint y_size;
-    guint8 *pixels;
-
-    yuv.y_width = enc->info_width;
-    yuv.y_height = enc->info_height;
-    yuv.y_stride = enc->info_width;
-
-    yuv.uv_width = enc->info_width / 2;
-    yuv.uv_height = enc->info_height / 2;
-    yuv.uv_stride = yuv.uv_width;
-
-    y_size = enc->info_width * enc->info_height;
-
-    if (enc->width == enc->info_width && enc->height == enc->info_height) {
-      GST_LOG_OBJECT (enc, "no cropping/conversion needed");
-      /* easy case, no cropping/conversion needed */
-      pixels = GST_BUFFER_DATA (buffer);
-
-      yuv.y = pixels;
-      yuv.u = yuv.y + y_size;
-      yuv.v = yuv.u + y_size / 4;
-    } else {
-      GstBuffer *newbuf;
-      gint i;
-      guchar *dest_y, *src_y;
-      guchar *dest_u, *src_u;
-      guchar *dest_v, *src_v;
-      gint src_y_stride, src_uv_stride;
-      gint dst_y_stride, dst_uv_stride;
-      gint width, height;
-      gint cwidth, cheight;
-      gint offset_x, right_x, right_border;
-
-      GST_LOG_OBJECT (enc, "cropping/conversion needed for strides");
-      /* source width/height */
-      width = enc->width;
-      height = enc->height;
-      /* soucre chroma width/height */
-      cwidth = width / 2;
-      cheight = height / 2;
-
-      /* source strides as defined in videotestsrc */
-      src_y_stride = GST_ROUND_UP_4 (width);
-      src_uv_stride = GST_ROUND_UP_8 (width) / 2;
-
-      /* destination strides from the real picture width */
-      dst_y_stride = enc->info_width;
-      dst_uv_stride = enc->info_width / 2;
-
-      newbuf = gst_buffer_new_and_alloc (y_size * 3 / 2);
-      if (!newbuf) {
-        ret = GST_FLOW_ERROR;
-        goto no_buffer;
-      }
-      GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
-      gst_buffer_set_caps (newbuf, GST_PAD_CAPS (enc->srcpad));
-
-      dest_y = yuv.y = GST_BUFFER_DATA (newbuf);
-      dest_u = yuv.u = yuv.y + y_size;
-      dest_v = yuv.v = yuv.u + y_size / 4;
-
-      src_y = GST_BUFFER_DATA (buffer);
-      src_u = src_y + src_y_stride * GST_ROUND_UP_2 (height);
-      src_v = src_u + src_uv_stride * GST_ROUND_UP_2 (height) / 2;
-
-      if (enc->border != BORDER_NONE) {
-        /* fill top border */
-        for (i = 0; i < enc->offset_y; i++) {
-          memset (dest_y, 0, dst_y_stride);
-          dest_y += dst_y_stride;
-        }
-      } else {
-        dest_y += dst_y_stride * enc->offset_y;
-      }
-
-      offset_x = enc->offset_x;
-      right_x = width + enc->offset_x;
-      right_border = dst_y_stride - right_x;
-
-      /* copy Y plane */
-      for (i = 0; i < height; i++) {
-        memcpy (dest_y + offset_x, src_y, width);
-        if (enc->border != BORDER_NONE) {
-          memset (dest_y, 0, offset_x);
-          memset (dest_y + right_x, 0, right_border);
-        }
-
-        dest_y += dst_y_stride;
-        src_y += src_y_stride;
-      }
-
-      if (enc->border != BORDER_NONE) {
-        /* fill bottom border */
-        for (i = height + enc->offset_y; i < enc->info.height; i++) {
-          memset (dest_y, 0, dst_y_stride);
-          dest_y += dst_y_stride;
-        }
-
-        /* fill top border chroma */
-        for (i = 0; i < enc->offset_y / 2; i++) {
-          memset (dest_u, 128, dst_uv_stride);
-          memset (dest_v, 128, dst_uv_stride);
-          dest_u += dst_uv_stride;
-          dest_v += dst_uv_stride;
-        }
-      } else {
-        dest_u += dst_uv_stride * enc->offset_y / 2;
-        dest_v += dst_uv_stride * enc->offset_y / 2;
-      }
-
-      offset_x = enc->offset_x / 2;
-      right_x = cwidth + offset_x;
-      right_border = dst_uv_stride - right_x;
-
-      /* copy UV planes */
-      for (i = 0; i < cheight; i++) {
-        memcpy (dest_v + offset_x, src_v, cwidth);
-        memcpy (dest_u + offset_x, src_u, cwidth);
-
-        if (enc->border != BORDER_NONE) {
-          memset (dest_u, 128, offset_x);
-          memset (dest_u + right_x, 128, right_border);
-          memset (dest_v, 128, offset_x);
-          memset (dest_v + right_x, 128, right_border);
-        }
-
-        dest_u += dst_uv_stride;
-        dest_v += dst_uv_stride;
-        src_u += src_uv_stride;
-        src_v += src_uv_stride;
-      }
-
-      if (enc->border != BORDER_NONE) {
-        /* fill bottom border */
-        for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
-          memset (dest_u, 128, dst_uv_stride);
-          memset (dest_v, 128, dst_uv_stride);
-          dest_u += dst_uv_stride;
-          dest_v += dst_uv_stride;
-        }
-      }
-
-      gst_buffer_unref (buffer);
-      buffer = newbuf;
-    }
-
-    if (theora_enc_is_discontinuous (enc, buffer)) {
-      theora_enc_reset (enc);
-      enc->granulepos_offset =
-          gst_util_uint64_scale (in_time, enc->fps_n, GST_SECOND * enc->fps_d);
-      enc->timestamp_offset = in_time;
-      enc->next_ts = 0;
-      enc->next_discont = TRUE;
-    }
-
-    res = theora_encode_YUVin (&enc->state, &yuv);
-
-    ret = GST_FLOW_OK;
-    while (theora_encode_packetout (&enc->state, 0, &op)) {
-      GstClockTime next_time = theora_enc_get_ogg_packet_end_time (enc, &op);
-
-      ret =
-          theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
-      enc->next_ts = next_time;
-      if (ret != GST_FLOW_OK)
-        goto data_push;
-    }
-    gst_buffer_unref (buffer);
-  }
-
-  return ret;
-
-  /* ERRORS */
-header_buffer_alloc:
-  {
-    gst_buffer_unref (buffer);
-    return ret;
-  }
-header_push:
-  {
-    gst_buffer_unref (buffer);
-    return ret;
-  }
-no_buffer:
-  {
-    return ret;
-  }
-data_push:
-  {
-    gst_buffer_unref (buffer);
-    return ret;
-  }
-encoder_disabled:
-  {
-    GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
-        ("libtheora has been compiled with the encoder disabled"));
-    gst_buffer_unref (buffer);
-    return GST_FLOW_ERROR;
-  }
-}
-
-static GstStateChangeReturn
-theora_enc_change_state (GstElement * element, GstStateChange transition)
-{
-  GstTheoraEnc *enc;
-  GstStateChangeReturn ret;
-
-  enc = GST_THEORA_ENC (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
-      theora_info_init (&enc->info);
-      theora_comment_init (&enc->comment);
-      enc->packetno = 0;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  ret = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
-      theora_clear (&enc->state);
-      theora_comment_clear (&enc->comment);
-      theora_info_clear (&enc->info);
-
-      theora_enc_clear (enc);
-      enc->initialised = FALSE;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-static void
-theora_enc_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstTheoraEnc *enc = GST_THEORA_ENC (object);
-
-  switch (prop_id) {
-    case ARG_CENTER:
-      enc->center = g_value_get_boolean (value);
-      break;
-    case ARG_BORDER:
-      enc->border = g_value_get_enum (value);
-      break;
-    case ARG_BITRATE:
-      enc->video_bitrate = g_value_get_int (value) * 1000;
-      enc->video_quality = 0;
-      break;
-    case ARG_QUALITY:
-      enc->video_quality = g_value_get_int (value);
-      enc->video_bitrate = 0;
-      break;
-    case ARG_QUICK:
-      enc->quick = g_value_get_boolean (value);
-      break;
-    case ARG_KEYFRAME_AUTO:
-      enc->keyframe_auto = g_value_get_boolean (value);
-      break;
-    case ARG_KEYFRAME_FREQ:
-      enc->keyframe_freq = g_value_get_int (value);
-      break;
-    case ARG_KEYFRAME_FREQ_FORCE:
-      enc->keyframe_force = g_value_get_int (value);
-      break;
-    case ARG_KEYFRAME_THRESHOLD:
-      enc->keyframe_threshold = g_value_get_int (value);
-      break;
-    case ARG_KEYFRAME_MINDISTANCE:
-      enc->keyframe_mindistance = g_value_get_int (value);
-      break;
-    case ARG_NOISE_SENSITIVITY:
-      enc->noise_sensitivity = g_value_get_int (value);
-      break;
-    case ARG_SHARPNESS:
-      enc->sharpness = g_value_get_int (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-theora_enc_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstTheoraEnc *enc = GST_THEORA_ENC (object);
-
-  switch (prop_id) {
-    case ARG_CENTER:
-      g_value_set_boolean (value, enc->center);
-      break;
-    case ARG_BORDER:
-      g_value_set_enum (value, enc->border);
-      break;
-    case ARG_BITRATE:
-      g_value_set_int (value, enc->video_bitrate / 1000);
-      break;
-    case ARG_QUALITY:
-      g_value_set_int (value, enc->video_quality);
-      break;
-    case ARG_QUICK:
-      g_value_set_boolean (value, enc->quick);
-      break;
-    case ARG_KEYFRAME_AUTO:
-      g_value_set_boolean (value, enc->keyframe_auto);
-      break;
-    case ARG_KEYFRAME_FREQ:
-      g_value_set_int (value, enc->keyframe_freq);
-      break;
-    case ARG_KEYFRAME_FREQ_FORCE:
-      g_value_set_int (value, enc->keyframe_force);
-      break;
-    case ARG_KEYFRAME_THRESHOLD:
-      g_value_set_int (value, enc->keyframe_threshold);
-      break;
-    case ARG_KEYFRAME_MINDISTANCE:
-      g_value_set_int (value, enc->keyframe_mindistance);
-      break;
-    case ARG_NOISE_SENSITIVITY:
-      g_value_set_int (value, enc->noise_sensitivity);
-      break;
-    case ARG_SHARPNESS:
-      g_value_set_int (value, enc->sharpness);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
--- a/gst_plugins_base/ext/theora/theoraparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,917 +0,0 @@
-/* GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2006 Andy Wingo <wingo@pobox.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.
- */
-
-/**
- * SECTION:element-theoraparse
- * @short_description: parses theora streams 
- * @see_also: theoradec, oggdemux, vorbisparse
- *
- * <refsect2>
- * <para>
- * The theoraparse element will parse the header packets of the Theora
- * stream and put them as the streamheader in the caps. This is used in the
- * multifdsink case where you want to stream live theora streams to multiple
- * clients, each client has to receive the streamheaders first before they can
- * consume the theora packets.
- * </para>
- * <para>
- * This element also makes sure that the buffers that it pushes out are properly
- * timestamped and that their offset and offset_end are set. The buffers that
- * vorbisparse outputs have all of the metadata that oggmux expects to receive,
- * which allows you to (for example) remux an ogg/theora file.
- * </para>
- * <para>
- * In addition, this element allows you to fix badly synchronized streams. You
- * pass in an array of (granule time, buffer time) synchronization points via
- * the synchronization-points GValueArray property, and this element will adjust
- * the granulepos values that it outputs. The adjustment will be made by
- * offsetting all buffers that it outputs by a specified amount, and updating
- * that offset from the value array whenever a keyframe is processed.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=video.ogg ! oggdemux ! theoraparse ! fakesink
- * </programlisting>
- * This pipeline shows that the streamheader is set in the caps, and that each
- * buffer has the timestamp, duration, offset, and offset_end set.
- * </para>
- * <para>
- * <programlisting>
- * gst-launch filesrc location=video.ogg ! oggdemux ! vorbisparse \
- *            ! oggmux ! filesink location=video-remuxed.ogg
- * </programlisting>
- * This pipeline shows remuxing. video-remuxed.ogg might not be exactly the same
- * as video.ogg, but they should produce exactly the same decoded data.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-04-01 (0.10.4.1)
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "gsttheoraparse.h"
-
-#define GST_CAT_DEFAULT theoraparse_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-static GstElementDetails theora_parse_details = {
-  "Theora video parser",
-  "Codec/Parser/Video",
-  "parse raw theora streams",
-  "Andy Wingo <wingo@pobox.com>"
-};
-
-static GstStaticPadTemplate theora_parse_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-theora")
-    );
-
-static GstStaticPadTemplate theora_parse_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-theora")
-    );
-
-enum
-{
-  PROP_0,
-  PROP_SYNCHRONIZATION_POINTS
-};
-
-GST_BOILERPLATE (GstTheoraParse, gst_theora_parse, GstElement,
-    GST_TYPE_ELEMENT);
-
-static void theora_parse_dispose (GObject * object);
-static void theora_parse_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void theora_parse_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-
-static gboolean theora_parse_src_query (GstPad * pad, GstQuery * query);
-static GstFlowReturn theora_parse_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn theora_parse_change_state (GstElement * element,
-    GstStateChange transition);
-static gboolean theora_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean theora_parse_src_query (GstPad * pad, GstQuery * query);
-
-static void
-gst_theora_parse_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&theora_parse_src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&theora_parse_sink_factory));
-  gst_element_class_set_details (element_class, &theora_parse_details);
-}
-
-static void
-gst_theora_parse_class_init (GstTheoraParseClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->dispose = theora_parse_dispose;
-  gobject_class->get_property = theora_parse_get_property;
-  gobject_class->set_property = theora_parse_set_property;
-
-  /**
-   * GstTheoraParse:sychronization-points
-   *
-   * An array of (granuletime, buffertime) pairs
-   *
-   * Since: 0.10.10
-   */
-  g_object_class_install_property (gobject_class, PROP_SYNCHRONIZATION_POINTS,
-      g_param_spec_value_array ("synchronization-points",
-          "Synchronization points",
-          "An array of (granuletime, buffertime) pairs",
-          g_param_spec_uint64 ("time", "Time",
-              "Time (either granuletime or buffertime)", 0, G_MAXUINT64, 0,
-              G_PARAM_READWRITE), (GParamFlags) G_PARAM_READWRITE));
-
-  gstelement_class->change_state = theora_parse_change_state;
-
-  GST_DEBUG_CATEGORY_INIT (theoraparse_debug, "theoraparse", 0,
-      "Theora parser");
-}
-
-static void
-gst_theora_parse_init (GstTheoraParse * parse, GstTheoraParseClass * g_class)
-{
-  parse->sinkpad =
-      gst_pad_new_from_static_template (&theora_parse_sink_factory, "sink");
-  gst_pad_set_chain_function (parse->sinkpad, theora_parse_chain);
-  gst_pad_set_event_function (parse->sinkpad, theora_parse_sink_event);
-  gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
-
-  parse->srcpad =
-      gst_pad_new_from_static_template (&theora_parse_src_factory, "src");
-  gst_pad_set_query_function (parse->srcpad, theora_parse_src_query);
-  gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
-}
-
-static void
-theora_parse_dispose (GObject * object)
-{
-  GstTheoraParse *parse = GST_THEORA_PARSE (object);
-
-  g_free (parse->times);
-  parse->times = NULL;
-
-  G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-theora_parse_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstTheoraParse *parse = GST_THEORA_PARSE (object);
-
-  switch (prop_id) {
-    case PROP_SYNCHRONIZATION_POINTS:
-    {
-      GValueArray *array;
-      guint i;
-
-      array = g_value_get_boxed (value);
-
-      if (array) {
-        if (array->n_values % 2)
-          goto odd_values;
-
-        g_free (parse->times);
-        parse->times = g_new (GstClockTime, array->n_values);
-        parse->npairs = array->n_values / 2;
-        for (i = 0; i < array->n_values; i++)
-          parse->times[i] = g_value_get_uint64 (&array->values[i]);
-      } else {
-        g_free (parse->times);
-        parse->npairs = 0;
-      }
-    }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  return;
-
-odd_values:
-  {
-    g_critical ("expected an even number of time values for "
-        "synchronization-points");
-    return;
-  }
-}
-
-static void
-theora_parse_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstTheoraParse *parse = GST_THEORA_PARSE (object);
-
-  switch (prop_id) {
-    case PROP_SYNCHRONIZATION_POINTS:
-    {
-      GValueArray *array = NULL;
-      guint i;
-
-      array = g_value_array_new (parse->npairs * 2);
-
-      for (i = 0; i < parse->npairs; i++) {
-        GValue v = { 0, };
-
-        g_value_init (&v, G_TYPE_UINT64);
-        g_value_set_uint64 (&v, parse->times[i * 2]);
-        g_value_array_append (array, &v);
-        g_value_set_uint64 (&v, parse->times[i * 2 + 1]);
-        g_value_array_append (array, &v);
-        g_value_unset (&v);
-      }
-
-      g_value_set_boxed (value, array);
-    }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-theora_parse_set_header_on_caps (GstTheoraParse * parse, GstCaps * caps)
-{
-  GstBuffer **bufs;
-  GstStructure *structure;
-  gint i;
-  GValue array = { 0 };
-  GValue value = { 0 };
-
-  bufs = parse->streamheader;
-  structure = gst_caps_get_structure (caps, 0);
-  g_value_init (&array, GST_TYPE_ARRAY);
-
-  for (i = 0; i < 3; i++) {
-    g_assert (bufs[i]);
-    bufs[i] = gst_buffer_make_metadata_writable (bufs[i]);
-    GST_BUFFER_FLAG_SET (bufs[i], GST_BUFFER_FLAG_IN_CAPS);
-
-    g_value_init (&value, GST_TYPE_BUFFER);
-    gst_value_set_buffer (&value, bufs[i]);
-    gst_value_array_append_value (&array, &value);
-    g_value_unset (&value);
-  }
-
-  gst_structure_set_value (structure, "streamheader", &array);
-  g_value_unset (&array);
-}
-
-/* FIXME: copy from libtheora, theora should somehow make this available for seeking */
-static int
-_theora_ilog (unsigned int v)
-{
-  int ret = 0;
-
-  while (v) {
-    ret++;
-    v >>= 1;
-  }
-  return (ret);
-}
-
-/* two tasks to do here: set the streamheader on the caps, and use libtheora to
-   parse the headers */
-static void
-theora_parse_set_streamheader (GstTheoraParse * parse)
-{
-  GstCaps *caps;
-  gint i;
-  guint32 bitstream_version;
-
-  g_assert (!parse->streamheader_received);
-
-  caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad));
-  theora_parse_set_header_on_caps (parse, caps);
-  GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps);
-  gst_pad_set_caps (parse->srcpad, caps);
-  gst_caps_unref (caps);
-
-  for (i = 0; i < 3; i++) {
-    ogg_packet packet;
-    GstBuffer *buf;
-
-    buf = parse->streamheader[i];
-    gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
-
-    packet.packet = GST_BUFFER_DATA (buf);
-    packet.bytes = GST_BUFFER_SIZE (buf);
-    packet.granulepos = GST_BUFFER_OFFSET_END (buf);
-    packet.packetno = i + 1;
-    packet.e_o_s = 0;
-    theora_decode_header (&parse->info, &parse->comment, &packet);
-  }
-
-  parse->fps_n = parse->info.fps_numerator;
-  parse->fps_d = parse->info.fps_denominator;
-  parse->shift = _theora_ilog (parse->info.keyframe_frequency_force - 1);
-
-  /* With libtheora-1.0beta1 the granulepos scheme was changed:
-   * where earlier the granulepos refered to the index/beginning
-   * of a frame, it now refers to the end, which matches the use
-   * in vorbis/speex. We check the bitstream version from the header so
-   * we know which way to interpret the incoming granuepos
-   */
-  bitstream_version = (parse->info.version_major << 16) |
-      (parse->info.version_minor << 8) | parse->info.version_subminor;
-  parse->is_old_bitstream = (bitstream_version <= 0x00030200);
-
-  parse->streamheader_received = TRUE;
-}
-
-static void
-theora_parse_drain_event_queue (GstTheoraParse * parse)
-{
-  while (parse->event_queue->length) {
-    GstEvent *event;
-
-    event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
-    gst_pad_event_default (parse->sinkpad, event);
-  }
-}
-
-static void
-theora_parse_push_headers (GstTheoraParse * parse)
-{
-  gint i;
-
-  theora_parse_drain_event_queue (parse);
-
-  if (!parse->streamheader_received)
-    theora_parse_set_streamheader (parse);
-
-  /* ignore return values, we pass along the result of pushing data packets only
-   */
-  for (i = 0; i < 3; i++)
-    gst_pad_push (parse->srcpad, gst_buffer_ref (parse->streamheader[i]));
-
-  parse->send_streamheader = FALSE;
-}
-
-static void
-theora_parse_clear_queue (GstTheoraParse * parse)
-{
-  while (parse->buffer_queue->length) {
-    GstBuffer *buf;
-
-    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-    gst_buffer_unref (buf);
-  }
-  while (parse->event_queue->length) {
-    GstEvent *event;
-
-    event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
-    gst_buffer_unref (event);
-  }
-}
-
-static gint64
-make_granulepos (GstTheoraParse * parse, gint64 keyframe, gint64 frame)
-{
-  if (keyframe == -1)
-    keyframe = 0;
-  /* If using newer theora, offset the granulepos by +1, see comment
-   * in theora_parse_set_streamheader */
-  if (!parse->is_old_bitstream)
-    keyframe += 1;
-
-  g_return_val_if_fail (frame >= keyframe, -1);
-  g_return_val_if_fail (frame - keyframe < 1 << parse->shift, -1);
-
-  return (keyframe << parse->shift) + (frame - keyframe);
-}
-
-static void
-parse_granulepos (GstTheoraParse * parse, gint64 granulepos,
-    gint64 * keyframe, gint64 * frame)
-{
-  gint64 kf;
-
-  kf = granulepos >> parse->shift;
-  /* If using newer theora, offset the granulepos by -1, see comment
-   * in theora_parse_set_streamheader */
-  if (!parse->is_old_bitstream)
-    kf -= 1;
-  if (keyframe)
-    *keyframe = kf;
-  if (frame)
-    *frame = kf + (granulepos & ((1 << parse->shift) - 1));
-}
-
-static gboolean
-is_keyframe (GstBuffer * buf)
-{
-  if (!GST_BUFFER_DATA (buf))
-    return FALSE;
-  if (!GST_BUFFER_SIZE (buf))
-    return FALSE;
-  return ((GST_BUFFER_DATA (buf)[0] & 0x40) == 0);
-}
-
-static void
-theora_parse_munge_granulepos (GstTheoraParse * parse, GstBuffer * buf,
-    gint64 keyframe, gint64 frame)
-{
-  gint64 frames_diff;
-  GstClockTimeDiff time_diff;
-
-  if (keyframe == frame) {
-    gint i;
-
-    /* update granule_offset */
-    for (i = 0; i < parse->npairs; i++) {
-      if (parse->times[i * 2] >= GST_BUFFER_OFFSET (buf))
-        break;
-    }
-    if (i > 0) {
-      /* time_diff gets reset below */
-      time_diff = parse->times[i * 2 - 1] - parse->times[i * 2 - 2];
-      parse->granule_offset = gst_util_uint64_scale (time_diff,
-          parse->fps_n, parse->fps_d * GST_SECOND);
-      parse->granule_offset <<= parse->shift;
-    }
-  }
-
-  frames_diff = parse->granule_offset >> parse->shift;
-  time_diff = gst_util_uint64_scale_int (GST_SECOND * frames_diff,
-      parse->fps_d, parse->fps_n);
-
-  GST_DEBUG_OBJECT (parse, "offsetting theora stream by %" G_GINT64_FORMAT
-      " frames (%" GST_TIME_FORMAT ")", frames_diff, GST_TIME_ARGS (time_diff));
-
-  GST_BUFFER_OFFSET_END (buf) += parse->granule_offset;
-  GST_BUFFER_OFFSET (buf) += time_diff;
-  GST_BUFFER_TIMESTAMP (buf) += time_diff;
-}
-
-static GstFlowReturn
-theora_parse_push_buffer (GstTheoraParse * parse, GstBuffer * buf,
-    gint64 keyframe, gint64 frame)
-{
-
-  GstClockTime this_time, next_time;
-
-  this_time = gst_util_uint64_scale_int (GST_SECOND * frame,
-      parse->fps_d, parse->fps_n);
-
-  next_time = gst_util_uint64_scale_int (GST_SECOND * (frame + 1),
-      parse->fps_d, parse->fps_n);
-
-  GST_BUFFER_OFFSET_END (buf) = make_granulepos (parse, keyframe, frame);
-  GST_BUFFER_OFFSET (buf) = this_time;
-  GST_BUFFER_TIMESTAMP (buf) = this_time;
-  GST_BUFFER_DURATION (buf) = next_time - this_time;
-
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
-
-  if (parse->times)
-    theora_parse_munge_granulepos (parse, buf, keyframe, frame);
-
-  GST_DEBUG_OBJECT (parse, "pushing buffer with granulepos %" G_GINT64_FORMAT
-      "|%" G_GINT64_FORMAT, keyframe, frame - keyframe);
-
-  return gst_pad_push (parse->srcpad, buf);
-}
-
-static GstFlowReturn
-theora_parse_drain_queue_prematurely (GstTheoraParse * parse)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  /* got an EOS event, make sure to push out any buffers that were in the queue
-   * -- won't normally be the case, but this catches the
-   * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous
-   * stream. */
-
-  GST_DEBUG_OBJECT (parse, "got EOS, draining queue");
-
-  /* if we get an eos before pushing the streamheaders, drain our events before
-   * eos */
-  theora_parse_drain_event_queue (parse);
-
-  while (!g_queue_is_empty (parse->buffer_queue)) {
-    GstBuffer *buf;
-
-    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
-    parse->prev_frame++;
-
-    if (is_keyframe (buf))
-      /* we have a keyframe */
-      parse->prev_keyframe = parse->prev_frame;
-    else
-      GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT;
-
-    if (parse->prev_keyframe < 0) {
-      if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
-        parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
-            &parse->prev_keyframe, NULL);
-      } else {
-        /* No previous keyframe known; can't extract one from this frame. That
-         * means we can't do any valid output for this frame, just continue to
-         * the next frame.
-         */
-        gst_buffer_unref (buf);
-        continue;
-      }
-    }
-
-    ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe,
-        parse->prev_frame);
-
-    if (ret != GST_FLOW_OK)
-      goto done;
-  }
-
-done:
-  return ret;
-}
-
-static GstFlowReturn
-theora_parse_drain_queue (GstTheoraParse * parse, gint64 granulepos)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  gint64 keyframe, prev_frame, frame;
-
-  parse_granulepos (parse, granulepos, &keyframe, &frame);
-
-  prev_frame = frame - g_queue_get_length (parse->buffer_queue);
-  if (prev_frame < parse->prev_frame) {
-    GST_WARNING ("jumped %" G_GINT64_FORMAT
-        " frames backwards! not sure what to do here",
-        parse->prev_frame - prev_frame);
-    ret = GST_FLOW_ERROR;
-    goto done;
-  } else if (prev_frame > parse->prev_frame) {
-    GST_INFO ("discontinuity detected (%" G_GINT64_FORMAT
-        " frames)", prev_frame - parse->prev_frame);
-    if (keyframe <= prev_frame && keyframe > parse->prev_keyframe)
-      parse->prev_keyframe = keyframe;
-    parse->prev_frame = prev_frame;
-  }
-
-  GST_DEBUG ("draining queue of length %d",
-      g_queue_get_length (parse->buffer_queue));
-
-  while (!g_queue_is_empty (parse->buffer_queue)) {
-    GstBuffer *buf;
-
-    parse->prev_frame++;
-    g_assert (parse->prev_frame >= 0);
-
-    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
-    if (is_keyframe (buf))
-      /* we have a keyframe */
-      parse->prev_keyframe = parse->prev_frame;
-    else
-      GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT;
-
-    ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe,
-        parse->prev_frame);
-
-    if (ret != GST_FLOW_OK)
-      goto done;
-  }
-
-done:
-  return ret;
-}
-
-static GstFlowReturn
-theora_parse_queue_buffer (GstTheoraParse * parse, GstBuffer * buf)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  buf = gst_buffer_make_metadata_writable (buf);
-
-  g_queue_push_tail (parse->buffer_queue, buf);
-
-  if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
-    if (parse->prev_keyframe < 0) {
-      parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
-          &parse->prev_keyframe, NULL);
-    }
-    ret = theora_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
-  }
-
-  return ret;
-}
-
-static GstFlowReturn
-theora_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstFlowReturn ret;
-  GstBuffer *buf;
-  GstTheoraParse *parse;
-
-  parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
-  buf = GST_BUFFER (buffer);
-  parse->packetno++;
-
-  if (parse->packetno <= 3) {
-    /* if 1 <= packetno <= 3, it's streamheader,
-     * so put it on the streamheader list and return */
-    parse->streamheader[parse->packetno - 1] = buf;
-    ret = GST_FLOW_OK;
-  } else {
-    if (parse->send_streamheader)
-      theora_parse_push_headers (parse);
-
-    ret = theora_parse_queue_buffer (parse, buf);
-  }
-
-  gst_object_unref (parse);
-
-  return ret;
-}
-
-static gboolean
-theora_parse_queue_event (GstTheoraParse * parse, GstEvent * event)
-{
-  g_queue_push_tail (parse->event_queue, event);
-  return TRUE;
-}
-
-static gboolean
-theora_parse_sink_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret;
-  GstTheoraParse *parse;
-
-  parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_STOP:
-      theora_parse_clear_queue (parse);
-      parse->prev_keyframe = -1;
-      parse->prev_frame = -1;
-      ret = gst_pad_event_default (pad, event);
-      break;
-    case GST_EVENT_EOS:
-      theora_parse_drain_queue_prematurely (parse);
-      ret = gst_pad_event_default (pad, event);
-      break;
-    default:
-      if (parse->send_streamheader && GST_EVENT_IS_SERIALIZED (event))
-        ret = theora_parse_queue_event (parse, event);
-      else
-        ret = gst_pad_event_default (pad, event);
-      break;
-  }
-
-  gst_object_unref (parse);
-
-  return ret;
-}
-
-static gboolean
-theora_parse_src_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  GstTheoraParse *parse;
-  guint64 scale = 1;
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
-  /* we need the info part before we can done something */
-  if (!parse->streamheader_received)
-    goto no_header;
-
-  switch (src_format) {
-    case GST_FORMAT_BYTES:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          *dest_value = gst_util_uint64_scale_int (src_value, 2,
-              parse->info.height * parse->info.width * 3);
-          break;
-        case GST_FORMAT_TIME:
-          /* seems like a rather silly conversion, implement me if you like */
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          scale = 3 * (parse->info.width * parse->info.height) / 2;
-        case GST_FORMAT_DEFAULT:
-          *dest_value = scale * gst_util_uint64_scale (src_value,
-              parse->info.fps_numerator,
-              parse->info.fps_denominator * GST_SECOND);
-          break;
-        default:
-          GST_DEBUG_OBJECT (parse, "cannot convert to format %s",
-              gst_format_get_name (*dest_format));
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          *dest_value = gst_util_uint64_scale (src_value,
-              GST_SECOND * parse->info.fps_denominator,
-              parse->info.fps_numerator);
-          break;
-        case GST_FORMAT_BYTES:
-          *dest_value = gst_util_uint64_scale_int (src_value,
-              3 * parse->info.width * parse->info.height, 2);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-done:
-  gst_object_unref (parse);
-  return res;
-
-  /* ERRORS */
-no_header:
-  {
-    GST_DEBUG_OBJECT (parse, "no header yet, cannot convert");
-    res = FALSE;
-    goto done;
-  }
-}
-
-static gboolean
-theora_parse_src_query (GstPad * pad, GstQuery * query)
-{
-  GstTheoraParse *parse;
-
-  gboolean res = FALSE;
-
-  parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    {
-      gint64 frame, value;
-      GstFormat my_format, format;
-      gint64 time;
-
-      frame = parse->prev_frame;
-
-      GST_LOG_OBJECT (parse,
-          "query %p: we have current frame: %lld", query, frame);
-
-      /* parse format */
-      gst_query_parse_position (query, &format, NULL);
-
-      /* and convert to the final format in two steps with time as the 
-       * intermediate step */
-      my_format = GST_FORMAT_TIME;
-      if (!(res =
-              theora_parse_src_convert (parse->sinkpad, GST_FORMAT_DEFAULT,
-                  frame, &my_format, &time)))
-        goto error;
-
-      /* fixme: handle segments
-         time = (time - parse->segment.start) + parse->segment.time;
-       */
-
-      GST_LOG_OBJECT (parse,
-          "query %p: our time: %" GST_TIME_FORMAT " (conv to %s)",
-          query, GST_TIME_ARGS (time), gst_format_get_name (format));
-
-      if (!(res =
-              theora_parse_src_convert (pad, my_format, time, &format, &value)))
-        goto error;
-
-      gst_query_set_position (query, format, value);
-
-      GST_LOG_OBJECT (parse,
-          "query %p: we return %lld (format %u)", query, value, format);
-
-      break;
-    }
-    case GST_QUERY_DURATION:
-      /* forward to peer for total */
-      if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query)))
-        goto error;
-      break;
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              theora_parse_src_convert (pad, src_fmt, src_val, &dest_fmt,
-                  &dest_val)))
-        goto error;
-
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-done:
-  gst_object_unref (parse);
-
-  return res;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (parse, "query failed");
-    goto done;
-  }
-}
-
-static GstStateChangeReturn
-theora_parse_change_state (GstElement * element, GstStateChange transition)
-{
-  GstTheoraParse *parse = GST_THEORA_PARSE (element);
-  GstStateChangeReturn ret;
-  gint i;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      theora_info_init (&parse->info);
-      theora_comment_init (&parse->comment);
-      parse->packetno = 0;
-      parse->send_streamheader = TRUE;
-      parse->buffer_queue = g_queue_new ();
-      parse->event_queue = g_queue_new ();
-      parse->prev_keyframe = -1;
-      parse->prev_frame = -1;
-      parse->granule_offset = 0;
-      break;
-    default:
-      break;
-  }
-
-  ret = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      theora_info_clear (&parse->info);
-      theora_comment_clear (&parse->comment);
-      theora_parse_clear_queue (parse);
-      g_queue_free (parse->buffer_queue);
-      g_queue_free (parse->event_queue);
-      parse->buffer_queue = NULL;
-      for (i = 0; i < 3; i++) {
-        if (parse->streamheader[i]) {
-          gst_buffer_unref (parse->streamheader[i]);
-          parse->streamheader[i] = NULL;
-        }
-      }
-      parse->streamheader_received = FALSE;
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
--- a/gst_plugins_base/ext/vorbis/vorbis.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst/tag/tag.h"
-
-#include "vorbisenc.h"
-#include "vorbisdec.h"
-#include "vorbisparse.h"
-#include "vorbistag.h"
-
-GST_DEBUG_CATEGORY (vorbisenc_debug);
-GST_DEBUG_CATEGORY (vorbisdec_debug);
-GST_DEBUG_CATEGORY (vorbisparse_debug);
-GST_DEBUG_CATEGORY (vorbistag_debug);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  if (!gst_element_register (plugin, "vorbisenc", GST_RANK_NONE,
-          GST_TYPE_VORBISENC))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "vorbisdec", GST_RANK_PRIMARY,
-          gst_vorbis_dec_get_type ()))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "vorbisparse", GST_RANK_NONE,
-          gst_vorbis_parse_get_type ()))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "vorbistag", GST_RANK_NONE,
-          gst_vorbis_tag_get_type ()))
-    return FALSE;
-
-  GST_DEBUG_CATEGORY_INIT (vorbisenc_debug, "vorbisenc", 0,
-      "vorbis encoding element");
-  GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "vorbisdec", 0,
-      "vorbis decoding element");
-  GST_DEBUG_CATEGORY_INIT (vorbisparse_debug, "vorbisparse", 0,
-      "vorbis parsing element");
-  GST_DEBUG_CATEGORY_INIT (vorbistag_debug, "vorbistag", 0,
-      "vorbis tagging element");
-
-  gst_tag_register_musicbrainz_tags ();
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "vorbis",
-    "Vorbis plugin library",
-    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/vorbis/vorbisdec.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1408 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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.
- */
-
-/**
- * SECTION:element-vorbisdec
- * @short_description: a decoder that decodes Vorbis to raw audio
- * @see_also: vorbisenc, oggdemux
- *
- * <refsect2>
- * <para>
- * This element decodes a Vorbis stream to raw float audio.
- * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
- * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
- * </programlisting>
- * Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the documentation of vorbisenc.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "vorbisdec.h"
-#include <string.h>
-#include <gst/audio/audio.h>
-#include <gst/tag/tag.h>
-#include <gst/audio/multichannel.h>
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug);
-#define GST_CAT_DEFAULT vorbisdec_debug
-
-static const GstElementDetails vorbis_dec_details =
-GST_ELEMENT_DETAILS ("Vorbis audio decoder",
-    "Codec/Decoder/Audio",
-    "decode raw vorbis streams to float audio",
-    "Benjamin Otte <in7y118@public.uni-hamburg.de>");
-
-static GstStaticPadTemplate vorbis_dec_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-float, "
-        "rate = (int) [ 1, MAX ], "
-        "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, "
-/* no ifdef in macros, please
-#ifdef GST_VORBIS_DEC_SEQUENTIAL
-      "layout = \"sequential\", "
-#endif
-*/
-        "width = (int) 32")
-    );
-
-static GstStaticPadTemplate vorbis_dec_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-vorbis")
-    );
-
-GST_BOILERPLATE (GstVorbisDec, gst_vorbis_dec, GstElement, GST_TYPE_ELEMENT);
-
-static void vorbis_dec_finalize (GObject * object);
-static gboolean vorbis_dec_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn vorbis_dec_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn vorbis_dec_chain_forward (GstVorbisDec * vd,
-    gboolean discont, GstBuffer * buffer);
-static GstStateChangeReturn vorbis_dec_change_state (GstElement * element,
-    GstStateChange transition);
-
-static gboolean vorbis_dec_src_event (GstPad * pad, GstEvent * event);
-static gboolean vorbis_dec_src_query (GstPad * pad, GstQuery * query);
-static gboolean vorbis_dec_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value);
-
-static gboolean vorbis_dec_sink_query (GstPad * pad, GstQuery * query);
-
-static void
-gst_vorbis_dec_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  GstPadTemplate *src_template, *sink_template;
-
-  src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
-  gst_element_class_add_pad_template (element_class, src_template);
-
-  sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory);
-  gst_element_class_add_pad_template (element_class, sink_template);
-
-  gst_element_class_set_details (element_class, &vorbis_dec_details);
-}
-
-static void
-gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->finalize = vorbis_dec_finalize;
-
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (vorbis_dec_change_state);
-}
-
-static const GstQueryType *
-vorbis_get_query_types (GstPad * pad)
-{
-  static const GstQueryType vorbis_dec_src_query_types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    0
-  };
-
-  return vorbis_dec_src_query_types;
-}
-
-static void
-gst_vorbis_dec_init (GstVorbisDec * dec, GstVorbisDecClass * g_class)
-{
-  dec->sinkpad = gst_pad_new_from_static_template (&vorbis_dec_sink_factory,
-      "sink");
-
-  gst_pad_set_event_function (dec->sinkpad,
-      GST_DEBUG_FUNCPTR (vorbis_dec_sink_event));
-  gst_pad_set_chain_function (dec->sinkpad,
-      GST_DEBUG_FUNCPTR (vorbis_dec_chain));
-  gst_pad_set_query_function (dec->sinkpad,
-      GST_DEBUG_FUNCPTR (vorbis_dec_sink_query));
-  gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
-
-  dec->srcpad = gst_pad_new_from_static_template (&vorbis_dec_src_factory,
-      "src");
-
-  gst_pad_set_event_function (dec->srcpad,
-      GST_DEBUG_FUNCPTR (vorbis_dec_src_event));
-  gst_pad_set_query_type_function (dec->srcpad,
-      GST_DEBUG_FUNCPTR (vorbis_get_query_types));
-  gst_pad_set_query_function (dec->srcpad,
-      GST_DEBUG_FUNCPTR (vorbis_dec_src_query));
-  gst_pad_use_fixed_caps (dec->srcpad);
-  gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
-
-  dec->queued = NULL;
-  dec->pendingevents = NULL;
-  dec->taglist = NULL;
-}
-
-static void
-vorbis_dec_finalize (GObject * object)
-{
-  /* Release any possibly allocated libvorbis data.
-   * _clear functions can safely be called multiple times
-   */
-  GstVorbisDec *vd = GST_VORBIS_DEC (object);
-
-  vorbis_block_clear (&vd->vb);
-  vorbis_dsp_clear (&vd->vd);
-  vorbis_comment_clear (&vd->vc);
-  vorbis_info_clear (&vd->vi);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_vorbis_dec_reset (GstVorbisDec * dec)
-{
-  dec->cur_timestamp = GST_CLOCK_TIME_NONE;
-  dec->prev_timestamp = GST_CLOCK_TIME_NONE;
-  dec->granulepos = -1;
-  dec->discont = TRUE;
-  gst_segment_init (&dec->segment, GST_FORMAT_TIME);
-
-  g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->queued);
-  dec->queued = NULL;
-  g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->gather);
-  dec->gather = NULL;
-  g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->decode);
-  dec->decode = NULL;
-  g_list_foreach (dec->pendingevents, (GFunc) gst_mini_object_unref, NULL);
-  g_list_free (dec->pendingevents);
-  dec->pendingevents = NULL;
-
-  if (dec->taglist)
-    gst_tag_list_free (dec->taglist);
-  dec->taglist = NULL;
-}
-
-
-static gboolean
-vorbis_dec_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  GstVorbisDec *dec;
-  guint64 scale = 1;
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
-  if (!dec->initialized)
-    goto no_header;
-
-  if (dec->sinkpad == pad &&
-      (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
-    goto no_format;
-
-  switch (src_format) {
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          scale = sizeof (float) * dec->vi.channels;
-        case GST_FORMAT_DEFAULT:
-          *dest_value =
-              scale * gst_util_uint64_scale_int (src_value, dec->vi.rate,
-              GST_SECOND);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          *dest_value = src_value * sizeof (float) * dec->vi.channels;
-          break;
-        case GST_FORMAT_TIME:
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, GST_SECOND, dec->vi.rate);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_BYTES:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          *dest_value = src_value / (sizeof (float) * dec->vi.channels);
-          break;
-        case GST_FORMAT_TIME:
-          *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
-              dec->vi.rate * sizeof (float) * dec->vi.channels);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-done:
-  gst_object_unref (dec);
-
-  return res;
-
-  /* ERRORS */
-no_header:
-  {
-    GST_DEBUG_OBJECT (dec, "no header packets received");
-    res = FALSE;
-    goto done;
-  }
-no_format:
-  {
-    GST_DEBUG_OBJECT (dec, "formats unsupported");
-    res = FALSE;
-    goto done;
-  }
-}
-
-static gboolean
-vorbis_dec_src_query (GstPad * pad, GstQuery * query)
-{
-  GstVorbisDec *dec;
-  gboolean res = FALSE;
-
-  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    {
-      gint64 granulepos, value;
-      GstFormat my_format, format;
-      gint64 time;
-
-      /* we start from the last seen granulepos */
-      granulepos = dec->granulepos;
-
-      gst_query_parse_position (query, &format, NULL);
-
-      /* and convert to the final format in two steps with time as the
-       * intermediate step */
-      my_format = GST_FORMAT_TIME;
-      if (!(res =
-              vorbis_dec_convert (pad, GST_FORMAT_DEFAULT, granulepos,
-                  &my_format, &time)))
-        goto error;
-
-      /* correct for the segment values */
-      time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
-
-      GST_LOG_OBJECT (dec,
-          "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
-
-      /* and convert to the final format */
-      if (!(res = vorbis_dec_convert (pad, my_format, time, &format, &value)))
-        goto error;
-
-      gst_query_set_position (query, format, value);
-
-      GST_LOG_OBJECT (dec,
-          "query %p: we return %lld (format %u)", query, value, format);
-
-      break;
-    }
-    case GST_QUERY_DURATION:
-    {
-      GstPad *peer;
-
-      if (!(peer = gst_pad_get_peer (dec->sinkpad))) {
-        GST_WARNING_OBJECT (dec, "sink pad %" GST_PTR_FORMAT " is not linked",
-            dec->sinkpad);
-        goto error;
-      }
-
-      res = gst_pad_query (peer, query);
-      gst_object_unref (peer);
-      if (!res)
-        goto error;
-
-      break;
-    }
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
-        goto error;
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-done:
-  gst_object_unref (dec);
-
-  return res;
-
-  /* ERRORS */
-error:
-  {
-    GST_WARNING_OBJECT (dec, "error handling query");
-    goto done;
-  }
-}
-
-static gboolean
-vorbis_dec_sink_query (GstPad * pad, GstQuery * query)
-{
-  GstVorbisDec *dec;
-  gboolean res;
-
-  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
-        goto error;
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-
-done:
-  gst_object_unref (dec);
-
-  return res;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (dec, "error converting value");
-    goto done;
-  }
-}
-
-static gboolean
-vorbis_dec_src_event (GstPad * pad, GstEvent * event)
-{
-  gboolean res = TRUE;
-  GstVorbisDec *dec;
-
-  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_SEEK:
-    {
-      GstFormat format, tformat;
-      gdouble rate;
-      GstEvent *real_seek;
-      GstSeekFlags flags;
-      GstSeekType cur_type, stop_type;
-      gint64 cur, stop;
-      gint64 tcur, tstop;
-
-      gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
-          &stop_type, &stop);
-      gst_event_unref (event);
-
-      /* we have to ask our peer to seek to time here as we know
-       * nothing about how to generate a granulepos from the src
-       * formats or anything.
-       *
-       * First bring the requested format to time
-       */
-      tformat = GST_FORMAT_TIME;
-      if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur)))
-        goto convert_error;
-      if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop)))
-        goto convert_error;
-
-      /* then seek with time on the peer */
-      real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
-          flags, cur_type, tcur, stop_type, tstop);
-
-      res = gst_pad_push_event (dec->sinkpad, real_seek);
-
-      break;
-    }
-    default:
-      res = gst_pad_push_event (dec->sinkpad, event);
-      break;
-  }
-done:
-  gst_object_unref (dec);
-
-  return res;
-
-  /* ERRORS */
-convert_error:
-  {
-    GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
-    goto done;
-  }
-}
-
-static gboolean
-vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret = FALSE;
-  GstVorbisDec *dec;
-
-  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
-  GST_LOG_OBJECT (dec, "handling event");
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-    case GST_EVENT_FLUSH_START:
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      /* here we must clean any state in the decoder */
-#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
-      vorbis_synthesis_restart (&dec->vd);
-#endif
-      gst_vorbis_dec_reset (dec);
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-    case GST_EVENT_NEWSEGMENT:
-    {
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-      gboolean update;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      /* we need time for now */
-      if (format != GST_FORMAT_TIME)
-        goto newseg_wrong_format;
-
-      GST_DEBUG_OBJECT (dec,
-          "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT
-          ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT,
-          update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
-          GST_TIME_ARGS (time));
-
-      /* now configure the values */
-      gst_segment_set_newsegment_full (&dec->segment, update,
-          rate, arate, format, start, stop, time);
-
-      if (dec->initialized)
-        /* and forward */
-        ret = gst_pad_push_event (dec->srcpad, event);
-      else {
-        /* store it to send once we're initialized */
-        dec->pendingevents = g_list_append (dec->pendingevents, event);
-        ret = TRUE;
-      }
-      break;
-    }
-    default:
-      ret = gst_pad_push_event (dec->srcpad, event);
-      break;
-  }
-done:
-  gst_object_unref (dec);
-
-  return ret;
-
-  /* ERRORS */
-newseg_wrong_format:
-  {
-    GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
-    goto done;
-  }
-}
-
-static GstFlowReturn
-vorbis_handle_identification_packet (GstVorbisDec * vd)
-{
-  GstCaps *caps;
-  const GstAudioChannelPosition *pos = NULL;
-
-  switch (vd->vi.channels) {
-    case 1:
-    case 2:
-      /* nothing */
-      break;
-    case 3:{
-      static const GstAudioChannelPosition pos3[] = {
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
-      };
-      pos = pos3;
-      break;
-    }
-    case 4:{
-      static const GstAudioChannelPosition pos4[] = {
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
-      };
-      pos = pos4;
-      break;
-    }
-    case 5:{
-      static const GstAudioChannelPosition pos5[] = {
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
-      };
-      pos = pos5;
-      break;
-    }
-    case 6:{
-      static const GstAudioChannelPosition pos6[] = {
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_LFE
-      };
-      pos = pos6;
-      break;
-    }
-    default:
-      goto channel_count_error;
-  }
-
-  caps = gst_caps_new_simple ("audio/x-raw-float",
-      "rate", G_TYPE_INT, vd->vi.rate,
-      "channels", G_TYPE_INT, vd->vi.channels,
-      "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
-
-  if (pos) {
-    gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
-  }
-  gst_pad_set_caps (vd->srcpad, caps);
-  gst_caps_unref (caps);
-
-  return GST_FLOW_OK;
-
-  /* ERROR */
-channel_count_error:
-  {
-    GST_ELEMENT_ERROR (vd, STREAM, NOT_IMPLEMENTED, (NULL),
-        ("Unsupported channel count %d", vd->vi.channels));
-    return GST_FLOW_ERROR;
-  }
-}
-
-static GstFlowReturn
-vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
-{
-  guint bitrate = 0;
-  gchar *encoder = NULL;
-  GstTagList *list;
-  GstBuffer *buf;
-
-  GST_DEBUG_OBJECT (vd, "parsing comment packet");
-
-  buf = gst_buffer_new_and_alloc (packet->bytes);
-  GST_BUFFER_DATA (buf) = packet->packet;
-
-  list =
-      gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
-      &encoder);
-
-  vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);
-
-  gst_tag_list_free (list);
-  gst_buffer_unref (buf);
-
-  if (!vd->taglist) {
-    GST_ERROR_OBJECT (vd, "couldn't decode comments");
-    vd->taglist = gst_tag_list_new ();
-  }
-  if (encoder) {
-    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
-        GST_TAG_ENCODER, encoder, NULL);
-    g_free (encoder);
-  }
-  gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
-      GST_TAG_ENCODER_VERSION, vd->vi.version,
-      GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
-  if (vd->vi.bitrate_nominal > 0) {
-    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
-        GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
-    bitrate = vd->vi.bitrate_nominal;
-  }
-  if (vd->vi.bitrate_upper > 0) {
-    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
-        GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
-    if (!bitrate)
-      bitrate = vd->vi.bitrate_upper;
-  }
-  if (vd->vi.bitrate_lower > 0) {
-    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
-        GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
-    if (!bitrate)
-      bitrate = vd->vi.bitrate_lower;
-  }
-  if (bitrate) {
-    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
-        GST_TAG_BITRATE, (guint) bitrate, NULL);
-  }
-
-  if (vd->initialized) {
-    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad,
-        vd->taglist);
-    vd->taglist = NULL;
-  } else {
-    /* Only post them as messages for the time being. *
-     * They will be pushed on the pad once the decoder is initialized */
-    gst_element_post_message (GST_ELEMENT_CAST (vd),
-        gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
-  }
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-vorbis_handle_type_packet (GstVorbisDec * vd)
-{
-  GList *walk;
-
-  g_assert (vd->initialized == FALSE);
-
-  vorbis_synthesis_init (&vd->vd, &vd->vi);
-  vorbis_block_init (&vd->vd, &vd->vb);
-  vd->initialized = TRUE;
-
-  if (vd->pendingevents) {
-    for (walk = vd->pendingevents; walk; walk = g_list_next (walk))
-      gst_pad_push_event (vd->srcpad, GST_EVENT_CAST (walk->data));
-    g_list_free (vd->pendingevents);
-    vd->pendingevents = NULL;
-  }
-
-  if (vd->taglist) {
-    /* The tags have already been sent on the bus as messages. */
-    gst_pad_push_event (vd->srcpad, gst_event_new_tag (vd->taglist));
-    vd->taglist = NULL;
-  }
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet)
-{
-  GstFlowReturn res;
-
-  GST_DEBUG_OBJECT (vd, "parsing header packet");
-
-  /* Packetno = 0 if the first byte is exactly 0x01 */
-  packet->b_o_s = (packet->packet[0] == 0x1) ? 1 : 0;
-
-  if (vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet))
-    goto header_read_error;
-
-  switch (packet->packet[0]) {
-    case 0x01:
-      res = vorbis_handle_identification_packet (vd);
-      break;
-    case 0x03:
-      res = vorbis_handle_comment_packet (vd, packet);
-      break;
-    case 0x05:
-      res = vorbis_handle_type_packet (vd);
-      break;
-    default:
-      /* ignore */
-      g_warning ("unknown vorbis header packet found");
-      res = GST_FLOW_OK;
-      break;
-  }
-  return res;
-
-  /* ERRORS */
-header_read_error:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
-        (NULL), ("couldn't read header packet"));
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* These samples can be outside of the float -1.0 -- 1.0 range, this
- * is allowed, downstream elements are supposed to clip */
-static void
-copy_samples (float *out, float **in, guint samples, gint channels)
-{
-  gint i, j;
-
-#ifdef GST_VORBIS_DEC_SEQUENTIAL
-  for (i = 0; i < channels; i++) {
-    memcpy (out, in[i], samples * sizeof (float));
-    out += samples;
-  }
-#else
-  for (j = 0; j < samples; j++) {
-    for (i = 0; i < channels; i++) {
-      *out++ = in[i][j];
-    }
-  }
-#endif
-}
-
-static GstFlowReturn
-vorbis_dec_push_forward (GstVorbisDec * dec, GstBuffer * buf)
-{
-  GstFlowReturn result;
-  gint64 outoffset, origoffset;
-
-  origoffset = GST_BUFFER_OFFSET (buf);
-
-again:
-  outoffset = origoffset;
-
-  if (outoffset == -1) {
-    dec->queued = g_list_append (dec->queued, buf);
-    GST_DEBUG_OBJECT (dec, "queued buffer");
-    result = GST_FLOW_OK;
-  } else {
-    if (G_UNLIKELY (dec->queued)) {
-      guint size;
-      GstClockTime ts;
-      GList *walk;
-
-      GST_DEBUG_OBJECT (dec, "first buffer with offset %lld", outoffset);
-      ts = gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
-
-      size = g_list_length (dec->queued);
-      /* we walk the queued up list in reverse, and set the buffer fields
-       * calculating backwards */
-      for (walk = g_list_last (dec->queued); walk;
-          walk = g_list_previous (walk)) {
-        GstBuffer *buffer = GST_BUFFER (walk->data);
-        guint offset;
-
-        offset = GST_BUFFER_SIZE (buffer) / (sizeof (float) * dec->vi.channels);
-
-        if (outoffset >= offset)
-          outoffset -= offset;
-        else {
-          /* we can't go below 0, this means this first offset was at the eos
-           * page and we need to clip to it instead */
-          GST_DEBUG_OBJECT (dec, "clipping %" G_GINT64_FORMAT,
-              offset - outoffset);
-          origoffset += (offset - outoffset);
-          goto again;
-        }
-
-        GST_BUFFER_OFFSET (buffer) = outoffset;
-        GST_BUFFER_TIMESTAMP (buffer) =
-            gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
-        GST_BUFFER_DURATION (buffer) = GST_CLOCK_DIFF (GST_BUFFER_TIMESTAMP
-            (buffer), ts);
-        ts = GST_BUFFER_TIMESTAMP (buffer);
-        GST_DEBUG_OBJECT (dec, "patch buffer %u, offset %" G_GUINT64_FORMAT
-            ", timestamp %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
-            size, outoffset,
-            GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
-            GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
-        size--;
-      }
-      for (walk = dec->queued; walk; walk = g_list_next (walk)) {
-        GstBuffer *buffer = GST_BUFFER (walk->data);
-
-        /* clips to the configured segment, or returns NULL with buffer
-         * unreffed when the input buffer is completely outside the segment */
-        if (!(buffer = gst_audio_buffer_clip (buffer, &dec->segment,
-                    dec->vi.rate, dec->vi.channels * sizeof (float))))
-          continue;
-
-        if (dec->discont) {
-          GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
-          dec->discont = FALSE;
-        }
-        /* ignore the result */
-        gst_pad_push (dec->srcpad, buffer);
-      }
-      g_list_free (dec->queued);
-      dec->queued = NULL;
-    }
-
-    /* clip */
-    if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate,
-                dec->vi.channels * sizeof (float))))
-      return GST_FLOW_OK;
-
-    if (dec->discont) {
-      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
-      dec->discont = FALSE;
-    }
-
-    result = gst_pad_push (dec->srcpad, buf);
-  }
-
-  return result;
-}
-
-static GstFlowReturn
-vorbis_dec_push_reverse (GstVorbisDec * dec, GstBuffer * buf)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-
-  dec->queued = g_list_prepend (dec->queued, buf);
-
-  return result;
-}
-
-static GstFlowReturn
-vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet)
-{
-  float **pcm;
-  guint sample_count;
-  GstBuffer *out;
-  GstFlowReturn result;
-  GstClockTime timestamp = GST_CLOCK_TIME_NONE, nextts;
-  gint size;
-
-  if (!vd->initialized)
-    goto not_initialized;
-
-  /* FIXME, we should queue undecoded packets here until we get
-   * a timestamp, then we reverse timestamp the queued packets and
-   * clip them, then we decode only the ones we want and don't
-   * keep decoded data in memory.
-   * Ideally, of course, the demuxer gives us a valid timestamp on
-   * the first packet.
-   */
-
-  /* normal data packet */
-  /* FIXME, we can skip decoding if the packet is outside of the
-   * segment, this is however not very trivial as we need a previous
-   * packet to decode the current one so we must be carefull not to
-   * throw away too much. For now we decode everything and clip right
-   * before pushing data. */
-  if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet)))
-    goto could_not_read;
-
-  if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0))
-    goto not_accepted;
-
-  /* assume all goes well here */
-  result = GST_FLOW_OK;
-
-  /* count samples ready for reading */
-  if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0)
-    goto done;
-
-  GST_LOG_OBJECT (vd, "%d samples ready for reading", sample_count);
-  size = sample_count * vd->vi.channels * sizeof (float);
-
-  /* alloc buffer for it */
-  result =
-      gst_pad_alloc_buffer_and_set_caps (vd->srcpad, GST_BUFFER_OFFSET_NONE,
-      size, GST_PAD_CAPS (vd->srcpad), &out);
-  if (G_UNLIKELY (result != GST_FLOW_OK))
-    goto done;
-
-  /* get samples ready for reading now, should be sample_count */
-  if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count))
-    goto wrong_samples;
-
-  /* copy samples in buffer */
-  copy_samples ((float *) GST_BUFFER_DATA (out), pcm, sample_count,
-      vd->vi.channels);
-
-  GST_BUFFER_SIZE (out) = size;
-
-  /* this should not overflow */
-  GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate;
-
-  if (packet->granulepos != -1)
-    vd->granulepos = packet->granulepos - sample_count;
-
-  if (vd->cur_timestamp != GST_CLOCK_TIME_NONE) {
-    /* we have incoming timestamps */
-    timestamp = vd->cur_timestamp;
-    GST_DEBUG_OBJECT (vd,
-        "cur_timestamp: %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = %"
-        GST_TIME_FORMAT, GST_TIME_ARGS (vd->cur_timestamp),
-        GST_TIME_ARGS (GST_BUFFER_DURATION (out)),
-        GST_TIME_ARGS (vd->cur_timestamp + GST_BUFFER_DURATION (out)));
-    vd->cur_timestamp += GST_BUFFER_DURATION (out);
-    GST_BUFFER_OFFSET (out) = GST_CLOCK_TIME_TO_FRAMES (vd->cur_timestamp,
-        vd->vi.rate);
-    GST_BUFFER_OFFSET_END (out) = GST_BUFFER_OFFSET (out) + sample_count;
-  } else {
-    /* we have incoming granulepos */
-    GST_BUFFER_OFFSET (out) = vd->granulepos;
-    if (vd->granulepos != -1) {
-      GST_DEBUG_OBJECT (vd, "granulepos: %" G_GINT64_FORMAT, vd->granulepos);
-      GST_BUFFER_OFFSET_END (out) = vd->granulepos + sample_count;
-      timestamp =
-          gst_util_uint64_scale_int (vd->granulepos, GST_SECOND, vd->vi.rate);
-      nextts =
-          gst_util_uint64_scale_int (vd->granulepos + sample_count,
-          GST_SECOND, vd->vi.rate);
-      GST_DEBUG_OBJECT (vd, "corresponding timestamp %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (timestamp));
-      /* calculate a nano-second accurate duration */
-      GST_BUFFER_DURATION (out) = GST_CLOCK_DIFF (timestamp, nextts);
-      GST_DEBUG_OBJECT (vd, "set duration %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (GST_BUFFER_DURATION (out)));
-    } else {
-      timestamp = -1;
-    }
-  }
-  GST_BUFFER_TIMESTAMP (out) = timestamp;
-
-  if (vd->granulepos != -1)
-    vd->granulepos += sample_count;
-
-  if (vd->segment.rate >= 0.0)
-    result = vorbis_dec_push_forward (vd, out);
-  else
-    result = vorbis_dec_push_reverse (vd, out);
-
-done:
-  vorbis_synthesis_read (&vd->vd, sample_count);
-
-  GST_DEBUG_OBJECT (vd,
-      "decoded %ld bytes into %d samples, ts %" GST_TIME_FORMAT, packet->bytes,
-      sample_count, GST_TIME_ARGS (timestamp));
-
-  /* granulepos is the last sample in the packet */
-  if (packet->granulepos != -1)
-    vd->granulepos = packet->granulepos;
-
-  return result;
-
-  /* ERRORS */
-not_initialized:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
-        (NULL), ("no header sent yet"));
-    return GST_FLOW_ERROR;
-  }
-could_not_read:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
-        (NULL), ("couldn't read data packet"));
-    return GST_FLOW_ERROR;
-  }
-not_accepted:
-  {
-    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
-        (NULL), ("vorbis decoder did not accept data packet"));
-    return GST_FLOW_ERROR;
-  }
-wrong_samples:
-  {
-    gst_buffer_unref (out);
-    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
-        (NULL), ("vorbis decoder reported wrong number of samples"));
-    return GST_FLOW_ERROR;
-  }
-}
-
-static GstFlowReturn
-vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer)
-{
-  ogg_packet packet;
-  GstFlowReturn result = GST_FLOW_OK;
-  GstClockTime timestamp;
-  guint64 offset_end;
-
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  offset_end = GST_BUFFER_OFFSET_END (buffer);
-
-  /* only ogg has granulepos, demuxers of other container formats 
-   * might provide us with timestamps instead (e.g. matroskademux) */
-  if (offset_end == GST_BUFFER_OFFSET_NONE && timestamp != GST_CLOCK_TIME_NONE) {
-    /* we might get multiple consecutive buffers with the same timestamp */
-    if (timestamp != vd->prev_timestamp) {
-      vd->cur_timestamp = timestamp;
-      vd->prev_timestamp = timestamp;
-    }
-  } else {
-    vd->cur_timestamp = GST_CLOCK_TIME_NONE;
-    vd->prev_timestamp = GST_CLOCK_TIME_NONE;
-  }
-
-  /* make ogg_packet out of the buffer */
-  packet.packet = GST_BUFFER_DATA (buffer);
-  packet.bytes = GST_BUFFER_SIZE (buffer);
-  packet.granulepos = offset_end;
-  packet.packetno = 0;          /* we don't care */
-  /*
-   * FIXME. Is there anyway to know that this is the last packet and
-   * set e_o_s??
-   * Yes there is, keep one packet at all times and only push out when
-   * you receive a new one.  Implement this.
-   */
-  packet.e_o_s = 0;
-
-  /* error out on empty header packets, but just skip empty data packets */
-  if (G_UNLIKELY (packet.bytes == 0)) {
-    if (vd->initialized)
-      goto empty_buffer;
-    else
-      goto empty_header;
-  }
-
-  GST_DEBUG_OBJECT (vd, "vorbis granule: %" G_GINT64_FORMAT,
-      (gint64) packet.granulepos);
-
-  /* switch depending on packet type */
-  if (packet.packet[0] & 1) {
-    if (vd->initialized) {
-      GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet");
-      goto done;
-    }
-    result = vorbis_handle_header_packet (vd, &packet);
-  } else {
-    result = vorbis_handle_data_packet (vd, &packet);
-  }
-
-done:
-  return result;
-
-empty_buffer:
-  {
-    /* don't error out here, just ignore the buffer, it's invalid for vorbis
-     * but not fatal. */
-    GST_WARNING_OBJECT (vd, "empty buffer received, ignoring");
-    if (packet.granulepos != -1)
-      vd->granulepos = packet.granulepos;
-    result = GST_FLOW_OK;
-    goto done;
-  }
-
-/* ERRORS */
-empty_header:
-  {
-    GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty header received"));
-    result = GST_FLOW_ERROR;
-    vd->discont = TRUE;
-    goto done;
-  }
-}
-
-/* 
- * Input:
- *  Buffer decoding order:  7  8  9  4  5  6  3  1  2  EOS
- *  Discont flag:           D        D        D  D
- *
- * - Each Discont marks a discont in the decoding order.
- *
- * for vorbis, each buffer is a keyframe when we have the previous
- * buffer. This means that to decode buffer 7, we need buffer 6, which
- * arrives out of order.
- *
- * we first gather buffers in the gather queue until we get a DISCONT. We 
- * prepend each incomming buffer so that they are in reversed order.
- *   
- *    gather queue:    9  8  7
- *    decode queue:    
- *    output queue:    
- *
- * When a DISCONT is received (buffer 4), we move the gather queue to the 
- * decode queue. This is simply done be taking the head of the gather queue
- * and prepending it to the decode queue. This yields:
- * 
- *    gather queue:    
- *    decode queue:    7  8  9
- *    output queue:    
- *
- * Then we decode each buffer in the decode queue in order and put the output
- * buffer in the output queue. The first buffer (7) will not produce and output
- * because it needs the previous buffer (6) which did not arrive yet. This
- * yields:
- *
- *    gather queue:    
- *    decode queue:    7  8  9
- *    output queue:    9  8
- *
- * Then we remove the consumed buffers from the decode queue. Buffer 7 is not
- * completely consumed, we need to keep it around for when we receive buffer 
- * 6. This yields:
- *
- *    gather queue:    
- *    decode queue:    7 
- *    output queue:    9  8
- *
- * Then we accumulate more buffers:
- *
- *    gather queue:    6  5  4
- *    decode queue:    7
- *    output queue:    
- *
- * prepending to the decode queue on DISCONT yields:
- *
- *    gather queue:   
- *    decode queue:    4  5  6  7
- *    output queue:    
- *
- * after decoding and keeping buffer 4:
- *
- *    gather queue:   
- *    decode queue:    4 
- *    output queue:    7  6  5 
- *
- * Etc..
- */
-static GstFlowReturn
-vorbis_dec_flush_decode (GstVorbisDec * dec)
-{
-  GstFlowReturn res = GST_FLOW_OK;
-  GList *walk;
-
-  walk = dec->decode;
-
-  GST_DEBUG_OBJECT (dec, "flushing buffers to decoder");
-
-  while (walk) {
-    GList *next;
-    GstBuffer *buf = GST_BUFFER_CAST (walk->data);
-
-    GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT,
-        buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
-    next = g_list_next (walk);
-
-    /* decode buffer, prepend to output queue */
-    res = vorbis_dec_decode_buffer (dec, buf);
-
-    /* if we generated output, we can discard the buffer, else we
-     * keep it in the queue */
-    if (dec->queued) {
-      GST_DEBUG_OBJECT (dec, "decoded buffer to %p", dec->queued->data);
-      dec->decode = g_list_delete_link (dec->decode, walk);
-      gst_buffer_unref (buf);
-    } else {
-      GST_DEBUG_OBJECT (dec, "buffer did not decode, keeping");
-    }
-    walk = next;
-  }
-  if (dec->granulepos != -1) {
-    GstClockTime endts;
-
-    endts =
-        gst_util_uint64_scale_int (dec->granulepos, GST_SECOND, dec->vi.rate);
-
-    GST_DEBUG_OBJECT (dec, "we have granulepos %" G_GUINT64_FORMAT ", ts %"
-        GST_TIME_FORMAT, dec->granulepos, GST_TIME_ARGS (endts));
-
-    while (dec->queued) {
-      GstBuffer *buf;
-      guint sample_count;
-
-      buf = GST_BUFFER_CAST (dec->queued->data);
-
-      sample_count =
-          GST_BUFFER_SIZE (buf) / (dec->vi.channels * sizeof (float));
-
-      GST_BUFFER_OFFSET_END (buf) = dec->granulepos;
-      endts =
-          gst_util_uint64_scale_int (dec->granulepos, GST_SECOND, dec->vi.rate);
-      dec->granulepos -= sample_count;
-      GST_BUFFER_OFFSET (buf) = dec->granulepos;
-      GST_BUFFER_TIMESTAMP (buf) =
-          gst_util_uint64_scale_int (dec->granulepos, GST_SECOND, dec->vi.rate);
-      GST_BUFFER_DURATION (buf) = endts - GST_BUFFER_TIMESTAMP (buf);
-
-      /* clip, this will unref the buffer in case of clipping */
-      if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate,
-                  dec->vi.channels * sizeof (float)))) {
-        GST_DEBUG_OBJECT (dec, "clipped buffer %p", buf);
-        goto next;
-      }
-
-      if (dec->discont) {
-        GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
-        dec->discont = FALSE;
-      }
-      GST_DEBUG_OBJECT (dec, "pushing buffer %p, samples %u, "
-          "ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
-          buf, sample_count, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
-          GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
-
-      res = gst_pad_push (dec->srcpad, buf);
-    next:
-      dec->queued = g_list_delete_link (dec->queued, dec->queued);
-    }
-  } else {
-    GST_DEBUG_OBJECT (dec, "we don't have a granulepos yet, delayed push");
-  }
-  return res;
-}
-
-static GstFlowReturn
-vorbis_dec_chain_reverse (GstVorbisDec * vd, gboolean discont, GstBuffer * buf)
-{
-  GstFlowReturn result = GST_FLOW_OK;
-
-  /* if we have a discont, move buffers to the decode list */
-  if (G_UNLIKELY (discont)) {
-    GST_DEBUG_OBJECT (vd, "received discont");
-    while (vd->gather) {
-      GstBuffer *gbuf;
-
-      gbuf = GST_BUFFER_CAST (vd->gather->data);
-      /* remove from the gather list */
-      vd->gather = g_list_delete_link (vd->gather, vd->gather);
-      /* copy to decode queue */
-      vd->decode = g_list_prepend (vd->decode, gbuf);
-    }
-    /* flush and decode the decode queue */
-    result = vorbis_dec_flush_decode (vd);
-  }
-
-  GST_DEBUG_OBJECT (vd, "gathering buffer %p, size %u", buf,
-      GST_BUFFER_SIZE (buf));
-  /* add buffer to gather queue */
-  vd->gather = g_list_prepend (vd->gather, buf);
-
-  return result;
-}
-
-static GstFlowReturn
-vorbis_dec_chain_forward (GstVorbisDec * vd, gboolean discont,
-    GstBuffer * buffer)
-{
-  GstFlowReturn result;
-
-  result = vorbis_dec_decode_buffer (vd, buffer);
-
-  gst_buffer_unref (buffer);
-
-  return result;
-
-}
-
-static GstFlowReturn
-vorbis_dec_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstVorbisDec *vd;
-  GstFlowReturn result = GST_FLOW_OK;
-  gboolean discont;
-
-  vd = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
-  discont = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT);
-
-  /* resync on DISCONT */
-  if (G_UNLIKELY (discont)) {
-    GST_DEBUG_OBJECT (vd, "received DISCONT buffer");
-    vd->granulepos = -1;
-    vd->cur_timestamp = GST_CLOCK_TIME_NONE;
-    vd->prev_timestamp = GST_CLOCK_TIME_NONE;
-#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
-    vorbis_synthesis_restart (&vd->vd);
-#endif
-    vd->discont = TRUE;
-  }
-
-  if (vd->segment.rate >= 0.0)
-    result = vorbis_dec_chain_forward (vd, discont, buffer);
-  else
-    result = vorbis_dec_chain_reverse (vd, discont, buffer);
-
-  gst_object_unref (vd);
-
-  return result;
-}
-
-static GstStateChangeReturn
-vorbis_dec_change_state (GstElement * element, GstStateChange transition)
-{
-  GstVorbisDec *vd = GST_VORBIS_DEC (element);
-  GstStateChangeReturn res;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      vorbis_info_init (&vd->vi);
-      vorbis_comment_init (&vd->vc);
-      vd->initialized = FALSE;
-      gst_vorbis_dec_reset (vd);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  res = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      GST_DEBUG_OBJECT (vd, "PAUSED -> READY, clearing vorbis structures");
-      vorbis_block_clear (&vd->vb);
-      vorbis_dsp_clear (&vd->vd);
-      vorbis_comment_clear (&vd->vc);
-      vorbis_info_clear (&vd->vi);
-      gst_vorbis_dec_reset (vd);
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return res;
-}
--- a/gst_plugins_base/ext/vorbis/vorbisdec.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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_VORBIS_DEC_H__
-#define __GST_VORBIS_DEC_H__
-
-
-#include <gst/gst.h>
-#include <vorbis/codec.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_VORBIS_DEC \
-  (gst_vorbis_dec_get_type())
-#define GST_VORBIS_DEC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_DEC,GstVorbisDec))
-#define GST_VORBIS_DEC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_DEC,GstVorbisDecClass))
-#define GST_IS_VORBIS_DEC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_DEC))
-#define GST_IS_VORBIS_DEC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_DEC))
-
-typedef struct _GstVorbisDec GstVorbisDec;
-typedef struct _GstVorbisDecClass GstVorbisDecClass;
-
-/**
- * GstVorbisDec:
- *
- * Opaque data structure.
- */
-struct _GstVorbisDec {
-  GstElement        element;
-
-  GstPad           *sinkpad;
-  GstPad           *srcpad;
-
-  vorbis_dsp_state  vd;
-  vorbis_info       vi;
-  vorbis_comment    vc;
-  vorbis_block      vb;
-  guint64           granulepos;
-
-  gboolean          initialized;
-
-  /* list of buffers that need timestamps */
-  GList            *queued;
-  /* list of raw output buffers */
-  GList            *output;
-  /* gather/decode queues for reverse playback */
-  GList            *gather;
-  GList            *decode;
-
-  GstSegment        segment;
-  gboolean          discont;
-
-  GstClockTime      cur_timestamp; /* only used with non-ogg container formats */
-  GstClockTime      prev_timestamp; /* only used with non-ogg container formats */
-
-  GList            *pendingevents;
-  GstTagList       *taglist;
-};
-
-struct _GstVorbisDecClass {
-  GstElementClass parent_class;
-};
-
-GType gst_vorbis_dec_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_DEC_H__ */
--- a/gst_plugins_base/ext/vorbis/vorbisenc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1389 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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.
- */
-
-/**
- * SECTION:element-vorbisenc
- * @short_description: an encoder that encodes audio to Vorbis
- * @see_also: vorbisdec, oggmux
- *
- * <refsect2>
- * <para>
- * This element encodes raw float audio into a Vorbis stream.
- * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
- * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * Encode a test sine signal to Ogg/Vorbis.  Note that the resulting file
- * will be really small because a sine signal compresses very well.
- * </para>
- * <programlisting>
- * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg
- * </programlisting>
- * <para>
- * Record from a sound card using ALSA and encode to Ogg/Vorbis.
- * </para>
- * <programlisting>
- * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <vorbis/vorbisenc.h>
-
-#include <gst/gsttagsetter.h>
-#include <gst/tag/tag.h>
-#include <gst/audio/multichannel.h>
-#include "vorbisenc.h"
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
-#define GST_CAT_DEFAULT vorbisenc_debug
-
-static GstPadTemplate *gst_vorbis_enc_src_template,
-    *gst_vorbis_enc_sink_template;
-
-/* elementfactory information */
-static const GstElementDetails vorbisenc_details =
-GST_ELEMENT_DETAILS ("Vorbis audio encoder",
-    "Codec/Encoder/Audio",
-    "Encodes audio in Vorbis format",
-    "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
-
-enum
-{
-  ARG_0,
-  ARG_MAX_BITRATE,
-  ARG_BITRATE,
-  ARG_MIN_BITRATE,
-  ARG_QUALITY,
-  ARG_MANAGED,
-  ARG_LAST_MESSAGE
-};
-
-static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
-
-/* this function takes into account the granulepos_offset and the subgranule
- * time offset */
-static GstClockTime
-granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc,
-    ogg_int64_t granulepos)
-{
-  if (granulepos >= 0)
-    return gst_util_uint64_scale ((guint64) granulepos
-        + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency)
-        + vorbisenc->subgranule_offset;
-  return GST_CLOCK_TIME_NONE;
-}
-
-/* this function does a straight granulepos -> timestamp conversion */
-static GstClockTime
-granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos)
-{
-  if (granulepos >= 0)
-    return gst_util_uint64_scale ((guint64) granulepos,
-        GST_SECOND, vorbisenc->frequency);
-  return GST_CLOCK_TIME_NONE;
-}
-
-#define MAX_BITRATE_DEFAULT     -1
-#define BITRATE_DEFAULT         -1
-#define MIN_BITRATE_DEFAULT     -1
-#define QUALITY_DEFAULT         0.3
-#define LOWEST_BITRATE          6000    /* lowest allowed for a 8 kHz stream */
-#define HIGHEST_BITRATE         250001  /* highest allowed for a 44 kHz stream */
-
-static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
-
-static void gst_vorbis_enc_dispose (GObject * object);
-static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element,
-    GstStateChange transition);
-static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
-
-GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstElement,
-    GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces);
-
-static void
-gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
-{
-  static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
-
-  g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
-      &tag_setter_info);
-}
-
-static GstCaps *
-vorbis_caps_factory (void)
-{
-  return gst_caps_new_simple ("audio/x-vorbis", NULL);
-}
-
-static GstCaps *
-raw_caps_factory (void)
-{
-  /* lowest, highest sample rates come from vorbis/lib/modes/setup_X.h:
-   * 1-200000 Hz */
-  return
-      gst_caps_new_simple ("audio/x-raw-float",
-      "rate", GST_TYPE_INT_RANGE, 1, 200000,
-      "channels", GST_TYPE_INT_RANGE, 1, 256,
-      "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
-}
-
-static void
-gst_vorbis_enc_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  GstCaps *raw_caps, *vorbis_caps;
-
-  raw_caps = raw_caps_factory ();
-  vorbis_caps = vorbis_caps_factory ();
-
-  gst_vorbis_enc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
-      GST_PAD_ALWAYS, raw_caps);
-  gst_vorbis_enc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
-      GST_PAD_ALWAYS, vorbis_caps);
-  gst_element_class_add_pad_template (element_class,
-      gst_vorbis_enc_sink_template);
-  gst_element_class_add_pad_template (element_class,
-      gst_vorbis_enc_src_template);
-  gst_element_class_set_details (element_class, &vorbisenc_details);
-}
-
-static void
-gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  gobject_class->set_property = gst_vorbis_enc_set_property;
-  gobject_class->get_property = gst_vorbis_enc_get_property;
-  gobject_class->dispose = gst_vorbis_enc_dispose;
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
-      g_param_spec_int ("max-bitrate", "Maximum Bitrate",
-          "Specify a maximum bitrate (in bps). Useful for streaming "
-          "applications. (-1 == disabled)",
-          -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
-      g_param_spec_int ("bitrate", "Target Bitrate",
-          "Attempt to encode at a bitrate averaging this (in bps). "
-          "This uses the bitrate management engine, and is not recommended for most users. "
-          "Quality is a better alternative. (-1 == disabled)",
-          -1, HIGHEST_BITRATE, BITRATE_DEFAULT, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
-      g_param_spec_int ("min_bitrate", "Minimum Bitrate",
-          "Specify a minimum bitrate (in bps). Useful for encoding for a "
-          "fixed-size channel. (-1 == disabled)",
-          -1, HIGHEST_BITRATE, MIN_BITRATE_DEFAULT, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
-      g_param_spec_float ("quality", "Quality",
-          "Specify quality instead of specifying a particular bitrate.",
-          -0.1, 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
-      g_param_spec_boolean ("managed", "Managed",
-          "Enable bitrate management engine", FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
-      g_param_spec_string ("last-message", "last-message",
-          "The last status message", NULL, G_PARAM_READABLE));
-
-  gstelement_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state);
-}
-
-static void
-gst_vorbis_enc_dispose (GObject * object)
-{
-  GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
-
-  if (vorbisenc->sinkcaps) {
-    gst_caps_unref (vorbisenc->sinkcaps);
-    vorbisenc->sinkcaps = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static const GstAudioChannelPosition vorbischannelpositions[][6] = {
-  {                             /* Mono */
-      GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
-  {                             /* Stereo */
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
-  {                             /* Stereo + Centre */
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
-  {                             /* Quadraphonic */
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-      },
-  {                             /* Stereo + Centre + rear stereo */
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-      },
-  {                             /* Full 5.1 Surround */
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_LFE,
-      },
-};
-static GstCaps *
-gst_vorbis_enc_generate_sink_caps (void)
-{
-  GstCaps *caps = gst_caps_new_empty ();
-  int i, c;
-
-  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
-          "rate", GST_TYPE_INT_RANGE, 1, 200000,
-          "channels", G_TYPE_INT, 1,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
-          NULL));
-
-  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
-          "rate", GST_TYPE_INT_RANGE, 1, 200000,
-          "channels", G_TYPE_INT, 2,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
-          NULL));
-
-  for (i = 3; i <= 6; i++) {
-    GValue chanpos = { 0 };
-    GValue pos = { 0 };
-    GstStructure *structure;
-
-    g_value_init (&chanpos, GST_TYPE_ARRAY);
-    g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
-
-    for (c = 0; c < i; c++) {
-      g_value_set_enum (&pos, vorbischannelpositions[i - 1][c]);
-      gst_value_array_append_value (&chanpos, &pos);
-    }
-    g_value_unset (&pos);
-
-    structure = gst_structure_new ("audio/x-raw-float",
-        "rate", GST_TYPE_INT_RANGE, 1, 200000,
-        "channels", G_TYPE_INT, i,
-        "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
-    gst_structure_set_value (structure, "channel-positions", &chanpos);
-    g_value_unset (&chanpos);
-
-    gst_caps_append_structure (caps, structure);
-  }
-
-  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
-          "rate", GST_TYPE_INT_RANGE, 1, 200000,
-          "channels", GST_TYPE_INT_RANGE, 7, 256,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
-          NULL));
-
-  return caps;
-}
-
-static GstCaps *
-gst_vorbis_enc_sink_getcaps (GstPad * pad)
-{
-  GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
-  if (vorbisenc->sinkcaps == NULL)
-    vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
-
-  return gst_caps_ref (vorbisenc->sinkcaps);
-}
-
-static gboolean
-gst_vorbis_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstVorbisEnc *vorbisenc;
-  GstStructure *structure;
-
-  vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-  vorbisenc->setup = FALSE;
-
-  structure = gst_caps_get_structure (caps, 0);
-  gst_structure_get_int (structure, "channels", &vorbisenc->channels);
-  gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
-
-  gst_vorbis_enc_setup (vorbisenc);
-
-  if (vorbisenc->setup)
-    return TRUE;
-
-  return FALSE;
-}
-
-static gboolean
-gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  GstVorbisEnc *vorbisenc;
-  gint64 avg;
-
-  vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
-
-  if (vorbisenc->samples_in == 0 ||
-      vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) {
-    gst_object_unref (vorbisenc);
-    return FALSE;
-  }
-
-  avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
-
-  switch (src_format) {
-    case GST_FORMAT_BYTES:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-  gst_object_unref (vorbisenc);
-  return res;
-}
-
-static gboolean
-gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  guint scale = 1;
-  gint bytes_per_sample;
-  GstVorbisEnc *vorbisenc;
-
-  vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
-
-  bytes_per_sample = vorbisenc->channels * 2;
-
-  switch (src_format) {
-    case GST_FORMAT_BYTES:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          if (bytes_per_sample == 0)
-            return FALSE;
-          *dest_value = src_value / bytes_per_sample;
-          break;
-        case GST_FORMAT_TIME:
-        {
-          gint byterate = bytes_per_sample * vorbisenc->frequency;
-
-          if (byterate == 0)
-            return FALSE;
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
-          break;
-        }
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          *dest_value = src_value * bytes_per_sample;
-          break;
-        case GST_FORMAT_TIME:
-          if (vorbisenc->frequency == 0)
-            return FALSE;
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, GST_SECOND,
-              vorbisenc->frequency);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          scale = bytes_per_sample;
-          /* fallthrough */
-        case GST_FORMAT_DEFAULT:
-          *dest_value =
-              gst_util_uint64_scale_int (src_value,
-              scale * vorbisenc->frequency, GST_SECOND);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-  gst_object_unref (vorbisenc);
-  return res;
-}
-
-static const GstQueryType *
-gst_vorbis_enc_get_query_types (GstPad * pad)
-{
-  static const GstQueryType gst_vorbis_enc_src_query_types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    0
-  };
-
-  return gst_vorbis_enc_src_query_types;
-}
-
-static gboolean
-gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
-{
-  gboolean res = TRUE;
-  GstVorbisEnc *vorbisenc;
-  GstPad *peerpad;
-
-  vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
-  peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    {
-      GstFormat fmt, req_fmt;
-      gint64 pos, val;
-
-      gst_query_parse_position (query, &req_fmt, NULL);
-      if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
-        gst_query_set_position (query, req_fmt, val);
-        break;
-      }
-
-      fmt = GST_FORMAT_TIME;
-      if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
-        break;
-
-      if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
-        gst_query_set_position (query, req_fmt, val);
-      }
-      break;
-    }
-    case GST_QUERY_DURATION:
-    {
-      GstFormat fmt, req_fmt;
-      gint64 dur, val;
-
-      gst_query_parse_duration (query, &req_fmt, NULL);
-      if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
-        gst_query_set_duration (query, req_fmt, val);
-        break;
-      }
-
-      fmt = GST_FORMAT_TIME;
-      if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
-        break;
-
-      if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
-        gst_query_set_duration (query, req_fmt, val);
-      }
-      break;
-    }
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
-                  &dest_val)))
-        goto error;
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-
-error:
-  gst_object_unref (peerpad);
-  gst_object_unref (vorbisenc);
-  return res;
-}
-
-static gboolean
-gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query)
-{
-  gboolean res = TRUE;
-  GstVorbisEnc *vorbisenc;
-
-  vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
-                  &dest_val)))
-        goto error;
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-
-error:
-  return res;
-}
-
-static void
-gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
-{
-  vorbisenc->sinkpad =
-      gst_pad_new_from_template (gst_vorbis_enc_sink_template, "sink");
-  gst_pad_set_event_function (vorbisenc->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event));
-  gst_pad_set_chain_function (vorbisenc->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain));
-  gst_pad_set_setcaps_function (vorbisenc->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_setcaps));
-  gst_pad_set_getcaps_function (vorbisenc->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps));
-  gst_pad_set_query_function (vorbisenc->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query));
-  gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
-
-  vorbisenc->srcpad =
-      gst_pad_new_from_template (gst_vorbis_enc_src_template, "src");
-  gst_pad_set_query_function (vorbisenc->srcpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query));
-  gst_pad_set_query_type_function (vorbisenc->srcpad,
-      GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types));
-  gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
-
-  vorbisenc->channels = -1;
-  vorbisenc->frequency = -1;
-
-  vorbisenc->managed = FALSE;
-  vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
-  vorbisenc->bitrate = BITRATE_DEFAULT;
-  vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
-  vorbisenc->quality = QUALITY_DEFAULT;
-  vorbisenc->quality_set = FALSE;
-  vorbisenc->last_message = NULL;
-}
-
-static void
-gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
-    gpointer vorbisenc)
-{
-  GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
-  GList *vc_list, *l;
-
-  vc_list = gst_tag_to_vorbis_comments (list, tag);
-
-  for (l = vc_list; l != NULL; l = l->next) {
-    const gchar *vc_string = (const gchar *) l->data;
-    gchar *key = NULL, *val = NULL;
-
-    GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
-    if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
-      vorbis_comment_add_tag (&enc->vc, key, val);
-      g_free (key);
-      g_free (val);
-    }
-  }
-
-  g_list_foreach (vc_list, (GFunc) g_free, NULL);
-  g_list_free (vc_list);
-}
-
-static void
-gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
-{
-  GstTagList *merged_tags;
-  const GstTagList *user_tags;
-
-  vorbis_comment_init (&enc->vc);
-
-  user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
-
-  GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
-  GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
-
-  /* gst_tag_list_merge() will handle NULL for either or both lists fine */
-  merged_tags = gst_tag_list_merge (user_tags, enc->tags,
-      gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
-
-  if (merged_tags) {
-    GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
-    gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
-    gst_tag_list_free (merged_tags);
-  }
-}
-
-static gchar *
-get_constraints_string (GstVorbisEnc * vorbisenc)
-{
-  gint min = vorbisenc->min_bitrate;
-  gint max = vorbisenc->max_bitrate;
-  gchar *result;
-
-  if (min > 0 && max > 0)
-    result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
-  else if (min > 0)
-    result = g_strdup_printf ("(min %d bps, no max)", min);
-  else if (max > 0)
-    result = g_strdup_printf ("(no min, max %d bps)", max);
-  else
-    result = g_strdup_printf ("(no min or max)");
-
-  return result;
-}
-
-static void
-update_start_message (GstVorbisEnc * vorbisenc)
-{
-  gchar *constraints;
-
-  g_free (vorbisenc->last_message);
-
-  if (vorbisenc->bitrate > 0) {
-    if (vorbisenc->managed) {
-      constraints = get_constraints_string (vorbisenc);
-      vorbisenc->last_message =
-          g_strdup_printf ("encoding at average bitrate %d bps %s",
-          vorbisenc->bitrate, constraints);
-      g_free (constraints);
-    } else {
-      vorbisenc->last_message =
-          g_strdup_printf
-          ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
-          vorbisenc->bitrate);
-    }
-  } else {
-    if (vorbisenc->quality_set) {
-      if (vorbisenc->managed) {
-        constraints = get_constraints_string (vorbisenc);
-        vorbisenc->last_message =
-            g_strdup_printf
-            ("encoding at quality level %2.2f using constrained VBR %s",
-            vorbisenc->quality, constraints);
-        g_free (constraints);
-      } else {
-        vorbisenc->last_message =
-            g_strdup_printf ("encoding at quality level %2.2f",
-            vorbisenc->quality);
-      }
-    } else {
-      constraints = get_constraints_string (vorbisenc);
-      vorbisenc->last_message =
-          g_strdup_printf ("encoding using bitrate management %s", constraints);
-      g_free (constraints);
-    }
-  }
-
-  g_object_notify (G_OBJECT (vorbisenc), "last_message");
-}
-
-static gboolean
-gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
-{
-  vorbisenc->setup = FALSE;
-
-  if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
-      && vorbisenc->max_bitrate < 0) {
-    vorbisenc->quality_set = TRUE;
-  }
-
-  update_start_message (vorbisenc);
-
-  /* choose an encoding mode */
-  /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
-  vorbis_info_init (&vorbisenc->vi);
-
-  if (vorbisenc->quality_set) {
-    if (vorbis_encode_setup_vbr (&vorbisenc->vi,
-            vorbisenc->channels, vorbisenc->frequency,
-            vorbisenc->quality) != 0) {
-      GST_ERROR_OBJECT (vorbisenc,
-          "vorbisenc: initialisation failed: invalid parameters for quality");
-      vorbis_info_clear (&vorbisenc->vi);
-      return FALSE;
-    }
-
-    /* do we have optional hard quality restrictions? */
-    if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
-      struct ovectl_ratemanage_arg ai;
-
-      vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
-
-      ai.bitrate_hard_min = vorbisenc->min_bitrate;
-      ai.bitrate_hard_max = vorbisenc->max_bitrate;
-      ai.management_active = 1;
-
-      vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
-    }
-  } else {
-    long min_bitrate, max_bitrate;
-
-    min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
-    max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
-
-    if (vorbis_encode_setup_managed (&vorbisenc->vi,
-            vorbisenc->channels,
-            vorbisenc->frequency,
-            max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
-      GST_ERROR_OBJECT (vorbisenc,
-          "vorbis_encode_setup_managed "
-          "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
-          vorbisenc->channels, vorbisenc->frequency, max_bitrate,
-          vorbisenc->bitrate, min_bitrate);
-      vorbis_info_clear (&vorbisenc->vi);
-      return FALSE;
-    }
-  }
-
-  if (vorbisenc->managed && vorbisenc->bitrate < 0) {
-    vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
-  } else if (!vorbisenc->managed) {
-    /* Turn off management entirely (if it was turned on). */
-    vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
-  }
-  vorbis_encode_setup_init (&vorbisenc->vi);
-
-  /* set up the analysis state and auxiliary encoding storage */
-  vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
-  vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
-
-  vorbisenc->next_ts = 0;
-
-  vorbisenc->setup = TRUE;
-
-  return TRUE;
-}
-
-static GstFlowReturn
-gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  if (vorbisenc->setup) {
-    vorbis_analysis_wrote (&vorbisenc->vd, 0);
-    ret = gst_vorbis_enc_output_buffers (vorbisenc);
-
-    vorbisenc->setup = FALSE;
-  }
-
-  /* clean up and exit.  vorbis_info_clear() must be called last */
-  vorbis_block_clear (&vorbisenc->vb);
-  vorbis_dsp_clear (&vorbisenc->vd);
-  vorbis_info_clear (&vorbisenc->vi);
-
-  vorbisenc->header_sent = FALSE;
-
-  return ret;
-}
-
-/* prepare a buffer for transmission by passing data through libvorbis */
-static GstBuffer *
-gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc,
-    ogg_packet * packet)
-{
-  GstBuffer *outbuf;
-
-  outbuf = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
-  /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
-   * time representation */
-  GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos +
-      vorbisenc->granulepos_offset;
-  GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc,
-      GST_BUFFER_OFFSET_END (outbuf));
-  GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts;
-
-  /* update the next timestamp, taking granulepos_offset and subgranule offset
-   * into account */
-  vorbisenc->next_ts =
-      granulepos_to_timestamp_offset (vorbisenc, packet->granulepos);
-  GST_BUFFER_DURATION (outbuf) =
-      vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
-
-  if (vorbisenc->next_discont) {
-    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
-    vorbisenc->next_discont = FALSE;
-  }
-
-  GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes",
-      GST_BUFFER_SIZE (outbuf));
-  return outbuf;
-}
-
-/* the same as above, but different logic for setting timestamp and granulepos
- * */
-static GstBuffer *
-gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
-    ogg_packet * packet)
-{
-  GstBuffer *outbuf;
-
-  outbuf = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
-  GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
-  GST_BUFFER_OFFSET_END (outbuf) = 0;
-  GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
-  GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
-
-  gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
-
-  GST_DEBUG ("created header packet buffer, %d bytes",
-      GST_BUFFER_SIZE (outbuf));
-  return outbuf;
-}
-
-/* push out the buffer and do internal bookkeeping */
-static GstFlowReturn
-gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
-{
-  vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
-
-  GST_DEBUG_OBJECT (vorbisenc, "Pushing buffer with GP %lld, ts %lld",
-      GST_BUFFER_OFFSET_END (buffer), GST_BUFFER_TIMESTAMP (buffer));
-  return gst_pad_push (vorbisenc->srcpad, buffer);
-}
-
-static GstFlowReturn
-gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
-{
-  GstBuffer *outbuf;
-
-  outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet);
-  return gst_vorbis_enc_push_buffer (vorbisenc, outbuf);
-}
-
-/* Set a copy of these buffers as 'streamheader' on the caps.
- * We need a copy to avoid these buffers ending up with (indirect) refs on
- * themselves
- */
-static GstCaps *
-gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
-    GstBuffer * buf2, GstBuffer * buf3)
-{
-  GstBuffer *buf;
-  GstStructure *structure;
-  GValue array = { 0 };
-  GValue value = { 0 };
-
-  caps = gst_caps_make_writable (caps);
-  structure = gst_caps_get_structure (caps, 0);
-
-  /* mark buffers */
-  GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
-  GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
-  GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
-
-  /* put buffers in a fixed list */
-  g_value_init (&array, GST_TYPE_ARRAY);
-  g_value_init (&value, GST_TYPE_BUFFER);
-  buf = gst_buffer_copy (buf1);
-  gst_value_set_buffer (&value, buf);
-  gst_buffer_unref (buf);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-  g_value_init (&value, GST_TYPE_BUFFER);
-  buf = gst_buffer_copy (buf2);
-  gst_value_set_buffer (&value, buf);
-  gst_buffer_unref (buf);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-  g_value_init (&value, GST_TYPE_BUFFER);
-  buf = gst_buffer_copy (buf3);
-  gst_value_set_buffer (&value, buf);
-  gst_buffer_unref (buf);
-  gst_value_array_append_value (&array, &value);
-  gst_structure_set_value (structure, "streamheader", &array);
-  g_value_unset (&value);
-  g_value_unset (&array);
-
-  return caps;
-}
-
-static gboolean
-gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
-{
-  gboolean res = TRUE;
-  GstVorbisEnc *vorbisenc;
-
-  vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-      /* Tell the library we're at end of stream so that it can handle
-       * the last frame and mark end of stream in the output properly */
-      GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
-      gst_vorbis_enc_clear (vorbisenc);
-
-      res = gst_pad_push_event (vorbisenc->srcpad, event);
-      break;
-    case GST_EVENT_TAG:
-      if (vorbisenc->tags) {
-        GstTagList *list;
-
-        gst_event_parse_tag (event, &list);
-        gst_tag_list_insert (vorbisenc->tags, list,
-            gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
-      } else {
-        g_assert_not_reached ();
-      }
-      res = gst_pad_push_event (vorbisenc->srcpad, event);
-      break;
-    default:
-      res = gst_pad_push_event (vorbisenc->srcpad, event);
-      break;
-  }
-  return res;
-}
-
-static gboolean
-gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
-    GstBuffer * buffer)
-{
-  gboolean ret = FALSE;
-
-  if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
-      vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
-      GST_BUFFER_TIMESTAMP (buffer) != vorbisenc->expected_ts) {
-    /* It turns out that a lot of elements don't generate perfect streams due
-     * to rounding errors. So, we permit small errors (< 1/2 a sample) without
-     * causing a discont.
-     */
-    int halfsample = GST_SECOND / vorbisenc->frequency / 2;
-
-    if ((GstClockTimeDiff) (GST_BUFFER_TIMESTAMP (buffer) -
-            vorbisenc->expected_ts) > halfsample) {
-      GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
-          ", buffer TS %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (vorbisenc->expected_ts),
-          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-      ret = TRUE;
-    }
-  }
-
-  if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
-      GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE) {
-    vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer) +
-        GST_BUFFER_DURATION (buffer);
-  } else
-    vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstVorbisEnc *vorbisenc;
-  GstFlowReturn ret = GST_FLOW_OK;
-  gfloat *data;
-  gulong size;
-  gulong i, j;
-  float **vorbis_buffer;
-  GstBuffer *buf1, *buf2, *buf3;
-  gboolean first = FALSE;
-
-  vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
-  if (!vorbisenc->setup)
-    goto not_setup;
-
-  if (!vorbisenc->header_sent) {
-    /* Vorbis streams begin with three headers; the initial header (with
-       most of the codec setup parameters) which is mandated by the Ogg
-       bitstream spec.  The second header holds any comment fields.  The
-       third header holds the bitstream codebook.  We merely need to
-       make the headers, then pass them to libvorbis one at a time;
-       libvorbis handles the additional Ogg bitstream constraints */
-    ogg_packet header;
-    ogg_packet header_comm;
-    ogg_packet header_code;
-    GstCaps *caps;
-
-    /* first, make sure header buffers get timestamp == 0 */
-    vorbisenc->next_ts = 0;
-    vorbisenc->granulepos_offset = 0;
-    vorbisenc->subgranule_offset = 0;
-
-    GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
-    gst_vorbis_enc_set_metadata (vorbisenc);
-    vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
-        &header_comm, &header_code);
-    vorbis_comment_clear (&vorbisenc->vc);
-
-    /* create header buffers */
-    buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
-    buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
-    buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
-
-    /* mark and put on caps */
-    vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
-    caps = vorbisenc->srccaps;
-    caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3);
-
-    /* negotiate with these caps */
-    GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
-    gst_pad_set_caps (vorbisenc->srcpad, caps);
-
-    gst_buffer_set_caps (buf1, caps);
-    gst_buffer_set_caps (buf2, caps);
-    gst_buffer_set_caps (buf3, caps);
-
-    /* push out buffers */
-    /* push_buffer takes the reference even for failure */
-    if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
-      goto failed_header_push;
-    if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) {
-      buf2 = NULL;
-      goto failed_header_push;
-    }
-    if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) {
-      buf3 = NULL;
-      goto failed_header_push;
-    }
-
-    /* now adjust starting granulepos accordingly if the buffer's timestamp is
-       nonzero */
-    vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
-    vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer);
-    vorbisenc->granulepos_offset = gst_util_uint64_scale
-        (GST_BUFFER_TIMESTAMP (buffer), vorbisenc->frequency, GST_SECOND);
-    vorbisenc->subgranule_offset = 0;
-    vorbisenc->subgranule_offset =
-        vorbisenc->next_ts - granulepos_to_timestamp_offset (vorbisenc, 0);
-
-    vorbisenc->header_sent = TRUE;
-    first = TRUE;
-  }
-
-  if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
-      GST_BUFFER_TIMESTAMP (buffer) < vorbisenc->expected_ts) {
-    GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
-        "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
-        "), cannot handle. Dropping buffer.",
-        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
-        GST_TIME_ARGS (vorbisenc->expected_ts));
-    gst_buffer_unref (buffer);
-    return GST_FLOW_OK;
-  }
-
-  if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, buffer) && !first) {
-    GST_WARNING_OBJECT (vorbisenc, "Buffer is discontinuous, flushing encoder "
-        "and restarting (Discont from %" GST_TIME_FORMAT
-        " to %" GST_TIME_FORMAT ")", GST_TIME_ARGS (vorbisenc->next_ts),
-        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-    /* Re-initialise encoder (there's unfortunately no API to flush it) */
-    if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
-      return ret;
-    if (!gst_vorbis_enc_setup (vorbisenc))
-      return GST_FLOW_ERROR;    /* Should be impossible, we can only get here if
-                                   we successfully initialised earlier */
-
-    /* Now, set our granulepos offset appropriately. */
-    vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
-    /* We need to round to the nearest whole number of samples, not just do
-     * a truncating division here */
-    vorbisenc->granulepos_offset = gst_util_uint64_scale
-        (GST_BUFFER_TIMESTAMP (buffer) + GST_SECOND / vorbisenc->frequency / 2
-        - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
-
-    vorbisenc->header_sent = TRUE;
-
-    /* And our next output buffer must have DISCONT set on it */
-    vorbisenc->next_discont = TRUE;
-  }
-
-  /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */
-  if (GST_BUFFER_SIZE (buffer) == 0) {
-    gst_buffer_unref (buffer);
-    return GST_FLOW_OK;
-  }
-
-  /* data to encode */
-  data = (gfloat *) GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
-
-  /* expose the buffer to submit data */
-  vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
-
-  /* deinterleave samples, write the buffer data */
-  for (i = 0; i < size; i++) {
-    for (j = 0; j < vorbisenc->channels; j++) {
-      vorbis_buffer[j][i] = *data++;
-    }
-  }
-
-  /* tell the library how much we actually submitted */
-  vorbis_analysis_wrote (&vorbisenc->vd, size);
-
-  vorbisenc->samples_in += size;
-
-  gst_buffer_unref (buffer);
-
-  ret = gst_vorbis_enc_output_buffers (vorbisenc);
-
-  return ret;
-
-  /* error cases */
-not_setup:
-  {
-    gst_buffer_unref (buffer);
-    GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
-        ("encoder not initialized (input is not audio?)"));
-    return GST_FLOW_UNEXPECTED;
-  }
-failed_header_push:
-  {
-    GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
-    /* buf1 is always already unreffed */
-    if (buf2)
-      gst_buffer_unref (buf2);
-    if (buf3)
-      gst_buffer_unref (buf3);
-    gst_buffer_unref (buffer);
-    return ret;
-  }
-}
-
-static GstFlowReturn
-gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
-{
-  GstFlowReturn ret;
-
-  /* vorbis does some data preanalysis, then divides up blocks for
-     more involved (potentially parallel) processing.  Get a single
-     block for encoding now */
-  while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
-    ogg_packet op;
-
-    GST_LOG_OBJECT (vorbisenc, "analysed to a block");
-
-    /* analysis */
-    vorbis_analysis (&vorbisenc->vb, NULL);
-    vorbis_bitrate_addblock (&vorbisenc->vb);
-
-    while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
-      GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
-      ret = gst_vorbis_enc_push_packet (vorbisenc, &op);
-
-      if (ret != GST_FLOW_OK)
-        return ret;
-    }
-  }
-
-  return GST_FLOW_OK;
-}
-
-static void
-gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
-{
-  GstVorbisEnc *vorbisenc;
-
-  g_return_if_fail (GST_IS_VORBISENC (object));
-
-  vorbisenc = GST_VORBISENC (object);
-
-  switch (prop_id) {
-    case ARG_MAX_BITRATE:
-      g_value_set_int (value, vorbisenc->max_bitrate);
-      break;
-    case ARG_BITRATE:
-      g_value_set_int (value, vorbisenc->bitrate);
-      break;
-    case ARG_MIN_BITRATE:
-      g_value_set_int (value, vorbisenc->min_bitrate);
-      break;
-    case ARG_QUALITY:
-      g_value_set_float (value, vorbisenc->quality);
-      break;
-    case ARG_MANAGED:
-      g_value_set_boolean (value, vorbisenc->managed);
-      break;
-    case ARG_LAST_MESSAGE:
-      g_value_set_string (value, vorbisenc->last_message);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_vorbis_enc_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstVorbisEnc *vorbisenc;
-
-  g_return_if_fail (GST_IS_VORBISENC (object));
-
-  vorbisenc = GST_VORBISENC (object);
-
-  switch (prop_id) {
-    case ARG_MAX_BITRATE:
-    {
-      gboolean old_value = vorbisenc->managed;
-
-      vorbisenc->max_bitrate = g_value_get_int (value);
-      if (vorbisenc->max_bitrate >= 0
-          && vorbisenc->max_bitrate < LOWEST_BITRATE) {
-        g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
-        vorbisenc->max_bitrate = LOWEST_BITRATE;
-      }
-      if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
-        vorbisenc->managed = TRUE;
-      else
-        vorbisenc->managed = FALSE;
-
-      if (old_value != vorbisenc->managed)
-        g_object_notify (object, "managed");
-      break;
-    }
-    case ARG_BITRATE:
-      vorbisenc->bitrate = g_value_get_int (value);
-      if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
-        g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
-        vorbisenc->bitrate = LOWEST_BITRATE;
-      }
-      break;
-    case ARG_MIN_BITRATE:
-    {
-      gboolean old_value = vorbisenc->managed;
-
-      vorbisenc->min_bitrate = g_value_get_int (value);
-      if (vorbisenc->min_bitrate >= 0
-          && vorbisenc->min_bitrate < LOWEST_BITRATE) {
-        g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
-        vorbisenc->min_bitrate = LOWEST_BITRATE;
-      }
-      if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
-        vorbisenc->managed = TRUE;
-      else
-        vorbisenc->managed = FALSE;
-
-      if (old_value != vorbisenc->managed)
-        g_object_notify (object, "managed");
-      break;
-    }
-    case ARG_QUALITY:
-      vorbisenc->quality = g_value_get_float (value);
-      if (vorbisenc->quality >= 0.0)
-        vorbisenc->quality_set = TRUE;
-      else
-        vorbisenc->quality_set = FALSE;
-      break;
-    case ARG_MANAGED:
-      vorbisenc->managed = g_value_get_boolean (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static GstStateChangeReturn
-gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
-{
-  GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
-  GstStateChangeReturn res;
-
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      vorbisenc->tags = gst_tag_list_new ();
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      vorbisenc->setup = FALSE;
-      vorbisenc->next_discont = FALSE;
-      vorbisenc->header_sent = FALSE;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      vorbis_block_clear (&vorbisenc->vb);
-      vorbis_dsp_clear (&vorbisenc->vd);
-      vorbis_info_clear (&vorbisenc->vi);
-      g_free (vorbisenc->last_message);
-      vorbisenc->last_message = NULL;
-      if (vorbisenc->srccaps) {
-        gst_caps_unref (vorbisenc->srccaps);
-        vorbisenc->srccaps = NULL;
-      }
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      gst_tag_list_free (vorbisenc->tags);
-      vorbisenc->tags = NULL;
-    default:
-      break;
-  }
-
-  return res;
-}
--- a/gst_plugins_base/ext/vorbis/vorbisenc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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_VORBIS_ENC_H__
-#define __GST_VORBIS_ENC_H__
-
-
-#include <gst/gst.h>
-
-#include <vorbis/codec.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_VORBISENC \
-  (gst_vorbis_enc_get_type())
-#define GST_VORBISENC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBISENC,GstVorbisEnc))
-#define GST_VORBISENC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBISENC,GstVorbisEncClass))
-#define GST_IS_VORBISENC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBISENC))
-#define GST_IS_VORBISENC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBISENC))
-
-typedef struct _GstVorbisEnc GstVorbisEnc;
-typedef struct _GstVorbisEncClass GstVorbisEncClass;
-
-/**
- * GstVorbisEnc:
- *
- * Opaque data structure.
- */
-struct _GstVorbisEnc {
-  GstElement       element;
-
-  GstPad          *sinkpad;
-  GstPad          *srcpad;
-
-  GstCaps         *srccaps;
-  GstCaps         *sinkcaps;
-
-  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
-                                                            settings */
-  vorbis_comment   vc; /* struct that stores all the user comments */
-
-  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
-  vorbis_block     vb; /* local working space for packet->PCM decode */
-
-  gboolean         managed;
-  gint             bitrate;
-  gint             min_bitrate;
-  gint             max_bitrate;
-  gfloat           quality;
-  gboolean         quality_set;
-
-  gint             channels;
-  gint             frequency;
-
-  guint64          samples_in;
-  guint64          bytes_out;
-  GstClockTime     next_ts;
-  GstClockTime     expected_ts;
-  gboolean         next_discont;
-  guint64          granulepos_offset;
-  gint64           subgranule_offset;
-
-  GstTagList *     tags;
-
-  gboolean         setup;
-  gboolean         header_sent;
-  gchar           *last_message;
-};
-
-struct _GstVorbisEncClass {
-  GstElementClass parent_class;
-};
-
-GType gst_vorbis_enc_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_ENC_H__ */
--- a/gst_plugins_base/ext/vorbis/vorbisparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,666 +0,0 @@
-/* GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2006 Andy Wingo <wingo@pobox.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.
- */
-
-/**
- * SECTION:element-vorbisparse
- * @short_description: parses vorbis streams 
- * @see_also: vorbisdec, oggdemux, theoraparse
- *
- * <refsect2>
- * <para>
- * The vorbisparse element will parse the header packets of the Vorbis
- * stream and put them as the streamheader in the caps. This is used in the
- * multifdsink case where you want to stream live vorbis streams to multiple
- * clients, each client has to receive the streamheaders first before they can
- * consume the vorbis packets.
- * </para>
- * <para>
- * This element also makes sure that the buffers that it pushes out are properly
- * timestamped and that their offset and offset_end are set. The buffers that
- * vorbisparse outputs have all of the metadata that oggmux expects to receive,
- * which allows you to (for example) remux an ogg/vorbis file.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisparse ! fakesink
- * </programlisting>
- * This pipeline shows that the streamheader is set in the caps, and that each
- * buffer has the timestamp, duration, offset, and offset_end set.
- * </para>
- * <para>
- * <programlisting>
- * gst-launch filesrc location=sine.ogg ! oggdemux ! vorbisparse \
- *            ! oggmux ! filesink location=sine-remuxed.ogg
- * </programlisting>
- * This pipeline shows remuxing. sine-remuxed.ogg might not be exactly the same
- * as sine.ogg, but they should produce exactly the same decoded data.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-04-01 (0.10.4.1)
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "vorbisparse.h"
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug);
-#define GST_CAT_DEFAULT vorbisparse_debug
-
-static const GstElementDetails vorbis_parse_details = {
-  "VorbisParse",
-  "Codec/Parser/Audio",
-  "parse raw vorbis streams",
-  "Thomas Vander Stichele <thomas at apestaart dot org>"
-};
-
-static GstStaticPadTemplate vorbis_parse_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-vorbis")
-    );
-
-static GstStaticPadTemplate vorbis_parse_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-vorbis")
-    );
-
-GST_BOILERPLATE (GstVorbisParse, gst_vorbis_parse, GstElement,
-    GST_TYPE_ELEMENT);
-
-static GstFlowReturn vorbis_parse_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn vorbis_parse_change_state (GstElement * element,
-    GstStateChange transition);
-static gboolean vorbis_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean vorbis_parse_src_query (GstPad * pad, GstQuery * query);
-static gboolean vorbis_parse_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value);
-static GstFlowReturn vorbis_parse_parse_packet (GstVorbisParse * parse,
-    GstBuffer * buf);
-
-static void
-gst_vorbis_parse_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&vorbis_parse_src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&vorbis_parse_sink_factory));
-  gst_element_class_set_details (element_class, &vorbis_parse_details);
-}
-
-static void
-gst_vorbis_parse_class_init (GstVorbisParseClass * klass)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
-  gstelement_class->change_state = vorbis_parse_change_state;
-
-  klass->parse_packet = GST_DEBUG_FUNCPTR (vorbis_parse_parse_packet);
-}
-
-static void
-gst_vorbis_parse_init (GstVorbisParse * parse, GstVorbisParseClass * g_class)
-{
-  parse->sinkpad =
-      gst_pad_new_from_static_template (&vorbis_parse_sink_factory, "sink");
-  gst_pad_set_chain_function (parse->sinkpad,
-      GST_DEBUG_FUNCPTR (vorbis_parse_chain));
-  gst_pad_set_event_function (parse->sinkpad,
-      GST_DEBUG_FUNCPTR (vorbis_parse_sink_event));
-  gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
-
-  parse->srcpad =
-      gst_pad_new_from_static_template (&vorbis_parse_src_factory, "src");
-  gst_pad_set_query_function (parse->srcpad,
-      GST_DEBUG_FUNCPTR (vorbis_parse_src_query));
-  gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
-}
-
-static void
-vorbis_parse_set_header_on_caps (GstVorbisParse * parse, GstCaps * caps)
-{
-  GstBuffer *buf1, *buf2, *buf3;
-  GstStructure *structure;
-  GValue array = { 0 };
-  GValue value = { 0 };
-
-  g_assert (parse);
-  g_assert (parse->streamheader);
-  g_assert (parse->streamheader->next);
-  g_assert (parse->streamheader->next->next);
-  buf1 = parse->streamheader->data;
-  g_assert (buf1);
-  buf2 = parse->streamheader->next->data;
-  g_assert (buf2);
-  buf3 = parse->streamheader->next->next->data;
-  g_assert (buf3);
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  /* mark buffers */
-  GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
-  GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
-  GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
-
-  /* put buffers in a fixed list */
-  g_value_init (&array, GST_TYPE_ARRAY);
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buf1);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buf2);
-  gst_value_array_append_value (&array, &value);
-  g_value_unset (&value);
-  g_value_init (&value, GST_TYPE_BUFFER);
-  gst_value_set_buffer (&value, buf3);
-  gst_value_array_append_value (&array, &value);
-  gst_structure_set_value (structure, "streamheader", &array);
-  g_value_unset (&value);
-  g_value_unset (&array);
-}
-
-static void
-vorbis_parse_drain_event_queue (GstVorbisParse * parse)
-{
-  while (parse->event_queue->length) {
-    GstEvent *event;
-
-    event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
-    gst_pad_event_default (parse->sinkpad, event);
-  }
-}
-
-static void
-vorbis_parse_push_headers (GstVorbisParse * parse)
-{
-  /* mark and put on caps */
-  GstCaps *caps;
-  GstBuffer *outbuf, *outbuf1, *outbuf2, *outbuf3;
-  ogg_packet packet;
-
-  /* get the headers into the caps, passing them to vorbis as we go */
-  caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad));
-  vorbis_parse_set_header_on_caps (parse, caps);
-  GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps);
-  gst_pad_set_caps (parse->srcpad, caps);
-  gst_caps_unref (caps);
-
-  outbuf = GST_BUFFER_CAST (parse->streamheader->data);
-  packet.packet = GST_BUFFER_DATA (outbuf);
-  packet.bytes = GST_BUFFER_SIZE (outbuf);
-  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
-  packet.packetno = 1;
-  packet.e_o_s = 0;
-  packet.b_o_s = 1;
-  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
-  parse->sample_rate = parse->vi.rate;
-  outbuf1 = outbuf;
-
-  outbuf = GST_BUFFER_CAST (parse->streamheader->next->data);
-  packet.packet = GST_BUFFER_DATA (outbuf);
-  packet.bytes = GST_BUFFER_SIZE (outbuf);
-  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
-  packet.packetno = 2;
-  packet.e_o_s = 0;
-  packet.b_o_s = 0;
-  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
-  outbuf2 = outbuf;
-
-  outbuf = GST_BUFFER_CAST (parse->streamheader->next->next->data);
-  packet.packet = GST_BUFFER_DATA (outbuf);
-  packet.bytes = GST_BUFFER_SIZE (outbuf);
-  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
-  packet.packetno = 3;
-  packet.e_o_s = 0;
-  packet.b_o_s = 0;
-  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
-  outbuf3 = outbuf;
-
-  /* first process queued events */
-  vorbis_parse_drain_event_queue (parse);
-
-  /* push out buffers, ignoring return value... */
-  gst_buffer_set_caps (outbuf1, GST_PAD_CAPS (parse->srcpad));
-  gst_pad_push (parse->srcpad, outbuf1);
-  gst_buffer_set_caps (outbuf2, GST_PAD_CAPS (parse->srcpad));
-  gst_pad_push (parse->srcpad, outbuf2);
-  gst_buffer_set_caps (outbuf3, GST_PAD_CAPS (parse->srcpad));
-  gst_pad_push (parse->srcpad, outbuf3);
-
-  g_list_free (parse->streamheader);
-  parse->streamheader = NULL;
-
-  parse->streamheader_sent = TRUE;
-}
-
-static void
-vorbis_parse_clear_queue (GstVorbisParse * parse)
-{
-  while (parse->buffer_queue->length) {
-    GstBuffer *buf;
-
-    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-    gst_buffer_unref (buf);
-  }
-  while (parse->event_queue->length) {
-    GstEvent *event;
-
-    event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
-    gst_event_unref (event);
-  }
-}
-
-static GstFlowReturn
-vorbis_parse_push_buffer (GstVorbisParse * parse, GstBuffer * buf,
-    gint64 granulepos)
-{
-  guint64 samples;
-
-  /* our hack as noted below */
-  samples = GST_BUFFER_OFFSET (buf);
-
-  GST_BUFFER_OFFSET_END (buf) = granulepos;
-  GST_BUFFER_DURATION (buf) = samples * GST_SECOND / parse->sample_rate;
-  GST_BUFFER_OFFSET (buf) = granulepos * GST_SECOND / parse->sample_rate;
-  GST_BUFFER_TIMESTAMP (buf) =
-      GST_BUFFER_OFFSET (buf) - GST_BUFFER_DURATION (buf);
-
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
-
-  return gst_pad_push (parse->srcpad, buf);
-}
-
-static GstFlowReturn
-vorbis_parse_drain_queue_prematurely (GstVorbisParse * parse)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  gint64 granulepos = MAX (parse->prev_granulepos, 0);
-
-  /* got an EOS event, make sure to push out any buffers that were in the queue
-   * -- won't normally be the case, but this catches the
-   * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous
-   * stream. */
-
-  /* if we got EOS before any buffers came, go ahead and push the other events
-   * first */
-  vorbis_parse_drain_event_queue (parse);
-
-  while (!g_queue_is_empty (parse->buffer_queue)) {
-    GstBuffer *buf;
-
-    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
-    granulepos += GST_BUFFER_OFFSET (buf);
-    ret = vorbis_parse_push_buffer (parse, buf, granulepos);
-
-    if (ret != GST_FLOW_OK)
-      goto done;
-  }
-
-  parse->prev_granulepos = granulepos;
-
-done:
-  return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_drain_queue (GstVorbisParse * parse, gint64 granulepos)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  GList *walk;
-  gint64 cur = granulepos;
-  gint64 gp;
-
-  for (walk = parse->buffer_queue->head; walk; walk = walk->next)
-    cur -= GST_BUFFER_OFFSET (walk->data);
-
-  if (parse->prev_granulepos != -1)
-    cur = MAX (cur, parse->prev_granulepos);
-
-  while (!g_queue_is_empty (parse->buffer_queue)) {
-    GstBuffer *buf;
-
-    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
-    cur += GST_BUFFER_OFFSET (buf);
-    gp = CLAMP (cur, 0, granulepos);
-
-    ret = vorbis_parse_push_buffer (parse, buf, gp);
-
-    if (ret != GST_FLOW_OK)
-      goto done;
-  }
-
-  parse->prev_granulepos = granulepos;
-
-done:
-  return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  long blocksize;
-  ogg_packet packet;
-
-  buf = gst_buffer_make_metadata_writable (buf);
-
-  packet.packet = GST_BUFFER_DATA (buf);
-  packet.bytes = GST_BUFFER_SIZE (buf);
-  packet.granulepos = GST_BUFFER_OFFSET_END (buf);
-  packet.packetno = parse->packetno + parse->buffer_queue->length;
-  packet.e_o_s = 0;
-
-  blocksize = vorbis_packet_blocksize (&parse->vi, &packet);
-
-  /* temporarily store the sample count in OFFSET -- we overwrite this later */
-
-  if (parse->prev_blocksize < 0)
-    GST_BUFFER_OFFSET (buf) = 0;
-  else
-    GST_BUFFER_OFFSET (buf) = (blocksize + parse->prev_blocksize) / 4;
-
-  parse->prev_blocksize = blocksize;
-
-  g_queue_push_tail (parse->buffer_queue, buf);
-
-  if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
-    ret = vorbis_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
-
-  return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_parse_packet (GstVorbisParse * parse, GstBuffer * buf)
-{
-  GstFlowReturn ret;
-
-  parse->packetno++;
-
-  if (parse->packetno <= 3) {
-    /* if 1 <= packetno <= 3, it's streamheader,
-     * so put it on the streamheader list and return */
-    parse->streamheader = g_list_append (parse->streamheader, buf);
-    ret = GST_FLOW_OK;
-  } else {
-    if (!parse->streamheader_sent)
-      vorbis_parse_push_headers (parse);
-
-    ret = vorbis_parse_queue_buffer (parse, buf);
-  }
-
-  return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
-  GstVorbisParseClass *klass;
-  GstVorbisParse *parse;
-
-  parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
-  klass = GST_VORBIS_PARSE_CLASS (G_OBJECT_GET_CLASS (parse));
-
-  g_assert (klass->parse_packet != NULL);
-
-  return klass->parse_packet (parse, buffer);
-}
-
-static gboolean
-vorbis_parse_queue_event (GstVorbisParse * parse, GstEvent * event)
-{
-  GstFlowReturn ret = TRUE;
-
-  g_queue_push_tail (parse->event_queue, event);
-
-  return ret;
-}
-
-static gboolean
-vorbis_parse_sink_event (GstPad * pad, GstEvent * event)
-{
-  gboolean ret;
-  GstVorbisParse *parse;
-
-  parse = GST_VORBIS_PARSE (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      vorbis_parse_clear_queue (parse);
-      parse->prev_granulepos = -1;
-      parse->prev_blocksize = -1;
-      ret = gst_pad_event_default (pad, event);
-      break;
-    case GST_EVENT_EOS:
-      vorbis_parse_drain_queue_prematurely (parse);
-      ret = gst_pad_event_default (pad, event);
-      break;
-    default:
-      if (!parse->streamheader_sent && GST_EVENT_IS_SERIALIZED (event))
-        ret = vorbis_parse_queue_event (parse, event);
-      else
-        ret = gst_pad_event_default (pad, event);
-      break;
-  }
-
-  gst_object_unref (parse);
-
-  return ret;
-}
-
-static gboolean
-vorbis_parse_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  gboolean res = TRUE;
-  GstVorbisParse *parse;
-  guint64 scale = 1;
-
-  parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
-
-  /* fixme: assumes atomic access to lots of instance variables modified from
-   * the streaming thread, including 64-bit variables */
-
-  if (parse->packetno < 4)
-    return FALSE;
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  if (parse->sinkpad == pad &&
-      (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
-    return FALSE;
-
-  switch (src_format) {
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          scale = sizeof (float) * parse->vi.channels;
-        case GST_FORMAT_DEFAULT:
-          *dest_value =
-              scale * gst_util_uint64_scale_int (src_value, parse->vi.rate,
-              GST_SECOND);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_BYTES:
-          *dest_value = src_value * sizeof (float) * parse->vi.channels;
-          break;
-        case GST_FORMAT_TIME:
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, GST_SECOND, parse->vi.rate);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    case GST_FORMAT_BYTES:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          *dest_value = src_value / (sizeof (float) * parse->vi.channels);
-          break;
-        case GST_FORMAT_TIME:
-          *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
-              parse->vi.rate * sizeof (float) * parse->vi.channels);
-          break;
-        default:
-          res = FALSE;
-      }
-      break;
-    default:
-      res = FALSE;
-  }
-
-  return res;
-}
-
-static gboolean
-vorbis_parse_src_query (GstPad * pad, GstQuery * query)
-{
-  gint64 granulepos;
-  GstVorbisParse *parse;
-  gboolean res = FALSE;
-
-  parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    {
-      GstFormat format;
-      gint64 value;
-
-      granulepos = parse->prev_granulepos;
-
-      gst_query_parse_position (query, &format, NULL);
-
-      /* and convert to the final format */
-      if (!(res =
-              vorbis_parse_convert (pad, GST_FORMAT_DEFAULT, granulepos,
-                  &format, &value)))
-        goto error;
-
-      /* fixme: support segments
-         value = (value - parse->segment_start) + parse->segment_time;
-       */
-
-      gst_query_set_position (query, format, value);
-
-      GST_LOG_OBJECT (parse, "query %p: peer returned granulepos: %"
-          G_GUINT64_FORMAT " - we return %" G_GUINT64_FORMAT " (format %u)",
-          query, granulepos, value, format);
-
-      break;
-    }
-    case GST_QUERY_DURATION:
-    {
-      /* fixme: not threadsafe */
-      /* query peer for total length */
-      if (!gst_pad_is_linked (parse->sinkpad)) {
-        GST_WARNING_OBJECT (parse, "sink pad %" GST_PTR_FORMAT " is not linked",
-            parse->sinkpad);
-        goto error;
-      }
-      if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query)))
-        goto error;
-      break;
-    }
-    case GST_QUERY_CONVERT:
-    {
-      GstFormat src_fmt, dest_fmt;
-      gint64 src_val, dest_val;
-
-      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      if (!(res =
-              vorbis_parse_convert (pad, src_fmt, src_val, &dest_fmt,
-                  &dest_val)))
-        goto error;
-      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, query);
-      break;
-  }
-  return res;
-
-error:
-  {
-    GST_WARNING_OBJECT (parse, "error handling query");
-    return res;
-  }
-}
-
-static GstStateChangeReturn
-vorbis_parse_change_state (GstElement * element, GstStateChange transition)
-{
-  GstVorbisParse *parse = GST_VORBIS_PARSE (element);
-  GstStateChangeReturn ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      vorbis_info_init (&parse->vi);
-      vorbis_comment_init (&parse->vc);
-      parse->prev_granulepos = -1;
-      parse->prev_blocksize = -1;
-      parse->packetno = 0;
-      parse->streamheader_sent = FALSE;
-      parse->buffer_queue = g_queue_new ();
-      parse->event_queue = g_queue_new ();
-      break;
-    default:
-      break;
-  }
-
-  ret = parent_class->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      vorbis_info_clear (&parse->vi);
-      vorbis_comment_clear (&parse->vc);
-      vorbis_parse_clear_queue (parse);
-      g_queue_free (parse->buffer_queue);
-      parse->buffer_queue = NULL;
-      g_queue_free (parse->event_queue);
-      parse->event_queue = NULL;
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
--- a/gst_plugins_base/ext/vorbis/vorbisparse.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * 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_VORBIS_PARSE_H__
-#define __GST_VORBIS_PARSE_H__
-
-
-#include <gst/gst.h>
-#include <vorbis/codec.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_VORBIS_PARSE \
-  (gst_vorbis_parse_get_type())
-#define GST_VORBIS_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_PARSE,GstVorbisParse))
-#define GST_VORBIS_PARSE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_PARSE,GstVorbisParseClass))
-#define GST_IS_VORBIS_PARSE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_PARSE))
-#define GST_IS_VORBIS_PARSE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_PARSE))
-
-typedef struct _GstVorbisParse GstVorbisParse;
-typedef struct _GstVorbisParseClass GstVorbisParseClass;
-
-/**
- * GstVorbisParse:
- *
- * Opaque data structure.
- */
-struct _GstVorbisParse {
-  GstElement            element;
-
-  GstPad *              sinkpad;
-  GstPad *              srcpad;
-
-  guint                 packetno;
-  gboolean              streamheader_sent;
-  GList *               streamheader;
-
-  GQueue *		event_queue;
-  GQueue *		buffer_queue;
-
-  vorbis_info		vi;
-  vorbis_comment	vc;
-
-  gint64		prev_granulepos;
-  gint32		prev_blocksize;
-  guint32		sample_rate;
-};
-
-struct _GstVorbisParseClass {
-  GstElementClass parent_class;
-
-  /* virtual functions */
-  GstFlowReturn  (*parse_packet) (GstVorbisParse * parse, GstBuffer * buf);
-};
-
-GType gst_vorbis_parse_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_PARSE_H__ */
--- a/gst_plugins_base/ext/vorbis/vorbistag.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2006 James Livingston <doclivingston@gmail.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.
- */
-
-/**
- * SECTION:element-vorbistag
- * @see_also: #oggdemux, #oggmux, #vorbisparse, #GstTagSetter
- * @short_description: retags vorbis streams 
- *
- * <refsect2>
- * <para>
- * The vorbistags element can change the tag contained within a raw
- * vorbis stream. Specifically, it modifies the comments header packet
- * of the vorbis stream.
- * </para>
- * <para>
- * The element will also process the stream as the #vorbisparse element does
- * so it can be used when remuxing an Ogg Vorbis stream, without additional
- * elements.
- * </para>
- * <para>
- * Applications can set the tags to write using the #GstTagSetter interface.
- * Tags contained withing the vorbis bitstream will be picked up
- * automatically (and merged according to the merge mode set via the tag
- * setter interface).
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * This element is not useful with gst-launch, because it does not support
- * setting the tags on a #GstTagSetter interface. Conceptually, the element
- * will usually be used like:
- * <programlisting>
- * gst-launch -v filesrc location=foo.ogg ! oggdemux ! vorbistag ! oggmux ! filesink location=bar.ogg
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <glib.h>
-#include <gst/tag/tag.h>
-#include <gst/gsttagsetter.h>
-
-#include <vorbis/codec.h>
-
-#include "vorbistag.h"
-
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug);
-#define GST_CAT_DEFAULT vorbisparse_debug
-
-static void gst_vorbis_tag_base_init (gpointer g_class);
-static void gst_vorbis_tag_class_init (GstVorbisTagClass * klass);
-static void gst_vorbis_tag_init (GstVorbisTag * tagger,
-    GstVorbisTagClass * g_class);
-static GstFlowReturn gst_vorbis_tag_parse_packet (GstVorbisParse * parse,
-    GstBuffer * buffer);
-
-#define _do_init(type)                                                          \
-  G_STMT_START{                                                                 \
-    static const GInterfaceInfo tag_setter_info = {                             \
-      NULL,                                                                     \
-      NULL,                                                                     \
-      NULL                                                                      \
-    };                                                                          \
-    g_type_add_interface_static (type, GST_TYPE_TAG_SETTER,                     \
-                                 &tag_setter_info);                             \
-  }G_STMT_END
-
-GST_BOILERPLATE_FULL (GstVorbisTag, gst_vorbis_tag, GstVorbisParse,
-    GST_TYPE_VORBIS_PARSE, _do_init);
-
-static GstElementDetails vorbis_tag_details = {
-  "VorbisTag",
-  "Formatter/Metadata",
-  "Retags vorbis streams",
-  "James Livingston <doclivingston@gmail.com>"
-};
-
-
-static void
-gst_vorbis_tag_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &vorbis_tag_details);
-}
-
-static void
-gst_vorbis_tag_class_init (GstVorbisTagClass * klass)
-{
-  GstVorbisParseClass *vorbisparse_class = GST_VORBIS_PARSE_CLASS (klass);
-
-  vorbisparse_class->parse_packet = gst_vorbis_tag_parse_packet;
-}
-
-static void
-gst_vorbis_tag_init (GstVorbisTag * tagger, GstVorbisTagClass * g_class)
-{
-  /* nothing to do */
-}
-
-
-static GstFlowReturn
-gst_vorbis_tag_parse_packet (GstVorbisParse * parse, GstBuffer * buffer)
-{
-  GstTagList *old_tags, *new_tags;
-  const GstTagList *user_tags;
-  GstVorbisTag *tagger;
-  gchar *encoder = NULL;
-  GstBuffer *new_buf;
-
-  /* just pass everything except the comments packet */
-  if (GST_BUFFER_SIZE (buffer) >= 1 && GST_BUFFER_DATA (buffer)[0] != 0x03) {
-    return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, buffer);
-  }
-
-  tagger = GST_VORBIS_TAG (parse);
-
-  old_tags =
-      gst_tag_list_from_vorbiscomment_buffer (buffer, (guint8 *) "\003vorbis",
-      7, &encoder);
-  user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tagger));
-
-  /* build new tag list */
-  new_tags = gst_tag_list_merge (user_tags, old_tags,
-      gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tagger)));
-  gst_tag_list_free (old_tags);
-
-  new_buf =
-      gst_tag_list_to_vorbiscomment_buffer (new_tags, (guint8 *) "\003vorbis",
-      7, encoder);
-  gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS);
-
-  gst_tag_list_free (new_tags);
-  g_free (encoder);
-  gst_buffer_unref (buffer);
-
-  return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, new_buf);
-}
--- a/gst_plugins_base/ext/vorbis/vorbistag.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <2006> James Livingston <doclivingston@gmail.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_VORBIS_TAG_H__
-#define __GST_VORBIS_TAG_H__
-
-#include "vorbisparse.h"
-
-
-G_BEGIN_DECLS
-
-
-#define GST_TYPE_VORBIS_TAG \
-  (gst_vorbis_tag_get_type())
-#define GST_VORBIS_TAG(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_TAG,GstVorbisTag))
-#define GST_VORBIS_TAG_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_TAG,GstVorbisTagClass))
-#define GST_IS_VORBIS_TAG(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_TAG))
-#define GST_IS_VORBIS_TAG_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_TAG))
-
-
-typedef struct _GstVorbisTag GstVorbisTag;
-typedef struct _GstVorbisTagClass GstVorbisTagClass;
-
-/**
- * GstVorbisTag:
- *
- * Opaque data structure.
- */
-struct _GstVorbisTag {
-  GstVorbisParse parse;
-};
-
-struct _GstVorbisTagClass {
-  GstVorbisParseClass parent_class;
-};
-
-GType gst_vorbis_tag_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_TAG_H__ */
--- a/gst_plugins_base/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -17,11 +17,6 @@
 ../gst-libs/gst/interfaces/xoverlay.h				/sf/mw/gstreamer/include/gstreamer/gst/interfaces/xoverlay.h
 ../gst-libs/gst/interfaces/interfaces-enumtypes.h		/sf/mw/gstreamer/include/gstreamer/gst/interfaces/interfaces-enumtypes.h
 
-//app
-../gst-libs/gst/app/gstappbuffer.h				/sf/mw/gstreamer/include/gstreamer/gst/app/gstappbuffer.h
-../gst-libs/gst/app/gstappsink.h				/sf/mw/gstreamer/include/gstreamer/gst/app/gstappsink.h
-../gst-libs/gst/app/gstappsrc.h					/sf/mw/gstreamer/include/gstreamer/gst/app/gstappsrc.h
-
 // audio
 ../gst-libs/gst/audio/audio.h					/sf/mw/gstreamer/include/gstreamer/gst/audio/audio.h
 ../gst-libs/gst/audio/gstaudioclock.h				/sf/mw/gstreamer/include/gstreamer/gst/audio/gstaudioclock.h
@@ -33,11 +28,10 @@
 ../gst-libs/gst/audio/gstringbuffer.h				/sf/mw/gstreamer/include/gstreamer/gst/audio/gstringbuffer.h
 ../gst-libs/gst/audio/mixerutils.h				/sf/mw/gstreamer/include/gstreamer/gst/audio/mixerutils.h
 ../gst-libs/gst/audio/multichannel.h				/sf/mw/gstreamer/include/gstreamer/gst/audio/multichannel.h
-../gst-libs/gst/audio/multichannel-enumtypes.h			/sf/mw/gstreamer/include/gstreamer/gst/audio/multichannel-enumtypes.h
+../gst-libs/gst/audio/audio-enumtypes.h			/sf/mw/gstreamer/include/gstreamer/gst/audio/audio-enumtypes.h
 
 // cdda
-../gst-libs/gst/cdda/base64.h					/sf/mw/gstreamer/include/gstreamer/gst/cdda/base64.h
-../gst-libs/gst/cdda/sha1.h					/sf/mw/gstreamer/include/gstreamer/gst/cdda/sha1.h
+//../gst-libs/gst/cdda/base64.h					/sf/mw/gstreamer/include/gstreamer/gst/cdda/base64.h
 ../gst-libs/gst/cdda/gstcddabasesrc.h				/sf/mw/gstreamer/include/gstreamer/gst/cdda/gstcddabasesrc.h
 
 // floatcast
@@ -48,6 +42,10 @@
 ../gst-libs/gst/riff/riff-media.h				/sf/mw/gstreamer/include/gstreamer/gst/riff/riff-media.h
 ../gst-libs/gst/riff/riff-read.h				/sf/mw/gstreamer/include/gstreamer/gst/riff/riff-read.h
 
+//app
+../gst-libs/gst/app/gstappbuffer.h				/sf/mw/gstreamer/include/gstreamer/gst/app/gstappbuffer.h
+../gst-libs/gst/app/gstappsink.h				/sf/mw/gstreamer/include/gstreamer/gst/app/gstappsink.h
+../gst-libs/gst/app/gstappsrc.h					/sf/mw/gstreamer/include/gstreamer/gst/app/gstappsrc.h
 // rtp
 ../gst-libs/gst/rtp/gstbasertpdepayload.h			/sf/mw/gstreamer/include/gstreamer/gst/rtp/gstbasertpdepayload.h
 ../gst-libs/gst/rtp/gstbasertppayload.h				/sf/mw/gstreamer/include/gstreamer/gst/rtp/gstbasertppayload.h
@@ -67,6 +65,7 @@
 ../gst-libs/gst/video/gstvideofilter.h				/sf/mw/gstreamer/include/gstreamer/gst/video/gstvideofilter.h
 ../gst-libs/gst/video/gstvideosink.h				/sf/mw/gstreamer/include/gstreamer/gst/video/gstvideosink.h
 ../gst-libs/gst/video/video.h					/sf/mw/gstreamer/include/gstreamer/gst/video/video.h
+../gst-libs/gst/video/video-enumtypes.h					/sf/mw/gstreamer/include/gstreamer/gst/video/video-enumtypes.h
 
 // adder
 ../gst/adder/gstadder.h						/sf/mw/gstreamer/include/gstreamer/gst/adder/gstadder.h
@@ -78,11 +77,11 @@
 ../gst/audioconvert/plugin.h					/sf/mw/gstreamer/include/gstreamer/gst/audioconvert/plugin.h
 
 // audioresample
-../gst/audioresample/buffer.h					/sf/mw/gstreamer/include/gstreamer/gst/audioresample/buffer.h
-../gst/audioresample/debug.h					/sf/mw/gstreamer/include/gstreamer/gst/audioresample/debug.h
-../gst/audioresample/functable.h				/sf/mw/gstreamer/include/gstreamer/gst/audioresample/functable.h
+//../gst/audioresample/buffer.h					/sf/mw/gstreamer/include/gstreamer/gst/audioresample/buffer.h
+//../gst/audioresample/debug.h					/sf/mw/gstreamer/include/gstreamer/gst/audioresample/debug.h
+//../gst/audioresample/functable.h				/sf/mw/gstreamer/include/gstreamer/gst/audioresample/functable.h
 ../gst/audioresample/gstaudioresample.h				/sf/mw/gstreamer/include/gstreamer/gst/audioresample/gstaudioresample.h
-../gst/audioresample/resample.h					/sf/mw/gstreamer/include/gstreamer/gst/audioresample/resample.h
+//../gst/audioresample/resample.h					/sf/mw/gstreamer/include/gstreamer/gst/audioresample/resample.h
 
 // audiotestsrc
 ../gst/audiotestsrc/gstaudiotestsrc.h				/sf/mw/gstreamer/include/gstreamer/gst/audiotestsrc/gstaudiotestsrc.h
@@ -139,7 +138,7 @@
 ../gst/volume/gstvolume.h					/sf/mw/gstreamer/include/gstreamer/gst/volume/gstvolume.h
 
 //liboil   - Since liboil port is available, No need to use liboil stub.
-../gst/oil/liboil.h       															/sf/mw/gstreamer/include/gstreamer/gst/liboil.h
+//../gst/oil/liboil.h       															/sf/mw/gstreamer/include/gstreamer/gst/liboil.h
 
 // fft
 ../gst-libs/gst/fft/_kiss_fft_guts_f32.h			/sf/mw/gstreamer/include/gstreamer/gst/fft/_kiss_fft_guts_f32.h
@@ -189,16 +188,15 @@
 gstsubparse.mmp
 gsttcp.mmp
 gsttypefind.mmp
-gstapp.mmp
 gstgdp.mmp
 gstfft.mmp
-liboil.mmp
+gstapp.mmp
 
-#ifdef VIDEO
 // Video mmp
-gstvideo.mmp		//compiled
-gstvideorate.mmp		//compiled
-gstvideoscale.mmp 	// liboil  //not compiled
-gstvideotestsrc.mmp	//  liboil
+gstvideo.mmp
+gstvideorate.mmp        
+gstvideoscale.mmp   
+gstvideotestsrc.mmp 
 ffmpegcolorspace.mmp
-#endif
+
+
--- a/gst_plugins_base/group/ffmpegcolorspace.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/ffmpegcolorspace.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstffmpegcolorspace.dll
--- a/gst_plugins_base/group/gstadder.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstadder.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstadder.dll
--- a/gst_plugins_base/group/gstaudio.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstaudio.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstaudio.dll
@@ -52,8 +53,10 @@
 USERINCLUDE		../../include/gstreamer/gst/dataprotocol
 USERINCLUDE		../../include/gstreamer/gst/net
 
+USERINCLUDE     ../gst-libs/audio
+
 SOURCEPATH      ../gst-libs/gst/audio
-SOURCE          audio.c
+SOURCE          audio.c audio-enumtypes.c
 SOURCE          gstaudioclock.c
 SOURCE          mixerutils.c
 SOURCE          multichannel.c
@@ -63,8 +66,6 @@
 SOURCE          gstbaseaudiosink.c
 SOURCE          gstbaseaudiosrc.c
 SOURCE          gstringbuffer.c
-SOURCE          multichannel-enumtypes.c
-//SOURCE          gstaudiofiltertemplate.c
 
 
 LIBRARY         euser.lib
--- a/gst_plugins_base/group/gstaudioconvert.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstaudioconvert.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstaudioconvert.dll
--- a/gst_plugins_base/group/gstaudiorate.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstaudiorate.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstaudiorate.dll
--- a/gst_plugins_base/group/gstaudioresample.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstaudioresample.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstaudioresample.dll
@@ -51,13 +52,12 @@
 USERINCLUDE		../../include/gstreamer/gst/net
 
 SOURCEPATH      ../gst/audioresample
-SOURCE      buffer.c
-SOURCE      functable.c
+
 SOURCE      gstaudioresample.c
-SOURCE      resample.c
-SOURCE      resample_chunk.c
-SOURCE      resample_functable.c
-SOURCE      resample_ref.c
+//SOURCE      resample.c
+SOURCE      speex_resampler_double.c
+SOURCE      speex_resampler_float.c 
+SOURCE      speex_resampler_int.c
 
 LIBRARY         euser.lib
 LIBRARY         libgobject.lib
@@ -66,6 +66,7 @@
 LIBRARY         libm.lib
 LIBRARY         libgstreamer.lib
 LIBRARY         libgstbase.lib
+LIBRARY			liboil.lib
 
 
 MACRO           HAVE_CONFIG_H
--- a/gst_plugins_base/group/gstcdda.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstcdda.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -54,8 +54,6 @@
 
 SOURCEPATH      ../gst-libs/gst/cdda
 SOURCE          gstcddabasesrc.c
-SOURCE          base64.c
-SOURCE          sha1.c
 
 LIBRARY         euser.lib
 LIBRARY         libgobject.lib
--- a/gst_plugins_base/group/gstdecodebin.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstdecodebin.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET			libgstdecodebin.dll
--- a/gst_plugins_base/group/gstfft.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstfft.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstfft.dll
--- a/gst_plugins_base/group/gstinterfaces.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstinterfaces.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstinterfaces.dll
--- a/gst_plugins_base/group/gstpbutils.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstpbutils.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET			libgstpbutils.dll
--- a/gst_plugins_base/group/gstplayback.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstplayback.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -22,8 +22,8 @@
 
 #include <platform_paths.hrh>                    
 
-TARGET			libgstplaybin.dll
-TARGETTYPE		DLL
+TARGET			libgstplayback.dll
+TARGETTYPE		STDDLL
 UID             0x20004c45 0x2001F43E
 
 #ifdef EKA2
--- a/gst_plugins_base/group/gstplaybin.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstplaybin.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -62,6 +62,7 @@
 SOURCE  	    gstscreenshot.c
 SOURCE      	gststreaminfo.c
 SOURCE  		gststreamselector.c
+SOURCE  		gstinputselector.c
 SOURCE			gstplay-enum.c
 SOURCE			gstplay-marshal.c
 
--- a/gst_plugins_base/group/gstsubparse.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstsubparse.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -62,6 +62,7 @@
 LIBRARY		libglib.lib
 LIBRARY		libc.lib
 LIBRARY		libgstreamer.lib
+LIBRARY		libgstbase.lib
 
 
 MACRO           HAVE_CONFIG_H
--- a/gst_plugins_base/group/gstvideo.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstvideo.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -56,6 +56,7 @@
 SOURCE              gstvideofilter.c
 SOURCE              gstvideosink.c
 SOURCE              video.c
+SOURCE				video-enumtypes.c
 
 //LIBRARY         euser.lib
 LIBRARY         libc.lib
--- a/gst_plugins_base/group/gstvideotestsrc.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstvideotestsrc.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -23,7 +23,7 @@
 #include <platform_paths.hrh>                    
 
 TARGET          libgstvideotestsrc.dll
-TARGETTYPE      dll
+TARGETTYPE      DLL
 UID             0x1000008d 0x2001F442
 
 #ifdef EKA2
--- a/gst_plugins_base/group/gstvolume.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/group/gstvolume.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -43,7 +43,7 @@
 OS_LAYER_LIBC_SYSTEMINCLUDE
 
 OS_LAYER_GLIB_SYSTEMINCLUDE
-//OS_LAYER_LIBOIL_SYSTEMINCLUDE SYSTEMINCLUDE
+OS_LAYER_LIBOIL_SYSTEMINCLUDE SYSTEMINCLUDE
 USERINCLUDE		../../include/gstreamer
 USERINCLUDE		../../include/gstreamer/gst
 USERINCLUDE		../../include/gstreamer/gst/base
@@ -64,7 +64,7 @@
 LIBRARY         libpthread.lib
 LIBRARY         libc.lib
 LIBRARY         libgthread.lib
-LIBRARY			    liboil.lib
+LIBRARY			liboil.lib
 LIBRARY         libgstreamer.lib
 LIBRARY         libgstbase.lib
 LIBRARY         libgstcontroller.lib
--- a/gst_plugins_base/group/liboil.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-
-#include <platform_paths.hrh>                    
-
-TARGET      liboil.dll
-TARGETTYPE  dll
-UID         0x20004c45 0x2001F443
-
-#ifdef EKA2
-LANG            SC
-CAPABILITY All -Tcb
-VENDORID        VID_DEFAULT
-#endif
-
-#if !defined(__WINSCW__) && !defined(__WINS__)
-EpocAllowDllData
-#endif
-
-
-
-SOURCEPATH      ../gst/oil
-
-SOURCE stub.c
-
-USERINCLUDE     ../gst/oil
-USERINCLUDE     ..
-
-MW_LAYER_SYSTEMINCLUDE
-OS_LAYER_LIBC_SYSTEMINCLUDE
-
-USERINCLUDE		../../include/gstreamer
-
-LIBRARY libc.lib
-
-
-SMPSAFE
--- a/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,21 +1,5 @@
-/* GStreamer
- * Copyright (C) 2007
- *
- * 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 "gstapp-marshal.h"
+
 #include	<glib-object.h>
 
 
@@ -64,16 +48,14 @@
 #endif /* !G_ENABLE_DEBUG */
 
 
-/* VOID:UINT (gstapp-marshal.list:1) */
-
-/* BOOLEAN:UINT64 (gstapp-marshal.list:2) */
+/* BOOLEAN:UINT64 (gstapp-marshal.list:1) */
 void
 __gst_app_marshal_BOOLEAN__UINT64 (GClosure     *closure,
-                                 GValue       *return_value G_GNUC_UNUSED,
-                                 guint         n_param_values,
-                                 const GValue *param_values,
-                                 gpointer      invocation_hint G_GNUC_UNUSED,
-                                 gpointer      marshal_data)
+                                   GValue       *return_value G_GNUC_UNUSED,
+                                   guint         n_param_values,
+                                   const GValue *param_values,
+                                   gpointer      invocation_hint G_GNUC_UNUSED,
+                                   gpointer      marshal_data)
 {
   typedef gboolean (*GMarshalFunc_BOOLEAN__UINT64) (gpointer     data1,
                                                     guint64      arg_1,
@@ -105,14 +87,14 @@
   g_value_set_boolean (return_value, v_return);
 }
 
-/* ENUM:OBJECT (gstapp-marshal.list:3) */
+/* ENUM:OBJECT (gstapp-marshal.list:2) */
 void
 __gst_app_marshal_ENUM__OBJECT (GClosure     *closure,
-                              GValue       *return_value G_GNUC_UNUSED,
-                              guint         n_param_values,
-                              const GValue *param_values,
-                              gpointer      invocation_hint G_GNUC_UNUSED,
-                              gpointer      marshal_data)
+                                GValue       *return_value G_GNUC_UNUSED,
+                                guint         n_param_values,
+                                const GValue *param_values,
+                                gpointer      invocation_hint G_GNUC_UNUSED,
+                                gpointer      marshal_data)
 {
   typedef gint (*GMarshalFunc_ENUM__OBJECT) (gpointer     data1,
                                              gpointer     arg_1,
@@ -144,14 +126,14 @@
   g_value_set_enum (return_value, v_return);
 }
 
-/* ENUM:VOID (gstapp-marshal.list:4) */
+/* ENUM:VOID (gstapp-marshal.list:3) */
 void
 __gst_app_marshal_ENUM__VOID (GClosure     *closure,
-                            GValue       *return_value G_GNUC_UNUSED,
-                            guint         n_param_values,
-                            const GValue *param_values,
-                            gpointer      invocation_hint G_GNUC_UNUSED,
-                            gpointer      marshal_data)
+                              GValue       *return_value G_GNUC_UNUSED,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint G_GNUC_UNUSED,
+                              gpointer      marshal_data)
 {
   typedef gint (*GMarshalFunc_ENUM__VOID) (gpointer     data1,
                                            gpointer     data2);
@@ -181,3 +163,5 @@
   g_value_set_enum (return_value, v_return);
 }
 
+/* VOID:UINT (gstapp-marshal.list:4) */
+
--- a/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.h	Fri Apr 16 15:15:52 2010 +0300
@@ -1,56 +1,39 @@
-/* GStreamer
- * Copyright (C) 2007
- *
- * 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_app_marshal_MARSHAL_H__
-#define __gst_app_marshal_MARSHAL_H__
+
+#ifndef ____gst_app_marshal_MARSHAL_H__
+#define ____gst_app_marshal_MARSHAL_H__
 
 #include	<glib-object.h>
 
 G_BEGIN_DECLS
 
-/* VOID:UINT (gstapp-marshal.list:1) */
-#define __gst_app_marshal_VOID__UINT	g_cclosure_marshal_VOID__UINT
-
-/* BOOLEAN:UINT64 (gstapp-marshal.list:2) */
+/* BOOLEAN:UINT64 (gstapp-marshal.list:1) */
 extern void __gst_app_marshal_BOOLEAN__UINT64 (GClosure     *closure,
-                                             GValue       *return_value,
-                                             guint         n_param_values,
-                                             const GValue *param_values,
-                                             gpointer      invocation_hint,
-                                             gpointer      marshal_data);
+                                               GValue       *return_value,
+                                               guint         n_param_values,
+                                               const GValue *param_values,
+                                               gpointer      invocation_hint,
+                                               gpointer      marshal_data);
 
-/* ENUM:OBJECT (gstapp-marshal.list:3) */
+/* ENUM:OBJECT (gstapp-marshal.list:2) */
 extern void __gst_app_marshal_ENUM__OBJECT (GClosure     *closure,
+                                            GValue       *return_value,
+                                            guint         n_param_values,
+                                            const GValue *param_values,
+                                            gpointer      invocation_hint,
+                                            gpointer      marshal_data);
+
+/* ENUM:VOID (gstapp-marshal.list:3) */
+extern void __gst_app_marshal_ENUM__VOID (GClosure     *closure,
                                           GValue       *return_value,
                                           guint         n_param_values,
                                           const GValue *param_values,
                                           gpointer      invocation_hint,
                                           gpointer      marshal_data);
 
-/* ENUM:VOID (gstapp-marshal.list:4) */
-extern void __gst_app_marshal_ENUM__VOID (GClosure     *closure,
-                                        GValue       *return_value,
-                                        guint         n_param_values,
-                                        const GValue *param_values,
-                                        gpointer      invocation_hint,
-                                        gpointer      marshal_data);
+/* VOID:UINT (gstapp-marshal.list:4) */
+#define __gst_app_marshal_VOID__UINT	g_cclosure_marshal_VOID__UINT
 
 G_END_DECLS
 
-#endif /* __gst_app_marshal_MARSHAL_H__ */
+#endif /* ____gst_app_marshal_MARSHAL_H__ */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.list	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,5 @@
+BOOLEAN:UINT64
+ENUM:OBJECT
+ENUM:VOID
+VOID:UINT
+
--- a/gst_plugins_base/gst-libs/gst/app/gstappsink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/app/gstappsink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -84,13 +84,12 @@
 #include <gst/gst.h>
 #include <gst/base/gstbasesink.h>
 #include <gst/gstbuffer.h>
+#include <gst/gstbufferlist.h>
 
 #include <string.h>
 
 #include "gstappsink.h"
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
+
 struct _GstAppSinkPrivate
 {
   GstCaps *caps;
@@ -120,10 +119,12 @@
   SIGNAL_EOS,
   SIGNAL_NEW_PREROLL,
   SIGNAL_NEW_BUFFER,
+  SIGNAL_NEW_BUFFER_LIST,
 
   /* actions */
   SIGNAL_PULL_PREROLL,
   SIGNAL_PULL_BUFFER,
+  SIGNAL_PULL_BUFFER_LIST,
 
   LAST_SIGNAL
 };
@@ -161,7 +162,6 @@
 static void gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass);
 static void gst_app_sink_base_init (gpointer g_class);
 #endif
-
 static void gst_app_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_app_sink_get_property (GObject * object, guint prop_id,
@@ -174,9 +174,14 @@
 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
     GstBuffer * buffer);
+static GstFlowReturn gst_app_sink_render_common (GstBaseSink * psink,
+    GstMiniObject * data, gboolean is_list);
 static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
     GstBuffer * buffer);
+static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink,
+    GstBufferList * list);
 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink);
+static GstMiniObject *gst_app_sink_pull_object (GstAppSink * appsink);
 
 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
 
@@ -204,7 +209,6 @@
       g_type_class_peek_parent (g_class);              
       gst_app_sink_class_init ((GstAppSinkClass *)g_class);       
 }
-
 EXPORT_C GType
 gst_app_sink_get_type (void)
 {
@@ -292,28 +296,28 @@
   g_object_class_install_property (gobject_class, PROP_CAPS,
       g_param_spec_boxed ("caps", "Caps",
           "The allowed caps for the sink pad", GST_TYPE_CAPS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_EOS,
       g_param_spec_boolean ("eos", "EOS",
           "Check if the sink is EOS or not started", DEFAULT_PROP_EOS,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
       g_param_spec_boolean ("emit-signals", "Emit signals",
           "Emit new-preroll and new-buffer signals", DEFAULT_PROP_EMIT_SIGNALS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
       g_param_spec_uint ("max-buffers", "Max Buffers",
           "The maximum number of buffers to queue internally (0 = unlimited)",
           0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_DROP,
       g_param_spec_boolean ("drop", "Drop",
           "Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstAppSink::eos:
@@ -366,6 +370,26 @@
       g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+  /**
+   * GstAppSink::new-buffer-list:
+   * @appsink: the appsink element that emited the signal
+   *
+   * Signal that a new bufferlist is available.
+   *
+   * This signal is emited from the steaming thread and only when the
+   * "emit-signals" property is %TRUE. 
+   *
+   * The new buffer can be retrieved with the "pull-buffer-list" action
+   * signal or gst_app_sink_pull_buffe_listr() either from this signal callback
+   * or from any other thread.
+   *
+   * Note that this signal is only emited when the "emit-signals" property is
+   * set to %TRUE, which it is not by default for performance reasons.
+   */
+  gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] =
+      g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list),
+      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
 
   /**
    * GstAppSink::pull-preroll:
@@ -421,6 +445,32 @@
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
           pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID,
       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
+  /**
+   * GstAppSink::pull-buffer-list:
+   * @appsink: the appsink element to emit this signal on
+   *
+   * This function blocks until a buffer list or EOS becomes available or the appsink
+   * element is set to the READY/NULL state. 
+   *
+   * This function will only return bufferlists when the appsink is in the PLAYING
+   * state. All rendered bufferlists will be put in a queue so that the application
+   * can pull bufferlists at its own rate. 
+   *
+   * Note that when the application does not pull bufferlists fast enough, the
+   * queued bufferlists could consume a lot of memory, especially when dealing with
+   * raw video frames. It's possible to control the behaviour of the queue with
+   * the "drop" and "max-buffers" properties.
+   *
+   * If an EOS event was received before any buffers, this function returns
+   * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
+   *
+   * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
+   */
+  gst_app_sink_signals[SIGNAL_PULL_BUFFER_LIST] =
+      g_signal_new ("pull-buffer-list", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
+          pull_buffer_list), NULL, NULL, gst_app_marshal_BUFFER__VOID,
+      GST_TYPE_BUFFER_LIST, 0, G_TYPE_NONE);
 
   basesink_class->unlock = gst_app_sink_unlock_start;
   basesink_class->unlock_stop = gst_app_sink_unlock_stop;
@@ -429,10 +479,12 @@
   basesink_class->event = gst_app_sink_event;
   basesink_class->preroll = gst_app_sink_preroll;
   basesink_class->render = gst_app_sink_render;
+  basesink_class->render_list = gst_app_sink_render_list;
   basesink_class->get_caps = gst_app_sink_getcaps;
 
   klass->pull_preroll = gst_app_sink_pull_preroll;
   klass->pull_buffer = gst_app_sink_pull_buffer;
+  klass->pull_buffer_list = gst_app_sink_pull_buffer_list;
 
   g_type_class_add_private (klass, sizeof (GstAppSinkPrivate));
 }
@@ -456,7 +508,7 @@
 gst_app_sink_dispose (GObject * obj)
 {
   GstAppSink *appsink = GST_APP_SINK (obj);
-  GstBuffer *buffer;
+  GstMiniObject *queue_obj;
 
   GST_OBJECT_LOCK (appsink);
   if (appsink->priv->caps) {
@@ -476,8 +528,8 @@
     gst_buffer_unref (appsink->priv->preroll);
     appsink->priv->preroll = NULL;
   }
-  while ((buffer = g_queue_pop_head (appsink->priv->queue)))
-    gst_buffer_unref (buffer);
+  while ((queue_obj = g_queue_pop_head (appsink->priv->queue)))
+    gst_mini_object_unref (queue_obj);
   g_mutex_unlock (appsink->priv->mutex);
 
   G_OBJECT_CLASS (parent_class)->dispose (obj);
@@ -586,13 +638,13 @@
 static void
 gst_app_sink_flush_unlocked (GstAppSink * appsink)
 {
-  GstBuffer *buffer;
+  GstMiniObject *obj;
 
   GST_DEBUG_OBJECT (appsink, "flush stop appsink");
   appsink->priv->is_eos = FALSE;
   gst_buffer_replace (&appsink->priv->preroll, NULL);
-  while ((buffer = g_queue_pop_head (appsink->priv->queue)))
-    gst_buffer_unref (buffer);
+  while ((obj = g_queue_pop_head (appsink->priv->queue)))
+    gst_mini_object_unref (obj);
   g_cond_signal (appsink->priv->cond);
 }
 
@@ -698,9 +750,9 @@
 }
 
 static GstFlowReturn
-gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
+gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data,
+    gboolean is_list)
 {
-  GstFlowReturn res = GST_FLOW_OK;
   GstAppSink *appsink = GST_APP_SINK (psink);
   gboolean emit;
 
@@ -708,18 +760,18 @@
   if (appsink->priv->flushing)
     goto flushing;
 
-  GST_DEBUG_OBJECT (appsink, "pushing render buffer %p on queue (%d)",
-      buffer, appsink->priv->queue->length);
+  GST_DEBUG_OBJECT (appsink, "pushing render buffer%s %p on queue (%d)",
+      is_list ? " list" : "", data, appsink->priv->queue->length);
 
   while (appsink->priv->max_buffers > 0 &&
       appsink->priv->queue->length >= appsink->priv->max_buffers) {
     if (appsink->priv->drop) {
-      GstBuffer *buf;
+      GstMiniObject *obj;
 
-      /* we need to drop the oldest buffer and try again */
-      buf = g_queue_pop_head (appsink->priv->queue);
-      GST_DEBUG_OBJECT (appsink, "dropping old buffer %p", buf);
-      gst_buffer_unref (buf);
+      /* we need to drop the oldest buffer/list and try again */
+      obj = g_queue_pop_head (appsink->priv->queue);
+      GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", obj);
+      gst_mini_object_unref (obj);
     } else {
       GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
           appsink->priv->queue->length, appsink->priv->max_buffers);
@@ -730,19 +782,22 @@
     }
   }
   /* we need to ref the buffer when pushing it in the queue */
-  g_queue_push_tail (appsink->priv->queue, gst_buffer_ref (buffer));
-
+  g_queue_push_tail (appsink->priv->queue, gst_mini_object_ref (data));
   g_cond_signal (appsink->priv->cond);
   emit = appsink->priv->emit_signals;
   g_mutex_unlock (appsink->priv->mutex);
 
-  if (appsink->priv->callbacks.new_buffer)
-    res =
-        appsink->priv->callbacks.new_buffer (appsink, appsink->priv->user_data);
-  else if (emit)
-    g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
-
-  return res;
+  if (is_list) {
+    if (appsink->priv->callbacks.new_buffer_list)
+      appsink->priv->callbacks.new_buffer_list (appsink,
+          appsink->priv->user_data);
+  } else {
+    if (appsink->priv->callbacks.new_buffer)
+      appsink->priv->callbacks.new_buffer (appsink, appsink->priv->user_data);
+    else if (emit)
+      g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
+  }
+  return GST_FLOW_OK;
 
 flushing:
   {
@@ -752,6 +807,19 @@
   }
 }
 
+static GstFlowReturn
+gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
+{
+  return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer),
+      FALSE);
+}
+
+static GstFlowReturn
+gst_app_sink_render_list (GstBaseSink * psink, GstBufferList * list)
+{
+  return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (list), TRUE);
+}
+
 static GstCaps *
 gst_app_sink_getcaps (GstBaseSink * psink)
 {
@@ -768,6 +836,53 @@
   return caps;
 }
 
+static GstMiniObject *
+gst_app_sink_pull_object (GstAppSink * appsink)
+{
+  GstMiniObject *obj = NULL;
+
+  g_return_val_if_fail (appsink != NULL, NULL);
+  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
+
+  g_mutex_lock (appsink->priv->mutex);
+
+  while (TRUE) {
+    GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list");
+    if (!appsink->priv->started)
+      goto not_started;
+
+    if (!g_queue_is_empty (appsink->priv->queue))
+      break;
+
+    if (appsink->priv->is_eos)
+      goto eos;
+
+    /* nothing to return, wait */
+    GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list");
+    g_cond_wait (appsink->priv->cond, appsink->priv->mutex);
+  }
+  obj = g_queue_pop_head (appsink->priv->queue);
+  GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj);
+  g_cond_signal (appsink->priv->cond);
+  g_mutex_unlock (appsink->priv->mutex);
+
+  return obj;
+
+  /* special conditions */
+eos:
+  {
+    GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
+    g_mutex_unlock (appsink->priv->mutex);
+    return NULL;
+  }
+not_started:
+  {
+    GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
+    g_mutex_unlock (appsink->priv->mutex);
+    return NULL;
+  }
+}
+
 /* external API */
 
 /**
@@ -1111,51 +1226,38 @@
  *
  * Since: 0.10.22
  */
+
 EXPORT_C GstBuffer *
 gst_app_sink_pull_buffer (GstAppSink * appsink)
 {
-  GstBuffer *buf = NULL;
-
-  g_return_val_if_fail (appsink != NULL, NULL);
-  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
-
-  g_mutex_lock (appsink->priv->mutex);
-
-  while (TRUE) {
-    GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
-    if (!appsink->priv->started)
-      goto not_started;
-
-    if (!g_queue_is_empty (appsink->priv->queue))
-      break;
-
-    if (appsink->priv->is_eos)
-      goto eos;
+  GST_DEBUG_OBJECT (appsink, "pull a buffer");
+  return GST_BUFFER_CAST (gst_app_sink_pull_object (appsink));
+}
 
-    /* nothing to return, wait */
-    GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
-    g_cond_wait (appsink->priv->cond, appsink->priv->mutex);
-  }
-  buf = g_queue_pop_head (appsink->priv->queue);
-  GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buf);
-  g_cond_signal (appsink->priv->cond);
-  g_mutex_unlock (appsink->priv->mutex);
-
-  return buf;
-
-  /* special conditions */
-eos:
-  {
-    GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
-    g_mutex_unlock (appsink->priv->mutex);
-    return NULL;
-  }
-not_started:
-  {
-    GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
-    g_mutex_unlock (appsink->priv->mutex);
-    return NULL;
-  }
+/**
+ * gst_app_sink_pull_buffer_list:
+ * @appsink: a #GstAppSink
+ *
+ * This function blocks until a buffer list or EOS becomes available or the
+ * appsink element is set to the READY/NULL state. 
+ *
+ * This function will only return buffer lists when the appsink is in the
+ * PLAYING state. All rendered buffer lists will be put in a queue so that
+ * the application can pull buffer lists at its own rate. Note that when
+ * the application does not pull buffer lists fast enough, the queued buffer
+ * lists could consume a lot of memory, especially when dealing with raw
+ * video frames.
+ *
+ * If an EOS event was received before any buffer lists, this function returns
+ * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
+ *
+ * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
+ */
+EXPORT_C GstBufferList *
+gst_app_sink_pull_buffer_list (GstAppSink * appsink)
+{
+  GST_DEBUG_OBJECT (appsink, "pull a buffer list");
+  return GST_BUFFER_LIST_CAST (gst_app_sink_pull_object (appsink));
 }
 
 /**
@@ -1174,7 +1276,7 @@
  *
  * Since: 0.10.23
  */
-void
+EXPORT_C void
 gst_app_sink_set_callbacks (GstAppSink * appsink,
     GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify)
 {
--- a/gst_plugins_base/gst-libs/gst/app/gstappsink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/app/gstappsink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -57,6 +57,11 @@
  *       The new buffer can be retrieved with
  *       gst_app_sink_pull_buffer() either from this callback
  *       or from any other thread.
+ * @new_buffer_list: Called when a new bufferlist is available. 
+ *       This callback is called from the steaming thread.
+ *       The new bufferlist can be retrieved with
+ *       gst_app_sink_pull_buffer_list() either from this callback
+ *       or from any other thread.
  *
  * A set of callbacks that can be installed on the appsink with
  * gst_app_sink_set_callbacks().
@@ -64,12 +69,13 @@
  * Since: 0.10.23
  */
 typedef struct {
-  void          (*eos)           (GstAppSink *sink, gpointer user_data);
-  GstFlowReturn (*new_preroll)   (GstAppSink *sink, gpointer user_data);
-  GstFlowReturn (*new_buffer)    (GstAppSink *sink, gpointer user_data);
+  void          (*eos)              (GstAppSink *sink, gpointer user_data);
+  GstFlowReturn (*new_preroll)      (GstAppSink *sink, gpointer user_data);
+  GstFlowReturn (*new_buffer)       (GstAppSink *sink, gpointer user_data);
+  GstFlowReturn (*new_buffer_list)  (GstAppSink *sink, gpointer user_data);
 
   /*< private >*/
-  gpointer     _gst_reserved[GST_PADDING];
+  gpointer     _gst_reserved[GST_PADDING - 1];
 } GstAppSinkCallbacks;
 
 struct _GstAppSink
@@ -93,11 +99,15 @@
   void        (*new_buffer)   (GstAppSink *sink);
 
   /* actions */
-  GstBuffer * (*pull_preroll)  (GstAppSink *sink);
-  GstBuffer * (*pull_buffer)   (GstAppSink *sink);
+  GstBuffer     * (*pull_preroll)      (GstAppSink *sink);
+  GstBuffer     * (*pull_buffer)       (GstAppSink *sink);
+
+  /* ABI added */
+  GstBufferList * (*new_buffer_list)   (GstAppSink *sink);
+  GstBufferList * (*pull_buffer_list)  (GstAppSink *sink);
 
   /*< private >*/
-  gpointer     _gst_reserved[GST_PADDING];
+  gpointer     _gst_reserved[GST_PADDING - 2];
 };
 
 IMPORT_C GType gst_app_sink_get_type(void);
@@ -118,6 +128,7 @@
 
 IMPORT_C GstBuffer *     gst_app_sink_pull_preroll   (GstAppSink *appsink);
 IMPORT_C GstBuffer *     gst_app_sink_pull_buffer    (GstAppSink *appsink);
+IMPORT_C GstBufferList * gst_app_sink_pull_buffer_list (GstAppSink *appsink);
 
 IMPORT_C void            gst_app_sink_set_callbacks    (GstAppSink * appsink,
                                                GstAppSinkCallbacks *callbacks,
--- a/gst_plugins_base/gst-libs/gst/app/gstappsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/app/gstappsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -113,9 +113,6 @@
 
 #include "gstapp-marshal.h"
 #include "gstappsrc.h"
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
 
 struct _GstAppSrcPrivate
 {
@@ -225,7 +222,6 @@
 static void gst_app_src_class_init (GstAppSrcClass * klass);
 static void gst_app_src_init (GstAppSrc * appsrc, GstAppSrcClass * klass);
 #endif
-
 static void gst_app_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_app_src_get_property (GObject * object, guint prop_id,
@@ -267,7 +263,6 @@
 GST_BOILERPLATE_FULL (GstAppSrc, gst_app_src, GstBaseSrc, GST_TYPE_BASE_SRC,
     _do_init);
 #else
-
 static GstBaseSrcClass *parent_class = NULL;           
 static void
 gst_app_src_class_init_trampoline (gpointer g_class,
@@ -277,7 +272,6 @@
       g_type_class_peek_parent (g_class);              
       gst_app_src_class_init ((GstAppSrcClass *)g_class);       
 }
-
 EXPORT_C GType
 gst_app_src_get_type (void)
 {
@@ -302,8 +296,6 @@
 }
 #endif
 
-
-
 static void
 gst_app_src_base_init (gpointer g_class)
 {
@@ -340,7 +332,7 @@
   g_object_class_install_property (gobject_class, PROP_CAPS,
       g_param_spec_boxed ("caps", "Caps",
           "The allowed caps for the src pad", GST_TYPE_CAPS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::format
    *
@@ -350,7 +342,7 @@
   g_object_class_install_property (gobject_class, PROP_FORMAT,
       g_param_spec_enum ("format", "Format",
           "The format of the segment events and seek", GST_TYPE_FORMAT,
-          DEFAULT_PROP_FORMAT, G_PARAM_READWRITE));
+          DEFAULT_PROP_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::size
    *
@@ -361,7 +353,7 @@
       g_param_spec_int64 ("size", "Size",
           "The size of the data stream in bytes (-1 if unknown)",
           -1, G_MAXINT64, DEFAULT_PROP_SIZE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::stream-type
    *
@@ -372,7 +364,7 @@
       g_param_spec_enum ("stream-type", "Stream Type",
           "the type of the stream", GST_TYPE_APP_STREAM_TYPE,
           DEFAULT_PROP_STREAM_TYPE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::max-bytes
    *
@@ -384,7 +376,7 @@
       g_param_spec_uint64 ("max-bytes", "Max bytes",
           "The maximum number of bytes to queue internally (0 = unlimited)",
           0, G_MAXUINT64, DEFAULT_PROP_MAX_BYTES,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::block
    *
@@ -395,7 +387,7 @@
   g_object_class_install_property (gobject_class, PROP_BLOCK,
       g_param_spec_boolean ("block", "Block",
           "Block push-buffer when max-bytes are queued",
-          DEFAULT_PROP_BLOCK, G_PARAM_READWRITE));
+          DEFAULT_PROP_BLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstAppSrc::is-live
@@ -406,7 +398,7 @@
   g_object_class_install_property (gobject_class, PROP_IS_LIVE,
       g_param_spec_boolean ("is-live", "Is Live",
           "Whether to act as a live source",
-          DEFAULT_PROP_IS_LIVE, G_PARAM_READWRITE ));
+          DEFAULT_PROP_IS_LIVE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::min-latency
    *
@@ -417,7 +409,7 @@
       g_param_spec_int64 ("min-latency", "Min Latency",
           "The minimum latency (-1 = default)",
           -1, G_MAXINT64, DEFAULT_PROP_MIN_LATENCY,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstAppSrc::max-latency
    *
@@ -428,7 +420,7 @@
       g_param_spec_int64 ("max-latency", "Max Latency",
           "The maximum latency (-1 = unlimited)",
           -1, G_MAXINT64, DEFAULT_PROP_MAX_LATENCY,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstAppSrc::emit-signals
@@ -442,7 +434,7 @@
   g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
       g_param_spec_boolean ("emit-signals", "Emit signals",
           "Emit new-preroll and new-buffer signals", DEFAULT_PROP_EMIT_SIGNALS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstAppSrc::need-data:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/audio/TODO	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,15 @@
+TODO 
+----
+
+- audio base classes:
+   - GstBaseAudioSink
+      - parse caps into rinbuffer spec, also make sure surround sound
+        is parsed correctly.
+      - implement seek/query/convert
+      - implement getrange scheduling
+   - simple resampling
+   - more accurate master/slave calibration handling
+   - faster audio cutoff when going to PAUSED
+   - resubmit samples from ringbuffer when doing PAUSED->PLAYING again
+   - the ringbuffer should have a state where it is filling up the
+     buffer before going to playing.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/audio/audio-enumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,172 @@
+
+/* Generated data (by glib-mkenums) */
+
+#include "audio-enumtypes.h"
+
+#include "multichannel.h" 
+#include "gstringbuffer.h"
+
+/* enumerations from "multichannel.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_audio_channel_position_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_AUDIO_CHANNEL_POSITION_INVALID, "GST_AUDIO_CHANNEL_POSITION_INVALID", "invalid" },
+      { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO", "front-mono" },
+      { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT", "front-left" },
+      { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT", "front-right" },
+      { GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, "GST_AUDIO_CHANNEL_POSITION_REAR_CENTER", "rear-center" },
+      { GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, "GST_AUDIO_CHANNEL_POSITION_REAR_LEFT", "rear-left" },
+      { GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, "GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT", "rear-right" },
+      { GST_AUDIO_CHANNEL_POSITION_LFE, "GST_AUDIO_CHANNEL_POSITION_LFE", "lfe" },
+      { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, "GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER", "front-center" },
+      { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER", "front-left-of-center" },
+      { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER", "front-right-of-center" },
+      { GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, "GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT", "side-left" },
+      { GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, "GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT", "side-right" },
+      { GST_AUDIO_CHANNEL_POSITION_NONE, "GST_AUDIO_CHANNEL_POSITION_NONE", "none" },
+      { GST_AUDIO_CHANNEL_POSITION_NUM, "GST_AUDIO_CHANNEL_POSITION_NUM", "num" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstAudioChannelPosition", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+
+/* enumerations from "gstringbuffer.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_ring_buffer_state_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RING_BUFFER_STATE_STOPPED, "GST_RING_BUFFER_STATE_STOPPED", "stopped" },
+      { GST_RING_BUFFER_STATE_PAUSED, "GST_RING_BUFFER_STATE_PAUSED", "paused" },
+      { GST_RING_BUFFER_STATE_STARTED, "GST_RING_BUFFER_STATE_STARTED", "started" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRingBufferState", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_ring_buffer_seg_state_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_SEGSTATE_INVALID, "GST_SEGSTATE_INVALID", "invalid" },
+      { GST_SEGSTATE_EMPTY, "GST_SEGSTATE_EMPTY", "empty" },
+      { GST_SEGSTATE_FILLED, "GST_SEGSTATE_FILLED", "filled" },
+      { GST_SEGSTATE_PARTIAL, "GST_SEGSTATE_PARTIAL", "partial" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRingBufferSegState", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_buffer_format_type_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_BUFTYPE_LINEAR, "GST_BUFTYPE_LINEAR", "linear" },
+      { GST_BUFTYPE_FLOAT, "GST_BUFTYPE_FLOAT", "float" },
+      { GST_BUFTYPE_MU_LAW, "GST_BUFTYPE_MU_LAW", "mu-law" },
+      { GST_BUFTYPE_A_LAW, "GST_BUFTYPE_A_LAW", "a-law" },
+      { GST_BUFTYPE_IMA_ADPCM, "GST_BUFTYPE_IMA_ADPCM", "ima-adpcm" },
+      { GST_BUFTYPE_MPEG, "GST_BUFTYPE_MPEG", "mpeg" },
+      { GST_BUFTYPE_GSM, "GST_BUFTYPE_GSM", "gsm" },
+      { GST_BUFTYPE_IEC958, "GST_BUFTYPE_IEC958", "iec958" },
+      { GST_BUFTYPE_AC3, "GST_BUFTYPE_AC3", "ac3" },
+      { GST_BUFTYPE_EAC3, "GST_BUFTYPE_EAC3", "eac3" },
+      { GST_BUFTYPE_DTS, "GST_BUFTYPE_DTS", "dts" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstBufferFormatType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_buffer_format_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_UNKNOWN, "GST_UNKNOWN", "unknown" },
+      { GST_S8, "GST_S8", "s8" },
+      { GST_U8, "GST_U8", "u8" },
+      { GST_S16_LE, "GST_S16_LE", "s16-le" },
+      { GST_S16_BE, "GST_S16_BE", "s16-be" },
+      { GST_U16_LE, "GST_U16_LE", "u16-le" },
+      { GST_U16_BE, "GST_U16_BE", "u16-be" },
+      { GST_S24_LE, "GST_S24_LE", "s24-le" },
+      { GST_S24_BE, "GST_S24_BE", "s24-be" },
+      { GST_U24_LE, "GST_U24_LE", "u24-le" },
+      { GST_U24_BE, "GST_U24_BE", "u24-be" },
+      { GST_S32_LE, "GST_S32_LE", "s32-le" },
+      { GST_S32_BE, "GST_S32_BE", "s32-be" },
+      { GST_U32_LE, "GST_U32_LE", "u32-le" },
+      { GST_U32_BE, "GST_U32_BE", "u32-be" },
+      { GST_S24_3LE, "GST_S24_3LE", "s24-3le" },
+      { GST_S24_3BE, "GST_S24_3BE", "s24-3be" },
+      { GST_U24_3LE, "GST_U24_3LE", "u24-3le" },
+      { GST_U24_3BE, "GST_U24_3BE", "u24-3be" },
+      { GST_S20_3LE, "GST_S20_3LE", "s20-3le" },
+      { GST_S20_3BE, "GST_S20_3BE", "s20-3be" },
+      { GST_U20_3LE, "GST_U20_3LE", "u20-3le" },
+      { GST_U20_3BE, "GST_U20_3BE", "u20-3be" },
+      { GST_S18_3LE, "GST_S18_3LE", "s18-3le" },
+      { GST_S18_3BE, "GST_S18_3BE", "s18-3be" },
+      { GST_U18_3LE, "GST_U18_3LE", "u18-3le" },
+      { GST_U18_3BE, "GST_U18_3BE", "u18-3be" },
+      { GST_FLOAT32_LE, "GST_FLOAT32_LE", "float32-le" },
+      { GST_FLOAT32_BE, "GST_FLOAT32_BE", "float32-be" },
+      { GST_FLOAT64_LE, "GST_FLOAT64_LE", "float64-le" },
+      { GST_FLOAT64_BE, "GST_FLOAT64_BE", "float64-be" },
+      { GST_MU_LAW, "GST_MU_LAW", "mu-law" },
+      { GST_A_LAW, "GST_A_LAW", "a-law" },
+      { GST_IMA_ADPCM, "GST_IMA_ADPCM", "ima-adpcm" },
+      { GST_MPEG, "GST_MPEG", "mpeg" },
+      { GST_GSM, "GST_GSM", "gsm" },
+      { GST_IEC958, "GST_IEC958", "iec958" },
+      { GST_AC3, "GST_AC3", "ac3" },
+      { GST_EAC3, "GST_EAC3", "eac3" },
+      { GST_DTS, "GST_DTS", "dts" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstBufferFormat", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+
+/* Generated data ends here */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/audio/audio-enumtypes.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,37 @@
+
+/* Generated data (by glib-mkenums) */
+
+#ifndef __GST_AUDIO_ENUM_TYPES_H__
+#define __GST_AUDIO_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* enumerations from "multichannel.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_audio_channel_position_get_type (void);
+#define GST_TYPE_AUDIO_CHANNEL_POSITION (gst_audio_channel_position_get_type())
+
+/* enumerations from "gstringbuffer.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_ring_buffer_state_get_type (void);
+#define GST_TYPE_RING_BUFFER_STATE (gst_ring_buffer_state_get_type())
+GType gst_ring_buffer_seg_state_get_type (void);
+#define GST_TYPE_RING_BUFFER_SEG_STATE (gst_ring_buffer_seg_state_get_type())
+GType gst_buffer_format_type_get_type (void);
+#define GST_TYPE_BUFFER_FORMAT_TYPE (gst_buffer_format_type_get_type())
+GType gst_buffer_format_get_type (void);
+#define GST_TYPE_BUFFER_FORMAT (gst_buffer_format_get_type())
+G_END_DECLS
+
+#endif /* __GST_AUDIO_ENUM_TYPES_H__ */
+
+/* Generated data ends here */
+
--- a/gst_plugins_base/gst-libs/gst/audio/audio.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/audio.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,27 +16,22 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:gstaudio
+ * @short_description: Support library for audio elements
+ *
+ * This library contains some helper functions for audio elements.
+ */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
 #include "audio.h"
-#include "multichannel-enumtypes.h"
+#include "audio-enumtypes.h"
 
 #include <gst/gststructure.h>
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
-/**
- * SECTION:gstaudio
- * @short_description: Support library for audio elements
- *
- * This library contains some helper functions for audio elements.
- */
-
 /**
  * gst_audio_frame_byte_size:
  * @pad: the #GstPad to get the caps from
@@ -117,7 +112,7 @@
  * Calculate length in nanoseconds of audio buffer @buf based on capabilities of
  * @pad.
  *
- * Return: the length.
+ * Returns: the length.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
--- a/gst_plugins_base/gst-libs/gst/audio/audio.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/audio.h	Fri Apr 16 15:15:52 2010 +0300
@@ -77,6 +77,12 @@
  */
 #define GST_AUDIO_DEF_RATE 44100
 
+/**
+ * GST_AUDIO_INT_PAD_TEMPLATE_CAPS:
+ * 
+ * Template caps for integer audio. Can be used when defining a 
+ * #GstStaticPadTemplate
+ */
 #define GST_AUDIO_INT_PAD_TEMPLATE_CAPS \
   "audio/x-raw-int, " \
   "rate = (int) [ 1, MAX ], " \
@@ -86,7 +92,12 @@
   "depth = (int) [ 1, 32 ], " \
   "signed = (boolean) { true, false }"
 
-/* "standard" int audio is native order, 16 bit stereo. */
+/**
+ * GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS:
+ * 
+ * Template caps for 16bit integer stereo audio in native byte-order.
+ * Can be used when defining a #GstStaticPadTemplate
+ */
 #define GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS \
   "audio/x-raw-int, " \
   "rate = (int) [ 1, MAX ], " \
@@ -96,6 +107,12 @@
   "depth = (int) 16, " \
   "signed = (boolean) true"
 
+/**
+ * GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS:
+ * 
+ * Template caps for float audio. Can be used when defining a 
+ * #GstStaticPadTemplate
+ */
 #define GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS \
   "audio/x-raw-float, " \
   "rate = (int) [ 1, MAX ], " \
@@ -103,7 +120,12 @@
   "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " \
   "width = (int) { 32, 64 }"
 
-/* "standard" float audio is native order, 32 bit mono. */
+/**
+ * GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS:
+ * 
+ * Template caps for 32bit float mono audio in native byte-order.
+ * Can be used when defining a #GstStaticPadTemplate
+ */
 #define GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS \
   "audio/x-raw-float, " \
   "width = (int) 32, " \
@@ -158,7 +180,7 @@
   GST_AUDIO_FIELD_ENDIANNESS    = (1 << 2),
   GST_AUDIO_FIELD_WIDTH         = (1 << 3),
   GST_AUDIO_FIELD_DEPTH         = (1 << 4),
-  GST_AUDIO_FIELD_SIGNED        = (1 << 5),
+  GST_AUDIO_FIELD_SIGNED        = (1 << 5)
 } GstAudioFieldFlag;
 #endif
 
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudioclock.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudioclock.c	Fri Apr 16 15:15:52 2010 +0300
@@ -39,6 +39,9 @@
 
 #include "gstaudioclock.h"
 
+GST_DEBUG_CATEGORY_STATIC (gst_audio_clock_debug);
+#define GST_CAT_DEFAULT gst_audio_clock_debug
+
 static void gst_audio_clock_class_init (GstAudioClockClass * klass);
 static void gst_audio_clock_init (GstAudioClock * clock);
 
@@ -92,12 +95,16 @@
   parent_class = g_type_class_peek_parent (klass);
 
   gstclock_class->get_internal_time = gst_audio_clock_get_internal_time;
+
+  GST_DEBUG_CATEGORY_INIT (gst_audio_clock_debug, "audioclock", 0,
+      "audioclock");
 }
 
 static void
 gst_audio_clock_init (GstAudioClock * clock)
 {
   clock->last_time = 0;
+  clock->abidata.ABI.time_offset = 0;
   GST_OBJECT_FLAG_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER);
 }
 
@@ -118,7 +125,7 @@
 #endif
 
 GstClock *
-gst_audio_clock_new (gchar * name, GstAudioClockGetTimeFunc func,
+gst_audio_clock_new (const gchar * name, GstAudioClockGetTimeFunc func,
     gpointer user_data)
 {
   GstAudioClock *aclock =
@@ -130,17 +137,119 @@
   return (GstClock *) aclock;
 }
 
+/**
+ * gst_audio_clock_reset:
+ * @clock: a #GstAudioClock
+ * @time: a #GstClockTime
+ *
+ * Inform @clock that future calls to #GstAudioClockGetTimeFunc will return values
+ * starting from @time. The clock will update an internal offset to make sure that
+ * future calls to internal_time will return an increasing result as required by
+ * the #GstClock object.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_audio_clock_reset (GstAudioClock * clock, GstClockTime time)
+{
+  GstClockTimeDiff time_offset;
+
+  if (clock->last_time >= time)
+    time_offset = clock->last_time - time;
+  else
+    time_offset = -(time - clock->last_time);
+
+  clock->abidata.ABI.time_offset = time_offset;
+
+  GST_DEBUG_OBJECT (clock,
+      "reset clock to %" GST_TIME_FORMAT ", offset %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (time), GST_TIME_ARGS (time_offset));
+}
+
 static GstClockTime
 gst_audio_clock_get_internal_time (GstClock * clock)
 {
-  GstAudioClock *aclock = GST_AUDIO_CLOCK (clock);
+  GstAudioClock *aclock;
   GstClockTime result;
 
+  aclock = GST_AUDIO_CLOCK_CAST (clock);
+
   result = aclock->func (clock, aclock->user_data);
-  if (result == GST_CLOCK_TIME_NONE)
+  if (result == GST_CLOCK_TIME_NONE) {
     result = aclock->last_time;
-  else
-    aclock->last_time = result;
+  } else {
+    result += aclock->abidata.ABI.time_offset;
+    /* clock must be increasing */
+    if (aclock->last_time < result)
+      aclock->last_time = result;
+    else
+      result = aclock->last_time;
+  }
+
+  GST_DEBUG_OBJECT (clock,
+      "result %" GST_TIME_FORMAT ", last_time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (result), GST_TIME_ARGS (aclock->last_time));
 
   return result;
 }
+
+/**
+ * gst_audio_clock_get_time:
+ * @clock: a #GstAudioClock
+ *
+ * Report the time as returned by the #GstAudioClockGetTimeFunc without applying
+ * any offsets. 
+ *
+ * Returns: the time as reported by the time function of the audio clock
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstClockTime
+gst_audio_clock_get_time (GstClock * clock)
+{
+  GstAudioClock *aclock;
+  GstClockTime result;
+
+  aclock = GST_AUDIO_CLOCK_CAST (clock);
+
+  result = aclock->func (clock, aclock->user_data);
+  if (result == GST_CLOCK_TIME_NONE) {
+    result = aclock->last_time - aclock->abidata.ABI.time_offset;
+  }
+
+  return result;
+}
+
+/**
+ * gst_audio_clock_adjust:
+ * @clock: a #GstAudioClock
+ * @time: a #GstClockTime
+ *
+ * Adjust @time with the internal offset of the audio clock.
+ *
+ * Returns: @time adjusted with the internal offset.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstClockTime
+gst_audio_clock_adjust (GstClock * clock, GstClockTime time)
+{
+  GstAudioClock *aclock;
+  GstClockTime result;
+
+  aclock = GST_AUDIO_CLOCK_CAST (clock);
+
+  result = time + aclock->abidata.ABI.time_offset;
+
+  return result;
+}
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudioclock.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudioclock.h	Fri Apr 16 15:15:52 2010 +0300
@@ -23,6 +23,7 @@
 #ifndef __GST_AUDIO_CLOCK_H__
 #define __GST_AUDIO_CLOCK_H__
 
+#include <gst/gst.h>
 #include <gst/gstsystemclock.h>
 
 G_BEGIN_DECLS
@@ -37,6 +38,8 @@
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_CLOCK))
 #define GST_IS_AUDIO_CLOCK_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_CLOCK))
+#define GST_AUDIO_CLOCK_CAST(obj) \
+  ((GstAudioClock*)(obj))
 
 typedef struct _GstAudioClock GstAudioClock;
 typedef struct _GstAudioClockClass GstAudioClockClass;
@@ -71,7 +74,13 @@
   GstClockTime last_time;
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  union {
+    struct {
+      GstClockTimeDiff   time_offset;
+    } ABI;
+    /* adding + 0 to mark ABI change to be undone later */
+    gpointer _gst_reserved[GST_PADDING + 0];
+  } abidata;
 };
 
 struct _GstAudioClockClass {
@@ -90,8 +99,24 @@
 IMPORT_C
 #endif
 
-GstClock*       gst_audio_clock_new             (gchar *name, GstAudioClockGetTimeFunc func,
+GstClock*       gst_audio_clock_new             (const gchar *name, GstAudioClockGetTimeFunc func,
                                                  gpointer user_data);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_audio_clock_reset           (GstAudioClock *clock, GstClockTime time);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstClockTime    gst_audio_clock_get_time        (GstClock * clock);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstClockTime    gst_audio_clock_adjust          (GstClock * clock, GstClockTime time);
 
 G_END_DECLS
 
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -32,13 +32,14 @@
  * their base_init function to easily configure the set of caps/formats that
  * the element is able to handle.
  *
- * Derived classes should override the GstAudioFilter::setup() and
- * GstBaseTransform::transform_ip() and/or GstBaseTransform::transform()
+ * Derived classes should override the #GstAudioFilterClass.setup() and
+ * #GstBaseTransformClass.transform_ip() and/or
+ * #GstBaseTransformClass.transform()
  * virtual functions in their class_init function.
  *
- * Since: 0.10.12
+ * Last reviewed on 2007-02-03 (0.10.11.1)
  *
- * Last reviewed on 2007-02-03 (0.10.11.1)
+ * Since: 0.10.12
  */
 
 #ifdef HAVE_CONFIG_H
@@ -168,8 +169,6 @@
   GstAudioFilter *filter;
   gboolean ret = TRUE;
 
-  g_assert (gst_caps_is_equal (incaps, outcaps));
-
   filter = GST_AUDIO_FILTER (btrans);
 
   GST_LOG_OBJECT (filter, "caps: %" GST_PTR_FORMAT, incaps);
@@ -227,16 +226,19 @@
     const GstCaps * allowed_caps)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstPadTemplate *pad_template;
 
   g_return_if_fail (GST_IS_AUDIO_FILTER_CLASS (klass));
   g_return_if_fail (allowed_caps != NULL);
   g_return_if_fail (GST_IS_CAPS (allowed_caps));
 
-  gst_element_class_add_pad_template (element_class,
-      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
-          gst_caps_copy (allowed_caps)));
+  pad_template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+      gst_caps_copy (allowed_caps));
+  gst_element_class_add_pad_template (element_class, pad_template);
+  gst_object_unref (pad_template);
 
-  gst_element_class_add_pad_template (element_class,
-      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
-          gst_caps_copy (allowed_caps)));
+  pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+      gst_caps_copy (allowed_caps));
+  gst_element_class_add_pad_template (element_class, pad_template);
+  gst_object_unref (pad_template);
 }
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -61,6 +61,7 @@
 
 /**
  * GstAudioFilterClass:
+ * @basetransformclass: parent class
  * @setup: virtual function called whenever the format changes
  *
  * In addition to the @setup virtual function, you should also override the
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiofilterexample.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- *
- * 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 was (probably) generated from
- * gstaudiofiltertemplate.c,v 1.14 2007-02-03 23:28:45 tpm Exp 
- * and
- * $Id: make_filter,v 1.3 2004-04-19 22:51:56 ds Exp $
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/audio/audio.h>
-#include <gst/audio/gstaudiofilter.h>
-#include <string.h>
-
-GST_DEBUG_CATEGORY_STATIC (audio_filter_template_debug);
-#define GST_CAT_DEFAULT audio_filter_template_debug
-
-static const GstElementDetails audio_filter_template_details =
-GST_ELEMENT_DETAILS ("Audio filter template",
-    "Filter/Effect/Audio",
-    "Filters audio",
-    "David Schleef <ds@schleef.org>");
-
-typedef struct _GstAudioFilterTemplate GstAudioFilterTemplate;
-typedef struct _GstAudioFilterTemplateClass GstAudioFilterTemplateClass;
-
-#define GST_TYPE_AUDIO_FILTER_TEMPLATE \
-  (gst_audio_filter_template_get_type())
-#define GST_AUDIO_FILTER_TEMPLATE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FILTER_TEMPLATE,GstAudioFilterTemplate))
-#define GST_AUDIO_FILTER_TEMPLATE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_FILTER_TEMPLATE,GstAudioFilterTemplateClass))
-#define GST_IS_AUDIO_FILTER_TEMPLATE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FILTER_TEMPLATE))
-#define GST_IS_AUDIO_FILTER_TEMPLATE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_FILTER_TEMPLATE))
-
-struct _GstAudioFilterTemplate
-{
-  GstAudioFilter audiofilter;
-};
-
-struct _GstAudioFilterTemplateClass
-{
-  GstAudioFilterClass parent_class;
-};
-
-
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0
-      /* FILL ME */
-};
-
-GST_BOILERPLATE (GstAudioFilterTemplate, gst_audio_filter_template,
-    GstAudioFilter, GST_TYPE_AUDIO_FILTER);
-
-static void gst_audio_filter_template_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_audio_filter_template_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static gboolean gst_audio_filter_template_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * spec);
-static GstFlowReturn gst_audio_filter_template_filter (GstBaseTransform * bt,
-    GstBuffer * outbuf, GstBuffer * inbuf);
-static GstFlowReturn
-gst_audio_filter_template_filter_inplace (GstBaseTransform * base_transform,
-    GstBuffer * buf);
-
-#define ALLOWED_CAPS_STRING \
-    GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS
-
-static void
-gst_audio_filter_template_base_init (gpointer g_class)
-{
-  GstAudioFilterTemplateClass *klass = (GstAudioFilterTemplateClass *) g_class;
-  GstAudioFilterClass *audiofilter_class = GST_AUDIO_FILTER_CLASS (g_class);
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *caps;
-
-  gst_element_class_set_details (element_class, &audio_filter_template_details);
-
-  caps = gst_caps_from_string (ALLOWED_CAPS_STRING);
-  gst_audio_filter_class_add_pad_templates (audiofilter_class, caps);
-  gst_caps_unref (caps);
-}
-
-static void
-gst_audio_filter_template_class_init (GstAudioFilterTemplateClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstBaseTransformClass *btrans_class;
-  GstAudioFilterClass *audio_filter_class;
-
-  gobject_class = (GObjectClass *) klass;
-  btrans_class = (GstBaseTransformClass *) klass;
-  audio_filter_class = (GstAudioFilterClass *) klass;
-
-#if 0
-  g_object_class_install_property (gobject_class, ARG_METHOD,
-      g_param_spec_enum ("method", "method", "method",
-          GST_TYPE_AUDIOTEMPLATE_METHOD, GST_AUDIOTEMPLATE_METHOD_1,
-          G_PARAM_READWRITE));
-#endif
-
-  gobject_class->set_property = gst_audio_filter_template_set_property;
-  gobject_class->get_property = gst_audio_filter_template_get_property;
-
-  /* this function will be called whenever the format changes */
-  audio_filter_class->setup = gst_audio_filter_template_setup;
-
-  /* here you set up functions to process data (either in place, or from
-   * one input buffer to another output buffer); only one is required */
-  btrans_class->transform = gst_audio_filter_template_filter;
-  btrans_class->transform_ip = gst_audio_filter_template_filter_inplace;
-}
-
-static void
-gst_audio_filter_template_init (GstAudioFilterTemplate * audio_filter_template,
-    GstAudioFilterTemplateClass * g_class)
-{
-  GST_DEBUG ("init");
-
-  /* do stuff if you need to */
-}
-
-static void
-gst_audio_filter_template_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstAudioFilterTemplate *filter;
-
-  filter = GST_AUDIO_FILTER_TEMPLATE (object);
-
-  GST_DEBUG ("set  property %u", prop_id);
-
-  GST_OBJECT_LOCK (filter);
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-  GST_OBJECT_UNLOCK (filter);
-}
-
-static void
-gst_audio_filter_template_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstAudioFilterTemplate *filter;
-
-  filter = GST_AUDIO_FILTER_TEMPLATE (object);
-
-  GST_DEBUG ("get  property %u", prop_id);
-
-  GST_OBJECT_LOCK (filter);
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-  GST_OBJECT_UNLOCK (filter);
-}
-
-static gboolean
-gst_audio_filter_template_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * spec)
-{
-  GstAudioFilterTemplate *audio_filter_template;
-
-  audio_filter_template = GST_AUDIO_FILTER_TEMPLATE (filter);
-
-  /* if any setup needs to be done, do it here */
-
-  return TRUE;                  /* it's all good */
-}
-
-/* You may choose to implement either a copying filter or an
- * in-place filter (or both).  Implementing only one will give
- * full functionality, however, implementing both will cause
- * audiofilter to use the optimal function in every situation,
- * with a minimum of memory copies. */
-
-static GstFlowReturn
-gst_audio_filter_template_filter (GstBaseTransform * base_transform,
-    GstBuffer * inbuf, GstBuffer * outbuf)
-{
-  GstAudioFilterTemplate *audio_filter_template;
-  GstAudioFilter *audiofilter;
-
-  audiofilter = GST_AUDIO_FILTER (base_transform);
-  audio_filter_template = GST_AUDIO_FILTER_TEMPLATE (base_transform);
-
-  /* do something interesting here.  This simply copies the source
-   * to the destination. */
-
-  memcpy (GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf),
-      GST_BUFFER_SIZE (inbuf));
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_audio_filter_template_filter_inplace (GstBaseTransform * base_transform,
-    GstBuffer * buf)
-{
-  GstAudioFilterTemplate *audio_filter_template;
-  GstAudioFilter *audiofilter;
-
-  audiofilter = GST_AUDIO_FILTER (base_transform);
-  audio_filter_template = GST_AUDIO_FILTER_TEMPLATE (base_transform);
-
-  /* do something interesting here.  This simply copies the source
-   * to the destination. */
-
-  return GST_FLOW_OK;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (audio_filter_template_debug, "audiofilterexample",
-      0, "audiofilterexample");
-
-  return gst_element_register (plugin, "audiofilterexample", GST_RANK_NONE,
-      GST_TYPE_AUDIO_FILTER_TEMPLATE);
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "gstaudio_filter_template",
-    "Audio filter template",
-    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiofiltertemplate.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- *
- * 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 was (probably) generated from
- * $Id: gstaudiofiltertemplate.c,v 1.14 2007-02-03 23:28:45 tpm Exp $
- * and
- * MAKEFILTERVERSION
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/audio/audio.h>
-#include <gst/audio/gstaudiofilter.h>
-#include <string.h>
-
-GST_DEBUG_CATEGORY_STATIC (audio_filter_template_debug);
-#define GST_CAT_DEFAULT audio_filter_template_debug
-
-static const GstElementDetails audio_filter_template_details =
-GST_ELEMENT_DETAILS ("Audio filter template",
-    "Filter/Effect/Audio",
-    "Filters audio",
-    "David Schleef <ds@schleef.org>");
-
-typedef struct _GstAudioFilterTemplate GstAudioFilterTemplate;
-typedef struct _GstAudioFilterTemplateClass GstAudioFilterTemplateClass;
-
-#define GST_TYPE_AUDIO_FILTER_TEMPLATE \
-  (gst_audio_filter_template_get_type())
-#define GST_AUDIO_FILTER_TEMPLATE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FILTER_TEMPLATE,GstAudioFilterTemplate))
-#define GST_AUDIO_FILTER_TEMPLATE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_FILTER_TEMPLATE,GstAudioFilterTemplateClass))
-#define GST_IS_AUDIO_FILTER_TEMPLATE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FILTER_TEMPLATE))
-#define GST_IS_AUDIO_FILTER_TEMPLATE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_FILTER_TEMPLATE))
-
-struct _GstAudioFilterTemplate
-{
-  GstAudioFilter audiofilter;
-};
-
-struct _GstAudioFilterTemplateClass
-{
-  GstAudioFilterClass parent_class;
-};
-
-
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0
-      /* FILL ME */
-};
-
-GST_BOILERPLATE (GstAudioFilterTemplate, gst_audio_filter_template,
-    GstAudioFilter, GST_TYPE_AUDIO_FILTER);
-
-static void gst_audio_filter_template_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_audio_filter_template_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static gboolean gst_audio_filter_template_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * spec);
-static GstFlowReturn gst_audio_filter_template_filter (GstBaseTransform * bt,
-    GstBuffer * outbuf, GstBuffer * inbuf);
-static GstFlowReturn
-gst_audio_filter_template_filter_inplace (GstBaseTransform * base_transform,
-    GstBuffer * buf);
-
-#define ALLOWED_CAPS_STRING \
-    GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS
-
-static void
-gst_audio_filter_template_base_init (gpointer g_class)
-{
-  GstAudioFilterTemplateClass *klass = (GstAudioFilterTemplateClass *) g_class;
-  GstAudioFilterClass *audiofilter_class = GST_AUDIO_FILTER_CLASS (g_class);
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *caps;
-
-  gst_element_class_set_details (element_class, &audio_filter_template_details);
-
-  caps = gst_caps_from_string (ALLOWED_CAPS_STRING);
-  gst_audio_filter_class_add_pad_templates (audiofilter_class, caps);
-  gst_caps_unref (caps);
-}
-
-static void
-gst_audio_filter_template_class_init (GstAudioFilterTemplateClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstBaseTransformClass *btrans_class;
-  GstAudioFilterClass *audio_filter_class;
-
-  gobject_class = (GObjectClass *) klass;
-  btrans_class = (GstBaseTransformClass *) klass;
-  audio_filter_class = (GstAudioFilterClass *) klass;
-
-#if 0
-  g_object_class_install_property (gobject_class, ARG_METHOD,
-      g_param_spec_enum ("method", "method", "method",
-          GST_TYPE_AUDIOTEMPLATE_METHOD, GST_AUDIOTEMPLATE_METHOD_1,
-          G_PARAM_READWRITE));
-#endif
-
-  gobject_class->set_property = gst_audio_filter_template_set_property;
-  gobject_class->get_property = gst_audio_filter_template_get_property;
-
-  /* this function will be called whenever the format changes */
-  audio_filter_class->setup = gst_audio_filter_template_setup;
-
-  /* here you set up functions to process data (either in place, or from
-   * one input buffer to another output buffer); only one is required */
-  btrans_class->transform = gst_audio_filter_template_filter;
-  btrans_class->transform_ip = gst_audio_filter_template_filter_inplace;
-}
-
-static void
-gst_audio_filter_template_init (GstAudioFilterTemplate * audio_filter_template,
-    GstAudioFilterTemplateClass * g_class)
-{
-  GST_DEBUG ("init");
-
-  /* do stuff if you need to */
-}
-
-static void
-gst_audio_filter_template_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstAudioFilterTemplate *filter;
-
-  filter = GST_AUDIO_FILTER_TEMPLATE (object);
-
-  GST_DEBUG ("set  property %u", prop_id);
-
-  GST_OBJECT_LOCK (filter);
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-  GST_OBJECT_UNLOCK (filter);
-}
-
-static void
-gst_audio_filter_template_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstAudioFilterTemplate *filter;
-
-  filter = GST_AUDIO_FILTER_TEMPLATE (object);
-
-  GST_DEBUG ("get  property %u", prop_id);
-
-  GST_OBJECT_LOCK (filter);
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-  GST_OBJECT_UNLOCK (filter);
-}
-
-static gboolean
-gst_audio_filter_template_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * spec)
-{
-  GstAudioFilterTemplate *audio_filter_template;
-
-  audio_filter_template = GST_AUDIO_FILTER_TEMPLATE (filter);
-
-  /* if any setup needs to be done, do it here */
-
-  return TRUE;                  /* it's all good */
-}
-
-/* You may choose to implement either a copying filter or an
- * in-place filter (or both).  Implementing only one will give
- * full functionality, however, implementing both will cause
- * audiofilter to use the optimal function in every situation,
- * with a minimum of memory copies. */
-
-static GstFlowReturn
-gst_audio_filter_template_filter (GstBaseTransform * base_transform,
-    GstBuffer * inbuf, GstBuffer * outbuf)
-{
-  GstAudioFilterTemplate *audio_filter_template;
-  GstAudioFilter *audiofilter;
-
-  audiofilter = GST_AUDIO_FILTER (base_transform);
-  audio_filter_template = GST_AUDIO_FILTER_TEMPLATE (base_transform);
-
-  /* do something interesting here.  This simply copies the source
-   * to the destination. */
-
-  memcpy (GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf),
-      GST_BUFFER_SIZE (inbuf));
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_audio_filter_template_filter_inplace (GstBaseTransform * base_transform,
-    GstBuffer * buf)
-{
-  GstAudioFilterTemplate *audio_filter_template;
-  GstAudioFilter *audiofilter;
-
-  audiofilter = GST_AUDIO_FILTER (base_transform);
-  audio_filter_template = GST_AUDIO_FILTER_TEMPLATE (base_transform);
-
-  /* do something interesting here.  This simply copies the source
-   * to the destination. */
-
-  return GST_FLOW_OK;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (audio_filter_template_debug, "audiofiltertemplate",
-      0, "audiofiltertemplate");
-
-  return gst_element_register (plugin, "audiofiltertemplate", GST_RANK_NONE,
-      GST_TYPE_AUDIO_FILTER_TEMPLATE);
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "gstaudio_filter_template",
-    "Audio filter template",
-    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -71,10 +71,6 @@
 
 #include "gstaudiosink.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
 #define GST_CAT_DEFAULT gst_audio_sink_debug
 
@@ -133,6 +129,8 @@
 static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf);
 static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
 static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
+static gboolean gst_audioringbuffer_activate (GstRingBuffer * buf,
+    gboolean active);
 
 /* ringbuffer abstract base class */
 static GType
@@ -191,6 +189,8 @@
   gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
 
   gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
+  gstringbuffer_class->activate =
+      GST_DEBUG_FUNCPTR (gst_audioringbuffer_activate);
 }
 
 typedef guint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
@@ -207,36 +207,55 @@
   GstAudioSinkClass *csink;
   GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER_CAST (buf);
   WriteFunc writefunc;
+  GstMessage *message;
+  GValue val = { 0 };
 
   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
   csink = GST_AUDIO_SINK_GET_CLASS (sink);
 
   GST_DEBUG_OBJECT (sink, "enter thread");
 
+  GST_OBJECT_LOCK (abuf);
+  GST_DEBUG_OBJECT (sink, "signal wait");
+  GST_AUDIORING_BUFFER_SIGNAL (buf);
+  GST_OBJECT_UNLOCK (abuf);
+
   writefunc = csink->write;
   if (writefunc == NULL)
     goto no_function;
 
+  g_value_init (&val, G_TYPE_POINTER);
+  g_value_set_pointer (&val, sink->thread);
+  message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
+      GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink));
+  gst_message_set_stream_status_object (message, &val);
+  GST_DEBUG_OBJECT (sink, "posting ENTER stream status");
+  gst_element_post_message (GST_ELEMENT_CAST (sink), message);
+
   while (TRUE) {
     gint left, len;
     guint8 *readptr;
     gint readseg;
 
+    /* buffer must be started */
     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
-      gint written = 0;
+      gint written;
 
       left = len;
       do {
-        written = writefunc (sink, readptr + written, left);
+        written = writefunc (sink, readptr, left);
         GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
             written, left, readseg);
         if (written < 0 || written > left) {
+          /* might not be critical, it e.g. happens when aborting playback */
           GST_WARNING_OBJECT (sink,
-              "error writing data (reason: %s), skipping segment",
-              g_strerror (errno));
+              "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)",
+              GST_DEBUG_FUNCPTR_NAME (writefunc),
+              (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
           break;
         }
         left -= written;
+        readptr += written;
       } while (left > 0);
 
       /* clear written samples */
@@ -259,8 +278,9 @@
       GST_OBJECT_UNLOCK (abuf);
     }
   }
-  GST_DEBUG_OBJECT (sink, "exit thread");
 
+  /* Will never be reached */
+  g_assert_not_reached ();
   return;
 
   /* ERROR */
@@ -273,6 +293,11 @@
   {
     GST_OBJECT_UNLOCK (abuf);
     GST_DEBUG_OBJECT (sink, "stop running, exit thread");
+    message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
+        GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink));
+    gst_message_set_stream_status_object (message, &val);
+    GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
+    gst_element_post_message (GST_ELEMENT_CAST (sink), message);
     return;
   }
 }
@@ -358,7 +383,6 @@
 {
   GstAudioSink *sink;
   GstAudioSinkClass *csink;
-  GstAudioRingBuffer *abuf;
   gboolean result = FALSE;
 
   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
@@ -366,26 +390,18 @@
 
   if (csink->prepare)
     result = csink->prepare (sink, spec);
-
   if (!result)
     goto could_not_prepare;
 
-  /* allocate one more segment as we need some headroom */
-  spec->segtotal++;
+  /* set latency to one more segment as we need some headroom */
+  spec->seglatency = spec->segtotal + 1;
 
   buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
   memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
 
-  abuf = GST_AUDIORING_BUFFER_CAST (buf);
-  abuf->running = TRUE;
+  return TRUE;
 
-  sink->thread =
-      g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
-      NULL);
-  GST_AUDIORING_BUFFER_WAIT (buf);
-
-  return result;
-
+  /* ERRORS */
 could_not_prepare:
   {
     GST_DEBUG_OBJECT (sink, "could not prepare device");
@@ -393,6 +409,55 @@
   }
 }
 
+static gboolean
+gst_audioringbuffer_activate (GstRingBuffer * buf, gboolean active)
+{
+  GstAudioSink *sink;
+  GstAudioRingBuffer *abuf;
+  GError *error = NULL;
+
+  sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
+  abuf = GST_AUDIORING_BUFFER_CAST (buf);
+
+  if (active) {
+    abuf->running = TRUE;
+
+    GST_DEBUG_OBJECT (sink, "starting thread");
+    sink->thread =
+        g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
+        &error);
+    if (!sink->thread || error != NULL)
+      goto thread_failed;
+
+    GST_DEBUG_OBJECT (sink, "waiting for thread");
+    /* the object lock is taken */
+    GST_AUDIORING_BUFFER_WAIT (buf);
+    GST_DEBUG_OBJECT (sink, "thread is started");
+  } else {
+    abuf->running = FALSE;
+    GST_DEBUG_OBJECT (sink, "signal wait");
+    GST_AUDIORING_BUFFER_SIGNAL (buf);
+
+    GST_OBJECT_UNLOCK (buf);
+
+    /* join the thread */
+    g_thread_join (sink->thread);
+
+    GST_OBJECT_LOCK (buf);
+  }
+  return TRUE;
+
+  /* ERRORS */
+thread_failed:
+  {
+    if (error)
+      GST_ERROR_OBJECT (sink, "could not create thread %s", error->message);
+    else
+      GST_ERROR_OBJECT (sink, "could not create thread for unknown reason");
+    return FALSE;
+  }
+}
+
 /* function is called with LOCK */
 static gboolean
 gst_audioringbuffer_release (GstRingBuffer * buf)
@@ -406,16 +471,6 @@
   csink = GST_AUDIO_SINK_GET_CLASS (sink);
   abuf = GST_AUDIORING_BUFFER_CAST (buf);
 
-  abuf->running = FALSE;
-  GST_DEBUG_OBJECT (sink, "signal wait");
-  GST_AUDIORING_BUFFER_SIGNAL (buf);
-  GST_OBJECT_UNLOCK (buf);
-
-  /* join the thread */
-  g_thread_join (sink->thread);
-
-  GST_OBJECT_LOCK (buf);
-
   /* free the buffer */
   gst_buffer_unref (buf->data);
   buf->data = NULL;
@@ -426,6 +481,8 @@
   if (!result)
     goto could_not_unprepare;
 
+  GST_DEBUG_OBJECT (sink, "unprepared");
+
   return result;
 
 could_not_unprepare:
@@ -484,12 +541,13 @@
     csink->reset (sink);
     GST_DEBUG_OBJECT (sink, "reset done");
   }
-
+#if 0
   if (abuf->running) {
     GST_DEBUG_OBJECT (sink, "stop, waiting...");
     GST_AUDIORING_BUFFER_WAIT (buf);
     GST_DEBUG_OBJECT (sink, "stopped");
   }
+#endif
 
   return TRUE;
 }
@@ -551,6 +609,8 @@
 
   gstbaseaudiosink_class->create_ringbuffer =
       GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
+
+  g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
 }
 
 static void
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -83,6 +83,8 @@
   /* close the device */
   gboolean (*close)     (GstAudioSink *sink);
   /* write samples to the device */
+  /* FIXME 0.11: change return value to gint, as most implementation use that
+   * already anyway */
   guint    (*write)     (GstAudioSink *sink, gpointer data, guint length);
   /* get number of samples queued in the device */
   guint    (*delay)     (GstAudioSink *sink);
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -71,10 +71,6 @@
 
 #include "gstaudiosrc.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_audio_src_debug);
 #define GST_CAT_DEFAULT gst_audio_src_debug
 
@@ -203,6 +199,8 @@
   GstAudioSrcClass *csrc;
   GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER (buf);
   ReadFunc readfunc;
+  GstMessage *message;
+  GValue val = { 0 };
 
   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
   csrc = GST_AUDIO_SRC_GET_CLASS (src);
@@ -213,26 +211,35 @@
   if (readfunc == NULL)
     goto no_function;
 
+  g_value_init (&val, G_TYPE_POINTER);
+  g_value_set_pointer (&val, src->thread);
+  message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
+      GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (src));
+  gst_message_set_stream_status_object (message, &val);
+  GST_DEBUG_OBJECT (src, "posting ENTER stream status");
+  gst_element_post_message (GST_ELEMENT_CAST (src), message);
+
   while (TRUE) {
     gint left, len;
     guint8 *readptr;
     gint readseg;
 
     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
-      gint read = 0;
+      gint read;
 
       left = len;
       do {
-        read = readfunc (src, readptr + read, left);
+        read = readfunc (src, readptr, left);
         GST_LOG_OBJECT (src, "transfered %d bytes of %d to segment %d", read,
             left, readseg);
         if (read < 0 || read > left) {
           GST_WARNING_OBJECT (src,
-              "error reading data (reason: %s), skipping segment",
+              "error reading data %d (reason: %s), skipping segment", read,
               g_strerror (errno));
           break;
         }
         left -= read;
+        readptr += read;
       } while (left > 0);
 
       /* we read one segment */
@@ -252,8 +259,9 @@
       GST_OBJECT_UNLOCK (abuf);
     }
   }
-  GST_DEBUG_OBJECT (src, "exit thread");
 
+  /* Will never be reached */
+  g_assert_not_reached ();
   return;
 
   /* ERROR */
@@ -266,6 +274,11 @@
   {
     GST_OBJECT_UNLOCK (abuf);
     GST_DEBUG ("stop running, exit thread");
+    message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
+        GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (src));
+    gst_message_set_stream_status_object (message, &val);
+    GST_DEBUG_OBJECT (src, "posting LEAVE stream status");
+    gst_element_post_message (GST_ELEMENT_CAST (src), message);
     return;
   }
 }
@@ -364,9 +377,6 @@
   if (!result)
     goto could_not_open;
 
-  /* allocate one more segment as we need some headroom */
-  spec->segtotal++;
-
   buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
   memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
 
@@ -446,10 +456,11 @@
     csrc->reset (src);
     GST_DEBUG ("reset done");
   }
-
+#if 0
   GST_DEBUG ("stop, waiting...");
   GST_AUDIORING_BUFFER_WAIT (buf);
   GST_DEBUG ("stoped");
+#endif
 
   return TRUE;
 }
@@ -512,6 +523,8 @@
 
   gstbaseaudiosrc_class->create_ringbuffer =
       GST_DEBUG_FUNCPTR (gst_audio_src_create_ringbuffer);
+
+  g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
 }
 
 static void
--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -20,21 +20,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-/* a base class for simple audio srcs.
- *
- * This base class only requires subclasses to implement a set
- * of simple functions.
- *
- * - open: open the device with the specified caps
- * - read: read samples to the audio device
- * - close: close the device
- * - delay: the number of samples queued in the device
- * - reset: unblock a read to the device and reset.
- *
- * All scheduling of samples and timestamps is done in this
- * base class.
- */
-
 #ifndef __GST_AUDIO_SRC_H__
 #define __GST_AUDIO_SRC_H__
 
@@ -53,6 +38,12 @@
 typedef struct _GstAudioSrc GstAudioSrc;
 typedef struct _GstAudioSrcClass GstAudioSrcClass;
 
+/**
+ * GstAudioSrc:
+ * @element: parent class
+ *
+ * Base class for simple audio sources.
+ */
 struct _GstAudioSrc {
   GstBaseAudioSrc        element;
 
@@ -63,6 +54,20 @@
   gpointer _gst_reserved[GST_PADDING];
 };
 
+/**
+ * GstAudioSrcClass:
+ * @parent_class: the parent class.
+ * @open: open the device with the specified caps
+ * @prepare: configure device with format
+ * @unprepare: undo the configuration
+ * @close: close the device
+ * @read: read samples to the audio device
+ * @delay: the number of samples queued in the device
+ * @reset: unblock a read to the device and reset.
+ *
+ * #GstAudioSrc class. Override the vmethod to implement
+ * functionality.
+ */
 struct _GstAudioSrcClass {
   GstBaseAudioSrcClass parent_class;
 
--- a/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -36,10 +36,6 @@
 
 #include "gstbaseaudiosink.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_sink_debug);
 #define GST_CAT_DEFAULT gst_base_audio_sink_debug
 
@@ -56,6 +52,10 @@
   GstClockTimeDiff avg_skew;
   /* the number of samples we aligned last time */
   gint64 last_align;
+
+  gboolean sync_latency;
+
+  GstClockTime eos_time;
 };
 
 /* BaseAudioSink signals and args */
@@ -80,19 +80,25 @@
 #define DEFAULT_PROVIDE_CLOCK   TRUE
 #define DEFAULT_SLAVE_METHOD    GST_BASE_AUDIO_SINK_SLAVE_SKEW
 
+/* FIXME, enable pull mode when clock slaving and trick modes are figured out */
+#define DEFAULT_CAN_ACTIVATE_PULL FALSE
+
 enum
 {
   PROP_0,
   PROP_BUFFER_TIME,
   PROP_LATENCY_TIME,
   PROP_PROVIDE_CLOCK,
-  PROP_SLAVE_METHOD
+  PROP_SLAVE_METHOD,
+  PROP_CAN_ACTIVATE_PULL
 };
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-#define GST_TYPE_SLAVE_METHOD (slave_method_get_type ())
 
-static GType
-slave_method_get_type (void)
+GType
+gst_base_audio_sink_slave_method_get_type (void)
 {
   static GType slave_method_type = 0;
   static const GEnumValue slave_method[] = {
@@ -150,6 +156,9 @@
     GstCaps * caps);
 static void gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
 
+static gboolean gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query);
+
+
 /* static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 }; */
 
 static void
@@ -179,22 +188,30 @@
   g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
       g_param_spec_int64 ("buffer-time", "Buffer Time",
           "Size of audio buffer in microseconds", 1,
-          G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_BUFFER_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
       g_param_spec_int64 ("latency-time", "Latency Time",
           "Audio latency in microseconds", 1,
-          G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_LATENCY_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
       g_param_spec_boolean ("provide-clock", "Provide Clock",
           "Provide a clock to be used as the global pipeline clock",
-          DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE));
+          DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
       g_param_spec_enum ("slave-method", "Slave Method",
           "Algorithm to use to match the rate of the masterclock",
-          GST_TYPE_SLAVE_METHOD, DEFAULT_SLAVE_METHOD, G_PARAM_READWRITE));
+          GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
+      g_param_spec_boolean ("can-activate-pull", "Allow Pull Scheduling",
+          "Allow pull-based scheduling", DEFAULT_CAN_ACTIVATE_PULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
@@ -217,6 +234,7 @@
   /* ref class from a thread-safe context to work around missing bit of
    * thread-safety in GObject */
   g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
+  g_type_class_ref (GST_TYPE_RING_BUFFER);
 }
 
 static void
@@ -234,9 +252,11 @@
       (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
 
   GST_BASE_SINK (baseaudiosink)->can_activate_push = TRUE;
-  /* FIXME, enable pull mode when segments, latency, state changes, negotiation
-   * and clock slaving are figured out */
-  GST_BASE_SINK (baseaudiosink)->can_activate_pull = FALSE;
+  GST_BASE_SINK (baseaudiosink)->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
+
+  /* install some custom pad_query functions */
+  gst_pad_set_query_function (GST_BASE_SINK_PAD (baseaudiosink),
+      GST_DEBUG_FUNCPTR (gst_base_audio_sink_query_pad));
 }
 
 static void
@@ -258,6 +278,7 @@
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
+
 static GstClock *
 gst_base_audio_sink_provide_clock (GstElement * elem)
 {
@@ -297,11 +318,47 @@
 }
 
 static gboolean
+gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query)
+{
+  gboolean res = FALSE;
+  GstBaseAudioSink *basesink;
+
+  basesink = GST_BASE_AUDIO_SINK (gst_pad_get_parent (pad));
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CONVERT:
+    {
+      GstFormat src_fmt, dest_fmt;
+      gint64 src_val, dest_val;
+
+      GST_LOG_OBJECT (pad, "query convert");
+
+      if (basesink->ringbuffer) {
+        gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
+        res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val,
+            dest_fmt, &dest_val);
+        if (res) {
+          gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
+        }
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  gst_object_unref (basesink);
+
+  return res;
+}
+
+static gboolean
 gst_base_audio_sink_query (GstElement * element, GstQuery * query)
 {
   gboolean res = FALSE;
+  GstBaseAudioSink *basesink;
 
-  GstBaseAudioSink *basesink = GST_BASE_AUDIO_SINK (element);
+  basesink = GST_BASE_AUDIO_SINK (element);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_LATENCY:
@@ -333,7 +390,7 @@
           basesink->priv->us_latency = min_l;
 
           min_latency =
-              gst_util_uint64_scale_int (spec->segtotal * spec->segsize,
+              gst_util_uint64_scale_int (spec->seglatency * spec->segsize,
               GST_SECOND, spec->rate * spec->bytes_per_sample);
 
           /* we cannot go lower than the buffer size and the min peer latency */
@@ -349,13 +406,30 @@
         } else {
           GST_DEBUG_OBJECT (basesink,
               "peer or we are not live, don't care about latency");
-          min_latency = 0;
-          max_latency = -1;
+          min_latency = min_l;
+          max_latency = max_l;
         }
         gst_query_set_latency (query, live, min_latency, max_latency);
       }
       break;
     }
+    case GST_QUERY_CONVERT:
+    {
+      GstFormat src_fmt, dest_fmt;
+      gint64 src_val, dest_val;
+
+      GST_LOG_OBJECT (basesink, "query convert");
+
+      if (basesink->ringbuffer) {
+        gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
+        res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val,
+            dest_fmt, &dest_val);
+        if (res) {
+          gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
+        }
+      }
+      break;
+    }
     default:
       res = GST_ELEMENT_CLASS (parent_class)->query (element, query);
       break;
@@ -371,7 +445,7 @@
 {
   guint64 raw, samples;
   guint delay;
-  GstClockTime result, us_latency;
+  GstClockTime result;
 
   if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0)
     return GST_CLOCK_TIME_NONE;
@@ -391,15 +465,10 @@
   result = gst_util_uint64_scale_int (samples, GST_SECOND,
       sink->ringbuffer->spec.rate);
 
-  /* latency before starting the clock */
-  us_latency = sink->priv->us_latency;
-
-  result += us_latency;
-
   GST_DEBUG_OBJECT (sink,
-      "processed samples: raw %llu, delay %u, real %llu, time %"
-      GST_TIME_FORMAT ", upstream latency %" GST_TIME_FORMAT, raw, delay,
-      samples, GST_TIME_ARGS (result), GST_TIME_ARGS (us_latency));
+      "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"
+      G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
+      raw, delay, samples, GST_TIME_ARGS (result));
 
   return result;
 }
@@ -532,6 +601,9 @@
     case PROP_SLAVE_METHOD:
       gst_base_audio_sink_set_slave_method (sink, g_value_get_enum (value));
       break;
+    case PROP_CAN_ACTIVATE_PULL:
+      GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -559,6 +631,9 @@
     case PROP_SLAVE_METHOD:
       g_value_set_enum (value, gst_base_audio_sink_get_slave_method (sink));
       break;
+    case PROP_CAN_ACTIVATE_PULL:
+      g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -579,6 +654,8 @@
   GST_DEBUG_OBJECT (sink, "release old ringbuffer");
 
   /* release old ringbuffer */
+  gst_ring_buffer_pause (sink->ringbuffer);
+  gst_ring_buffer_activate (sink->ringbuffer, FALSE);
   gst_ring_buffer_release (sink->ringbuffer);
 
   GST_DEBUG_OBJECT (sink, "parse caps");
@@ -592,11 +669,15 @@
 
   gst_ring_buffer_debug_spec_buff (spec);
 
-  GST_DEBUG_OBJECT (sink, "acquire new ringbuffer");
-
+  GST_DEBUG_OBJECT (sink, "acquire ringbuffer");
   if (!gst_ring_buffer_acquire (sink->ringbuffer, spec))
     goto acquire_error;
 
+  if (bsink->pad_mode == GST_ACTIVATE_PUSH) {
+    GST_DEBUG_OBJECT (sink, "activate ringbuffer");
+    gst_ring_buffer_activate (sink->ringbuffer, TRUE);
+  }
+
   /* calculate actual latency and buffer times. 
    * FIXME: In 0.11, store the latency_time internally in ns */
   spec->latency_time = gst_util_uint64_scale (spec->segsize,
@@ -663,8 +744,6 @@
 static gboolean
 gst_base_audio_sink_drain (GstBaseAudioSink * sink)
 {
-  GstClockTime base_time;
-
   if (!sink->ringbuffer)
     return TRUE;
   if (!sink->ringbuffer->spec.rate)
@@ -676,35 +755,16 @@
   if (gst_ring_buffer_is_acquired (sink->ringbuffer))
     gst_ring_buffer_start (sink->ringbuffer);
 
-  if (sink->next_sample != -1) {
-    GstClockTime time;
-
-    /* convert next expected sample to time */
-    time =
-        gst_util_uint64_scale_int (sink->next_sample, GST_SECOND,
-        sink->ringbuffer->spec.rate);
-
+  if (sink->priv->eos_time != -1) {
     GST_DEBUG_OBJECT (sink,
-        "last sample %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
-        sink->next_sample, GST_TIME_ARGS (time));
-
-    /* our time already includes the base_time, _wait_eos() wants a running_time
-     * so we have to subtract the base_time again here. FIXME, store an
-     * unadjusted EOS time so that we don't have to do this. */
-    GST_OBJECT_LOCK (sink);
-    base_time = GST_ELEMENT_CAST (sink)->base_time;
-    GST_OBJECT_UNLOCK (sink);
-
-    if (time > base_time)
-      time -= base_time;
-    else
-      time = 0;
+        "last sample time %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (sink->priv->eos_time));
 
     /* wait for the EOS time to be reached, this is the time when the last
      * sample is played. */
-    gst_base_sink_wait_eos (GST_BASE_SINK (sink), time, NULL);
+    gst_base_sink_wait_eos (GST_BASE_SINK (sink), sink->priv->eos_time, NULL);
 
-    sink->next_sample = -1;
+    GST_DEBUG_OBJECT (sink, "drained audio");
   }
   return TRUE;
 }
@@ -723,6 +783,7 @@
       /* always resync on sample after a flush */
       sink->priv->avg_skew = -1;
       sink->next_sample = -1;
+      sink->priv->eos_time = -1;
       if (sink->ringbuffer)
         gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
       break;
@@ -803,8 +864,7 @@
 
 static GstClockTime
 clock_convert_external (GstClockTime external, GstClockTime cinternal,
-    GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom,
-    GstClockTime us_latency)
+    GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom)
 {
   /* adjust for rate and speed */
   if (external >= cexternal) {
@@ -812,19 +872,13 @@
         gst_util_uint64_scale (external - cexternal, crate_denom, crate_num);
     external += cinternal;
   } else {
-    external = gst_util_uint64_scale (cexternal - external,
-        crate_denom, crate_num);
+    external =
+        gst_util_uint64_scale (cexternal - external, crate_denom, crate_num);
     if (cinternal > external)
       external = cinternal - external;
     else
       external = 0;
   }
-  /* adjust for offset when slaving started */
-  if (external > us_latency)
-    external -= us_latency;
-  else
-    external = 0;
-
   return external;
 }
 
@@ -838,6 +892,22 @@
   GstClockTime cinternal, cexternal;
   GstClockTime crate_num, crate_denom;
 
+  /* FIXME, we can sample and add observations here or use the timeouts on the
+   * clock. No idea which one is better or more stable. The timeout seems more
+   * arbitrary but this one seems more demanding and does not work when there is
+   * no data comming in to the sink. */
+#if 0
+  GstClockTime etime, itime;
+  gdouble r_squared;
+
+  /* sample clocks and figure out clock skew */
+  etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink));
+  itime = gst_audio_clock_get_time (sink->provided_clock);
+
+  /* add new observation */
+  gst_clock_add_observation (sink->provided_clock, itime, etime, &r_squared);
+#endif
+
   /* get calibration parameters to compensate for speed and offset differences
    * when we are slaved */
   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
@@ -854,9 +924,9 @@
 
   /* bring external time to internal time */
   render_start = clock_convert_external (render_start, cinternal, cexternal,
-      crate_num, crate_denom, sink->priv->us_latency);
+      crate_num, crate_denom);
   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
-      crate_num, crate_denom, sink->priv->us_latency);
+      crate_num, crate_denom);
 
   GST_DEBUG_OBJECT (sink,
       "after slaving: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
@@ -885,11 +955,21 @@
 
   /* sample clocks and figure out clock skew */
   etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink));
-  itime = gst_clock_get_internal_time (sink->provided_clock);
+  itime = gst_audio_clock_get_time (sink->provided_clock);
+
+  GST_DEBUG_OBJECT (sink,
+      "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT
+      " cinternal %" GST_TIME_FORMAT " cexternal %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (itime), GST_TIME_ARGS (etime),
+      GST_TIME_ARGS (cinternal), GST_TIME_ARGS (cexternal));
 
-  etime -= cexternal;
-  itime -= cinternal;
+  /* make sure we never go below 0 */
+  etime = etime > cexternal ? etime - cexternal : 0;
+  itime = itime > cinternal ? itime - cinternal : 0;
 
+  /* do itime - etime.
+   * positive value means external clock goes slower
+   * negative value means external clock goes faster */
   skew = GST_CLOCK_DIFF (etime, itime);
   if (sink->priv->avg_skew == -1) {
     /* first observation */
@@ -913,7 +993,7 @@
     GST_WARNING_OBJECT (sink,
         "correct clock skew %" G_GINT64_FORMAT " > %" G_GINT64_FORMAT,
         sink->priv->avg_skew, segtime2);
-    cinternal += segtime;
+    cexternal = cexternal > segtime ? cexternal - segtime : 0;
     sink->priv->avg_skew -= segtime;
 
     segsamples =
@@ -960,9 +1040,9 @@
 
   /* convert, ignoring speed */
   render_start = clock_convert_external (render_start, cinternal, cexternal,
-      crate_num, crate_denom, sink->priv->us_latency);
+      crate_num, crate_denom);
   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
-      crate_num, crate_denom, sink->priv->us_latency);
+      crate_num, crate_denom);
 
   *srender_start = render_start;
   *srender_stop = render_stop;
@@ -982,9 +1062,9 @@
 
   /* convert, ignoring speed */
   render_start = clock_convert_external (render_start, cinternal, cexternal,
-      crate_num, crate_denom, sink->priv->us_latency);
+      crate_num, crate_denom);
   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
-      crate_num, crate_denom, sink->priv->us_latency);
+      crate_num, crate_denom);
 
   *srender_start = render_start;
   *srender_stop = render_stop;
@@ -1015,11 +1095,137 @@
   }
 }
 
+/* must be called with LOCK */
+static GstFlowReturn
+gst_base_audio_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj)
+{
+  GstClock *clock;
+  GstClockReturn status;
+  GstClockTime time;
+  GstFlowReturn ret;
+  GstBaseAudioSink *sink;
+  GstClockTime itime, etime;
+  GstClockTime rate_num, rate_denom;
+  GstClockTimeDiff jitter;
+
+  sink = GST_BASE_AUDIO_SINK (bsink);
+
+  clock = GST_ELEMENT_CLOCK (sink);
+  if (G_UNLIKELY (clock == NULL))
+    goto no_clock;
+
+  /* we provided the global clock, don't need to do anything special */
+  if (clock == sink->provided_clock)
+    goto no_slaving;
+
+  GST_OBJECT_UNLOCK (sink);
+
+  do {
+    GST_DEBUG_OBJECT (sink, "checking preroll");
+
+    ret = gst_base_sink_do_preroll (bsink, obj);
+    if (ret != GST_FLOW_OK)
+      goto flushing;
+
+    GST_OBJECT_LOCK (sink);
+    time = sink->priv->us_latency;
+    GST_OBJECT_UNLOCK (sink);
+
+    /* preroll done, we can sync since we are in PLAYING now. */
+    GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %"
+        GST_TIME_FORMAT, GST_TIME_ARGS (time));
+
+    /* wait for the clock, this can be interrupted because we got shut down or 
+     * we PAUSED. */
+    status = gst_base_sink_wait_clock (bsink, time, &jitter);
+
+    GST_DEBUG_OBJECT (sink, "clock returned %d %" GST_TIME_FORMAT, status,
+        GST_TIME_ARGS (jitter));
+
+    /* invalid time, no clock or sync disabled, just continue then */
+    if (status == GST_CLOCK_BADTIME)
+      break;
+
+    /* waiting could have been interrupted and we can be flushing now */
+    if (G_UNLIKELY (bsink->flushing))
+      goto flushing;
+
+    /* retry if we got unscheduled, which means we did not reach the timeout
+     * yet. if some other error occures, we continue. */
+  } while (status == GST_CLOCK_UNSCHEDULED);
+
+  GST_OBJECT_LOCK (sink);
+  GST_DEBUG_OBJECT (sink, "latency synced");
+
+  /* when we prerolled in time, we can accurately set the calibration,
+   * our internal clock should exactly have been the latency (== the running
+   * time of the external clock) */
+  etime = GST_ELEMENT_CAST (sink)->base_time + time;
+  itime = gst_audio_clock_get_time (sink->provided_clock);
+
+  if (status == GST_CLOCK_EARLY) {
+    /* when we prerolled late, we have to take into account the lateness */
+    GST_DEBUG_OBJECT (sink, "late preroll, adding jitter");
+    etime += jitter;
+  }
+
+  /* start ringbuffer so we can start slaving right away when we need to */
+  gst_ring_buffer_start (sink->ringbuffer);
+
+  GST_DEBUG_OBJECT (sink,
+      "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (itime), GST_TIME_ARGS (etime));
+
+  /* copy the original calibrated rate but update the internal and external
+   * times. */
+  gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num,
+      &rate_denom);
+  gst_clock_set_calibration (sink->provided_clock, itime, etime,
+      rate_num, rate_denom);
+
+  switch (sink->priv->slave_method) {
+    case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE:
+      /* only set as master when we are resampling */
+      GST_DEBUG_OBJECT (sink, "Setting clock as master");
+      gst_clock_set_master (sink->provided_clock, clock);
+      break;
+    case GST_BASE_AUDIO_SINK_SLAVE_SKEW:
+    case GST_BASE_AUDIO_SINK_SLAVE_NONE:
+    default:
+      break;
+  }
+
+  sink->priv->avg_skew = -1;
+  sink->next_sample = -1;
+  sink->priv->eos_time = -1;
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+no_clock:
+  {
+    GST_DEBUG_OBJECT (sink, "we have no clock");
+    return GST_FLOW_OK;
+  }
+no_slaving:
+  {
+    GST_DEBUG_OBJECT (sink, "we are not slaved");
+    return GST_FLOW_OK;
+  }
+flushing:
+  {
+    GST_DEBUG_OBJECT (sink, "we are flushing");
+    GST_OBJECT_LOCK (sink);
+    return GST_FLOW_WRONG_STATE;
+  }
+}
+
 static GstFlowReturn
 gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
 {
   guint64 in_offset;
   GstClockTime time, stop, render_start, render_stop, sample_offset;
+  GstClockTimeDiff sync_offset, ts_offset;
   GstBaseAudioSink *sink;
   GstRingBuffer *ringbuf;
   gint64 diff, align, ctime, cstop;
@@ -1029,9 +1235,11 @@
   gint bps;
   gint accum;
   gint out_samples;
-  GstClockTime base_time = GST_CLOCK_TIME_NONE, latency;
+  GstClockTime base_time, render_delay, latency;
   GstClock *clock;
   gboolean sync, slaved, align_next;
+  GstFlowReturn ret;
+  GstSegment clip_seg;
 
   sink = GST_BASE_AUDIO_SINK (bsink);
 
@@ -1041,6 +1249,22 @@
   if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf)))
     goto wrong_state;
 
+  /* Wait for upstream latency before starting the ringbuffer, we do this so
+   * that we can align the first sample of the ringbuffer to the base_time +
+   * latency. */
+  GST_OBJECT_LOCK (sink);
+  base_time = GST_ELEMENT_CAST (sink)->base_time;
+  if (G_UNLIKELY (sink->priv->sync_latency)) {
+    ret = gst_base_audio_sink_sync_latency (bsink, GST_MINI_OBJECT_CAST (buf));
+    GST_OBJECT_UNLOCK (sink);
+    if (G_UNLIKELY (ret != GST_FLOW_OK))
+      goto sync_latency_failed;
+    /* only do this once until we are set back to PLAYING */
+    sink->priv->sync_latency = FALSE;
+  } else {
+    GST_OBJECT_UNLOCK (sink);
+  }
+
   bps = ringbuf->spec.bytes_per_sample;
 
   size = GST_BUFFER_SIZE (buf);
@@ -1052,12 +1276,10 @@
 
   in_offset = GST_BUFFER_OFFSET (buf);
   time = GST_BUFFER_TIMESTAMP (buf);
-  stop = time + gst_util_uint64_scale_int (samples, GST_SECOND,
-      ringbuf->spec.rate);
 
   GST_DEBUG_OBJECT (sink,
-      "time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT
-      ", samples %u", GST_TIME_ARGS (time), in_offset,
+      "time %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT ", start %"
+      GST_TIME_FORMAT ", samples %u", GST_TIME_ARGS (time), in_offset,
       GST_TIME_ARGS (bsink->segment.start), samples);
 
   data = GST_BUFFER_DATA (buf);
@@ -1070,16 +1292,48 @@
     GST_DEBUG_OBJECT (sink,
         "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT,
         GST_BUFFER_SIZE (buf), render_start);
+    /* we don't have a start so we don't know stop either */
+    stop = -1;
     goto no_sync;
   }
 
+  /* let's calc stop based on the number of samples in the buffer instead
+   * of trusting the DURATION */
+  stop = time + gst_util_uint64_scale_int (samples, GST_SECOND,
+      ringbuf->spec.rate);
+
+  /* prepare the clipping segment. Since we will be subtracting ts-offset and
+   * device-delay later we scale the start and stop with those values so that we
+   * can correctly clip them */
+  clip_seg.format = GST_FORMAT_TIME;
+  clip_seg.start = bsink->segment.start;
+  clip_seg.stop = bsink->segment.stop;
+  clip_seg.duration = -1;
+
+  /* the sync offset is the combination of ts-offset and device-delay */
+  latency = gst_base_sink_get_latency (bsink);
+  ts_offset = gst_base_sink_get_ts_offset (bsink);
+  render_delay = gst_base_sink_get_render_delay (bsink);
+  sync_offset = ts_offset - render_delay + latency;
+
+  GST_DEBUG_OBJECT (sink,
+      "sync-offset %" G_GINT64_FORMAT ", render-delay %" GST_TIME_FORMAT
+      ", ts-offset %" G_GINT64_FORMAT, sync_offset,
+      GST_TIME_ARGS (render_delay), ts_offset);
+
+  /* compensate for ts-offset and device-delay when negative we need to
+   * clip. */
+  if (sync_offset < 0) {
+    clip_seg.start += -sync_offset;
+    if (clip_seg.stop != -1)
+      clip_seg.stop += -sync_offset;
+  }
+
   /* samples should be rendered based on their timestamp. All samples
    * arriving before the segment.start or after segment.stop are to be 
    * thrown away. All samples should also be clipped to the segment 
    * boundaries */
-  /* let's calc stop based on the number of samples in the buffer instead
-   * of trusting the DURATION */
-  if (!gst_segment_clip (&bsink->segment, GST_FORMAT_TIME, time, stop, &ctime,
+  if (!gst_segment_clip (&clip_seg, GST_FORMAT_TIME, time, stop, &ctime,
           &cstop))
     goto out_of_segment;
 
@@ -1129,32 +1383,42 @@
       "running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
 
-  base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bsink));
+  /* store the time of the last sample, we'll use this to perform sync on the
+   * last sample when draining the buffer */
+  if (bsink->segment.rate >= 0.0) {
+    sink->priv->eos_time = render_stop;
+  } else {
+    sink->priv->eos_time = render_start;
+  }
 
-  GST_DEBUG_OBJECT (sink, "base_time %" GST_TIME_FORMAT,
+  /* compensate for ts-offset and delay we know this will not underflow because we
+   * clipped above. */
+  GST_DEBUG_OBJECT (sink,
+      "compensating for sync-offset %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (sync_offset));
+  render_start += sync_offset;
+  render_stop += sync_offset;
+
+  GST_DEBUG_OBJECT (sink, "adding base_time %" GST_TIME_FORMAT,
       GST_TIME_ARGS (base_time));
 
   /* add base time to sync against the clock */
   render_start += base_time;
   render_stop += base_time;
 
-  /* compensate for latency */
-  latency = gst_base_sink_get_latency (bsink);
   GST_DEBUG_OBJECT (sink,
-      "compensating for latency %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
-
-  /* add latency to get the timestamp to sync against the pipeline clock */
-  render_start += latency;
-  render_stop += latency;
-
-  GST_DEBUG_OBJECT (sink,
-      "after latency: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
+      "after compensation: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
 
   if ((slaved = clock != sink->provided_clock)) {
     /* handle clock slaving */
     gst_base_audio_sink_handle_slaving (sink, render_start, render_stop,
         &render_start, &render_stop);
+  } else {
+    /* no slaving needed but we need to adapt to the clock calibration
+     * parameters */
+    gst_base_audio_sink_none_slaving (sink, render_start, render_stop,
+        &render_start, &render_stop);
   }
 
   /* and bring the time to the rate corrected offset in the buffer */
@@ -1163,26 +1427,34 @@
   render_stop = gst_util_uint64_scale_int (render_stop,
       ringbuf->spec.rate, GST_SECOND);
 
+  /* positive playback rate, first sample is render_start, negative rate, first
+   * sample is render_stop. When no rate conversion is active, render exactly
+   * the amount of input samples to avoid aligning to rounding errors. */
+  if (bsink->segment.rate >= 0.0) {
+    sample_offset = render_start;
+    if (bsink->segment.rate == 1.0)
+      render_stop = sample_offset + samples;
+  } else {
+    sample_offset = render_stop;
+    if (bsink->segment.rate == -1.0)
+      render_start = sample_offset + samples;
+  }
+
   /* always resync after a discont */
   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) {
     GST_DEBUG_OBJECT (sink, "resync after discont");
     goto no_align;
   }
 
+  /* resync when we don't know what to align the sample with */
   if (G_UNLIKELY (sink->next_sample == -1)) {
     GST_DEBUG_OBJECT (sink,
         "no align possible: no previous sample position known");
     goto no_align;
   }
 
-  /* positive playback rate, first sample is render_start, negative rate, first
-   * sample is render_stop */
-  if (bsink->segment.rate >= 1.0)
-    sample_offset = render_start;
-  else
-    sample_offset = render_stop;
-
-  /* now try to align the sample to the previous one */
+  /* now try to align the sample to the previous one, first see how big the
+   * difference is. */
   if (sample_offset >= sink->next_sample)
     diff = sample_offset - sink->next_sample;
   else
@@ -1228,7 +1500,7 @@
 
 no_sync:
   /* we render the first or last sample first, depending on the rate */
-  if (bsink->segment.rate >= 1.0)
+  if (bsink->segment.rate >= 0.0)
     sample_offset = render_start;
   else
     sample_offset = render_stop;
@@ -1250,13 +1522,21 @@
       break;
 
     /* else something interrupted us and we wait for preroll. */
-    if (gst_base_sink_wait_preroll (bsink) != GST_FLOW_OK)
+    if ((ret = gst_base_sink_wait_preroll (bsink)) != GST_FLOW_OK)
       goto stopping;
 
     /* if we got interrupted, we cannot assume that the next sample should
      * be aligned to this one */
     align_next = FALSE;
 
+    /* update the output samples. FIXME, this will just skip them when pausing
+     * during trick mode */
+    if (out_samples > written) {
+      out_samples -= written;
+      accum = 0;
+    } else
+      break;
+
     samples -= written;
     data += written * bps;
   } while (TRUE);
@@ -1302,8 +1582,14 @@
   }
 stopping:
   {
-    GST_DEBUG_OBJECT (sink, "ringbuffer is stopping");
-    return GST_FLOW_WRONG_STATE;
+    GST_DEBUG_OBJECT (sink, "preroll got interrupted: %d (%s)", ret,
+        gst_flow_get_name (ret));
+    return ret;
+  }
+sync_latency_failed:
+  {
+    GST_DEBUG_OBJECT (sink, "failed waiting for latency");
+    return ret;
   }
 }
 
@@ -1337,25 +1623,6 @@
   return buffer;
 }
 
-static gboolean
-gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active)
-{
-  gboolean ret;
-  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink);
-
-  if (active) {
-    gst_ring_buffer_set_callback (sink->ringbuffer,
-        gst_base_audio_sink_callback, sink);
-    ret = gst_ring_buffer_start (sink->ringbuffer);
-  } else {
-    gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL);
-    /* stop thread */
-    ret = gst_ring_buffer_release (sink->ringbuffer);
-  }
-
-  return ret;
-}
-
 static void
 gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
     gpointer user_data)
@@ -1368,11 +1635,15 @@
   basesink = GST_BASE_SINK (user_data);
   sink = GST_BASE_AUDIO_SINK (user_data);
 
+  GST_PAD_STREAM_LOCK (basesink->sinkpad);
+
   /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we
      will copy twice, once into data, once into DMA */
   GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT
       " to fill audio buffer", len, basesink->offset);
-  ret = gst_pad_pull_range (basesink->sinkpad, basesink->offset, len, &buf);
+  ret =
+      gst_pad_pull_range (basesink->sinkpad, basesink->segment.last_stop, len,
+      &buf);
 
   if (ret != GST_FLOW_OK) {
     if (ret == GST_FLOW_UNEXPECTED)
@@ -1381,22 +1652,37 @@
       goto error;
   }
 
+  GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+  if (basesink->flushing)
+    goto flushing;
+
+  /* complete preroll and wait for PLAYING */
+  ret = gst_base_sink_do_preroll (basesink, GST_MINI_OBJECT_CAST (buf));
+  if (ret != GST_FLOW_OK)
+    goto preroll_error;
+
   if (len != GST_BUFFER_SIZE (buf)) {
-    GST_INFO_OBJECT (basesink, "short read pulling from sink pad: %d<%d",
-        len, GST_BUFFER_SIZE (buf));
+    GST_INFO_OBJECT (basesink,
+        "got different size than requested from sink pad: %u != %u", len,
+        GST_BUFFER_SIZE (buf));
     len = MIN (GST_BUFFER_SIZE (buf), len);
   }
 
-  basesink->offset += len;
+  basesink->segment.last_stop += len;
 
   memcpy (data, GST_BUFFER_DATA (buf), len);
+  GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+
+  GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
 
   return;
 
 error:
   {
-    GST_WARNING_OBJECT (basesink, "Got flow error but can't return it: %d",
-        ret);
+    GST_WARNING_OBJECT (basesink, "Got flow '%s' but can't return it: %d",
+        gst_flow_get_name (ret), ret);
+    gst_ring_buffer_pause (rbuf);
+    GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
     return;
   }
 eos:
@@ -1405,82 +1691,72 @@
      * the sink gets shut down; maybe we should set a flag somewhere, or
      * set segment.stop and segment.duration to the last sample or so */
     GST_DEBUG_OBJECT (sink, "EOS");
+    gst_base_audio_sink_drain (sink);
+    gst_ring_buffer_pause (rbuf);
     gst_element_post_message (GST_ELEMENT_CAST (sink),
         gst_message_new_eos (GST_OBJECT_CAST (sink)));
-    gst_base_audio_sink_drain (sink);
+    GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
+  }
+flushing:
+  {
+    GST_DEBUG_OBJECT (sink, "we are flushing");
+    gst_ring_buffer_pause (rbuf);
+    GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+    GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
+    return;
+  }
+preroll_error:
+  {
+    GST_DEBUG_OBJECT (sink, "error %s", gst_flow_get_name (ret));
+    gst_ring_buffer_pause (rbuf);
+    GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+    GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
+    return;
   }
 }
 
+static gboolean
+gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active)
+{
+  gboolean ret;
+  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink);
+
+  if (active) {
+    GST_DEBUG_OBJECT (basesink, "activating pull");
+
+    gst_ring_buffer_set_callback (sink->ringbuffer,
+        gst_base_audio_sink_callback, sink);
+
+    ret = gst_ring_buffer_activate (sink->ringbuffer, TRUE);
+  } else {
+    GST_DEBUG_OBJECT (basesink, "deactivating pull");
+    gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL);
+    ret = gst_ring_buffer_activate (sink->ringbuffer, FALSE);
+  }
+
+  return ret;
+}
+
 /* should be called with the LOCK */
 static GstStateChangeReturn
 gst_base_audio_sink_async_play (GstBaseSink * basesink)
 {
-  GstClock *clock;
   GstBaseAudioSink *sink;
-  GstClockTime itime, etime;
-  GstClockTime rate_num, rate_denom;
 
   sink = GST_BASE_AUDIO_SINK (basesink);
 
   GST_DEBUG_OBJECT (sink, "ringbuffer may start now");
+  sink->priv->sync_latency = TRUE;
   gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
-
-  clock = GST_ELEMENT_CLOCK (sink);
-  if (clock == NULL)
-    goto done;
-
-  /* we provided the global clock, don't need to do anything special */
-  if (clock == sink->provided_clock)
-    goto done;
-
-  /* if we are slaved to a clock, we need to set the initial
-   * calibration */
-  /* get external and internal time to set as calibration params */
-  etime = gst_clock_get_time (clock);
-  itime = gst_clock_get_internal_time (sink->provided_clock);
-
-  sink->priv->avg_skew = -1;
-  sink->next_sample = -1;
-
-  GST_DEBUG_OBJECT (sink,
-      "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (itime), GST_TIME_ARGS (etime));
-
-  gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num,
-      &rate_denom);
-  gst_clock_set_calibration (sink->provided_clock, itime, etime,
-      rate_num, rate_denom);
-
-  switch (sink->priv->slave_method) {
-    case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE:
-      /* only set as master if we need to resample */
-      GST_DEBUG_OBJECT (sink, "Setting clock as master");
-      gst_clock_set_master (sink->provided_clock, clock);
-      break;
-    default:
-      break;
+  if (basesink->pad_mode == GST_ACTIVATE_PULL) {
+    /* we always start the ringbuffer in pull mode immediatly */
+    gst_ring_buffer_start (sink->ringbuffer);
   }
 
-  /* start ringbuffer so we can start slaving right away when we need to */
-  gst_ring_buffer_start (sink->ringbuffer);
-
-done:
   return GST_STATE_CHANGE_SUCCESS;
 }
 
 static GstStateChangeReturn
-gst_base_audio_sink_do_play (GstBaseAudioSink * sink)
-{
-  GstStateChangeReturn ret;
-
-  GST_OBJECT_LOCK (sink);
-  ret = gst_base_audio_sink_async_play (GST_BASE_SINK_CAST (sink));
-  GST_OBJECT_UNLOCK (sink);
-
-  return ret;
-}
-
-static GstStateChangeReturn
 gst_base_audio_sink_change_state (GstElement * element,
     GstStateChange transition)
 {
@@ -1490,6 +1766,7 @@
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       if (sink->ringbuffer == NULL) {
+        gst_audio_clock_reset (GST_AUDIO_CLOCK (sink->provided_clock), 0);
         sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink);
       }
       if (!gst_ring_buffer_open_device (sink->ringbuffer))
@@ -1498,19 +1775,29 @@
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       sink->next_sample = -1;
       sink->priv->last_align = -1;
+      sink->priv->eos_time = -1;
       gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
       gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      gst_base_audio_sink_do_play (sink);
+      GST_OBJECT_LOCK (sink);
+      GST_DEBUG_OBJECT (sink, "ringbuffer may start now");
+      sink->priv->sync_latency = TRUE;
+      GST_OBJECT_UNLOCK (sink);
+
+      gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
+      if (GST_BASE_SINK_CAST (sink)->pad_mode == GST_ACTIVATE_PULL) {
+        /* we always start the ringbuffer in pull mode immediatly */
+        gst_ring_buffer_start (sink->ringbuffer);
+      }
       break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      /* need to take the lock so we don't interfere with an
-       * async play */
-      GST_OBJECT_LOCK (sink);
       /* ringbuffer cannot start anymore */
       gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
       gst_ring_buffer_pause (sink->ringbuffer);
+
+      GST_OBJECT_LOCK (sink);
+      sink->priv->sync_latency = FALSE;
       GST_OBJECT_UNLOCK (sink);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
@@ -1530,6 +1817,7 @@
       gst_clock_set_master (sink->provided_clock, NULL);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_ring_buffer_activate (sink->ringbuffer, FALSE);
       gst_ring_buffer_release (sink->ringbuffer);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -1537,8 +1825,13 @@
        * caps, which happens before we commit the state to PAUSED and thus the
        * PAUSED->READY state change (see above, where we release the ringbuffer)
        * might not be called when we get here. */
+      gst_ring_buffer_activate (sink->ringbuffer, FALSE);
       gst_ring_buffer_release (sink->ringbuffer);
       gst_ring_buffer_close_device (sink->ringbuffer);
+      GST_OBJECT_LOCK (sink);
+      gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer));
+      sink->ringbuffer = NULL;
+      GST_OBJECT_UNLOCK (sink);
       break;
     default:
       break;
--- a/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -85,7 +85,8 @@
  * drifts too much.
  * @GST_BASE_AUDIO_SINK_SLAVE_NONE: No adjustment is done. 
  *
- * Different possible clock slaving algorithms
+ * Different possible clock slaving algorithms used when the internal audio
+ * clock is not selected as the pipeline master clock.
  */
 typedef enum 
 {
@@ -94,6 +95,8 @@
   GST_BASE_AUDIO_SINK_SLAVE_NONE
 } GstBaseAudioSinkSlaveMethod;
 
+#define GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD (gst_base_audio_sink_slave_method_get_type ())
+
 typedef struct _GstBaseAudioSink GstBaseAudioSink;
 typedef struct _GstBaseAudioSinkClass GstBaseAudioSinkClass;
 typedef struct _GstBaseAudioSinkPrivate GstBaseAudioSinkPrivate;
@@ -154,6 +157,11 @@
 IMPORT_C
 #endif
 
+GType gst_base_audio_sink_slave_method_get_type (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GstRingBuffer *gst_base_audio_sink_create_ringbuffer (GstBaseAudioSink *sink);
 #ifdef __SYMBIAN32__
--- a/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -42,12 +42,31 @@
 
 #include "gst/gst-i18n-plugin.h"
 
+GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
+#define GST_CAT_DEFAULT gst_base_audio_src_debug
+
 #ifdef __SYMBIAN32__
-#include <glib_global.h>
+EXPORT_C
 #endif
 
-GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
-#define GST_CAT_DEFAULT gst_base_audio_src_debug
+GType
+gst_base_audio_src_slave_method_get_type (void)
+{
+  static GType slave_method_type = 0;
+  static const GEnumValue slave_method[] = {
+    {GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE, "Resampling slaving", "resample"},
+    {GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP, "Re-timestamp", "re-timestamp"},
+    {GST_BASE_AUDIO_SRC_SLAVE_SKEW, "Skew", "skew"},
+    {GST_BASE_AUDIO_SRC_SLAVE_NONE, "No slaving", "none"},
+    {0, NULL, NULL},
+  };
+
+  if (!slave_method_type) {
+    slave_method_type =
+        g_enum_register_static ("GstBaseAudioSrcSlaveMethod", slave_method);
+  }
+  return slave_method_type;
+}
 
 #define GST_BASE_AUDIO_SRC_GET_PRIVATE(obj)  \
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SRC, GstBaseAudioSrcPrivate))
@@ -55,6 +74,9 @@
 struct _GstBaseAudioSrcPrivate
 {
   gboolean provide_clock;
+
+  /* the clock slaving algorithm in use */
+  GstBaseAudioSrcSlaveMethod slave_method;
 };
 
 /* BaseAudioSrc signals and args */
@@ -66,14 +88,21 @@
 
 #define DEFAULT_BUFFER_TIME     ((200 * GST_MSECOND) / GST_USECOND)
 #define DEFAULT_LATENCY_TIME    ((10 * GST_MSECOND) / GST_USECOND)
+#define DEFAULT_ACTUAL_BUFFER_TIME     -1
+#define DEFAULT_ACTUAL_LATENCY_TIME    -1
 #define DEFAULT_PROVIDE_CLOCK   TRUE
+#define DEFAULT_SLAVE_METHOD    GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP
 
 enum
 {
   PROP_0,
   PROP_BUFFER_TIME,
   PROP_LATENCY_TIME,
-  PROP_PROVIDE_CLOCK
+  PROP_ACTUAL_BUFFER_TIME,
+  PROP_ACTUAL_LATENCY_TIME,
+  PROP_PROVIDE_CLOCK,
+  PROP_SLAVE_METHOD,
+  PROP_LAST
 };
 
 static void
@@ -86,6 +115,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 }
 
@@ -147,17 +177,51 @@
   g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
       g_param_spec_int64 ("buffer-time", "Buffer Time",
           "Size of audio buffer in microseconds", 1,
-          G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_BUFFER_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
       g_param_spec_int64 ("latency-time", "Latency Time",
           "Audio latency in microseconds", 1,
-          G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_LATENCY_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstBaseAudioSrc:actual-buffer-time:
+   *
+   * Actual configured size of audio buffer in microseconds.
+   *
+   * Since: 0.10.20
+   **/
+  g_object_class_install_property (gobject_class, PROP_ACTUAL_BUFFER_TIME,
+      g_param_spec_int64 ("actual-buffer-time", "Actual Buffer Time",
+          "Actual configured size of audio buffer in microseconds",
+          DEFAULT_ACTUAL_BUFFER_TIME, G_MAXINT64, DEFAULT_ACTUAL_BUFFER_TIME,
+          G_PARAM_READABLE));
+
+  /**
+   * GstBaseAudioSrc:actual-latency-time:
+   *
+   * Actual configured audio latency in microseconds.
+   *
+   * Since: 0.10.20
+   **/
+  g_object_class_install_property (gobject_class, PROP_ACTUAL_LATENCY_TIME,
+      g_param_spec_int64 ("actual-latency-time", "Actual Latency Time",
+          "Actual configured audio latency in microseconds",
+          DEFAULT_ACTUAL_LATENCY_TIME, G_MAXINT64, DEFAULT_ACTUAL_LATENCY_TIME,
+          G_PARAM_READABLE));
 
   g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
       g_param_spec_boolean ("provide-clock", "Provide Clock",
           "Provide a clock to be used as the global pipeline clock",
-          DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE));
+          DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
+      g_param_spec_enum ("slave-method", "Slave Method",
+          "Algorithm to use to match the rate of the masterclock",
+          GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_audio_src_change_state);
@@ -177,6 +241,7 @@
   /* ref class from a thread-safe context to work around missing bit of
    * thread-safety in GObject */
   g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
+  g_type_class_ref (GST_TYPE_RING_BUFFER);
 }
 
 static void
@@ -188,6 +253,7 @@
   baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME;
   baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME;
   baseaudiosrc->priv->provide_clock = DEFAULT_PROVIDE_CLOCK;
+  baseaudiosrc->priv->slave_method = DEFAULT_SLAVE_METHOD;
   /* reset blocksize we use latency time to calculate a more useful 
    * value based on negotiated format. */
   GST_BASE_SRC (baseaudiosrc)->blocksize = 0;
@@ -208,6 +274,7 @@
 
   src = GST_BASE_AUDIO_SRC (object);
 
+  GST_OBJECT_LOCK (src);
   if (src->clock)
     gst_object_unref (src->clock);
   src->clock = NULL;
@@ -216,6 +283,7 @@
     gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
     src->ringbuffer = NULL;
   }
+  GST_OBJECT_UNLOCK (src);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -350,6 +418,58 @@
   return result;
 }
 
+/**
+ * gst_base_audio_src_set_slave_method:
+ * @src: a #GstBaseAudioSrc
+ * @method: the new slave method
+ *
+ * Controls how clock slaving will be performed in @src. 
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_base_audio_src_set_slave_method (GstBaseAudioSrc * src,
+    GstBaseAudioSrcSlaveMethod method)
+{
+  g_return_if_fail (GST_IS_BASE_AUDIO_SRC (src));
+
+  GST_OBJECT_LOCK (src);
+  src->priv->slave_method = method;
+  GST_OBJECT_UNLOCK (src);
+}
+
+/**
+ * gst_base_audio_src_get_slave_method:
+ * @src: a #GstBaseAudioSrc
+ *
+ * Get the current slave method used by @src.
+ *
+ * Returns: The current slave method used by @src.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBaseAudioSrcSlaveMethod
+gst_base_audio_src_get_slave_method (GstBaseAudioSrc * src)
+{
+  GstBaseAudioSrcSlaveMethod result;
+
+  g_return_val_if_fail (GST_IS_BASE_AUDIO_SRC (src), -1);
+
+  GST_OBJECT_LOCK (src);
+  result = src->priv->slave_method;
+  GST_OBJECT_UNLOCK (src);
+
+  return result;
+}
+
 static void
 gst_base_audio_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -368,6 +488,9 @@
     case PROP_PROVIDE_CLOCK:
       gst_base_audio_src_set_provide_clock (src, g_value_get_boolean (value));
       break;
+    case PROP_SLAVE_METHOD:
+      gst_base_audio_src_set_slave_method (src, g_value_get_enum (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -389,9 +512,28 @@
     case PROP_LATENCY_TIME:
       g_value_set_int64 (value, src->latency_time);
       break;
+    case PROP_ACTUAL_BUFFER_TIME:
+      GST_OBJECT_LOCK (src);
+      if (src->ringbuffer && src->ringbuffer->acquired)
+        g_value_set_int64 (value, src->ringbuffer->spec.buffer_time);
+      else
+        g_value_set_int64 (value, DEFAULT_ACTUAL_BUFFER_TIME);
+      GST_OBJECT_UNLOCK (src);
+      break;
+    case PROP_ACTUAL_LATENCY_TIME:
+      GST_OBJECT_LOCK (src);
+      if (src->ringbuffer && src->ringbuffer->acquired)
+        g_value_set_int64 (value, src->ringbuffer->spec.latency_time);
+      else
+        g_value_set_int64 (value, DEFAULT_ACTUAL_LATENCY_TIME);
+      GST_OBJECT_UNLOCK (src);
+      break;
     case PROP_PROVIDE_CLOCK:
       g_value_set_boolean (value, gst_base_audio_src_get_provide_clock (src));
       break;
+    case PROP_SLAVE_METHOD:
+      g_value_set_enum (value, gst_base_audio_src_get_slave_method (src));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -463,6 +605,9 @@
 
   gst_ring_buffer_debug_spec_buff (spec);
 
+  g_object_notify (G_OBJECT (src), "actual-buffer-time");
+  g_object_notify (G_OBJECT (src), "actual-latency-time");
+
   return TRUE;
 
   /* ERRORS */
@@ -538,21 +683,31 @@
 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
 {
   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
+  gboolean res;
+
+  res = TRUE;
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_START:
+      GST_DEBUG_OBJECT (bsrc, "flush-start");
       gst_ring_buffer_pause (src->ringbuffer);
       gst_ring_buffer_clear_all (src->ringbuffer);
       break;
     case GST_EVENT_FLUSH_STOP:
+      GST_DEBUG_OBJECT (bsrc, "flush-stop");
       /* always resync on sample after a flush */
       src->next_sample = -1;
       gst_ring_buffer_clear_all (src->ringbuffer);
       break;
+    case GST_EVENT_SEEK:
+      GST_DEBUG_OBJECT (bsrc, "refuse to seek");
+      res = FALSE;
+      break;
     default:
+      GST_DEBUG_OBJECT (bsrc, "dropping event %p", event);
       break;
   }
-  return TRUE;
+  return res;
 }
 
 /* get the next offset in the ringbuffer for reading samples.
@@ -591,7 +746,7 @@
   if (diff >= segtotal) {
     GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone);
     /* sample would be dropped, position to next playable position */
-    sample = (segdone - segtotal + 1) * sps;
+    sample = ((guint64) (segdone)) * sps;
   }
 
   return sample;
@@ -677,7 +832,9 @@
         G_GUINT64_FORMAT, sample - src->next_sample, sample);
     GST_ELEMENT_WARNING (src, CORE, CLOCK,
         (_("Can't record audio fast enough")),
-        ("dropped %" G_GUINT64_FORMAT " samples", sample - src->next_sample));
+        ("Dropped %" G_GUINT64_FORMAT " samples. This is most likely because "
+            "downstream can't keep up and is consuming samples too slowly.",
+            sample - src->next_sample));
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
   }
 
@@ -689,28 +846,179 @@
       spec->rate) - timestamp;
 
   GST_OBJECT_LOCK (src);
-  clock = GST_ELEMENT_CLOCK (src);
-  if (clock != NULL && clock != src->clock) {
-    GstClockTime base_time, latency;
+  if (!(clock = GST_ELEMENT_CLOCK (src)))
+    goto no_sync;
+
+  if (clock != src->clock) {
+    /* we are slaved, check how to handle this */
+    switch (src->priv->slave_method) {
+      case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE:
+        /* not implemented, use skew algorithm. This algorithm should
+         * work on the readout pointer and produces more or less samples based
+         * on the clock drift */
+      case GST_BASE_AUDIO_SRC_SLAVE_SKEW:
+      {
+        GstClockTime running_time;
+        GstClockTime base_time;
+        GstClockTime current_time;
+        guint64 running_time_sample;
+        gint running_time_segment;
+        gint current_segment;
+        gint segment_skew;
+        gint sps;
+
+        /* samples per segment */
+        sps = ringbuffer->samples_per_seg;
+
+        /* get the current time */
+        current_time = gst_clock_get_time (clock);
+
+        /* get the basetime */
+        base_time = GST_ELEMENT_CAST (src)->base_time;
+
+        /* get the running_time */
+        running_time = current_time - base_time;
+
+        /* the running_time converted to a sample (relative to the ringbuffer) */
+        running_time_sample =
+            gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND);
+
+        /* the segmentnr corrensponding to running_time, round down */
+        running_time_segment = running_time_sample / sps;
+
+        /* the segment currently read from the ringbuffer */
+        current_segment = sample / sps;
+
+        /* the skew we have between running_time and the ringbuffertime */
+        segment_skew = running_time_segment - current_segment;
+
+        GST_DEBUG_OBJECT (bsrc, "\n running_time = %" GST_TIME_FORMAT
+            "\n timestamp     = %" GST_TIME_FORMAT
+            "\n running_time_segment = %d"
+            "\n current_segment      = %d"
+            "\n segment_skew         = %d",
+            GST_TIME_ARGS (running_time),
+            GST_TIME_ARGS (timestamp),
+            running_time_segment, current_segment, segment_skew);
 
-    /* We are slaved to another clock, take running time of the clock and just
-     * timestamp against it. Somebody else in the pipeline should figure out the
-     * clock drift, for now. We keep the duration we calculated above. */
-    timestamp = gst_clock_get_time (clock);
+        /* Resync the ringbuffer if:
+         * 1. We get one segment into the future.
+         *    This is clearly a lie, because we can't
+         *    possibly have a buffer with timestamp 1 at
+         *    time 0. (unless it has time-travelled...)
+         *
+         * 2. We are more than the length of the ringbuffer behind.
+         *    The length of the ringbuffer then gets to dictate
+         *    the threshold for what is concidered "too late"
+         *
+         * 3. If this is our first buffer.
+         *    We know that we should catch up to running_time
+         *    the first time we are ran.
+         */
+        if ((segment_skew < 0) ||
+            (segment_skew >= ringbuffer->spec.segtotal) ||
+            (current_segment == 0)) {
+          gint segments_written;
+          gint first_segment;
+          gint last_segment;
+          gint new_last_segment;
+          gint segment_diff;
+          gint new_first_segment;
+          guint64 new_sample;
+
+          /* we are going to say that the last segment was captured at the current time
+             (running_time), minus one segment of creation-latency in the ringbuffer.
+             This can be thought of as: The segment arrived in the ringbuffer at time X, and
+             that means it was created at time X - (one segment). */
+          new_last_segment = running_time_segment - 1;
+
+          /* for better readablity */
+          first_segment = current_segment;
+
+          /* get the amount of segments written from the device by now */
+          segments_written = g_atomic_int_get (&ringbuffer->segdone);
+
+          /* subtract the base to segments_written to get the number of the
+             last written segment in the ringbuffer (one segment written = segment 0) */
+          last_segment = segments_written - ringbuffer->segbase - 1;
+
+          /* we see how many segments the ringbuffer was timeshifted */
+          segment_diff = new_last_segment - last_segment;
+
+          /* we move the first segment an equal amount */
+          new_first_segment = first_segment + segment_diff;
+
+          /* and we also move the segmentbase the same amount */
+          ringbuffer->segbase -= segment_diff;
+
+          /* we calculate the new sample value */
+          new_sample = ((guint64) new_first_segment) * sps;
+
+          /* and get the relative time to this -> our new timestamp */
+          timestamp =
+              gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate);
+
+          /* we update the next sample accordingly */
+          src->next_sample = new_sample + samples;
+
+          GST_DEBUG_OBJECT (bsrc,
+              "Timeshifted the ringbuffer with %d segments: "
+              "Updating the timestamp to %" GST_TIME_FORMAT ", "
+              "and src->next_sample to %" G_GUINT64_FORMAT, segment_diff,
+              GST_TIME_ARGS (timestamp), src->next_sample);
+        }
+        break;
+      }
+      case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP:
+      {
+        GstClockTime base_time, latency;
+
+        /* We are slaved to another clock, take running time of the pipeline clock and
+         * timestamp against it. Somebody else in the pipeline should figure out the
+         * clock drift. We keep the duration we calculated above. */
+        timestamp = gst_clock_get_time (clock);
+        base_time = GST_ELEMENT_CAST (src)->base_time;
+
+        if (timestamp > base_time)
+          timestamp -= base_time;
+        else
+          timestamp = 0;
+
+        /* subtract latency */
+        latency =
+            gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
+        if (timestamp > latency)
+          timestamp -= latency;
+        else
+          timestamp = 0;
+      }
+      case GST_BASE_AUDIO_SRC_SLAVE_NONE:
+        break;
+    }
+  } else {
+    GstClockTime base_time;
+
+    /* to get the timestamp against the clock we also need to add our offset */
+    timestamp = gst_audio_clock_adjust (clock, timestamp);
+
+    /* we are not slaved, subtract base_time */
     base_time = GST_ELEMENT_CAST (src)->base_time;
 
-    if (timestamp > base_time)
+    if (timestamp > base_time) {
       timestamp -= base_time;
-    else
+      GST_LOG_OBJECT (src,
+          "buffer timestamp %" GST_TIME_FORMAT " (base_time %" GST_TIME_FORMAT
+          ")", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (base_time));
+    } else {
+      GST_LOG_OBJECT (src,
+          "buffer timestamp 0, ts %" GST_TIME_FORMAT " <= base_time %"
+          GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
+          GST_TIME_ARGS (base_time));
       timestamp = 0;
+    }
+  }
 
-    /* subtract latency */
-    latency = gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
-    if (timestamp > latency)
-      timestamp -= latency;
-    else
-      timestamp = 0;
-  }
+no_sync:
   GST_OBJECT_UNLOCK (src);
 
   GST_BUFFER_TIMESTAMP (buf) = timestamp;
@@ -718,8 +1026,6 @@
   GST_BUFFER_OFFSET (buf) = sample;
   GST_BUFFER_OFFSET_END (buf) = sample + samples;
 
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (bsrc)));
-
   *outbuf = buf;
 
   return GST_FLOW_OK;
@@ -785,9 +1091,12 @@
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       GST_DEBUG_OBJECT (src, "NULL->READY");
+      GST_OBJECT_LOCK (src);
       if (src->ringbuffer == NULL) {
+        gst_audio_clock_reset (GST_AUDIO_CLOCK (src->clock), 0);
         src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
       }
+      GST_OBJECT_UNLOCK (src);
       if (!gst_ring_buffer_open_device (src->ringbuffer))
         goto open_failed;
       break;
@@ -824,8 +1133,10 @@
     case GST_STATE_CHANGE_READY_TO_NULL:
       GST_DEBUG_OBJECT (src, "READY->NULL");
       gst_ring_buffer_close_device (src->ringbuffer);
+      GST_OBJECT_LOCK (src);
       gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
       src->ringbuffer = NULL;
+      GST_OBJECT_UNLOCK (src);
       break;
     default:
       break;
--- a/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -60,6 +60,28 @@
 typedef struct _GstBaseAudioSrcPrivate GstBaseAudioSrcPrivate;
 
 /**
+ * GstBaseAudioSrcSlaveMethod:
+ * @GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE: Resample to match the master clock. 
+ * @GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP: Retimestamp output buffers with master
+ * clock time.
+ * @GST_BASE_AUDIO_SRC_SLAVE_SKEW: Adjust capture pointer when master clock
+ * drifts too much.
+ * @GST_BASE_AUDIO_SRC_SLAVE_NONE: No adjustment is done. 
+ *
+ * Different possible clock slaving algorithms when the internal audio clock was
+ * not selected as the pipeline clock.
+ */
+typedef enum
+{
+  GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE,
+  GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP,
+  GST_BASE_AUDIO_SRC_SLAVE_SKEW,
+  GST_BASE_AUDIO_SRC_SLAVE_NONE
+} GstBaseAudioSrcSlaveMethod;
+
+#define GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD (gst_base_audio_src_slave_method_get_type ())
+
+/**
  * GstBaseAudioSrc:
  *
  * Opaque #GstBaseAudioSrc.
@@ -114,6 +136,11 @@
 IMPORT_C
 #endif
 
+GType gst_base_audio_src_slave_method_get_type (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GstRingBuffer *gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc *src);
 #ifdef __SYMBIAN32__
@@ -127,6 +154,20 @@
 #endif
 
 gboolean   gst_base_audio_src_get_provide_clock        (GstBaseAudioSrc *src);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void       gst_base_audio_src_set_slave_method         (GstBaseAudioSrc *src,
+                                                        GstBaseAudioSrcSlaveMethod method);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBaseAudioSrcSlaveMethod
+           gst_base_audio_src_get_slave_method         (GstBaseAudioSrc *src);
+
 
 G_END_DECLS
 
--- a/gst_plugins_base/gst-libs/gst/audio/gstringbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstringbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -43,10 +43,6 @@
 
 #include "gstringbuffer.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_ring_buffer_debug);
 #define GST_CAT_DEFAULT gst_ring_buffer_debug
 
@@ -56,6 +52,9 @@
 static void gst_ring_buffer_finalize (GObject * object);
 
 static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf);
+static void default_clear_all (GstRingBuffer * buf);
+static guint default_commit (GstRingBuffer * buf, guint64 * sample,
+    guchar * data, gint in_samples, gint out_samples, gint * accum);
 
 static GstObjectClass *parent_class = NULL;
 
@@ -97,14 +96,19 @@
 {
   GObjectClass *gobject_class;
   GstObjectClass *gstobject_class;
+  GstRingBufferClass *gstringbuffer_class;
 
   gobject_class = (GObjectClass *) klass;
   gstobject_class = (GstObjectClass *) klass;
+  gstringbuffer_class = (GstRingBufferClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ring_buffer_dispose);
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ring_buffer_finalize);
+
+  gstringbuffer_class->clear_all = GST_DEBUG_FUNCPTR (default_clear_all);
+  gstringbuffer_class->commit = GST_DEBUG_FUNCPTR (default_commit);
 }
 
 static void
@@ -274,6 +278,7 @@
   GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
       spec->latency_time);
   GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
+  GST_DEBUG ("acquire ringbuffer: latency segments: %d", spec->seglatency);
   GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
       spec->segsize, spec->segsize / spec->bytes_per_sample);
   GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
@@ -434,6 +439,9 @@
   spec->segsize -= spec->segsize % spec->bytes_per_sample;
 
   spec->segtotal = spec->buffer_time / spec->latency_time;
+  /* leave the latency undefined now, implementations can change it but if it's
+   * not changed, we assume the same value as segtotal */
+  spec->seglatency = -1;
 
   gst_ring_buffer_debug_spec_caps (spec);
   gst_ring_buffer_debug_spec_buff (spec);
@@ -449,6 +457,105 @@
 }
 
 /**
+ * gst_ring_buffer_convert:
+ * @buf: the #GstRingBuffer
+ * @src_fmt: the source format
+ * @src_val: the source value
+ * @dest_fmt: the destination format
+ * @dest_val: a location to store the converted value
+ *
+ * Convert @src_val in @src_fmt to the equivalent value in @dest_fmt. The result
+ * will be put in @dest_val.
+ *
+ * Returns: TRUE if the conversion succeeded.
+ *
+ * Since: 0.10.22.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_ring_buffer_convert (GstRingBuffer * buf,
+    GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val)
+{
+  gboolean res = TRUE;
+  gint bps, rate;
+
+  GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)",
+      src_val, gst_format_get_name (src_fmt), src_fmt,
+      gst_format_get_name (dest_fmt), dest_fmt);
+
+  if (src_fmt == dest_fmt || src_val == -1) {
+    *dest_val = src_val;
+    goto done;
+  }
+
+  /* get important info */
+  GST_OBJECT_LOCK (buf);
+  bps = buf->spec.bytes_per_sample;
+  rate = buf->spec.rate;
+  GST_OBJECT_UNLOCK (buf);
+
+  if (bps == 0 || rate == 0) {
+    GST_DEBUG ("no rate or bps configured");
+    res = FALSE;
+    goto done;
+  }
+
+  switch (src_fmt) {
+    case GST_FORMAT_BYTES:
+      switch (dest_fmt) {
+        case GST_FORMAT_TIME:
+          *dest_val = gst_util_uint64_scale_int (src_val / bps, GST_SECOND,
+              rate);
+          break;
+        case GST_FORMAT_DEFAULT:
+          *dest_val = src_val / bps;
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_DEFAULT:
+      switch (dest_fmt) {
+        case GST_FORMAT_TIME:
+          *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate);
+          break;
+        case GST_FORMAT_BYTES:
+          *dest_val = src_val * bps;
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_TIME:
+      switch (dest_fmt) {
+        case GST_FORMAT_DEFAULT:
+          *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
+          break;
+        case GST_FORMAT_BYTES:
+          *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
+          *dest_val *= bps;
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    default:
+      res = FALSE;
+      break;
+  }
+done:
+  GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val);
+
+  return res;
+}
+
+/**
  * gst_ring_buffer_set_callback:
  * @buf: the #GstRingBuffer to set the callback on
  * @cb: the callback to set
@@ -640,7 +747,6 @@
   return res;
 }
 
-
 /**
  * gst_ring_buffer_acquire:
  * @buf: the #GstRingBuffer to acquire
@@ -689,6 +795,11 @@
   if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0))
     goto invalid_bps;
 
+  /* if the seglatency was overwritten with something else than -1, use it, else
+   * assume segtotal as the latency */
+  if (buf->spec.seglatency == -1)
+    buf->spec.seglatency = buf->spec.segtotal;
+
   segsize = buf->spec.segsize;
 
   buf->samples_per_seg = segsize / bps;
@@ -840,6 +951,111 @@
 }
 
 /**
+ * gst_ring_buffer_activate:
+ * @buf: the #GstRingBuffer to activate
+ * @active: the new mode
+ *
+ * Activate @buf to start or stop pulling data.
+ *
+ * MT safe.
+ *
+ * Returns: TRUE if the device could be activated in the requested mode,
+ * FALSE on error.
+ *
+ * Since: 0.10.22.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_ring_buffer_activate (GstRingBuffer * buf, gboolean active)
+{
+  gboolean res = FALSE;
+  GstRingBufferClass *rclass;
+
+  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
+
+  GST_DEBUG_OBJECT (buf, "activate device");
+
+  GST_OBJECT_LOCK (buf);
+  if (G_UNLIKELY (active && !buf->acquired))
+    goto not_acquired;
+
+  if (G_UNLIKELY (buf->abidata.ABI.active == active))
+    goto was_active;
+
+  rclass = GST_RING_BUFFER_GET_CLASS (buf);
+  /* if there is no activate function we assume it was started/released
+   * in the acquire method */
+  if (G_LIKELY (rclass->activate))
+    res = rclass->activate (buf, active);
+  else
+    res = TRUE;
+
+  if (G_UNLIKELY (!res))
+    goto activate_failed;
+
+  buf->abidata.ABI.active = active;
+
+done:
+  GST_OBJECT_UNLOCK (buf);
+
+  return res;
+
+  /* ERRORS */
+not_acquired:
+  {
+    GST_DEBUG_OBJECT (buf, "device not acquired");
+    g_critical ("Device for %p not acquired", buf);
+    res = FALSE;
+    goto done;
+  }
+was_active:
+  {
+    res = TRUE;
+    GST_DEBUG_OBJECT (buf, "device was active in mode %d", active);
+    goto done;
+  }
+activate_failed:
+  {
+    GST_DEBUG_OBJECT (buf, "failed to activate device");
+    goto done;
+  }
+}
+
+/**
+ * gst_ring_buffer_is_active:
+ * @buf: the #GstRingBuffer
+ *
+ * Check if @buf is activated.
+ *
+ * MT safe.
+ *
+ * Returns: TRUE if the device is active.
+ *
+ * Since: 0.10.22.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_ring_buffer_is_active (GstRingBuffer * buf)
+{
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
+
+  GST_OBJECT_LOCK (buf);
+  res = buf->abidata.ABI.active;
+  GST_OBJECT_UNLOCK (buf);
+
+  return res;
+}
+
+
+/**
  * gst_ring_buffer_set_flushing:
  * @buf: the #GstRingBuffer to flush
  * @flushing: the new mode
@@ -860,9 +1076,10 @@
   GST_OBJECT_LOCK (buf);
   buf->abidata.ABI.flushing = flushing;
 
-  gst_ring_buffer_clear_all (buf);
   if (flushing) {
     gst_ring_buffer_pause_unlocked (buf);
+  } else {
+    gst_ring_buffer_clear_all (buf);
   }
   GST_OBJECT_UNLOCK (buf);
 }
@@ -904,13 +1121,14 @@
       GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED);
 
   if (!res) {
+    GST_DEBUG_OBJECT (buf, "was not stopped, try paused");
     /* was not stopped, try from paused */
     res = g_atomic_int_compare_and_exchange (&buf->state,
         GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STARTED);
     if (!res) {
       /* was not paused either, must be started then */
       res = TRUE;
-      GST_DEBUG_OBJECT (buf, "was started");
+      GST_DEBUG_OBJECT (buf, "was not paused, must have been started");
       goto done;
     }
     resume = TRUE;
@@ -1071,10 +1289,16 @@
       GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED);
 
   if (!res) {
-    /* was not started, must be stopped then */
-    GST_DEBUG_OBJECT (buf, "was not started");
-    res = TRUE;
-    goto done;
+    GST_DEBUG_OBJECT (buf, "was not started, try paused");
+    /* was not started, try from paused */
+    res = g_atomic_int_compare_and_exchange (&buf->state,
+        GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STOPPED);
+    if (!res) {
+      /* was not paused either, must have been stopped then */
+      res = TRUE;
+      GST_DEBUG_OBJECT (buf, "was not paused, must have been stopped");
+      goto done;
+    }
   }
 
   /* signal any waiters */
@@ -1220,6 +1444,22 @@
       buf->segbase);
 }
 
+static void
+default_clear_all (GstRingBuffer * buf)
+{
+  gint i;
+
+  /* not fatal, we just are not negotiated yet */
+  if (G_UNLIKELY (buf->spec.segtotal <= 0))
+    return;
+
+  GST_DEBUG_OBJECT (buf, "clear all segments");
+
+  for (i = 0; i < buf->spec.segtotal; i++) {
+    gst_ring_buffer_clear (buf, i);
+  }
+}
+
 /**
  * gst_ring_buffer_clear_all:
  * @buf: the #GstRingBuffer to clear
@@ -1235,19 +1475,14 @@
 void
 gst_ring_buffer_clear_all (GstRingBuffer * buf)
 {
-  gint i;
+  GstRingBufferClass *rclass;
 
   g_return_if_fail (GST_IS_RING_BUFFER (buf));
 
-  /* not fatal, we just are not negotiated yet */
-  if (G_UNLIKELY (buf->spec.segtotal <= 0))
-    return;
+  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 
-  GST_DEBUG_OBJECT (buf, "clear all segments");
-
-  for (i = 0; i < buf->spec.segtotal; i++) {
-    gst_ring_buffer_clear (buf, i);
-  }
+  if (G_LIKELY (rclass->clear_all))
+    rclass->clear_all (buf);
 }
 
 
@@ -1370,7 +1605,7 @@
       memcpy (d, se, bps);			\
     se -= bps;					\
     *accum += outr;				\
-    while ((*accum << 1) >= inr) {		\
+    while (d < de && (*accum << 1) >= inr) {	\
       *accum -= inr;				\
       d += bps;					\
     }						\
@@ -1388,7 +1623,7 @@
       memcpy (d, se, bps);			\
     d += bps;					\
     *accum += inr;				\
-    while ((*accum << 1) >= outr) {		\
+    while (s <= se && (*accum << 1) >= outr) {	\
       *accum -= outr;				\
       se -= bps;				\
     }						\
@@ -1398,47 +1633,8 @@
   GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess);	\
 } G_STMT_END
 
-/**
- * gst_ring_buffer_commit_full:
- * @buf: the #GstRingBuffer to commit
- * @sample: the sample position of the data
- * @data: the data to commit
- * @in_samples: the number of samples in the data to commit
- * @out_samples: the number of samples to write to the ringbuffer
- * @accum: accumulator for rate conversion.
- *
- * Commit @in_samples samples pointed to by @data to the ringbuffer @buf. 
- *
- * @in_samples and @out_samples define the rate conversion to perform on the the
- * samples in @data. For negative rates, @out_samples must be negative and
- * @in_samples positive.
- *
- * When @out_samples is positive, the first sample will be written at position @sample
- * in the ringbuffer. When @out_samples is negative, the last sample will be written to
- * @sample in reverse order.
- *
- * @out_samples does not need to be a multiple of the segment size of the ringbuffer
- * although it is recommended for optimal performance. 
- *
- * @accum will hold a temporary accumulator used in rate conversion and should be
- * set to 0 when this function is first called. In case the commit operation is
- * interrupted, one can resume the processing by passing the previously returned
- * @accum value back to this function.
- *
- * Returns: The number of samples written to the ringbuffer or -1 on error. The
- * number of samples written can be less than @out_samples when @buf was interrupted
- * with a flush or stop.
- *
- * Since: 0.10.11.
- *
- * MT safe.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-guint
-gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 * sample,
+static guint
+default_commit (GstRingBuffer * buf, guint64 * sample,
     guchar * data, gint in_samples, gint out_samples, gint * accum)
 {
   gint segdone;
@@ -1449,10 +1645,6 @@
   gint inr, outr;
   gboolean reverse;
 
-  if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
-    return in_samples;
-
-  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
   g_return_val_if_fail (buf->data != NULL, -1);
   g_return_val_if_fail (data != NULL, -1);
 
@@ -1571,6 +1763,65 @@
 }
 
 /**
+ * gst_ring_buffer_commit_full:
+ * @buf: the #GstRingBuffer to commit
+ * @sample: the sample position of the data
+ * @data: the data to commit
+ * @in_samples: the number of samples in the data to commit
+ * @out_samples: the number of samples to write to the ringbuffer
+ * @accum: accumulator for rate conversion.
+ *
+ * Commit @in_samples samples pointed to by @data to the ringbuffer @buf. 
+ *
+ * @in_samples and @out_samples define the rate conversion to perform on the the
+ * samples in @data. For negative rates, @out_samples must be negative and
+ * @in_samples positive.
+ *
+ * When @out_samples is positive, the first sample will be written at position @sample
+ * in the ringbuffer. When @out_samples is negative, the last sample will be written to
+ * @sample in reverse order.
+ *
+ * @out_samples does not need to be a multiple of the segment size of the ringbuffer
+ * although it is recommended for optimal performance. 
+ *
+ * @accum will hold a temporary accumulator used in rate conversion and should be
+ * set to 0 when this function is first called. In case the commit operation is
+ * interrupted, one can resume the processing by passing the previously returned
+ * @accum value back to this function.
+ *
+ * MT safe.
+ *
+ * Returns: The number of samples written to the ringbuffer or -1 on error. The
+ * number of samples written can be less than @out_samples when @buf was interrupted
+ * with a flush or stop.
+ *
+ * Since: 0.10.11.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 * sample,
+    guchar * data, gint in_samples, gint out_samples, gint * accum)
+{
+  GstRingBufferClass *rclass;
+  guint res = -1;
+
+  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
+
+  if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
+    return in_samples;
+
+  rclass = GST_RING_BUFFER_GET_CLASS (buf);
+
+  if (G_LIKELY (rclass->commit))
+    res = rclass->commit (buf, sample, data, in_samples, out_samples, accum);
+
+  return res;
+}
+
+/**
  * gst_ring_buffer_commit:
  * @buf: the #GstRingBuffer to commit
  * @sample: the sample position of the data
@@ -1742,10 +1993,6 @@
 
   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 
-  /* buffer must be started */
-  if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
-    return FALSE;
-
   g_return_val_if_fail (buf->data != NULL, FALSE);
   g_return_val_if_fail (segment != NULL, FALSE);
   g_return_val_if_fail (readptr != NULL, FALSE);
@@ -1753,6 +2000,12 @@
 
   data = GST_BUFFER_DATA (buf->data);
 
+  if (buf->callback == NULL) {
+    /* push mode, fail when nothing is started */
+    if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
+      return FALSE;
+  }
+
   /* get the position of the pointer */
   segdone = g_atomic_int_get (&buf->segdone);
 
@@ -1760,14 +2013,14 @@
   *len = buf->spec.segsize;
   *readptr = data + *segment * *len;
 
+  GST_LOG ("prepare read from segment %d (real %d) @%p",
+      *segment, segdone, *readptr);
+
   /* callback to fill the memory with data, for pull based
    * scheduling. */
   if (buf->callback)
     buf->callback (buf, *readptr, *len, buf->cb_data);
 
-  GST_LOG ("prepare read from segment %d (real %d) @%p",
-      *segment, segdone, *readptr);
-
   return TRUE;
 }
 
@@ -1851,9 +2104,9 @@
  * Tell the ringbuffer that it is allowed to start playback when
  * the ringbuffer is filled with samples. 
  *
- * Since: 0.10.6
+ * MT safe.
  *
- * MT safe.
+ * Since: 0.10.6
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1865,5 +2118,5 @@
   g_return_if_fail (GST_IS_RING_BUFFER (buf));
 
   GST_LOG_OBJECT (buf, "may start: %d", allowed);
-  gst_atomic_int_set (&buf->abidata.ABI.may_start, allowed);
+  g_atomic_int_set (&buf->abidata.ABI.may_start, allowed);
 }
--- a/gst_plugins_base/gst-libs/gst/audio/gstringbuffer.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/gstringbuffer.h	Fri Apr 16 15:15:52 2010 +0300
@@ -181,6 +181,8 @@
  * @segtotal: the total number of segments
  * @bytes_per_sample: number of bytes in one sample
  * @silence_sample: bytes representing one sample of silence
+ * @seglatency: number of segments queued in the lower level device,
+ *  defaults to segtotal
  *
  * The structure containing the format specification of the ringbuffer.
  */
@@ -200,17 +202,30 @@
   gint      rate;
   gint      channels;
   
-  guint64  latency_time;        /* the required/actual latency time */
-  guint64  buffer_time;         /* the required/actual time of the buffer */
-  gint     segsize;             /* size of one buffer segment in bytes */
-  gint     segtotal;            /* total number of segments */
-
+  guint64  latency_time;        /* the required/actual latency time, this is the
+				 * actual the size of one segment and the
+				 * minimum possible latency we can achieve. */
+  guint64  buffer_time;         /* the required/actual time of the buffer, this is
+				 * the total size of the buffer and maximum
+				 * latency we can compensate for. */
+  gint     segsize;             /* size of one buffer segment in bytes, this value
+				 * should be chosen to match latency_time as
+				 * well as possible. */
+  gint     segtotal;            /* total number of segments, this value is the
+				 * number of segments of @segsize and should be
+				 * chosen so that it matches buffer_time as
+				 * close as possible. */
   /* out */
   gint     bytes_per_sample;    /* number of bytes of one sample */
   guint8   silence_sample[32];  /* bytes representing silence */
 
+  /* ABI added 0.10.20 */
+  gint     seglatency;          /* number of segments queued in the lower
+				 * level device, defaults to segtotal. */
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  /* gpointer _gst_reserved[GST_PADDING]; */
+  guint8 _gst_reserved[(sizeof (gpointer) * GST_PADDING) - sizeof (gint)];
 };
 
 #define GST_RING_BUFFER_GET_COND(buf) (((GstRingBuffer *)buf)->cond)
@@ -264,6 +279,7 @@
       gboolean           flushing;
       /* ATOMIC */
       gint               may_start;
+      gboolean           active;
     } ABI;
     /* adding + 0 to mark ABI change to be undone later */
     gpointer _gst_reserved[GST_PADDING + 0];
@@ -272,6 +288,7 @@
 
 /**
  * GstRingBufferClass:
+ * @parent_class: parent class
  * @open_device:  open the device, don't set any params or allocate anything
  * @acquire: allocate the resources for the ringbuffer using the given spec
  * @release: free resources of the ringbuffer
@@ -281,6 +298,10 @@
  * @resume: resume processing of samples after pause
  * @stop: stop processing of samples
  * @delay: get number of samples queued in device
+ * @activate: activate the thread that starts pulling and monitoring the
+ * consumed segments in the device. Since 0.10.22
+ * @commit: write samples into the ringbuffer
+ * @clear_all: clear the entire ringbuffer Since 0.10.24
  *
  * The vmethods that subclasses can override to implement the ringbuffer.
  */
@@ -300,8 +321,17 @@
 
   guint        (*delay)        (GstRingBuffer *buf);
 
+  /* ABI added */
+  gboolean     (*activate)     (GstRingBuffer *buf, gboolean active);
+
+  guint        (*commit)       (GstRingBuffer * buf, guint64 *sample,
+                                guchar * data, gint in_samples, 
+                                gint out_samples, gint * accum);
+
+  void         (*clear_all)    (GstRingBuffer * buf);
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING - 3];
 };
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -333,6 +363,14 @@
 #endif
 
 void            gst_ring_buffer_debug_spec_buff (GstRingBufferSpec *spec);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean        gst_ring_buffer_convert         (GstRingBuffer * buf, GstFormat src_fmt,
+                                                 gint64 src_val, GstFormat dest_fmt,
+						 gint64 * dest_val);
 
 /* device state */
 #ifdef __SYMBIAN32__
@@ -370,6 +408,18 @@
 
 gboolean        gst_ring_buffer_is_acquired     (GstRingBuffer *buf);
 
+/* activating */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean        gst_ring_buffer_activate        (GstRingBuffer *buf, gboolean active);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean        gst_ring_buffer_is_active       (GstRingBuffer *buf);
+
 /* flushing */
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst-libs/gst/audio/make_filter	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#!/bin/sh
-
-LANG=C
-LC_COLLATE=C
-export LANG
-export LC_COLLATE
-
-Template=$1;
-srcfile=$2;
-
-if test x"$1" = x ; then
-	echo "$0 Objectname [srcfile]\n";
-	echo "  creates gstobjectname.{c,h} implementing GstObjectname,\n";
-	echo "  subclassing GstAudiofilter.\n";
-	exit 1;
-fi
-
-if test x"$2" = x ; then
-	srcfile="gstaudiofiltertemplate.c"
-fi
-
-id=`echo '$Id: make_filter,v 1.3 2004-04-19 22:51:56 ds Exp $' | sed \
-	-e 's/\$I[d]: \([^$]*\)\$/\1/g'`
-echo $id
-
-TEMPLATE=`echo $Template | tr [:lower:] [:upper:]`
-template=`echo $Template | tr [:upper:] [:lower:]`
-
-echo TEMPLATE $TEMPLATE
-echo template $template
-
-# remember to break up the Id: in the line below
-sed \
-	-e 's/gstaudiofiltertemplate\.c/SOURCEFILE/g' \
-	-e "s/AudiofilterTemplate/$Template/g" \
-	-e "s/audiofiltertemplate/$template/g" \
-	-e "s/VIDEOFILTERTEMPLATE/$TEMPLATE/g" \
-	-e 's/\$I[d]: \([^$]*\)\$/\1/g' \
-	-e 's/SOURCEFILE/gstaudiofiltertemplate\.c/g' \
-	-e "s%MAKEFILTERVERSION%$id%g" \
-	$srcfile >gst$template.c.tmp && mv gst$template.c.tmp gst$template.c
-
--- a/gst_plugins_base/gst-libs/gst/audio/multichannel-enumtypes.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-#include "multichannel-enumtypes.h"
-
-#include "multichannel.h"
-
-/* enumerations from "multichannel.h" */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_audio_channel_position_get_type (void)
-{
-  static GType etype = 0;
-  if (etype == 0) {
-    static const GEnumValue values[] = {
-      { GST_AUDIO_CHANNEL_POSITION_INVALID, "GST_AUDIO_CHANNEL_POSITION_INVALID", "invalid" },
-      { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO", "front-mono" },
-      { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT", "front-left" },
-      { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT", "front-right" },
-      { GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, "GST_AUDIO_CHANNEL_POSITION_REAR_CENTER", "rear-center" },
-      { GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, "GST_AUDIO_CHANNEL_POSITION_REAR_LEFT", "rear-left" },
-      { GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, "GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT", "rear-right" },
-      { GST_AUDIO_CHANNEL_POSITION_LFE, "GST_AUDIO_CHANNEL_POSITION_LFE", "lfe" },
-      { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, "GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER", "front-center" },
-      { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER", "front-left-of-center" },
-      { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER", "front-right-of-center" },
-      { GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, "GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT", "side-left" },
-      { GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, "GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT", "side-right" },
-      { GST_AUDIO_CHANNEL_POSITION_NONE, "GST_AUDIO_CHANNEL_POSITION_NONE", "none" },
-      { GST_AUDIO_CHANNEL_POSITION_NUM, "GST_AUDIO_CHANNEL_POSITION_NUM", "num" },
-      { 0, NULL, NULL }
-    };
-    etype = g_enum_register_static ("GstAudioChannelPosition", values);
-  }
-  return etype;
-}
-
-/* Generated data ends here */
-
--- a/gst_plugins_base/gst-libs/gst/audio/multichannel-enumtypes.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-#ifndef __GST_AUDIO_ENUM_TYPES_H__
-#define __GST_AUDIO_ENUM_TYPES_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* enumerations from "multichannel.h" */
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-GType gst_audio_channel_position_get_type (void);
-#define GST_TYPE_AUDIO_CHANNEL_POSITION (gst_audio_channel_position_get_type())
-G_END_DECLS
-
-#endif /* __GST_AUDIO_ENUM_TYPES_H__ */
-
-/* Generated data ends here */
-
--- a/gst_plugins_base/gst-libs/gst/audio/multichannel.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/multichannel.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,32 +16,53 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:gstmultichannel
+ * @short_description: Support for multichannel audio elements
+ *
+ * This module contains some helper functions and a enum to work with
+ * multichannel audio.
+ */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "multichannel.h"
 
 #define GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME "channel-positions"
 
-/*
- * This function checks if basic assumptions apply:
- *  - does each position occur at most once?
- *  - do conflicting positions occur?
- *     + front_mono vs. front_left/right
- *     + front_center vs. front_left/right_of_center
- *     + rear_center vs. rear_left/right
- * It also adds some hacks that 0.8.x needs for compatibility:
- *  - if channels == 1, are we really mono?
- *  - if channels == 2, are we really stereo?
+/**
+ * gst_audio_check_channel_positions:
+ * @pos: An array of #GstAudioChannelPosition.
+ * @channels: The number of elements in @pos.
+ *
+ * This functions checks if the given channel positions are valid. Channel
+ * positions are valid if:
+ * <itemizedlist>
+ *   <listitem><para>No channel positions appears twice or all positions are %GST_AUDIO_CHANNEL_POSITION_NONE.
+ *   </para></listitem>
+ *   <listitem><para>Either all or none of the channel positions are %GST_AUDIO_CHANNEL_POSITION_NONE.
+ *   </para></listitem>
+ *   <listitem><para>%GST_AUDIO_CHANNEL_POSITION_FRONT_MONO and %GST_AUDIO_CHANNEL_POSITION_LEFT or %GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT don't appear together in the given positions.
+ *   </para></listitem>
+ * </itemizedlist>
+ *
+ * Since: 0.10.20
+ *
+ * Returns: %TRUE if the given channel positions are valid
+ * and %FALSE otherwise.
  */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-static gboolean
+gboolean
 gst_audio_check_channel_positions (const GstAudioChannelPosition * pos,
-    gint channels)
+    guint channels)
 {
   gint i, n;
+
   const struct
   {
     const GstAudioChannelPosition pos1[2];
@@ -51,27 +72,18 @@
     { {
     GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
             GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}},
-        /* front center: 2 <-> 1 */
-    { {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}},
-        /* rear: 2 <-> 1 */
-    { {
-    GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-            GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
-    GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, { {
     GST_AUDIO_CHANNEL_POSITION_INVALID}}
   };
 
-  g_assert (pos != NULL && channels > 0);
+  g_return_val_if_fail (pos != NULL, FALSE);
+  g_return_val_if_fail (channels > 0, FALSE);
 
   /* check for invalid channel positions */
   for (n = 0; n < channels; n++) {
     if (pos[n] <= GST_AUDIO_CHANNEL_POSITION_INVALID ||
         pos[n] >= GST_AUDIO_CHANNEL_POSITION_NUM) {
-      g_warning ("Channel position %d for channel %d is invalid", pos[n], n);
+      GST_WARNING ("Channel position %d for channel %d is invalid", pos[n], n);
       return FALSE;
     }
   }
@@ -82,7 +94,7 @@
   if (pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
     for (n = 1; n < channels; ++n) {
       if (pos[n] != GST_AUDIO_CHANNEL_POSITION_NONE) {
-        g_warning ("Either all channel positions must be defined, or all "
+        GST_WARNING ("Either all channel positions must be defined, or all "
             "be set to NONE, having only some defined is not allowed");
         return FALSE;
       }
@@ -103,13 +115,13 @@
 
     /* NONE may not occur mixed with other channel positions */
     if (i == GST_AUDIO_CHANNEL_POSITION_NONE && count > 0) {
-      g_warning ("Either all channel positions must be defined, or all "
+      GST_WARNING ("Either all channel positions must be defined, or all "
           "be set to NONE, having only some defined is not allowed");
       return FALSE;
     }
 
     if (count > 1) {
-      g_warning ("Channel position %d occurred %d times, not allowed",
+      GST_WARNING ("Channel position %d occurred %d times, not allowed",
           i, count);
       return FALSE;
     }
@@ -127,21 +139,12 @@
     }
 
     if (found1 && found2) {
-      g_warning ("Found conflicting channel positions %d/%d and %d",
+      GST_WARNING ("Found conflicting channel positions %d/%d and %d",
           conf[i].pos1[0], conf[i].pos1[1], conf[i].pos2[0]);
       return FALSE;
     }
   }
 
-  /* Throw warning if we encounter an unusual 2-channel configuration,
-   * at least until someone finds a reason why we should not */
-  if (channels == 2 && (pos[0] != GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT ||
-          pos[1] != GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT)) {
-    g_warning ("channels=2 implies stereo, but channel positions are "
-        "< %d, %d>", pos[0], pos[1]);
-    return FALSE;
-  }
-
   return TRUE;
 }
 
@@ -236,9 +239,13 @@
 gst_audio_get_channel_positions (GstStructure * str)
 {
   GstAudioChannelPosition *pos;
+
   gint channels, n;
+
   const GValue *pos_val_arr, *pos_val_entry;
+
   gboolean res;
+
   GType t;
 
   /* get number of channels, general type checkups */
@@ -316,6 +323,7 @@
   GValue pos_val_arr = { 0 }, pos_val_entry = {
   0};
   gint channels, n;
+
   gboolean res;
 
   /* get number of channels, checkups */
@@ -383,11 +391,6 @@
   g_return_if_fail (res);
   g_return_if_fail (channels > 0);
 
-  /* 0.8.x: channels=1 or channels=2 is mono/stereo, no positions needed
-   * there (we discard them anyway) */
-  if (channels == 1 || channels == 2)
-    return;
-
   /* create the array of lists */
   g_value_init (&pos_val_arr, GST_TYPE_ARRAY);
   g_value_init (&pos_val_entry, GST_TYPE_AUDIO_CHANNEL_POSITION);
@@ -417,6 +420,7 @@
     const GstAudioChannelPosition * pos, gint num_positions)
 {
   GstCaps *caps = gst_caps_new_empty ();
+
   const GValue *chan_val;
 
   chan_val = gst_structure_get_value (str, "channels");
@@ -424,6 +428,7 @@
     gst_audio_set_structure_channel_positions_list (str, pos, num_positions);
   } else if (G_VALUE_TYPE (chan_val) == GST_TYPE_LIST) {
     gint size;
+
     const GValue *sub_val;
 
     size = gst_value_list_get_size (chan_val);
@@ -526,9 +531,13 @@
 gst_audio_fixate_channel_positions (GstStructure * str)
 {
   GstAudioChannelPosition *pos;
+
   gint channels, n, num_unfixed = 0, i, c;
+
   const GValue *pos_val_arr, *pos_val_entry, *pos_val;
+
   gboolean res, is_stereo = TRUE;
+
   GType t;
 
   /*
@@ -543,19 +552,20 @@
     const GstAudioChannelPosition pos2[1];
   } conf[] = {
     /* front: mono <-> stereo */
-    { {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+    {
+      {
+      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
             GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}},
-        /* front center: 2 <-> 1 */
-    { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, { {
     GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
             GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}},
-        /* rear: 2 <-> 1 */
-    { {
+    GST_AUDIO_CHANNEL_POSITION_INVALID}}, { {
+    GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}}, { {
     GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
             GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
+    GST_AUDIO_CHANNEL_POSITION_INVALID}}, { {
+    GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, {
     GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { {
     GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, {
     GST_AUDIO_CHANNEL_POSITION_LFE}}, { {
--- a/gst_plugins_base/gst-libs/gst/audio/multichannel.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/audio/multichannel.h	Fri Apr 16 15:15:52 2010 +0300
@@ -21,7 +21,7 @@
 #define __GST_AUDIO_MULTICHANNEL_H__
 
 #include <gst/audio/audio.h>
-#include <gst/audio/multichannel-enumtypes.h>
+#include <gst/audio/audio-enumtypes.h>
 
 G_BEGIN_DECLS
 
@@ -109,6 +109,12 @@
 
 GstAudioChannelPosition *
         gst_audio_fixate_channel_positions (GstStructure *str);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_audio_check_channel_positions (const GstAudioChannelPosition * pos, guint channels);
 
 G_END_DECLS
 
--- a/gst_plugins_base/gst-libs/gst/audio/testchannels.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/* GStreamer Multichannel Test
- * (c) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gst/gst.h>
-
-#include <multichannel.c>
-#include <multichannel-enumtypes.c>
-
-gint
-main (gint argc, gchar * argv[])
-{
-  gchar *str;
-  GstCaps *caps;
-  GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
-  };
-
-  /* register multichannel type */
-  gst_init (&argc, &argv);
-  gst_audio_channel_position_get_type ();
-
-  /* test some caps-string conversions */
-  caps = gst_caps_new_simple ("audio/x-raw-int",
-      "channels", G_TYPE_INT, 2, NULL);
-  str = gst_caps_to_string (caps);
-  g_print ("Test caps #1: %s\n", str);
-  g_free (str);
-  gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
-  str = gst_caps_to_string (caps);
-  g_print ("Test caps #2: %s\n", str);
-  g_free (str);
-  gst_caps_unref (caps);
-
-  return 0;
-}
--- a/gst_plugins_base/gst-libs/gst/cdda/base64.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/* --------------------------------------------------------------------------
-
-   MusicBrainz -- The Internet music metadatabase
-
-   Copyright (C) 2000 Robert Kaye
-   
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 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
-   Lesser General Public License for more details.
-   
-   You should have received a copy of the GNU Lesser 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
-
-     $Id: base64.c,v 1.1 2005-12-28 18:06:50 tpm Exp $
-
-----------------------------------------------------------------------------*/
-/*
- * Program:	RFC-822 routines (originally from SMTP)
- *
- * Author:	Mark Crispin
- *		Networks and Distributed Computing
- *		Computing & Communications
- *		University of Washington
- *		Administration Building, AG-44
- *		Seattle, WA  98195
- *		Internet: MRC@CAC.Washington.EDU
- *
- * Date:	27 July 1988
- * Last Edited:	10 September 1998
- *
- * Sponsorship:	The original version of this work was developed in the
- *		Symbolic Systems Resources Group of the Knowledge Systems
- *		Laboratory at Stanford University in 1987-88, and was funded
- *		by the Biomedical Research Technology Program of the National
- *		Institutes of Health under grant number RR-00785.
- *
- * Original version Copyright 1988 by The Leland Stanford Junior University
- * Copyright 1998 by the University of Washington
- *
- *  Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notices appear in all copies and that both the
- * above copyright notices and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington or The
- * Leland Stanford Junior University not be used in advertising or publicity
- * pertaining to distribution of the software without specific, written prior
- * permission.  This software is made available "as is", and
- * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
- * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
- * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
- * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <time.h>
-#include <stdlib.h>
-
-#include "base64.h"
-
-/* NOTE: This is not true RFC822 anymore. The use of the characters
-   '/', '+', and '=' is no bueno when the ID will be used as part of a URL.
-   '_', '.', and '-' have been used instead
-*/
-
-/* Convert binary contents to BASE64
- * Accepts: source
- *	    length of source
- *	    pointer to return destination length
- * Returns: destination as BASE64
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-unsigned char *
-rfc822_binary (void *src, unsigned long srcl, unsigned long *len)
-{
-  unsigned char *ret, *d;
-  unsigned char *s = (unsigned char *) src;
-  char *v = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
-  unsigned long i = ((srcl + 2) / 3) * 4;
-
-  *len = i += 2 * ((i / 60) + 1);
-  d = ret = (unsigned char *) malloc ((size_t)++ i);
-  for (i = 0; srcl; s += 3) {   /* process tuplets */
-    *d++ = v[s[0] >> 2];        /* byte 1: high 6 bits (1) */
-    /* byte 2: low 2 bits (1), high 4 bits (2) */
-    *d++ = v[((s[0] << 4) + (--srcl ? (s[1] >> 4) : 0)) & 0x3f];
-    /* byte 3: low 4 bits (2), high 2 bits (3) */
-    *d++ = srcl ? v[((s[1] << 2) + (--srcl ? (s[2] >> 6) : 0)) & 0x3f] : '-';
-    /* byte 4: low 6 bits (3) */
-    *d++ = srcl ? v[s[2] & 0x3f] : '-';
-    if (srcl)
-      srcl--;                   /* count third character if processed */
-    if ((++i) == 15) {          /* output 60 characters? */
-      i = 0;                    /* restart line break count, insert CRLF */
-      *d++ = '\015';
-      *d++ = '\012';
-    }
-  }
-  *d = '\0';                    /* tie off string */
-
-  return ret;                   /* return the resulting string */
-}
--- a/gst_plugins_base/gst-libs/gst/cdda/base64.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/* --------------------------------------------------------------------------
-
-   MusicBrainz -- The Internet music metadatabase
-
-   Copyright (C) 2000 Robert Kaye
-   
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 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
-   Lesser General Public License for more details.
-   
-   You should have received a copy of the GNU Lesser 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
-
-     $Id: base64.h,v 1.2 2007-12-13 10:10:35 tpm Exp $
-
-----------------------------------------------------------------------------*/
-/*
- * Program:	RFC-822 routines (originally from SMTP)
- *
- * Author:	Mark Crispin
- *		Networks and Distributed Computing
- *		Computing & Communications
- *		University of Washington
- *		Administration Building, AG-44
- *		Seattle, WA  98195
- *		Internet: MRC@CAC.Washington.EDU
- *
- * Date:	27 July 1988
- * Last Edited:	10 September 1998
- *
- * Sponsorship:	The original version of this work was developed in the
- *		Symbolic Systems Resources Group of the Knowledge Systems
- *		Laboratory at Stanford University in 1987-88, and was funded
- *		by the Biomedical Research Technology Program of the National
- *		Institutes of Health under grant number RR-00785.
- *
- * Original version Copyright 1988 by The Leland Stanford Junior University
- * Copyright 1998 by the University of Washington
- *
- *  Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notices appear in all copies and that both the
- * above copyright notices and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington or The
- * Leland Stanford Junior University not be used in advertising or publicity
- * pertaining to distribution of the software without specific, written prior
- * permission.  This software is made available "as is", and
- * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
- * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
- * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
- * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifndef __GST_CDDA_BASE64_H__
-#define __GST_CDDA_BASE64_H__
-
-#define rfc822_binary  __gst_cdda_rfc822_binary
-
-unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len);
-
-#endif /* __GST_CDDA_BASE64_H__ */
-
--- a/gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -81,7 +81,6 @@
  * </refsect2>
  */
 
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -92,10 +91,6 @@
 #include "gstcddabasesrc.h"
 #include "gst/gst-i18n-plugin.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_cdda_base_src_debug);
 #define GST_CAT_DEFAULT gst_cdda_base_src_debug
 
@@ -109,8 +104,6 @@
 #define TIME_INTERVAL_FROM_SECTORS(sectors)  ((SAMPLES_PER_SECTOR * sectors * GST_SECOND) / 44100)
 #define SECTORS_FROM_TIME_INTERVAL(dtime)    (dtime * 44100 / (SAMPLES_PER_SECTOR * GST_SECOND))
 
-#define GST_TYPE_CDDA_BASE_SRC_MODE          (gst_cdda_base_src_mode_get_type ())
-
 enum
 {
   ARG_0,
@@ -164,8 +157,12 @@
 /* our two formats */
 static GstFormat track_format;
 static GstFormat sector_format;
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-static GType
+
+GType
 gst_cdda_base_src_mode_get_type (void)
 {
   static GType mode_type;       /* 0 */
@@ -226,14 +223,15 @@
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE,
       g_param_spec_string ("device", "Device", "CD device location",
-          NULL, G_PARAM_READWRITE));
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE,
       g_param_spec_enum ("mode", "Mode", "Mode", GST_TYPE_CDDA_BASE_SRC_MODE,
-          GST_CDDA_BASE_SRC_MODE_NORMAL, G_PARAM_READWRITE));
+          GST_CDDA_BASE_SRC_MODE_NORMAL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TRACK,
       g_param_spec_uint ("track", "Track", "Track", 1, 99, 1,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 #if 0
   /* Do we really need this toc adjustment stuff as properties? does the user
@@ -244,12 +242,13 @@
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_OFFSET,
       g_param_spec_int ("toc-offset", "Table of contents offset",
           "Add <n> sectors to the values reported", G_MININT, G_MAXINT, 0,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_BIAS,
       g_param_spec_boolean ("toc-bias", "Table of contents bias",
           "Assume that the beginning offset of track 1 as reported in the TOC "
           "will be addressed as LBA 0.  Necessary for some Toshiba drives to "
-          "get track boundaries", FALSE, G_PARAM_READWRITE));
+          "get track boundaries", FALSE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 #endif
 
   element_class->set_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_set_index);
@@ -880,7 +879,6 @@
     }
     default:{
       GST_LOG_OBJECT (src, "let base class handle event");
-      event = gst_event_ref (event);
       ret = GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
       break;
     }
@@ -1034,7 +1032,7 @@
   if (src->num_tracks > 0) {
     guint end_of_previous_track = src->tracks[src->num_tracks - 1].end;
 
-    if (track->start < end_of_previous_track) {
+    if (track->start <= end_of_previous_track) {
       GST_WARNING ("track %2u overlaps with previous tracks", track->num);
       return FALSE;
     }
@@ -1091,36 +1089,35 @@
   return ret;
 }
 
-#include "base64.h"
-#include "sha1.h"
-
 static void
 gst_cddabasesrc_calculate_musicbrainz_discid (GstCddaBaseSrc * src)
 {
   GString *s;
-  SHA_INFO sha;
-  guchar digest[20], *ptr;
+  GChecksum *sha;
+  guchar digest[20];
+  gchar *ptr;
   gchar tmp[9];
   gulong i;
   guint leadout_sector;
+  gsize digest_len;
 
   s = g_string_new (NULL);
 
   leadout_sector = src->tracks[src->num_tracks - 1].end + 1 + CD_MSF_OFFSET;
 
   /* generate SHA digest */
-  sha_init (&sha);
+  sha = g_checksum_new (G_CHECKSUM_SHA1);
   g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[0].num);
   g_string_append_printf (s, "%02X", src->tracks[0].num);
-  sha_update (&sha, (SHA_BYTE *) tmp, 2);
+  g_checksum_update (sha, (guchar *) tmp, 2);
 
   g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[src->num_tracks - 1].num);
   g_string_append_printf (s, " %02X", src->tracks[src->num_tracks - 1].num);
-  sha_update (&sha, (SHA_BYTE *) tmp, 2);
+  g_checksum_update (sha, (guchar *) tmp, 2);
 
   g_snprintf (tmp, sizeof (tmp), "%08X", leadout_sector);
   g_string_append_printf (s, " %08X", leadout_sector);
-  sha_update (&sha, (SHA_BYTE *) tmp, 8);
+  g_checksum_update (sha, (guchar *) tmp, 8);
 
   for (i = 0; i < 99; i++) {
     if (i < src->num_tracks) {
@@ -1128,21 +1125,36 @@
 
       g_snprintf (tmp, sizeof (tmp), "%08X", frame_offset);
       g_string_append_printf (s, " %08X", frame_offset);
-      sha_update (&sha, (SHA_BYTE *) tmp, 8);
+      g_checksum_update (sha, (guchar *) tmp, 8);
     } else {
-      sha_update (&sha, (SHA_BYTE *) "00000000", 8);
+      g_checksum_update (sha, (guchar *) "00000000", 8);
     }
   }
-  sha_final (digest, &sha);
+  digest_len = 20;
+  g_checksum_get_digest (sha, (guint8 *) & digest, &digest_len);
 
   /* re-encode to base64 */
-  ptr = rfc822_binary (digest, 20, &i);
+  ptr = g_base64_encode (digest, digest_len);
+  g_checksum_free (sha);
+  i = strlen (ptr);
 
   g_assert (i < sizeof (src->mb_discid) + 1);
   memcpy (src->mb_discid, ptr, i);
   src->mb_discid[i] = '\0';
   free (ptr);
 
+  /* Replace '/', '+' and '=' by '_', '.' and '-' as specified on
+   * http://musicbrainz.org/doc/DiscIDCalculation
+   */
+  for (ptr = src->mb_discid; *ptr != '\0'; ptr++) {
+    if (*ptr == '/')
+      *ptr = '_';
+    else if (*ptr == '+')
+      *ptr = '.';
+    else if (*ptr == '=')
+      *ptr = '-';
+  }
+
   GST_DEBUG_OBJECT (src, "musicbrainz-discid      = %s", src->mb_discid);
   GST_DEBUG_OBJECT (src, "musicbrainz-discid-full = %s", s->str);
 
@@ -1268,7 +1280,7 @@
         GST_FORMAT_TIME, &duration);
 
     gst_tag_list_add (src->tracks[i].tags,
-        GST_TAG_MERGE_REPLACE_ALL,
+        GST_TAG_MERGE_REPLACE,
         GST_TAG_TRACK_NUMBER, i + 1,
         GST_TAG_TRACK_COUNT, src->num_tracks, GST_TAG_DURATION, duration, NULL);
   }
@@ -1282,7 +1294,7 @@
    * gst_tag_list_get_value_index() rather than use tag names incl.
    * the track number ?? *////////////////////////////////////////
 
-  gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE_ALL,
+  gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE,
       GST_TAG_TRACK_COUNT, src->num_tracks, NULL);
 #if 0
   for (i = 0; i < src->num_tracks; ++i) {
@@ -1511,10 +1523,10 @@
 
   switch (src->mode) {
     case GST_CDDA_BASE_SRC_MODE_NORMAL:
-      eos = (src->cur_sector >= src->tracks[src->cur_track].end);
+      eos = (src->cur_sector > src->tracks[src->cur_track].end);
       break;
     case GST_CDDA_BASE_SRC_MODE_CONTINUOUS:
-      eos = (src->cur_sector >= src->tracks[src->num_tracks - 1].end);
+      eos = (src->cur_sector > src->tracks[src->num_tracks - 1].end);
       src->cur_track = gst_cdda_base_src_get_track_from_sector (src,
           src->cur_sector);
       break;
--- a/gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -54,6 +54,8 @@
   GST_CDDA_BASE_SRC_MODE_CONTINUOUS       /* stream = whole disc */
 } GstCddaBaseSrcMode;
 
+#define GST_TYPE_CDDA_BASE_SRC_MODE          (gst_cdda_base_src_mode_get_type ())
+
 /**
  * GstCddaBaseSrcTrack:
  * @is_audio: Whether this is an audio track
@@ -142,6 +144,11 @@
 IMPORT_C
 #endif
 
+GType    gst_cdda_base_src_mode_get_type (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 gboolean gst_cdda_base_src_add_track (GstCddaBaseSrc      * src,
                                       GstCddaBaseSrcTrack * track);
--- a/gst_plugins_base/gst-libs/gst/cdda/sha1.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,450 +0,0 @@
-/* (PD) 2001 The Bitzi Corporation
- * Please see file COPYING or http://bitzi.com/publicdomain 
- * for more info.
- *
- * NIST Secure Hash Algorithm 
- * heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> 
- * from Peter C. Gutmann's implementation as found in 
- * Applied Cryptography by Bruce Schneier 
- * Further modifications to include the "UNRAVEL" stuff, below 
- *
- * This code is in the public domain 
- *
- * $Id: sha1.c,v 1.2 2008-02-27 10:42:08 slomo Exp $
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <glib.h>
-#define SHA_BYTE_ORDER G_BYTE_ORDER
-
-#include <string.h>
-#include "sha1.h"
-
-/* UNRAVEL should be fastest & biggest */
-/* UNROLL_LOOPS should be just as big, but slightly slower */
-/* both undefined should be smallest and slowest */
-
-#define UNRAVEL
-/* #define UNROLL_LOOPS */
-
-/* SHA f()-functions */
-
-#define f1(x,y,z)	((x & y) | (~x & z))
-#define f2(x,y,z)	(x ^ y ^ z)
-#define f3(x,y,z)	((x & y) | (x & z) | (y & z))
-#define f4(x,y,z)	(x ^ y ^ z)
-
-/* SHA constants */
-
-#define CONST1		0x5a827999L
-#define CONST2		0x6ed9eba1L
-#define CONST3		0x8f1bbcdcL
-#define CONST4		0xca62c1d6L
-
-/* truncate to 32 bits -- should be a null op on 32-bit machines */
-
-#define T32(x)	((x) & 0xffffffffL)
-
-/* 32-bit rotate */
-
-#define R32(x,n)	T32(((x << n) | (x >> (32 - n))))
-
-/* the generic case, for when the overall rotation is not unraveled */
-
-#define FG(n)	\
-    T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n);	\
-    E = D; D = C; C = R32(B,30); B = A; A = T
-
-/* specific cases, for when the overall rotation is unraveled */
-
-#define FA(n)	\
-    T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
-
-#define FB(n)	\
-    E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
-
-#define FC(n)	\
-    D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
-
-#define FD(n)	\
-    C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
-
-#define FE(n)	\
-    B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
-
-#define FT(n)	\
-    A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
-
-/* do SHA transformation */
-
-static void
-sha_transform (SHA_INFO * sha_info)
-{
-  int i;
-  SHA_BYTE *dp;
-  SHA_LONG T, A, B, C, D, E, W[80], *WP;
-
-  dp = sha_info->data;
-
-/*
-the following makes sure that at least one code block below is
-traversed or an error is reported, without the necessity for nested
-preprocessor if/else/endif blocks, which are a great pain in the
-nether regions of the anatomy...
-*/
-#undef SWAP_DONE
-
-#if (SHA_BYTE_ORDER == 1234)
-#define SWAP_DONE
-  for (i = 0; i < 16; ++i) {
-    memcpy (&T, dp, sizeof (SHA_LONG));
-    dp += 4;
-    W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
-        ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
-  }
-#endif /* SHA_BYTE_ORDER == 1234 */
-
-#if (SHA_BYTE_ORDER == 4321)
-#define SWAP_DONE
-  for (i = 0; i < 16; ++i) {
-    memcpy (&T, dp, sizeof (SHA_LONG));
-    dp += 4;
-    W[i] = T32 (T);
-  }
-#endif /* SHA_BYTE_ORDER == 4321 */
-
-#if (SHA_BYTE_ORDER == 12345678)
-#define SWAP_DONE
-  for (i = 0; i < 16; i += 2) {
-    memcpy (&T, dp, sizeof (SHA_LONG));
-    dp += 8;
-    W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
-        ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
-    T >>= 32;
-    W[i + 1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
-        ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
-  }
-#endif /* SHA_BYTE_ORDER == 12345678 */
-
-#if (SHA_BYTE_ORDER == 87654321)
-#define SWAP_DONE
-  for (i = 0; i < 16; i += 2) {
-    memcpy (&T, dp, sizeof (SHA_LONG));
-    dp += 8;
-    W[i] = T32 (T >> 32);
-    W[i + 1] = T32 (T);
-  }
-#endif /* SHA_BYTE_ORDER == 87654321 */
-
-#ifndef SWAP_DONE
-#error Unknown byte order -- you need to add code here
-#endif /* SWAP_DONE */
-
-  for (i = 16; i < 80; ++i) {
-    W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
-#if (SHA_VERSION == 1)
-    W[i] = R32 (W[i], 1);
-#endif /* SHA_VERSION */
-  }
-  A = sha_info->digest[0];
-  B = sha_info->digest[1];
-  C = sha_info->digest[2];
-  D = sha_info->digest[3];
-  E = sha_info->digest[4];
-  WP = W;
-#ifdef UNRAVEL
-  FA (1);
-  FB (1);
-  FC (1);
-  FD (1);
-  FE (1);
-  FT (1);
-  FA (1);
-  FB (1);
-  FC (1);
-  FD (1);
-  FE (1);
-  FT (1);
-  FA (1);
-  FB (1);
-  FC (1);
-  FD (1);
-  FE (1);
-  FT (1);
-  FA (1);
-  FB (1);
-  FC (2);
-  FD (2);
-  FE (2);
-  FT (2);
-  FA (2);
-  FB (2);
-  FC (2);
-  FD (2);
-  FE (2);
-  FT (2);
-  FA (2);
-  FB (2);
-  FC (2);
-  FD (2);
-  FE (2);
-  FT (2);
-  FA (2);
-  FB (2);
-  FC (2);
-  FD (2);
-  FE (3);
-  FT (3);
-  FA (3);
-  FB (3);
-  FC (3);
-  FD (3);
-  FE (3);
-  FT (3);
-  FA (3);
-  FB (3);
-  FC (3);
-  FD (3);
-  FE (3);
-  FT (3);
-  FA (3);
-  FB (3);
-  FC (3);
-  FD (3);
-  FE (3);
-  FT (3);
-  FA (4);
-  FB (4);
-  FC (4);
-  FD (4);
-  FE (4);
-  FT (4);
-  FA (4);
-  FB (4);
-  FC (4);
-  FD (4);
-  FE (4);
-  FT (4);
-  FA (4);
-  FB (4);
-  FC (4);
-  FD (4);
-  FE (4);
-  FT (4);
-  FA (4);
-  FB (4);
-  sha_info->digest[0] = T32 (sha_info->digest[0] + E);
-  sha_info->digest[1] = T32 (sha_info->digest[1] + T);
-  sha_info->digest[2] = T32 (sha_info->digest[2] + A);
-  sha_info->digest[3] = T32 (sha_info->digest[3] + B);
-  sha_info->digest[4] = T32 (sha_info->digest[4] + C);
-#else /* !UNRAVEL */
-#ifdef UNROLL_LOOPS
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (1);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (2);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (3);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-  FG (4);
-#else /* !UNROLL_LOOPS */
-  for (i = 0; i < 20; ++i) {
-    FG (1);
-  }
-  for (i = 20; i < 40; ++i) {
-    FG (2);
-  }
-  for (i = 40; i < 60; ++i) {
-    FG (3);
-  }
-  for (i = 60; i < 80; ++i) {
-    FG (4);
-  }
-#endif /* !UNROLL_LOOPS */
-  sha_info->digest[0] = T32 (sha_info->digest[0] + A);
-  sha_info->digest[1] = T32 (sha_info->digest[1] + B);
-  sha_info->digest[2] = T32 (sha_info->digest[2] + C);
-  sha_info->digest[3] = T32 (sha_info->digest[3] + D);
-  sha_info->digest[4] = T32 (sha_info->digest[4] + E);
-#endif /* !UNRAVEL */
-}
-
-/* initialize the SHA digest */
-
-void
-sha_init (SHA_INFO * sha_info)
-{
-  sha_info->digest[0] = 0x67452301L;
-  sha_info->digest[1] = 0xefcdab89L;
-  sha_info->digest[2] = 0x98badcfeL;
-  sha_info->digest[3] = 0x10325476L;
-  sha_info->digest[4] = 0xc3d2e1f0L;
-  sha_info->count_lo = 0L;
-  sha_info->count_hi = 0L;
-  sha_info->local = 0;
-}
-
-/* update the SHA digest */
-
-void
-sha_update (SHA_INFO * sha_info, SHA_BYTE * buffer, int count)
-{
-  int i;
-  SHA_LONG clo;
-
-  clo = T32 (sha_info->count_lo + ((SHA_LONG) count << 3));
-  if (clo < sha_info->count_lo) {
-    ++sha_info->count_hi;
-  }
-  sha_info->count_lo = clo;
-  sha_info->count_hi += (SHA_LONG) count >> 29;
-  if (sha_info->local) {
-    i = SHA_BLOCKSIZE - sha_info->local;
-    if (i > count) {
-      i = count;
-    }
-    memcpy (((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
-    count -= i;
-    buffer += i;
-    sha_info->local += i;
-    if (sha_info->local == SHA_BLOCKSIZE) {
-      sha_transform (sha_info);
-    } else {
-      return;
-    }
-  }
-  while (count >= SHA_BLOCKSIZE) {
-    memcpy (sha_info->data, buffer, SHA_BLOCKSIZE);
-    buffer += SHA_BLOCKSIZE;
-    count -= SHA_BLOCKSIZE;
-    sha_transform (sha_info);
-  }
-  memcpy (sha_info->data, buffer, count);
-  sha_info->local = count;
-}
-
-/* finish computing the SHA digest */
-
-void
-sha_final (unsigned char digest[20], SHA_INFO * sha_info)
-{
-  int count;
-  SHA_LONG lo_bit_count, hi_bit_count;
-
-  lo_bit_count = sha_info->count_lo;
-  hi_bit_count = sha_info->count_hi;
-  count = (int) ((lo_bit_count >> 3) & 0x3f);
-  ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
-  if (count > SHA_BLOCKSIZE - 8) {
-    memset (((SHA_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
-    sha_transform (sha_info);
-    memset ((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
-  } else {
-    memset (((SHA_BYTE *) sha_info->data) + count, 0,
-        SHA_BLOCKSIZE - 8 - count);
-  }
-  sha_info->data[56] = (unsigned char) ((hi_bit_count >> 24) & 0xff);
-  sha_info->data[57] = (unsigned char) ((hi_bit_count >> 16) & 0xff);
-  sha_info->data[58] = (unsigned char) ((hi_bit_count >> 8) & 0xff);
-  sha_info->data[59] = (unsigned char) ((hi_bit_count >> 0) & 0xff);
-  sha_info->data[60] = (unsigned char) ((lo_bit_count >> 24) & 0xff);
-  sha_info->data[61] = (unsigned char) ((lo_bit_count >> 16) & 0xff);
-  sha_info->data[62] = (unsigned char) ((lo_bit_count >> 8) & 0xff);
-  sha_info->data[63] = (unsigned char) ((lo_bit_count >> 0) & 0xff);
-  sha_transform (sha_info);
-  digest[0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
-  digest[1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
-  digest[2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
-  digest[3] = (unsigned char) ((sha_info->digest[0]) & 0xff);
-  digest[4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
-  digest[5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
-  digest[6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
-  digest[7] = (unsigned char) ((sha_info->digest[1]) & 0xff);
-  digest[8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
-  digest[9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
-  digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
-  digest[11] = (unsigned char) ((sha_info->digest[2]) & 0xff);
-  digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
-  digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
-  digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
-  digest[15] = (unsigned char) ((sha_info->digest[3]) & 0xff);
-  digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
-  digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
-  digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
-  digest[19] = (unsigned char) ((sha_info->digest[4]) & 0xff);
-}
--- a/gst_plugins_base/gst-libs/gst/cdda/sha1.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* NIST Secure Hash Algorithm */
-/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
-/* from Peter C. Gutmann's implementation as found in */
-/* Applied Cryptography by Bruce Schneier */
-/* This code is in the public domain */
-/* $Id: sha1.h,v 1.2 2007-12-13 10:10:35 tpm Exp $ */
-
-#ifndef __GST_CDDA_SHA_H__
-#define __GST_CDDA_SHA_H__
-
-#include <stdlib.h>
-#include <stdio.h>
-
-/* Useful defines & typedefs */
-typedef unsigned char SHA_BYTE;	/* 8-bit quantity */
-typedef unsigned long SHA_LONG;	/* 32-or-more-bit quantity */
-
-#define SHA_BLOCKSIZE		64
-#define SHA_DIGESTSIZE		20
-
-typedef struct {
-    SHA_LONG digest[5];		/* message digest */
-    SHA_LONG count_lo, count_hi;	/* 64-bit bit count */
-    SHA_BYTE data[SHA_BLOCKSIZE];	/* SHA data buffer */
-    int local;			/* unprocessed amount in data */
-} SHA_INFO;
-
-#define sha_init   __gst_cdda_sha_init
-#define sha_update __gst_cdda_sha_update
-#define sha_final  __gst_cdda_sha_final
-
-void sha_init(SHA_INFO *);
-void sha_update(SHA_INFO *, SHA_BYTE *, int);
-void sha_final(unsigned char [20], SHA_INFO *);
-
-#define SHA_VERSION 1
-
-#ifdef HAVE_CONFIG_H 
-#include "config.h"
-
-
-#ifdef WORDS_BIGENDIAN
-#  if SIZEOF_LONG == 4
-#    define SHA_BYTE_ORDER  4321
-#  elif SIZEOF_LONG == 8
-#    define SHA_BYTE_ORDER  87654321
-#  endif
-#else
-#  if SIZEOF_LONG == 4
-#    define SHA_BYTE_ORDER  1234
-#  elif SIZEOF_LONG == 8
-#    define SHA_BYTE_ORDER  12345678
-#  endif
-#endif
-
-#else
-
-#define SHA_BYTE_ORDER 1234
-
-#endif
-
-#endif /* __GST_CDDA_SHA_H__ */
--- a/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f32.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f32.h	Fri Apr 16 15:15:52 2010 +0300
@@ -19,6 +19,20 @@
 #include "kiss_fft_f32.h"
 #include <limits.h>
 
+/* The 2*sizeof(size_t) alignment here is borrowed from
+ * GNU libc, so it should be good most everywhere.
+ * It is more conservative than is needed on some 64-bit
+ * platforms, but ia64 does require a 16-byte alignment.
+ * The SIMD extensions for x86 and ppc32 would want a
+ * larger alignment than this, but we don't need to
+ * do better than malloc.
+ *
+ * Borrowed from GLib's gobject/gtype.c
+ */
+#define STRUCT_ALIGNMENT (2 * sizeof (size_t))
+#define ALIGN_STRUCT(offset) \
+      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
+
 #define MAXFACTORS 32
 /* e.g. an fft of length 128 has 4 factors 
  as far as kissfft is concerned
--- a/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f64.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f64.h	Fri Apr 16 15:15:52 2010 +0300
@@ -19,6 +19,20 @@
 #include "kiss_fft_f64.h"
 #include <limits.h>
 
+/* The 2*sizeof(size_t) alignment here is borrowed from
+ * GNU libc, so it should be good most everywhere.
+ * It is more conservative than is needed on some 64-bit
+ * platforms, but ia64 does require a 16-byte alignment.
+ * The SIMD extensions for x86 and ppc32 would want a
+ * larger alignment than this, but we don't need to
+ * do better than malloc.
+ *
+ * Borrowed from GLib's gobject/gtype.c
+ */
+#define STRUCT_ALIGNMENT (2 * sizeof (size_t))
+#define ALIGN_STRUCT(offset) \
+      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
+
 #define MAXFACTORS 32
 /* e.g. an fft of length 128 has 4 factors 
  as far as kissfft is concerned
--- a/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s16.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s16.h	Fri Apr 16 15:15:52 2010 +0300
@@ -19,6 +19,20 @@
 #include "kiss_fft_s16.h"
 #include <limits.h>
 
+/* The 2*sizeof(size_t) alignment here is borrowed from
+ * GNU libc, so it should be good most everywhere.
+ * It is more conservative than is needed on some 64-bit
+ * platforms, but ia64 does require a 16-byte alignment.
+ * The SIMD extensions for x86 and ppc32 would want a
+ * larger alignment than this, but we don't need to
+ * do better than malloc.
+ *
+ * Borrowed from GLib's gobject/gtype.c
+ */
+#define STRUCT_ALIGNMENT (2 * sizeof (size_t))
+#define ALIGN_STRUCT(offset) \
+      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
+
 #define MAXFACTORS 32
 /* e.g. an fft of length 128 has 4 factors 
  as far as kissfft is concerned
--- a/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s32.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s32.h	Fri Apr 16 15:15:52 2010 +0300
@@ -19,6 +19,20 @@
 #include "kiss_fft_s32.h"
 #include <limits.h>
 
+/* The 2*sizeof(size_t) alignment here is borrowed from
+ * GNU libc, so it should be good most everywhere.
+ * It is more conservative than is needed on some 64-bit
+ * platforms, but ia64 does require a 16-byte alignment.
+ * The SIMD extensions for x86 and ppc32 would want a
+ * larger alignment than this, but we don't need to
+ * do better than malloc.
+ *
+ * Borrowed from GLib's gobject/gtype.c
+ */
+#define STRUCT_ALIGNMENT (2 * sizeof (size_t))
+#define ALIGN_STRUCT(offset) \
+      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
+
 #define MAXFACTORS 32
 /* e.g. an fft of length 128 has 4 factors 
  as far as kissfft is concerned
--- a/gst_plugins_base/gst-libs/gst/fft/gstfft.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/gstfft.c	Fri Apr 16 15:15:52 2010 +0300
@@ -23,7 +23,6 @@
  * 
  * This library includes general definitions and functions, useful for
  * all typed FFT classes.
- *
  */
 
 #include <glib.h>
--- a/gst_plugins_base/gst-libs/gst/fft/gstfftf32.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/gstfftf32.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 #include <glib.h>
 #include <math.h>
 
+#include "_kiss_fft_guts_f32.h"
 #include "kiss_fftr_f32.h"
 #include "gstfft.h"
 #include "gstfftf32.h"
@@ -78,13 +79,18 @@
 gst_fft_f32_new (gint len, gboolean inverse)
 {
   GstFFTF32 *self;
+  gsize subsize = 0, memneeded;
 
   g_return_val_if_fail (len > 0, NULL);
   g_return_val_if_fail (len % 2 == 0, NULL);
 
-  self = g_new (GstFFTF32, 1);
+  kiss_fftr_f32_alloc (len, (inverse) ? 1 : 0, NULL, &subsize);
+  memneeded = ALIGN_STRUCT (sizeof (GstFFTF32)) + subsize;
 
-  self->cfg = kiss_fftr_f32_alloc (len, (inverse) ? 1 : 0, NULL, NULL);
+  self = (GstFFTF32 *) g_malloc0 (memneeded);
+
+  self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTF32)));
+  self->cfg = kiss_fftr_f32_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize);
   g_assert (self->cfg);
 
   self->inverse = inverse;
@@ -168,7 +174,6 @@
 void
 gst_fft_f32_free (GstFFTF32 * self)
 {
-  kiss_fftr_f32_free (self->cfg);
   g_free (self);
 }
 
--- a/gst_plugins_base/gst-libs/gst/fft/gstfftf64.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/gstfftf64.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 #include <glib.h>
 #include <math.h>
 
+#include "_kiss_fft_guts_f64.h"
 #include "kiss_fftr_f64.h"
 #include "gstfft.h"
 #include "gstfftf64.h"
@@ -78,13 +79,18 @@
 gst_fft_f64_new (gint len, gboolean inverse)
 {
   GstFFTF64 *self;
+  gsize subsize = 0, memneeded;
 
   g_return_val_if_fail (len > 0, NULL);
   g_return_val_if_fail (len % 2 == 0, NULL);
 
-  self = g_new (GstFFTF64, 1);
+  kiss_fftr_f64_alloc (len, (inverse) ? 1 : 0, NULL, &subsize);
+  memneeded = ALIGN_STRUCT (sizeof (GstFFTF64)) + subsize;
 
-  self->cfg = kiss_fftr_f64_alloc (len, (inverse) ? 1 : 0, NULL, NULL);
+  self = (GstFFTF64 *) g_malloc0 (memneeded);
+
+  self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTF64)));
+  self->cfg = kiss_fftr_f64_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize);
   g_assert (self->cfg);
 
   self->inverse = inverse;
@@ -168,7 +174,6 @@
 void
 gst_fft_f64_free (GstFFTF64 * self)
 {
-  kiss_fftr_f64_free (self->cfg);
   g_free (self);
 }
 
--- a/gst_plugins_base/gst-libs/gst/fft/gstffts16.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/gstffts16.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 #include <glib.h>
 #include <math.h>
 
+#include "_kiss_fft_guts_s16.h"
 #include "kiss_fftr_s16.h"
 #include "gstfft.h"
 #include "gstffts16.h"
@@ -78,13 +79,18 @@
 gst_fft_s16_new (gint len, gboolean inverse)
 {
   GstFFTS16 *self;
+  gsize subsize = 0, memneeded;
 
   g_return_val_if_fail (len > 0, NULL);
   g_return_val_if_fail (len % 2 == 0, NULL);
 
-  self = g_new (GstFFTS16, 1);
+  kiss_fftr_s16_alloc (len, (inverse) ? 1 : 0, NULL, &subsize);
+  memneeded = ALIGN_STRUCT (sizeof (GstFFTS16)) + subsize;
 
-  self->cfg = kiss_fftr_s16_alloc (len, (inverse) ? 1 : 0, NULL, NULL);
+  self = (GstFFTS16 *) g_malloc0 (memneeded);
+
+  self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTS16)));
+  self->cfg = kiss_fftr_s16_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize);
   g_assert (self->cfg);
 
   self->inverse = inverse;
@@ -168,7 +174,6 @@
 void
 gst_fft_s16_free (GstFFTS16 * self)
 {
-  kiss_fftr_s16_free (self->cfg);
   g_free (self);
 }
 
--- a/gst_plugins_base/gst-libs/gst/fft/gstffts32.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/gstffts32.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 #include <glib.h>
 #include <math.h>
 
+#include "_kiss_fft_guts_s32.h"
 #include "kiss_fftr_s32.h"
 #include "gstfft.h"
 #include "gstffts32.h"
@@ -77,13 +78,18 @@
 gst_fft_s32_new (gint len, gboolean inverse)
 {
   GstFFTS32 *self;
+  gsize subsize = 0, memneeded;
 
   g_return_val_if_fail (len > 0, NULL);
   g_return_val_if_fail (len % 2 == 0, NULL);
 
-  self = g_new (GstFFTS32, 1);
+  kiss_fftr_s32_alloc (len, (inverse) ? 1 : 0, NULL, &subsize);
+  memneeded = ALIGN_STRUCT (sizeof (GstFFTS32)) + subsize;
 
-  self->cfg = kiss_fftr_s32_alloc (len, (inverse) ? 1 : 0, NULL, NULL);
+  self = (GstFFTS32 *) g_malloc0 (memneeded);
+
+  self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTS32)));
+  self->cfg = kiss_fftr_s32_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize);
   g_assert (self->cfg);
 
   self->inverse = inverse;
@@ -167,7 +173,6 @@
 void
 gst_fft_s32_free (GstFFTS32 * self)
 {
-  kiss_fftr_s32_free (self->cfg);
   g_free (self);
 }
 
--- a/gst_plugins_base/gst-libs/gst/fft/kiss_fft_s16.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fft_s16.h	Fri Apr 16 15:15:52 2010 +0300
@@ -26,7 +26,9 @@
 
 #define KISS_FFT_S16_MALLOC g_malloc
 
-#include "machine/_stdint.h"
+#ifndef __SYMBIAN32__
+#include "_stdint.h"
+#endif
 
 #define kiss_fft_s16_scalar int16_t
 
--- a/gst_plugins_base/gst-libs/gst/fft/kiss_fft_s32.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fft_s32.h	Fri Apr 16 15:15:52 2010 +0300
@@ -26,8 +26,9 @@
 
 #define KISS_FFT_S32_MALLOC g_malloc
 
-
-#include "machine/_stdint.h"
+#ifndef __SYMBIAN32__
+#include "_stdint.h"
+#endif
 
 #define kiss_fft_s32_scalar int32_t
 
--- a/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f32.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f32.c	Fri Apr 16 15:15:52 2010 +0300
@@ -43,9 +43,8 @@
   nfft >>= 1;
 
   kiss_fft_f32_alloc (nfft, inverse_fft, NULL, &subsize);
-  memneeded =
-      sizeof (struct kiss_fftr_f32_state) + subsize +
-      sizeof (kiss_fft_f32_cpx) * (nfft * 2);
+  memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_f32_state))
+      + ALIGN_STRUCT (subsize) + sizeof (kiss_fft_f32_cpx) * (nfft * 2);
 
   if (lenmem == NULL) {
     st = (kiss_fftr_f32_cfg) KISS_FFT_F32_MALLOC (memneeded);
@@ -57,8 +56,9 @@
   if (!st)
     return NULL;
 
-  st->substate = (kiss_fft_f32_cfg) (st + 1);   /*just beyond kiss_fftr_f32_state struct */
-  st->tmpbuf = (kiss_fft_f32_cpx *) (((char *) st->substate) + subsize);
+  st->substate = (kiss_fft_f32_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_f32_state)));       /*just beyond kiss_fftr_f32_state struct */
+  st->tmpbuf =
+      (kiss_fft_f32_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize));
   st->super_twiddles = st->tmpbuf + nfft;
   kiss_fft_f32_alloc (nfft, inverse_fft, st->substate, &subsize);
 
--- a/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f64.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f64.c	Fri Apr 16 15:15:52 2010 +0300
@@ -43,9 +43,9 @@
   nfft >>= 1;
 
   kiss_fft_f64_alloc (nfft, inverse_fft, NULL, &subsize);
-  memneeded =
-      sizeof (struct kiss_fftr_f64_state) + subsize +
-      sizeof (kiss_fft_f64_cpx) * (nfft * 2);
+  memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_f64_state))
+      + ALIGN_STRUCT (subsize)
+      + sizeof (kiss_fft_f64_cpx) * (nfft * 2);
 
   if (lenmem == NULL) {
     st = (kiss_fftr_f64_cfg) KISS_FFT_F64_MALLOC (memneeded);
@@ -57,8 +57,9 @@
   if (!st)
     return NULL;
 
-  st->substate = (kiss_fft_f64_cfg) (st + 1);   /*just beyond kiss_fftr_f64_state struct */
-  st->tmpbuf = (kiss_fft_f64_cpx *) (((char *) st->substate) + subsize);
+  st->substate = (kiss_fft_f64_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_f64_state)));       /*just beyond kiss_fftr_f64_state struct */
+  st->tmpbuf =
+      (kiss_fft_f64_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize));
   st->super_twiddles = st->tmpbuf + nfft;
   kiss_fft_f64_alloc (nfft, inverse_fft, st->substate, &subsize);
 
--- a/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s16.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s16.c	Fri Apr 16 15:15:52 2010 +0300
@@ -43,9 +43,9 @@
   nfft >>= 1;
 
   kiss_fft_s16_alloc (nfft, inverse_fft, NULL, &subsize);
-  memneeded =
-      sizeof (struct kiss_fftr_s16_state) + subsize +
-      sizeof (kiss_fft_s16_cpx) * (nfft * 2);
+  memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_s16_state))
+      + ALIGN_STRUCT (subsize)
+      + sizeof (kiss_fft_s16_cpx) * (nfft * 2);
 
   if (lenmem == NULL) {
     st = (kiss_fftr_s16_cfg) KISS_FFT_S16_MALLOC (memneeded);
@@ -57,8 +57,9 @@
   if (!st)
     return NULL;
 
-  st->substate = (kiss_fft_s16_cfg) (st + 1);   /*just beyond kiss_fftr_s16_state struct */
-  st->tmpbuf = (kiss_fft_s16_cpx *) (((char *) st->substate) + subsize);
+  st->substate = (kiss_fft_s16_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_s16_state)));       /*just beyond kiss_fftr_s16_state struct */
+  st->tmpbuf =
+      (kiss_fft_s16_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize));
   st->super_twiddles = st->tmpbuf + nfft;
   kiss_fft_s16_alloc (nfft, inverse_fft, st->substate, &subsize);
 
--- a/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s32.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s32.c	Fri Apr 16 15:15:52 2010 +0300
@@ -43,9 +43,9 @@
   nfft >>= 1;
 
   kiss_fft_s32_alloc (nfft, inverse_fft, NULL, &subsize);
-  memneeded =
-      sizeof (struct kiss_fftr_s32_state) + subsize +
-      sizeof (kiss_fft_s32_cpx) * (nfft * 2);
+  memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_s32_state))
+      + ALIGN_STRUCT (subsize)
+      + sizeof (kiss_fft_s32_cpx) * (nfft * 2);
 
   if (lenmem == NULL) {
     st = (kiss_fftr_s32_cfg) KISS_FFT_S32_MALLOC (memneeded);
@@ -57,8 +57,9 @@
   if (!st)
     return NULL;
 
-  st->substate = (kiss_fft_s32_cfg) (st + 1);   /*just beyond kiss_fftr_s32_state struct */
-  st->tmpbuf = (kiss_fft_s32_cpx *) (((char *) st->substate) + subsize);
+  st->substate = (kiss_fft_s32_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_s32_state)));       /*just beyond kiss_fftr_s32_state struct */
+  st->tmpbuf =
+      (kiss_fft_s32_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize));
   st->super_twiddles = st->tmpbuf + nfft;
   kiss_fft_s32_alloc (nfft, inverse_fft, st->substate, &subsize);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_version	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+Based on Kiss FFT version 1.2.6. http://kissfft.sourceforge.net
+
+Only changes are limitation to one data type for each version in
+kiss_fft.h and _kiss_fft_guts.h.
--- a/gst_plugins_base/gst-libs/gst/floatcast/floatcast.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/floatcast/floatcast.h	Fri Apr 16 15:15:52 2010 +0300
@@ -40,8 +40,7 @@
 #define __FLOATCAST_H__
 
 #include <string.h>
-#include <glib/gtypes.h>
-#include <glib/gutils.h>  /* to make sure inline is defined properly */
+#include <glib.h>
 
 #if defined (_MSC_VER) && !defined (inline)
 #define inline __inline
@@ -97,128 +96,6 @@
 
 #endif
 
-/* FIXME 0.11: don't use GLib namespace (GDOUBLE_SWAP_LE_BE, GFLOAT_TO_LE,
- * GFLOAT_TO_BE, GDOUBLE_TO_LE, GDOUBLE_TO_BE) */
-
-/**
- * GFLOAT_SWAP_LE_BE:
- * @in: input value
- *
- * Swap byte order of a 32-bit floating point value (float).
- */
-inline static gfloat
-GFLOAT_SWAP_LE_BE(gfloat in)
-{
-  union
-  {
-    guint32 i;
-    gfloat f;
-  } u;
-
-  u.f = in;
-  u.i = GUINT32_SWAP_LE_BE (u.i);
-  return u.f;
-}
-
-/**
- * GDOUBLE_SWAP_LE_BE:
- * @in: input value
- *
- * Swap byte order of a 64-bit floating point value (double).
- */
-inline static gdouble
-GDOUBLE_SWAP_LE_BE(gdouble in)
-{
-  union
-  {
-    guint64 i;
-    gdouble d;
-  } u;
-
-  u.d = in;
-  u.i = GUINT64_SWAP_LE_BE (u.i);
-  return u.d;
-}
-
-/**
- * GDOUBLE_TO_LE:
- * @val: value
- *
- * Convert 64-bit floating point value (double) from native byte order into
- * little endian byte order.
- */
-/**
- * GDOUBLE_TO_BE:
- * @val: value
- *
- * Convert 64-bit floating point value (double) from native byte order into
- * big endian byte order.
- */
-/**
- * GDOUBLE_FROM_LE:
- * @val: value
- *
- * Convert 64-bit floating point value (double) from little endian byte order
- * into native byte order.
- */
-/**
- * GDOUBLE_FROM_BE:
- * @val: value
- *
- * Convert 64-bit floating point value (double) from big endian byte order
- * into native byte order.
- */
-
-/**
- * GFLOAT_TO_LE:
- * @val: value
- *
- * Convert 32-bit floating point value (float) from native byte order into
- * little endian byte order.
- */
-/**
- * GFLOAT_TO_BE:
- * @val: value
- *
- * Convert 32-bit floating point value (float) from native byte order into
- * big endian byte order.
- */
-/**
- * GFLOAT_FROM_LE:
- * @val: value
- *
- * Convert 32-bit floating point value (float) from little endian byte order
- * into native byte order.
- */
-/**
- * GFLOAT_FROM_BE:
- * @val: value
- *
- * Convert 32-bit floating point value (float) from big endian byte order
- * into native byte order.
- */
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define GFLOAT_TO_LE(val)    ((gfloat) (val))
-#define GFLOAT_TO_BE(val)    (GFLOAT_SWAP_LE_BE (val))
-#define GDOUBLE_TO_LE(val)   ((gdouble) (val))
-#define GDOUBLE_TO_BE(val)   (GDOUBLE_SWAP_LE_BE (val))
-
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
-#define GFLOAT_TO_LE(val)    (GFLOAT_SWAP_LE_BE (val))
-#define GFLOAT_TO_BE(val)    ((gfloat) (val))
-#define GDOUBLE_TO_LE(val)   (GDOUBLE_SWAP_LE_BE (val))
-#define GDOUBLE_TO_BE(val)   ((gdouble) (val))
-
-#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
-#error unknown ENDIAN type
-#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
-
-#define GFLOAT_FROM_LE(val)  (GFLOAT_TO_LE (val))
-#define GFLOAT_FROM_BE(val)  (GFLOAT_TO_BE (val))
-#define GDOUBLE_FROM_LE(val) (GDOUBLE_TO_LE (val))
-#define GDOUBLE_FROM_BE(val) (GDOUBLE_TO_BE (val))
-
 G_END_DECLS
 
 #endif /* __FLOATCAST_H__ */
--- a/gst_plugins_base/gst-libs/gst/interfaces/colorbalance.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalance.c	Fri Apr 16 15:15:52 2010 +0300
@@ -30,6 +30,15 @@
 /**
  * SECTION:gstcolorbalance
  * @short_description: Interface for adjusting color balance settings
+ *
+ * <refsect2><para>
+ * This interface is implemented by elements which can perform some color
+ * balance operation on video frames they process. For example, modifying
+ * the brightness, contrast, hue or saturation.
+ * </para><para>
+ * Example elements are 'xvimagesink' and 'colorbalance'
+ * </para>
+ * </refsect2>
  */
 
 enum
@@ -79,6 +88,14 @@
   static gboolean initialized = FALSE;
 
   if (!initialized) {
+    /**
+     * GstColorBalance::value-changed:
+     * @colorbalance: The GstColorBalance instance
+     * @channel: The #GstColorBalanceChannel
+     * @value: The new value
+     *
+     * Fired when the value of the indicated channel has changed.
+     */
     gst_color_balance_signals[VALUE_CHANGED] =
         g_signal_new ("value-changed",
         GST_TYPE_COLOR_BALANCE, G_SIGNAL_RUN_LAST,
@@ -97,11 +114,21 @@
   klass->set_value = NULL;
   klass->get_value = NULL;
 }
+
+/**
+ * gst_color_balance_list_channels:
+ * @balance: A #GstColorBalance instance
+ * 
+ * Retrieve a list of the available channels.
+ *
+ * Returns: A GList containing pointers to #GstColorBalanceChannel objects.
+ *          The list is owned by the #GstColorBalance instance and must not
+ *          be freed.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 const GList *
 gst_color_balance_list_channels (GstColorBalance * balance)
 {
@@ -113,11 +140,24 @@
 
   return NULL;
 }
+
+/**
+ * gst_color_balance_set_value:
+ * @balance: A #GstColorBalance instance
+ * @channel: A #GstColorBalanceChannel instance
+ * @value: The new value for the channel.
+ *
+ * Sets the current value of the channel to the passed value, which must
+ * be between min_value and max_value.
+ * 
+ * See Also: The #GstColorBalanceChannel::min_value and
+ *         #GstColorBalanceChannel::max_value members of the
+ *         #GstColorBalanceChannel object.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_color_balance_set_value (GstColorBalance * balance,
     GstColorBalanceChannel * channel, gint value)
@@ -128,11 +168,25 @@
     klass->set_value (balance, channel, value);
   }
 }
+
+/**
+ * gst_color_balance_get_value:
+ * @balance: A #GstColorBalance instance
+ * @channel: A #GstColorBalanceChannel instance
+ *
+ * Retrieve the current value of the indicated channel, between min_value
+ * and max_value.
+ * 
+ * See Also: The #GstColorBalanceChannel::min_value and
+ *         #GstColorBalanceChannel::max_value members of the
+ *         #GstColorBalanceChannel object.
+ * 
+ * Returns: The current value of the channel.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 gint
 gst_color_balance_get_value (GstColorBalance * balance,
     GstColorBalanceChannel * channel)
@@ -145,11 +199,45 @@
 
   return channel->min_value;
 }
+
+/**
+ * gst_color_balance_get_balance_type:
+ * @balance: The #GstColorBalance implementation
+ *
+ * Get the #GstColorBalanceType of this implementation.
+ *
+ * Returns: A the #GstColorBalanceType.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstColorBalanceType
+gst_color_balance_get_balance_type (GstColorBalance * balance)
+{
+  GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance);
+
+  return klass->balance_type;
+}
+
+/**
+ * gst_color_balance_value_changed:
+ * @balance: A #GstColorBalance instance
+ * @channel: A #GstColorBalanceChannel whose value has changed
+ * @value: The new value of the channel
+ *
+ * A helper function called by implementations of the GstColorBalance
+ * interface. It fires the #GstColorBalance::value-changed signal on the
+ * instance, and the #GstColorBalanceChannel::value-changed signal on the
+ * channel object.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_color_balance_value_changed (GstColorBalance * balance,
     GstColorBalanceChannel * channel, gint value)
--- a/gst_plugins_base/gst-libs/gst/interfaces/colorbalance.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalance.h	Fri Apr 16 15:15:52 2010 +0300
@@ -46,14 +46,27 @@
 #define GST_COLOR_BALANCE_TYPE(klass) (klass->balance_type)
 
 typedef struct _GstColorBalance GstColorBalance;
+typedef struct _GstColorBalanceClass GstColorBalanceClass;
   
+/**
+ * GstColorBalanceType:
+ * @GST_COLOR_BALANCE_HARDWARE: Color balance is implemented with dedicated
+ *         hardware.
+ * @GST_COLOR_BALANCE_SOFTWARE: Color balance is implemented via software
+ *         processing.
+ * 
+ * An enumeration indicating whether an element implements color balancing
+ * operations in software or in dedicated hardware. In general, dedicated
+ * hardware implementations (such as those provided by xvimagesink) are
+ * preferred.
+ */
 typedef enum
 {
   GST_COLOR_BALANCE_HARDWARE,
   GST_COLOR_BALANCE_SOFTWARE
 } GstColorBalanceType;
 
-typedef struct _GstColorBalanceClass {
+struct _GstColorBalanceClass {
   GTypeInterface klass;
 
   GstColorBalanceType balance_type;
@@ -73,7 +86,7 @@
                           gint                    value);
 
   gpointer _gst_reserved[GST_PADDING];
-} GstColorBalanceClass;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -101,6 +114,12 @@
 
 gint    gst_color_balance_get_value     (GstColorBalance        *balance,
                                          GstColorBalanceChannel *channel);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstColorBalanceType
+        gst_color_balance_get_balance_type (GstColorBalance        *balance);
 
 /* trigger signal */
 #ifdef __SYMBIAN32__
--- a/gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,6 +25,17 @@
 
 #include "colorbalancechannel.h"
 
+/**
+ * SECTION:gstcolorbalancechannel
+ * @short_description: Object representing a channel from the #GstColorBalance
+ *         interface.
+ *
+ * <refsect2><para>The #GstColorBalanceChannel object represents a parameter
+ * for modifying the color balance implemented by an element providing the
+ * #GstColorBalance interface. For example, Hue or Saturation.
+ * </para></refsect2>
+ */
+
 enum
 {
   /* FILL ME */
@@ -78,6 +89,13 @@
 
   parent_class = g_type_class_peek_parent (klass);
 
+  /**
+   * GstColorBalanceChannel::value-changed:
+   * @channel: The #GstColorBalanceChannel
+   * @value: The new value
+   *
+   * Fired when the value of the indicated channel has changed.
+   */
   signals[SIGNAL_VALUE_CHANGED] =
       g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
--- a/gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.h	Fri Apr 16 15:15:52 2010 +0300
@@ -39,15 +39,26 @@
 #define GST_IS_COLOR_BALANCE_CHANNEL_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_COLOR_BALANCE_CHANNEL))
 
-typedef struct _GstColorBalanceChannel {
+typedef struct _GstColorBalanceChannel GstColorBalanceChannel;
+typedef struct _GstColorBalanceChannelClass GstColorBalanceChannelClass;
+
+/**
+ * GstColorBalanceChannel:
+ * @label: A string containing a descriptive name for this channel
+ * @min_value: The minimum valid value for this channel.
+ * @max_value: The maximum valid value for this channel.
+ */
+struct _GstColorBalanceChannel {
   GObject parent;
 
+  /*< public >*/
   gchar  *label;
-  gint    min_value,
-          max_value;
-} GstColorBalanceChannel;
+  gint    min_value;
+  gint    max_value;
+};
 
-typedef struct _GstColorBalanceChannelClass {
+
+struct _GstColorBalanceChannelClass {
   GObjectClass parent;
 
   /* signals */
@@ -55,7 +66,7 @@
                           gint                    value);
 
   gpointer _gst_reserved[GST_PADDING];
-} GstColorBalanceChannelClass;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,16 +24,17 @@
 GType
 gst_color_balance_type_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GEnumValue values[] = {
       { GST_COLOR_BALANCE_HARDWARE, "GST_COLOR_BALANCE_HARDWARE", "hardware" },
       { GST_COLOR_BALANCE_SOFTWARE, "GST_COLOR_BALANCE_SOFTWARE", "software" },
       { 0, NULL, NULL }
     };
-    etype = g_enum_register_static ("GstColorBalanceType", values);
+    GType g_define_type_id = g_enum_register_static ("GstColorBalanceType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 
 /* enumerations from "mixer.h" */
@@ -44,16 +45,17 @@
 GType
 gst_mixer_type_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GEnumValue values[] = {
       { GST_MIXER_HARDWARE, "GST_MIXER_HARDWARE", "hardware" },
       { GST_MIXER_SOFTWARE, "GST_MIXER_SOFTWARE", "software" },
       { 0, NULL, NULL }
     };
-    etype = g_enum_register_static ("GstMixerType", values);
+    GType g_define_type_id = g_enum_register_static ("GstMixerType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -62,8 +64,8 @@
 GType
 gst_mixer_message_type_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GEnumValue values[] = {
       { GST_MIXER_MESSAGE_INVALID, "GST_MIXER_MESSAGE_INVALID", "invalid" },
       { GST_MIXER_MESSAGE_MUTE_TOGGLED, "GST_MIXER_MESSAGE_MUTE_TOGGLED", "mute-toggled" },
@@ -74,9 +76,10 @@
       { GST_MIXER_MESSAGE_MIXER_CHANGED, "GST_MIXER_MESSAGE_MIXER_CHANGED", "mixer-changed" },
       { 0, NULL, NULL }
     };
-    etype = g_enum_register_static ("GstMixerMessageType", values);
+    GType g_define_type_id = g_enum_register_static ("GstMixerMessageType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -85,16 +88,19 @@
 GType
 gst_mixer_flags_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GFlagsValue values[] = {
       { GST_MIXER_FLAG_NONE, "GST_MIXER_FLAG_NONE", "none" },
       { GST_MIXER_FLAG_AUTO_NOTIFICATIONS, "GST_MIXER_FLAG_AUTO_NOTIFICATIONS", "auto-notifications" },
+      { GST_MIXER_FLAG_HAS_WHITELIST, "GST_MIXER_FLAG_HAS_WHITELIST", "has-whitelist" },
+      { GST_MIXER_FLAG_GROUPING, "GST_MIXER_FLAG_GROUPING", "grouping" },
       { 0, NULL, NULL }
     };
-    etype = g_flags_register_static ("GstMixerFlags", values);
+    GType g_define_type_id = g_flags_register_static ("GstMixerFlags", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 
 /* enumerations from "mixertrack.h" */
@@ -105,8 +111,8 @@
 GType
 gst_mixer_track_flags_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GFlagsValue values[] = {
       { GST_MIXER_TRACK_INPUT, "GST_MIXER_TRACK_INPUT", "input" },
       { GST_MIXER_TRACK_OUTPUT, "GST_MIXER_TRACK_OUTPUT", "output" },
@@ -114,11 +120,114 @@
       { GST_MIXER_TRACK_RECORD, "GST_MIXER_TRACK_RECORD", "record" },
       { GST_MIXER_TRACK_MASTER, "GST_MIXER_TRACK_MASTER", "master" },
       { GST_MIXER_TRACK_SOFTWARE, "GST_MIXER_TRACK_SOFTWARE", "software" },
+      { GST_MIXER_TRACK_NO_RECORD, "GST_MIXER_TRACK_NO_RECORD", "no-record" },
+      { GST_MIXER_TRACK_NO_MUTE, "GST_MIXER_TRACK_NO_MUTE", "no-mute" },
+      { GST_MIXER_TRACK_WHITELIST, "GST_MIXER_TRACK_WHITELIST", "whitelist" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_flags_register_static ("GstMixerTrackFlags", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+
+/* enumerations from "navigation.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_navigation_command_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_NAVIGATION_COMMAND_INVALID, "GST_NAVIGATION_COMMAND_INVALID", "invalid" },
+      { GST_NAVIGATION_COMMAND_MENU1, "GST_NAVIGATION_COMMAND_MENU1", "menu1" },
+      { GST_NAVIGATION_COMMAND_MENU2, "GST_NAVIGATION_COMMAND_MENU2", "menu2" },
+      { GST_NAVIGATION_COMMAND_MENU3, "GST_NAVIGATION_COMMAND_MENU3", "menu3" },
+      { GST_NAVIGATION_COMMAND_MENU4, "GST_NAVIGATION_COMMAND_MENU4", "menu4" },
+      { GST_NAVIGATION_COMMAND_MENU5, "GST_NAVIGATION_COMMAND_MENU5", "menu5" },
+      { GST_NAVIGATION_COMMAND_MENU6, "GST_NAVIGATION_COMMAND_MENU6", "menu6" },
+      { GST_NAVIGATION_COMMAND_MENU7, "GST_NAVIGATION_COMMAND_MENU7", "menu7" },
+      { GST_NAVIGATION_COMMAND_LEFT, "GST_NAVIGATION_COMMAND_LEFT", "left" },
+      { GST_NAVIGATION_COMMAND_RIGHT, "GST_NAVIGATION_COMMAND_RIGHT", "right" },
+      { GST_NAVIGATION_COMMAND_UP, "GST_NAVIGATION_COMMAND_UP", "up" },
+      { GST_NAVIGATION_COMMAND_DOWN, "GST_NAVIGATION_COMMAND_DOWN", "down" },
+      { GST_NAVIGATION_COMMAND_ACTIVATE, "GST_NAVIGATION_COMMAND_ACTIVATE", "activate" },
+      { GST_NAVIGATION_COMMAND_PREV_ANGLE, "GST_NAVIGATION_COMMAND_PREV_ANGLE", "prev-angle" },
+      { GST_NAVIGATION_COMMAND_NEXT_ANGLE, "GST_NAVIGATION_COMMAND_NEXT_ANGLE", "next-angle" },
       { 0, NULL, NULL }
     };
-    etype = g_flags_register_static ("GstMixerTrackFlags", values);
+    GType g_define_type_id = g_enum_register_static ("GstNavigationCommand", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_navigation_query_type_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_NAVIGATION_QUERY_INVALID, "GST_NAVIGATION_QUERY_INVALID", "invalid" },
+      { GST_NAVIGATION_QUERY_COMMANDS, "GST_NAVIGATION_QUERY_COMMANDS", "commands" },
+      { GST_NAVIGATION_QUERY_ANGLES, "GST_NAVIGATION_QUERY_ANGLES", "angles" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstNavigationQueryType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_navigation_message_type_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_NAVIGATION_MESSAGE_INVALID, "GST_NAVIGATION_MESSAGE_INVALID", "invalid" },
+      { GST_NAVIGATION_MESSAGE_MOUSE_OVER, "GST_NAVIGATION_MESSAGE_MOUSE_OVER", "mouse-over" },
+      { GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED, "GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED", "commands-changed" },
+      { GST_NAVIGATION_MESSAGE_ANGLES_CHANGED, "GST_NAVIGATION_MESSAGE_ANGLES_CHANGED", "angles-changed" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstNavigationMessageType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_navigation_event_type_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_NAVIGATION_EVENT_INVALID, "GST_NAVIGATION_EVENT_INVALID", "invalid" },
+      { GST_NAVIGATION_EVENT_KEY_PRESS, "GST_NAVIGATION_EVENT_KEY_PRESS", "key-press" },
+      { GST_NAVIGATION_EVENT_KEY_RELEASE, "GST_NAVIGATION_EVENT_KEY_RELEASE", "key-release" },
+      { GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS, "GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS", "mouse-button-press" },
+      { GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, "GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE", "mouse-button-release" },
+      { GST_NAVIGATION_EVENT_MOUSE_MOVE, "GST_NAVIGATION_EVENT_MOUSE_MOVE", "mouse-move" },
+      { GST_NAVIGATION_EVENT_COMMAND, "GST_NAVIGATION_EVENT_COMMAND", "command" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstNavigationEventType", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
 }
 
 /* enumerations from "tunerchannel.h" */
@@ -129,8 +238,8 @@
 GType
 gst_tuner_channel_flags_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GFlagsValue values[] = {
       { GST_TUNER_CHANNEL_INPUT, "GST_TUNER_CHANNEL_INPUT", "input" },
       { GST_TUNER_CHANNEL_OUTPUT, "GST_TUNER_CHANNEL_OUTPUT", "output" },
@@ -138,9 +247,10 @@
       { GST_TUNER_CHANNEL_AUDIO, "GST_TUNER_CHANNEL_AUDIO", "audio" },
       { 0, NULL, NULL }
     };
-    etype = g_flags_register_static ("GstTunerChannelFlags", values);
+    GType g_define_type_id = g_flags_register_static ("GstTunerChannelFlags", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 
 /* Generated data ends here */
--- a/gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.h	Fri Apr 16 15:15:52 2010 +0300
@@ -36,6 +36,20 @@
 GType gst_mixer_track_flags_get_type (void);
 #define GST_TYPE_MIXER_TRACK_FLAGS (gst_mixer_track_flags_get_type())
 
+/* enumerations from "navigation.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_navigation_command_get_type (void);
+#define GST_TYPE_NAVIGATION_COMMAND (gst_navigation_command_get_type())
+GType gst_navigation_query_type_get_type (void);
+#define GST_TYPE_NAVIGATION_QUERY_TYPE (gst_navigation_query_type_get_type())
+GType gst_navigation_message_type_get_type (void);
+#define GST_TYPE_NAVIGATION_MESSAGE_TYPE (gst_navigation_message_type_get_type())
+GType gst_navigation_event_type_get_type (void);
+#define GST_TYPE_NAVIGATION_EVENT_TYPE (gst_navigation_event_type_get_type())
+
 /* enumerations from "tunerchannel.h" */
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst-libs/gst/interfaces/mixer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -143,6 +143,8 @@
  * it is allowed to only provide input elements in this list.
  *
  * Returns: A #GList consisting of zero or more #GstMixerTracks.
+ *          The list is owned by the #GstMixer instance and must not be freed
+ *          or modified.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -354,6 +356,28 @@
 }
 
 /**
+ * gst_mixer_get_mixer_type:
+ * @mixer: The #GstMixer implementation
+ *
+ * Get the #GstMixerType of this mixer implementation.
+ *
+ * Returns: A the #GstMixerType.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMixerType
+gst_mixer_get_mixer_type (GstMixer * mixer)
+{
+  GstMixerClass *klass = GST_MIXER_GET_CLASS (mixer);
+
+  return klass->mixer_type;
+}
+
+/**
  * gst_mixer_get_mixer_flags:
  * @mixer: The #GstMixer implementation
  *
@@ -655,7 +679,7 @@
  * message and return the GstMixerMessageType identifying which
  * type of notification it is.
  *
- * Returns: The type of the GstMixerMessage, or GST_MIXER_MESSAGE_NONE
+ * Returns: The type of the GstMixerMessage, or GST_MIXER_MESSAGE_INVALID
  * if the message is not a GstMixer notification.
  *
  * Since: 0.10.14
--- a/gst_plugins_base/gst-libs/gst/interfaces/mixer.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixer.h	Fri Apr 16 15:15:52 2010 +0300
@@ -85,18 +85,26 @@
 /**
  * GstMixerFlags:
  * @GST_MIXER_FLAG_NONE: No flags
- * @GST_MIXER_FLAG_AUTO_NOTIFICATIONS: The mixer implementation automatically sends
- *    notification messages.
+ * @GST_MIXER_FLAG_AUTO_NOTIFICATIONS: The mixer implementation automatically
+ *    sends notification messages.
+ * @GST_MIXER_FLAG_HAS_WHITELIST: The mixer implementation flags tracks that
+ *    should be displayed by default (whitelisted). Since: 0.10.23
+ * @GST_MIXER_FLAG_GROUPING: The mixer implementation will leave some controls
+ *    marked without either input or output.  Controls marked as input or
+ *    output should be grouped with input & output sliders, even if they
+ *    are options or bare switches. Since: 0.10.23
  * 
- * Flags for supported features. Whether the element automatically sends 
- * notifications on the bus is the only one for now. 
+ * Flags indicating which optional features are supported by a mixer
+ * implementation.
  *
  * Since: 0.10.14
  */
 typedef enum
 {
   GST_MIXER_FLAG_NONE                = 0,
-  GST_MIXER_FLAG_AUTO_NOTIFICATIONS  = (1<<0)
+  GST_MIXER_FLAG_AUTO_NOTIFICATIONS  = (1<<0),
+  GST_MIXER_FLAG_HAS_WHITELIST       = (1<<1),
+  GST_MIXER_FLAG_GROUPING            = (1<<2),
 } GstMixerFlags;
 
 struct _GstMixerClass {
@@ -250,11 +258,15 @@
 
 
 void            gst_mixer_options_list_changed (GstMixer        *mixer,
-                                                GstMixerOptions *opts);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
+                                                GstMixerOptions *opts);
 
+GstMixerType    gst_mixer_get_mixer_type  (GstMixer *mixer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
 
 
 GstMixerFlags   gst_mixer_get_mixer_flags (GstMixer *mixer);
--- a/gst_plugins_base/gst-libs/gst/interfaces/mixertrack.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixertrack.c	Fri Apr 16 15:15:52 2010 +0300
@@ -41,6 +41,7 @@
   ARG_0,
   ARG_LABEL,
   ARG_UNTRANSLATED_LABEL,
+  ARG_INDEX,
   ARG_MIN_VOLUME,
   ARG_MAX_VOLUME,
   ARG_FLAGS,
@@ -102,7 +103,7 @@
   g_object_class_install_property (object_klass, ARG_LABEL,
       g_param_spec_string ("label", "Track label",
           "The label assigned to the track (may be translated)", NULL,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstMixerTrack:untranslated-label
@@ -118,27 +119,42 @@
   g_object_class_install_property (object_klass, ARG_UNTRANSLATED_LABEL,
       g_param_spec_string ("untranslated-label", "Untranslated track label",
           "The untranslated label assigned to the track (since 0.10.13)",
-          NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+          NULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstMixerTrack:index
+   *
+   * Index of the mixer track, if available. Mixer track implementations
+   * must set this at construct time. This can be used to discern between
+   * multiple tracks with identical labels.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (object_klass, ARG_INDEX,
+      g_param_spec_uint ("index", "Index",
+          "Track index", 0, G_MAXUINT,
+          0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   g_object_class_install_property (object_klass, ARG_MIN_VOLUME,
-      g_param_spec_int ("min_volume", "Minimum volume level",
+      g_param_spec_int ("min-volume", "Minimum volume level",
           "The minimum possible volume level", G_MININT, G_MAXINT,
-          0, G_PARAM_READABLE));
+          0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_klass, ARG_MAX_VOLUME,
-      g_param_spec_int ("max_volume", "Maximum volume level",
+      g_param_spec_int ("max-volume", "Maximum volume level",
           "The maximum possible volume level", G_MININT, G_MAXINT,
-          0, G_PARAM_READABLE));
+          0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_klass, ARG_FLAGS,
       g_param_spec_uint ("flags", "Flags",
           "Flags indicating the type of mixer track",
-          0, G_MAXUINT, 0, G_PARAM_READABLE));
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_klass, ARG_NUM_CHANNELS,
-      g_param_spec_int ("num_channels", "Number of channels",
+      g_param_spec_int ("num-channels", "Number of channels",
           "The number of channels contained within the track",
-          0, G_MAXINT, 0, G_PARAM_READABLE));
+          0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 #if 0
   signals[SIGNAL_RECORD_TOGGLED] =
@@ -176,8 +192,9 @@
   mixer_track->num_channels = 0;
 }
 
-/* FIXME 0.11: move this as a member into the mixer track structure */
+/* FIXME 0.11: move these as members into the mixer track structure */
 #define MIXER_TRACK_OBJECT_DATA_KEY_UNTRANSLATED_LABEL "gst-mixer-track-ulabel"
+#define MIXER_TRACK_OBJECT_DATA_KEY_INDEX "index"
 
 static void
 gst_mixer_track_get_property (GObject * object, guint prop_id, GValue * value,
@@ -196,6 +213,11 @@
           (const gchar *) g_object_get_data (G_OBJECT (mixer_track),
               MIXER_TRACK_OBJECT_DATA_KEY_UNTRANSLATED_LABEL));
       break;
+    case ARG_INDEX:
+      g_value_set_uint (value,
+          GPOINTER_TO_INT (g_object_get_data (G_OBJECT (mixer_track),
+                  MIXER_TRACK_OBJECT_DATA_KEY_INDEX)));
+      break;
     case ARG_MIN_VOLUME:
       g_value_set_int (value, mixer_track->min_volume);
       break;
@@ -228,6 +250,11 @@
           MIXER_TRACK_OBJECT_DATA_KEY_UNTRANSLATED_LABEL,
           g_value_dup_string (value), (GDestroyNotify) g_free);
       break;
+    case ARG_INDEX:
+      g_object_set_data (G_OBJECT (mixer_track),
+          MIXER_TRACK_OBJECT_DATA_KEY_INDEX,
+          GINT_TO_POINTER (g_value_get_uint (value)));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
--- a/gst_plugins_base/gst-libs/gst/interfaces/mixertrack.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixertrack.h	Fri Apr 16 15:15:52 2010 +0300
@@ -54,14 +54,34 @@
  * mixer, which means that setting this track will change
  * the hearable volume on any output.
  */
-
+/**
+ * GstMixerTrackFlags:
+ * @GST_MIXER_TRACK_INPUT: mixer track is for input
+ * @GST_MIXER_TRACK_OUTPUT: mixer track is for output
+ * @GST_MIXER_TRACK_MUTE: input or output is muted
+ * @GST_MIXER_TRACK_RECORD: input is audible in speakers attached to output
+ *     (for #GST_MIXER_TRACK_INPUT mixer tracks only)
+ * @GST_MIXER_TRACK_MASTER: this mixer track is likely to be the master control
+ * @GST_MIXER_TRACK_SOFTWARE: mixer track's' volume control is implemented
+ *     in software (as opposed to a hardware control)
+ * @GST_MIXER_TRACK_NO_RECORD: input track lacks support for recordable.
+ *     Since: 0.10.23
+ * @GST_MIXER_TRACK_NO_MUTE: play track doesn't support mute. Since: 0.10.23
+ * @GST_MIXER_TRACK_WHITELIST: track should be displayed "by default" in apps.
+ *     Since: 0.10.23
+ *
+ * Mixer track flags.
+ */
 typedef enum {
   GST_MIXER_TRACK_INPUT  = (1<<0),
   GST_MIXER_TRACK_OUTPUT = (1<<1),
   GST_MIXER_TRACK_MUTE   = (1<<2),
   GST_MIXER_TRACK_RECORD = (1<<3),
   GST_MIXER_TRACK_MASTER = (1<<4),
-  GST_MIXER_TRACK_SOFTWARE = (1<<5)
+  GST_MIXER_TRACK_SOFTWARE = (1<<5),
+  GST_MIXER_TRACK_NO_RECORD = (1<<6),
+  GST_MIXER_TRACK_NO_MUTE = (1<<7),
+  GST_MIXER_TRACK_WHITELIST = (1<<8),
 } GstMixerTrackFlags;
 
 #define GST_MIXER_TRACK_HAS_FLAG(channel, flag) \
--- a/gst_plugins_base/gst-libs/gst/interfaces/navigation.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/navigation.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,7 +1,8 @@
 /* GStreamer Navigation
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2007-2009 Jan Schmidt <thaytan@noraisin.net>
  *
- * navigation.c: navigation design virtual class function wrappers
+ * navigation.c: navigation event virtual class function wrappers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -19,18 +20,62 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:gstnavigation
+ * @short_description: Interface for creating, sending and parsing navigation
+ * events.
+ *
+ * The Navigation interface is used for creating and injecting navigation related
+ * events such as mouse button presses, cursor motion and key presses. The associated
+ * library also provides methods for parsing received events, and for sending and
+ * receiving navigation related bus events. One main usecase is DVD menu navigation.
+ *
+ * The main parts of the API are:
+ * <itemizedlist>
+ * <listitem>
+ * <para>
+ * The GstNavigation interface, implemented by elements which provide an application
+ * with the ability to create and inject navigation events into the pipeline.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * GstNavigation event handling API. GstNavigation events are created in response to
+ * calls on a GstNavigation interface implementation, and sent in the pipeline. Upstream
+ * elements can use the navigation event API functions to parse the contents of received
+ * messages.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * GstNavigation message handling API. GstNavigation messages may be sent on the message
+ * bus to inform applications of navigation related changes in the pipeline, such as the
+ * mouse moving over a clickable region, or the set of available angles changing.
+ * </para><para>
+ * The GstNavigation message functions provide functions for creating and parsing
+ * custom bus messages for signalling GstNavigation changes.
+ * </para>
+ * </listitem>
+ * </itemizedlist>
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include <gst/interfaces/navigation.h>
+#include <gst/interfaces/interfaces-enumtypes.h>
 
 static void gst_navigation_class_init (GstNavigationInterface * iface);
+
+#define GST_NAVIGATION_MESSAGE_NAME "GstNavigationMessage"
+#define GST_NAVIGATION_QUERY_NAME "GstNavigationQuery"
+#define GST_NAVIGATION_EVENT_NAME "application/x-gst-navigation"
+
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 GType
 gst_navigation_get_type (void)
 {
@@ -78,30 +123,807 @@
     iface->send_event (navigation, structure);
   }
 }
+
+/**
+ * gst_navigation_send_mouse_event:
+ * @navigation: The navigation interface instance
+ * @event: The type of the key event. Recognised values are "key-press" and
+ * "key-release"
+ * @key: Character representation of the key. This is typically as produced
+ * by XKeysymToString.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_navigation_send_key_event (GstNavigation * navigation, const char *event,
     const char *key)
 {
   gst_navigation_send_event (navigation,
-      gst_structure_new ("application/x-gst-navigation", "event", G_TYPE_STRING,
+      gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
           event, "key", G_TYPE_STRING, key, NULL));
 }
+
+/**
+ * gst_navigation_send_mouse_event:
+ * @navigation: The navigation interface instance
+ * @event: The type of mouse event, as a text string. Recognised values are
+ * "mouse-button-press", "mouse-button-release" and "mouse-move".
+ * @button: The button number of the button being pressed or released. Pass 0
+ * for mouse-move events.
+ * @x: The x coordinate of the mouse event.
+ * @y: The y coordinate of the mouse event.
+ *
+ * Sends a mouse event to the navigation interface. Mouse event coordinates
+ * are sent relative to the display space of the related output area. This is
+ * usually the size in pixels of the window associated with the element
+ * implementing the #GstNavigation interface.
+ *
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_navigation_send_mouse_event (GstNavigation * navigation, const char *event,
     int button, double x, double y)
 {
   gst_navigation_send_event (navigation,
-      gst_structure_new ("application/x-gst-navigation", "event", G_TYPE_STRING,
+      gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
           event, "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x,
           "pointer_y", G_TYPE_DOUBLE, y, NULL));
 }
+
+/**
+ * gst_navigation_send_command:
+ * @navigation: The navigation interface instance
+ * @command: The command to issue
+ *
+ * Sends the indicated command to the navigation interface.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_navigation_send_command (GstNavigation * navigation,
+    GstNavigationCommand command)
+{
+  gst_navigation_send_event (navigation,
+      gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
+          "command", "command-code", G_TYPE_UINT, (guint) command, NULL));
+}
+
+/* Navigation Queries */
+
+#define GST_NAVIGATION_QUERY_HAS_TYPE(query,query_type) \
+(gst_navigation_query_get_type (query) == GST_NAVIGATION_QUERY_ ## query_type)
+
+/**
+ * gst_navigation_query_get_type:
+ * @query: The query to inspect
+ *
+ * Inspect a #GstQuery and return the #GstNavigationQueryType associated with
+ * it if it is a #GstNavigation query.
+ *
+ * Returns: The #GstNavigationQueryType of the query, or
+ * #GST_NAVIGATION_QUERY_INVALID
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstNavigationQueryType
+gst_navigation_query_get_type (GstQuery * query)
+{
+  const GstStructure *s;
+  const gchar *q_type;
+
+  if (query == NULL || GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM)
+    return GST_NAVIGATION_QUERY_INVALID;
+
+  s = gst_query_get_structure (query);
+  if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_QUERY_NAME))
+    return GST_NAVIGATION_QUERY_INVALID;
+
+  q_type = gst_structure_get_string (s, "type");
+  if (q_type == NULL)
+    return GST_NAVIGATION_QUERY_INVALID;
+
+  if (g_str_equal (q_type, "commands"))
+    return GST_NAVIGATION_QUERY_COMMANDS;
+  else if (g_str_equal (q_type, "angles"))
+    return GST_NAVIGATION_QUERY_ANGLES;
+
+  return GST_NAVIGATION_QUERY_INVALID;
+}
+
+/**
+ * gst_navigation_query_new_commands:
+ *
+ * Create a new #GstNavigation commands query. When executed, it will
+ * query the pipeline for the set of currently available commands.
+ *
+ * Returns: The new query.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstQuery *
+gst_navigation_query_new_commands (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME,
+      "type", G_TYPE_STRING, "commands", NULL);
+  query = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  return query;
+}
+
+static void
+gst_query_list_add_command (GValue * list, GstNavigationCommand val)
+{
+  GValue item = { 0, };
+
+  g_value_init (&item, GST_TYPE_NAVIGATION_COMMAND);
+  g_value_set_enum (&item, val);
+  gst_value_list_append_value (list, &item);
+  g_value_unset (&item);
+}
+
+/**
+ * gst_navigation_query_set_commands:
+ * @query: a #GstQuery
+ * @n_cmds: the number of commands to set.
+ * @...: A list of @GstNavigationCommand values, @n_cmds entries long.
+ *
+ * Set the #GstNavigation command query result fields in @query. The number
+ * of commands passed must be equal to @n_commands.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_navigation_query_set_commands (GstQuery * query, gint n_cmds, ...)
+{
+  va_list ap;
+  GValue list = { 0, };
+  GstStructure *structure;
+  gint i;
+
+  g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS));
+
+  g_value_init (&list, GST_TYPE_LIST);
+
+  va_start (ap, n_cmds);
+  for (i = 0; i < n_cmds; i++) {
+    GstNavigationCommand val = va_arg (ap, GstNavigationCommand);
+    gst_query_list_add_command (&list, val);
+  }
+  va_end (ap);
+
+  structure = gst_query_get_structure (query);
+  gst_structure_set_value (structure, "commands", &list);
+
+  g_value_unset (&list);
+}
+
+/**
+ * gst_navigation_query_set_commandsv:
+ * @query: a #GstQuery
+ * @n_cmds: the number of commands to set.
+ * @cmds: An array containing @n_cmds @GstNavigationCommand values.
+ *
+ * Set the #GstNavigation command query result fields in @query. The number
+ * of commands passed must be equal to @n_commands.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_navigation_query_set_commandsv (GstQuery * query, gint n_cmds,
+    GstNavigationCommand * cmds)
+{
+  GValue list = { 0, };
+  GstStructure *structure;
+  gint i;
+
+  g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS));
+
+  g_value_init (&list, GST_TYPE_LIST);
+  for (i = 0; i < n_cmds; i++) {
+    gst_query_list_add_command (&list, cmds[i]);
+  }
+  structure = gst_query_get_structure (query);
+  gst_structure_set_value (structure, "commands", &list);
+
+  g_value_unset (&list);
+}
+
+/**
+ * gst_navigation_query_parse_commands_length:
+ * @query: a #GstQuery
+ * @n_cmds: the number of commands in this query.
+ *
+ * Parse the number of commands in the #GstNavigation commands @query.
+ *
+ * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_query_parse_commands_length (GstQuery * query, guint * n_cmds)
+{
+  GstStructure *structure;
+  const GValue *list;
+
+  g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE);
+
+  if (n_cmds == NULL)
+    return TRUE;
+
+  structure = gst_query_get_structure (query);
+  list = gst_structure_get_value (structure, "commands");
+  if (list == NULL)
+    *n_cmds = 0;
+  else
+    *n_cmds = gst_value_list_get_size (list);
+
+  return TRUE;
+}
+
+/**
+ * gst_navigation_query_parse_commands_nth:
+ * @query: a #GstQuery
+ * @nth: the nth command to retrieve.
+ * @cmd: a pointer to store the nth command into.
+ *
+ * Parse the #GstNavigation command query and retrieve the @nth command from
+ * it into @cmd. If the list contains less elements than @nth, @cmd will be
+ * set to #GST_NAVIGATION_COMMAND_INVALID.
+ *
+ * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_query_parse_commands_nth (GstQuery * query, guint nth,
+    GstNavigationCommand * cmd)
+{
+  GstStructure *structure;
+  const GValue *list;
+
+  g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE);
+
+  if (cmd == NULL)
+    return TRUE;
+
+  structure = gst_query_get_structure (query);
+  list = gst_structure_get_value (structure, "commands");
+  if (list == NULL) {
+    *cmd = GST_NAVIGATION_COMMAND_INVALID;
+  } else {
+    if (nth < gst_value_list_get_size (list)) {
+      *cmd = (GstNavigationCommand)
+          g_value_get_enum (gst_value_list_get_value (list, nth));
+    } else
+      *cmd = GST_NAVIGATION_COMMAND_INVALID;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_navigation_query_new_angles:
+ *
+ * Create a new #GstNavigation angles query. When executed, it will
+ * query the pipeline for the set of currently available angles, which may be
+ * greater than one in a multiangle video.
+ *
+ * Returns: The new query.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstQuery *
+gst_navigation_query_new_angles (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME,
+      "type", G_TYPE_STRING, "angles", NULL);
+  query = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  return query;
+}
+
+/**
+ * gst_navigation_query_set_angles:
+ * @query: a #GstQuery
+ * @cur_angle: the current viewing angle to set.
+ * @n_angles: the number of viewing angles to set.
+ *
+ * Set the #GstNavigation angles query result field in @query.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_navigation_query_set_angles (GstQuery * query, guint cur_angle,
+    guint n_angles)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES));
+
+  structure = gst_query_get_structure (query);
+  gst_structure_set (structure,
+      "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL);
+}
+
+/**
+ * gst_navigation_query_parse_angles:
+ * @query: a #GstQuery
+ * @cur_angle: Pointer to a #guint into which to store the currently selected
+ * angle value from the query, or NULL
+ * @n_angles: Pointer to a #guint into which to store the number of angles
+ * value from the query, or NULL
+ *
+ * Parse the current angle number in the #GstNavigation angles @query into the
+ * #guint pointed to by the @cur_angle variable, and the number of available
+ * angles into the #guint pointed to by the @n_angles variable.
+ *
+ * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_query_parse_angles (GstQuery * query, guint * cur_angle,
+    guint * n_angles)
+{
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES), FALSE);
+
+  structure = gst_query_get_structure (query);
+
+  if (cur_angle)
+    g_return_val_if_fail (gst_structure_get_uint (structure,
+            "angle", cur_angle), FALSE);
+
+  if (n_angles)
+    g_return_val_if_fail (gst_structure_get_uint (structure,
+            "angles", n_angles), FALSE);
+
+  return TRUE;
+}
+
+/* Navigation Messages */
+
+#define GST_NAVIGATION_MESSAGE_HAS_TYPE(msg,msg_type) \
+(gst_navigation_message_get_type (msg) == GST_NAVIGATION_MESSAGE_ ## msg_type)
+
+/**
+ * gst_navigation_message_get_type:
+ * @message: A #GstMessage to inspect.
+ *
+ * Check a bus message to see if it is a #GstNavigation event, and return
+ * the #GstNavigationMessageType identifying the type of the message if so.
+ *
+ * Returns: The type of the #GstNavigationMessage, or
+ * #GST_NAVIGATION_MESSAGE_INVALID if the message is not a #GstNavigation
+ * notification.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstNavigationMessageType
+gst_navigation_message_get_type (GstMessage * message)
+{
+  const GstStructure *s;
+  const gchar *m_type;
+
+  if (message == NULL || GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
+    return GST_NAVIGATION_MESSAGE_INVALID;
+
+  s = gst_message_get_structure (message);
+  if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_MESSAGE_NAME))
+    return GST_NAVIGATION_MESSAGE_INVALID;
+
+  m_type = gst_structure_get_string (s, "type");
+  if (m_type == NULL)
+    return GST_NAVIGATION_MESSAGE_INVALID;
+
+  if (g_str_equal (m_type, "mouse-over"))
+    return GST_NAVIGATION_MESSAGE_MOUSE_OVER;
+  else if (g_str_equal (m_type, "commands-changed"))
+    return GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED;
+  else if (g_str_equal (m_type, "angles-changed"))
+    return GST_NAVIGATION_MESSAGE_ANGLES_CHANGED;
+
+  return GST_NAVIGATION_MESSAGE_INVALID;
+}
+
+/**
+ * gst_navigation_message_new_mouse_over:
+ * @src: A #GstObject to set as source of the new message.
+ * @active: %TRUE if the mouse has entered a clickable area of the display.
+ * %FALSE if it over a non-clickable area.
+ *
+ * Creates a new #GstNavigation message with type
+ * #GST_NAVIGATION_MESSAGE_MOUSE_OVER.
+ *
+ * Returns: The new #GstMessage.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_navigation_message_new_mouse_over (GstObject * src, gboolean active)
+{
+  GstStructure *s;
+  GstMessage *m;
+
+  s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
+      "type", G_TYPE_STRING, "mouse-over", "active", G_TYPE_BOOLEAN, active,
+      NULL);
+
+  m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
+
+  return m;
+}
+
+/**
+ * gst_navigation_message_parse_mouse_over:
+ * @message: A #GstMessage to inspect.
+ * @active: A pointer to a gboolean to receive the active/inactive state,
+ * or NULL.
+ *
+ * Parse a #GstNavigation message of type #GST_NAVIGATION_MESSAGE_MOUSE_OVER
+ * and extract the active/inactive flag. If the mouse over event is marked
+ * active, it indicates that the mouse is over a clickable area.
+ *
+ * Returns: %TRUE if the message could be successfully parsed. %FALSE if not.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_message_parse_mouse_over (GstMessage * message,
+    gboolean * active)
+{
+  if (!GST_NAVIGATION_MESSAGE_HAS_TYPE (message, MOUSE_OVER))
+    return FALSE;
+
+  if (active) {
+    const GstStructure *s = gst_message_get_structure (message);
+    if (gst_structure_get_boolean (s, "active", active) == FALSE)
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_navigation_message_new_commands_changed:
+ * @src: A #GstObject to set as source of the new message.
+ *
+ * Creates a new #GstNavigation message with type
+ * #GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED
+ *
+ * Returns: The new #GstMessage.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_navigation_message_new_commands_changed (GstObject * src)
+{
+  GstStructure *s;
+  GstMessage *m;
+
+  s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
+      "type", G_TYPE_STRING, "commands-changed", NULL);
+
+  m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
+
+  return m;
+}
+
+/**
+ * gst_navigation_message_new_angles_changed:
+ * @src: A #GstObject to set as source of the new message.
+ * @cur_angle: The currently selected angle.
+ * @n_angles: The number of viewing angles now available.
+ *
+ * Creates a new #GstNavigation message with type
+ * #GST_NAVIGATION_MESSAGE_ANGLES_CHANGED for notifying an application
+ * that the current angle, or current number of angles available in a
+ * multiangle video has changed.
+ *
+ * Returns: The new #GstMessage.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_navigation_message_new_angles_changed (GstObject * src, guint cur_angle,
+    guint n_angles)
+{
+  GstStructure *s;
+  GstMessage *m;
+
+  s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
+      "type", G_TYPE_STRING, "angles-changed",
+      "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL);
+
+  m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
+
+  return m;
+}
+
+/**
+ * gst_navigation_message_parse_angles_changed:
+ * @message: A #GstMessage to inspect.
+ * @cur_angle: A pointer to a #guint to receive the new current angle number,
+ * or NULL
+ * @n_angles: A pointer to a #guint to receive the new angle count, or NULL.
+ *
+ * Parse a #GstNavigation message of type GST_NAVIGATION_MESSAGE_ANGLES_CHANGED
+ * and extract the @cur_angle and @n_angles parameters.
+ *
+ * Returns: %TRUE if the message could be successfully parsed. %FALSE if not.
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_message_parse_angles_changed (GstMessage * message,
+    guint * cur_angle, guint * n_angles)
+{
+  const GstStructure *s;
+
+  g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message,
+          ANGLES_CHANGED), FALSE);
+
+  s = gst_message_get_structure (message);
+  if (cur_angle)
+    g_return_val_if_fail (gst_structure_get_uint (s, "angle", cur_angle),
+        FALSE);
+
+  if (n_angles)
+    g_return_val_if_fail (gst_structure_get_uint (s, "angles", n_angles),
+        FALSE);
+
+  return TRUE;
+}
+
+#define GST_NAVIGATION_EVENT_HAS_TYPE(event,event_type) \
+(gst_navigation_event_get_type (event) == GST_NAVIGATION_EVENT_ ## event_type)
+
+/**
+ * gst_navigation_event_get_type:
+ * @event: A #GstEvent to inspect.
+ *
+ * Inspect a #GstEvent and return the #GstNavigationEventType of the event, or
+ * #GST_NAVIGATION_EVENT_INVALID if the event is not a #GstNavigation event.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstNavigationEventType
+gst_navigation_event_get_type (GstEvent * event)
+{
+  const GstStructure *s;
+  const gchar *e_type;
+
+  if (event == NULL || GST_EVENT_TYPE (event) != GST_EVENT_NAVIGATION)
+    return GST_NAVIGATION_EVENT_INVALID;
+
+  s = gst_event_get_structure (event);
+  if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_EVENT_NAME))
+    return GST_NAVIGATION_EVENT_INVALID;
+
+  e_type = gst_structure_get_string (s, "event");
+  if (e_type == NULL)
+    return GST_NAVIGATION_EVENT_INVALID;
+
+  if (g_str_equal (e_type, "mouse-button-press"))
+    return GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS;
+  else if (g_str_equal (e_type, "mouse-button-release"))
+    return GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE;
+  else if (g_str_equal (e_type, "mouse-move"))
+    return GST_NAVIGATION_EVENT_MOUSE_MOVE;
+  else if (g_str_equal (e_type, "key-press"))
+    return GST_NAVIGATION_EVENT_KEY_PRESS;
+  else if (g_str_equal (e_type, "key-release"))
+    return GST_NAVIGATION_EVENT_KEY_RELEASE;
+  else if (g_str_equal (e_type, "command"))
+    return GST_NAVIGATION_EVENT_COMMAND;
+
+  return GST_NAVIGATION_EVENT_INVALID;
+}
+
+/**
+ * gst_navigation_event_parse_key_event:
+ * @event: A #GstEvent to inspect.
+ * @key: A pointer to a location to receive the string identifying the key
+ * press. The returned string is owned by the event, and valid only until the
+ * event is unreffed.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_event_parse_key_event (GstEvent * event, const gchar ** key)
+{
+  GstNavigationEventType e_type;
+  const GstStructure *s;
+
+  e_type = gst_navigation_event_get_type (event);
+  g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_KEY_PRESS ||
+      e_type == GST_NAVIGATION_EVENT_KEY_RELEASE, FALSE);
+
+  if (key) {
+    s = gst_event_get_structure (event);
+    *key = gst_structure_get_string (s, "key");
+    if (*key == NULL)
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_navigation_event_parse_mouse_button_event:
+ * @event: A #GstEvent to inspect.
+ * @button: Pointer to a gint that will receive the button number associated
+ * with the event.
+ * @x: Pointer to a gdouble to receive the x coordinate of the mouse button
+ * event.
+ * @y: Pointer to a gdouble to receive the y coordinate of the mouse button
+ * event.
+ * 
+ * Retrieve the details of either a #GstNavigation mouse button press event or
+ * a mouse button release event. Determine which type the event is using
+ * gst_navigation_event_get_type() to retrieve the #GstNavigationEventType.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_event_parse_mouse_button_event (GstEvent * event, gint * button,
+    gdouble * x, gdouble * y)
+{
+  GstNavigationEventType e_type;
+  const GstStructure *s;
+
+  e_type = gst_navigation_event_get_type (event);
+  g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS ||
+      e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, FALSE);
+
+  s = gst_event_get_structure (event);
+  if (x)
+    g_return_val_if_fail (gst_structure_get_double (s, "pointer_x", x), FALSE);
+  if (y)
+    g_return_val_if_fail (gst_structure_get_double (s, "pointer_y", y), FALSE);
+  if (button)
+    g_return_val_if_fail (gst_structure_get_int (s, "button", button), FALSE);
+
+  return TRUE;
+}
+
+/**
+ * gst_navigation_event_parse_mouse_move_event:
+ * @event: A #GstEvent to inspect.
+ * @x: Pointer to a gdouble to receive the x coordinate of the mouse movement.
+ * @y: Pointer to a gdouble to receive the y coordinate of the mouse movement.
+ *
+ * Inspect a #GstNavigation mouse movement event and extract the coordinates
+ * of the event.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_event_parse_mouse_move_event (GstEvent * event, gdouble * x,
+    gdouble * y)
+{
+  const GstStructure *s;
+
+  g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, MOUSE_MOVE),
+      FALSE);
+
+  s = gst_event_get_structure (event);
+  if (x)
+    g_return_val_if_fail (gst_structure_get_double (s, "pointer_x", x), FALSE);
+  if (y)
+    g_return_val_if_fail (gst_structure_get_double (s, "pointer_y", y), FALSE);
+
+  return TRUE;
+}
+
+/**
+ * gst_navigation_event_parse_command:
+ * @event: A #GstEvent to inspect.
+ * @command: Pointer to GstNavigationCommand to receive the type of the
+ * navigation event.
+ *
+ * Inspect a #GstNavigation command event and retrieve the enum value of the
+ * associated command.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_navigation_event_parse_command (GstEvent * event,
+    GstNavigationCommand * command)
+{
+  const GstStructure *s;
+  g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, COMMAND), FALSE);
+
+  if (command) {
+    s = gst_event_get_structure (event);
+    g_return_val_if_fail (gst_structure_get_uint (s, "command-code", (guint*)command),
+        FALSE);
+  }
+
+  return TRUE;
+}
--- a/gst_plugins_base/gst-libs/gst/interfaces/navigation.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/navigation.h	Fri Apr 16 15:15:52 2010 +0300
@@ -37,15 +37,16 @@
     (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_NAVIGATION, GstNavigationInterface))
 
 typedef struct _GstNavigation GstNavigation;
+typedef struct _GstNavigationInterface GstNavigationInterface;
 
-typedef struct _GstNavigationInterface {
+struct _GstNavigationInterface {
   GTypeInterface g_iface;
 
   /* virtual functions */
   void (*send_event) (GstNavigation *navigation, GstStructure *structure);
   
   gpointer _gst_reserved[GST_PADDING];
-} GstNavigationInterface;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -53,16 +54,288 @@
 
 GType           gst_navigation_get_type (void);
 
-/* virtual class function wrappers */
+/* Navigation commands */
+
+/**
+ * GstNavigationCommand:
+ * @GST_NAVIGATION_COMMAND_INVALID: An invalid command entry
+ * @GST_NAVIGATION_COMMAND_MENU1: Execute navigation menu command 1. For DVD,
+ * this enters the DVD root menu, or exits back to the title from the menu.
+ * @GST_NAVIGATION_COMMAND_MENU2: Execute navigation menu command 2. For DVD,
+ * this jumps to the DVD title menu.
+ * @GST_NAVIGATION_COMMAND_MENU3: Execute navigation menu command 3. For DVD,
+ * this jumps into the DVD root menu.
+ * @GST_NAVIGATION_COMMAND_MENU4: Execute navigation menu command 4. For DVD,
+ * this jumps to the Subpicture menu.
+ * @GST_NAVIGATION_COMMAND_MENU5: Execute navigation menu command 5. For DVD,
+ * the jumps to the audio menu.
+ * @GST_NAVIGATION_COMMAND_MENU6: Execute navigation menu command 6. For DVD,
+ * this jumps to the angles menu.
+ * @GST_NAVIGATION_COMMAND_MENU7: Execute navigation menu command 7. For DVD,
+ * this jumps to the chapter menu.
+ * @GST_NAVIGATION_COMMAND_LEFT: Select the next button to the left in a menu,
+ * if such a button exists.
+ * @GST_NAVIGATION_COMMAND_RIGHT: Select the next button to the right in a menu,
+ * if such a button exists.
+ * @GST_NAVIGATION_COMMAND_UP: Select the button above the current one in a
+ * menu, if such a button exists.
+ * @GST_NAVIGATION_COMMAND_DOWN: Select the button below the current one in a
+ * menu, if such a button exists.
+ * @GST_NAVIGATION_COMMAND_ACTIVATE: Activate (click) the currently selected
+ * button in a menu, if such a button exists.
+ * @GST_NAVIGATION_COMMAND_PREV_ANGLE: Switch to the previous angle in a
+ * multiangle feature.
+ * @GST_NAVIGATION_COMMAND_NEXT_ANGLE: Switch to the next angle in a multiangle
+ * feature.
+ *
+ * A set of commands that may be issued to an element providing the
+ * #GstNavigation interface. The available commands can be queried via
+ * the gst_navigation_query_new_commands() query.
+ *
+ * For convenience in handling DVD navigation, the MENU commands are aliased as:
+ *    GST_NAVIGATION_COMMAND_DVD_MENU            = @GST_NAVIGATION_COMMAND_MENU1
+ *    GST_NAVIGATION_COMMAND_DVD_TITLE_MENU      = @GST_NAVIGATION_COMMAND_MENU2
+ *    GST_NAVIGATION_COMMAND_DVD_ROOT_MENU       = @GST_NAVIGATION_COMMAND_MENU3
+ *    GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU = @GST_NAVIGATION_COMMAND_MENU4
+ *    GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU      = @GST_NAVIGATION_COMMAND_MENU5
+ *    GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU      = @GST_NAVIGATION_COMMAND_MENU6
+ *    GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU    = @GST_NAVIGATION_COMMAND_MENU7
+ *
+ * Since: 0.10.23
+ */
+typedef enum {
+  GST_NAVIGATION_COMMAND_INVALID  = 0,
+
+  GST_NAVIGATION_COMMAND_MENU1    = 1,
+  GST_NAVIGATION_COMMAND_MENU2    = 2,
+  GST_NAVIGATION_COMMAND_MENU3    = 3,
+  GST_NAVIGATION_COMMAND_MENU4    = 4,
+  GST_NAVIGATION_COMMAND_MENU5    = 5,
+  GST_NAVIGATION_COMMAND_MENU6    = 6,
+  GST_NAVIGATION_COMMAND_MENU7    = 7,
+  
+  GST_NAVIGATION_COMMAND_LEFT     = 20,
+  GST_NAVIGATION_COMMAND_RIGHT    = 21,
+  GST_NAVIGATION_COMMAND_UP       = 22,
+  GST_NAVIGATION_COMMAND_DOWN     = 23,
+  GST_NAVIGATION_COMMAND_ACTIVATE = 24,
+
+  GST_NAVIGATION_COMMAND_PREV_ANGLE = 30,
+  GST_NAVIGATION_COMMAND_NEXT_ANGLE = 31
+} GstNavigationCommand;
+
+/* Some aliases for the menu command types */
+#define GST_NAVIGATION_COMMAND_DVD_MENU            GST_NAVIGATION_COMMAND_MENU1
+#define GST_NAVIGATION_COMMAND_DVD_TITLE_MENU      GST_NAVIGATION_COMMAND_MENU2
+#define GST_NAVIGATION_COMMAND_DVD_ROOT_MENU       GST_NAVIGATION_COMMAND_MENU3
+#define GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU GST_NAVIGATION_COMMAND_MENU4
+#define GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU      GST_NAVIGATION_COMMAND_MENU5
+#define GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU      GST_NAVIGATION_COMMAND_MENU6
+#define GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU    GST_NAVIGATION_COMMAND_MENU7
+
+/* Queries */
+typedef enum
+{
+  GST_NAVIGATION_QUERY_INVALID     = 0,
+  GST_NAVIGATION_QUERY_COMMANDS    = 1,
+  GST_NAVIGATION_QUERY_ANGLES      = 2
+} GstNavigationQueryType;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstNavigationQueryType gst_navigation_query_get_type (GstQuery *query);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstQuery *gst_navigation_query_new_commands (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_navigation_query_set_commands (GstQuery *query, gint n_cmds, ...);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_navigation_query_set_commandsv (GstQuery *query, gint n_cmds,
+    GstNavigationCommand *cmds);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_query_parse_commands_length (GstQuery *query,
+                                                 guint *n_cmds);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_query_parse_commands_nth (GstQuery *query, guint nth,
+                                              GstNavigationCommand *cmd);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstQuery *gst_navigation_query_new_angles (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_navigation_query_set_angles (GstQuery *query, guint cur_angle,
+                                      guint n_angles);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-void gst_navigation_send_event (GstNavigation *navigation, GstStructure *structure);
+gboolean gst_navigation_query_parse_angles (GstQuery *query, guint *cur_angle,
+                                            guint *n_angles);
+
+/* Element messages */
+/**
+ * GstNavigationMessageType:
+ * @GST_NAVIGATION_MESSAGE_INVALID: Returned from
+ * gst_navigation_message_get_type() when the passed message is not a
+ * navigation message.
+ * @GST_NAVIGATION_MESSAGE_MOUSE_OVER: Sent when the mouse moves over or leaves a
+ * clickable region of the output, such as a DVD menu button.
+ * @GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED: Sent when the set of available commands
+ * changes and should re-queried by interested applications.
+ * @GST_NAVIGATION_MESSAGE_ANGLES_CHANGED: Sent when display angles in a multi-angle
+ * feature (such as a multiangle DVD) change - either angles have appeared or
+ * disappeared.
+ *
+ * A set of notifications that may be received on the bus when navigation
+ * related status changes.
+ *
+ * Since: 0.10.23
+ */
+typedef enum {
+  GST_NAVIGATION_MESSAGE_INVALID,
+  GST_NAVIGATION_MESSAGE_MOUSE_OVER,
+  GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED,
+  GST_NAVIGATION_MESSAGE_ANGLES_CHANGED
+} GstNavigationMessageType;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstNavigationMessageType gst_navigation_message_get_type (GstMessage *message);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstMessage *gst_navigation_message_new_mouse_over (GstObject *src,
+                                                   gboolean active);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_message_parse_mouse_over (GstMessage *message,
+                                              gboolean *active);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstMessage *gst_navigation_message_new_commands_changed (GstObject *src);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstMessage *gst_navigation_message_new_angles_changed (GstObject *src,
+                                                       guint cur_angle,
+                                                       guint n_angles);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+gboolean gst_navigation_message_parse_angles_changed (GstMessage *message,
+                                                      guint *cur_angle,
+                                                      guint *n_angles);
+
+/* event parsing functions */
+/**
+ * GstNavigationEventType:
+ * @GST_NAVIGATION_EVENT_INVALID: Returned from
+ * gst_navigation_event_get_type() when the passed event is not a navigation event.
+ * @GST_NAVIGATION_EVENT_KEY_PRESS: A key press event. Use
+ * gst_navigation_event_parse_key_event() to extract the details from the event.
+ * @GST_NAVIGATION_EVENT_KEY_RELEASE: A key release event. Use
+ * gst_navigation_event_parse_key_event() to extract the details from the event.
+ * @GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: A mouse button press event. Use
+ * gst_navigation_event_parse_mouse_button_event() to extract the details from the
+ * event.
+ * @GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE: A mouse button release event. Use
+ * gst_navigation_event_parse_mouse_button_event() to extract the details from the
+ * event.
+ * @GST_NAVIGATION_EVENT_MOUSE_MOVE: A mouse movement event. Use
+ * gst_navigation_event_parse_mouse_move_event() to extract the details from the
+ * event.
+ * @GST_NAVIGATION_EVENT_COMMAND: A navigation command event. Use
+ * gst_navigation_event_parse_command() to extract the details from the event.
+ *
+ * Enum values for the various events that an element implementing the
+ * GstNavigation interface might send up the pipeline.
+ *
+ * Since: 0.10.23
+ */
+typedef enum {
+  GST_NAVIGATION_EVENT_INVALID                    = 0,
+  GST_NAVIGATION_EVENT_KEY_PRESS                  = 1,
+  GST_NAVIGATION_EVENT_KEY_RELEASE                = 2,
+  GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS         = 3,
+  GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE       = 4,
+  GST_NAVIGATION_EVENT_MOUSE_MOVE                 = 5,
+  GST_NAVIGATION_EVENT_COMMAND                    = 6
+} GstNavigationEventType;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstNavigationEventType gst_navigation_event_get_type (GstEvent *event);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_event_parse_key_event (GstEvent *event,
+    const gchar **key);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_event_parse_mouse_button_event (GstEvent *event,
+    gint *button, gdouble *x, gdouble *y);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_event_parse_mouse_move_event (GstEvent *event,
+    gdouble *x, gdouble *y);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_navigation_event_parse_command (GstEvent *event,
+    GstNavigationCommand *command);
+
+/* interface virtual function wrappers */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_navigation_send_event (GstNavigation *navigation,
+        GstStructure *structure);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
 
 void gst_navigation_send_key_event (GstNavigation *navigation, 
         const char *event, const char *key);
@@ -72,6 +345,12 @@
 
 void gst_navigation_send_mouse_event (GstNavigation *navigation, 
         const char *event, int button, double x, double y);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_navigation_send_command (GstNavigation *navigation,
+        GstNavigationCommand command);
 
 G_END_DECLS
 
--- a/gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,7 +18,15 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-
+/**
+ * SECTION:gstpropertyprobe
+ * @short_description: Interface for probing possible property values
+ *
+ * The property probe is a way to autodetect allowed values for a GObject
+ * property. It's primary use is to autodetect device-names in several elements.
+ *
+ * The interface is implemented by many hardware sources and sinks.
+ */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -73,6 +81,15 @@
   static gboolean initialized = FALSE;
 
   if (!initialized) {
+    /**
+     * GstPropertyProbe::probe-needed
+     * @pspec: #GParamSpec that needs a probe
+     *
+     */
+    /* FIXME:
+     * what is the purpose of this signal, I can't find any usage of it
+     * according to proto n *.h, it should be g_cclosure_marshal_VOID__PARAM
+     */
     gst_property_probe_signals[SIGNAL_PROBE_NEEDED] =
         g_signal_new ("probe-needed", G_TYPE_FROM_CLASS (iface),
         G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPropertyProbeInterface,
@@ -99,13 +116,13 @@
 EXPORT_C
 #endif
 
-
 const GList *
 gst_property_probe_get_properties (GstPropertyProbe * probe)
 {
   GstPropertyProbeInterface *iface;
 
   g_return_val_if_fail (probe != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL);
 
   iface = GST_PROPERTY_PROBE_GET_IFACE (probe);
 
@@ -114,35 +131,58 @@
 
   return NULL;
 }
+
+/**
+ * gst_property_probe_get_property:
+ * @probe: the #GstPropertyProbe to get the properties for.
+ * @name: name of the property.
+ *
+ * Get #GParamSpec for a property for which probing is supported.
+ *
+ * Returns: the #GParamSpec of %NULL.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 const GParamSpec *
 gst_property_probe_get_property (GstPropertyProbe * probe, const gchar * name)
 {
-  const GList *pspecs = gst_property_probe_get_properties (probe);
+  const GList *pspecs;
 
   g_return_val_if_fail (probe != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL);
   g_return_val_if_fail (name != NULL, NULL);
 
+  pspecs = gst_property_probe_get_properties (probe);
+
   while (pspecs) {
     const GParamSpec *pspec = pspecs->data;
 
-    if (!strcmp (pspec->name, name))
-      return pspec;
+    if (pspec) {
+      if (!strcmp (pspec->name, name))
+        return pspec;
+    } else {
+      GST_WARNING_OBJECT (probe, "NULL paramspec in property probe list");
+    }
 
     pspecs = pspecs->next;
   }
 
   return NULL;
 }
+
+/**
+ * gst_property_probe_probe_property:
+ * @probe: the #GstPropertyProbe to check.
+ * @pspec: #GParamSpec of the property.
+ *
+ * Runs a probe on the property specified by %pspec
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_property_probe_probe_property (GstPropertyProbe * probe,
     const GParamSpec * pspec)
@@ -150,6 +190,7 @@
   GstPropertyProbeInterface *iface;
 
   g_return_if_fail (probe != NULL);
+  g_return_if_fail (GST_IS_PROPERTY_PROBE (probe));
   g_return_if_fail (pspec != NULL);
 
   iface = GST_PROPERTY_PROBE_GET_IFACE (probe);
@@ -161,15 +202,14 @@
 /**
  * gst_property_probe_probe_property_name:
  * @probe: the #GstPropertyProbe to check.
- * @name: name of the property to return.
+ * @name: name of the property.
  *
- * Runs a probe on the given property.
+ * Runs a probe on the property specified by %name.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_property_probe_probe_property_name (GstPropertyProbe * probe,
     const gchar * name)
@@ -177,6 +217,7 @@
   const GParamSpec *pspec;
 
   g_return_if_fail (probe != NULL);
+  g_return_if_fail (GST_IS_PROPERTY_PROBE (probe));
   g_return_if_fail (name != NULL);
 
   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name);
@@ -205,7 +246,6 @@
 EXPORT_C
 #endif
 
-
 gboolean
 gst_property_probe_needs_probe (GstPropertyProbe * probe,
     const GParamSpec * pspec)
@@ -213,6 +253,7 @@
   GstPropertyProbeInterface *iface;
 
   g_return_val_if_fail (probe != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), FALSE);
   g_return_val_if_fail (pspec != NULL, FALSE);
 
   iface = GST_PROPERTY_PROBE_GET_IFACE (probe);
@@ -236,7 +277,6 @@
 EXPORT_C
 #endif
 
-
 gboolean
 gst_property_probe_needs_probe_name (GstPropertyProbe * probe,
     const gchar * name)
@@ -244,6 +284,7 @@
   const GParamSpec *pspec;
 
   g_return_val_if_fail (probe != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), FALSE);
   g_return_val_if_fail (name != NULL, FALSE);
 
   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name);
@@ -269,7 +310,6 @@
 EXPORT_C
 #endif
 
-
 GValueArray *
 gst_property_probe_get_values (GstPropertyProbe * probe,
     const GParamSpec * pspec)
@@ -277,6 +317,7 @@
   GstPropertyProbeInterface *iface;
 
   g_return_val_if_fail (probe != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL);
   g_return_val_if_fail (pspec != NULL, NULL);
 
   iface = GST_PROPERTY_PROBE_GET_IFACE (probe);
@@ -300,7 +341,6 @@
 EXPORT_C
 #endif
 
-
 GValueArray *
 gst_property_probe_get_values_name (GstPropertyProbe * probe,
     const gchar * name)
@@ -308,6 +348,7 @@
   const GParamSpec *pspec;
 
   g_return_val_if_fail (probe != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL);
   g_return_val_if_fail (name != NULL, NULL);
 
   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name);
@@ -334,7 +375,6 @@
 EXPORT_C
 #endif
 
-
 GValueArray *
 gst_property_probe_probe_and_get_values (GstPropertyProbe * probe,
     const GParamSpec * pspec)
@@ -342,6 +382,7 @@
   GstPropertyProbeInterface *iface;
 
   g_return_val_if_fail (probe != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL);
   g_return_val_if_fail (pspec != NULL, NULL);
 
   iface = GST_PROPERTY_PROBE_GET_IFACE (probe);
@@ -365,7 +406,6 @@
 EXPORT_C
 #endif
 
-
 GValueArray *
 gst_property_probe_probe_and_get_values_name (GstPropertyProbe * probe,
     const gchar * name)
@@ -373,6 +413,7 @@
   const GParamSpec *pspec;
 
   g_return_val_if_fail (probe != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL);
   g_return_val_if_fail (name != NULL, NULL);
 
   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name);
--- a/gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.h	Fri Apr 16 15:15:52 2010 +0300
@@ -35,9 +35,26 @@
 #define GST_PROPERTY_PROBE_GET_IFACE(obj) \
   (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_PROPERTY_PROBE, GstPropertyProbeInterface))
 
+/**
+ * GstPropertyProbe:
+ *
+ * Opaque #GstPropertyProbe data structure.
+ */
 typedef struct _GstPropertyProbe GstPropertyProbe; /* dummy typedef */
+typedef struct _GstPropertyProbeInterface GstPropertyProbeInterface;
 
-typedef struct _GstPropertyProbeInterface {
+/**
+ * GstPropertyProbeInterface:
+ * @klass: parent interface type.
+ * @probe_needed: default signal handler
+ * @get_properties: virtual method to get list of probable properties
+ * @needs_probe: virtual method to tell if probe need update
+ * @probe_property: virtual method to probe a property
+ * @get_values: virtual method to get probe results for a property
+ *
+ * #GstPropertyProbe interface.
+ */
+struct _GstPropertyProbeInterface {
   GTypeInterface klass;
 
   /* signals */
@@ -56,8 +73,9 @@
                                    guint             prop_id,
                                    const GParamSpec *pspec);
 
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
-} GstPropertyProbeInterface;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst-libs/gst/interfaces/tuner.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tuner.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,6 +31,46 @@
 /**
  * SECTION:gsttuner
  * @short_description: Interface for elements providing tuner operations
+ * 
+ * <refsect2>
+ * <para>
+ * The GstTuner interface is provided by elements that have the ability to
+ * tune into multiple input signals, for example TV or radio capture cards.
+ * </para><para>
+ * The interpretation of 'tuning into' an input stream depends on the element
+ * implementing the interface. For v4lsrc, it might imply selection of an
+ * input source and/or frequency to be configured on a TV card. Another 
+ * GstTuner implementation might be to allow selection of an active input pad
+ * from multiple input pads.
+ * </para><para>
+ * That said, the GstTuner interface functions are biased toward the
+ * TV capture scenario.
+ * </para><para>
+ * The general parameters provided are for configuration are:
+ * <itemizedlist>
+ * <listitem>Selection of a current #GstTunerChannel. The current channel
+ * represents the input source (e.g. Composite, S-Video etc for TV capture).
+ * </listitem>
+ * <listitem>The #GstTunerNorm for the channel. The norm chooses the
+ * interpretation of the incoming signal for the current channel. For example,
+ * PAL or NTSC, or more specific variants there-of.
+ * </listitem>
+ * <listitem>Channel frequency. If the current channel has the ability to tune
+ * between multiple frequencies (if it has the GST_TUNER_CHANNEL_FREQUENCY flag)
+ * then the frequency can be changed/
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+retrieved via the
+ * gst_tuner_set_frequency() and gst_tuner_get_frequency() methods.
+ * </listitem>
+ * </itemizedlist>
+ * </para>
+ * <para>
+ * Where applicable, the signal strength can be retrieved and/or monitored
+ * via a signal.
+ * </para>
+ * </refsect2>
  */
 
 enum
@@ -83,12 +123,26 @@
   static gboolean initialized = FALSE;
 
   if (!initialized) {
+    /**
+     * GstTuner::norm-changed:
+     * @tuner: The element providing the GstTuner interface
+     * @norm: The new configured norm.
+     *
+     * Reports that the current #GstTunerNorm has changed.
+     */
     gst_tuner_signals[NORM_CHANGED] =
         g_signal_new ("norm-changed",
         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
         G_STRUCT_OFFSET (GstTunerClass, norm_changed),
         NULL, NULL,
         g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_TUNER_NORM);
+    /**
+     * GstTuner::channel-changed:
+     * @tuner: The element providing the GstTuner interface
+     * @channel: The new configured channel.
+     *
+     * Reports that the current #GstTunerChannel has changed.
+     */
     gst_tuner_signals[CHANNEL_CHANGED] =
         g_signal_new ("channel-changed",
         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
@@ -96,6 +150,13 @@
         NULL, NULL,
         g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
         GST_TYPE_TUNER_CHANNEL);
+    /**
+     * GstTuner::frequency-changed:
+     * @tuner: The element providing the GstTuner interface
+     * @frequency: The new frequency (an unsigned long)
+     *
+     * Reports that the current frequency has changed.
+     */
     gst_tuner_signals[FREQUENCY_CHANGED] =
         g_signal_new ("frequency-changed",
         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
@@ -103,6 +164,16 @@
         NULL, NULL,
         gst_interfaces_marshal_VOID__OBJECT_ULONG, G_TYPE_NONE, 2,
         GST_TYPE_TUNER_CHANNEL, G_TYPE_ULONG);
+    /**
+     * GstTuner::signal-changed:
+     * @tuner: The element providing the GstTuner interface
+     * @channel: The current #GstTunerChannel
+     * @signal: The new signal strength (an integer)
+     *
+     * Reports that the signal strength has changed.
+     *
+     * See Also: gst_tuner_signal_strength()
+     */
     gst_tuner_signals[SIGNAL_CHANGED] =
         g_signal_new ("signal-changed",
         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
@@ -132,16 +203,16 @@
  * gst_tuner_list_channels:
  * @tuner: the #GstTuner (a #GstElement) to get the channels from.
  *
- * Retrieve a list of channels (e.g. 'composite', 's-video', ...)
- * from the given tuner object.
+ * Retrieve a #GList of #GstTunerChannels available
+ * (e.g. 'composite', 's-video', ...) from the given tuner object.
  *
- * Returns: a list of channels available on this tuner.
+ * Returns: A list of channels available on this tuner. The list is
+ *          owned by the GstTuner and must not be freed.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 const GList *
 gst_tuner_list_channels (GstTuner * tuner)
 {
@@ -183,7 +254,7 @@
 }
 
 /**
- * gst_Tuner_get_channel:
+ * gst_tuner_get_channel:
  * @tuner: the #GstTuner (a #GstElement) to get the current channel from.
  *
  * Retrieve the current channel from the tuner.
@@ -211,14 +282,15 @@
 }
 
 /**
- * gst_tuner_get_norms_list:
+ * gst_tuner_list_norms:
  * @tuner: the #GstTuner (*a #GstElement) to get the list of norms from.
  *
- * Retrieve a list of available norms on the currently tuned channel
- * from the given tuner object.
+ * Retrieve a GList of available #GstTunerNorm settings for the currently
+ * tuned channel on the given tuner object.
  *
  * Returns: A list of norms available on the current channel for this
- *          tuner object.
+ *          tuner object. The list is owned by the GstTuner and must not
+ *          be freed.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -296,20 +368,24 @@
 
 /**
  * gst_tuner_set_frequency:
- * @tuner: the #Gsttuner (a #GstElement) that owns the given channel.
- * @channel: the #GstTunerChannel to set the frequency on.
- * @frequency: the frequency to tune in to.
+ * @tuner: The #Gsttuner (a #GstElement) that owns the given channel.
+ * @channel: The #GstTunerChannel to set the frequency on.
+ * @frequency: The frequency to tune in to.
  *
  * Sets a tuning frequency on the given tuner/channel. Note that this
  * requires the given channel to be a "tuning" channel, which can be
  * checked using GST_TUNER_CHANNEL_HAS_FLAG (), with the proper flag
  * being GST_TUNER_CHANNEL_FREQUENCY.
+ *
+ * The frequency is in Hz, with minimum steps indicated by the 
+ * frequency_multiplicator provided in the #GstTunerChannel. The
+ * valid range is provided in the min_frequency and max_frequency properties
+ * of the #GstTunerChannel.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_tuner_set_frequency (GstTuner * tuner,
     GstTunerChannel * channel, gulong frequency)
@@ -329,13 +405,14 @@
 
 /**
  * gst_tuner_get_frequency:
- * @tuner: the #GstTuner (a #GstElement) that owns the given channel.
- * @channel: the #GstTunerChannel to retrieve the frequency from.
+ * @tuner: The #GstTuner (a #GstElement) that owns the given channel.
+ * @channel: The #GstTunerChannel to retrieve the frequency from.
  *
- * Retrieve the current frequency from the given channel. The same
- * applies as for set_frequency (): check the flag.
+ * Retrieve the current frequency from the given channel. As for
+ * gst_tuner_set_frequency(), the #GstTunerChannel must support frequency
+ * operations, as indicated by the GST_TUNER_CHANNEL_FREQUENCY flag.
  *
- * Returns: the current frequency, or 0 on error.
+ * Returns: The current frequency, or 0 on error.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -362,23 +439,25 @@
 }
 
 /**
- * gst_tuner_get_signal_strength:
+ * gst_tuner_signal_strength:
  * @tuner: the #GstTuner (a #GstElement) that owns the given channel.
  * @channel: the #GstTunerChannel to get the signal strength from.
  *
- * get the strength of the signal on this channel. Note that this
- * requires the current channel to be a "tuning" channel, e.g. a
+ * Get the strength of the signal on this channel. Note that this
+ * requires the current channel to be a "tuning" channel, i.e. a
  * channel on which frequency can be set. This can be checked using
  * GST_TUNER_CHANNEL_HAS_FLAG (), and the appropriate flag to check
  * for is GST_TUNER_CHANNEL_FREQUENCY.
  *
- * Returns: signal strength, or 0 on error.
+ * The valid range of the signal strength is indicated in the 
+ * min_signal and max_signal properties of the #GstTunerChannel.
+ *
+ * Returns: Signal strength, or 0 on error.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 gint
 gst_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
 {
@@ -396,11 +475,21 @@
 
   return 0;
 }
+
+/**
+ * gst_tuner_find_norm_by_name:
+ * @tuner: A #GstTuner instance
+ * @norm: A string containing the name of a #GstTunerNorm
+ * 
+ * Look up a #GstTunerNorm by name.
+ *
+ * Returns: A #GstTunerNorm, or NULL if no norm with the provided name
+ * is available.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 GstTunerNorm *
 gst_tuner_find_norm_by_name (GstTuner * tuner, gchar * norm)
 {
@@ -417,11 +506,21 @@
   }
   return NULL;
 }
+
+/**
+ * gst_tuner_find_channel_by_name:
+ * @tuner: A #GstTuner instance
+ * @channel: A string containing the name of a #GstTunerChannel
+ * 
+ * Look up a #GstTunerChannel by name.
+ *
+ * Returns: A #GstTunerChannel, or NULL if no channel with the provided name
+ * is available.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 GstTunerChannel *
 gst_tuner_find_channel_by_name (GstTuner * tuner, gchar * channel)
 {
@@ -438,11 +537,19 @@
   }
   return NULL;
 }
+
+/**
+ * gst_tuner_channel_changed:
+ * @tuner: A #GstTuner instance
+ * @channel: A #GstTunerChannel instance
+ *
+ * Called by elements implementing the #GstTuner interface when the
+ * current channel changes. Fires the #GstTuner::channel-changed signal.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_tuner_channel_changed (GstTuner * tuner, GstTunerChannel * channel)
 {
@@ -452,11 +559,20 @@
   g_signal_emit (G_OBJECT (tuner),
       gst_tuner_signals[CHANNEL_CHANGED], 0, channel);
 }
+
+/**
+ * gst_tuner_norm_changed:
+ * @tuner: A #GstTuner instance
+ * @norm: A #GstTunerNorm instance
+ *
+ * Called by elements implementing the #GstTuner interface when the
+ * current norm changes. Fires the #GstTuner::norm-changed signal.
+ * 
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_tuner_norm_changed (GstTuner * tuner, GstTunerNorm * norm)
 {
@@ -465,11 +581,22 @@
 
   g_signal_emit (G_OBJECT (tuner), gst_tuner_signals[NORM_CHANGED], 0, norm);
 }
+
+/**
+ * gst_tuner_frequency_changed:
+ * @tuner: A #GstTuner instance
+ * @channel: The current #GstTunerChannel
+ * @frequency: The new frequency setting
+ *
+ * Called by elements implementing the #GstTuner interface when the
+ * configured frequency changes. Fires the #GstTuner::frequency-changed
+ * signal on the tuner, and the #GstTunerChannel::frequency-changed signal
+ * on the channel.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_tuner_frequency_changed (GstTuner * tuner,
     GstTunerChannel * channel, gulong frequency)
@@ -482,11 +609,22 @@
 
   g_signal_emit_by_name (G_OBJECT (channel), "frequency_changed", frequency);
 }
+
+/**
+ * gst_tuner_signal_changed:
+ * @tuner: A #GstTuner instance
+ * @channel: The current #GstTunerChannel
+ * @signal: The new signal strength
+ *
+ * Called by elements implementing the #GstTuner interface when the
+ * incoming signal strength changes. Fires the #GstTuner::signal-changed
+ * signal on the tuner and the #GstTunerChannel::signal-changed signal on 
+ * the channel.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_tuner_signal_changed (GstTuner * tuner,
     GstTunerChannel * channel, gint signal)
--- a/gst_plugins_base/gst-libs/gst/interfaces/tuner.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tuner.h	Fri Apr 16 15:15:52 2010 +0300
@@ -43,8 +43,9 @@
   (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TUNER, GstTunerClass))
 
 typedef struct _GstTuner GstTuner;
+typedef struct _GstTunerClass GstTunerClass;
 
-typedef struct _GstTunerClass {
+struct _GstTunerClass {
   GTypeInterface klass;
 
   /* virtual functions */
@@ -80,7 +81,7 @@
                              gint             signal);
 
   gpointer _gst_reserved[GST_PADDING];
-} GstTunerClass;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,6 +25,24 @@
 
 #include "tunerchannel.h"
 
+/**
+ * SECTION:gsttunerchannel
+ * @short_description: A channel from an element implementing the #GstTuner
+ * interface.
+ *
+ * <refsect2>
+ * <para>The #GstTunerChannel object is provided by an element implementing
+ * the #GstTuner interface.
+ * </para>
+ * <para>
+ * GstTunerChannel provides a name and flags to determine the type and
+ * capabilities of the channel. If the GST_TUNER_CHANNEL_FREQUENCY flag is
+ * set, then the channel also information about the minimum and maximum
+ * frequency, and range of the reported signal strength.
+ * </para>
+ * </refsect2>
+ */
+
 enum
 {
   /* FILL ME */
@@ -78,12 +96,28 @@
 
   parent_class = g_type_class_peek_parent (klass);
 
+  /**
+   * GstTunerChannel::frequency-changed:
+   * @tunerchannel: The #GstTunerChannel
+   * @frequency: The new frequency (an unsigned long)
+   *
+   * Reports that the current frequency has changed.
+   */
   signals[SIGNAL_FREQUENCY_CHANGED] =
       g_signal_new ("frequency-changed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstTunerChannelClass,
           frequency_changed),
       NULL, NULL, g_cclosure_marshal_VOID__ULONG, G_TYPE_NONE, 1, G_TYPE_ULONG);
+  /**
+   * GstTunerChannel::signal-changed:
+   * @tunerchannel: The #GstTunerChannel
+   * @signal: The new signal strength (an integer)
+   *
+   * Reports that the signal strength has changed.
+   *
+   * See Also: gst_tuner_signal_strength()
+   */
   signals[SIGNAL_SIGNAL_CHANGED] =
       g_signal_new ("signal-changed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
--- a/gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.h	Fri Apr 16 15:15:52 2010 +0300
@@ -39,6 +39,20 @@
 #define GST_IS_TUNER_CHANNEL_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER_CHANNEL))
 
+typedef struct _GstTunerChannel GstTunerChannel;
+typedef struct _GstTunerChannelClass GstTunerChannelClass;
+
+/**
+ * GstTunerChannelFlags:
+ * @GST_TUNER_CHANNEL_INPUT: The channel is for input
+ * @GST_TUNER_CHANNEL_OUTPUT: The channel is for output
+ * @GST_TUNER_CHANNEL_FREQUENCY: The channel has a frequency setting
+ *                               and signal strength.
+ * @GST_TUNER_CHANNEL_AUDIO: The channel carries audio.
+ * 
+ * An enumeration for flags indicating the available capabilities
+ * of a #GstTunerChannel.
+ */
 typedef enum {
   GST_TUNER_CHANNEL_INPUT     = (1<<0),
   GST_TUNER_CHANNEL_OUTPUT    = (1<<1),
@@ -46,24 +60,43 @@
   GST_TUNER_CHANNEL_AUDIO     = (1<<3)
 } GstTunerChannelFlags;
 
+/**
+ * GST_TUNER_CHANNEL_HAS_FLAG:
+ * @channel: A #GstTunerChannel
+ * @flag: The flag to check for
+ * 
+ * Macro to check if the given flag is set on a channel
+ */
 #define GST_TUNER_CHANNEL_HAS_FLAG(channel, flag) \
   ((channel)->flags & flag)
 
-typedef struct _GstTunerChannel {
+/**
+ * GstTunerChannel:
+ * @label: A string containing a descriptive name for this channel
+ * @flags: A set of #GstTunerChannelFlags for this channel
+ * @freq_multiplicator: The step size (in Hz) for the frequency setting.
+ * @min_frequency: Minimum valid frequency setting (in Hz).
+ * @max_frequency: Maximum valid frequency setting (in Hz).
+ * @min_signal: Minimum reported signal strength value.
+ * @max_signal: Maximum reported signal strength value.
+ */
+struct _GstTunerChannel {
   GObject              parent;
 
+  /*< public >*/
   gchar               *label;
   GstTunerChannelFlags flags;
   gfloat               freq_multiplicator;
-  gulong               min_frequency,
-                       max_frequency;
-  gint                 min_signal,
-                       max_signal;
-} GstTunerChannel;
+  gulong               min_frequency;
+  gulong               max_frequency;
+  gint                 min_signal;
+  gint                 max_signal;
+};
 
-typedef struct _GstTunerChannelClass {
+struct _GstTunerChannelClass {
   GObjectClass parent;
 
+  /*< private >*/
   /* signals */
   void (*frequency_changed) (GstTunerChannel *channel,
                              gulong           frequency);
@@ -71,7 +104,7 @@
                              gint             signal);
 
   gpointer _gst_reserved[GST_PADDING];
-} GstTunerChannelClass;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst-libs/gst/interfaces/tunernorm.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunernorm.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,6 +25,19 @@
 
 #include "tunernorm.h"
 
+/**
+ * SECTION:gsttunernorm
+ * @short_description: Encapsulates information about the data format(s)
+ * for a #GstTunerChannel.
+ *
+ * <refsect2>
+ * <para>The #GstTunerNorm object is created by an element implementing the
+ * #GstTuner interface and encapsulates the selection of a capture/output format
+ * for a selected #GstTunerChannel.
+ * </para>
+ * </refsect2>
+ */
+
 enum
 {
   /* FILL ME */
--- a/gst_plugins_base/gst-libs/gst/interfaces/tunernorm.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunernorm.h	Fri Apr 16 15:15:52 2010 +0300
@@ -37,18 +37,28 @@
 #define GST_IS_TUNER_NORM_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER_NORM))
 
-typedef struct _GstTunerNorm {
+typedef struct _GstTunerNorm GstTunerNorm;
+typedef struct _GstTunerNormClass GstTunerNormClass;
+
+/**
+ * GstTunerNorm:
+ * @label: A string containing a descriptive name for the norm
+ * @framerate: A GValue containing the framerate associated with this norm,
+ *             if any. (May be unset).
+ */
+struct _GstTunerNorm {
   GObject parent;
 
+  /*< public >*/
   gchar  *label;
   GValue  framerate;
-} GstTunerNorm;
+};
 
-typedef struct _GstTunerNormClass {
+struct _GstTunerNormClass {
   GObjectClass parent;
 
   gpointer _gst_reserved[GST_PADDING];
-} GstTunerNormClass;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst-libs/gst/interfaces/videoorientation.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/videoorientation.h	Fri Apr 16 15:15:52 2010 +0300
@@ -42,6 +42,7 @@
  * Opaque #GstVideoOrientation data structure.
  */
 typedef struct _GstVideoOrientation GstVideoOrientation;
+typedef struct _GstVideoOrientationInterface GstVideoOrientationInterface;
 
 /**
  * GstVideoOrientationInterface:
@@ -57,7 +58,7 @@
  *
  * #GstVideoOrientationInterface interface.
  */
-typedef struct _GstVideoOrientationInterface {
+struct _GstVideoOrientationInterface {
   GTypeInterface parent;
 
   /* virtual functions */
@@ -73,7 +74,7 @@
 
   /*< private > */
   gpointer _gst_reserved[GST_PADDING];
-} GstVideoOrientationInterface;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst-libs/gst/interfaces/xoverlay.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/interfaces/xoverlay.h	Fri Apr 16 15:15:52 2010 +0300
@@ -41,9 +41,24 @@
 #define GST_X_OVERLAY_GET_CLASS(inst) \
   (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_X_OVERLAY, GstXOverlayClass))
 
+/**
+ * GstXOverlay:
+ *
+ * Opaque #GstXOverlay data structure.
+ */
 typedef struct _GstXOverlay GstXOverlay;
+typedef struct _GstXOverlayClass GstXOverlayClass;
 
-typedef struct _GstXOverlayClass {
+/**
+ * GstXOverlayClass:
+ * @klass: parent interface type.
+ * @set_xwindow_id: virtual method to configure the XWindow id
+ * @expose: virtual method to handle expose events
+ * @handle_events: virtual method to handle events
+ *
+ * #GstXOverlay interface
+ */
+struct _GstXOverlayClass {
   GTypeInterface klass;
 
   /* virtual functions */
@@ -57,7 +72,7 @@
 
   /*< private >*/
   gpointer                 _gst_reserved[GST_PADDING - 1];
-} GstXOverlayClass;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/netbuffer/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,9 @@
+The network libraries
+---------------------
+
+GstNetBuffer:
+
+  A GstBuffer subclass that can be used by network sources or sinks to
+  store additional to and from addresses. This is required for plugins
+  that operate on this data like RTP.
+
--- a/gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -145,6 +145,9 @@
  * @port: a port number to set.
  *
  * Set @naddr with the IPv4 @address and @port pair.
+ *
+ * Note that @port and @address must be expressed in network byte order,
+ * use g_htons() and g_htonl() to convert them to network byte order.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -168,6 +171,9 @@
  * @port: a port number to set.
  *
  * Set @naddr with the IPv6 @address and @port pair.
+ *
+ * Note that @port must be expressed in network byte order, use g_htons() to convert
+ * it to network byte order.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -197,7 +203,7 @@
 #endif
 
 GstNetType
-gst_netaddress_get_net_type (GstNetAddress * naddr)
+gst_netaddress_get_net_type (const GstNetAddress * naddr)
 {
   g_return_val_if_fail (naddr != NULL, GST_NET_TYPE_UNKNOWN);
 
@@ -210,7 +216,11 @@
  * @address: a location to store the address.
  * @port: a location to store the port.
  *
- * Get the IPv4 address stored in @naddr into @address.
+ * Get the IPv4 address stored in @naddr into @address. This function requires
+ * that the address type of @naddr is of type #GST_NET_TYPE_IP4.
+ *
+ * Note that @port and @address are expressed in network byte order, use
+ * g_ntohs() and g_ntohl() to convert them to host order.
  *
  * Returns: TRUE if the address could be retrieved.
  */
@@ -219,12 +229,12 @@
 #endif
 
 gboolean
-gst_netaddress_get_ip4_address (GstNetAddress * naddr, guint32 * address,
+gst_netaddress_get_ip4_address (const GstNetAddress * naddr, guint32 * address,
     guint16 * port)
 {
   g_return_val_if_fail (naddr != NULL, FALSE);
 
-  if (naddr->type == GST_NET_TYPE_UNKNOWN)
+  if (naddr->type == GST_NET_TYPE_UNKNOWN || naddr->type == GST_NET_TYPE_IP6)
     return FALSE;
 
   if (address)
@@ -243,6 +253,12 @@
  *
  * Get the IPv6 address stored in @naddr into @address.
  *
+ * If @naddr is of type GST_NET_TYPE_IP4, the transitional IP6 address is
+ * returned.
+ *
+ * Note that @port is expressed in network byte order, use g_ntohs() to convert
+ * it to host order.
+ *
  * Returns: TRUE if the address could be retrieved.
  */
 #ifdef __SYMBIAN32__
@@ -250,16 +266,24 @@
 #endif
 
 gboolean
-gst_netaddress_get_ip6_address (GstNetAddress * naddr, guint8 address[16],
+gst_netaddress_get_ip6_address (const GstNetAddress * naddr, guint8 address[16],
     guint16 * port)
 {
+  static guint8 ip4_transition[16] =
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
   g_return_val_if_fail (naddr != NULL, FALSE);
 
   if (naddr->type == GST_NET_TYPE_UNKNOWN)
     return FALSE;
 
-  if (address)
-    memcpy (address, naddr->address.ip6, 16);
+  if (address) {
+    if (naddr->type == GST_NET_TYPE_IP6) {
+      memcpy (address, naddr->address.ip6, 16);
+    } else {                    /* naddr->type == GST_NET_TYPE_IP4 */
+      memcpy (address, ip4_transition, 12);
+      memcpy (address + 12, (guint8 *) & (naddr->address.ip4), 4);
+    }
+  }
   if (port)
     *port = naddr->port;
 
@@ -267,6 +291,98 @@
 }
 
 /**
+ * gst_netaddress_get_address_bytes:
+ * @naddr: a network address
+ * @address: a location to store the result.
+ * @port: a location to store the port.
+ *
+ * Get just the address bytes stored in @naddr into @address.
+ *
+ * Note that @port is expressed in network byte order, use g_ntohs() to convert
+ * it to host order. IP4 addresses are also stored in network byte order.
+ *
+ * Returns: number of bytes actually copied
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gint
+gst_netaddress_get_address_bytes (const GstNetAddress * naddr,
+    guint8 address[16], guint16 * port)
+{
+  gint ret = 0;
+
+  g_return_val_if_fail (naddr != NULL, FALSE);
+
+  if (naddr->type == GST_NET_TYPE_UNKNOWN)
+    return 0;
+
+  if (address) {
+    if (naddr->type == GST_NET_TYPE_IP6) {
+      memcpy (address, naddr->address.ip6, 16);
+      ret = 16;
+    } else {                    /* naddr->type == GST_NET_TYPE_IP4 */
+      memcpy (address, (guint8 *) & (naddr->address.ip4), 4);
+      ret = 4;
+    }
+  }
+  if (port)
+    *port = naddr->port;
+
+  return ret;
+}
+
+/**
+ * gst_netaddress_set_address_bytes:
+ * @naddr: a network address
+ * @address: a location to store the result.
+ * @port: a location to store the port.
+ *
+ * Set just the address bytes stored in @naddr into @address.
+ *
+ * Note that @port must be expressed in network byte order, use g_htons() to convert
+ * it to network byte order order. IP4 address bytes must also be stored in
+ * network byte order.
+ *
+ * Returns: number of bytes actually copied
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gint
+gst_netaddress_set_address_bytes (GstNetAddress * naddr, GstNetType type,
+    guint8 address[16], guint16 port)
+{
+  gint len = 0;
+
+  g_return_val_if_fail (naddr != NULL, 0);
+
+  naddr->type = type;
+  switch (naddr->type) {
+    case GST_NET_TYPE_UNKNOWN:
+    case GST_NET_TYPE_IP6:
+      len = 16;
+      memcpy (naddr->address.ip6, address, 16);
+      break;
+    case GST_NET_TYPE_IP4:
+      len = 4;
+      memcpy ((guint8 *) & (naddr->address.ip4), address, 4);
+      break;
+  }
+
+  if (port)
+    naddr->port = port;
+
+  return len;
+}
+
+/**
  * gst_netaddress_equal:
  * @naddr1: The first #GstNetAddress
  * @naddr2: The second #GstNetAddress
@@ -309,3 +425,68 @@
   }
   return TRUE;
 }
+
+/**
+ * gst_netaddress_to_string:
+ * @naddr: a #GstNetAddress
+ * @dest: destination
+ * @len: len of @dest
+ *
+ * Copies a string representation of @naddr into @dest. Up to @len bytes are
+ * copied.
+ *
+ * Returns: the number of bytes which would be produced if the buffer was large
+ * enough
+ *
+ * Since: 0.10.24
+ */
+ 
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gint
+gst_netaddress_to_string (const GstNetAddress * naddr, gchar * dest, gulong len)
+{
+  gint result;
+
+  g_return_val_if_fail (naddr != NULL, FALSE);
+  g_return_val_if_fail (dest != NULL, FALSE);
+
+  switch (naddr->type) {
+    case GST_NET_TYPE_IP4:
+    {
+      guint32 address;
+      guint16 port;
+
+      gst_netaddress_get_ip4_address (naddr, &address, &port);
+      address = g_ntohl (address);
+
+      result = g_snprintf (dest, len, "%d.%d.%d.%d:%d", (address >> 24) & 0xff,
+          (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff,
+          g_ntohs (port));
+      break;
+    }
+    case GST_NET_TYPE_IP6:
+    {
+      guint8 address[16];
+      guint16 port;
+
+      gst_netaddress_get_ip6_address (naddr, address, &port);
+
+      result =
+          g_snprintf (dest, len, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%d",
+          (address[0] << 8) | address[1], (address[2] << 8) | address[3],
+          (address[4] << 8) | address[5], (address[6] << 8) | address[7],
+          (address[8] << 8) | address[9], (address[10] << 8) | address[11],
+          (address[12] << 8) | address[13], (address[14] << 8) | address[15],
+          g_ntohs (port));
+      break;
+    }
+    default:
+      dest[0] = 0;
+      result = 0;
+      break;
+  }
+  return result;
+}
--- a/gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.h	Fri Apr 16 15:15:52 2010 +0300
@@ -50,6 +50,16 @@
 } GstNetType;
 
 /**
+ * GST_NETADDRESS_MAX_LEN:
+ *
+ * The maximum length of a string representation of a GstNetAddress as produced
+ * by gst_netaddress_to_string().
+ *
+ * Since: 0.10.24
+ */
+#define GST_NETADDRESS_MAX_LEN	64
+
+/**
  * GstNetAddress:
  *
  * An opaque network address as used in #GstNetBuffer.
@@ -97,48 +107,64 @@
 IMPORT_C
 #endif
 
-GType           gst_netbuffer_get_type          (void);
+GType           gst_netbuffer_get_type           (void);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
-GstNetBuffer*   gst_netbuffer_new               (void);
+GstNetBuffer*   gst_netbuffer_new                (void);
 
 /* address operations */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-void            gst_netaddress_set_ip4_address  (GstNetAddress *naddr, guint32 address, guint16 port);
+void            gst_netaddress_set_ip4_address   (GstNetAddress *naddr, guint32 address, guint16 port);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-void            gst_netaddress_set_ip6_address  (GstNetAddress *naddr, guint8 address[16], guint16 port);
+void            gst_netaddress_set_ip6_address   (GstNetAddress *naddr, guint8 address[16], guint16 port);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gint            gst_netaddress_set_address_bytes (GstNetAddress *naddr, GstNetType type,
+                                                  guint8 address[16], guint16 port);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
-GstNetType      gst_netaddress_get_net_type     (GstNetAddress *naddr);
+GstNetType      gst_netaddress_get_net_type      (const GstNetAddress *naddr);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gboolean        gst_netaddress_get_ip4_address  (GstNetAddress *naddr, guint32 *address, guint16 *port);
+gboolean        gst_netaddress_get_ip4_address   (const GstNetAddress *naddr, guint32 *address, guint16 *port);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gboolean        gst_netaddress_get_ip6_address  (GstNetAddress *naddr, guint8 address[16], guint16 *port);
+gboolean        gst_netaddress_get_ip6_address   (const GstNetAddress *naddr, guint8 address[16], guint16 *port);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gint            gst_netaddress_get_address_bytes (const GstNetAddress *naddr, guint8 address[16], guint16 *port);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
-gboolean        gst_netaddress_equal            (const GstNetAddress *naddr1,
-                                                 const GstNetAddress *naddr2);
+gboolean        gst_netaddress_equal             (const GstNetAddress *naddr1,
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+                                                  const GstNetAddress *naddr2);
+
+gint            gst_netaddress_to_string         (const GstNetAddress *naddr, gchar *dest, gulong len);
 
 G_END_DECLS
 
--- a/gst_plugins_base/gst-libs/gst/pbutils/descriptions.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/pbutils/descriptions.c	Fri Apr 16 15:15:52 2010 +0300
@@ -30,11 +30,7 @@
  * </para>
  * <para>
  * gst_pb_utils_add_codec_description_to_tag_list() is a utility function
- * for demuxer and decoder elements to add audio/
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-video codec tags from a
+ * for demuxer and decoder elements to add audio/video codec tags from a
  * given (fixed) #GstCaps.
  * </para>
  * </refsect2>
@@ -73,7 +69,10 @@
   {"application/vnd.rn-realmedia", "Realmedia", FLAG_CONTAINER},
   {"application/x-id3", N_("ID3 tag"), FLAG_CONTAINER},
   {"application/x-ape", N_("APE tag"), FLAG_CONTAINER},
+  {"application/x-apetag", N_("APE tag"), FLAG_CONTAINER},
   {"application/x-icy", N_("ICY internet radio"), FLAG_CONTAINER},
+  {"application/x-3gp", "3GP", FLAG_CONTAINER},
+  {"multipart/x-mixed-replace", "Multipart", FLAG_CONTAINER},
   {"video/x-fli", "FLI/FLC/FLX Animation", FLAG_CONTAINER},
   {"video/x-flv", "Flash", FLAG_CONTAINER},
   {"video/x-matroska", "Matroska", FLAG_CONTAINER},
@@ -81,6 +80,7 @@
   {"video/x-msvideo", "AVI", FLAG_CONTAINER},
   {"video/x-quicktime", "Quicktime", FLAG_CONTAINER},
   {"video/quicktime", "Quicktime", FLAG_CONTAINER},
+  {"video/mj2", "Motion JPEG 2000", FLAG_CONTAINER},
 
   /* audio formats with static descriptions */
   {"audio/x-ac3", "AC-3 (ATSC A/52)", 0},
@@ -120,12 +120,14 @@
   {"audio/x-nist", "Sphere NIST", 0},
   {"audio/x-nsf", "Nintendo NSF", 0},
   {"audio/x-paris", "Ensoniq PARIS", 0},
+  {"audio/x-qdm", "QDesign Music (QDM)", 0},
   {"audio/x-qdm2", "QDesign Music (QDM) 2", 0},
   {"audio/x-ralf-mpeg4-generic", "Real Audio Lossless (RALF)", 0},
   {"audio/x-sds", "SDS", 0},
   {"audio/x-shorten", "Shorten Lossless", 0},
   {"audio/x-sid", "Sid", 0},
   {"audio/x-sipro", "Sipro/ACELP.NET Voice", 0},
+  {"audio/x-siren", "Siren", 0},
   {"audio/x-spc", "SNES-SPC700 Sound File Data", 0},
   {"audio/x-speex", "Speex", 0},
   {"audio/x-svx", "Amiga IFF / SVX8 / SV16", 0},
@@ -157,7 +159,7 @@
   {"video/x-dvd-subpicture", "DVD subpicture", 0},
   {"video/x-ffv", N_("FFMpeg v1"), 0},
   {"video/x-flash-screen", "Flash Screen Video", 0},
-  {"video/x-flash-video", "Flash Video", 0},
+  {"video/x-flash-video", "Sorenson Spark Video", 0},
   {"video/x-h261", "H.261", 0},
   {"video/x-huffyuv", "Huffyuv", 0},
   {"video/x-intel-h263", "Intel H.263", 0},
@@ -204,6 +206,9 @@
   {"image/tiff", "TIFF", 0},
   {"image/x-cmu-raster", "CMU Raster Format", 0},
   {"image/x-icon", "ICO", 0},
+  {"image/x-j2c", "JPEG 2000", 0},
+  {"image/x-jpc", "JPEG 2000", 0},
+  {"image/jp2", "JPEG 2000", 0},
   {"image/x-xcf", "XFC", 0},
   {"image/x-pixmap", "XPM", 0},
   {"image/x-xpixmap", "XPM", 0},
@@ -214,8 +219,14 @@
   /* subtitle formats with static descriptions */
   {"application/x-subtitle-sami", N_("Sami subtitle format"), 0},
   {"application/x-subtitle-tmplayer", N_("TMPlayer subtitle format"), 0},
+  {"application/x-kate", "Kate", 0},
+  {"subtitle/x-kate", N_("Kate subtitle format"), 0},
   /* add variant field to typefinder? { "application/x-subtitle", N_("subtitle"), 0}, */
 
+  /* non-audio/video/container formats */
+  {"hdv/aux-v", "HDV AUX-V", 0},
+  {"hdv/aux-a", "HDV AUX-A", 0},
+
   /* formats with dynamic descriptions */
   {"audio/mpeg", NULL, 0},
   {"audio/x-adpcm", NULL, 0},
@@ -355,6 +366,8 @@
       ret = "ITU H.264";
     else if (strcmp (variant, "videosoft") == 0)
       ret = "Videosoft H.264";
+    else if (strcmp (variant, "lead") == 0)
+      ret = "Lead H.264";
     else {
       GST_WARNING ("Unknown H264 variant '%s'", variant);
       ret = "H.264";
--- a/gst_plugins_base/gst-libs/gst/pbutils/install-plugins.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/pbutils/install-plugins.c	Fri Apr 16 15:15:52 2010 +0300
@@ -144,7 +144,7 @@
  * as interlocutor to the real installer though, even more so if command line
  * argument munging is required to transform the command line arguments
  * passed by GStreamer to the helper application into arguments that are
- * understood by the reeal installer.
+ * understood by the real installer.
  * </para>
  * <para>
  * The helper application path defined at compile time can be overriden at
@@ -370,6 +370,8 @@
 #include <sys/wait.h>
 #endif
 
+#include <string.h>
+
 /* best effort to make things compile and possibly even work on win32 */
 #ifndef WEXITSTATUS
 # define WEXITSTATUS(status) ((((guint)(status)) & 0xff00) >> 8)
@@ -393,8 +395,9 @@
  *
  * This function is for X11-based applications (such as most Gtk/Qt
  * applications on linux/unix) only. You can use it to tell the external
- * the XID of your main application window, so the installer can make its
- * own window transient to your application windonw during the installation.
+ * installer the XID of your main application window. That way the installer
+ * can make its own window transient to your application window during the
+ * installation.
  *
  * If set, the XID will be passed to the installer via a --transient-for=XID
  * command line option.
@@ -509,6 +512,18 @@
 }
 
 static gboolean
+ptr_array_contains_string (GPtrArray * arr, const gchar * s)
+{
+  gint i;
+
+  for (i = 0; i < arr->len; ++i) {
+    if (strcmp ((const char *) g_ptr_array_index (arr, i), s) == 0)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+static gboolean
 gst_install_plugins_spawn_child (gchar ** details,
     GstInstallPluginsContext * ctx, GPid * child_pid, gint * exit_status)
 {
@@ -528,9 +543,10 @@
     g_ptr_array_add (arr, xid_str);
   }
 
-  /* finally, add the detail strings */
+  /* finally, add the detail strings, but without duplicates */
   while (details != NULL && details[0] != NULL) {
-    g_ptr_array_add (arr, details[0]);
+    if (!ptr_array_contains_string (arr, details[0]))
+      g_ptr_array_add (arr, details[0]);
     ++details;
   }
 
--- a/gst_plugins_base/gst-libs/gst/pbutils/missing-plugins.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/pbutils/missing-plugins.c	Fri Apr 16 15:15:52 2010 +0300
@@ -64,10 +64,6 @@
 # include <process.h>           /* getpid on win32 */
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
-
 #include "gst/gst-i18n-plugin.h"
 
 #include "pbutils.h"
@@ -134,10 +130,13 @@
   gst_structure_remove_field (s, "framerate");
   gst_structure_remove_field (s, "leaf_size");
   gst_structure_remove_field (s, "packet_size");
+  gst_structure_remove_field (s, "block_align");
+  gst_structure_remove_field (s, "metadata-interval");  /* icy caps */
   /* decoders/encoders almost always handle the usual width/height/channel/rate
    * range (and if we don't remove this then the app will have a much harder
    * time blacklisting formats it has unsuccessfully tried to install before) */
   gst_structure_remove_field (s, "width");
+  gst_structure_remove_field (s, "depth");
   gst_structure_remove_field (s, "height");
   gst_structure_remove_field (s, "channels");
   gst_structure_remove_field (s, "rate");
@@ -151,6 +150,7 @@
   gst_structure_remove_field (s, "npt-stop");
   gst_structure_remove_field (s, "play-speed");
   gst_structure_remove_field (s, "play-scale");
+  gst_structure_remove_field (s, "dynamic_range");
 
   return ret;
 }
@@ -518,6 +518,7 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 gchar *
 gst_missing_plugin_message_get_description (GstMessage * msg)
 {
--- a/gst_plugins_base/gst-libs/gst/pbutils/pbutils-enumtypes.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/pbutils/pbutils-enumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,12 +1,6 @@
 
 /* Generated data (by glib-mkenums) */
 
-
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
-
-
 #include "pbutils-enumtypes.h"
 
 #include "pbutils.h" 
@@ -22,8 +16,8 @@
 GType
 gst_install_plugins_return_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GEnumValue values[] = {
       { GST_INSTALL_PLUGINS_SUCCESS, "GST_INSTALL_PLUGINS_SUCCESS", "success" },
       { GST_INSTALL_PLUGINS_NOT_FOUND, "GST_INSTALL_PLUGINS_NOT_FOUND", "not-found" },
@@ -38,9 +32,10 @@
       { GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS, "GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS", "install-in-progress" },
       { 0, NULL, NULL }
     };
-    etype = g_enum_register_static ("GstInstallPluginsReturn", values);
+    GType g_define_type_id = g_enum_register_static ("GstInstallPluginsReturn", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 
 /* Generated data ends here */
--- a/gst_plugins_base/gst-libs/gst/pbutils/pbutils.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/pbutils/pbutils.c	Fri Apr 16 15:15:52 2010 +0300
@@ -72,10 +72,6 @@
 # include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
-
 #include "pbutils.h"
 
 #include "gst/gst-i18n-plugin.h"
@@ -109,6 +105,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif
 
   inited = TRUE;
--- a/gst_plugins_base/gst-libs/gst/riff/riff-ids.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/riff/riff-ids.h	Fri Apr 16 15:15:52 2010 +0300
@@ -52,6 +52,7 @@
 #define GST_RIFF_TAG_bext GST_MAKE_FOURCC ('b','e','x','t')
 #define GST_RIFF_TAG_BEXT GST_MAKE_FOURCC ('B','E','X','T')
 #define GST_RIFF_TAG_fact GST_MAKE_FOURCC ('f','a','c','t')
+#define GST_RIFF_TAG_acid GST_MAKE_FOURCC ('a','c','i','d')
 
 /* LIST types */
 #define GST_RIFF_LIST_movi GST_MAKE_FOURCC ('m','o','v','i')
@@ -134,6 +135,8 @@
 #define GST_RIFF_WHAM GST_MAKE_FOURCC ('W', 'H', 'A', 'M')
 #define GST_RIFF_rgb  GST_MAKE_FOURCC (0x00,0x00,0x00,0x00)
 #define GST_RIFF_RGB  GST_MAKE_FOURCC ('R', 'G', 'B', ' ')
+#define GST_RIFF_RAW  GST_MAKE_FOURCC ('R', 'A', 'W', ' ')
+#define GST_RIFF_DIB  GST_MAKE_FOURCC ('D', 'I', 'B', ' ')
 #define GST_RIFF_rle8 GST_MAKE_FOURCC (0x01,0x00,0x00,0x00)
 #define GST_RIFF_RLE8 GST_MAKE_FOURCC ('R', 'L', 'E', '8')
 #define GST_RIFF_rle4 GST_MAKE_FOURCC (0x02,0x00,0x00,0x00)
@@ -323,15 +326,26 @@
 #define GST_RIFF_WAVE_FORMAT_RT24           (0x0052)
 #define GST_RIFF_WAVE_FORMAT_PAC            (0x0053)
 #define GST_RIFF_WAVE_FORMAT_MPEGL3         (0x0055)
+#define GST_RIFF_WAVE_FORMAT_AMR_NB         (0x0057)
+#define GST_RIFF_WAVE_FORMAT_AMR_WB         (0x0058)
 #define GST_RIFF_WAVE_FORMAT_LUCENT_G723    (0x0059)
 #define GST_RIFF_WAVE_FORMAT_CIRRUS         (0x0060)
+#define GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK4  (0x0061)  /* not official */
+#define GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK3  (0x0062)  /* not official */
+/* FIXME: where are these from? are they used at all? */
+#if 0
 #define GST_RIFF_WAVE_FORMAT_ESPCM          (0x0061)
 #define GST_RIFF_WAVE_FORMAT_VOXWARE        (0x0062)
+#endif
 #define GST_RIFF_WAVE_FORMAT_CANOPUS_ATRAC  (0x0063)
 #define GST_RIFF_WAVE_FORMAT_G726_ADPCM     (0x0064)
 #define GST_RIFF_WAVE_FORMAT_G722_ADPCM     (0x0065)
 #define GST_RIFF_WAVE_FORMAT_DSAT_DISPLAY   (0x0067)
+#define GST_RIFF_WAVE_FORMAT_ADPCM_IMA_WAV (0x0069)
+/* FIXME: where are these from? are they used at all? */
+#if 0
 #define GST_RIFF_WAVE_FORMAT_VOXWARE_BYTE_ALIGNED (0x0069)
+#endif
 #define GST_RIFF_WAVE_FORMAT_VOXWARE_AC8    (0x0070)
 #define GST_RIFF_WAVE_FORMAT_VOXWARE_AC10   (0x0071)
 #define GST_RIFF_WAVE_FORMAT_VOXWARE_AC16   (0x0072)
@@ -393,8 +407,10 @@
 #define GST_RIFF_WAVE_FORMAT_IPI_RPELP      (0x0251)
 #define GST_RIFF_WAVE_FORMAT_CS2            (0x0260)
 #define GST_RIFF_WAVE_FORMAT_SONY_ATRAC3    (0x0270)
+#define GST_RIFF_WAVE_FORMAT_SIREN          (0x028E)
 #define GST_RIFF_WAVE_FORMAT_FM_TOWNS_SND   (0x0300)
 #define GST_RIFF_WAVE_FORMAT_BTV_DIGITAL    (0x0400)
+#define GST_RIFF_WAVE_FORMAT_IMC            (0x0401)
 #define GST_RIFF_WAVE_FORMAT_QDESIGN_MUSIC  (0x0450)
 #define GST_RIFF_WAVE_FORMAT_VME_VMPCM      (0x0680)
 #define GST_RIFF_WAVE_FORMAT_TPC            (0x0681)
@@ -408,14 +424,19 @@
 #define GST_RIFF_WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS (0x1500)
 #define GST_RIFF_WAVE_FORMAT_A52            (0x2000)
 #define GST_RIFF_WAVE_FORMAT_DTS            (0x2001)
+#define GST_RIFF_WAVE_FORMAT_SONIC          (0x2048)
+#define GST_RIFF_WAVE_FORMAT_SONIC_LS       (0x2048)
+#define GST_RIFF_WAVE_FORMAT_AAC_AC         (0x4143)
 #define GST_RIFF_WAVE_FORMAT_VORBIS1        (0x674f)
 #define GST_RIFF_WAVE_FORMAT_VORBIS2        (0x6750)
 #define GST_RIFF_WAVE_FORMAT_VORBIS3        (0x6751)
 #define GST_RIFF_WAVE_FORMAT_VORBIS1PLUS    (0x676f)
 #define GST_RIFF_WAVE_FORMAT_VORBIS2PLUS    (0x6770)
 #define GST_RIFF_WAVE_FORMAT_VORBIS3PLUS    (0x6771)
+#define GST_RIFF_WAVE_FORMAT_AAC_pm         (0x706d)
 #define GST_RIFF_WAVE_FORMAT_GSM_AMR_CBR    (0x7A21)
 #define GST_RIFF_WAVE_FORMAT_GSM_AMR_VBR    (0x7A22)
+#define GST_RIFF_WAVE_FORMAT_FLAC           (0xF1AC)
 #define GST_RIFF_WAVE_FORMAT_EXTENSIBLE     (0xFFFE)
   guint16 channels;
   guint32 rate;
@@ -450,6 +471,41 @@
   guint32 totalframes;
 } gst_riff_dmlh;
 
+/* taken from libsndfile/wav.c (LGPL) */
+typedef struct _gst_riff_acid {
+  /* 4 bytes (int)     type of file:
+   *  this appears to be a bit mask,however some combinations
+   *  are probably impossible and/or qualified as "errors"
+   *
+   *  0x01 On: One Shot         Off: Loop
+   *  0x02 On: Root note is Set Off: No root
+   *  0x04 On: Stretch is On,   Off: Strech is OFF
+   *  0x08 On: Disk Based       Off: Ram based
+   *  0x10 On: ??????????       Off: ????????? (Acidizer puts that ON)
+   */
+  guint32 loop_type;
+  /* 2 bytes (short)      root note
+   *  if type 0x10 is OFF : [C,C#,(...),B] -> [0x30 to 0x3B]
+   *  if type 0x10 is ON  : [C,C#,(...),B] -> [0x3C to 0x47]
+   *  (both types fit on same MIDI pitch albeit different octaves, so who cares)
+   */
+  guint16 root_note;
+  /* 2 bytes (short)      ??? always set to 0x8000
+   * 4 bytes (float)      ??? seems to be always 0
+   */
+  guint16 unknown1;
+  gfloat unknown2;
+  /* 4 bytes (int)        number of beats
+   * 2 bytes (short)      meter denominator   //always 4 in SF/ACID
+   * 2 bytes (short)      meter numerator     //always 4 in SF/ACID
+   *                      //are we sure about the order?? usually its num/denom
+   * 4 bytes (float)      tempo
+   */
+  guint32 number_of_beats;
+  guint16 meter_d, meter_n;
+  gfloat tempo;
+} gst_riff_acid;
+
 G_END_DECLS
 
 #endif /* __GST_RIFF_IDS_H__ */
--- a/gst_plugins_base/gst-libs/gst/riff/riff-media.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/riff/riff-media.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,7 +35,7 @@
 #define GST_CAT_DEFAULT riff_debug
 
 /**
- * gst_riff_create_video_caps_with_data:
+ * gst_riff_create_video_caps:
  * @codec_fcc: fourCC codec for this codec.
  * @strh: pointer to the strh stream header structure.
  * @strf: pointer to the strf stream header structure, including any
@@ -63,7 +63,11 @@
   GST_DEBUG ("video fourcc %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (codec_fcc));
 
   switch (codec_fcc) {
-    case GST_MAKE_FOURCC ('D', 'I', 'B', ' '):{
+    case GST_MAKE_FOURCC ('D', 'I', 'B', ' '): /* uncompressed RGB */
+    case GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00):
+    case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
+    case GST_MAKE_FOURCC ('R', 'A', 'W', ' '):
+    {
       gint bpp = (strf && strf->bit_cnt != 0) ? strf->bit_cnt : 8;
 
       if (strf) {
@@ -79,6 +83,7 @@
               "blue_mask", G_TYPE_INT, 0xff0000, NULL);
         } else {
           GST_WARNING ("Unhandled DIB RGB depth: %d", bpp);
+          return NULL;
         }
       } else {
         /* for template */
@@ -113,11 +118,20 @@
         *codec_name = g_strdup ("Uncompressed packed YVU 4:1:0");
       break;
 
+    case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+      caps = gst_caps_new_simple ("video/x-raw-yuv",
+          "format", GST_TYPE_FOURCC, codec_fcc, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Uncompressed packed YUV 4:2:2");
+      break;
+
     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'): /* YUY2 MJPEG */
     case GST_MAKE_FOURCC ('A', 'V', 'R', 'n'):
     case GST_MAKE_FOURCC ('I', 'J', 'P', 'G'):
     case GST_MAKE_FOURCC ('i', 'j', 'p', 'g'):
-    case GST_MAKE_FOURCC ('J', 'P', 'G', 'L'):
+    case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
+    case GST_MAKE_FOURCC ('A', 'C', 'D', 'V'):
+    case GST_MAKE_FOURCC ('Q', 'I', 'V', 'G'):
       caps = gst_caps_new_simple ("image/jpeg", NULL);
       if (codec_name)
         *codec_name = g_strdup ("Motion JPEG");
@@ -134,7 +148,25 @@
     case GST_MAKE_FOURCC ('V', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
       caps = gst_caps_new_simple ("image/jpeg", NULL);
       if (codec_name)
-        *codec_name = g_strdup ("Miro/Pinnacle Motion JPEG Video");
+        *codec_name = g_strdup ("Miro/Pinnacle Motion JPEG");
+      break;
+
+    case GST_MAKE_FOURCC ('C', 'J', 'P', 'G'):
+      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Creative Webcam JPEG");
+      break;
+
+    case GST_MAKE_FOURCC ('S', 'L', 'M', 'J'):
+      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("SL Motion JPEG");
+      break;
+
+    case GST_MAKE_FOURCC ('J', 'P', 'G', 'L'):
+      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Pegasus Lossless JPEG");
       break;
 
     case GST_MAKE_FOURCC ('S', 'P', '5', '3'):
@@ -163,14 +195,19 @@
     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
     case GST_MAKE_FOURCC ('M', 'P', 'G', '1'):
     case GST_MAKE_FOURCC ('P', 'I', 'M', '1'):
+    case GST_MAKE_FOURCC (0x01, 0x00, 0x00, 0x10):
       caps = gst_caps_new_simple ("video/mpeg",
           "systemstream", G_TYPE_BOOLEAN, FALSE,
           "mpegversion", G_TYPE_INT, 1, NULL);
       if (codec_name)
         *codec_name = g_strdup ("MPEG-1 video");
       break;
+
     case GST_MAKE_FOURCC ('M', 'P', 'G', '2'):
     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'):
+    case GST_MAKE_FOURCC ('P', 'I', 'M', '2'):
+    case GST_MAKE_FOURCC ('D', 'V', 'R', ' '):
+    case GST_MAKE_FOURCC (0x02, 0x00, 0x00, 0x10):
       caps = gst_caps_new_simple ("video/mpeg",
           "systemstream", G_TYPE_BOOLEAN, FALSE,
           "mpegversion", G_TYPE_INT, 2, NULL);
@@ -178,10 +215,20 @@
         *codec_name = g_strdup ("MPEG-2 video");
       break;
 
+    case GST_MAKE_FOURCC ('L', 'M', 'P', '2'):
+      caps = gst_caps_new_simple ("video/mpeg",
+          "systemstream", G_TYPE_BOOLEAN, FALSE,
+          "mpegversion", G_TYPE_INT, 2, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Lead MPEG-2 video");
+      break;
+
     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
     case GST_MAKE_FOURCC ('i', '2', '6', '3'):
     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
+    case GST_MAKE_FOURCC ('v', 'i', 'v', '1'):
+    case GST_MAKE_FOURCC ('T', '2', '6', '3'):
       caps = gst_caps_new_simple ("video/x-h263",
           "variant", G_TYPE_STRING, "itu", NULL);
       if (codec_name)
@@ -233,6 +280,15 @@
         *codec_name = g_strdup ("Intel H.263");
       break;
 
+    case GST_MAKE_FOURCC ('V', 'X', '1', 'K'):
+      caps = gst_caps_new_simple ("video/x-h263",
+          "variant", G_TYPE_STRING, "lucent", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Lucent VX1000S H.263");
+      break;
+
+    case GST_MAKE_FOURCC ('X', '2', '6', '4'):
+    case GST_MAKE_FOURCC ('x', '2', '6', '4'):
     case GST_MAKE_FOURCC ('H', '2', '6', '4'):
     case GST_MAKE_FOURCC ('h', '2', '6', '4'):
     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
@@ -250,6 +306,14 @@
         *codec_name = g_strdup ("VideoSoft H.264");
       break;
 
+    case GST_MAKE_FOURCC ('L', '2', '6', '4'):
+      /* http://www.leadcodecs.com/Codecs/LEAD-H264.htm */
+      caps = gst_caps_new_simple ("video/x-h264",
+          "variant", G_TYPE_STRING, "lead", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Lead H.264");
+      break;
+
     case GST_MAKE_FOURCC ('S', 'E', 'D', 'G'):
       caps = gst_caps_new_simple ("video/mpeg",
           "mpegversion", G_TYPE_INT, 4, NULL);
@@ -257,8 +321,17 @@
         *codec_name = g_strdup ("Samsung MPEG-4");
       break;
 
+    case GST_MAKE_FOURCC ('M', '4', 'C', 'C'):
+      caps = gst_caps_new_simple ("video/mpeg",
+          "mpegversion", G_TYPE_INT, 4, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Divio MPEG-4");
+      break;
+
     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
     case GST_MAKE_FOURCC ('d', 'i', 'v', '3'):
+    case GST_MAKE_FOURCC ('D', 'V', 'X', '3'):
+    case GST_MAKE_FOURCC ('d', 'v', 'x', '3'):
     case GST_MAKE_FOURCC ('D', 'I', 'V', '4'):
     case GST_MAKE_FOURCC ('d', 'i', 'v', '4'):
     case GST_MAKE_FOURCC ('D', 'I', 'V', '5'):
@@ -308,7 +381,8 @@
       break;
 
     case GST_MAKE_FOURCC ('M', 'P', 'G', '4'):
-    case GST_MAKE_FOURCC ('M', 'P', '4', 'S'):
+    case GST_MAKE_FOURCC ('M', 'P', '4', '1'):
+    case GST_MAKE_FOURCC ('m', 'p', '4', '1'):
       caps = gst_caps_new_simple ("video/x-msmpeg",
           "msmpegversion", G_TYPE_INT, 41, NULL);
       if (codec_name)
@@ -331,6 +405,7 @@
         *codec_name = g_strdup ("Microsoft MPEG-4 4.3");
       break;
 
+    case GST_MAKE_FOURCC ('M', 'P', '4', 'S'):
     case GST_MAKE_FOURCC ('M', '4', 'S', '2'):
       caps = gst_caps_new_simple ("video/mpeg",
           "mpegversion", G_TYPE_INT, 4, NULL);
@@ -340,17 +415,40 @@
 
     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
+    case GST_MAKE_FOURCC ('F', 'F', 'D', 'S'):
       caps = gst_caps_new_simple ("video/mpeg",
           "mpegversion", G_TYPE_INT, 4, NULL);
       if (codec_name)
         *codec_name = g_strdup ("FFmpeg MPEG-4");
       break;
 
+    case GST_MAKE_FOURCC ('E', 'M', '4', 'A'):
+    case GST_MAKE_FOURCC ('E', 'P', 'V', 'H'):
+    case GST_MAKE_FOURCC ('F', 'V', 'F', 'W'):
+    case GST_MAKE_FOURCC ('I', 'N', 'M', 'C'):
+    case GST_MAKE_FOURCC ('D', 'I', 'G', 'I'):
+    case GST_MAKE_FOURCC ('D', 'M', '2', 'K'):
+    case GST_MAKE_FOURCC ('D', 'C', 'O', 'D'):
+    case GST_MAKE_FOURCC ('M', 'V', 'X', 'M'):
+    case GST_MAKE_FOURCC ('P', 'M', '4', 'V'):
+    case GST_MAKE_FOURCC ('S', 'M', 'P', '4'):
+    case GST_MAKE_FOURCC ('D', 'X', 'G', 'M'):
+    case GST_MAKE_FOURCC ('V', 'I', 'D', 'M'):
+    case GST_MAKE_FOURCC ('M', '4', 'T', '3'):
+    case GST_MAKE_FOURCC ('G', 'E', 'O', 'X'):
+      caps = gst_caps_new_simple ("video/mpeg",
+          "mpegversion", G_TYPE_INT, 4, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("MPEG-4");
+      break;
+
     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
+      caps = gst_caps_new_simple ("video/x-msmpeg",
+          "msmpegversion", G_TYPE_INT, 43, NULL);
       if (codec_name)
         *codec_name = g_strdup ("Microsoft MPEG-4 4.3");        /* FIXME? */
-      return gst_caps_from_string ("video/x-msmpeg, msmpegversion = (int) 43");
+      break;
 
     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
@@ -361,13 +459,33 @@
 
     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
-    case GST_MAKE_FOURCC ('C', 'D', 'V', 'C'):
+    case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
+    case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
       caps = gst_caps_new_simple ("video/x-dv",
-          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+          "systemstream", G_TYPE_BOOLEAN, FALSE,
+          "dvversion", G_TYPE_INT, 25, NULL);
       if (codec_name)
         *codec_name = g_strdup ("Generic DV");
       break;
 
+    case GST_MAKE_FOURCC ('C', 'D', 'V', 'C'):
+    case GST_MAKE_FOURCC ('c', 'd', 'v', 'c'):
+      caps = gst_caps_new_simple ("video/x-dv",
+          "systemstream", G_TYPE_BOOLEAN, FALSE,
+          "dvversion", G_TYPE_INT, 25, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Canopus DV");
+      break;
+
+    case GST_MAKE_FOURCC ('D', 'V', '5', '0'):
+    case GST_MAKE_FOURCC ('d', 'v', '5', '0'):
+      caps = gst_caps_new_simple ("video/x-dv",
+          "systemstream", G_TYPE_BOOLEAN, FALSE,
+          "dvversion", G_TYPE_INT, 50, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("DVCPro50 Video");
+      break;
+
     case GST_MAKE_FOURCC ('W', 'M', 'V', '1'):
       caps = gst_caps_new_simple ("video/x-wmv",
           "wmvversion", G_TYPE_INT, 1, NULL);
@@ -391,7 +509,7 @@
 
     case GST_MAKE_FOURCC ('W', 'M', 'V', 'A'):
       caps = gst_caps_new_simple ("video/x-wmv",
-          "wmvversion", G_TYPE_INT, 3, "fourcc", GST_TYPE_FOURCC,
+          "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
           codec_fcc, NULL);
       if (codec_name)
         *codec_name = g_strdup ("Microsoft Windows Media Advanced Profile");
@@ -399,7 +517,7 @@
 
     case GST_MAKE_FOURCC ('W', 'V', 'C', '1'):
       caps = gst_caps_new_simple ("video/x-wmv",
-          "wmvversion", G_TYPE_INT, 3, "fourcc", GST_TYPE_FOURCC,
+          "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
           codec_fcc, NULL);
       if (codec_name)
         *codec_name = g_strdup ("Microsoft Windows Media VC-1");
@@ -428,6 +546,7 @@
     case GST_MAKE_FOURCC ('R', 'L', 'E', ' '):
     case GST_MAKE_FOURCC ('m', 'r', 'l', 'e'):
     case GST_MAKE_FOURCC (0x1, 0x0, 0x0, 0x0): /* why, why, why? */
+    case GST_MAKE_FOURCC (0x2, 0x0, 0x0, 0x0): /* why, why, why? */
       caps = gst_caps_new_simple ("video/x-rle",
           "layout", G_TYPE_STRING, "microsoft", NULL);
       palette = strf_data;
@@ -494,6 +613,7 @@
       break;
 
     case GST_MAKE_FOURCC ('C', 'L', 'J', 'R'):
+    case GST_MAKE_FOURCC ('c', 'l', 'j', 'r'):
       caps = gst_caps_new_simple ("video/x-cirrus-logic-accupak", NULL);
       if (codec_name)
         *codec_name = g_strdup ("Cirrus Logipak AccuPak");
@@ -507,6 +627,7 @@
       break;
 
     case GST_MAKE_FOURCC ('D', 'U', 'C', 'K'):
+    case GST_MAKE_FOURCC ('P', 'V', 'E', 'Z'):
       caps = gst_caps_new_simple ("video/x-truemotion",
           "trueversion", G_TYPE_INT, 1, NULL);
       if (codec_name)
@@ -608,6 +729,56 @@
         *codec_name = g_strdup ("Dirac");
       break;
 
+    case GST_RIFF_rpza:
+    case GST_RIFF_azpr:
+    case GST_MAKE_FOURCC ('R', 'P', 'Z', 'A'):
+      caps = gst_caps_new_simple ("video/x-apple-video", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Apple Video (RPZA)");
+      break;
+
+
+    case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
+      caps = gst_caps_new_simple ("video/x-ffv",
+          "ffvversion", G_TYPE_INT, 1, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("FFmpeg lossless video codec");
+      break;
+
+    case GST_MAKE_FOURCC ('K', 'M', 'V', 'C'):
+      caps = gst_caps_new_simple ("video/x-kmvc", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Karl Morton's video codec");
+      break;
+
+    case GST_MAKE_FOURCC ('v', 'p', '6', '0'):
+    case GST_MAKE_FOURCC ('V', 'P', '6', '0'):
+      caps = gst_caps_new_simple ("video/x-vp6", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("On2 VP6");
+      break;
+
+    case GST_MAKE_FOURCC ('L', 'M', '2', '0'):
+      caps = gst_caps_new_simple ("video/x-mimic", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Mimic webcam");
+      break;
+
+    case GST_MAKE_FOURCC ('T', 'H', 'E', 'O'):
+    case GST_MAKE_FOURCC ('t', 'h', 'e', 'o'):
+      caps = gst_caps_new_simple ("video/x-theora", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Theora video codec");
+
+      break;
+
+    case GST_MAKE_FOURCC ('F', 'P', 'S', '1'):
+      caps = gst_caps_new_simple ("video/x-fraps", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Fraps video");
+
+      break;
+
     default:
       GST_WARNING ("Unknown video fourcc %" GST_FOURCC_FORMAT,
           GST_FOURCC_ARGS (codec_fcc));
@@ -634,8 +805,11 @@
 
   /* extradata */
   if (strf_data || strd_data) {
-    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
-        strf_data ? strf_data : strd_data, NULL);
+    GstBuffer *codec_data;
+
+    codec_data = strf_data ? strf_data : strd_data;
+
+    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
   }
 
   /* palette */
@@ -862,6 +1036,7 @@
 
   switch (codec_id) {
     case GST_RIFF_WAVE_FORMAT_PCM:     /* PCM */
+      rate_max = 192000;
       channels_max = 8;
 
       if (strf != NULL) {
@@ -927,6 +1102,7 @@
       break;
 
     case GST_RIFF_WAVE_FORMAT_IEEE_FLOAT:
+      rate_max = 192000;
       channels_max = 8;
 
       if (strf != NULL) {
@@ -969,14 +1145,14 @@
           GST_WARNING ("invalid depth (%d) of alaw audio, overwriting.",
               strf->size);
           strf->size = 8;
-          strf->av_bps = 8;
-          strf->blockalign = strf->av_bps * strf->channels;
+          strf->blockalign = (strf->size * strf->channels) / 8;
+          strf->av_bps = strf->blockalign * strf->rate;
         }
         if (strf->av_bps == 0 || strf->blockalign == 0) {
           GST_WARNING ("fixing av_bps (%d) and blockalign (%d) of alaw audio",
               strf->av_bps, strf->blockalign);
-          strf->av_bps = strf->size;
-          strf->blockalign = strf->av_bps * strf->channels;
+          strf->blockalign = (strf->size * strf->channels) / 8;
+          strf->av_bps = strf->blockalign * strf->rate;
         }
       }
       rate_max = 48000;
@@ -1007,14 +1183,14 @@
           GST_WARNING ("invalid depth (%d) of mulaw audio, overwriting.",
               strf->size);
           strf->size = 8;
-          strf->av_bps = 8;
-          strf->blockalign = strf->av_bps * strf->channels;
+          strf->blockalign = (strf->size * strf->channels) / 8;
+          strf->av_bps = strf->blockalign * strf->rate;
         }
         if (strf->av_bps == 0 || strf->blockalign == 0) {
           GST_WARNING ("fixing av_bps (%d) and blockalign (%d) of mulaw audio",
               strf->av_bps, strf->blockalign);
-          strf->av_bps = strf->size;
-          strf->blockalign = strf->av_bps * strf->channels;
+          strf->blockalign = (strf->size * strf->channels) / 8;
+          strf->av_bps = strf->blockalign * strf->rate;
         }
       }
       rate_max = 48000;
@@ -1035,8 +1211,17 @@
       block_align = TRUE;
       break;
 
+    case GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH:
+      rate_min = 8000;
+      rate_max = 8000;
+      caps = gst_caps_new_simple ("audio/x-truespeech", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("DSP Group TrueSpeech");
+      break;
+
     case GST_RIFF_WAVE_FORMAT_GSM610:
     case GST_RIFF_WAVE_FORMAT_MSN:
+      rate_min = 1;
       caps = gst_caps_new_simple ("audio/ms-gsm", NULL);
       if (codec_name)
         *codec_name = g_strdup ("MS GSM audio");
@@ -1060,12 +1245,31 @@
         *codec_name = g_strdup ("MPEG-1 layer 3");
       break;
 
+    case GST_RIFF_WAVE_FORMAT_AMR_NB:  /* amr-nb */
+      rate_min = 8000;
+      rate_max = 8000;
+      channels_max = 1;
+      caps = gst_caps_new_simple ("audio/AMR", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("AMR Narrow Band (NB)");
+      break;
+
+    case GST_RIFF_WAVE_FORMAT_AMR_WB:  /* amr-wb */
+      rate_min = 16000;
+      rate_max = 16000;
+      channels_max = 1;
+      caps = gst_caps_new_simple ("audio/AMR-WB", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("AMR Wide Band (WB)");
+      break;
+
     case GST_RIFF_WAVE_FORMAT_VORBIS1: /* ogg/vorbis mode 1 */
     case GST_RIFF_WAVE_FORMAT_VORBIS2: /* ogg/vorbis mode 2 */
     case GST_RIFF_WAVE_FORMAT_VORBIS3: /* ogg/vorbis mode 3 */
     case GST_RIFF_WAVE_FORMAT_VORBIS1PLUS:     /* ogg/vorbis mode 1+ */
     case GST_RIFF_WAVE_FORMAT_VORBIS2PLUS:     /* ogg/vorbis mode 2+ */
     case GST_RIFF_WAVE_FORMAT_VORBIS3PLUS:     /* ogg/vorbis mode 3+ */
+      rate_max = 192000;
       caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
       if (codec_name)
         *codec_name = g_strdup ("Vorbis");
@@ -1086,6 +1290,8 @@
       rate_chan = FALSE;
       break;
     case GST_RIFF_WAVE_FORMAT_AAC:
+    case GST_RIFF_WAVE_FORMAT_AAC_AC:
+    case GST_RIFF_WAVE_FORMAT_AAC_pm:
     {
       channels_max = 8;
       caps = gst_caps_new_simple ("audio/mpeg",
@@ -1097,6 +1303,7 @@
     case GST_RIFF_WAVE_FORMAT_WMAV1:
     case GST_RIFF_WAVE_FORMAT_WMAV2:
     case GST_RIFF_WAVE_FORMAT_WMAV3:
+    case GST_RIFF_WAVE_FORMAT_WMAV3_L:
     {
       gint version = (codec_id - GST_RIFF_WAVE_FORMAT_WMAV1) + 1;
 
@@ -1106,8 +1313,12 @@
       caps = gst_caps_new_simple ("audio/x-wma",
           "wmaversion", G_TYPE_INT, version, NULL);
 
-      if (codec_name)
-        *codec_name = g_strdup_printf ("WMA Version %d", version + 6);
+      if (codec_name) {
+        if (codec_id == GST_RIFF_WAVE_FORMAT_WMAV3_L)
+          *codec_name = g_strdup ("WMA Lossless");
+        else
+          *codec_name = g_strdup_printf ("WMA Version %d", version + 6);
+      }
 
       if (strf != NULL) {
         gst_caps_set_simple (caps,
@@ -1119,17 +1330,50 @@
       }
       break;
     }
-    case GST_RIFF_WAVE_FORMAT_WMAV3_L:
-    {
-      /* WMA Version 9 Lossless */
-      goto unknown;
-    }
     case GST_RIFF_WAVE_FORMAT_SONY_ATRAC3:
       caps = gst_caps_new_simple ("audio/x-vnd.sony.atrac3", NULL);
       if (codec_name)
         *codec_name = g_strdup ("Sony ATRAC3");
       break;
 
+    case GST_RIFF_WAVE_FORMAT_SIREN:
+      caps = gst_caps_new_simple ("audio/x-siren", NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("Siren7");
+      rate_chan = FALSE;
+      break;
+
+    case GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK4:
+      rate_min = 8000;
+      rate_max = 96000;
+      channels_max = 2;
+      caps =
+          gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING, "dk4",
+          NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("IMA/DK4 ADPCM");
+      break;
+    case GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK3:
+      rate_min = 8000;
+      rate_max = 96000;
+      channels_max = 2;
+      caps =
+          gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING, "dk3",
+          NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("IMA/DK3 ADPCM");
+      break;
+
+    case GST_RIFF_WAVE_FORMAT_ADPCM_IMA_WAV:
+      rate_min = 8000;
+      rate_max = 96000;
+      channels_max = 2;
+      caps =
+          gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING, "dvi",
+          NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("IMA/WAV ADPCM");
+      break;
     case GST_RIFF_WAVE_FORMAT_EXTENSIBLE:{
       guint16 valid_bits_per_sample;
       guint32 channel_mask;
@@ -1307,8 +1551,6 @@
       break;
     }
       /* can anything decode these? pitfdll? */
-    case GST_RIFF_WAVE_FORMAT_VOXWARE:
-    case GST_RIFF_WAVE_FORMAT_VOXWARE_BYTE_ALIGNED:
     case GST_RIFF_WAVE_FORMAT_VOXWARE_AC8:
     case GST_RIFF_WAVE_FORMAT_VOXWARE_AC10:
     case GST_RIFF_WAVE_FORMAT_VOXWARE_AC16:
@@ -1349,9 +1591,16 @@
     }
   } else {
     if (rate_chan) {
-      gst_caps_set_simple (caps,
-          "rate", GST_TYPE_INT_RANGE, rate_min, rate_max,
-          "channels", GST_TYPE_INT_RANGE, 1, channels_max, NULL);
+      if (rate_min == rate_max)
+        gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate_min, NULL);
+      else
+        gst_caps_set_simple (caps,
+            "rate", GST_TYPE_INT_RANGE, rate_min, rate_max, NULL);
+      if (channels_max == 1)
+        gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL);
+      else
+        gst_caps_set_simple (caps,
+            "channels", GST_TYPE_INT_RANGE, 1, channels_max, NULL);
     }
     if (block_align) {
       gst_caps_set_simple (caps,
@@ -1434,9 +1683,12 @@
     GST_MAKE_FOURCC ('D', 'I', 'V', 'X'),
     GST_MAKE_FOURCC ('D', 'U', 'C', 'K'),
     GST_MAKE_FOURCC ('D', 'V', 'S', 'D'),
+    GST_MAKE_FOURCC ('D', 'V', '5', '0'),
     GST_MAKE_FOURCC ('D', 'X', '5', '0'),
+    GST_MAKE_FOURCC ('M', '4', 'C', 'C'),
     GST_MAKE_FOURCC ('F', 'L', 'V', '1'),
     GST_MAKE_FOURCC ('H', '2', '6', '3'),
+    GST_MAKE_FOURCC ('V', 'X', '1', 'K'),
     GST_MAKE_FOURCC ('H', '2', '6', '4'),
     GST_MAKE_FOURCC ('H', 'F', 'Y', 'U'),
     GST_MAKE_FOURCC ('I', '2', '6', '3'),
@@ -1445,6 +1697,7 @@
     GST_MAKE_FOURCC ('I', 'V', '4', '1'),
     GST_MAKE_FOURCC ('I', 'V', '5', '0'),
     GST_MAKE_FOURCC ('L', '2', '6', '3'),
+    GST_MAKE_FOURCC ('L', '2', '6', '4'),
     GST_MAKE_FOURCC ('M', '2', '6', '3'),
     GST_MAKE_FOURCC ('M', '4', 'S', '2'),
     GST_MAKE_FOURCC ('M', 'J', 'P', 'G'),
@@ -1461,6 +1714,7 @@
     GST_MAKE_FOURCC ('T', 'M', '2', '0'),
     GST_MAKE_FOURCC ('T', 'S', 'C', 'C'),
     GST_MAKE_FOURCC ('U', 'L', 'T', 'I'),
+    GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
     GST_MAKE_FOURCC ('V', 'C', 'R', '1'),
     GST_MAKE_FOURCC ('V', 'C', 'R', '2'),
     GST_MAKE_FOURCC ('V', 'D', 'O', 'W'),
@@ -1480,8 +1734,15 @@
     GST_MAKE_FOURCC ('h', '2', '6', '4'),
     GST_MAKE_FOURCC ('m', 's', 'v', 'c'),
     GST_MAKE_FOURCC ('x', '2', '6', '3'),
-    GST_MAKE_FOURCC ('d', 'r', 'a', 'c')
-        /* FILL ME */
+    GST_MAKE_FOURCC ('d', 'r', 'a', 'c'),
+    GST_MAKE_FOURCC ('F', 'F', 'V', '1'),
+    GST_MAKE_FOURCC ('K', 'M', 'V', 'C'),
+    GST_MAKE_FOURCC ('V', 'P', '6', '0'),
+    GST_MAKE_FOURCC ('L', 'M', '2', '0'),
+    GST_MAKE_FOURCC ('R', 'P', 'Z', 'A'),
+    GST_MAKE_FOURCC ('T', 'H', 'E', 'O'),
+    GST_MAKE_FOURCC ('F', 'P', 'S', '1'),
+    /* FILL ME */
   };
   guint i;
   GstCaps *caps, *one;
@@ -1517,13 +1778,20 @@
     GST_RIFF_WAVE_FORMAT_WMS,
     GST_RIFF_WAVE_FORMAT_ADPCM,
     GST_RIFF_WAVE_FORMAT_DVI_ADPCM,
+    GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH,
     GST_RIFF_WAVE_FORMAT_WMAV1,
     GST_RIFF_WAVE_FORMAT_WMAV2,
     GST_RIFF_WAVE_FORMAT_WMAV3,
     GST_RIFF_WAVE_FORMAT_SONY_ATRAC3,
     GST_RIFF_WAVE_FORMAT_IEEE_FLOAT,
-    GST_RIFF_WAVE_FORMAT_VOXWARE
-        /* FILL ME */
+    GST_RIFF_WAVE_FORMAT_VOXWARE_METASOUND,
+    GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK4,
+    GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK3,
+    GST_RIFF_WAVE_FORMAT_ADPCM_IMA_WAV,
+    GST_RIFF_WAVE_FORMAT_AMR_NB,
+    GST_RIFF_WAVE_FORMAT_AMR_WB,
+    GST_RIFF_WAVE_FORMAT_SIREN,
+    /* FILL ME */
   };
   guint i;
   GstCaps *caps, *one;
--- a/gst_plugins_base/gst-libs/gst/riff/riff-read.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/riff/riff-read.c	Fri Apr 16 15:15:52 2010 +0300
@@ -161,6 +161,10 @@
   GST_DEBUG_OBJECT (element, "fourcc=%" GST_FOURCC_FORMAT ", size=%u",
       GST_FOURCC_ARGS (fourcc), size);
 
+  /* be paranoid: size may be nonsensical value here, such as (guint) -1 */
+  if (G_UNLIKELY (size > G_MAXINT))
+    goto bogus_size;
+
   if (bufsize < size + 8 + offset) {
     GST_DEBUG_OBJECT (element,
         "Needed chunk data (%d) is more than available (%d), shortcutting",
@@ -191,6 +195,11 @@
         offset, bufsize, 8);
     return FALSE;
   }
+bogus_size:
+  {
+    GST_ERROR_OBJECT (element, "Broken file: bogus chunk size %u", size);
+    return FALSE;
+  }
 }
 
 /**
@@ -646,6 +655,10 @@
     tsize = GST_READ_UINT32_LE (data + 4);
     size -= 8;
     data += 8;
+
+    GST_DEBUG ("tag %" GST_FOURCC_FORMAT ", size %u",
+        GST_FOURCC_ARGS (tag), tsize);
+
     if (tsize > size) {
       GST_WARNING_OBJECT (element,
           "Tagsize %d is larger than available data %d", tsize, size);
@@ -688,7 +701,7 @@
         type = GST_TAG_GENRE;
         break;
       case GST_RIFF_INFO_IKEY:
-        type = NULL; /*"Keywords"; */ ;
+        type = GST_TAG_KEYWORDS;
         break;
       case GST_RIFF_INFO_ILGT:
         type = NULL;            /*"Lightness"; */
@@ -747,6 +760,12 @@
       }
     }
 
+    if (tsize & 1) {
+      tsize++;
+      if (tsize > size)
+        tsize = size;
+    }
+
     data += tsize;
     size -= tsize;
   }
--- a/gst_plugins_base/gst-libs/gst/riff/riff.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/riff/riff.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,7 +1,7 @@
 /* GStreamer RIFF I/O
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
- * riff.c: plugin registering
+ * riff.c: library initialisation
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -18,6 +18,13 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:gstriff
+ * @short_description: Riff fileformat utillity functions.
+ *
+ * A collection of functions to handle riff base files, such as avi, wav and
+ * asf.
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -26,11 +33,16 @@
 #include <gst/gst.h>
 
 GST_DEBUG_CATEGORY (riff_debug);
+
+/**
+ * gst_riff_init:
+ *
+ * Initialize riff library.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
 gst_riff_init (void)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtp/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,66 @@
+The RTP libraries
+---------------------
+
+  RTP Buffers
+  -----------
+  The real time protocol as described in RFC 3550 requires the use of special
+  packets containing an additional RTP header of at least 12 bytes. GStreamer
+  provides some helper functions for creating and parsing these RTP headers.
+  The result is a normal #GstBuffer with an additional RTP header.
+ 
+  RTP buffers are usually created with gst_rtp_buffer_new_allocate() or
+  gst_rtp_buffer_new_allocate_len(). These functions create buffers with a
+  preallocated space of memory. It will also ensure that enough memory
+  is allocated for the RTP header. The first function is used when the payload
+  size is known. gst_rtp_buffer_new_allocate_len() should be used when the size
+  of the whole RTP buffer (RTP header + payload) is known.
+ 
+  When receiving RTP buffers from a network, gst_rtp_buffer_new_take_data()
+  should be used when the user would like to parse that RTP packet. (TODO Ask
+  Wim what the real purpose of this function is as it seems to simply create a
+  duplicate GstBuffer with the same data as the previous one). The
+  function will create a new RTP buffer with the given data as the whole RTP
+  packet. Alternatively, gst_rtp_buffer_new_copy_data() can be used if the user
+  wishes to make a copy of the data before using it in the new RTP buffer. An
+  important function is gst_rtp_buffer_validate() that is used to verify that
+  the buffer a well formed RTP buffer.
+ 
+  It is now possible to use all the gst_rtp_buffer_get_*() or
+  gst_rtp_buffer_set_*() functions to read or write the different parts of the
+  RTP header such as the payload type, the sequence number or the RTP
+  timestamp. The use can also retreive a pointer to the actual RTP payload data
+  using the gst_rtp_buffer_get_payload() function.
+
+  RTP Base Payloader Class (GstBaseRTPPayload)
+  --------------------------------------------
+
+  All RTP payloader elements (audio or video) should derive from this class.
+
+  RTP Base Audio Payloader Class (GstBaseRTPAudioPayload)
+  -------------------------------------------------------
+
+  This base class can be tested through it's children classes. Here is an
+  example using the iLBC payloader (frame based).
+
+  For 20ms mode :
+
+  GST_DEBUG="basertpaudiopayload:5" gst-launch-0.10 fakesrc sizetype=2
+  sizemax=114 datarate=1900 ! audio/x-iLBC, mode=20 !  rtpilbcpay
+  max-ptime="40000000" ! fakesink
+
+  For 30ms mode :
+
+  GST_DEBUG="basertpaudiopayload:5" gst-launch-0.10 fakesrc sizetype=2
+  sizemax=150 datarate=1662 ! audio/x-iLBC, mode=30 !  rtpilbcpay
+  max-ptime="60000000" ! fakesink
+
+  Here is an example using the uLaw payloader (sample based).
+
+  GST_DEBUG="basertpaudiopayload:5" gst-launch-0.10 fakesrc sizetype=2
+  sizemax=150 datarate=8000 ! audio/x-mulaw ! rtppcmupay max-ptime="6000000" !
+  fakesink
+
+  RTP Base Depayloader Class (GstBaseRTPDepayload)
+  ------------------------------------------------
+
+  All RTP depayloader elements (audio or video) should derive from this class.
--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertpaudiopayload.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertpaudiopayload.c	Fri Apr 16 15:15:52 2010 +0300
@@ -110,10 +110,6 @@
 
 GST_BOILERPLATE (GstBaseRTPAudioPayload, gst_base_rtp_audio_payload,
     GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD);
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
 
 static void
 gst_base_rtp_audio_payload_base_init (gpointer klass)
--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.c	Fri Apr 16 15:15:52 2010 +0300
@@ -56,6 +56,10 @@
   gboolean discont;
   GstClockTime timestamp;
   GstClockTime duration;
+
+  guint32 next_seqnum;
+
+  gboolean negotiated;
 };
 
 /* Filter signals and args */
@@ -70,7 +74,8 @@
 enum
 {
   PROP_0,
-  PROP_QUEUE_DELAY
+  PROP_QUEUE_DELAY,
+  PROP_LAST
 };
 
 static void gst_base_rtp_depayload_finalize (GObject * object);
@@ -90,6 +95,8 @@
 
 static void gst_base_rtp_depayload_set_gst_timestamp
     (GstBaseRTPDepayload * filter, guint32 rtptime, GstBuffer * buf);
+static gboolean gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload *
+    filter, GstEvent * event);
 
 GST_BOILERPLATE (GstBaseRTPDepayload, gst_base_rtp_depayload, GstElement,
     GST_TYPE_ELEMENT);
@@ -128,12 +135,13 @@
   g_object_class_install_property (gobject_class, PROP_QUEUE_DELAY,
       g_param_spec_uint ("queue-delay", "Queue Delay",
           "Amount of ms to queue/buffer, deprecated", 0, G_MAXUINT,
-          DEFAULT_QUEUE_DELAY, G_PARAM_READWRITE));
+          DEFAULT_QUEUE_DELAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 #endif
 
   gstelement_class->change_state = gst_base_rtp_depayload_change_state;
 
   klass->set_gst_timestamp = gst_base_rtp_depayload_set_gst_timestamp;
+  klass->packet_lost = gst_base_rtp_depayload_packet_lost;
 
   GST_DEBUG_CATEGORY_INIT (basertpdepayload_debug, "basertpdepayload", 0,
       "Base class for RTP Depayloaders");
@@ -237,6 +245,8 @@
   else
     res = TRUE;
 
+  priv->negotiated = res;
+
   gst_object_unref (filter);
 
   return res;
@@ -251,29 +261,89 @@
   GstFlowReturn ret = GST_FLOW_OK;
   GstBuffer *out_buf;
   GstClockTime timestamp;
+  guint16 seqnum;
+  guint32 rtptime;
+  gboolean reset_seq, discont;
+  gint gap;
 
   filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad));
+  priv = filter->priv;
 
-  priv = filter->priv;
+  /* we must have a setcaps first */
+  if (G_UNLIKELY (!priv->negotiated))
+    goto not_negotiated;
+
+  /* we must validate, it's possible that this element is plugged right after a
+   * network receiver and we don't want to operate on invalid data */
+  if (G_UNLIKELY (!gst_rtp_buffer_validate (in)))
+    goto invalid_buffer;
+
   priv->discont = GST_BUFFER_IS_DISCONT (in);
 
+  timestamp = GST_BUFFER_TIMESTAMP (in);
   /* convert to running_time and save the timestamp, this is the timestamp
    * we put on outgoing buffers. */
-  timestamp = GST_BUFFER_TIMESTAMP (in);
   timestamp = gst_segment_to_running_time (&filter->segment, GST_FORMAT_TIME,
       timestamp);
   priv->timestamp = timestamp;
   priv->duration = GST_BUFFER_DURATION (in);
 
+  seqnum = gst_rtp_buffer_get_seq (in);
+  rtptime = gst_rtp_buffer_get_timestamp (in);
+  reset_seq = TRUE;
+  discont = FALSE;
+
+  GST_LOG_OBJECT (filter, "discont %d, seqnum %u, rtptime %u, timestamp %"
+      GST_TIME_FORMAT, priv->discont, seqnum, rtptime,
+      GST_TIME_ARGS (timestamp));
+
+  /* Check seqnum. This is a very simple check that makes sure that the seqnums
+   * are striclty increasing, dropping anything that is out of the ordinary. We
+   * can only do this when the next_seqnum is known. */
+  if (G_LIKELY (priv->next_seqnum != -1)) {
+    gap = gst_rtp_buffer_compare_seqnum (seqnum, priv->next_seqnum);
+
+    /* if we have no gap, all is fine */
+    if (G_UNLIKELY (gap != 0)) {
+      GST_LOG_OBJECT (filter, "got packet %u, expected %u, gap %d", seqnum,
+          priv->next_seqnum, gap);
+      if (gap < 0) {
+        /* seqnum > next_seqnum, we are missing some packets, this is always a
+         * DISCONT. */
+        GST_LOG_OBJECT (filter, "%d missing packets", gap);
+        discont = TRUE;
+      } else {
+        /* seqnum < next_seqnum, we have seen this packet before or the sender
+         * could be restarted. If the packet is not too old, we throw it away as
+         * a duplicate, otherwise we mark discont and continue. 100 misordered
+         * packets is a good threshold. See also RFC 4737. */
+        if (gap < 100)
+          goto dropping;
+
+        GST_LOG_OBJECT (filter,
+            "%d > 100, packet too old, sender likely restarted", gap);
+        discont = TRUE;
+      }
+    }
+  }
+  priv->next_seqnum = (seqnum + 1) & 0xffff;
+
+  if (G_UNLIKELY (discont && !priv->discont)) {
+    GST_LOG_OBJECT (filter, "mark DISCONT on input buffer");
+    /* we detected a seqnum discont but the buffer was not flagged with a discont,
+     * set the discont flag so that the subclass can throw away old data. */
+    priv->discont = TRUE;
+    GST_BUFFER_FLAG_SET (in, GST_BUFFER_FLAG_DISCONT);
+  }
+
   bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
 
+  if (G_UNLIKELY (bclass->process == NULL))
+    goto no_process;
+
   /* let's send it out to processing */
   out_buf = bclass->process (filter, in);
   if (out_buf) {
-    guint32 rtptime;
-
-    rtptime = gst_rtp_buffer_get_timestamp (in);
-
     /* we pass rtptime as backward compatibility, in reality, the incomming
      * buffer timestamp is always applied to the outgoing packet. */
     ret = gst_base_rtp_depayload_push_ts (filter, rtptime, out_buf);
@@ -281,6 +351,38 @@
   gst_buffer_unref (in);
 
   return ret;
+
+  /* ERRORS */
+not_negotiated:
+  {
+    /* this is not fatal but should be filtered earlier */
+    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL),
+        ("Not RTP format was negotiated"));
+    gst_buffer_unref (in);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+invalid_buffer:
+  {
+    /* this is not fatal but should be filtered earlier */
+    GST_ELEMENT_WARNING (filter, STREAM, DECODE, (NULL),
+        ("Received invalid RTP payload, dropping"));
+    gst_buffer_unref (in);
+    return GST_FLOW_OK;
+  }
+dropping:
+  {
+    GST_WARNING_OBJECT (filter, "%d <= 100, dropping old packet", gap);
+    gst_buffer_unref (in);
+    return GST_FLOW_OK;
+  }
+no_process:
+  {
+    /* this is not fatal but should be filtered earlier */
+    GST_ELEMENT_ERROR (filter, STREAM, NOT_IMPLEMENTED, (NULL),
+        ("The subclass does not have a process method"));
+    gst_buffer_unref (in);
+    return GST_FLOW_ERROR;
+  }
 }
 
 static gboolean
@@ -297,6 +399,7 @@
 
       gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED);
       filter->need_newsegment = TRUE;
+      filter->priv->next_seqnum = -1;
       break;
     case GST_EVENT_NEWSEGMENT:
     {
@@ -316,6 +419,29 @@
       gst_event_unref (event);
       break;
     }
+    case GST_EVENT_CUSTOM_DOWNSTREAM:
+    {
+      GstBaseRTPDepayloadClass *bclass;
+
+      bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
+
+      if (gst_event_has_name (event, "GstRTPPacketLost")) {
+        /* we get this event from the jitterbuffer when it considers a packet as
+         * being lost. We send it to our packet_lost vmethod. The default
+         * implementation will make time progress by pushing out a NEWSEGMENT
+         * update event. Subclasses can override and to one of the following:
+         *  - Adjust timestamp/duration to something more accurate before
+         *    calling the parent (default) packet_lost method.
+         *  - do some more advanced error concealing on the already received
+         *    (fragmented) packets.
+         *  - ignore the packet lost.
+         */
+        if (bclass->packet_lost)
+          res = bclass->packet_lost (filter, event);
+      }
+      gst_event_unref (event);
+      break;
+    }
     default:
       /* pass other events forward */
       res = gst_pad_push_event (filter->srcpad, event);
@@ -324,6 +450,28 @@
   return res;
 }
 
+static GstEvent *
+create_segment_event (GstBaseRTPDepayload * filter, gboolean update,
+    GstClockTime position)
+{
+  GstEvent *event;
+  GstClockTime stop;
+  GstBaseRTPDepayloadPrivate *priv;
+
+  priv = filter->priv;
+
+  if (priv->npt_stop != -1)
+    stop = priv->npt_stop - priv->npt_start;
+  else
+    stop = -1;
+
+  event = gst_event_new_new_segment_full (update, priv->play_speed,
+      priv->play_scale, GST_FORMAT_TIME, position, stop,
+      position + priv->npt_start);
+
+  return event;
+}
+
 static GstFlowReturn
 gst_base_rtp_depayload_push_full (GstBaseRTPDepayload * filter,
     gboolean do_ts, guint32 rtptime, GstBuffer * out_buf)
@@ -337,7 +485,7 @@
 
   /* set the caps if any */
   srccaps = GST_PAD_CAPS (filter->srcpad);
-  if (srccaps)
+  if (G_LIKELY (srccaps))
     gst_buffer_set_caps (out_buf, srccaps);
 
   bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
@@ -346,7 +494,20 @@
   if (bclass->set_gst_timestamp && do_ts)
     bclass->set_gst_timestamp (filter, rtptime, out_buf);
 
-  if (priv->discont) {
+  /* if this is the first buffer send a NEWSEGMENT */
+  if (G_UNLIKELY (filter->need_newsegment)) {
+    GstEvent *event;
+
+    event = create_segment_event (filter, FALSE, 0);
+
+    gst_pad_push_event (filter->srcpad, event);
+
+    filter->need_newsegment = FALSE;
+    GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer");
+  }
+
+  if (G_UNLIKELY (priv->discont)) {
+    GST_LOG_OBJECT (filter, "Marking DISCONT on output buffer");
     GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT);
     priv->discont = FALSE;
   }
@@ -355,8 +516,8 @@
   GST_LOG_OBJECT (filter, "Pushing buffer size %d, timestamp %" GST_TIME_FORMAT,
       GST_BUFFER_SIZE (out_buf),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf)));
+
   ret = gst_pad_push (filter->srcpad, out_buf);
-  GST_LOG_OBJECT (filter, "Pushed buffer: %s", gst_flow_get_name (ret));
 
   return ret;
 }
@@ -410,6 +571,38 @@
   return gst_base_rtp_depayload_push_full (filter, FALSE, 0, out_buf);
 }
 
+/* convert the PacketLost event form a jitterbuffer to a segment update.
+ * subclasses can override this.  */
+static gboolean
+gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload * filter,
+    GstEvent * event)
+{
+  GstBaseRTPDepayloadPrivate *priv;
+  GstClockTime timestamp, duration, position;
+  GstEvent *sevent;
+  const GstStructure *s;
+
+  priv = filter->priv;
+
+  s = gst_event_get_structure (event);
+
+  /* first start by parsing the timestamp and duration */
+  timestamp = -1;
+  duration = -1;
+
+  gst_structure_get_clock_time (s, "timestamp", &timestamp);
+  gst_structure_get_clock_time (s, "duration", &duration);
+
+  position = timestamp;
+  if (duration != -1)
+    position += duration;
+
+  /* update the current segment with the elapsed time */
+  sevent = create_segment_event (filter, TRUE, position);
+
+  return gst_pad_push_event (filter->srcpad, sevent);
+}
+
 static void
 gst_base_rtp_depayload_set_gst_timestamp (GstBaseRTPDepayload * filter,
     guint32 rtptime, GstBuffer * buf)
@@ -428,28 +621,6 @@
     GST_BUFFER_TIMESTAMP (buf) = priv->timestamp;
   if (!GST_CLOCK_TIME_IS_VALID (duration))
     GST_BUFFER_DURATION (buf) = priv->duration;
-
-  /* if this is the first buffer send a NEWSEGMENT */
-  if (filter->need_newsegment) {
-    GstEvent *event;
-    GstClockTime stop, position;
-
-    if (priv->npt_stop != -1)
-      stop = priv->npt_stop - priv->npt_start;
-    else
-      stop = -1;
-
-    position = priv->npt_start;
-
-    event =
-        gst_event_new_new_segment_full (FALSE, priv->play_speed,
-        priv->play_scale, GST_FORMAT_TIME, 0, stop, position);
-
-    gst_pad_push_event (filter->srcpad, event);
-
-    filter->need_newsegment = FALSE;
-    GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer");
-  }
 }
 
 static GstStateChangeReturn
@@ -472,6 +643,8 @@
       priv->npt_stop = -1;
       priv->play_speed = 1.0;
       priv->play_scale = 1.0;
+      priv->next_seqnum = -1;
+      priv->negotiated = FALSE;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.h	Fri Apr 16 15:15:52 2010 +0300
@@ -96,7 +96,7 @@
 {
   GstElementClass parent_class;
 
-  /* virtuals */
+  /* virtuals, inform the subclass of the caps. */
   gboolean (*set_caps) (GstBaseRTPDepayload *filter, GstCaps *caps);
 
   /* non-pure function, default implementation in base class
@@ -104,17 +104,23 @@
   GstFlowReturn (*add_to_queue) (GstBaseRTPDepayload *filter, GstBuffer *in);
 
   /* pure virtual function, child must use this to process incoming
-   * rtp packets. If the child returns a buffer, the timestamp of @in will be
-   * applied to the result buffer and the buffer will be pushed. If this
-   * function returns %NULL, nothing is pushed.  */
+   * rtp packets. If the child returns a buffer without a valid timestamp,
+   * the timestamp of @in will be applied to the result buffer and the
+   * buffer will be pushed. If this function returns %NULL, nothing is
+   * pushed.  */
   GstBuffer * (*process) (GstBaseRTPDepayload *base, GstBuffer *in);
 
   /* non-pure function used to convert from RTP timestamp to GST timestamp
    * this function is used by the child class before gst_pad_pushing */
   void (*set_gst_timestamp) (GstBaseRTPDepayload *filter, guint32 timestamp, GstBuffer *buf);
 
+  /* non-pure function used to to signal the depayloader about packet loss. the
+   * timestamp and duration are the estimated values of the lost packet.
+   * The default implementation of this message pushes a segment update. */
+  gboolean (*packet_lost) (GstBaseRTPDepayload *filter, GstEvent *event);
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING-1];
 };
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c	Fri Apr 16 15:15:52 2010 +0300
@@ -45,8 +45,6 @@
   gboolean seqnum_offset_random;
   gboolean ssrc_random;
   guint16 next_seqnum;
-
-  GstClockTime rt_base;
 };
 
 /* BaseRTPPayload signals and args */
@@ -90,8 +88,8 @@
     gpointer g_class);
 static void gst_basertppayload_finalize (GObject * object);
 
-static gboolean gst_basertppayload_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_basertppayload_getcaps (GstPad * pad);
+static gboolean gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_basertppayload_sink_getcaps (GstPad * pad);
 static gboolean gst_basertppayload_event (GstPad * pad, GstEvent * event);
 static GstFlowReturn gst_basertppayload_chain (GstPad * pad,
     GstBuffer * buffer);
@@ -163,28 +161,31 @@
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU,
       g_param_spec_uint ("mtu", "MTU",
           "Maximum size of one packet",
-          28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE));
+          28, G_MAXUINT, DEFAULT_MTU,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
       g_param_spec_uint ("pt", "payload type",
-          "The payload type of the packets",
-          0, 0x80, DEFAULT_PT, G_PARAM_READWRITE));
+          "The payload type of the packets", 0, 0x80, DEFAULT_PT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
       g_param_spec_uint ("ssrc", "SSRC",
-          "The SSRC of the packets (default == random)",
-          0, G_MAXUINT32, DEFAULT_SSRC, G_PARAM_READWRITE));
+          "The SSRC of the packets (default == random)", 0, G_MAXUINT32,
+          DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass),
       PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset",
           "Timestamp Offset",
           "Offset to add to all outgoing timestamps (default = random)", 0,
-          G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET, G_PARAM_READWRITE));
+          G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16,
-          DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE));
+          DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME,
       g_param_spec_int64 ("max-ptime", "Max packet time",
           "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)",
-          -1, G_MAXINT64, DEFAULT_MAX_PTIME, G_PARAM_READWRITE));
+          -1, G_MAXINT64, DEFAULT_MAX_PTIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstBaseRTPAudioPayload:min-ptime:
    *
@@ -195,16 +196,17 @@
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME,
       g_param_spec_int64 ("min-ptime", "Min packet time",
           "Minimum duration of the packet data in ns (can't go above MTU)",
-          0, G_MAXINT64, DEFAULT_MIN_PTIME, G_PARAM_READWRITE));
+          0, G_MAXINT64, DEFAULT_MIN_PTIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
       g_param_spec_uint ("timestamp", "Timestamp",
           "The RTP timestamp of the last processed packet",
-          0, G_MAXUINT32, 0, G_PARAM_READABLE));
+          0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
       g_param_spec_uint ("seqnum", "Sequence number",
           "The RTP sequence number of the last processed packet",
-          0, G_MAXUINT16, 0, G_PARAM_READABLE));
+          0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state = gst_basertppayload_change_state;
 
@@ -234,9 +236,9 @@
 
   basertppayload->sinkpad = gst_pad_new_from_template (templ, "sink");
   gst_pad_set_setcaps_function (basertppayload->sinkpad,
-      gst_basertppayload_setcaps);
+      gst_basertppayload_sink_setcaps);
   gst_pad_set_getcaps_function (basertppayload->sinkpad,
-      gst_basertppayload_getcaps);
+      gst_basertppayload_sink_getcaps);
   gst_pad_set_event_function (basertppayload->sinkpad,
       gst_basertppayload_event);
   gst_pad_set_chain_function (basertppayload->sinkpad,
@@ -288,7 +290,7 @@
 }
 
 static gboolean
-gst_basertppayload_setcaps (GstPad * pad, GstCaps * caps)
+gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstBaseRTPPayload *basertppayload;
   GstBaseRTPPayloadClass *basertppayload_class;
@@ -307,7 +309,7 @@
 }
 
 static GstCaps *
-gst_basertppayload_getcaps (GstPad * pad)
+gst_basertppayload_sink_getcaps (GstPad * pad)
 {
   GstBaseRTPPayload *basertppayload;
   GstBaseRTPPayloadClass *basertppayload_class;
@@ -477,8 +479,9 @@
     ...)
 {
   GstCaps *srccaps, *peercaps;
+  gboolean res;
 
-  /* fill in the defaults, there properties cannot be negotiated. */
+  /* fill in the defaults, their properties cannot be negotiated. */
   srccaps = gst_caps_new_simple ("application/x-rtp",
       "media", G_TYPE_STRING, payload->media,
       "clock-rate", G_TYPE_INT, payload->clock_rate,
@@ -591,10 +594,10 @@
     GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
   }
 
-  gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
+  res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
   gst_caps_unref (srccaps);
 
-  return TRUE;
+  return res;
 }
 
 /**
@@ -603,7 +606,7 @@
  * @size: the size of the packet
  * @duration: the duration of the packet
  *
- * Check if the packet with @size and @duration would exceed the configure
+ * Check if the packet with @size and @duration would exceed the configured
  * maximum size.
  *
  * Returns: %TRUE if the packet of @size and @duration would exceed the
@@ -626,6 +629,155 @@
   return FALSE;
 }
 
+typedef struct
+{
+  GstBaseRTPPayload *payload;
+  guint32 ssrc;
+  guint16 seqnum;
+  guint8 pt;
+  GstCaps *caps;
+  GstClockTime timestamp;
+  guint32 rtptime;
+} HeaderData;
+
+static GstBufferListItem
+find_timestamp (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
+{
+  data->timestamp = GST_BUFFER_TIMESTAMP (*buffer);
+
+  /* stop when we find a timestamp */
+  if (data->timestamp != -1)
+    return GST_BUFFER_LIST_END;
+  else
+    return GST_BUFFER_LIST_CONTINUE;
+}
+
+static GstBufferListItem
+set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
+{
+  gst_rtp_buffer_set_ssrc (*buffer, data->ssrc);
+  gst_rtp_buffer_set_payload_type (*buffer, data->pt);
+  gst_rtp_buffer_set_seq (*buffer, data->seqnum);
+  gst_rtp_buffer_set_timestamp (*buffer, data->rtptime);
+  gst_buffer_set_caps (*buffer, data->caps);
+  data->seqnum++;
+
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
+
+/* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer
+ * before the buffer is pushed. */
+static GstFlowReturn
+gst_basertppayload_prepare_push (GstBaseRTPPayload * payload,
+    gpointer obj, gboolean is_list)
+{
+  GstBaseRTPPayloadPrivate *priv;
+  HeaderData data;
+
+  if (payload->clock_rate == 0)
+    goto no_rate;
+
+  priv = payload->priv;
+
+  /* update first, so that the property is set to the last
+   * seqnum pushed */
+  payload->seqnum = priv->next_seqnum;
+
+  /* fill in the fields we want to set on all headers */
+  data.payload = payload;
+  data.seqnum = payload->seqnum;
+  data.ssrc = payload->current_ssrc;
+  data.pt = payload->pt;
+  data.caps = GST_PAD_CAPS (payload->srcpad);
+  data.timestamp = -1;
+
+  /* find the first buffer with a timestamp */
+  if (is_list) {
+    gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
+        (GstBufferListFunc) find_timestamp, &data);
+  } else {
+    data.timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (obj));
+  }
+
+  /* convert to RTP time */
+  if (GST_CLOCK_TIME_IS_VALID (data.timestamp)) {
+    gint64 rtime;
+
+    rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
+        data.timestamp);
+
+    rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
+
+    /* add running_time in clock-rate units to the base timestamp */
+    data.rtptime = payload->ts_base + rtime;
+  } else {
+    /* no timestamp to convert, take previous timestamp */
+    data.rtptime = payload->timestamp;
+  }
+
+  /* set ssrc, payload type, seq number, caps and rtptime */
+  if (is_list) {
+    gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
+        (GstBufferListFunc) set_headers, &data);
+  } else {
+    GstBuffer *buf = GST_BUFFER_CAST (obj);
+    set_headers (&buf, 0, 0, &data);
+  }
+
+  priv->next_seqnum = data.seqnum;
+  payload->timestamp = data.rtptime;
+
+  GST_LOG_OBJECT (payload,
+      "Preparing to push packet with size %d, seq=%d, rtptime=%u, timestamp %"
+      GST_TIME_FORMAT, (is_list) ? -1 :
+      GST_BUFFER_SIZE (GST_BUFFER (obj)), payload->seqnum, data.rtptime,
+      GST_TIME_ARGS (data.timestamp));
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+no_rate:
+  {
+    GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
+        ("subclass did not specify clock-rate"));
+    return GST_FLOW_ERROR;
+  }
+}
+
+/**
+ * gst_basertppayload_push_list:
+ * @payload: a #GstBaseRTPPayload
+ * @list: a #GstBufferList
+ *
+ * Push @list to the peer element of the payloader. The SSRC, payload type,
+ * seqnum and timestamp of the RTP buffer will be updated first.
+ *
+ * This function takes ownership of @list.
+ *
+ * Returns: a #GstFlowReturn.
+ *
+ * Since: 0.10.24
+ */
+ 
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstFlowReturn
+gst_basertppayload_push_list (GstBaseRTPPayload * payload, GstBufferList * list)
+{
+  GstFlowReturn res;
+
+  res = gst_basertppayload_prepare_push (payload, list, TRUE);
+
+  if (G_LIKELY (res == GST_FLOW_OK))
+    res = gst_pad_push_list (payload->srcpad, list);
+  else
+    gst_buffer_list_unref (list);
+
+  return res;
+}
+
 /**
  * gst_basertppayload_push:
  * @payload: a #GstBaseRTPPayload
@@ -646,78 +798,15 @@
 gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer)
 {
   GstFlowReturn res;
-  GstClockTime timestamp;
-  guint32 rtptime;
-  GstBaseRTPPayloadPrivate *priv;
 
-  if (payload->clock_rate == 0)
-    goto no_rate;
-
-  priv = payload->priv;
-
-  gst_rtp_buffer_set_ssrc (buffer, payload->current_ssrc);
-
-  gst_rtp_buffer_set_payload_type (buffer, payload->pt);
-
-  /* update first, so that the property is set to the last
-   * seqnum pushed */
-  payload->seqnum = priv->next_seqnum;
-  gst_rtp_buffer_set_seq (buffer, payload->seqnum);
-
-  /* can wrap around, which is perfectly fine */
-  priv->next_seqnum++;
-
-  /* add our random offset to the timestamp */
-  rtptime = payload->ts_base;
-
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-    gint64 rtime;
-
-    rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
-        timestamp);
+  res = gst_basertppayload_prepare_push (payload, buffer, FALSE);
 
-    /* take first timestamp as base, we want to calculate the RTP timestamp
-     * starting from the ts_base */
-    if (priv->rt_base == -1) {
-      priv->rt_base = rtime;
-      GST_LOG_OBJECT (payload, "first timestamp %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (rtime));
-    }
-    rtime -= priv->rt_base;
-
-    rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
-
-    /* add running_time in clock-rate units to the base timestamp */
-    rtptime += rtime;
-  } else {
-    /* no timestamp to convert, take previous timestamp */
-    rtptime = payload->timestamp;
-  }
-  gst_rtp_buffer_set_timestamp (buffer, rtptime);
-
-  payload->timestamp = rtptime;
-
-  /* set caps */
-  gst_buffer_set_caps (buffer, GST_PAD_CAPS (payload->srcpad));
-
-  GST_LOG_OBJECT (payload,
-      "Pushing packet size %d, seq=%d, rtptime=%u, timestamp %" GST_TIME_FORMAT,
-      GST_BUFFER_SIZE (buffer), payload->seqnum, rtptime,
-      GST_TIME_ARGS (timestamp));
-
-  res = gst_pad_push (payload->srcpad, buffer);
+  if (G_LIKELY (res == GST_FLOW_OK))
+    res = gst_pad_push (payload->srcpad, buffer);
+  else
+    gst_buffer_unref (buffer);
 
   return res;
-
-  /* ERRORS */
-no_rate:
-  {
-    GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
-        ("subclass did not specify clock-rate"));
-    gst_buffer_unref (buffer);
-    return GST_FLOW_ERROR;
-  }
 }
 
 static void
@@ -843,6 +932,7 @@
       else
         basertppayload->seqnum_base = basertppayload->seqnum_offset;
       priv->next_seqnum = basertppayload->seqnum_base;
+      basertppayload->seqnum = basertppayload->seqnum_base;
 
       if (priv->ssrc_random)
         basertppayload->current_ssrc = g_rand_int (basertppayload->ssrc_rand);
@@ -853,8 +943,7 @@
         basertppayload->ts_base = g_rand_int (basertppayload->ts_rand);
       else
         basertppayload->ts_base = basertppayload->ts_offset;
-
-      priv->rt_base = -1;
+      basertppayload->timestamp = basertppayload->ts_base;
       break;
     default:
       break;
--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.h	Fri Apr 16 15:15:52 2010 +0300
@@ -118,7 +118,7 @@
   /* receive caps on the sink pad, configure the payloader. */
   gboolean      (*set_caps)             (GstBaseRTPPayload *payload, GstCaps *caps);
   /* handle a buffer, perform 0 or more gst_basertppayload_push() on
-   * the RTP buffers */
+   * the RTP buffers. This function takes ownership of the buffer. */
   GstFlowReturn (*handle_buffer)        (GstBaseRTPPayload *payload, 
                                          GstBuffer *buffer);
   gboolean      (*handle_event)         (GstPad * pad, GstEvent * event);
@@ -162,8 +162,14 @@
 
 
 GstFlowReturn   gst_basertppayload_push                 (GstBaseRTPPayload *payload, 
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
                                                          GstBuffer *buffer);
 
+GstFlowReturn   gst_basertppayload_push_list            (GstBaseRTPPayload *payload,
+                                                         GstBufferList *list);
+
 G_END_DECLS
 
 #endif /* __GST_BASE_RTP_PAYLOAD_H__ */
--- a/gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -36,14 +36,18 @@
  * <para>
  * An RTCP buffer consists of 1 or more #GstRTCPPacket structures that you can
  * retrieve with gst_rtcp_buffer_get_first_packet(). #GstRTCPPacket acts as a pointer
- * into the RTCP buffer; you can move to the next packet with
+ * into the RTCP buffer;
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+ you can move to the next packet with
  * gst_rtcp_packet_move_to_next().
  * </para>
  * </refsect2>
  *
- * Since: 0.10.13
+ * Last reviewed on 2007-03-26 (0.10.13)
  *
- * Last reviewed on 2007-03-26 (0.10.13)
+ * Since: 0.10.13
  */
 
 #include <string.h>
@@ -405,7 +409,8 @@
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
+
 gboolean
 gst_rtcp_packet_move_to_next (GstRTCPPacket * packet)
 {
@@ -488,6 +493,11 @@
     case GST_RTCP_TYPE_APP:
       len = 12;
       break;
+    case GST_RTCP_TYPE_RTPFB:
+      len = 12;
+      break;
+    case GST_RTCP_TYPE_PSFB:
+      len = 12;
     default:
       goto unknown_type;
   }
@@ -525,21 +535,38 @@
  * gst_rtcp_packet_remove:
  * @packet: a #GstRTCPPacket
  *
- * Removes the packet pointed to by @packet.
+ * Removes the packet pointed to by @packet and moves pointer to the next one
  *
- * Note: Not implemented.
+ * Returns: TRUE if @packet is pointing to a valid packet after calling this
+ * function.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-void
+gboolean
 gst_rtcp_packet_remove (GstRTCPPacket * packet)
 {
-  g_return_if_fail (packet != NULL);
-  g_return_if_fail (packet->type != GST_RTCP_TYPE_INVALID);
+  gboolean ret = FALSE;
+  guint offset = 0;
+
+  g_return_val_if_fail (packet != NULL, FALSE);
+  g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
+
+  /* The next packet starts at offset + length + 4 (the header) */
+  offset = packet->offset + (packet->length << 2) + 4;
 
-  g_warning ("not implemented");
+  /* Overwrite this packet with the rest of the data */
+  memmove (GST_BUFFER_DATA (packet->buffer) + packet->offset,
+      GST_BUFFER_DATA (packet->buffer) + offset,
+      GST_BUFFER_SIZE (packet->buffer) - offset);
+
+  /* try to read next header */
+  ret = read_packet_header (packet);
+  if (!ret)
+    packet->type = GST_RTCP_TYPE_INVALID;
+
+  return ret;
 }
 
 /**
@@ -569,7 +596,8 @@
  *
  * Get the packet type of the packet pointed to by @packet.
  *
- * Returns: The packet type.
+ * Returns: The packet type or GST_RTCP_TYPE_INVALID when @packet is not
+ * pointing to a valid packet.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -579,8 +607,6 @@
 gst_rtcp_packet_get_type (GstRTCPPacket * packet)
 {
   g_return_val_if_fail (packet != NULL, GST_RTCP_TYPE_INVALID);
-  g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID,
-      GST_RTCP_TYPE_INVALID);
 
   return packet->type;
 }
@@ -1779,6 +1805,187 @@
 }
 
 /**
+ * gst_rtcp_packet_fb_get_sender_ssrc:
+ * @packet: a valid RTPFB or PSFB #GstRTCPPacket
+ *
+ * Get the sender SSRC field of the RTPFB or PSFB @packet.
+ *
+ * Returns: the sender SSRC.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket * packet)
+{
+  guint8 *data;
+  guint32 ssrc;
+
+  g_return_val_if_fail (packet != NULL, 0);
+  g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
+          packet->type == GST_RTCP_TYPE_PSFB), 0);
+  g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0);
+
+  data = GST_BUFFER_DATA (packet->buffer);
+
+  /* skip header */
+  data += packet->offset + 4;
+  ssrc = GST_READ_UINT32_BE (data);
+
+  return ssrc;
+}
+
+/**
+ * gst_rtcp_packet_fb_set_sender_ssrc:
+ * @packet: a valid RTPFB or PSFB #GstRTCPPacket
+ * @ssrc: a sender SSRC
+ *
+ * Set the sender SSRC field of the RTPFB or PSFB @packet.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket * packet, guint32 ssrc)
+{
+  guint8 *data;
+
+  g_return_if_fail (packet != NULL);
+  g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
+      packet->type == GST_RTCP_TYPE_PSFB);
+  g_return_if_fail (GST_IS_BUFFER (packet->buffer));
+
+  data = GST_BUFFER_DATA (packet->buffer);
+
+  /* skip header */
+  data += packet->offset + 4;
+  GST_WRITE_UINT32_BE (data, ssrc);
+}
+
+/**
+ * gst_rtcp_packet_fb_get_media_ssrc:
+ * @packet: a valid RTPFB or PSFB #GstRTCPPacket
+ *
+ * Get the media SSRC field of the RTPFB or PSFB @packet.
+ *
+ * Returns: the media SSRC.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket * packet)
+{
+  guint8 *data;
+  guint32 ssrc;
+
+  g_return_val_if_fail (packet != NULL, 0);
+  g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
+          packet->type == GST_RTCP_TYPE_PSFB), 0);
+  g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0);
+
+  data = GST_BUFFER_DATA (packet->buffer);
+
+  /* skip header and sender ssrc */
+  data += packet->offset + 8;
+  ssrc = GST_READ_UINT32_BE (data);
+
+  return ssrc;
+}
+
+/**
+ * gst_rtcp_packet_fb_set_media_ssrc:
+ * @packet: a valid RTPFB or PSFB #GstRTCPPacket
+ * @ssrc: a media SSRC
+ *
+ * Set the media SSRC field of the RTPFB or PSFB @packet.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket * packet, guint32 ssrc)
+{
+  guint8 *data;
+
+  g_return_if_fail (packet != NULL);
+  g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
+      packet->type == GST_RTCP_TYPE_PSFB);
+  g_return_if_fail (GST_IS_BUFFER (packet->buffer));
+
+  data = GST_BUFFER_DATA (packet->buffer);
+
+  /* skip header and sender ssrc */
+  data += packet->offset + 8;
+  GST_WRITE_UINT32_BE (data, ssrc);
+}
+
+/**
+ * gst_rtcp_packet_fb_get_type:
+ * @packet: a valid RTPFB or PSFB #GstRTCPPacket
+ *
+ * Get the feedback message type of the FB @packet.
+ *
+ * Returns: The feedback message type.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstRTCPFBType
+gst_rtcp_packet_fb_get_type (GstRTCPPacket * packet)
+{
+  g_return_val_if_fail (packet != NULL, GST_RTCP_FB_TYPE_INVALID);
+  g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
+      packet->type == GST_RTCP_TYPE_PSFB, GST_RTCP_FB_TYPE_INVALID);
+
+  return packet->count;
+}
+
+/**
+ * gst_rtcp_packet_fb_set_type:
+ * @packet: a valid RTPFB or PSFB #GstRTCPPacket
+ * @type: the #GstRTCPFBType to set
+ *
+ * Set the feedback message type of the FB @packet.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_rtcp_packet_fb_set_type (GstRTCPPacket * packet, GstRTCPFBType type)
+{
+  guint8 *data;
+
+  g_return_if_fail (packet != NULL);
+  g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
+      packet->type == GST_RTCP_TYPE_PSFB);
+  g_return_if_fail (GST_IS_BUFFER (packet->buffer));
+
+  data = GST_BUFFER_DATA (packet->buffer);
+
+  data[packet->offset] = (data[packet->offset] & 0xe0) | type;
+  packet->count = type;
+}
+
+/**
  * gst_rtcp_ntp_to_unix:
  * @ntptime: an NTP timestamp
  *
@@ -1819,7 +2026,7 @@
  * bits, the fractional seconds. The resulting value can be used as an ntptime
  * for constructing SR RTCP packets.
  *
- * Returns: the NTP time for @gsttime.
+ * Returns: the NTP time for @unixtime.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
--- a/gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.h	Fri Apr 16 15:15:52 2010 +0300
@@ -42,6 +42,8 @@
  * @GST_RTCP_TYPE_SDES: Source description
  * @GST_RTCP_TYPE_BYE: Goodbye
  * @GST_RTCP_TYPE_APP: Application defined
+ * @GST_RTCP_TYPE_RTPFB: Transport layer feedback. Since: 0.10.23
+ * @GST_RTCP_TYPE_PSFB: Payload-specific feedback. Since: 0.10.23
  *
  * Different RTCP packet types.
  */
@@ -52,9 +54,37 @@
   GST_RTCP_TYPE_RR      = 201,
   GST_RTCP_TYPE_SDES    = 202,
   GST_RTCP_TYPE_BYE     = 203,
-  GST_RTCP_TYPE_APP     = 204
+  GST_RTCP_TYPE_APP     = 204,
+  GST_RTCP_TYPE_RTPFB   = 205,
+  GST_RTCP_TYPE_PSFB    = 206
 } GstRTCPType;
 
+/**
+ * GstRTCPFBType:
+ * @GST_RTCP_FB_TYPE_INVALID: Invalid type
+ * @GST_RTCP_RTPFB_TYPE_NACK: Generic NACK
+ * @GST_RTCP_PSFB_TYPE_PLI: Picture Loss Indication
+ * @GST_RTCP_PSFB_TYPE_SLI: Slice Loss Indication
+ * @GST_RTCP_PSFB_TYPE_RPSI: Reference Picture Selection Indication
+ * @GST_RTCP_PSFB_TYPE_AFB: Application layer Feedback
+ *
+ * Different types of feedback messages.
+ *
+ * Since: 0.10.23
+ */
+typedef enum
+{
+  /* generic */
+  GST_RTCP_FB_TYPE_INVALID    = 0,
+  /* RTPFB types */
+  GST_RTCP_RTPFB_TYPE_NACK    = 1,
+  /* PSFB types */
+  GST_RTCP_PSFB_TYPE_PLI      = 1,
+  GST_RTCP_PSFB_TYPE_SLI      = 2,
+  GST_RTCP_PSFB_TYPE_RPSI     = 3,
+  GST_RTCP_PSFB_TYPE_AFB      = 15
+} GstRTCPFBType;
+
 /** 
  * GstRTCPSDESType:
  * @GST_RTCP_SDES_INVALID: Invalid SDES entry
@@ -213,7 +243,7 @@
 IMPORT_C
 #endif
 
-void            gst_rtcp_packet_remove            (GstRTCPPacket *packet);
+gboolean        gst_rtcp_packet_remove            (GstRTCPPacket *packet);
 
 /* working with packets */
 #ifdef __SYMBIAN32__
@@ -392,6 +422,38 @@
 
 gboolean        gst_rtcp_packet_bye_set_reason        (GstRTCPPacket *packet, const gchar *reason);
 
+/* feedback packets */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint32         gst_rtcp_packet_fb_get_sender_ssrc    (GstRTCPPacket *packet);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_rtcp_packet_fb_set_sender_ssrc    (GstRTCPPacket *packet, guint32 ssrc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint32         gst_rtcp_packet_fb_get_media_ssrc     (GstRTCPPacket *packet);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_rtcp_packet_fb_set_media_ssrc     (GstRTCPPacket *packet, guint32 ssrc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstRTCPFBType   gst_rtcp_packet_fb_get_type           (GstRTCPPacket *packet);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_rtcp_packet_fb_set_type           (GstRTCPPacket *packet, GstRTCPFBType type);
+
 /* helper functions */
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -69,20 +69,19 @@
   guint8 csrclist[4];           /* optional CSRC list, 32 bits each */
 } GstRTPHeader;
 
-#define GST_RTP_HEADER_VERSION(buf)     (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->version)
-#define GST_RTP_HEADER_PADDING(buf)     (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->padding)
-#define GST_RTP_HEADER_EXTENSION(buf)   (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->extension)
-#define GST_RTP_HEADER_CSRC_COUNT(buf)  (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc_count)
-#define GST_RTP_HEADER_MARKER(buf)      (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->marker)
-#define GST_RTP_HEADER_PAYLOAD_TYPE(buf)(((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->payload_type)
-#define GST_RTP_HEADER_SEQ(buf)         (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->seq)
-#define GST_RTP_HEADER_TIMESTAMP(buf)   (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->timestamp)
-#define GST_RTP_HEADER_SSRC(buf)        (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->ssrc)
-#define GST_RTP_HEADER_CSRC_LIST_OFFSET(buf,i)  \
-    GST_BUFFER_DATA (buf) +                     \
-    G_STRUCT_OFFSET(GstRTPHeader, csrclist) +   \
+#define GST_RTP_HEADER_VERSION(data)      (((GstRTPHeader *)(data))->version)
+#define GST_RTP_HEADER_PADDING(data)      (((GstRTPHeader *)(data))->padding)
+#define GST_RTP_HEADER_EXTENSION(data)    (((GstRTPHeader *)(data))->extension)
+#define GST_RTP_HEADER_CSRC_COUNT(data)   (((GstRTPHeader *)(data))->csrc_count)
+#define GST_RTP_HEADER_MARKER(data)       (((GstRTPHeader *)(data))->marker)
+#define GST_RTP_HEADER_PAYLOAD_TYPE(data) (((GstRTPHeader *)(data))->payload_type)
+#define GST_RTP_HEADER_SEQ(data)          (((GstRTPHeader *)(data))->seq)
+#define GST_RTP_HEADER_TIMESTAMP(data)    (((GstRTPHeader *)(data))->timestamp)
+#define GST_RTP_HEADER_SSRC(data)         (((GstRTPHeader *)(data))->ssrc)
+#define GST_RTP_HEADER_CSRC_LIST_OFFSET(data,i)        \
+    data + G_STRUCT_OFFSET(GstRTPHeader, csrclist) +   \
     ((i) * sizeof(guint32))
-#define GST_RTP_HEADER_CSRC_SIZE(buf)   (GST_RTP_HEADER_CSRC_COUNT(buf) * sizeof (guint32))
+#define GST_RTP_HEADER_CSRC_SIZE(data)   (GST_RTP_HEADER_CSRC_COUNT(data) * sizeof (guint32))
 
 /**
  * gst_rtp_buffer_allocate_data:
@@ -105,6 +104,7 @@
     guint8 pad_len, guint8 csrc_count)
 {
   guint len;
+  guint8 *data;
 
   g_return_if_fail (csrc_count <= 15);
   g_return_if_fail (GST_IS_BUFFER (buffer));
@@ -112,22 +112,23 @@
   len = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32)
       + payload_len + pad_len;
 
-  GST_BUFFER_MALLOCDATA (buffer) = g_malloc (len);
-  GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
+  data = g_malloc (len);
+  GST_BUFFER_MALLOCDATA (buffer) = data;
+  GST_BUFFER_DATA (buffer) = data;
   GST_BUFFER_SIZE (buffer) = len;
 
   /* fill in defaults */
-  GST_RTP_HEADER_VERSION (buffer) = GST_RTP_VERSION;
-  GST_RTP_HEADER_PADDING (buffer) = FALSE;
-  GST_RTP_HEADER_EXTENSION (buffer) = FALSE;
-  GST_RTP_HEADER_CSRC_COUNT (buffer) = csrc_count;
-  memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, 0), 0,
+  GST_RTP_HEADER_VERSION (data) = GST_RTP_VERSION;
+  GST_RTP_HEADER_PADDING (data) = FALSE;
+  GST_RTP_HEADER_EXTENSION (data) = FALSE;
+  GST_RTP_HEADER_CSRC_COUNT (data) = csrc_count;
+  memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, 0), 0,
       csrc_count * sizeof (guint32));
-  GST_RTP_HEADER_MARKER (buffer) = FALSE;
-  GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = 0;
-  GST_RTP_HEADER_SEQ (buffer) = 0;
-  GST_RTP_HEADER_TIMESTAMP (buffer) = 0;
-  GST_RTP_HEADER_SSRC (buffer) = 0;
+  GST_RTP_HEADER_MARKER (data) = FALSE;
+  GST_RTP_HEADER_PAYLOAD_TYPE (data) = 0;
+  GST_RTP_HEADER_SEQ (data) = 0;
+  GST_RTP_HEADER_TIMESTAMP (data) = 0;
+  GST_RTP_HEADER_SSRC (data) = 0;
 }
 
 /**
@@ -316,23 +317,18 @@
 }
 
 /**
- * gst_rtp_buffer_validate_data:
+ * validate_data:
  * @data: the data to validate
  * @len: the length of @data to validate
+ * @payload: the payload if @data represents the header only
+ * @payload_len: the len of the payload
  *
- * Check if the @data and @size point to the data of a valid RTP packet.
- * This function checks the length, version and padding of the packet data.
- * Use this function to validate a packet before using the other functions in
- * this module.
+ * Checks if @data is a valid RTP packet.
  *
- * Returns: TRUE if the data points to a valid RTP packet.
+ * Returns: TRUE if @data is a valid RTP packet
  */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gboolean
-gst_rtp_buffer_validate_data (guint8 * data, guint len)
+static gboolean
+validate_data (guint8 * data, guint len, guint8 * payload, guint payload_len)
 {
   guint8 padding;
   guint8 csrc_count;
@@ -346,8 +342,8 @@
     goto wrong_length;
 
   /* check version */
-  version = (data[0] & 0xc0) >> 6;
-  if (G_UNLIKELY (version != GST_RTP_VERSION))
+  version = (data[0] & 0xc0);
+  if (G_UNLIKELY (version != (GST_RTP_VERSION << 6)))
     goto wrong_version;
 
   /* calc header length with csrc */
@@ -376,13 +372,17 @@
   }
 
   /* check for padding */
-  if (data[0] & 0x20)
-    padding = data[len - 1];
-  else
+  if (data[0] & 0x20) {
+    if (payload)
+      padding = payload[payload_len - 1];
+    else
+      padding = data[len - 1];
+  } else {
     padding = 0;
+  }
 
-  /* check if padding not bigger than packet and header */
-  if (G_UNLIKELY (len - header_len < padding))
+  /* check if padding and header not bigger than packet length */
+  if (G_UNLIKELY (len < padding + header_len))
     goto wrong_padding;
 
   return TRUE;
@@ -406,11 +406,35 @@
 }
 
 /**
+ * gst_rtp_buffer_validate_data:
+ * @data: the data to validate
+ * @len: the length of @data to validate
+ *
+ * Check if the @data and @size point to the data of a valid RTP packet.
+ * This function checks the length, version and padding of the packet data.
+ * Use this function to validate a packet before using the other functions in
+ * this module.
+ *
+ * Returns: TRUE if the data points to a valid RTP packet.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_rtp_buffer_validate_data (guint8 * data, guint len)
+{
+  return validate_data (data, len, NULL, 0);
+}
+
+/**
  * gst_rtp_buffer_validate:
  * @buffer: the buffer to validate
  *
  * Check if the data pointed to by @buffer is a valid RTP packet using
- * gst_rtp_buffer_validate_data().
+ * validate_data().
+ * Use this function to validate a packet before using the other functions in
+ * this module.
  *
  * Returns: TRUE if @buffer is a valid RTP packet.
  */
@@ -429,7 +453,99 @@
   data = GST_BUFFER_DATA (buffer);
   len = GST_BUFFER_SIZE (buffer);
 
-  return gst_rtp_buffer_validate_data (data, len);
+  return validate_data (data, len, NULL, 0);
+}
+
+/**
+ * gst_rtp_buffer_list_validate:
+ * @list: the buffer list to validate
+ *
+ * Check if all RTP packets in the @list are valid using validate_data().
+ * Use this function to validate an list before using the other functions in
+ * this module.
+ *
+ * Returns: TRUE if @list consists only of valid RTP packets.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_rtp_buffer_list_validate (GstBufferList * list)
+{
+  guint16 prev_seqnum = 0;
+  GstBufferListIterator *it;
+  guint i = 0;
+
+  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE);
+
+  it = gst_buffer_list_iterate (list);
+  g_return_val_if_fail (it != NULL, FALSE);
+
+  /* iterate through all the RTP packets in the list */
+  while (gst_buffer_list_iterator_next_group (it)) {
+    GstBuffer *rtpbuf;
+    GstBuffer *paybuf;
+    guint8 *packet_header;
+    guint8 *packet_payload;
+    guint payload_size;
+    guint packet_size;
+
+    /* each group should consists of 2 buffers: one containing the RTP header
+     * and the other one the payload, FIXME, relax the requirement of only one
+     * payload buffer. */
+    if (gst_buffer_list_iterator_n_buffers (it) != 2)
+      goto invalid_list;
+
+    /* get the RTP header */
+    rtpbuf = gst_buffer_list_iterator_next (it);
+    packet_header = GST_BUFFER_DATA (rtpbuf);
+    if (packet_header == NULL)
+      goto invalid_list;
+
+    /* get the payload */
+    paybuf = gst_buffer_list_iterator_next (it);
+    packet_payload = GST_BUFFER_DATA (paybuf);
+    if (packet_payload == NULL) {
+      goto invalid_list;
+    }
+    payload_size = GST_BUFFER_SIZE (paybuf);
+    if (payload_size == 0) {
+      goto invalid_list;
+    }
+
+    /* the size of the RTP packet within the current group */
+    packet_size = GST_BUFFER_SIZE (rtpbuf) + payload_size;
+
+    /* check the sequence number */
+    if (G_UNLIKELY (i == 0)) {
+      prev_seqnum = g_ntohs (GST_RTP_HEADER_SEQ (packet_header));
+      i++;
+    } else {
+      if (++prev_seqnum != g_ntohs (GST_RTP_HEADER_SEQ (packet_header)))
+        goto invalid_list;
+    }
+
+    /* validate packet */
+    if (!validate_data (packet_header, packet_size, packet_payload,
+            payload_size)) {
+      goto invalid_list;
+    }
+  }
+
+  gst_buffer_list_iterator_free (it);
+
+  return TRUE;
+
+  /* ERRORS */
+invalid_list:
+  {
+    gst_buffer_list_iterator_free (it);
+    return FALSE;
+  }
 }
 
 /**
@@ -448,22 +564,20 @@
 gst_rtp_buffer_set_packet_len (GstBuffer * buffer, guint len)
 {
   guint oldlen;
-
-  g_return_if_fail (GST_IS_BUFFER (buffer));
+  guint8 *data;
 
   oldlen = GST_BUFFER_SIZE (buffer);
+  data = GST_BUFFER_DATA (buffer);
 
   if (oldlen < len) {
-    guint8 *newdata;
-
-    newdata = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len);
-    GST_BUFFER_MALLOCDATA (buffer) = newdata;
-    GST_BUFFER_DATA (buffer) = newdata;
+    data = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len);
+    GST_BUFFER_MALLOCDATA (buffer) = data;
+    GST_BUFFER_DATA (buffer) = data;
   }
   GST_BUFFER_SIZE (buffer) = len;
 
   /* remove any padding */
-  GST_RTP_HEADER_PADDING (buffer) = FALSE;
+  GST_RTP_HEADER_PADDING (data) = FALSE;
 }
 
 /**
@@ -481,8 +595,6 @@
 guint
 gst_rtp_buffer_get_packet_len (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-
   return GST_BUFFER_SIZE (buffer);
 }
 
@@ -503,12 +615,13 @@
 gst_rtp_buffer_get_header_len (GstBuffer * buffer)
 {
   guint len;
+  guint8 *data;
 
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  data = GST_BUFFER_DATA (buffer);
 
-  len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (buffer);
-  if (GST_RTP_HEADER_EXTENSION (buffer))
-    len += GST_READ_UINT16_BE (GST_BUFFER_DATA (buffer) + len + 2) * 4 + 4;
+  len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data);
+  if (GST_RTP_HEADER_EXTENSION (data))
+    len += GST_READ_UINT16_BE (data + len + 2) * 4 + 4;
 
   return len;
 }
@@ -528,10 +641,7 @@
 guint8
 gst_rtp_buffer_get_version (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
-
-  return GST_RTP_HEADER_VERSION (buffer);
+  return GST_RTP_HEADER_VERSION (GST_BUFFER_DATA (buffer));
 }
 
 /**
@@ -548,11 +658,9 @@
 void
 gst_rtp_buffer_set_version (GstBuffer * buffer, guint8 version)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
   g_return_if_fail (version < 0x04);
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
 
-  GST_RTP_HEADER_VERSION (buffer) = version;
+  GST_RTP_HEADER_VERSION (GST_BUFFER_DATA (buffer)) = version;
 }
 
 /**
@@ -570,10 +678,7 @@
 gboolean
 gst_rtp_buffer_get_padding (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
-
-  return GST_RTP_HEADER_PADDING (buffer);
+  return GST_RTP_HEADER_PADDING (GST_BUFFER_DATA (buffer));
 }
 
 /**
@@ -590,10 +695,7 @@
 void
 gst_rtp_buffer_set_padding (GstBuffer * buffer, gboolean padding)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
-
-  GST_RTP_HEADER_PADDING (buffer) = padding;
+  GST_RTP_HEADER_PADDING (GST_BUFFER_DATA (buffer)) = padding;
 }
 
 /**
@@ -613,13 +715,14 @@
 void
 gst_rtp_buffer_pad_to (GstBuffer * buffer, guint len)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+  guint8 *data;
+
+  data = GST_BUFFER_DATA (buffer);
 
   if (len > 0)
-    GST_RTP_HEADER_PADDING (buffer) = TRUE;
+    GST_RTP_HEADER_PADDING (data) = TRUE;
   else
-    GST_RTP_HEADER_PADDING (buffer) = FALSE;
+    GST_RTP_HEADER_PADDING (data) = FALSE;
 
   /* FIXME, set the padding byte at the end of the payload data */
 }
@@ -639,10 +742,7 @@
 gboolean
 gst_rtp_buffer_get_extension (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
-
-  return GST_RTP_HEADER_EXTENSION (buffer);
+  return GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer));
 }
 
 /**
@@ -659,10 +759,7 @@
 void
 gst_rtp_buffer_set_extension (GstBuffer * buffer, gboolean extension)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
-
-  GST_RTP_HEADER_EXTENSION (buffer) = extension;
+  GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer)) = extension;
 }
 
 /**
@@ -694,15 +791,14 @@
   guint len;
   guint8 *pdata;
 
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
+  pdata = GST_BUFFER_DATA (buffer);
 
-  if (!GST_RTP_HEADER_EXTENSION (buffer))
+  if (!GST_RTP_HEADER_EXTENSION (pdata))
     return FALSE;
 
   /* move to the extension */
-  len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (buffer);
-  pdata = GST_BUFFER_DATA (buffer) + len;
+  len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (pdata);
+  pdata += len;
 
   if (bits)
     *bits = GST_READ_UINT16_BE (pdata);
@@ -740,27 +836,32 @@
   guint32 min_size = 0;
   guint8 *data;
 
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
+  data = GST_BUFFER_DATA (buffer);
 
-  gst_rtp_buffer_set_extension (buffer, TRUE);
+  /* check if the buffer is big enough to hold the extension */
   min_size =
-      GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (buffer) + 4 +
+      GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data) + 4 +
       length * sizeof (guint32);
+  if (G_UNLIKELY (min_size > GST_BUFFER_SIZE (buffer)))
+    goto too_small;
+
+  /* now we can set the extension bit */
+  gst_rtp_buffer_set_extension (buffer, TRUE);
 
-  if (min_size > GST_BUFFER_SIZE (buffer)) {
-    GST_WARNING_OBJECT (buffer,
-        "rtp buffer too small: need more than %d bytes but only have %d bytes",
+  data += GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data);
+  GST_WRITE_UINT16_BE (data, bits);
+  GST_WRITE_UINT16_BE (data + 2, length);
+
+  return TRUE;
+
+  /* ERRORS */
+too_small:
+  {
+    g_warning
+        ("rtp buffer too small: need more than %d bytes but only have %d bytes",
         min_size, GST_BUFFER_SIZE (buffer));
     return FALSE;
   }
-
-  data =
-      GST_BUFFER_DATA (buffer) + GST_RTP_HEADER_LEN +
-      GST_RTP_HEADER_CSRC_SIZE (buffer);
-  GST_WRITE_UINT16_BE (data, bits);
-  GST_WRITE_UINT16_BE (data + 2, length);
-  return TRUE;
 }
 
 /**
@@ -778,10 +879,34 @@
 guint32
 gst_rtp_buffer_get_ssrc (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+  return g_ntohl (GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer)));
+}
 
-  return g_ntohl (GST_RTP_HEADER_SSRC (buffer));
+/**
+ * gst_rtp_buffer_list_get_ssrc:
+ * @list: the buffer list
+ *
+ * Get the SSRC of the first RTP packet in @list.
+ * All RTP packets within @list have the same SSRC.
+ *
+ * Returns: the SSRC of @list in host order.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_rtp_buffer_list_get_ssrc (GstBufferList * list)
+{
+  GstBuffer *buffer;
+
+  buffer = gst_buffer_list_get (list, 0, 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+
+  return g_ntohl (GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer)));
 }
 
 /**
@@ -798,10 +923,32 @@
 void
 gst_rtp_buffer_set_ssrc (GstBuffer * buffer, guint32 ssrc)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+  GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer)) = g_htonl (ssrc);
+}
+
+static GstBufferListItem
+set_ssrc_header (GstBuffer ** buffer, guint group, guint idx, guint32 * ssrc)
+{
+  GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (*buffer)) = g_htonl (*ssrc);
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
 
-  GST_RTP_HEADER_SSRC (buffer) = g_htonl (ssrc);
+/**
+ * gst_rtp_buffer_list_set_ssrc:
+ * @list: the buffer list
+ * @ssrc: the new SSRC
+ *
+ * Set the SSRC on each RTP packet in @list to @ssrc.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+void
+gst_rtp_buffer_list_set_ssrc (GstBufferList * list, guint32 ssrc)
+{
+  gst_buffer_list_foreach (list, (GstBufferListFunc) set_ssrc_header, &ssrc);
 }
 
 /**
@@ -819,10 +966,7 @@
 guint8
 gst_rtp_buffer_get_csrc_count (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
-
-  return GST_RTP_HEADER_CSRC_COUNT (buffer);
+  return GST_RTP_HEADER_CSRC_COUNT (GST_BUFFER_DATA (buffer));
 }
 
 /**
@@ -841,11 +985,13 @@
 guint32
 gst_rtp_buffer_get_csrc (GstBuffer * buffer, guint8 idx)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
-  g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (buffer), 0);
+  guint8 *data;
+
+  data = GST_BUFFER_DATA (buffer);
 
-  return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, idx));
+  g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data), 0);
+
+  return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx));
 }
 
 /**
@@ -863,11 +1009,13 @@
 void
 gst_rtp_buffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
-  g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (buffer));
+  guint8 *data;
+
+  data = GST_BUFFER_DATA (buffer);
 
-  GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, idx), csrc);
+  g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data));
+
+  GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx), csrc);
 }
 
 /**
@@ -885,10 +1033,7 @@
 gboolean
 gst_rtp_buffer_get_marker (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
-
-  return GST_RTP_HEADER_MARKER (buffer);
+  return GST_RTP_HEADER_MARKER (GST_BUFFER_DATA (buffer));
 }
 
 /**
@@ -905,10 +1050,7 @@
 void
 gst_rtp_buffer_set_marker (GstBuffer * buffer, gboolean marker)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
-
-  GST_RTP_HEADER_MARKER (buffer) = marker;
+  GST_RTP_HEADER_MARKER (GST_BUFFER_DATA (buffer)) = marker;
 }
 
 /**
@@ -926,10 +1068,34 @@
 guint8
 gst_rtp_buffer_get_payload_type (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+  return GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer));
+}
 
-  return GST_RTP_HEADER_PAYLOAD_TYPE (buffer);
+/**
+ * gst_rtp_buffer_list_get_payload_type:
+ * @list: the buffer list
+ *
+ * Get the payload type of the first RTP packet in @list.
+ * All packets in @list should have the same payload type.
+ *
+ * Returns: The payload type.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint8
+gst_rtp_buffer_list_get_payload_type (GstBufferList * list)
+{
+  GstBuffer *buffer;
+
+  buffer = gst_buffer_list_get (list, 0, 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+
+  return GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer));
 }
 
 /**
@@ -946,11 +1112,39 @@
 void
 gst_rtp_buffer_set_payload_type (GstBuffer * buffer, guint8 payload_type)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
   g_return_if_fail (payload_type < 0x80);
 
-  GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = payload_type;
+  GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer)) = payload_type;
+}
+
+static GstBufferListItem
+set_pt_header (GstBuffer ** buffer, guint group, guint idx, guint8 * pt)
+{
+  GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (*buffer)) = *pt;
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
+
+/**
+ * gst_rtp_buffer_list_set_payload_type:
+ * @list: the buffer list
+ * @payload_type: the new type
+ *
+ * Set the payload type of each RTP packet in @list to @payload_type.
+ *
+ * Since: 0.10.24
+ */
+ 
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+ 
+void
+gst_rtp_buffer_list_set_payload_type (GstBufferList * list, guint8 payload_type)
+{
+  g_return_if_fail (payload_type < 0x80);
+
+  gst_buffer_list_foreach (list, (GstBufferListFunc) set_pt_header,
+      &payload_type);
 }
 
 /**
@@ -968,10 +1162,7 @@
 guint16
 gst_rtp_buffer_get_seq (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
-
-  return g_ntohs (GST_RTP_HEADER_SEQ (buffer));
+  return g_ntohs (GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer)));
 }
 
 /**
@@ -988,13 +1179,69 @@
 void
 gst_rtp_buffer_set_seq (GstBuffer * buffer, guint16 seq)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+  GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer)) = g_htons (seq);
+}
+
+static GstBufferListItem
+set_seq_header (GstBuffer ** buffer, guint group, guint idx, guint16 * seq)
+{
+  GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (*buffer)) = g_htons (*seq);
+  (*seq)++;
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
+
+/**
+ * gst_rtp_buffer_list_set_seq:
+ * @list: the buffer list
+ * @seq: the new sequence number
+ *
+ * Set the sequence number of each RTP packet in @list to @seq.
+ *
+ * Returns: The seq number of the last packet in the list + 1.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-  GST_RTP_HEADER_SEQ (buffer) = g_htons (seq);
+guint16
+gst_rtp_buffer_list_set_seq (GstBufferList * list, guint16 seq)
+{
+  gst_buffer_list_foreach (list, (GstBufferListFunc) set_seq_header, &seq);
+  return seq;
 }
 
 /**
+ * gst_rtp_buffer_list_get_seq:
+ * @list: the buffer list
+ *
+ * Get the sequence number of the first RTP packet in @list.
+ * All packets within @list have the same sequence number.
+ *
+ * Returns: The seq number
+ *
+ * Since: 0.10.24
+ */
+ 
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+ 
+guint16
+gst_rtp_buffer_list_get_seq (GstBufferList * list)
+{
+  GstBuffer *buffer;
+
+  buffer = gst_buffer_list_get (list, 0, 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+
+  return g_ntohl (GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer)));
+}
+
+
+/**
  * gst_rtp_buffer_get_timestamp:
  * @buffer: the buffer
  *
@@ -1009,10 +1256,34 @@
 guint32
 gst_rtp_buffer_get_timestamp (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+  return g_ntohl (GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer)));
+}
 
-  return g_ntohl (GST_RTP_HEADER_TIMESTAMP (buffer));
+/**
+ * gst_rtp_buffer_list_get_timestamp:
+ * @list: the buffer list
+ *
+ * Get the timestamp of the first RTP packet in @list.
+ * All packets within @list have the same timestamp.
+ *
+ * Returns: The timestamp in host order.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_rtp_buffer_list_get_timestamp (GstBufferList * list)
+{
+  GstBuffer *buffer;
+
+  buffer = gst_buffer_list_get (list, 0, 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+
+  return g_ntohl (GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer)));
 }
 
 /**
@@ -1029,10 +1300,37 @@
 void
 gst_rtp_buffer_set_timestamp (GstBuffer * buffer, guint32 timestamp)
 {
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+  GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer)) = g_htonl (timestamp);
+}
+
+
+static GstBufferListItem
+set_timestamp_header (GstBuffer ** buffer, guint group, guint idx,
+    guint32 * timestamp)
+{
+  GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (*buffer)) = g_htonl (*timestamp);
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
 
-  GST_RTP_HEADER_TIMESTAMP (buffer) = g_htonl (timestamp);
+/**
+ * gst_rtp_buffer_list_set_timestamp:
+ * @list: the buffer list
+ * @timestamp: the new timestamp
+ *
+ * Set the timestamp of each RTP packet in @list to @timestamp.
+ *
+ * Since: 0.10.24
+ */
+ 
+ #ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_rtp_buffer_list_set_timestamp (GstBufferList * list, guint32 timestamp)
+{
+  gst_buffer_list_foreach (list, (GstBufferListFunc) set_timestamp_header,
+      &timestamp);
 }
 
 /**
@@ -1059,15 +1357,10 @@
 {
   guint poffset, plen;
 
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL);
-
   plen = gst_rtp_buffer_get_payload_len (buffer);
   /* we can't go past the length */
-  if (G_UNLIKELY (offset >= plen)) {
-    GST_WARNING ("offset=%u should be less then plen=%u", offset, plen);
-    return (NULL);
-  }
+  if (G_UNLIKELY (offset >= plen))
+    goto wrong_offset;
 
   /* apply offset */
   poffset = gst_rtp_buffer_get_header_len (buffer) + offset;
@@ -1078,6 +1371,13 @@
     plen = len;
 
   return gst_buffer_create_sub (buffer, poffset, plen);
+
+  /* ERRORS */
+wrong_offset:
+  {
+    g_warning ("offset=%u should be less then plen=%u", offset, plen);
+    return NULL;
+  }
 }
 
 /**
@@ -1116,16 +1416,58 @@
 gst_rtp_buffer_get_payload_len (GstBuffer * buffer)
 {
   guint len, size;
-
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+  guint8 *data;
 
   size = GST_BUFFER_SIZE (buffer);
+  data = GST_BUFFER_DATA (buffer);
 
   len = size - gst_rtp_buffer_get_header_len (buffer);
 
-  if (GST_RTP_HEADER_PADDING (buffer))
-    len -= GST_BUFFER_DATA (buffer)[size - 1];
+  if (GST_RTP_HEADER_PADDING (data))
+    len -= data[size - 1];
+
+  return len;
+}
+
+/**
+ * gst_rtp_buffer_list_get_payload_len:
+ * @list: the buffer list
+ *
+ * Get the length of the payload of the RTP packet in @list.
+ *
+ * Returns: The length of the payload in @list.
+ *
+ * Since: 0.10.24
+ */
+ 
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+ 
+guint
+gst_rtp_buffer_list_get_payload_len (GstBufferList * list)
+{
+  guint len;
+  GstBufferListIterator *it;
+
+  it = gst_buffer_list_iterate (list);
+  len = 0;
+
+  while (gst_buffer_list_iterator_next_group (it)) {
+    guint i;
+    GstBuffer *buf;
+
+    i = 0;
+    while ((buf = gst_buffer_list_iterator_next (it))) {
+      /* skip the RTP header */
+      if (!i++)
+        continue;
+      /* take the size of the current buffer */
+      len += GST_BUFFER_SIZE (buf);
+    }
+  }
+
+  gst_buffer_list_iterator_free (it);
 
   return len;
 }
@@ -1146,9 +1488,6 @@
 gpointer
 gst_rtp_buffer_get_payload (GstBuffer * buffer)
 {
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
-  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL);
-
   return GST_BUFFER_DATA (buffer) + gst_rtp_buffer_get_header_len (buffer);
 }
 
@@ -1190,10 +1529,11 @@
  * @seqnum1: a sequence number
  * @seqnum2: a sequence number
  *
- * Compare two sequence numbers, taking care of wraparounds.
+ * Compare two sequence numbers, taking care of wraparounds. This function
+ * returns the difference between @seqnum1 and @seqnum2.
  *
- * Returns: -1 if @seqnum1 is before @seqnum2, 0 if they are equal or 1 if
- * @seqnum1 is bigger than @segnum2.
+ * Returns: a negative value if @seqnum1 is bigger than @seqnum2, 0 if they
+ * are equal or a positive value if @seqnum1 is smaller than @segnum2.
  *
  * Since: 0.10.15
  */
@@ -1204,13 +1544,7 @@
 gint
 gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2)
 {
-  /* check if diff more than half of the 16bit range */
-  if (abs (seqnum2 - seqnum1) > (1 << 15)) {
-    /* one of a/b has wrapped */
-    return seqnum1 - seqnum2;
-  } else {
-    return seqnum2 - seqnum1;
-  }
+  return (gint16) (seqnum2 - seqnum1);
 }
 
 /**
--- a/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.h	Fri Apr 16 15:15:52 2010 +0300
@@ -95,6 +95,11 @@
 IMPORT_C
 #endif
 
+gboolean        gst_rtp_buffer_list_validate         (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void            gst_rtp_buffer_set_packet_len        (GstBuffer *buffer, guint len);
 #ifdef __SYMBIAN32__
@@ -167,11 +172,21 @@
 IMPORT_C
 #endif
 
+guint32         gst_rtp_buffer_list_get_ssrc         (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void            gst_rtp_buffer_set_ssrc              (GstBuffer *buffer, guint32 ssrc);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void            gst_rtp_buffer_list_set_ssrc         (GstBufferList *list, guint32 ssrc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 guint8          gst_rtp_buffer_get_csrc_count        (GstBuffer *buffer);
 #ifdef __SYMBIAN32__
@@ -205,33 +220,63 @@
 IMPORT_C
 #endif
 
+guint8          gst_rtp_buffer_list_get_payload_type (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void            gst_rtp_buffer_set_payload_type      (GstBuffer *buffer, guint8 payload_type);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void            gst_rtp_buffer_list_set_payload_type (GstBufferList *list, guint8 payload_type);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 guint16         gst_rtp_buffer_get_seq               (GstBuffer *buffer);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+guint16         gst_rtp_buffer_list_get_seq          (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void            gst_rtp_buffer_set_seq               (GstBuffer *buffer, guint16 seq);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+guint16         gst_rtp_buffer_list_set_seq          (GstBufferList *list, guint16 seq);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 guint32         gst_rtp_buffer_get_timestamp         (GstBuffer *buffer);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+guint32         gst_rtp_buffer_list_get_timestamp    (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void            gst_rtp_buffer_set_timestamp         (GstBuffer *buffer, guint32 timestamp);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void            gst_rtp_buffer_list_set_timestamp    (GstBufferList *list, guint32 timestamp);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GstBuffer* 	gst_rtp_buffer_get_payload_buffer    (GstBuffer *buffer);
 #ifdef __SYMBIAN32__
@@ -249,6 +294,11 @@
 IMPORT_C
 #endif
 
+guint           gst_rtp_buffer_list_get_payload_len  (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 gpointer        gst_rtp_buffer_get_payload           (GstBuffer *buffer);
 
 /* some helpers */
--- a/gst_plugins_base/gst-libs/gst/rtp/gstrtppayloads.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtppayloads.c	Fri Apr 16 15:15:52 2010 +0300
@@ -228,7 +228,7 @@
 
   for (i = 0; info[i].media; i++) {
     if (strcmp (media, info[i].media) == 0
-        && g_strcasecmp (encoding_name, info[i].encoding_name) == 0) {
+        && g_ascii_strcasecmp (encoding_name, info[i].encoding_name) == 0) {
       result = &info[i];
       break;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsp-enumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,295 @@
+
+/* Generated data (by glib-mkenums) */
+
+#include "gstrtsp-enumtypes.h"
+
+#include "gstrtspdefs.h"
+
+/* enumerations from "gstrtspdefs.h" */
+GType
+gst_rtsp_result_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_OK, "GST_RTSP_OK", "ok" },
+      { GST_RTSP_ERROR, "GST_RTSP_ERROR", "error" },
+      { GST_RTSP_EINVAL, "GST_RTSP_EINVAL", "einval" },
+      { GST_RTSP_EINTR, "GST_RTSP_EINTR", "eintr" },
+      { GST_RTSP_ENOMEM, "GST_RTSP_ENOMEM", "enomem" },
+      { GST_RTSP_ERESOLV, "GST_RTSP_ERESOLV", "eresolv" },
+      { GST_RTSP_ENOTIMPL, "GST_RTSP_ENOTIMPL", "enotimpl" },
+      { GST_RTSP_ESYS, "GST_RTSP_ESYS", "esys" },
+      { GST_RTSP_EPARSE, "GST_RTSP_EPARSE", "eparse" },
+      { GST_RTSP_EWSASTART, "GST_RTSP_EWSASTART", "ewsastart" },
+      { GST_RTSP_EWSAVERSION, "GST_RTSP_EWSAVERSION", "ewsaversion" },
+      { GST_RTSP_EEOF, "GST_RTSP_EEOF", "eeof" },
+      { GST_RTSP_ENET, "GST_RTSP_ENET", "enet" },
+      { GST_RTSP_ENOTIP, "GST_RTSP_ENOTIP", "enotip" },
+      { GST_RTSP_ETIMEOUT, "GST_RTSP_ETIMEOUT", "etimeout" },
+      { GST_RTSP_ETGET, "GST_RTSP_ETGET", "etget" },
+      { GST_RTSP_ETPOST, "GST_RTSP_ETPOST", "etpost" },
+      { GST_RTSP_ELAST, "GST_RTSP_ELAST", "elast" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPResult", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_event_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GFlagsValue values[] = {
+      { GST_RTSP_EV_READ, "GST_RTSP_EV_READ", "read" },
+      { GST_RTSP_EV_WRITE, "GST_RTSP_EV_WRITE", "write" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_flags_register_static ("GstRTSPEvent", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_family_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_FAM_NONE, "GST_RTSP_FAM_NONE", "none" },
+      { GST_RTSP_FAM_INET, "GST_RTSP_FAM_INET", "inet" },
+      { GST_RTSP_FAM_INET6, "GST_RTSP_FAM_INET6", "inet6" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPFamily", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_state_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_STATE_INVALID, "GST_RTSP_STATE_INVALID", "invalid" },
+      { GST_RTSP_STATE_INIT, "GST_RTSP_STATE_INIT", "init" },
+      { GST_RTSP_STATE_READY, "GST_RTSP_STATE_READY", "ready" },
+      { GST_RTSP_STATE_SEEKING, "GST_RTSP_STATE_SEEKING", "seeking" },
+      { GST_RTSP_STATE_PLAYING, "GST_RTSP_STATE_PLAYING", "playing" },
+      { GST_RTSP_STATE_RECORDING, "GST_RTSP_STATE_RECORDING", "recording" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPState", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_version_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_VERSION_INVALID, "GST_RTSP_VERSION_INVALID", "invalid" },
+      { GST_RTSP_VERSION_1_0, "GST_RTSP_VERSION_1_0", "1-0" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPVersion", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_method_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GFlagsValue values[] = {
+      { GST_RTSP_INVALID, "GST_RTSP_INVALID", "invalid" },
+      { GST_RTSP_DESCRIBE, "GST_RTSP_DESCRIBE", "describe" },
+      { GST_RTSP_ANNOUNCE, "GST_RTSP_ANNOUNCE", "announce" },
+      { GST_RTSP_GET_PARAMETER, "GST_RTSP_GET_PARAMETER", "get-parameter" },
+      { GST_RTSP_OPTIONS, "GST_RTSP_OPTIONS", "options" },
+      { GST_RTSP_PAUSE, "GST_RTSP_PAUSE", "pause" },
+      { GST_RTSP_PLAY, "GST_RTSP_PLAY", "play" },
+      { GST_RTSP_RECORD, "GST_RTSP_RECORD", "record" },
+      { GST_RTSP_REDIRECT, "GST_RTSP_REDIRECT", "redirect" },
+      { GST_RTSP_SETUP, "GST_RTSP_SETUP", "setup" },
+      { GST_RTSP_SET_PARAMETER, "GST_RTSP_SET_PARAMETER", "set-parameter" },
+      { GST_RTSP_TEARDOWN, "GST_RTSP_TEARDOWN", "teardown" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_flags_register_static ("GstRTSPMethod", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_auth_method_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_AUTH_NONE, "GST_RTSP_AUTH_NONE", "none" },
+      { GST_RTSP_AUTH_BASIC, "GST_RTSP_AUTH_BASIC", "basic" },
+      { GST_RTSP_AUTH_DIGEST, "GST_RTSP_AUTH_DIGEST", "digest" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPAuthMethod", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_header_field_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_HDR_INVALID, "GST_RTSP_HDR_INVALID", "invalid" },
+      { GST_RTSP_HDR_ACCEPT, "GST_RTSP_HDR_ACCEPT", "accept" },
+      { GST_RTSP_HDR_ACCEPT_ENCODING, "GST_RTSP_HDR_ACCEPT_ENCODING", "accept-encoding" },
+      { GST_RTSP_HDR_ACCEPT_LANGUAGE, "GST_RTSP_HDR_ACCEPT_LANGUAGE", "accept-language" },
+      { GST_RTSP_HDR_ALLOW, "GST_RTSP_HDR_ALLOW", "allow" },
+      { GST_RTSP_HDR_AUTHORIZATION, "GST_RTSP_HDR_AUTHORIZATION", "authorization" },
+      { GST_RTSP_HDR_BANDWIDTH, "GST_RTSP_HDR_BANDWIDTH", "bandwidth" },
+      { GST_RTSP_HDR_BLOCKSIZE, "GST_RTSP_HDR_BLOCKSIZE", "blocksize" },
+      { GST_RTSP_HDR_CACHE_CONTROL, "GST_RTSP_HDR_CACHE_CONTROL", "cache-control" },
+      { GST_RTSP_HDR_CONFERENCE, "GST_RTSP_HDR_CONFERENCE", "conference" },
+      { GST_RTSP_HDR_CONNECTION, "GST_RTSP_HDR_CONNECTION", "connection" },
+      { GST_RTSP_HDR_CONTENT_BASE, "GST_RTSP_HDR_CONTENT_BASE", "content-base" },
+      { GST_RTSP_HDR_CONTENT_ENCODING, "GST_RTSP_HDR_CONTENT_ENCODING", "content-encoding" },
+      { GST_RTSP_HDR_CONTENT_LANGUAGE, "GST_RTSP_HDR_CONTENT_LANGUAGE", "content-language" },
+      { GST_RTSP_HDR_CONTENT_LENGTH, "GST_RTSP_HDR_CONTENT_LENGTH", "content-length" },
+      { GST_RTSP_HDR_CONTENT_LOCATION, "GST_RTSP_HDR_CONTENT_LOCATION", "content-location" },
+      { GST_RTSP_HDR_CONTENT_TYPE, "GST_RTSP_HDR_CONTENT_TYPE", "content-type" },
+      { GST_RTSP_HDR_CSEQ, "GST_RTSP_HDR_CSEQ", "cseq" },
+      { GST_RTSP_HDR_DATE, "GST_RTSP_HDR_DATE", "date" },
+      { GST_RTSP_HDR_EXPIRES, "GST_RTSP_HDR_EXPIRES", "expires" },
+      { GST_RTSP_HDR_FROM, "GST_RTSP_HDR_FROM", "from" },
+      { GST_RTSP_HDR_IF_MODIFIED_SINCE, "GST_RTSP_HDR_IF_MODIFIED_SINCE", "if-modified-since" },
+      { GST_RTSP_HDR_LAST_MODIFIED, "GST_RTSP_HDR_LAST_MODIFIED", "last-modified" },
+      { GST_RTSP_HDR_PROXY_AUTHENTICATE, "GST_RTSP_HDR_PROXY_AUTHENTICATE", "proxy-authenticate" },
+      { GST_RTSP_HDR_PROXY_REQUIRE, "GST_RTSP_HDR_PROXY_REQUIRE", "proxy-require" },
+      { GST_RTSP_HDR_PUBLIC, "GST_RTSP_HDR_PUBLIC", "public" },
+      { GST_RTSP_HDR_RANGE, "GST_RTSP_HDR_RANGE", "range" },
+      { GST_RTSP_HDR_REFERER, "GST_RTSP_HDR_REFERER", "referer" },
+      { GST_RTSP_HDR_REQUIRE, "GST_RTSP_HDR_REQUIRE", "require" },
+      { GST_RTSP_HDR_RETRY_AFTER, "GST_RTSP_HDR_RETRY_AFTER", "retry-after" },
+      { GST_RTSP_HDR_RTP_INFO, "GST_RTSP_HDR_RTP_INFO", "rtp-info" },
+      { GST_RTSP_HDR_SCALE, "GST_RTSP_HDR_SCALE", "scale" },
+      { GST_RTSP_HDR_SESSION, "GST_RTSP_HDR_SESSION", "session" },
+      { GST_RTSP_HDR_SERVER, "GST_RTSP_HDR_SERVER", "server" },
+      { GST_RTSP_HDR_SPEED, "GST_RTSP_HDR_SPEED", "speed" },
+      { GST_RTSP_HDR_TRANSPORT, "GST_RTSP_HDR_TRANSPORT", "transport" },
+      { GST_RTSP_HDR_UNSUPPORTED, "GST_RTSP_HDR_UNSUPPORTED", "unsupported" },
+      { GST_RTSP_HDR_USER_AGENT, "GST_RTSP_HDR_USER_AGENT", "user-agent" },
+      { GST_RTSP_HDR_VIA, "GST_RTSP_HDR_VIA", "via" },
+      { GST_RTSP_HDR_WWW_AUTHENTICATE, "GST_RTSP_HDR_WWW_AUTHENTICATE", "www-authenticate" },
+      { GST_RTSP_HDR_CLIENT_CHALLENGE, "GST_RTSP_HDR_CLIENT_CHALLENGE", "client-challenge" },
+      { GST_RTSP_HDR_REAL_CHALLENGE1, "GST_RTSP_HDR_REAL_CHALLENGE1", "real-challenge1" },
+      { GST_RTSP_HDR_REAL_CHALLENGE2, "GST_RTSP_HDR_REAL_CHALLENGE2", "real-challenge2" },
+      { GST_RTSP_HDR_REAL_CHALLENGE3, "GST_RTSP_HDR_REAL_CHALLENGE3", "real-challenge3" },
+      { GST_RTSP_HDR_SUBSCRIBE, "GST_RTSP_HDR_SUBSCRIBE", "subscribe" },
+      { GST_RTSP_HDR_ALERT, "GST_RTSP_HDR_ALERT", "alert" },
+      { GST_RTSP_HDR_CLIENT_ID, "GST_RTSP_HDR_CLIENT_ID", "client-id" },
+      { GST_RTSP_HDR_COMPANY_ID, "GST_RTSP_HDR_COMPANY_ID", "company-id" },
+      { GST_RTSP_HDR_GUID, "GST_RTSP_HDR_GUID", "guid" },
+      { GST_RTSP_HDR_REGION_DATA, "GST_RTSP_HDR_REGION_DATA", "region-data" },
+      { GST_RTSP_HDR_MAX_ASM_WIDTH, "GST_RTSP_HDR_MAX_ASM_WIDTH", "max-asm-width" },
+      { GST_RTSP_HDR_LANGUAGE, "GST_RTSP_HDR_LANGUAGE", "language" },
+      { GST_RTSP_HDR_PLAYER_START_TIME, "GST_RTSP_HDR_PLAYER_START_TIME", "player-start-time" },
+      { GST_RTSP_HDR_LOCATION, "GST_RTSP_HDR_LOCATION", "location" },
+      { GST_RTSP_HDR_ETAG, "GST_RTSP_HDR_ETAG", "etag" },
+      { GST_RTSP_HDR_IF_MATCH, "GST_RTSP_HDR_IF_MATCH", "if-match" },
+      { GST_RTSP_HDR_ACCEPT_CHARSET, "GST_RTSP_HDR_ACCEPT_CHARSET", "accept-charset" },
+      { GST_RTSP_HDR_SUPPORTED, "GST_RTSP_HDR_SUPPORTED", "supported" },
+      { GST_RTSP_HDR_VARY, "GST_RTSP_HDR_VARY", "vary" },
+      { GST_RTSP_HDR_X_ACCELERATE_STREAMING, "GST_RTSP_HDR_X_ACCELERATE_STREAMING", "x-accelerate-streaming" },
+      { GST_RTSP_HDR_X_ACCEPT_AUTHENT, "GST_RTSP_HDR_X_ACCEPT_AUTHENT", "x-accept-authent" },
+      { GST_RTSP_HDR_X_ACCEPT_PROXY_AUTHENT, "GST_RTSP_HDR_X_ACCEPT_PROXY_AUTHENT", "x-accept-proxy-authent" },
+      { GST_RTSP_HDR_X_BROADCAST_ID, "GST_RTSP_HDR_X_BROADCAST_ID", "x-broadcast-id" },
+      { GST_RTSP_HDR_X_BURST_STREAMING, "GST_RTSP_HDR_X_BURST_STREAMING", "x-burst-streaming" },
+      { GST_RTSP_HDR_X_NOTICE, "GST_RTSP_HDR_X_NOTICE", "x-notice" },
+      { GST_RTSP_HDR_X_PLAYER_LAG_TIME, "GST_RTSP_HDR_X_PLAYER_LAG_TIME", "x-player-lag-time" },
+      { GST_RTSP_HDR_X_PLAYLIST, "GST_RTSP_HDR_X_PLAYLIST", "x-playlist" },
+      { GST_RTSP_HDR_X_PLAYLIST_CHANGE_NOTICE, "GST_RTSP_HDR_X_PLAYLIST_CHANGE_NOTICE", "x-playlist-change-notice" },
+      { GST_RTSP_HDR_X_PLAYLIST_GEN_ID, "GST_RTSP_HDR_X_PLAYLIST_GEN_ID", "x-playlist-gen-id" },
+      { GST_RTSP_HDR_X_PLAYLIST_SEEK_ID, "GST_RTSP_HDR_X_PLAYLIST_SEEK_ID", "x-playlist-seek-id" },
+      { GST_RTSP_HDR_X_PROXY_CLIENT_AGENT, "GST_RTSP_HDR_X_PROXY_CLIENT_AGENT", "x-proxy-client-agent" },
+      { GST_RTSP_HDR_X_PROXY_CLIENT_VERB, "GST_RTSP_HDR_X_PROXY_CLIENT_VERB", "x-proxy-client-verb" },
+      { GST_RTSP_HDR_X_RECEDING_PLAYLISTCHANGE, "GST_RTSP_HDR_X_RECEDING_PLAYLISTCHANGE", "x-receding-playlistchange" },
+      { GST_RTSP_HDR_X_RTP_INFO, "GST_RTSP_HDR_X_RTP_INFO", "x-rtp-info" },
+      { GST_RTSP_HDR_X_STARTUPPROFILE, "GST_RTSP_HDR_X_STARTUPPROFILE", "x-startupprofile" },
+      { GST_RTSP_HDR_TIMESTAMP, "GST_RTSP_HDR_TIMESTAMP", "timestamp" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPHeaderField", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+GType
+gst_rtsp_status_code_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_RTSP_STS_INVALID, "GST_RTSP_STS_INVALID", "invalid" },
+      { GST_RTSP_STS_CONTINUE, "GST_RTSP_STS_CONTINUE", "continue" },
+      { GST_RTSP_STS_OK, "GST_RTSP_STS_OK", "ok" },
+      { GST_RTSP_STS_CREATED, "GST_RTSP_STS_CREATED", "created" },
+      { GST_RTSP_STS_LOW_ON_STORAGE, "GST_RTSP_STS_LOW_ON_STORAGE", "low-on-storage" },
+      { GST_RTSP_STS_MULTIPLE_CHOICES, "GST_RTSP_STS_MULTIPLE_CHOICES", "multiple-choices" },
+      { GST_RTSP_STS_MOVED_PERMANENTLY, "GST_RTSP_STS_MOVED_PERMANENTLY", "moved-permanently" },
+      { GST_RTSP_STS_MOVE_TEMPORARILY, "GST_RTSP_STS_MOVE_TEMPORARILY", "move-temporarily" },
+      { GST_RTSP_STS_SEE_OTHER, "GST_RTSP_STS_SEE_OTHER", "see-other" },
+      { GST_RTSP_STS_NOT_MODIFIED, "GST_RTSP_STS_NOT_MODIFIED", "not-modified" },
+      { GST_RTSP_STS_USE_PROXY, "GST_RTSP_STS_USE_PROXY", "use-proxy" },
+      { GST_RTSP_STS_BAD_REQUEST, "GST_RTSP_STS_BAD_REQUEST", "bad-request" },
+      { GST_RTSP_STS_UNAUTHORIZED, "GST_RTSP_STS_UNAUTHORIZED", "unauthorized" },
+      { GST_RTSP_STS_PAYMENT_REQUIRED, "GST_RTSP_STS_PAYMENT_REQUIRED", "payment-required" },
+      { GST_RTSP_STS_FORBIDDEN, "GST_RTSP_STS_FORBIDDEN", "forbidden" },
+      { GST_RTSP_STS_NOT_FOUND, "GST_RTSP_STS_NOT_FOUND", "not-found" },
+      { GST_RTSP_STS_METHOD_NOT_ALLOWED, "GST_RTSP_STS_METHOD_NOT_ALLOWED", "method-not-allowed" },
+      { GST_RTSP_STS_NOT_ACCEPTABLE, "GST_RTSP_STS_NOT_ACCEPTABLE", "not-acceptable" },
+      { GST_RTSP_STS_PROXY_AUTH_REQUIRED, "GST_RTSP_STS_PROXY_AUTH_REQUIRED", "proxy-auth-required" },
+      { GST_RTSP_STS_REQUEST_TIMEOUT, "GST_RTSP_STS_REQUEST_TIMEOUT", "request-timeout" },
+      { GST_RTSP_STS_GONE, "GST_RTSP_STS_GONE", "gone" },
+      { GST_RTSP_STS_LENGTH_REQUIRED, "GST_RTSP_STS_LENGTH_REQUIRED", "length-required" },
+      { GST_RTSP_STS_PRECONDITION_FAILED, "GST_RTSP_STS_PRECONDITION_FAILED", "precondition-failed" },
+      { GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE, "GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE", "request-entity-too-large" },
+      { GST_RTSP_STS_REQUEST_URI_TOO_LARGE, "GST_RTSP_STS_REQUEST_URI_TOO_LARGE", "request-uri-too-large" },
+      { GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE, "GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE", "unsupported-media-type" },
+      { GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD, "GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD", "parameter-not-understood" },
+      { GST_RTSP_STS_CONFERENCE_NOT_FOUND, "GST_RTSP_STS_CONFERENCE_NOT_FOUND", "conference-not-found" },
+      { GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH, "GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH", "not-enough-bandwidth" },
+      { GST_RTSP_STS_SESSION_NOT_FOUND, "GST_RTSP_STS_SESSION_NOT_FOUND", "session-not-found" },
+      { GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, "GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE", "method-not-valid-in-this-state" },
+      { GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE, "GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE", "header-field-not-valid-for-resource" },
+      { GST_RTSP_STS_INVALID_RANGE, "GST_RTSP_STS_INVALID_RANGE", "invalid-range" },
+      { GST_RTSP_STS_PARAMETER_IS_READONLY, "GST_RTSP_STS_PARAMETER_IS_READONLY", "parameter-is-readonly" },
+      { GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED, "GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED", "aggregate-operation-not-allowed" },
+      { GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, "GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED", "only-aggregate-operation-allowed" },
+      { GST_RTSP_STS_UNSUPPORTED_TRANSPORT, "GST_RTSP_STS_UNSUPPORTED_TRANSPORT", "unsupported-transport" },
+      { GST_RTSP_STS_DESTINATION_UNREACHABLE, "GST_RTSP_STS_DESTINATION_UNREACHABLE", "destination-unreachable" },
+      { GST_RTSP_STS_INTERNAL_SERVER_ERROR, "GST_RTSP_STS_INTERNAL_SERVER_ERROR", "internal-server-error" },
+      { GST_RTSP_STS_NOT_IMPLEMENTED, "GST_RTSP_STS_NOT_IMPLEMENTED", "not-implemented" },
+      { GST_RTSP_STS_BAD_GATEWAY, "GST_RTSP_STS_BAD_GATEWAY", "bad-gateway" },
+      { GST_RTSP_STS_SERVICE_UNAVAILABLE, "GST_RTSP_STS_SERVICE_UNAVAILABLE", "service-unavailable" },
+      { GST_RTSP_STS_GATEWAY_TIMEOUT, "GST_RTSP_STS_GATEWAY_TIMEOUT", "gateway-timeout" },
+      { GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED, "GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED", "rtsp-version-not-supported" },
+      { GST_RTSP_STS_OPTION_NOT_SUPPORTED, "GST_RTSP_STS_OPTION_NOT_SUPPORTED", "option-not-supported" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstRTSPStatusCode", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+
+/* Generated data ends here */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsp-enumtypes.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,35 @@
+
+/* Generated data (by glib-mkenums) */
+
+#ifndef __gst_rtsp_ENUM_TYPES_H__
+#define __gst_rtsp_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* enumerations from "gstrtspdefs.h" */
+GType gst_rtsp_result_get_type (void);
+#define GST_TYPE_RTSP_RESULT (gst_rtsp_result_get_type())
+GType gst_rtsp_event_get_type (void);
+#define GST_TYPE_RTSP_EVENT (gst_rtsp_event_get_type())
+GType gst_rtsp_family_get_type (void);
+#define GST_TYPE_RTSP_FAMILY (gst_rtsp_family_get_type())
+GType gst_rtsp_state_get_type (void);
+#define GST_TYPE_RTSP_STATE (gst_rtsp_state_get_type())
+GType gst_rtsp_version_get_type (void);
+#define GST_TYPE_RTSP_VERSION (gst_rtsp_version_get_type())
+GType gst_rtsp_method_get_type (void);
+#define GST_TYPE_RTSP_METHOD (gst_rtsp_method_get_type())
+GType gst_rtsp_auth_method_get_type (void);
+#define GST_TYPE_RTSP_AUTH_METHOD (gst_rtsp_auth_method_get_type())
+GType gst_rtsp_header_field_get_type (void);
+#define GST_TYPE_RTSP_HEADER_FIELD (gst_rtsp_header_field_get_type())
+GType gst_rtsp_status_code_get_type (void);
+#define GST_TYPE_RTSP_STATUS_CODE (gst_rtsp_status_code_get_type())
+G_END_DECLS
+
+#endif /* __gst_rtsp_ENUM_TYPES_H__ */
+
+/* Generated data ends here */
+
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.c	Fri Apr 16 15:15:52 2010 +0300
@@ -32,16 +32,6 @@
 
 #include "gstrtspbase64.h"
 
-static char base64table[64] = {
-  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
-  'P',
-  'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e',
-  'f',
-  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
-  'v',
-  'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
-};
-
 /**
  * gst_rtsp_base64_encode:
  * @data: the binary data to encode
@@ -49,48 +39,19 @@
  *
  * Encode a sequence of binary data into its Base-64 stringified representation.
  *
+ * Deprecated: Use g_base64_encode()
+ *
  * Returns: a newly allocated, zero-terminated Base-64 encoded string
  * representing @data.
  */
 /* This isn't efficient, but it doesn't need to be */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
+#ifndef GST_REMOVE_DEPRECATED
 gchar *
 gst_rtsp_base64_encode (const gchar * data, gsize len)
 {
-  gchar *out = g_malloc (len * 4 / 3 + 4);
-  gchar *result = out;
-  int chunk;
-
-  while (len > 0) {
-    chunk = (len > 3) ? 3 : len;
-    *out++ = base64table[(*data & 0xFC) >> 2];
-    *out++ = base64table[((*data & 0x03) << 4) | ((*(data + 1) & 0xF0) >> 4)];
-    switch (chunk) {
-      case 3:
-        *out++ =
-            base64table[((*(data + 1) & 0x0F) << 2) | ((*(data +
-                        2) & 0xC0) >> 6)];
-        *out++ = base64table[(*(data + 2)) & 0x3F];
-        break;
-      case 2:
-        *out++ = base64table[((*(data + 1) & 0x0F) << 2)];
-        *out++ = '=';
-        break;
-      case 1:
-        *out++ = '=';
-        *out++ = '=';
-        break;
-    }
-    data += chunk;
-    len -= chunk;
-  }
-  *out = 0;
-
-  return result;
+  return g_base64_encode ((const guchar *) data, len);
 }
+#endif
 
 /**
  * gst_rtsp_base64_decode_ip:
@@ -100,51 +61,24 @@
  * Decode the base64 string pointed to by @data in-place. When @len is not #NULL
  * it will contain the length of the decoded data.
  */
+/* FIXME: Deprecate this once we depend on GLib 2.20 and
+ * use g_base64_decode_inplace then.
+ */
 void
 gst_rtsp_base64_decode_ip (gchar * data, gsize * len)
 {
-  char dtable[256];
-  int i, j, k = 0, n = strlen (data);
+  gint input_length, output_length, state = 0;
+  guint save = 0;
 
-  for (i = 0; i < 255; i++)
-    dtable[i] = 0x80;
-  for (i = 'A'; i <= 'Z'; i++)
-    dtable[i] = 0 + (i - 'A');
-  for (i = 'a'; i <= 'z'; i++)
-    dtable[i] = 26 + (i - 'a');
-  for (i = '0'; i <= '9'; i++)
-    dtable[i] = 52 + (i - '0');
-  dtable['+'] = 62;
-  dtable['/'] = 63;
-  dtable['='] = 0;
+  g_return_if_fail (data != NULL);
 
-  for (j = 0; j < n; j += 4) {
-    char a[4], b[4];
-
-    for (i = 0; i < 4; i++) {
-      int c = data[i + j];
+  input_length = strlen (data);
 
-      if (dtable[c] & 0x80) {
-        if (len)
-          *len = 0;
-        return;
-      }
-      a[i] = (char) c;
-      b[i] = (char) dtable[c];
-    }
-    data[k++] = (b[0] << 2) | (b[1] >> 4);
-    data[k++] = (b[1] << 4) | (b[2] >> 2);
-    data[k++] = (b[2] << 6) | b[3];
-    i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
-    if (i < 3) {
-      data[k] = 0;
-      if (len)
-        *len = k;
-      return;
-    }
-  }
-  data[k] = 0;
+  g_return_if_fail (input_length > 1);
+
+  output_length =
+      g_base64_decode_step (data, input_length, (guchar *) data, &state, &save);
+
   if (len)
-    *len = k;
-  return;
+    *len = output_length;
 }
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.h	Fri Apr 16 15:15:52 2010 +0300
@@ -24,7 +24,10 @@
 
 G_BEGIN_DECLS
 
+#ifndef GST_DISABLE_DEPRECATED
 gchar *gst_rtsp_base64_encode    (const gchar *data, gsize len);
+#endif
+
 void   gst_rtsp_base64_decode_ip (gchar *data, gsize *len);
 
 G_END_DECLS
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,5 @@
 /* GStreamer
- * Copyright (C) <2005,2006> Wim Taymans <wim@fluendo.com>
+ * Copyright (C) <2005-2009> Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -69,21 +69,25 @@
 #include <unistd.h>
 #endif
 
-
 /* we include this here to get the G_OS_* defines */
 #include <glib.h>
 #include <gst/gst.h>
 
 #ifdef G_OS_WIN32
+/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
+ * minwg32 headers check WINVER before allowing the use of these */
+#ifndef WINVER
+#define WINVER 0x0501
+#endif
 #include <winsock2.h>
+#include <ws2tcpip.h>
 #define EINPROGRESS WSAEINPROGRESS
 #else
 #include <sys/ioctl.h>
 #include <netdb.h>
 #include <sys/socket.h>
+#include <fcntl.h>
 #include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
 #endif
 
 #ifdef HAVE_FIONREAD_IN_SYS_FILIO
@@ -92,85 +96,709 @@
 
 #include "gstrtspconnection.h"
 #include "gstrtspbase64.h"
+#include "md5.h"
+
+union gst_sockaddr
+{
+  struct sockaddr sa;
+  struct sockaddr_in sa_in;
+  struct sockaddr_in6 sa_in6;
+  struct sockaddr_storage sa_stor;
+};
+
+typedef struct
+{
+  gint state;
+  guint save;
+  guchar out[3];                /* the size must be evenly divisible by 3 */
+  guint cout;
+  guint coutl;
+} DecodeCtx;
+
+static GstRTSPResult read_line (gint fd, guint8 * buffer, guint * idx,
+    guint size, DecodeCtx * ctxp);
+static GstRTSPResult parse_key_value (guint8 * buffer, gchar * key,
+    guint keysize, gchar ** value);
+static void parse_string (gchar * dest, gint size, gchar ** src);
 
 #ifdef G_OS_WIN32
-#define FIONREAD_TYPE gulong
-#define IOCTL_SOCKET ioctlsocket
-#define READ_SOCKET(fd, buf, len) recv (fd, buf, len, 0)
-#define WRITE_SOCKET(fd, buf, len) send (fd, buf, len, 0)
+#define READ_SOCKET(fd, buf, len) recv (fd, (char *)buf, len, 0)
+#define WRITE_SOCKET(fd, buf, len) send (fd, (const char *)buf, len, 0)
+#define SETSOCKOPT(sock, level, name, val, len) setsockopt (sock, level, name, (const char *)val, len)
 #define CLOSE_SOCKET(sock) closesocket (sock)
-#define ERRNO_IS_NOT_EAGAIN (WSAGetLastError () != WSAEWOULDBLOCK)
-#define ERRNO_IS_NOT_EINTR (WSAGetLastError () != WSAEINTR)
+#define ERRNO_IS_EAGAIN (WSAGetLastError () == WSAEWOULDBLOCK)
+#define ERRNO_IS_EINTR (WSAGetLastError () == WSAEINTR)
 /* According to Microsoft's connect() documentation this one returns
  * WSAEWOULDBLOCK and not WSAEINPROGRESS. */
-#define ERRNO_IS_NOT_EINPROGRESS (WSAGetLastError () != WSAEWOULDBLOCK)
+#define ERRNO_IS_EINPROGRESS (WSAGetLastError () == WSAEWOULDBLOCK)
 #else
-#define FIONREAD_TYPE gint
-#define IOCTL_SOCKET ioctl
 #define READ_SOCKET(fd, buf, len) read (fd, buf, len)
 #define WRITE_SOCKET(fd, buf, len) write (fd, buf, len)
+#define SETSOCKOPT(sock, level, name, val, len) setsockopt (sock, level, name, val, len)
 #define CLOSE_SOCKET(sock) close (sock)
-#define ERRNO_IS_NOT_EAGAIN (errno != EAGAIN)
-#define ERRNO_IS_NOT_EINTR (errno != EINTR)
-#define ERRNO_IS_NOT_EINPROGRESS (errno != EINPROGRESS)
+#define ERRNO_IS_EAGAIN (errno == EAGAIN)
+#define ERRNO_IS_EINTR (errno == EINTR)
+#define ERRNO_IS_EINPROGRESS (errno == EINPROGRESS)
 #endif
 
-#ifdef G_OS_WIN32
-static int
-inet_aton (const char *c, struct in_addr *paddr)
+#define ADD_POLLFD(fdset, pfd, fd)        \
+G_STMT_START {                            \
+  (pfd)->fd = fd;                         \
+  gst_poll_add_fd (fdset, pfd);           \
+} G_STMT_END
+
+#define REMOVE_POLLFD(fdset, pfd)          \
+G_STMT_START {                             \
+  if ((pfd)->fd != -1) {                   \
+    GST_DEBUG ("remove fd %d", (pfd)->fd); \
+    gst_poll_remove_fd (fdset, pfd);       \
+    CLOSE_SOCKET ((pfd)->fd);              \
+    (pfd)->fd = -1;                        \
+  }                                        \
+} G_STMT_END
+
+typedef enum
+{
+  TUNNEL_STATE_NONE,
+  TUNNEL_STATE_GET,
+  TUNNEL_STATE_POST,
+  TUNNEL_STATE_COMPLETE
+} GstRTSPTunnelState;
+
+#define TUNNELID_LEN   24
+
+struct _GstRTSPConnection
 {
-  /* note that inet_addr is deprecated on unix because
-   * inet_addr returns -1 (INADDR_NONE) for the valid 255.255.255.255
-   * address. */
-  paddr->s_addr = inet_addr (c);
-
-  if (paddr->s_addr == INADDR_NONE)
-    return 0;
-
-  return 1;
+  /*< private > */
+  /* URL for the connection */
+  GstRTSPUrl *url;
+
+  /* connection state */
+  GstPollFD fd0;
+  GstPollFD fd1;
+
+  GstPollFD *readfd;
+  GstPollFD *writefd;
+
+  gchar tunnelid[TUNNELID_LEN];
+  gboolean tunneled;
+  GstRTSPTunnelState tstate;
+
+  GstPoll *fdset;
+  gchar *ip;
+
+  /* Session state */
+  gint cseq;                    /* sequence number */
+  gchar session_id[512];        /* session id */
+  gint timeout;                 /* session timeout in seconds */
+  GTimer *timer;                /* timeout timer */
+
+  /* Authentication */
+  GstRTSPAuthMethod auth_method;
+  gchar *username;
+  gchar *passwd;
+  GHashTable *auth_params;
+
+  DecodeCtx ctx;
+  DecodeCtx *ctxp;
+
+  gchar *proxy_host;
+  guint proxy_port;
+};
+
+enum
+{
+  STATE_START = 0,
+  STATE_DATA_HEADER,
+  STATE_DATA_BODY,
+  STATE_READ_LINES,
+  STATE_END,
+  STATE_LAST
+};
+
+/* a structure for constructing RTSPMessages */
+typedef struct
+{
+  gint state;
+  guint8 buffer[4096];
+  guint offset;
+
+  guint line;
+  guint8 *body_data;
+  glong body_len;
+} GstRTSPBuilder;
+
+static void
+build_reset (GstRTSPBuilder * builder)
+{
+  g_free (builder->body_data);
+  memset (builder, 0, sizeof (GstRTSPBuilder));
 }
-#endif
 
 /**
  * gst_rtsp_connection_create:
  * @url: a #GstRTSPUrl 
- * @conn: a #GstRTSPConnection
+ * @conn: storage for a #GstRTSPConnection
  *
  * Create a newly allocated #GstRTSPConnection from @url and store it in @conn.
  * The connection will not yet attempt to connect to @url, use
  * gst_rtsp_connection_connect().
  *
+ * A copy of @url will be made.
+ *
  * Returns: #GST_RTSP_OK when @conn contains a valid connection.
  */
 GstRTSPResult
-gst_rtsp_connection_create (GstRTSPUrl * url, GstRTSPConnection ** conn)
+gst_rtsp_connection_create (const GstRTSPUrl * url, GstRTSPConnection ** conn)
 {
   GstRTSPConnection *newconn;
+#ifdef G_OS_WIN32
+  WSADATA w;
+  int error;
+#endif
 
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
 
+#ifdef G_OS_WIN32
+  error = WSAStartup (0x0202, &w);
+
+  if (error)
+    goto startup_error;
+
+  if (w.wVersion != 0x0202)
+    goto version_error;
+#endif
+
   newconn = g_new0 (GstRTSPConnection, 1);
 
   if ((newconn->fdset = gst_poll_new (TRUE)) == NULL)
     goto no_fdset;
 
-  newconn->url = url;
-  newconn->fd.fd = -1;
+  newconn->url = gst_rtsp_url_copy (url);
+  newconn->fd0.fd = -1;
+  newconn->fd1.fd = -1;
   newconn->timer = g_timer_new ();
+  newconn->timeout = 60;
+  newconn->cseq = 1;
 
   newconn->auth_method = GST_RTSP_AUTH_NONE;
   newconn->username = NULL;
   newconn->passwd = NULL;
+  newconn->auth_params = NULL;
+
+  *conn = newconn;
+
+  return GST_RTSP_OK;
+
+  /* ERRORS */
+#ifdef G_OS_WIN32
+startup_error:
+  {
+    g_warning ("Error %d on WSAStartup", error);
+    return GST_RTSP_EWSASTART;
+  }
+version_error:
+  {
+    g_warning ("Windows sockets are not version 0x202 (current 0x%x)",
+        w.wVersion);
+    WSACleanup ();
+    return GST_RTSP_EWSAVERSION;
+  }
+#endif
+no_fdset:
+  {
+    g_free (newconn);
+#ifdef G_OS_WIN32
+    WSACleanup ();
+#endif
+    return GST_RTSP_ESYS;
+  }
+}
+
+/**
+ * gst_rtsp_connection_accept:
+ * @sock: a socket
+ * @conn: storage for a #GstRTSPConnection
+ *
+ * Accept a new connection on @sock and create a new #GstRTSPConnection for
+ * handling communication on new socket.
+ *
+ * Returns: #GST_RTSP_OK when @conn contains a valid connection.
+ *
+ * Since: 0.10.23
+ */
+GstRTSPResult
+gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn)
+{
+  int fd;
+  GstRTSPConnection *newconn = NULL;
+  union gst_sockaddr sa;
+  socklen_t slen = sizeof (sa);
+  gchar ip[INET6_ADDRSTRLEN];
+  GstRTSPUrl *url;
+#ifdef G_OS_WIN32
+  gulong flags = 1;
+#endif
+
+  memset (&sa, 0, slen);
+
+#ifndef G_OS_WIN32
+  fd = accept (sock, &sa.sa, &slen);
+#else
+  fd = accept (sock, &sa.sa, (gint *) & slen);
+#endif /* G_OS_WIN32 */
+  if (fd == -1)
+    goto accept_failed;
+
+  if (getnameinfo (&sa.sa, slen, ip, sizeof (ip), NULL, 0, NI_NUMERICHOST) != 0)
+    goto getnameinfo_failed;
+  if (sa.sa.sa_family != AF_INET && sa.sa.sa_family != AF_INET6)
+    goto wrong_family;
+
+  /* set to non-blocking mode so that we can cancel the communication */
+#ifndef G_OS_WIN32
+  fcntl (fd, F_SETFL, O_NONBLOCK);
+#else
+  ioctlsocket (fd, FIONBIO, &flags);
+#endif /* G_OS_WIN32 */
+
+  /* create a url for the client address */
+  url = g_new0 (GstRTSPUrl, 1);
+  url->host = g_strdup (ip);
+  if (sa.sa.sa_family == AF_INET)
+    url->port = sa.sa_in.sin_port;
+  else
+    url->port = sa.sa_in6.sin6_port;
+
+  /* now create the connection object */
+  gst_rtsp_connection_create (url, &newconn);
+  gst_rtsp_url_free (url);
+
+  ADD_POLLFD (newconn->fdset, &newconn->fd0, fd);
+
+  /* both read and write initially */
+  newconn->readfd = &newconn->fd0;
+  newconn->writefd = &newconn->fd0;
 
   *conn = newconn;
 
   return GST_RTSP_OK;
 
   /* ERRORS */
-no_fdset:
+accept_failed:
+  {
+    return GST_RTSP_ESYS;
+  }
+getnameinfo_failed:
+wrong_family:
+  {
+    close (fd);
+    return GST_RTSP_ERROR;
+  }
+}
+
+static gchar *
+do_resolve (const gchar * host)
+{
+  static gchar ip[INET6_ADDRSTRLEN];
+  struct addrinfo *aires;
+  struct addrinfo *ai;
+  gint aierr;
+
+  aierr = getaddrinfo (host, NULL, NULL, &aires);
+  if (aierr != 0)
+    goto no_addrinfo;
+
+  for (ai = aires; ai; ai = ai->ai_next) {
+    if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
+      break;
+    }
+  }
+  if (ai == NULL)
+    goto no_family;
+
+  aierr = getnameinfo (ai->ai_addr, ai->ai_addrlen, ip, sizeof (ip), NULL, 0,
+      NI_NUMERICHOST | NI_NUMERICSERV);
+  if (aierr != 0)
+    goto no_address;
+
+  freeaddrinfo (aires);
+
+  return g_strdup (ip);
+
+  /* ERRORS */
+no_addrinfo:
+  {
+    GST_ERROR ("no addrinfo found for %s: %s", host, gai_strerror (aierr));
+    return NULL;
+  }
+no_family:
+  {
+    GST_ERROR ("no family found for %s", host);
+    freeaddrinfo (aires);
+    return NULL;
+  }
+no_address:
+  {
+    GST_ERROR ("no address found for %s: %s", host, gai_strerror (aierr));
+    freeaddrinfo (aires);
+    return NULL;
+  }
+}
+
+static GstRTSPResult
+do_connect (const gchar * ip, guint16 port, GstPollFD * fdout,
+    GstPoll * fdset, GTimeVal * timeout)
+{
+  gint fd;
+  struct addrinfo hints;
+  struct addrinfo *aires;
+  struct addrinfo *ai;
+  gint aierr;
+  gchar service[NI_MAXSERV];
+  gint ret;
+#ifdef G_OS_WIN32
+  unsigned long flags = 1;
+#endif /* G_OS_WIN32 */
+  GstClockTime to;
+  gint retval;
+
+  memset (&hints, 0, sizeof hints);
+  hints.ai_flags = AI_NUMERICHOST;
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  g_snprintf (service, sizeof (service) - 1, "%hu", port);
+  service[sizeof (service) - 1] = '\0';
+
+  aierr = getaddrinfo (ip, service, &hints, &aires);
+  if (aierr != 0)
+    goto no_addrinfo;
+
+  for (ai = aires; ai; ai = ai->ai_next) {
+    if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
+      break;
+    }
+  }
+  if (ai == NULL)
+    goto no_family;
+
+  fd = socket (ai->ai_family, SOCK_STREAM, 0);
+  if (fd == -1)
+    goto no_socket;
+
+  /* set to non-blocking mode so that we can cancel the connect */
+#ifndef G_OS_WIN32
+  fcntl (fd, F_SETFL, O_NONBLOCK);
+#else
+  ioctlsocket (fd, FIONBIO, &flags);
+#endif /* G_OS_WIN32 */
+
+  /* add the socket to our fdset */
+  ADD_POLLFD (fdset, fdout, fd);
+
+  /* we are going to connect ASYNC now */
+  ret = connect (fd, ai->ai_addr, ai->ai_addrlen);
+  if (ret == 0)
+    goto done;
+  if (!ERRNO_IS_EINPROGRESS)
+    goto sys_error;
+
+  /* wait for connect to complete up to the specified timeout or until we got
+   * interrupted. */
+  gst_poll_fd_ctl_write (fdset, fdout, TRUE);
+
+  to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
+
+  do {
+    retval = gst_poll_wait (fdset, to);
+  } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
+
+  if (retval == 0)
+    goto timeout;
+  else if (retval == -1)
+    goto sys_error;
+
+  /* we can still have an error connecting on windows */
+  if (gst_poll_fd_has_error (fdset, fdout)) {
+    socklen_t len = sizeof (errno);
+#ifndef G_OS_WIN32
+    getsockopt (fd, SOL_SOCKET, SO_ERROR, &errno, &len);
+#else
+    getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &errno, &len);
+#endif
+    goto sys_error;
+  }
+
+  gst_poll_fd_ignored (fdset, fdout);
+
+done:
+  freeaddrinfo (aires);
+
+  return GST_RTSP_OK;
+
+  /* ERRORS */
+no_addrinfo:
+  {
+    GST_ERROR ("no addrinfo found for %s: %s", ip, gai_strerror (aierr));
+    return GST_RTSP_ERROR;
+  }
+no_family:
+  {
+    GST_ERROR ("no family found for %s", ip);
+    freeaddrinfo (aires);
+    return GST_RTSP_ERROR;
+  }
+no_socket:
+  {
+    GST_ERROR ("no socket %d (%s)", errno, g_strerror (errno));
+    freeaddrinfo (aires);
+    return GST_RTSP_ESYS;
+  }
+sys_error:
+  {
+    GST_ERROR ("system error %d (%s)", errno, g_strerror (errno));
+    REMOVE_POLLFD (fdset, fdout);
+    freeaddrinfo (aires);
+    return GST_RTSP_ESYS;
+  }
+timeout:
   {
-    g_free (newconn);
-    return GST_RTSP_ESYS;
+    GST_ERROR ("timeout");
+    REMOVE_POLLFD (fdset, fdout);
+    freeaddrinfo (aires);
+    return GST_RTSP_ETIMEOUT;
+  }
+}
+
+static GstRTSPResult
+setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout)
+{
+  gint i;
+  GstRTSPResult res;
+  gchar *str;
+  guint idx, line;
+  gint retval;
+  GstClockTime to;
+  gchar *ip, *url_port_str;
+  guint16 port, url_port;
+  gchar codestr[4], *resultstr;
+  gint code;
+  GstRTSPUrl *url;
+  gchar *hostparam;
+
+  /* create a random sessionid */
+  for (i = 0; i < TUNNELID_LEN; i++)
+    conn->tunnelid[i] = g_random_int_range ('a', 'z');
+  conn->tunnelid[TUNNELID_LEN - 1] = '\0';
+
+  url = conn->url;
+  /* get the port from the url */
+  gst_rtsp_url_get_port (url, &url_port);
+
+  if (conn->proxy_host) {
+    hostparam = g_strdup_printf ("Host: %s:%d\r\n", url->host, url_port);
+    url_port_str = g_strdup_printf (":%d", url_port);
+    ip = conn->proxy_host;
+    port = conn->proxy_port;
+  } else {
+    hostparam = NULL;
+    url_port_str = NULL;
+    ip = conn->ip;
+    port = url_port;
+  }
+
+  /* */
+  str = g_strdup_printf ("GET %s%s%s%s%s%s HTTP/1.0\r\n"
+      "%s"
+      "x-sessioncookie: %s\r\n"
+      "Accept: application/x-rtsp-tunnelled\r\n"
+      "Pragma: no-cache\r\n"
+      "Cache-Control: no-cache\r\n" "\r\n",
+      conn->proxy_host ? "http://" : "",
+      conn->proxy_host ? url->host : "",
+      conn->proxy_host ? url_port_str : "",
+      url->abspath, url->query ? "?" : "", url->query ? url->query : "",
+      hostparam ? hostparam : "", conn->tunnelid);
+
+  /* we start by writing to this fd */
+  conn->writefd = &conn->fd0;
+
+  res = gst_rtsp_connection_write (conn, (guint8 *) str, strlen (str), timeout);
+  g_free (str);
+  if (res != GST_RTSP_OK)
+    goto write_failed;
+
+  gst_poll_fd_ctl_write (conn->fdset, &conn->fd0, FALSE);
+  gst_poll_fd_ctl_read (conn->fdset, &conn->fd0, TRUE);
+
+  to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
+
+  line = 0;
+  while (TRUE) {
+    guint8 buffer[4096];
+
+    idx = 0;
+    while (TRUE) {
+      res = read_line (conn->fd0.fd, buffer, &idx, sizeof (buffer), NULL);
+      if (res == GST_RTSP_EEOF)
+        goto eof;
+      if (res == GST_RTSP_OK)
+        break;
+      if (res != GST_RTSP_EINTR)
+        goto read_error;
+
+      do {
+        retval = gst_poll_wait (conn->fdset, to);
+      } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
+
+      /* check for timeout */
+      if (retval == 0)
+        goto timeout;
+
+      if (retval == -1) {
+        if (errno == EBUSY)
+          goto stopped;
+        else
+          goto select_error;
+      }
+    }
+
+    /* check for last line */
+    if (buffer[0] == '\r')
+      buffer[0] = '\0';
+    if (buffer[0] == '\0')
+      break;
+
+    if (line == 0) {
+      /* first line, parse response */
+      gchar versionstr[20];
+      gchar *bptr;
+
+      bptr = (gchar *) buffer;
+
+      parse_string (versionstr, sizeof (versionstr), &bptr);
+      parse_string (codestr, sizeof (codestr), &bptr);
+      code = atoi (codestr);
+
+      while (g_ascii_isspace (*bptr))
+        bptr++;
+
+      resultstr = bptr;
+
+      if (code != GST_RTSP_STS_OK)
+        goto wrong_result;
+    } else {
+      gchar key[32];
+      gchar *value;
+
+      /* other lines, parse key/value */
+      res = parse_key_value (buffer, key, sizeof (key), &value);
+      if (res == GST_RTSP_OK) {
+        /* we got a new ip address */
+        if (g_ascii_strcasecmp (key, "x-server-ip-address") == 0) {
+          if (conn->proxy_host) {
+            /* if we use a proxy we need to change the destination url */
+            g_free (url->host);
+            url->host = g_strdup (value);
+            g_free (hostparam);
+            g_free (url_port_str);
+            hostparam =
+                g_strdup_printf ("Host: %s:%d\r\n", url->host, url_port);
+            url_port_str = g_strdup_printf (":%d", url_port);
+          } else {
+            /* and resolve the new ip address */
+            if (!(ip = do_resolve (conn->ip)))
+              goto not_resolved;
+            g_free (conn->ip);
+            conn->ip = ip;
+          }
+        }
+      }
+    }
+    line++;
+  }
+
+  /* connect to the host/port */
+  res = do_connect (ip, port, &conn->fd1, conn->fdset, timeout);
+  if (res != GST_RTSP_OK)
+    goto connect_failed;
+
+  /* this is now our writing socket */
+  conn->writefd = &conn->fd1;
+
+  /* */
+  str = g_strdup_printf ("POST %s%s%s%s%s%s HTTP/1.0\r\n"
+      "%s"
+      "x-sessioncookie: %s\r\n"
+      "Content-Type: application/x-rtsp-tunnelled\r\n"
+      "Pragma: no-cache\r\n"
+      "Cache-Control: no-cache\r\n"
+      "Content-Length: 32767\r\n"
+      "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n"
+      "\r\n",
+      conn->proxy_host ? "http://" : "",
+      conn->proxy_host ? url->host : "",
+      conn->proxy_host ? url_port_str : "",
+      url->abspath, url->query ? "?" : "", url->query ? url->query : "",
+      hostparam ? hostparam : "", conn->tunnelid);
+
+  res = gst_rtsp_connection_write (conn, (guint8 *) str, strlen (str), timeout);
+  g_free (str);
+  if (res != GST_RTSP_OK)
+    goto write_failed;
+
+exit:
+  g_free (hostparam);
+  g_free (url_port_str);
+
+  return res;
+
+  /* ERRORS */
+write_failed:
+  {
+    GST_ERROR ("write failed (%d)", res);
+    goto exit;
+  }
+eof:
+  {
+    res = GST_RTSP_EEOF;
+    goto exit;
+  }
+read_error:
+  {
+    goto exit;
+  }
+timeout:
+  {
+    res = GST_RTSP_ETIMEOUT;
+    goto exit;
+  }
+select_error:
+  {
+    res = GST_RTSP_ESYS;
+    goto exit;
+  }
+stopped:
+  {
+    res = GST_RTSP_EINTR;
+    goto exit;
+  }
+wrong_result:
+  {
+    GST_ERROR ("got failure response %d %s", code, resultstr);
+    res = GST_RTSP_ERROR;
+    goto exit;
+  }
+not_resolved:
+  {
+    GST_ERROR ("could not resolve %s", conn->ip);
+    res = GST_RTSP_ENET;
+    goto exit;
+  }
+connect_failed:
+  {
+    GST_ERROR ("failed to connect");
+    goto exit;
   }
 }
 
@@ -191,132 +819,128 @@
 GstRTSPResult
 gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout)
 {
-  gint fd;
-  struct sockaddr_in sa_in;
-  struct hostent *hostinfo;
-  const gchar *ip;
-  struct in_addr addr;
-  gint ret;
+  GstRTSPResult res;
+  gchar *ip;
   guint16 port;
   GstRTSPUrl *url;
-  GstClockTime to;
-  gint retval;
-
-#ifdef G_OS_WIN32
-  unsigned long flags = 1;
-  struct in_addr *addrp;
-#else
-  char **addrs;
-  gchar ipbuf[INET_ADDRSTRLEN];
-#endif /* G_OS_WIN32 */
 
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (conn->url != NULL, GST_RTSP_EINVAL);
-  g_return_val_if_fail (conn->fd.fd < 0, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->fd0.fd < 0, GST_RTSP_EINVAL);
 
   url = conn->url;
 
-  /* first check if it already is an IP address */
-  if (inet_aton (url->host, &addr)) {
-    ip = url->host;
+  if (conn->proxy_host && conn->tunneled) {
+    if (!(ip = do_resolve (conn->proxy_host))) {
+      GST_ERROR ("could not resolve %s", conn->proxy_host);
+      goto not_resolved;
+    }
+    port = conn->proxy_port;
+    g_free (conn->proxy_host);
+    conn->proxy_host = ip;
   } else {
-    hostinfo = gethostbyname (url->host);
-    if (!hostinfo)
-      goto not_resolved;        /* h_errno set */
-
-    if (hostinfo->h_addrtype != AF_INET)
-      goto not_ip;              /* host not an IP host */
-#ifdef G_OS_WIN32
-    addrp = (struct in_addr *) hostinfo->h_addr_list[0];
-    /* this is not threadsafe */
-    ip = inet_ntoa (*addrp);
-#else
-    addrs = hostinfo->h_addr_list;
-    ip = inet_ntop (AF_INET, (struct in_addr *) addrs[0], ipbuf,
-        sizeof (ipbuf));
-#endif /* G_OS_WIN32 */
+    if (!(ip = do_resolve (url->host))) {
+      GST_ERROR ("could not resolve %s", url->host);
+      goto not_resolved;
+    }
+    /* get the port from the url */
+    gst_rtsp_url_get_port (url, &port);
+
+    g_free (conn->ip);
+    conn->ip = ip;
   }
 
-  /* get the port from the url */
-  gst_rtsp_url_get_port (url, &port);
-
-  memset (&sa_in, 0, sizeof (sa_in));
-  sa_in.sin_family = AF_INET;   /* network socket */
-  sa_in.sin_port = htons (port);        /* on port */
-  sa_in.sin_addr.s_addr = inet_addr (ip);       /* on host ip */
-
-  fd = socket (AF_INET, SOCK_STREAM, 0);
-  if (fd == -1)
-    goto sys_error;
-
-  /* set to non-blocking mode so that we can cancel the connect */
-#ifndef G_OS_WIN32
-  fcntl (fd, F_SETFL, O_NONBLOCK);
-#else
-  ioctlsocket (fd, FIONBIO, &flags);
-#endif /* G_OS_WIN32 */
-
-  /* add the socket to our fdset */
-  conn->fd.fd = fd;
-  gst_poll_add_fd (conn->fdset, &conn->fd);
-
-  /* we are going to connect ASYNC now */
-  ret = connect (fd, (struct sockaddr *) &sa_in, sizeof (sa_in));
-  if (ret == 0)
-    goto done;
-  if (ERRNO_IS_NOT_EINPROGRESS)
-    goto sys_error;
-
-  /* wait for connect to complete up to the specified timeout or until we got
-   * interrupted. */
-  gst_poll_fd_ctl_write (conn->fdset, &conn->fd, TRUE);
-
-  to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
-
-  do {
-    retval = gst_poll_wait (conn->fdset, to);
-  } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
-
-  if (retval == 0)
-    goto timeout;
-  else if (retval == -1)
-    goto sys_error;
-
-  gst_poll_fd_ignored (conn->fdset, &conn->fd);
-
-done:
-  conn->ip = g_strdup (ip);
+  /* connect to the host/port */
+  res = do_connect (ip, port, &conn->fd0, conn->fdset, timeout);
+  if (res != GST_RTSP_OK)
+    goto connect_failed;
+
+  /* this is our read URL */
+  conn->readfd = &conn->fd0;
+
+  if (conn->tunneled) {
+    res = setup_tunneling (conn, timeout);
+    if (res != GST_RTSP_OK)
+      goto tunneling_failed;
+  } else {
+    conn->writefd = &conn->fd0;
+  }
 
   return GST_RTSP_OK;
 
-sys_error:
-  {
-    if (conn->fd.fd >= 0) {
-      gst_poll_remove_fd (conn->fdset, &conn->fd);
-      conn->fd.fd = -1;
-    }
-    if (fd >= 0)
-      CLOSE_SOCKET (fd);
-    return GST_RTSP_ESYS;
-  }
 not_resolved:
   {
     return GST_RTSP_ENET;
   }
-not_ip:
+connect_failed:
   {
-    return GST_RTSP_ENOTIP;
+    GST_ERROR ("failed to connect");
+    return res;
   }
-timeout:
+tunneling_failed:
   {
-    if (conn->fd.fd >= 0) {
-      gst_poll_remove_fd (conn->fdset, &conn->fd);
-      conn->fd.fd = -1;
-    }
-    if (fd >= 0)
-      CLOSE_SOCKET (fd);
-    return GST_RTSP_ETIMEOUT;
+    GST_ERROR ("failed to setup tunneling");
+    return res;
+  }
+}
+
+static void
+md5_digest_to_hex_string (unsigned char digest[16], char string[33])
+{
+  static const char hexdigits[] = "0123456789abcdef";
+  int i;
+
+  for (i = 0; i < 16; i++) {
+    string[i * 2] = hexdigits[(digest[i] >> 4) & 0x0f];
+    string[i * 2 + 1] = hexdigits[digest[i] & 0x0f];
   }
+  string[32] = 0;
+}
+
+static void
+auth_digest_compute_hex_urp (const gchar * username,
+    const gchar * realm, const gchar * password, gchar hex_urp[33])
+{
+  struct MD5Context md5_context;
+  unsigned char digest[16];
+
+  MD5Init (&md5_context);
+  MD5Update (&md5_context, username, strlen (username));
+  MD5Update (&md5_context, ":", 1);
+  MD5Update (&md5_context, realm, strlen (realm));
+  MD5Update (&md5_context, ":", 1);
+  MD5Update (&md5_context, password, strlen (password));
+  MD5Final (digest, &md5_context);
+  md5_digest_to_hex_string (digest, hex_urp);
+}
+
+static void
+auth_digest_compute_response (const gchar * method,
+    const gchar * uri, const gchar * hex_a1, const gchar * nonce,
+    gchar response[33])
+{
+  char hex_a2[33];
+  struct MD5Context md5_context;
+  unsigned char digest[16];
+
+  /* compute A2 */
+  MD5Init (&md5_context);
+  MD5Update (&md5_context, method, strlen (method));
+  MD5Update (&md5_context, ":", 1);
+  MD5Update (&md5_context, uri, strlen (uri));
+  MD5Final (digest, &md5_context);
+  md5_digest_to_hex_string (digest, hex_a2);
+
+  /* compute KD */
+  MD5Init (&md5_context);
+  MD5Update (&md5_context, hex_a1, strlen (hex_a1));
+  MD5Update (&md5_context, ":", 1);
+  MD5Update (&md5_context, nonce, strlen (nonce));
+  MD5Update (&md5_context, ":", 1);
+
+  MD5Update (&md5_context, hex_a2, 32);
+  MD5Final (digest, &md5_context);
+  md5_digest_to_hex_string (digest, response);
 }
 
 static void
@@ -324,18 +948,62 @@
 {
   switch (conn->auth_method) {
     case GST_RTSP_AUTH_BASIC:{
-      gchar *user_pass =
-          g_strdup_printf ("%s:%s", conn->username, conn->passwd);
-      gchar *user_pass64 =
-          gst_rtsp_base64_encode (user_pass, strlen (user_pass));
-      gchar *auth_string = g_strdup_printf ("Basic %s", user_pass64);
-
-      gst_rtsp_message_add_header (message, GST_RTSP_HDR_AUTHORIZATION,
+      gchar *user_pass;
+      gchar *user_pass64;
+      gchar *auth_string;
+
+      user_pass = g_strdup_printf ("%s:%s", conn->username, conn->passwd);
+      user_pass64 = g_base64_encode ((guchar *) user_pass, strlen (user_pass));
+      auth_string = g_strdup_printf ("Basic %s", user_pass64);
+
+      gst_rtsp_message_take_header (message, GST_RTSP_HDR_AUTHORIZATION,
           auth_string);
 
       g_free (user_pass);
       g_free (user_pass64);
-      g_free (auth_string);
+      break;
+    }
+    case GST_RTSP_AUTH_DIGEST:{
+      gchar response[33], hex_urp[33];
+      gchar *auth_string, *auth_string2;
+      gchar *realm;
+      gchar *nonce;
+      gchar *opaque;
+      const gchar *uri;
+      const gchar *method;
+
+      /* we need to have some params set */
+      if (conn->auth_params == NULL)
+        break;
+
+      /* we need the realm and nonce */
+      realm = (gchar *) g_hash_table_lookup (conn->auth_params, "realm");
+      nonce = (gchar *) g_hash_table_lookup (conn->auth_params, "nonce");
+      if (realm == NULL || nonce == NULL)
+        break;
+
+      auth_digest_compute_hex_urp (conn->username, realm, conn->passwd,
+          hex_urp);
+
+      method = gst_rtsp_method_as_text (message->type_data.request.method);
+      uri = message->type_data.request.uri;
+
+      /* Assume no qop, algorithm=md5, stale=false */
+      /* For algorithm MD5, a1 = urp. */
+      auth_digest_compute_response (method, uri, hex_urp, nonce, response);
+      auth_string = g_strdup_printf ("Digest username=\"%s\", "
+          "realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
+          conn->username, realm, nonce, uri, response);
+
+      opaque = (gchar *) g_hash_table_lookup (conn->auth_params, "opaque");
+      if (opaque) {
+        auth_string2 = g_strdup_printf ("%s, opaque=\"%s\"", auth_string,
+            opaque);
+        g_free (auth_string);
+        auth_string = auth_string2;
+      }
+      gst_rtsp_message_take_header (message, GST_RTSP_HDR_AUTHORIZATION,
+          auth_string);
       break;
     }
     default:
@@ -345,12 +1013,10 @@
 }
 
 static void
-add_date_header (GstRTSPMessage * message)
+gen_date_string (gchar * date_string, guint len)
 {
   GTimeVal tv;
-  gchar date_string[100];
   time_t t;
-
 #ifdef HAVE_GMTIME_R
   struct tm tm_;
 #endif
@@ -359,14 +1025,139 @@
   t = (time_t) tv.tv_sec;
 
 #ifdef HAVE_GMTIME_R
-  strftime (date_string, sizeof (date_string), "%a, %d %b %Y %H:%M:%S GMT",
-      gmtime_r (&t, &tm_));
+  strftime (date_string, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime_r (&t, &tm_));
 #else
-  strftime (date_string, sizeof (date_string), "%a, %d %b %Y %H:%M:%S GMT",
-      gmtime (&t));
+  strftime (date_string, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime (&t));
 #endif
-
-  gst_rtsp_message_add_header (message, GST_RTSP_HDR_DATE, date_string);
+}
+
+static GstRTSPResult
+write_bytes (gint fd, const guint8 * buffer, guint * idx, guint size)
+{
+  guint left;
+
+  if (G_UNLIKELY (*idx > size))
+    return GST_RTSP_ERROR;
+
+  left = size - *idx;
+
+  while (left) {
+    gint r;
+
+    r = WRITE_SOCKET (fd, &buffer[*idx], left);
+    if (G_UNLIKELY (r == 0)) {
+      return GST_RTSP_EINTR;
+    } else if (G_UNLIKELY (r < 0)) {
+      if (ERRNO_IS_EAGAIN)
+        return GST_RTSP_EINTR;
+      if (!ERRNO_IS_EINTR)
+        return GST_RTSP_ESYS;
+    } else {
+      left -= r;
+      *idx += r;
+    }
+  }
+  return GST_RTSP_OK;
+}
+
+static gint
+fill_bytes (gint fd, guint8 * buffer, guint size, DecodeCtx * ctx)
+{
+  gint out = 0;
+
+  if (ctx) {
+    while (size > 0) {
+      guint8 in[sizeof (ctx->out) * 4 / 3];
+      gint r;
+
+      while (size > 0 && ctx->cout < ctx->coutl) {
+        /* we have some leftover bytes */
+        *buffer++ = ctx->out[ctx->cout++];
+        size--;
+        out++;
+      }
+
+      /* got what we needed? */
+      if (size == 0)
+        break;
+
+      /* try to read more bytes */
+      r = READ_SOCKET (fd, in, sizeof (in));
+      if (r <= 0) {
+        if (out == 0)
+          out = r;
+        break;
+      }
+
+      ctx->cout = 0;
+      ctx->coutl =
+          g_base64_decode_step ((gchar *) in, r, ctx->out, &ctx->state,
+          &ctx->save);
+    }
+  } else {
+    out = READ_SOCKET (fd, buffer, size);
+  }
+
+  return out;
+}
+
+static GstRTSPResult
+read_bytes (gint fd, guint8 * buffer, guint * idx, guint size, DecodeCtx * ctx)
+{
+  guint left;
+
+  if (G_UNLIKELY (*idx > size))
+    return GST_RTSP_ERROR;
+
+  left = size - *idx;
+
+  while (left) {
+    gint r;
+
+    r = fill_bytes (fd, &buffer[*idx], left, ctx);
+    if (G_UNLIKELY (r == 0)) {
+      return GST_RTSP_EEOF;
+    } else if (G_UNLIKELY (r < 0)) {
+      if (ERRNO_IS_EAGAIN)
+        return GST_RTSP_EINTR;
+      if (!ERRNO_IS_EINTR)
+        return GST_RTSP_ESYS;
+    } else {
+      left -= r;
+      *idx += r;
+    }
+  }
+  return GST_RTSP_OK;
+}
+
+static GstRTSPResult
+read_line (gint fd, guint8 * buffer, guint * idx, guint size, DecodeCtx * ctx)
+{
+  while (TRUE) {
+    guint8 c;
+    gint r;
+
+    r = fill_bytes (fd, &c, 1, ctx);
+    if (G_UNLIKELY (r == 0)) {
+      return GST_RTSP_EEOF;
+    } else if (G_UNLIKELY (r < 0)) {
+      if (ERRNO_IS_EAGAIN)
+        return GST_RTSP_EINTR;
+      if (!ERRNO_IS_EINTR)
+        return GST_RTSP_ESYS;
+    } else {
+      if (c == '\n')            /* end on \n */
+        break;
+      if (c == '\r')            /* ignore \r */
+        continue;
+
+      if (G_LIKELY (*idx < size - 1))
+        buffer[(*idx)++] = c;
+    }
+  }
+  buffer[*idx] = '\0';
+
+  return GST_RTSP_OK;
 }
 
 /**
@@ -388,47 +1179,48 @@
 gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data,
     guint size, GTimeVal * timeout)
 {
-  guint towrite;
+  guint offset;
   gint retval;
   GstClockTime to;
+  GstRTSPResult res;
 
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (data != NULL || size == 0, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL);
 
   gst_poll_set_controllable (conn->fdset, TRUE);
-  gst_poll_fd_ctl_write (conn->fdset, &conn->fd, TRUE);
-  gst_poll_fd_ctl_read (conn->fdset, &conn->fd, FALSE);
+  gst_poll_fd_ctl_write (conn->fdset, conn->writefd, TRUE);
+  gst_poll_fd_ctl_read (conn->fdset, conn->readfd, FALSE);
+  /* clear all previous poll results */
+  gst_poll_fd_ignored (conn->fdset, conn->writefd);
+  gst_poll_fd_ignored (conn->fdset, conn->readfd);
 
   to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
 
-  towrite = size;
-
-  while (towrite > 0) {
-    gint written;
-
+  offset = 0;
+
+  while (TRUE) {
+    /* try to write */
+    res = write_bytes (conn->writefd->fd, data, &offset, size);
+    if (G_LIKELY (res == GST_RTSP_OK))
+      break;
+    if (G_UNLIKELY (res != GST_RTSP_EINTR))
+      goto write_error;
+
+    /* not all is written, wait until we can write more */
     do {
       retval = gst_poll_wait (conn->fdset, to);
     } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
 
-    if (retval == 0)
+    if (G_UNLIKELY (retval == 0))
       goto timeout;
 
-    if (retval == -1) {
+    if (G_UNLIKELY (retval == -1)) {
       if (errno == EBUSY)
         goto stopped;
       else
         goto select_error;
     }
-
-    /* now we can write */
-    written = WRITE_SOCKET (conn->fd.fd, data, towrite);
-    if (written < 0) {
-      if (ERRNO_IS_NOT_EAGAIN && ERRNO_IS_NOT_EINTR)
-        goto write_error;
-    } else {
-      towrite -= written;
-      data += written;
-    }
   }
   return GST_RTSP_OK;
 
@@ -447,48 +1239,14 @@
   }
 write_error:
   {
-    return GST_RTSP_ESYS;
+    return res;
   }
 }
 
-/**
- * gst_rtsp_connection_send:
- * @conn: a #GstRTSPConnection
- * @message: the message to send
- * @timeout: a timeout value or #NULL
- *
- * Attempt to send @message to the connected @conn, blocking up to
- * the specified @timeout. @timeout can be #NULL, in which case this function
- * might block forever.
- * 
- * This function can be cancelled with gst_rtsp_connection_flush().
- *
- * Returns: #GST_RTSP_OK on success.
- */
-GstRTSPResult
-gst_rtsp_connection_send (GstRTSPConnection * conn, GstRTSPMessage * message,
-    GTimeVal * timeout)
+static GString *
+message_to_string (GstRTSPConnection * conn, GstRTSPMessage * message)
 {
   GString *str = NULL;
-  GstRTSPResult res;
-
-#ifdef G_OS_WIN32
-  WSADATA w;
-  int error;
-#endif
-
-  g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
-  g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
-
-#ifdef G_OS_WIN32
-  error = WSAStartup (0x0202, &w);
-
-  if (error)
-    goto startup_error;
-
-  if (w.wVersion != 0x0202)
-    goto version_error;
-#endif
 
   str = g_string_new ("");
 
@@ -530,14 +1288,19 @@
       break;
     }
     default:
-      g_return_val_if_reached (GST_RTSP_EINVAL);
+      g_string_free (str, TRUE);
+      g_return_val_if_reached (NULL);
       break;
   }
 
   /* append headers and body */
   if (message->type != GST_RTSP_MESSAGE_DATA) {
+    gchar date_string[100];
+
+    gen_date_string (date_string, sizeof (date_string));
+
     /* add date header */
-    add_date_header (message);
+    gst_rtsp_message_add_header (message, GST_RTSP_HDR_DATE, date_string);
 
     /* append headers */
     gst_rtsp_message_append_headers (message, str);
@@ -561,71 +1324,64 @@
     }
   }
 
+  return str;
+}
+
+/**
+ * gst_rtsp_connection_send:
+ * @conn: a #GstRTSPConnection
+ * @message: the message to send
+ * @timeout: a timeout value or #NULL
+ *
+ * Attempt to send @message to the connected @conn, blocking up to
+ * the specified @timeout. @timeout can be #NULL, in which case this function
+ * might block forever.
+ * 
+ * This function can be cancelled with gst_rtsp_connection_flush().
+ *
+ * Returns: #GST_RTSP_OK on success.
+ */
+GstRTSPResult
+gst_rtsp_connection_send (GstRTSPConnection * conn, GstRTSPMessage * message,
+    GTimeVal * timeout)
+{
+  GString *string = NULL;
+  GstRTSPResult res;
+  gchar *str;
+  gsize len;
+
+  g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
+
+  if (G_UNLIKELY (!(string = message_to_string (conn, message))))
+    goto no_message;
+
+  if (conn->tunneled) {
+    str = g_base64_encode ((const guchar *) string->str, string->len);
+    g_string_free (string, TRUE);
+    len = strlen (str);
+  } else {
+    str = string->str;
+    len = string->len;
+    g_string_free (string, FALSE);
+  }
+
   /* write request */
-  res =
-      gst_rtsp_connection_write (conn, (guint8 *) str->str, str->len, timeout);
-
-  g_string_free (str, TRUE);
+  res = gst_rtsp_connection_write (conn, (guint8 *) str, len, timeout);
+
+  g_free (str);
 
   return res;
 
-#ifdef G_OS_WIN32
-startup_error:
-  {
-    g_warning ("Error %d on WSAStartup", error);
-    return GST_RTSP_EWSASTART;
-  }
-version_error:
+no_message:
   {
-    g_warning ("Windows sockets are not version 0x202 (current 0x%x)",
-        w.wVersion);
-    WSACleanup ();
-    return GST_RTSP_EWSAVERSION;
-  }
-#endif
-}
-
-static GstRTSPResult
-read_line (gint fd, gchar * buffer, guint size)
-{
-  guint idx;
-  gchar c;
-  gint r;
-
-  idx = 0;
-  while (TRUE) {
-    r = READ_SOCKET (fd, &c, 1);
-    if (r == 0) {
-      goto eof;
-    } else if (r < 0) {
-      if (ERRNO_IS_NOT_EAGAIN && ERRNO_IS_NOT_EINTR)
-        goto read_error;
-    } else {
-      if (c == '\n')            /* end on \n */
-        break;
-      if (c == '\r')            /* ignore \r */
-        continue;
-
-      if (idx < size - 1)
-        buffer[idx++] = c;
-    }
-  }
-  buffer[idx] = '\0';
-
-  return GST_RTSP_OK;
-
-eof:
-  {
-    return GST_RTSP_EEOF;
-  }
-read_error:
-  {
-    return GST_RTSP_ESYS;
+    g_warning ("Wrong message");
+    return GST_RTSP_EINVAL;
   }
 }
 
 static void
-read_string (gchar * dest, gint size, gchar ** src)
+parse_string (gchar * dest, gint size, gchar ** src)
 {
   gint idx;
 
@@ -644,7 +1400,7 @@
 }
 
 static void
-read_key (gchar * dest, gint size, gchar ** src)
+parse_key (gchar * dest, gint size, gchar ** src)
 {
   gint idx;
 
@@ -659,7 +1415,7 @@
 }
 
 static GstRTSPResult
-parse_response_status (gchar * buffer, GstRTSPMessage * msg)
+parse_response_status (guint8 * buffer, GstRTSPMessage * msg)
 {
   GstRTSPResult res;
   gchar versionstr[20];
@@ -667,10 +1423,10 @@
   gint code;
   gchar *bptr;
 
-  bptr = buffer;
-
-  read_string (versionstr, sizeof (versionstr), &bptr);
-  read_string (codestr, sizeof (codestr), &bptr);
+  bptr = (gchar *) buffer;
+
+  parse_string (versionstr, sizeof (versionstr), &bptr);
+  parse_string (codestr, sizeof (codestr), &bptr);
   code = atoi (codestr);
 
   while (g_ascii_isspace (*bptr))
@@ -695,7 +1451,8 @@
 }
 
 static GstRTSPResult
-parse_request_line (gchar * buffer, GstRTSPMessage * msg)
+parse_request_line (GstRTSPConnection * conn, guint8 * buffer,
+    GstRTSPMessage * msg)
 {
   GstRTSPResult res = GST_RTSP_OK;
   gchar versionstr[20];
@@ -703,148 +1460,374 @@
   gchar urlstr[4096];
   gchar *bptr;
   GstRTSPMethod method;
-
-  bptr = buffer;
-
-  read_string (methodstr, sizeof (methodstr), &bptr);
+  GstRTSPTunnelState tstate = TUNNEL_STATE_NONE;
+
+  bptr = (gchar *) buffer;
+
+  parse_string (methodstr, sizeof (methodstr), &bptr);
   method = gst_rtsp_find_method (methodstr);
-
-  read_string (urlstr, sizeof (urlstr), &bptr);
-  if (*urlstr == '\0')
-    res = GST_RTSP_EPARSE;
-
-  read_string (versionstr, sizeof (versionstr), &bptr);
-
-  if (*bptr != '\0')
-    res = GST_RTSP_EPARSE;
+  if (method == GST_RTSP_INVALID) {
+    /* a tunnel request is allowed when we don't have one yet */
+    if (conn->tstate != TUNNEL_STATE_NONE)
+      goto invalid_method;
+    /* we need GET or POST for a valid tunnel request */
+    if (!strcmp (methodstr, "GET"))
+      tstate = TUNNEL_STATE_GET;
+    else if (!strcmp (methodstr, "POST"))
+      tstate = TUNNEL_STATE_POST;
+    else
+      goto invalid_method;
+  }
+
+  parse_string (urlstr, sizeof (urlstr), &bptr);
+  if (G_UNLIKELY (*urlstr == '\0'))
+    goto invalid_url;
+
+  parse_string (versionstr, sizeof (versionstr), &bptr);
+
+  if (G_UNLIKELY (*bptr != '\0'))
+    goto invalid_version;
 
   if (strcmp (versionstr, "RTSP/1.0") == 0) {
-    if (gst_rtsp_message_init_request (msg, method, urlstr) != GST_RTSP_OK)
-      res = GST_RTSP_EPARSE;
+    res = gst_rtsp_message_init_request (msg, method, urlstr);
   } else if (strncmp (versionstr, "RTSP/", 5) == 0) {
-    if (gst_rtsp_message_init_request (msg, method, urlstr) != GST_RTSP_OK)
+    res = gst_rtsp_message_init_request (msg, method, urlstr);
+    msg->type_data.request.version = GST_RTSP_VERSION_INVALID;
+  } else if (strcmp (versionstr, "HTTP/1.0") == 0) {
+    /* tunnel request, we need a tunnel method */
+    if (tstate == TUNNEL_STATE_NONE) {
       res = GST_RTSP_EPARSE;
-    msg->type_data.request.version = GST_RTSP_VERSION_INVALID;
+    } else {
+      conn->tstate = tstate;
+    }
   } else {
-    gst_rtsp_message_init_request (msg, method, urlstr);
-    msg->type_data.request.version = GST_RTSP_VERSION_INVALID;
     res = GST_RTSP_EPARSE;
   }
 
   return res;
+
+  /* ERRORS */
+invalid_method:
+  {
+    GST_ERROR ("invalid method %s", methodstr);
+    return GST_RTSP_EPARSE;
+  }
+invalid_url:
+  {
+    GST_ERROR ("invalid url %s", urlstr);
+    return GST_RTSP_EPARSE;
+  }
+invalid_version:
+  {
+    GST_ERROR ("invalid version");
+    return GST_RTSP_EPARSE;
+  }
 }
 
-/* parsing lines means reading a Key: Value pair */
 static GstRTSPResult
-parse_line (gchar * buffer, GstRTSPMessage * msg)
+parse_key_value (guint8 * buffer, gchar * key, guint keysize, gchar ** value)
 {
-  gchar key[32];
   gchar *bptr;
-  GstRTSPHeaderField field;
-
-  bptr = buffer;
+
+  bptr = (gchar *) buffer;
 
   /* read key */
-  read_key (key, sizeof (key), &bptr);
-  if (*bptr != ':')
+  parse_key (key, keysize, &bptr);
+  if (G_UNLIKELY (*bptr != ':'))
     goto no_column;
 
   bptr++;
-
-  field = gst_rtsp_find_header_field (key);
-  if (field != GST_RTSP_HDR_INVALID) {
-    while (g_ascii_isspace (*bptr))
-      bptr++;
-    gst_rtsp_message_add_header (msg, field, bptr);
-  }
+  while (g_ascii_isspace (*bptr))
+    bptr++;
+
+  *value = bptr;
 
   return GST_RTSP_OK;
 
+  /* ERRORS */
 no_column:
   {
     return GST_RTSP_EPARSE;
   }
 }
 
+/* parsing lines means reading a Key: Value pair */
+static GstRTSPResult
+parse_line (GstRTSPConnection * conn, guint8 * buffer, GstRTSPMessage * msg)
+{
+  GstRTSPResult res;
+  gchar key[32];
+  gchar *value;
+  GstRTSPHeaderField field;
+
+  res = parse_key_value (buffer, key, sizeof (key), &value);
+  if (G_UNLIKELY (res != GST_RTSP_OK))
+    goto parse_error;
+
+  if (conn->tstate == TUNNEL_STATE_GET || conn->tstate == TUNNEL_STATE_POST) {
+    /* save the tunnel session in the connection */
+    if (!strcmp (key, "x-sessioncookie")) {
+      strncpy (conn->tunnelid, value, TUNNELID_LEN);
+      conn->tunnelid[TUNNELID_LEN - 1] = '\0';
+      conn->tunneled = TRUE;
+    }
+  } else {
+    field = gst_rtsp_find_header_field (key);
+    if (field != GST_RTSP_HDR_INVALID)
+      gst_rtsp_message_add_header (msg, field, value);
+  }
+
+  return GST_RTSP_OK;
+
+  /* ERRORS */
+parse_error:
+  {
+    return res;
+  }
+}
+
+/* returns:
+ *  GST_RTSP_OK when a complete message was read.
+ *  GST_RTSP_EEOF: when the socket is closed
+ *  GST_RTSP_EINTR: when more data is needed.
+ *  GST_RTSP_..: some other error occured.
+ */
+static GstRTSPResult
+build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
+    GstRTSPConnection * conn)
+{
+  GstRTSPResult res;
+
+  while (TRUE) {
+    switch (builder->state) {
+      case STATE_START:
+        builder->offset = 0;
+        res =
+            read_bytes (conn->readfd->fd, (guint8 *) builder->buffer,
+            &builder->offset, 1, conn->ctxp);
+        if (res != GST_RTSP_OK)
+          goto done;
+
+        /* we have 1 bytes now and we can see if this is a data message or
+         * not */
+        if (builder->buffer[0] == '$') {
+          /* data message, prepare for the header */
+          builder->state = STATE_DATA_HEADER;
+        } else {
+          builder->line = 0;
+          builder->state = STATE_READ_LINES;
+        }
+        break;
+      case STATE_DATA_HEADER:
+      {
+        res =
+            read_bytes (conn->readfd->fd, (guint8 *) builder->buffer,
+            &builder->offset, 4, conn->ctxp);
+        if (res != GST_RTSP_OK)
+          goto done;
+
+        gst_rtsp_message_init_data (message, builder->buffer[1]);
+
+        builder->body_len = (builder->buffer[2] << 8) | builder->buffer[3];
+        builder->body_data = g_malloc (builder->body_len + 1);
+        builder->body_data[builder->body_len] = '\0';
+        builder->offset = 0;
+        builder->state = STATE_DATA_BODY;
+        break;
+      }
+      case STATE_DATA_BODY:
+      {
+        res =
+            read_bytes (conn->readfd->fd, builder->body_data, &builder->offset,
+            builder->body_len, conn->ctxp);
+        if (res != GST_RTSP_OK)
+          goto done;
+
+        /* we have the complete body now, store in the message adjusting the
+         * length to include the traling '\0' */
+        gst_rtsp_message_take_body (message,
+            (guint8 *) builder->body_data, builder->body_len + 1);
+        builder->body_data = NULL;
+        builder->body_len = 0;
+
+        builder->state = STATE_END;
+        break;
+      }
+      case STATE_READ_LINES:
+      {
+        res = read_line (conn->readfd->fd, builder->buffer, &builder->offset,
+            sizeof (builder->buffer), conn->ctxp);
+        if (res != GST_RTSP_OK)
+          goto done;
+
+        /* we have a regular response */
+        if (builder->buffer[0] == '\r') {
+          builder->buffer[0] = '\0';
+        }
+
+        if (builder->buffer[0] == '\0') {
+          gchar *hdrval;
+
+          /* empty line, end of message header */
+          /* see if there is a Content-Length header */
+          if (gst_rtsp_message_get_header (message,
+                  GST_RTSP_HDR_CONTENT_LENGTH, &hdrval, 0) == GST_RTSP_OK) {
+            /* there is, prepare to read the body */
+            builder->body_len = atol (hdrval);
+            builder->body_data = g_malloc (builder->body_len + 1);
+            builder->body_data[builder->body_len] = '\0';
+            builder->offset = 0;
+            builder->state = STATE_DATA_BODY;
+          } else {
+            builder->state = STATE_END;
+          }
+          break;
+        }
+
+        /* we have a line */
+        if (builder->line == 0) {
+          /* first line, check for response status */
+          if (memcmp (builder->buffer, "RTSP", 4) == 0) {
+            res = parse_response_status (builder->buffer, message);
+          } else {
+            res = parse_request_line (conn, builder->buffer, message);
+          }
+          /* the first line must parse without errors */
+          if (res != GST_RTSP_OK)
+            goto done;
+        } else {
+          /* else just parse the line, ignore errors */
+          parse_line (conn, builder->buffer, message);
+        }
+        builder->line++;
+        builder->offset = 0;
+        break;
+      }
+      case STATE_END:
+      {
+        gchar *session_id;
+
+        if (conn->tstate == TUNNEL_STATE_GET) {
+          res = GST_RTSP_ETGET;
+          goto done;
+        } else if (conn->tstate == TUNNEL_STATE_POST) {
+          res = GST_RTSP_ETPOST;
+          goto done;
+        }
+
+        if (message->type == GST_RTSP_MESSAGE_DATA) {
+          /* data messages don't have headers */
+          res = GST_RTSP_OK;
+          goto done;
+        }
+
+        /* save session id in the connection for further use */
+        if (message->type == GST_RTSP_MESSAGE_RESPONSE &&
+            gst_rtsp_message_get_header (message, GST_RTSP_HDR_SESSION,
+                &session_id, 0) == GST_RTSP_OK) {
+          gint maxlen, i;
+
+          maxlen = sizeof (conn->session_id) - 1;
+          /* the sessionid can have attributes marked with ;
+           * Make sure we strip them */
+          for (i = 0; session_id[i] != '\0'; i++) {
+            if (session_id[i] == ';') {
+              maxlen = i;
+              /* parse timeout */
+              do {
+                i++;
+              } while (g_ascii_isspace (session_id[i]));
+              if (g_str_has_prefix (&session_id[i], "timeout=")) {
+                gint to;
+
+                /* if we parsed something valid, configure */
+                if ((to = atoi (&session_id[i + 8])) > 0)
+                  conn->timeout = to;
+              }
+              break;
+            }
+          }
+
+          /* make sure to not overflow */
+          strncpy (conn->session_id, session_id, maxlen);
+          conn->session_id[maxlen] = '\0';
+        }
+        res = GST_RTSP_OK;
+        goto done;
+      }
+      default:
+        res = GST_RTSP_ERROR;
+        break;
+    }
+  }
+done:
+  return res;
+}
+
 /**
- * gst_rtsp_connection_read_internal:
+ * gst_rtsp_connection_read:
  * @conn: a #GstRTSPConnection
  * @data: the data to read
  * @size: the size of @data
  * @timeout: a timeout value or #NULL
- * @allow_interrupt: can the pending read be interrupted
  *
  * Attempt to read @size bytes into @data from the connected @conn, blocking up to
  * the specified @timeout. @timeout can be #NULL, in which case this function
  * might block forever.
- * 
- * This function can be cancelled with gst_rtsp_connection_flush() only if
- * @allow_interrupt is set.
+ *
+ * This function can be cancelled with gst_rtsp_connection_flush().
  *
  * Returns: #GST_RTSP_OK on success.
  */
-static GstRTSPResult
-gst_rtsp_connection_read_internal (GstRTSPConnection * conn, guint8 * data,
-    guint size, GTimeVal * timeout, gboolean allow_interrupt)
+GstRTSPResult
+gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size,
+    GTimeVal * timeout)
 {
-  guint toread;
+  guint offset;
   gint retval;
   GstClockTime to;
-  FIONREAD_TYPE avail;
+  GstRTSPResult res;
 
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL);
-
-  if (size == 0)
+  g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL);
+
+  if (G_UNLIKELY (size == 0))
     return GST_RTSP_OK;
 
-  toread = size;
+  offset = 0;
 
   /* configure timeout if any */
   to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
 
-  /* if the call fails, just go in the select.. it should not fail. Else if
-   * there is enough data to read, skip the select call al together.*/
-  if (IOCTL_SOCKET (conn->fd.fd, FIONREAD, &avail) < 0)
-    avail = 0;
-  else if (avail >= toread)
-    goto do_read;
-
-  gst_poll_set_controllable (conn->fdset, allow_interrupt);
-  gst_poll_fd_ctl_write (conn->fdset, &conn->fd, FALSE);
-  gst_poll_fd_ctl_read (conn->fdset, &conn->fd, TRUE);
-
-  while (toread > 0) {
-    gint bytes;
+  gst_poll_set_controllable (conn->fdset, TRUE);
+  gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE);
+  gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE);
+
+  while (TRUE) {
+    res = read_bytes (conn->readfd->fd, data, &offset, size, conn->ctxp);
+    if (G_UNLIKELY (res == GST_RTSP_EEOF))
+      goto eof;
+    if (G_LIKELY (res == GST_RTSP_OK))
+      break;
+    if (G_UNLIKELY (res != GST_RTSP_EINTR))
+      goto read_error;
 
     do {
       retval = gst_poll_wait (conn->fdset, to);
     } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
 
-    if (retval == -1) {
+    /* check for timeout */
+    if (G_UNLIKELY (retval == 0))
+      goto select_timeout;
+
+    if (G_UNLIKELY (retval == -1)) {
       if (errno == EBUSY)
         goto stopped;
       else
         goto select_error;
     }
-
-    /* check for timeout */
-    if (retval == 0)
-      goto select_timeout;
-
-  do_read:
-    /* if we get here there is activity on the real fd since the select
-     * completed and the control socket was not readable. */
-    bytes = READ_SOCKET (conn->fd.fd, data, toread);
-    if (bytes == 0) {
-      goto eof;
-    } else if (bytes < 0) {
-      if (ERRNO_IS_NOT_EAGAIN && ERRNO_IS_NOT_EINTR)
-        goto read_error;
-    } else {
-      toread -= bytes;
-      data += bytes;
-    }
+    gst_poll_set_controllable (conn->fdset, FALSE);
   }
   return GST_RTSP_OK;
 
@@ -867,65 +1850,42 @@
   }
 read_error:
   {
-    return GST_RTSP_ESYS;
+    return res;
   }
 }
 
-/**
- * gst_rtsp_connection_read:
- * @conn: a #GstRTSPConnection
- * @data: the data to read
- * @size: the size of @data
- * @timeout: a timeout value or #NULL
- *
- * Attempt to read @size bytes into @data from the connected @conn, blocking up to
- * the specified @timeout. @timeout can be #NULL, in which case this function
- * might block forever.
- *
- * This function can be cancelled with gst_rtsp_connection_flush().
- *
- * Returns: #GST_RTSP_OK on success.
- */
-GstRTSPResult
-gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size,
-    GTimeVal * timeout)
-{
-  return gst_rtsp_connection_read_internal (conn, data, size, timeout, TRUE);
-}
-
-
-static GstRTSPResult
-read_body (GstRTSPConnection * conn, glong content_length, GstRTSPMessage * msg,
-    GTimeVal * timeout)
+static GString *
+gen_tunnel_reply (GstRTSPConnection * conn, GstRTSPStatusCode code)
 {
-  guint8 *body;
-  GstRTSPResult res;
-
-  if (content_length <= 0) {
-    body = NULL;
-    content_length = 0;
-    goto done;
+  GString *str;
+  gchar date_string[100];
+  const gchar *status;
+
+  gen_date_string (date_string, sizeof (date_string));
+
+  status = gst_rtsp_status_as_text (code);
+  if (status == NULL) {
+    code = GST_RTSP_STS_INTERNAL_SERVER_ERROR;
+    status = "Internal Server Error";
   }
 
-  body = g_malloc (content_length + 1);
-  body[content_length] = '\0';
-
-  GST_RTSP_CHECK (gst_rtsp_connection_read_internal (conn, body, content_length,
-          timeout, FALSE), read_error);
-
-  content_length += 1;
-
-done:
-  gst_rtsp_message_take_body (msg, (guint8 *) body, content_length);
-
-  return GST_RTSP_OK;
-
-  /* ERRORS */
-read_error:
-  {
-    g_free (body);
-    return res;
+  str = g_string_new ("");
+
+  /* */
+  g_string_append_printf (str, "HTTP/1.0 %d %s\r\n", code, status);
+  g_string_append_printf (str,
+      "Server: GStreamer RTSP Server\r\n"
+      "Date: %s\r\n"
+      "Connection: close\r\n"
+      "Cache-Control: no-store\r\n" "Pragma: no-cache\r\n", date_string);
+  if (code == GST_RTSP_STS_OK) {
+    if (conn->ip)
+      g_string_append_printf (str, "x-server-ip-address: %s\r\n", conn->ip);
+    g_string_append_printf (str,
+        "Content-Type: application/x-rtsp-tunnelled\r\n");
   }
+  g_string_append_printf (str, "\r\n");
+  return str;
 }
 
 /**
@@ -946,138 +1906,93 @@
 gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message,
     GTimeVal * timeout)
 {
-  gchar buffer[4096];
-  gint line;
-  glong content_length;
   GstRTSPResult res;
-  gboolean need_body;
+  GstRTSPBuilder builder;
+  gint retval;
+  GstClockTime to;
 
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
-
-  line = 0;
-
-  need_body = TRUE;
-
-  res = GST_RTSP_OK;
-  /* parse first line and headers */
-  while (res == GST_RTSP_OK) {
-    guint8 c;
-
-    /* read first character, this identifies data messages */
-    /* This is the only read() that we allow to be interrupted */
-    GST_RTSP_CHECK (gst_rtsp_connection_read_internal (conn, &c, 1, timeout,
-            TRUE), read_error);
-
-    /* check for data packet, first character is $ */
-    if (c == '$') {
-      guint16 size;
-
-      /* data packets are $<1 byte channel><2 bytes length,BE><data bytes> */
-
-      /* read channel, which is the next char */
-      GST_RTSP_CHECK (gst_rtsp_connection_read_internal (conn, &c, 1, timeout,
-              FALSE), read_error);
-
-      /* now we create a data message */
-      gst_rtsp_message_init_data (message, c);
-
-      /* next two bytes are the length of the data */
-      GST_RTSP_CHECK (gst_rtsp_connection_read_internal (conn,
-              (guint8 *) & size, 2, timeout, FALSE), read_error);
-
-      size = GUINT16_FROM_BE (size);
-
-      /* and read the body */
-      res = read_body (conn, size, message, timeout);
-      need_body = FALSE;
+  g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL);
+
+  /* configure timeout if any */
+  to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
+
+  gst_poll_set_controllable (conn->fdset, TRUE);
+  gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE);
+  gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE);
+
+  memset (&builder, 0, sizeof (GstRTSPBuilder));
+  while (TRUE) {
+    res = build_next (&builder, message, conn);
+    if (G_UNLIKELY (res == GST_RTSP_EEOF))
+      goto eof;
+    if (G_LIKELY (res == GST_RTSP_OK))
+      break;
+    if (res == GST_RTSP_ETGET) {
+      GString *str;
+
+      /* tunnel GET request, we can reply now */
+      str = gen_tunnel_reply (conn, GST_RTSP_STS_OK);
+      res =
+          gst_rtsp_connection_write (conn, (guint8 *) str->str, str->len,
+          timeout);
+      g_string_free (str, TRUE);
+    } else if (res == GST_RTSP_ETPOST) {
+      /* tunnel POST request, return the value, the caller now has to link the
+       * two connections. */
       break;
-    } else {
-      gint offset = 0;
-
-      /* we have a regular response */
-      if (c != '\r') {
-        buffer[0] = c;
-        offset = 1;
-      }
-      /* should not happen */
-      if (c == '\n')
-        break;
-
-      /* read lines */
-      GST_RTSP_CHECK (read_line (conn->fd.fd, buffer + offset,
-              sizeof (buffer) - offset), read_error);
-
-      if (buffer[0] == '\0')
-        break;
-
-      if (line == 0) {
-        /* first line, check for response status */
-        if (g_str_has_prefix (buffer, "RTSP")) {
-          res = parse_response_status (buffer, message);
-        } else {
-          res = parse_request_line (buffer, message);
-        }
-      } else {
-        /* else just parse the line */
-        parse_line (buffer, message);
-      }
+    } else if (G_UNLIKELY (res != GST_RTSP_EINTR))
+      goto read_error;
+
+    do {
+      retval = gst_poll_wait (conn->fdset, to);
+    } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
+
+    /* check for timeout */
+    if (G_UNLIKELY (retval == 0))
+      goto select_timeout;
+
+    if (G_UNLIKELY (retval == -1)) {
+      if (errno == EBUSY)
+        goto stopped;
+      else
+        goto select_error;
     }
-    line++;
+    gst_poll_set_controllable (conn->fdset, FALSE);
   }
 
-  /* read the rest of the body if needed */
-  if (need_body) {
-    gchar *session_id;
-    gchar *hdrval;
-
-    /* see if there is a Content-Length header */
-    if (gst_rtsp_message_get_header (message, GST_RTSP_HDR_CONTENT_LENGTH,
-            &hdrval, 0) == GST_RTSP_OK) {
-      /* there is, read the body */
-      content_length = atol (hdrval);
-      GST_RTSP_CHECK (read_body (conn, content_length, message, timeout),
-          read_error);
-    }
-
-    /* save session id in the connection for further use */
-    if (gst_rtsp_message_get_header (message, GST_RTSP_HDR_SESSION,
-            &session_id, 0) == GST_RTSP_OK) {
-      gint maxlen, i;
-
-      /* default session timeout */
-      conn->timeout = 60;
-
-      maxlen = sizeof (conn->session_id) - 1;
-      /* the sessionid can have attributes marked with ;
-       * Make sure we strip them */
-      for (i = 0; session_id[i] != '\0'; i++) {
-        if (session_id[i] == ';') {
-          maxlen = i;
-          /* parse timeout */
-          do {
-            i++;
-          } while (g_ascii_isspace (session_id[i]));
-          if (g_str_has_prefix (&session_id[i], "timeout=")) {
-            gint to;
-
-            /* if we parsed something valid, configure */
-            if ((to = atoi (&session_id[i + 9])) > 0)
-              conn->timeout = to;
-          }
-          break;
-        }
-      }
-
-      /* make sure to not overflow */
-      strncpy (conn->session_id, session_id, maxlen);
-      conn->session_id[maxlen] = '\0';
-    }
+  /* we have a message here */
+  build_reset (&builder);
+
+  return GST_RTSP_OK;
+
+  /* ERRORS */
+select_error:
+  {
+    res = GST_RTSP_ESYS;
+    goto cleanup;
+  }
+select_timeout:
+  {
+    res = GST_RTSP_ETIMEOUT;
+    goto cleanup;
   }
-  return res;
-
+stopped:
+  {
+    res = GST_RTSP_EINTR;
+    goto cleanup;
+  }
+eof:
+  {
+    res = GST_RTSP_EEOF;
+    goto cleanup;
+  }
 read_error:
+cleanup:
   {
+    build_reset (&builder);
+    gst_rtsp_message_unset (message);
     return res;
   }
 }
@@ -1086,37 +2001,36 @@
  * gst_rtsp_connection_close:
  * @conn: a #GstRTSPConnection
  *
- * Close the connected @conn.
+ * Close the connected @conn. After this call, the connection is in the same
+ * state as when it was first created.
  * 
  * Returns: #GST_RTSP_OK on success.
  */
 GstRTSPResult
 gst_rtsp_connection_close (GstRTSPConnection * conn)
 {
-  gint res;
-
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
 
   g_free (conn->ip);
   conn->ip = NULL;
 
-  if (conn->fd.fd != -1) {
-    gst_poll_remove_fd (conn->fdset, &conn->fd);
-    res = CLOSE_SOCKET (conn->fd.fd);
-    conn->fd.fd = -1;
-#ifdef G_OS_WIN32
-    WSACleanup ();
-#endif
-    if (res != 0)
-      goto sys_error;
-  }
+  REMOVE_POLLFD (conn->fdset, &conn->fd0);
+  REMOVE_POLLFD (conn->fdset, &conn->fd1);
+  conn->writefd = NULL;
+  conn->readfd = NULL;
+  conn->tunneled = FALSE;
+  conn->tstate = TUNNEL_STATE_NONE;
+  conn->ctxp = NULL;
+  g_free (conn->username);
+  conn->username = NULL;
+  g_free (conn->passwd);
+  conn->passwd = NULL;
+  gst_rtsp_connection_clear_auth_params (conn);
+  conn->timeout = 60;
+  conn->cseq = 0;
+  conn->session_id[0] = '\0';
 
   return GST_RTSP_OK;
-
-sys_error:
-  {
-    return GST_RTSP_ESYS;
-  }
 }
 
 /**
@@ -1136,13 +2050,13 @@
 
   res = gst_rtsp_connection_close (conn);
   gst_poll_free (conn->fdset);
+  g_timer_destroy (conn->timer);
+  gst_rtsp_url_free (conn->url);
+  g_free (conn->proxy_host);
+  g_free (conn);
 #ifdef G_OS_WIN32
   WSACleanup ();
 #endif
-  g_timer_destroy (conn->timer);
-  g_free (conn->username);
-  g_free (conn->passwd);
-  g_free (conn);
 
   return res;
 }
@@ -1177,14 +2091,17 @@
   g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (events != 0, GST_RTSP_EINVAL);
   g_return_val_if_fail (revents != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL);
 
   gst_poll_set_controllable (conn->fdset, TRUE);
 
   /* add fd to writer set when asked to */
-  gst_poll_fd_ctl_write (conn->fdset, &conn->fd, events & GST_RTSP_EV_WRITE);
+  gst_poll_fd_ctl_write (conn->fdset, conn->writefd,
+      events & GST_RTSP_EV_WRITE);
 
   /* add fd to reader set when asked to */
-  gst_poll_fd_ctl_read (conn->fdset, &conn->fd, events & GST_RTSP_EV_READ);
+  gst_poll_fd_ctl_read (conn->fdset, conn->readfd, events & GST_RTSP_EV_READ);
 
   /* configure timeout if any */
   to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE;
@@ -1193,10 +2110,10 @@
     retval = gst_poll_wait (conn->fdset, to);
   } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
 
-  if (retval == 0)
+  if (G_UNLIKELY (retval == 0))
     goto select_timeout;
 
-  if (retval == -1) {
+  if (G_UNLIKELY (retval == -1)) {
     if (errno == EBUSY)
       goto stopped;
     else
@@ -1205,11 +2122,11 @@
 
   *revents = 0;
   if (events & GST_RTSP_EV_READ) {
-    if (gst_poll_fd_can_read (conn->fdset, &conn->fd))
+    if (gst_poll_fd_can_read (conn->fdset, conn->readfd))
       *revents |= GST_RTSP_EV_READ;
   }
   if (events & GST_RTSP_EV_WRITE) {
-    if (gst_poll_fd_can_write (conn->fdset, &conn->fd))
+    if (gst_poll_fd_can_write (conn->fdset, conn->writefd))
       *revents |= GST_RTSP_EV_WRITE;
   }
   return GST_RTSP_OK;
@@ -1302,6 +2219,31 @@
 }
 
 /**
+ * gst_rtsp_connection_set_proxy:
+ * @conn: a #GstRTSPConnection
+ * @host: the proxy host
+ * @port: the proxy port
+ *
+ * Set the proxy host and port.
+ * 
+ * Returns: #GST_RTSP_OK.
+ *
+ * Since: 0.10.23
+ */
+GstRTSPResult
+gst_rtsp_connection_set_proxy (GstRTSPConnection * conn,
+    const gchar * host, guint port)
+{
+  g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
+
+  g_free (conn->proxy_host);
+  conn->proxy_host = g_strdup (host);
+  conn->proxy_port = port;
+
+  return GST_RTSP_OK;
+}
+
+/**
  * gst_rtsp_connection_set_auth:
  * @conn: a #GstRTSPConnection
  * @method: authentication method
@@ -1317,9 +2259,11 @@
 gst_rtsp_connection_set_auth (GstRTSPConnection * conn,
     GstRTSPAuthMethod method, const gchar * user, const gchar * pass)
 {
-  /* Digest isn't implemented yet */
-  if (method == GST_RTSP_AUTH_DIGEST)
-    return GST_RTSP_ENOTIMPL;
+  g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
+
+  if (method == GST_RTSP_AUTH_DIGEST && ((user == NULL || pass == NULL)
+          || g_strrstr (user, ":") != NULL))
+    return GST_RTSP_EINVAL;
 
   /* Make sure the username and passwd are being set for authentication */
   if (method == GST_RTSP_AUTH_NONE && (user == NULL || pass == NULL))
@@ -1338,3 +2282,786 @@
 
   return GST_RTSP_OK;
 }
+
+/**
+ * str_case_hash:
+ * @key: ASCII string to hash
+ *
+ * Hashes @key in a case-insensitive manner.
+ *
+ * Returns: the hash code.
+ **/
+static guint
+str_case_hash (gconstpointer key)
+{
+  const char *p = key;
+  guint h = g_ascii_toupper (*p);
+
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + g_ascii_toupper (*p);
+
+  return h;
+}
+
+/**
+ * str_case_equal:
+ * @v1: an ASCII string
+ * @v2: another ASCII string
+ *
+ * Compares @v1 and @v2 in a case-insensitive manner
+ *
+ * Returns: %TRUE if they are equal (modulo case)
+ **/
+static gboolean
+str_case_equal (gconstpointer v1, gconstpointer v2)
+{
+  const char *string1 = v1;
+  const char *string2 = v2;
+
+  return g_ascii_strcasecmp (string1, string2) == 0;
+}
+
+/**
+ * gst_rtsp_connection_set_auth_param:
+ * @conn: a #GstRTSPConnection
+ * @param: authentication directive
+ * @value: value
+ *
+ * Setup @conn with authentication directives. This is not necesary for
+ * methods #GST_RTSP_AUTH_NONE and #GST_RTSP_AUTH_BASIC. For
+ * #GST_RTSP_AUTH_DIGEST, directives should be taken from the digest challenge
+ * in the WWW-Authenticate response header and can include realm, domain,
+ * nonce, opaque, stale, algorithm, qop as per RFC2617.
+ * 
+ * Since: 0.10.20
+ */
+void
+gst_rtsp_connection_set_auth_param (GstRTSPConnection * conn,
+    const gchar * param, const gchar * value)
+{
+  g_return_if_fail (conn != NULL);
+  g_return_if_fail (param != NULL);
+
+  if (conn->auth_params == NULL) {
+    conn->auth_params =
+        g_hash_table_new_full (str_case_hash, str_case_equal, g_free, g_free);
+  }
+  g_hash_table_insert (conn->auth_params, g_strdup (param), g_strdup (value));
+}
+
+/**
+ * gst_rtsp_connection_clear_auth_params:
+ * @conn: a #GstRTSPConnection
+ *
+ * Clear the list of authentication directives stored in @conn.
+ *
+ * Since: 0.10.20
+ */
+void
+gst_rtsp_connection_clear_auth_params (GstRTSPConnection * conn)
+{
+  g_return_if_fail (conn != NULL);
+
+  if (conn->auth_params != NULL) {
+    g_hash_table_destroy (conn->auth_params);
+    conn->auth_params = NULL;
+  }
+}
+
+static GstRTSPResult
+set_qos_dscp (gint fd, guint qos_dscp)
+{
+  union gst_sockaddr sa;
+  socklen_t slen = sizeof (sa);
+  gint af;
+  gint tos;
+
+  if (fd == -1)
+    return GST_RTSP_OK;
+
+  if (getsockname (fd, &sa.sa, &slen) < 0)
+    goto no_getsockname;
+
+  af = sa.sa.sa_family;
+
+  /* if this is an IPv4-mapped address then do IPv4 QoS */
+  if (af == AF_INET6) {
+    if (IN6_IS_ADDR_V4MAPPED (&sa.sa_in6.sin6_addr))
+      af = AF_INET;
+  }
+
+  /* extract and shift 6 bits of the DSCP */
+  tos = (qos_dscp & 0x3f) << 2;
+
+  switch (af) {
+    case AF_INET:
+      if (SETSOCKOPT (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0)
+        goto no_setsockopt;
+      break;
+    case AF_INET6:
+#ifdef IPV6_TCLASS
+      if (SETSOCKOPT (fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof (tos)) < 0)
+        goto no_setsockopt;
+      break;
+#endif
+    default:
+      goto wrong_family;
+  }
+
+  return GST_RTSP_OK;
+
+  /* ERRORS */
+no_getsockname:
+no_setsockopt:
+  {
+    return GST_RTSP_ESYS;
+  }
+
+wrong_family:
+  {
+    return GST_RTSP_ERROR;
+  }
+}
+
+/**
+ * gst_rtsp_connection_set_qos_dscp:
+ * @conn: a #GstRTSPConnection
+ * @qos_dscp: DSCP value
+ *
+ * Configure @conn to use the specified DSCP value.
+ *
+ * Returns: #GST_RTSP_OK on success.
+ *
+ * Since: 0.10.20
+ */
+GstRTSPResult
+gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp)
+{
+  GstRTSPResult res;
+
+  g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL);
+
+  res = set_qos_dscp (conn->fd0.fd, qos_dscp);
+  if (res == GST_RTSP_OK)
+    res = set_qos_dscp (conn->fd1.fd, qos_dscp);
+
+  return res;
+}
+
+
+/**
+ * gst_rtsp_connection_get_url:
+ * @conn: a #GstRTSPConnection
+ *
+ * Retrieve the URL of the other end of @conn.
+ *
+ * Returns: The URL. This value remains valid until the
+ * connection is freed.
+ *
+ * Since: 0.10.23
+ */
+GstRTSPUrl *
+gst_rtsp_connection_get_url (const GstRTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, NULL);
+
+  return conn->url;
+}
+
+/**
+ * gst_rtsp_connection_get_ip:
+ * @conn: a #GstRTSPConnection
+ *
+ * Retrieve the IP address of the other end of @conn.
+ *
+ * Returns: The IP address as a string. this value remains valid until the
+ * connection is closed.
+ *
+ * Since: 0.10.20
+ */
+const gchar *
+gst_rtsp_connection_get_ip (const GstRTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, NULL);
+
+  return conn->ip;
+}
+
+/**
+ * gst_rtsp_connection_set_ip:
+ * @conn: a #GstRTSPConnection
+ * @ip: an ip address
+ *
+ * Set the IP address of the server.
+ *
+ * Since: 0.10.23
+ */
+void
+gst_rtsp_connection_set_ip (GstRTSPConnection * conn, const gchar * ip)
+{
+  g_return_if_fail (conn != NULL);
+
+  g_free (conn->ip);
+  conn->ip = g_strdup (ip);
+}
+
+/**
+ * gst_rtsp_connection_get_readfd:
+ * @conn: a #GstRTSPConnection
+ *
+ * Get the file descriptor for reading.
+ *
+ * Returns: the file descriptor used for reading or -1 on error. The file
+ * descriptor remains valid until the connection is closed.
+ *
+ * Since: 0.10.23
+ */
+gint
+gst_rtsp_connection_get_readfd (const GstRTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, -1);
+  g_return_val_if_fail (conn->readfd != NULL, -1);
+
+  return conn->readfd->fd;
+}
+
+/**
+ * gst_rtsp_connection_get_writefd:
+ * @conn: a #GstRTSPConnection
+ *
+ * Get the file descriptor for writing.
+ *
+ * Returns: the file descriptor used for writing or -1 on error. The file
+ * descriptor remains valid until the connection is closed.
+ *
+ * Since: 0.10.23
+ */
+gint
+gst_rtsp_connection_get_writefd (const GstRTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, -1);
+  g_return_val_if_fail (conn->writefd != NULL, -1);
+
+  return conn->writefd->fd;
+}
+
+
+/**
+ * gst_rtsp_connection_set_tunneled:
+ * @conn: a #GstRTSPConnection
+ * @tunneled: the new state
+ *
+ * Set the HTTP tunneling state of the connection. This must be configured before
+ * the @conn is connected.
+ *
+ * Since: 0.10.23
+ */
+void
+gst_rtsp_connection_set_tunneled (GstRTSPConnection * conn, gboolean tunneled)
+{
+  g_return_if_fail (conn != NULL);
+  g_return_if_fail (conn->readfd == NULL);
+  g_return_if_fail (conn->writefd == NULL);
+
+  conn->tunneled = tunneled;
+}
+
+/**
+ * gst_rtsp_connection_is_tunneled:
+ * @conn: a #GstRTSPConnection
+ *
+ * Get the tunneling state of the connection. 
+ *
+ * Returns: if @conn is using HTTP tunneling.
+ *
+ * Since: 0.10.23
+ */
+gboolean
+gst_rtsp_connection_is_tunneled (const GstRTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, FALSE);
+
+  return conn->tunneled;
+}
+
+/**
+ * gst_rtsp_connection_get_tunnelid:
+ * @conn: a #GstRTSPConnection
+ *
+ * Get the tunnel session id the connection. 
+ *
+ * Returns: returns a non-empty string if @conn is being tunneled over HTTP.
+ *
+ * Since: 0.10.23
+ */
+const gchar *
+gst_rtsp_connection_get_tunnelid (const GstRTSPConnection * conn)
+{
+  g_return_val_if_fail (conn != NULL, NULL);
+
+  if (!conn->tunneled)
+    return NULL;
+
+  return conn->tunnelid;
+}
+
+/**
+ * gst_rtsp_connection_do_tunnel:
+ * @conn: a #GstRTSPConnection
+ * @conn2: a #GstRTSPConnection
+ *
+ * If @conn received the first tunnel connection and @conn2 received
+ * the second tunnel connection, link the two connections together so that
+ * @conn manages the tunneled connection.
+ *
+ * After this call, @conn2 cannot be used anymore and must be freed with
+ * gst_rtsp_connection_free().
+ *
+ * Returns: return GST_RTSP_OK on success.
+ *
+ * Since: 0.10.23
+ */
+GstRTSPResult
+gst_rtsp_connection_do_tunnel (GstRTSPConnection * conn,
+    GstRTSPConnection * conn2)
+{
+  g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn2 != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn->tstate == TUNNEL_STATE_GET, GST_RTSP_EINVAL);
+  g_return_val_if_fail (conn2->tstate == TUNNEL_STATE_POST, GST_RTSP_EINVAL);
+  g_return_val_if_fail (!memcmp (conn2->tunnelid, conn->tunnelid, TUNNELID_LEN),
+      GST_RTSP_EINVAL);
+
+  /* both connections have fd0 as the read/write socket. start by taking the
+   * socket from conn2 and set it as the socket in conn */
+  conn->fd1 = conn2->fd0;
+
+  /* clean up some of the state of conn2 */
+  gst_poll_remove_fd (conn2->fdset, &conn2->fd0);
+  conn2->fd0.fd = -1;
+  conn2->readfd = conn2->writefd = NULL;
+
+  /* We make fd0 the write socket and fd1 the read socket. */
+  conn->writefd = &conn->fd0;
+  conn->readfd = &conn->fd1;
+
+  conn->tstate = TUNNEL_STATE_COMPLETE;
+
+  /* we need base64 decoding for the readfd */
+  conn->ctx.state = 0;
+  conn->ctx.save = 0;
+  conn->ctx.cout = 0;
+  conn->ctx.coutl = 0;
+  conn->ctxp = &conn->ctx;
+
+  return GST_RTSP_OK;
+}
+
+#define READ_COND   (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define WRITE_COND  (G_IO_OUT | G_IO_ERR)
+
+typedef struct
+{
+  guint8 *data;
+  guint size;
+  guint id;
+} GstRTSPRec;
+
+/* async functions */
+struct _GstRTSPWatch
+{
+  GSource source;
+
+  GstRTSPConnection *conn;
+
+  GstRTSPBuilder builder;
+  GstRTSPMessage message;
+
+  GPollFD readfd;
+  GPollFD writefd;
+  gboolean write_added;
+
+  /* queued message for transmission */
+  guint id;
+  GAsyncQueue *messages;
+  guint8 *write_data;
+  guint write_off;
+  guint write_size;
+  guint write_id;
+
+  GstRTSPWatchFuncs funcs;
+
+  gpointer user_data;
+  GDestroyNotify notify;
+};
+
+static gboolean
+gst_rtsp_source_prepare (GSource * source, gint * timeout)
+{
+  GstRTSPWatch *watch = (GstRTSPWatch *) source;
+
+  *timeout = (watch->conn->timeout * 1000);
+
+  return FALSE;
+}
+
+static gboolean
+gst_rtsp_source_check (GSource * source)
+{
+  GstRTSPWatch *watch = (GstRTSPWatch *) source;
+
+  if (watch->readfd.revents & READ_COND)
+    return TRUE;
+
+  if (watch->writefd.revents & WRITE_COND)
+    return TRUE;
+
+  return FALSE;
+}
+
+static gboolean
+gst_rtsp_source_dispatch (GSource * source, GSourceFunc callback G_GNUC_UNUSED,
+    gpointer user_data G_GNUC_UNUSED)
+{
+  GstRTSPWatch *watch = (GstRTSPWatch *) source;
+  GstRTSPResult res;
+
+  /* first read as much as we can */
+  if (watch->readfd.revents & READ_COND) {
+    do {
+      res = build_next (&watch->builder, &watch->message, watch->conn);
+      if (res == GST_RTSP_EINTR)
+        break;
+      if (G_UNLIKELY (res == GST_RTSP_EEOF))
+        goto eof;
+      if (res == GST_RTSP_ETGET) {
+        GString *str;
+        GstRTSPStatusCode code;
+        guint size;
+
+        if (watch->funcs.tunnel_start)
+          code = watch->funcs.tunnel_start (watch, watch->user_data);
+        else
+          code = GST_RTSP_STS_OK;
+
+        /* queue the response string */
+        str = gen_tunnel_reply (watch->conn, code);
+        size = str->len;
+        gst_rtsp_watch_queue_data (watch, (guint8 *) g_string_free (str, FALSE),
+            size);
+      } else if (res == GST_RTSP_ETPOST) {
+        /* in the callback the connection should be tunneled with the
+         * GET connection */
+        if (watch->funcs.tunnel_complete)
+          watch->funcs.tunnel_complete (watch, watch->user_data);
+      } else if (G_UNLIKELY (res != GST_RTSP_OK))
+        goto error;
+
+      if (G_LIKELY (res == GST_RTSP_OK)) {
+        if (watch->funcs.message_received)
+          watch->funcs.message_received (watch, &watch->message,
+              watch->user_data);
+
+        gst_rtsp_message_unset (&watch->message);
+      }
+      build_reset (&watch->builder);
+    } while (FALSE);
+  }
+
+  if (watch->writefd.revents & WRITE_COND) {
+    do {
+      if (watch->write_data == NULL) {
+        GstRTSPRec *rec;
+
+        /* get a new message from the queue */
+        rec = g_async_queue_try_pop (watch->messages);
+        if (rec == NULL)
+          goto done;
+
+        watch->write_off = 0;
+        watch->write_data = rec->data;
+        watch->write_size = rec->size;
+        watch->write_id = rec->id;
+
+        g_slice_free (GstRTSPRec, rec);
+      }
+
+      res = write_bytes (watch->writefd.fd, watch->write_data,
+          &watch->write_off, watch->write_size);
+      if (res == GST_RTSP_EINTR)
+        break;
+      if (G_UNLIKELY (res != GST_RTSP_OK))
+        goto error;
+
+      if (watch->funcs.message_sent)
+        watch->funcs.message_sent (watch, watch->write_id, watch->user_data);
+
+    done:
+      if (g_async_queue_length (watch->messages) == 0 && watch->write_added) {
+        g_source_remove_poll ((GSource *) watch, &watch->writefd);
+        watch->write_added = FALSE;
+        watch->writefd.revents = 0;
+      }
+      g_free (watch->write_data);
+      watch->write_data = NULL;
+    } while (FALSE);
+  }
+
+  return TRUE;
+
+  /* ERRORS */
+eof:
+  {
+    if (watch->funcs.closed)
+      watch->funcs.closed (watch, watch->user_data);
+    return FALSE;
+  }
+error:
+  {
+    if (watch->funcs.error)
+      watch->funcs.error (watch, res, watch->user_data);
+    return FALSE;
+  }
+}
+
+static void
+gst_rtsp_rec_free (gpointer data)
+{
+  GstRTSPRec *rec = data;
+
+  g_free (rec->data);
+  g_slice_free (GstRTSPRec, rec);
+}
+
+static void
+gst_rtsp_source_finalize (GSource * source)
+{
+  GstRTSPWatch *watch = (GstRTSPWatch *) source;
+
+  build_reset (&watch->builder);
+  gst_rtsp_message_unset (&watch->message);
+
+  g_async_queue_unref (watch->messages);
+  watch->messages = NULL;
+
+  g_free (watch->write_data);
+
+  if (watch->notify)
+    watch->notify (watch->user_data);
+}
+
+static GSourceFuncs gst_rtsp_source_funcs = {
+  gst_rtsp_source_prepare,
+  gst_rtsp_source_check,
+  gst_rtsp_source_dispatch,
+  gst_rtsp_source_finalize,
+  NULL,
+  NULL
+};
+
+/**
+ * gst_rtsp_watch_new:
+ * @conn: a #GstRTSPConnection
+ * @funcs: watch functions
+ * @user_data: user data to pass to @funcs
+ * @notify: notify when @user_data is not referenced anymore
+ *
+ * Create a watch object for @conn. The functions provided in @funcs will be
+ * called with @user_data when activity happened on the watch.
+ *
+ * The new watch is usually created so that it can be attached to a
+ * maincontext with gst_rtsp_watch_attach(). 
+ *
+ * @conn must exist for the entire lifetime of the watch.
+ *
+ * Returns: a #GstRTSPWatch that can be used for asynchronous RTSP
+ * communication. Free with gst_rtsp_watch_unref () after usage.
+ *
+ * Since: 0.10.23
+ */
+GstRTSPWatch *
+gst_rtsp_watch_new (GstRTSPConnection * conn,
+    GstRTSPWatchFuncs * funcs, gpointer user_data, GDestroyNotify notify)
+{
+  GstRTSPWatch *result;
+
+  g_return_val_if_fail (conn != NULL, NULL);
+  g_return_val_if_fail (funcs != NULL, NULL);
+  g_return_val_if_fail (conn->readfd != NULL, NULL);
+  g_return_val_if_fail (conn->writefd != NULL, NULL);
+
+  result = (GstRTSPWatch *) g_source_new (&gst_rtsp_source_funcs,
+      sizeof (GstRTSPWatch));
+
+  result->conn = conn;
+  result->builder.state = STATE_START;
+
+  result->messages = g_async_queue_new_full (gst_rtsp_rec_free);
+
+  result->readfd.fd = -1;
+  result->writefd.fd = -1;
+
+  gst_rtsp_watch_reset (result);
+
+  result->funcs = *funcs;
+  result->user_data = user_data;
+  result->notify = notify;
+
+  /* only add the read fd, the write fd is only added when we have data
+   * to send. */
+  g_source_add_poll ((GSource *) result, &result->readfd);
+
+  return result;
+}
+
+/**
+ * gst_rtsp_watch_reset:
+ * @watch: a #GstRTSPWatch
+ *
+ * Reset @watch, this is usually called after gst_rtsp_connection_do_tunnel()
+ * when the file descriptors of the connection might have changed.
+ *
+ * Since: 0.10.23
+ */
+void
+gst_rtsp_watch_reset (GstRTSPWatch * watch)
+{
+  if (watch->readfd.fd != -1)
+    g_source_remove_poll ((GSource *) watch, &watch->readfd);
+  if (watch->writefd.fd != -1)
+    g_source_remove_poll ((GSource *) watch, &watch->writefd);
+
+  watch->readfd.fd = watch->conn->readfd->fd;
+  watch->readfd.events = READ_COND;
+  watch->readfd.revents = 0;
+
+  watch->writefd.fd = watch->conn->writefd->fd;
+  watch->writefd.events = WRITE_COND;
+  watch->writefd.revents = 0;
+  watch->write_added = FALSE;
+
+  g_source_add_poll ((GSource *) watch, &watch->readfd);
+}
+
+/**
+ * gst_rtsp_watch_attach:
+ * @watch: a #GstRTSPWatch
+ * @context: a GMainContext (if NULL, the default context will be used)
+ *
+ * Adds a #GstRTSPWatch to a context so that it will be executed within that context.
+ *
+ * Returns: the ID (greater than 0) for the watch within the GMainContext. 
+ *
+ * Since: 0.10.23
+ */
+guint
+gst_rtsp_watch_attach (GstRTSPWatch * watch, GMainContext * context)
+{
+  g_return_val_if_fail (watch != NULL, 0);
+
+  return g_source_attach ((GSource *) watch, context);
+}
+
+/**
+ * gst_rtsp_watch_unref:
+ * @watch: a #GstRTSPWatch
+ *
+ * Decreases the reference count of @watch by one. If the resulting reference
+ * count is zero the watch and associated memory will be destroyed.
+ *
+ * Since: 0.10.23
+ */
+void
+gst_rtsp_watch_unref (GstRTSPWatch * watch)
+{
+  g_return_if_fail (watch != NULL);
+
+  g_source_unref ((GSource *) watch);
+}
+
+/**
+ * gst_rtsp_watch_queue_data:
+ * @watch: a #GstRTSPWatch
+ * @data: the data to queue
+ * @size: the size of @data
+ *
+ * Queue @data for transmission in @watch. It will be transmitted when the
+ * connection of the @watch becomes writable.
+ *
+ * This function will take ownership of @data and g_free() it after use.
+ *
+ * The return value of this function will be used as the id argument in the
+ * message_sent callback.
+ *
+ * Returns: an id.
+ *
+ * Since: 0.10.24
+ */
+guint
+gst_rtsp_watch_queue_data (GstRTSPWatch * watch, const guint8 * data,
+    guint size)
+{
+  GstRTSPRec *rec;
+
+  g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (size != 0, GST_RTSP_EINVAL);
+
+  /* make a record with the data and id */
+  rec = g_slice_new (GstRTSPRec);
+  rec->data = (guint8 *) data;
+  rec->size = size;
+  do {
+    /* make sure rec->id is never 0 */
+    rec->id = ++watch->id;
+  } while (G_UNLIKELY (rec->id == 0));
+
+  /* add the record to a queue. FIXME we would like to have an upper limit here */
+  g_async_queue_push (watch->messages, rec);
+
+  /* FIXME: does the following need to be made thread-safe? (this might be
+   * called from a streaming thread, like appsink's render function) */
+  /* make sure the main context will now also check for writability on the
+   * socket */
+  if (!watch->write_added) {
+    g_source_add_poll ((GSource *) watch, &watch->writefd);
+    watch->write_added = TRUE;
+  }
+
+  return rec->id;
+}
+
+/**
+ * gst_rtsp_watch_queue_message:
+ * @watch: a #GstRTSPWatch
+ * @message: a #GstRTSPMessage
+ *
+ * Queue a @message for transmission in @watch. The contents of this
+ * message will be serialized and transmitted when the connection of the
+ * @watch becomes writable.
+ *
+ * The return value of this function will be used as the id argument in the
+ * message_sent callback.
+ *
+ * Returns: an id.
+ *
+ * Since: 0.10.23
+ */
+guint
+gst_rtsp_watch_queue_message (GstRTSPWatch * watch, GstRTSPMessage * message)
+{
+  GString *str;
+  guint size;
+
+  g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
+
+  /* make a record with the message as a string and id */
+  str = message_to_string (watch->conn, message);
+  size = str->len;
+  return gst_rtsp_watch_queue_data (watch,
+      (guint8 *) g_string_free (str, FALSE), size);
+}
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.h	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,5 @@
 /* GStreamer
- * Copyright (C) <2005,2006> Wim Taymans <wim@fluendo.com>
+ * Copyright (C) <2005,2009> Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -45,48 +45,28 @@
 
 #include <glib.h>
 
+#include <gst/gstconfig.h>
 #include <gst/rtsp/gstrtspdefs.h>
 #include <gst/rtsp/gstrtspurl.h>
 #include <gst/rtsp/gstrtspmessage.h>
 
 G_BEGIN_DECLS
 
-typedef struct _GstRTSPConnection GstRTSPConnection;
-
 /**
  * GstRTSPConnection:
  *
  * Opaque RTSP connection object.
  */
-struct _GstRTSPConnection
-{
-  /*< private >*/
-  /* URL for the connection */
-  GstRTSPUrl *url;
-
-  /* connection state */
-  GstPollFD   fd;
-  GstPoll    *fdset;
-  gchar      *ip;
-
-  /* Session state */
-  gint          cseq;                   /* sequence number */
-  gchar         session_id[512];        /* session id */
-  gint          timeout;                /* session timeout in seconds */
-  GTimer       *timer;                  /* timeout timer */
-
-  /* Authentication */
-  GstRTSPAuthMethod  auth_method;
-  gchar             *username;
-  gchar             *passwd;
-};
+typedef struct _GstRTSPConnection GstRTSPConnection;
 
 /* opening/closing a connection */
-GstRTSPResult      gst_rtsp_connection_create        (GstRTSPUrl *url, GstRTSPConnection **conn);
+GstRTSPResult      gst_rtsp_connection_create        (const GstRTSPUrl *url, GstRTSPConnection **conn);
+GstRTSPResult      gst_rtsp_connection_accept        (gint sock, GstRTSPConnection **conn);
 GstRTSPResult      gst_rtsp_connection_connect       (GstRTSPConnection *conn, GTimeVal *timeout);
 GstRTSPResult      gst_rtsp_connection_close         (GstRTSPConnection *conn);
 GstRTSPResult      gst_rtsp_connection_free          (GstRTSPConnection *conn);
 
+
 /* sending/receiving raw bytes */
 GstRTSPResult      gst_rtsp_connection_read          (GstRTSPConnection * conn, guint8 * data,
                                                       guint size, GTimeVal * timeout);
@@ -110,10 +90,95 @@
 /* flushing state */
 GstRTSPResult      gst_rtsp_connection_flush         (GstRTSPConnection *conn, gboolean flush);
 
-/* Configure Authentication data */
+/* HTTP proxy support */
+GstRTSPResult      gst_rtsp_connection_set_proxy     (GstRTSPConnection *conn,
+                                                      const gchar *host, guint port);
+
+/* configure authentication data */
 GstRTSPResult      gst_rtsp_connection_set_auth      (GstRTSPConnection *conn, GstRTSPAuthMethod method,
                                                       const gchar *user, const gchar *pass);
 
+void               gst_rtsp_connection_set_auth_param    (GstRTSPConnection *conn,
+		                                          const gchar * param,
+							  const gchar *value);
+void               gst_rtsp_connection_clear_auth_params (GstRTSPConnection *conn);
+
+/* configure DSCP */
+GstRTSPResult      gst_rtsp_connection_set_qos_dscp  (GstRTSPConnection *conn,
+                                                      guint qos_dscp);
+
+/* accessors */
+GstRTSPUrl *       gst_rtsp_connection_get_url       (const GstRTSPConnection *conn);
+const gchar *      gst_rtsp_connection_get_ip        (const GstRTSPConnection *conn);
+void               gst_rtsp_connection_set_ip        (GstRTSPConnection *conn, const gchar *ip);
+
+gint               gst_rtsp_connection_get_readfd    (const GstRTSPConnection *conn);
+gint               gst_rtsp_connection_get_writefd   (const GstRTSPConnection *conn);
+
+/* tunneling */
+void               gst_rtsp_connection_set_tunneled  (GstRTSPConnection *conn, gboolean tunneled);
+gboolean           gst_rtsp_connection_is_tunneled   (const GstRTSPConnection *conn);
+
+const gchar *      gst_rtsp_connection_get_tunnelid  (const GstRTSPConnection *conn);
+GstRTSPResult      gst_rtsp_connection_do_tunnel     (GstRTSPConnection *conn, GstRTSPConnection *conn2);
+
+/* async IO */
+
+/**
+ * GstRTSPWatch:
+ *
+ * Opaque RTSP watch object that can be used for asynchronous RTSP
+ * operations.
+ */
+typedef struct _GstRTSPWatch GstRTSPWatch;
+
+/**
+ * GstRTSPWatchFuncs:
+ * @message_received: callback when a message was received
+ * @message_sent: callback when a message was sent
+ * @closed: callback when the connection is closed
+ * @error: callback when an error occured
+ * @tunnel_start: a client started a tunneled connection. The tunnelid of the
+ *   connection must be saved.
+ * @tunnel_complete: a client finished a tunneled connection. In this callback
+ *   you usually pair the tunnelid of this connection with the saved one using
+ *   gst_rtsp_connection_do_tunnel().
+ *
+ * Callback functions from a #GstRTSPWatch.
+ *
+ * Since: 0.10.23
+ */
+typedef struct {
+  GstRTSPResult     (*message_received) (GstRTSPWatch *watch, GstRTSPMessage *message,
+                                         gpointer user_data);
+  GstRTSPResult     (*message_sent)     (GstRTSPWatch *watch, guint id,
+                                         gpointer user_data);
+  GstRTSPResult     (*closed)           (GstRTSPWatch *watch, gpointer user_data);
+  GstRTSPResult     (*error)            (GstRTSPWatch *watch, GstRTSPResult result,
+                                         gpointer user_data);
+  GstRTSPStatusCode (*tunnel_start)     (GstRTSPWatch *watch, gpointer user_data);
+  GstRTSPResult     (*tunnel_complete)  (GstRTSPWatch *watch, gpointer user_data);
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+} GstRTSPWatchFuncs;
+
+GstRTSPWatch *     gst_rtsp_watch_new                (GstRTSPConnection *conn,
+                                                      GstRTSPWatchFuncs *funcs,
+						      gpointer user_data,
+						      GDestroyNotify notify);
+void               gst_rtsp_watch_reset              (GstRTSPWatch *watch);
+void               gst_rtsp_watch_unref              (GstRTSPWatch *watch);
+
+guint              gst_rtsp_watch_attach             (GstRTSPWatch *watch,
+                                                      GMainContext *context);
+
+guint              gst_rtsp_watch_queue_data         (GstRTSPWatch * watch,
+                                                      const guint8 * data,
+                                                      guint size);
+guint              gst_rtsp_watch_queue_message      (GstRTSPWatch *watch,
+                                                      GstRTSPMessage *message);
+
 G_END_DECLS
 
 #endif /* __GST_RTSP_CONNECTION_H__ */
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.c	Fri Apr 16 15:15:52 2010 +0300
@@ -60,7 +60,9 @@
 
 #include "gstrtspdefs.h"
 
-#ifndef G_OS_WIN32
+#ifdef G_OS_WIN32
+#include <winsock2.h>
+#else
 #include <netdb.h>
 #endif
 
@@ -81,6 +83,8 @@
   "Network error: %s",
   "Host is not a valid IP address",
   "Timeout while waiting for server response",
+  "Tunnel GET request received",
+  "Tunnel POST request received",
   "Unknown error (%d)",
   NULL
 };
@@ -157,6 +161,30 @@
   "PlayerStarttime",            /* PlayerStarttime */
 
   "Location",                   /* Location */
+  "ETag",                       /* ETag */
+  "If-Match",                   /* If-Match */
+
+  /* WM extensions [MS-RTSP] */
+  "Accept-Charset",             /* Accept-Charset */
+  "Supported",                  /* Supported */
+  "Vary",                       /* Vary */
+  "X-Accelerate-Streaming",     /* X-Accelerate-Streaming */
+  "X-Accept-Authentication",    /* X-Accept-Authentication */
+  "X-Accept-Proxy-Authentication",      /* X-Accept-Proxy-Authentication */
+  "X-Broadcast-Id",             /* X-Broadcast-Id */
+  "X-Burst-Streaming",          /* X-Burst-Streaming */
+  "X-Notice",                   /* X-Notice */
+  "X-Player-Lag-Time",          /* X-Player-Lag-Time */
+  "X-Playlist",                 /* X-Playlist */
+  "X-Playlist-Change-Notice",   /* X-Playlist-Change-Notice */
+  "X-Playlist-Gen-Id",          /* X-Playlist-Gen-Id */
+  "X-Playlist-Seek-Id",         /* X-Playlist-Seek-Id */
+  "X-Proxy-Client-Agent",       /* X-Proxy-Client-Agent */
+  "X-Proxy-Client-Verb",        /* X-Proxy-Client-Verb */
+  "X-Receding-PlaylistChange",  /* X-Receding-PlaylistChange */
+  "X-RTP-Info",                 /* X-RTP-Info */
+  "X-StartupProfile",           /* X-StartupProfile */
+  "Timestamp",                  /* Timestamp */
 
   NULL
 };
@@ -243,16 +271,21 @@
   idx = CLAMP (idx, 0, -GST_RTSP_ELAST);
 
   switch (idx) {
+#ifdef G_OS_WIN32
+    case -GST_RTSP_ESYS:
+    case -GST_RTSP_ENET:
+    {
+      gchar *msg = g_win32_error_message (WSAGetLastError ());
+      res = g_strdup_printf (rtsp_results[idx], msg);
+      g_free (msg);
+      break;
+    }
+#else
     case -GST_RTSP_ESYS:
       res = g_strdup_printf (rtsp_results[idx], g_strerror (errno));
       break;
     case -GST_RTSP_ENET:
-#ifndef G_OS_WIN32
       res = g_strdup_printf (rtsp_results[idx], hstrerror (h_errno));
-#else
-      res =
-          g_strdup
-          ("not supported on win32, implement me in a different way ??");
 #endif
       break;
     case -GST_RTSP_ELAST:
@@ -388,3 +421,50 @@
   }
   return GST_RTSP_INVALID;
 }
+
+/**
+ * gst_rtsp_options_as_text:
+ * @options: one or more #GstRTSPMethod
+ *
+ * Convert @options to a string.
+ *
+ * Returns: a new string of @options. g_free() after usage.
+ *
+ * Since: 0.10.23
+ */
+gchar *
+gst_rtsp_options_as_text (GstRTSPMethod options)
+{
+  GString *str;
+
+  str = g_string_new ("");
+
+  if (options & GST_RTSP_OPTIONS)
+    g_string_append (str, "OPTIONS, ");
+  if (options & GST_RTSP_DESCRIBE)
+    g_string_append (str, "DESCRIBE, ");
+  if (options & GST_RTSP_ANNOUNCE)
+    g_string_append (str, "ANNOUNCE, ");
+  if (options & GST_RTSP_GET_PARAMETER)
+    g_string_append (str, "GET_PARAMETER, ");
+  if (options & GST_RTSP_PAUSE)
+    g_string_append (str, "PAUSE, ");
+  if (options & GST_RTSP_PLAY)
+    g_string_append (str, "PLAY, ");
+  if (options & GST_RTSP_RECORD)
+    g_string_append (str, "RECORD, ");
+  if (options & GST_RTSP_REDIRECT)
+    g_string_append (str, "REDIRECT, ");
+  if (options & GST_RTSP_SETUP)
+    g_string_append (str, "SETUP, ");
+  if (options & GST_RTSP_SET_PARAMETER)
+    g_string_append (str, "SET_PARAMETER, ");
+  if (options & GST_RTSP_TEARDOWN)
+    g_string_append (str, "TEARDOWN, ");
+
+  /* remove trailing ", " if there is one */
+  if (str->len > 2)
+    str = g_string_truncate (str, str->len - 2);
+
+  return g_string_free (str, FALSE);
+}
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.h	Fri Apr 16 15:15:52 2010 +0300
@@ -78,6 +78,8 @@
  * @GST_RTSP_ENET: a network problem occured, h_errno contains more details
  * @GST_RTSP_ENOTIP: the host is not an IP host
  * @GST_RTSP_ETIMEOUT: a timeout occured
+ * @GST_RTSP_ETGET: the tunnel GET request has been performed
+ * @GST_RTSP_ETPOST: the tunnel POST request has been performed
  * @GST_RTSP_ELAST: last error
  *
  * Result codes from the RTSP functions.
@@ -99,8 +101,10 @@
   GST_RTSP_ENET        = -12,
   GST_RTSP_ENOTIP      = -13,
   GST_RTSP_ETIMEOUT    = -14,
+  GST_RTSP_ETGET       = -15,
+  GST_RTSP_ETPOST      = -16,
 
-  GST_RTSP_ELAST       = -15
+  GST_RTSP_ELAST       = -17
 } GstRTSPResult;
 
 /**
@@ -279,7 +283,35 @@
   GST_RTSP_HDR_PLAYER_START_TIME,   /* PlayerStarttime */
 
   /* Since 0.10.16 */
-  GST_RTSP_HDR_LOCATION             /* Location */
+  GST_RTSP_HDR_LOCATION,            /* Location */
+
+  /* Since 0.10.23 */
+  GST_RTSP_HDR_ETAG,                /* ETag */
+  GST_RTSP_HDR_IF_MATCH,            /* If-Match */
+
+  /* WM extensions [MS-RTSP] Since 0.10.23 */
+  GST_RTSP_HDR_ACCEPT_CHARSET,      /* Accept-Charset */
+  GST_RTSP_HDR_SUPPORTED,           /* Supported */
+  GST_RTSP_HDR_VARY,                /* Vary */
+  GST_RTSP_HDR_X_ACCELERATE_STREAMING,    /* X-Accelerate-Streaming */
+  GST_RTSP_HDR_X_ACCEPT_AUTHENT,    /* X-Accept-Authentication */
+  GST_RTSP_HDR_X_ACCEPT_PROXY_AUTHENT,    /* X-Accept-Proxy-Authentication */
+  GST_RTSP_HDR_X_BROADCAST_ID,      /* X-Broadcast-Id */
+  GST_RTSP_HDR_X_BURST_STREAMING,   /* X-Burst-Streaming */
+  GST_RTSP_HDR_X_NOTICE,            /* X-Notice */
+  GST_RTSP_HDR_X_PLAYER_LAG_TIME,   /* X-Player-Lag-Time */
+  GST_RTSP_HDR_X_PLAYLIST,          /* X-Playlist */
+  GST_RTSP_HDR_X_PLAYLIST_CHANGE_NOTICE,  /* X-Playlist-Change-Notice */
+  GST_RTSP_HDR_X_PLAYLIST_GEN_ID,   /* X-Playlist-Gen-Id */
+  GST_RTSP_HDR_X_PLAYLIST_SEEK_ID,  /* X-Playlist-Seek-Id */
+  GST_RTSP_HDR_X_PROXY_CLIENT_AGENT,      /* X-Proxy-Client-Agent */
+  GST_RTSP_HDR_X_PROXY_CLIENT_VERB, /* X-Proxy-Client-Verb */
+  GST_RTSP_HDR_X_RECEDING_PLAYLISTCHANGE, /* X-Receding-PlaylistChange */
+  GST_RTSP_HDR_X_RTP_INFO,          /* X-RTP-Info */
+  GST_RTSP_HDR_X_STARTUPPROFILE,    /* X-StartupProfile */
+
+  /* Since 0.10.24 */
+  GST_RTSP_HDR_TIMESTAMP            /* Timestamp */
 
 } GstRTSPHeaderField;
 
@@ -338,6 +370,8 @@
 const gchar*       gst_rtsp_header_as_text     (GstRTSPHeaderField field);
 const gchar*       gst_rtsp_status_as_text     (GstRTSPStatusCode code);
 
+gchar*             gst_rtsp_options_as_text    (GstRTSPMethod options);
+
 GstRTSPHeaderField gst_rtsp_find_header_field  (const gchar *header);
 GstRTSPMethod      gst_rtsp_find_method        (const gchar *method);
 
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.c	Fri Apr 16 15:15:52 2010 +0300
@@ -196,6 +196,20 @@
 }
 
 GstRTSPResult
+gst_rtsp_extension_receive_request (GstRTSPExtension * ext,
+    GstRTSPMessage * msg)
+{
+  GstRTSPExtensionInterface *iface;
+  GstRTSPResult res = GST_RTSP_ENOTIMPL;
+
+  iface = GST_RTSP_EXTENSION_GET_IFACE (ext);
+  if (iface->receive_request)
+    res = iface->receive_request (ext, msg);
+
+  return res;
+}
+
+GstRTSPResult
 gst_rtsp_extension_send (GstRTSPExtension * ext, GstRTSPMessage * req,
     GstRTSPMessage * resp)
 {
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.h	Fri Apr 16 15:15:52 2010 +0300
@@ -64,8 +64,11 @@
   /* signals */
   GstRTSPResult (*send)             (GstRTSPExtension *ext, GstRTSPMessage *req, GstRTSPMessage *resp);
 
+  /* ABI: more vfunctions added later */
+  GstRTSPResult (*receive_request)  (GstRTSPExtension *ext, GstRTSPMessage *req);
+
   /*< private >*/
-  gpointer                 _gst_reserved[GST_PADDING];
+  gpointer                 _gst_reserved[GST_PADDING - 1];
 };
 
 GType           gst_rtsp_extension_get_type          (void);
@@ -83,6 +86,7 @@
 GstRTSPResult   gst_rtsp_extension_get_transports    (GstRTSPExtension *ext, GstRTSPLowerTrans protocols,
                                                       gchar **transport);
 GstRTSPResult   gst_rtsp_extension_stream_select     (GstRTSPExtension *ext, GstRTSPUrl *url);
+GstRTSPResult   gst_rtsp_extension_receive_request   (GstRTSPExtension *ext, GstRTSPMessage *req);
 
 /* signal emision */
 GstRTSPResult   gst_rtsp_extension_send              (GstRTSPExtension *ext, GstRTSPMessage *req,
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.c	Fri Apr 16 15:15:52 2010 +0300
@@ -57,6 +57,7 @@
 
 #include <string.h>
 
+#include <gst/gstutils.h>
 #include "gstrtspmessage.h"
 
 typedef struct _RTSPKeyValue
@@ -81,9 +82,9 @@
  * gst_rtsp_message_new:
  * @msg: a location for the new #GstRTSPMessage
  *
- * Create a new initialized #GstRTSPMessage.
+ * Create a new initialized #GstRTSPMessage. Free with gst_rtsp_message_free().
  *
- * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
+ * Returns: a #GstRTSPResult.
  */
 GstRTSPResult
 gst_rtsp_message_new (GstRTSPMessage ** msg)
@@ -144,9 +145,9 @@
  * @uri: the uri of the request
  *
  * Create a new #GstRTSPMessage with @method and @uri and store the result
- * request message in @msg. 
+ * request message in @msg. Free with gst_rtsp_message_free().
  *
- * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
+ * Returns: a #GstRTSPResult.
  */
 GstRTSPResult
 gst_rtsp_message_new_request (GstRTSPMessage ** msg, GstRTSPMethod method,
@@ -213,7 +214,7 @@
     GstRTSPMethod * method, const gchar ** uri, GstRTSPVersion * version)
 {
   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
-  g_return_val_if_fail (msg->type != GST_RTSP_MESSAGE_REQUEST, GST_RTSP_EINVAL);
+  g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_REQUEST, GST_RTSP_EINVAL);
 
   if (method)
     *method = msg->type_data.request.method;
@@ -233,14 +234,14 @@
  * @request: the request that triggered the response or #NULL
  *
  * Create a new response #GstRTSPMessage with @code and @reason and store the
- * result message in @msg. 
+ * result message in @msg. Free with gst_rtsp_message_free().
  *
  * When @reason is #NULL, the default reason for @code will be used.
  *
  * When @request is not #NULL, the relevant headers will be copied to the new
  * response message.
  *
- * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
+ * Returns: a #GstRTSPResult.
  */
 GstRTSPResult
 gst_rtsp_message_new_response (GstRTSPMessage ** msg, GstRTSPStatusCode code,
@@ -309,8 +310,7 @@
         *pos = '\0';
       }
       g_strchomp (header);
-      gst_rtsp_message_add_header (msg, GST_RTSP_HDR_SESSION, header);
-      g_free (header);
+      gst_rtsp_message_take_header (msg, GST_RTSP_HDR_SESSION, header);
     }
 
     /* FIXME copy more headers? */
@@ -340,7 +340,7 @@
     GstRTSPStatusCode * code, const gchar ** reason, GstRTSPVersion * version)
 {
   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
-  g_return_val_if_fail (msg->type != GST_RTSP_MESSAGE_RESPONSE,
+  g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_RESPONSE,
       GST_RTSP_EINVAL);
 
   if (code)
@@ -359,9 +359,9 @@
  * @channel: the channel
  *
  * Create a new data #GstRTSPMessage with @channel and store the
- * result message in @msg. 
+ * result message in @msg. Free with gst_rtsp_message_free().
  *
- * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
+ * Returns: a #GstRTSPResult.
  */
 GstRTSPResult
 gst_rtsp_message_new_data (GstRTSPMessage ** msg, guint8 channel)
@@ -412,7 +412,7 @@
 gst_rtsp_message_parse_data (GstRTSPMessage * msg, guint8 * channel)
 {
   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
-  g_return_val_if_fail (msg->type != GST_RTSP_MESSAGE_DATA, GST_RTSP_EINVAL);
+  g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_DATA, GST_RTSP_EINVAL);
 
   if (channel)
     *channel = msg->type_data.data.channel;
@@ -424,7 +424,7 @@
  * gst_rtsp_message_unset:
  * @msg: a #GstRTSPMessage
  *
- * Unset the concents of @msg so that it becomes an uninitialized
+ * Unset the contents of @msg so that it becomes an uninitialized
  * #GstRTSPMessage again. This function is mostly used in combination with 
  * gst_rtsp_message_init_request(), gst_rtsp_message_init_response() and
  * gst_rtsp_message_init_data() on stack allocated #GstRTSPMessage structures.
@@ -463,7 +463,7 @@
   }
   g_free (msg->body);
 
-  memset (msg, 0, sizeof *msg);
+  memset (msg, 0, sizeof (GstRTSPMessage));
 
   return GST_RTSP_OK;
 }
@@ -491,12 +491,43 @@
 }
 
 /**
+ * gst_rtsp_message_take_header:
+ * @msg: a #GstRTSPMessage
+ * @field: a #GstRTSPHeaderField
+ * @value: the value of the header
+ *
+ * Add a header with key @field and @value to @msg. This function takes
+ * ownership of @value.
+ *
+ * Returns: a #GstRTSPResult.
+ *
+ * Since: 0.10.23
+ */
+GstRTSPResult
+gst_rtsp_message_take_header (GstRTSPMessage * msg, GstRTSPHeaderField field,
+    gchar * value)
+{
+  RTSPKeyValue key_value;
+
+  g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
+  g_return_val_if_fail (value != NULL, GST_RTSP_EINVAL);
+
+  key_value.field = field;
+  key_value.value = value;
+
+  g_array_append_val (msg->hdr_fields, key_value);
+
+  return GST_RTSP_OK;
+}
+
+/**
  * gst_rtsp_message_add_header:
  * @msg: a #GstRTSPMessage
  * @field: a #GstRTSPHeaderField
  * @value: the value of the header
  *
- * Add a header with key @field and @value to @msg.
+ * Add a header with key @field and @value to @msg. This function takes a copy
+ * of @value.
  *
  * Returns: a #GstRTSPResult.
  */
@@ -504,17 +535,7 @@
 gst_rtsp_message_add_header (GstRTSPMessage * msg, GstRTSPHeaderField field,
     const gchar * value)
 {
-  RTSPKeyValue key_value;
-
-  g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
-  g_return_val_if_fail (value != NULL, GST_RTSP_EINVAL);
-
-  key_value.field = field;
-  key_value.value = g_strdup (value);
-
-  g_array_append_val (msg->hdr_fields, key_value);
-
-  return GST_RTSP_OK;
+  return gst_rtsp_message_take_header (msg, field, g_strdup (value));
 }
 
 /**
@@ -539,9 +560,10 @@
   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
 
   while (i < msg->hdr_fields->len) {
-    RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
+    RTSPKeyValue *key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i);
 
-    if (key_value.field == field && (indx == -1 || cnt++ == indx)) {
+    if (key_value->field == field && (indx == -1 || cnt++ == indx)) {
+      g_free (key_value->value);
       g_array_remove_index (msg->hdr_fields, i);
       res = GST_RTSP_OK;
       if (indx != -1)
@@ -560,7 +582,8 @@
  * @value: pointer to hold the result
  * @indx: the index of the header
  *
- * Get the @indx header value with key @field from @msg.
+ * Get the @indx header value with key @field from @msg. The result in @value
+ * stays valid as long as it remains present in @msg.
  *
  * Returns: #GST_RTSP_OK when @field was found, #GST_RTSP_ENOTIMPL if the key
  * was not found.
@@ -574,12 +597,16 @@
 
   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
 
-  for (i = 0; i < msg->hdr_fields->len; i++) {
-    RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
+  /* no header initialized, there are no headers */
+  if (msg->hdr_fields == NULL)
+    return GST_RTSP_ENOTIMPL;
 
-    if (key_value.field == field && cnt++ == indx) {
+  for (i = 0; i < msg->hdr_fields->len; i++) {
+    RTSPKeyValue *key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i);
+
+    if (key_value->field == field && cnt++ == indx) {
       if (value)
-        *value = key_value.value;
+        *value = key_value->value;
       return GST_RTSP_OK;
     }
   }
@@ -606,10 +633,13 @@
   g_return_val_if_fail (str != NULL, GST_RTSP_EINVAL);
 
   for (i = 0; i < msg->hdr_fields->len; i++) {
-    RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
-    const gchar *keystr = gst_rtsp_header_as_text (key_value.field);
+    RTSPKeyValue *key_value;
+    const gchar *keystr;
 
-    g_string_append_printf (str, "%s: %s\r\n", keystr, key_value.value);
+    key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i);
+    keystr = gst_rtsp_header_as_text (key_value->field);
+
+    g_string_append_printf (str, "%s: %s\r\n", keystr, key_value->value);
   }
   return GST_RTSP_OK;
 }
@@ -712,38 +742,7 @@
 }
 
 static void
-dump_mem (guint8 * mem, guint size)
-{
-  guint i, j;
-  GString *string = g_string_sized_new (50);
-  GString *chars = g_string_sized_new (18);
-
-  i = j = 0;
-  while (i < size) {
-    if (g_ascii_isprint (mem[i]))
-      g_string_append_printf (chars, "%c", mem[i]);
-    else
-      g_string_append_printf (chars, ".");
-
-    g_string_append_printf (string, "%02x ", mem[i]);
-
-    j++;
-    i++;
-
-    if (j == 16 || i == size) {
-      g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j, mem + i - j,
-          string->str, chars->str);
-      g_string_set_size (string, 0);
-      g_string_set_size (chars, 0);
-      j = 0;
-    }
-  }
-  g_string_free (string, TRUE);
-  g_string_free (chars, TRUE);
-}
-
-static void
-dump_key_value (gpointer data, gpointer user_data)
+dump_key_value (gpointer data, gpointer user_data G_GNUC_UNUSED)
 {
   RTSPKeyValue *key_value = (RTSPKeyValue *) data;
 
@@ -780,7 +779,7 @@
       key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
       g_print (" body:\n");
       gst_rtsp_message_get_body (msg, &data, &size);
-      dump_mem (data, size);
+      gst_util_dump_mem (data, size);
       break;
     case GST_RTSP_MESSAGE_RESPONSE:
       g_print ("RTSP response message %p\n", msg);
@@ -793,14 +792,14 @@
       key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
       gst_rtsp_message_get_body (msg, &data, &size);
       g_print (" body: length %d\n", size);
-      dump_mem (data, size);
+      gst_util_dump_mem (data, size);
       break;
     case GST_RTSP_MESSAGE_DATA:
       g_print ("RTSP data message %p\n", msg);
       g_print (" channel: '%d'\n", msg->type_data.data.channel);
       g_print (" size:    '%d'\n", msg->body_size);
       gst_rtsp_message_get_body (msg, &data, &size);
-      dump_mem (data, size);
+      gst_util_dump_mem (data, size);
       break;
     default:
       g_print ("unsupported message type %d\n", msg->type);
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.h	Fri Apr 16 15:15:52 2010 +0300
@@ -63,7 +63,7 @@
   GST_RTSP_MESSAGE_INVALID,
   GST_RTSP_MESSAGE_REQUEST,
   GST_RTSP_MESSAGE_RESPONSE,
-  GST_RTSP_MESSAGE_DATA,
+  GST_RTSP_MESSAGE_DATA
 } GstRTSPMsgType;
 
 typedef struct _GstRTSPMessage GstRTSPMessage;
@@ -147,6 +147,9 @@
 GstRTSPResult      gst_rtsp_message_add_header      (GstRTSPMessage *msg,
                                                      GstRTSPHeaderField field,
                                                      const gchar *value);
+GstRTSPResult      gst_rtsp_message_take_header     (GstRTSPMessage *msg,
+                                                     GstRTSPHeaderField field,
+                                                     gchar *value);
 GstRTSPResult      gst_rtsp_message_remove_header   (GstRTSPMessage *msg,
                                                      GstRTSPHeaderField field,
                                                      gint indx);
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.c	Fri Apr 16 15:15:52 2010 +0300
@@ -69,7 +69,7 @@
 static GstRTSPResult
 parse_npt_time (const gchar * str, GstRTSPTime * time)
 {
-  if (strcmp (str, "now") == 0) {
+  if (strncmp (str, "now", 3) == 0) {
     time->type = GST_RTSP_TIME_NOW;
   } else if (str[0] == '\0') {
     time->type = GST_RTSP_TIME_END;
@@ -167,9 +167,10 @@
   } else
     goto invalid;
 
-  if (ret == GST_RTSP_OK)
-    *range = res;
+  if (ret != GST_RTSP_OK)
+    goto invalid;
 
+  *range = res;
   return ret;
 
   /* ERRORS */
@@ -180,6 +181,88 @@
   }
 }
 
+static gboolean
+npt_time_string (const GstRTSPTime * time, GString * string)
+{
+  gboolean res = TRUE;;
+
+  switch (time->type) {
+    case GST_RTSP_TIME_SECONDS:
+      g_string_append_printf (string, "%f", time->seconds);
+      break;
+    case GST_RTSP_TIME_NOW:
+      g_string_append (string, "now");
+      break;
+    case GST_RTSP_TIME_END:
+      break;
+    default:
+      res = FALSE;
+      break;
+  }
+  return res;
+}
+
+static gboolean
+npt_range_string (const GstRTSPTimeRange * range, GString * string)
+{
+  gboolean res;
+
+  if (!(res = npt_time_string (&range->min, string)))
+    goto done;
+
+  g_string_append (string, "-");
+
+  if (!(res = npt_time_string (&range->max, string)))
+    goto done;
+
+done:
+  return res;
+}
+
+/**
+ * gst_rtsp_range_to_string:
+ * @range: a #GstRTSPTimeRange
+ *
+ * Convert @range into a string representation.
+ *
+ * Returns: The string representation of @range. g_free() after usage.
+ *
+ * Since: 0.10.23
+ */
+gchar *
+gst_rtsp_range_to_string (const GstRTSPTimeRange * range)
+{
+  gchar *result = NULL;
+  GString *string;
+
+  g_return_val_if_fail (range != NULL, NULL);
+
+  string = g_string_new ("");
+
+  switch (range->unit) {
+    case GST_RTSP_RANGE_NPT:
+      g_string_append (string, "npt=");
+      if (!npt_range_string (range, string)) {
+        g_string_free (string, TRUE);
+        string = NULL;
+      }
+      break;
+    case GST_RTSP_RANGE_SMPTE:
+    case GST_RTSP_RANGE_SMPTE_30_DROP:
+    case GST_RTSP_RANGE_SMPTE_25:
+    case GST_RTSP_RANGE_CLOCK:
+    default:
+      g_warning ("time range unit not yet implemented");
+      g_string_free (string, TRUE);
+      string = NULL;
+      break;
+  }
+  if (string)
+    result = g_string_free (string, FALSE);
+
+  return result;
+}
+
 /**
  * gst_rtsp_range_free:
  * @range: a #GstRTSPTimeRange
@@ -189,8 +272,5 @@
 void
 gst_rtsp_range_free (GstRTSPTimeRange * range)
 {
-  if (range == NULL)
-    return;
-
   g_free (range);
 }
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.h	Fri Apr 16 15:15:52 2010 +0300
@@ -113,6 +113,7 @@
 };
 
 GstRTSPResult   gst_rtsp_range_parse        (const gchar *rangestr, GstRTSPTimeRange **range);
+gchar *         gst_rtsp_range_to_string    (const GstRTSPTimeRange *range);
 void            gst_rtsp_range_free         (GstRTSPTimeRange *range);
 
 G_END_DECLS
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.c	Fri Apr 16 15:15:52 2010 +0300
@@ -544,6 +544,7 @@
 
     if ((tmp = rtsp_transport_ltrans_as_text (transport)) == NULL)
       goto invalid_transport;
+
     g_ptr_array_add (strs, g_ascii_strup (tmp, -1));
   }
 
@@ -601,32 +602,36 @@
   }
 
   /* add the port parameter */
-  if (transport->trans == GST_RTSP_TRANS_RTP && transport->port.min >= 0) {
-    if (transport->port.min < 65536 && transport->port.max < 65536) {
-      g_ptr_array_add (strs, g_strdup (";port="));
-      g_ptr_array_add (strs, range_as_text (&transport->port));
-    } else
-      goto invalid_transport;
-  }
+  if (transport->lower_transport != GST_RTSP_LOWER_TRANS_TCP) {
+    if (transport->trans == GST_RTSP_TRANS_RTP && transport->port.min >= 0) {
+      if (transport->port.min < 65536 && transport->port.max < 65536) {
+        g_ptr_array_add (strs, g_strdup (";port="));
+        g_ptr_array_add (strs, range_as_text (&transport->port));
+      } else
+        goto invalid_transport;
+    }
 
-  /* add the client_port parameter */
-  if (transport->trans == GST_RTSP_TRANS_RTP && transport->client_port.min >= 0) {
-    if (transport->client_port.min < 65536 &&
-        transport->client_port.max < 65536) {
-      g_ptr_array_add (strs, g_strdup (";client_port="));
-      g_ptr_array_add (strs, range_as_text (&transport->client_port));
-    } else
-      goto invalid_transport;
-  }
+    /* add the client_port parameter */
+    if (transport->trans == GST_RTSP_TRANS_RTP
+        && transport->client_port.min >= 0) {
+      if (transport->client_port.min < 65536
+          && transport->client_port.max < 65536) {
+        g_ptr_array_add (strs, g_strdup (";client_port="));
+        g_ptr_array_add (strs, range_as_text (&transport->client_port));
+      } else
+        goto invalid_transport;
+    }
 
-  /* add the server_port parameter */
-  if (transport->trans == GST_RTSP_TRANS_RTP && transport->server_port.min >= 0) {
-    if (transport->server_port.min < 65536 &&
-        transport->server_port.max < 65536) {
-      g_ptr_array_add (strs, g_strdup (";server_port="));
-      g_ptr_array_add (strs, range_as_text (&transport->server_port));
-    } else
-      goto invalid_transport;
+    /* add the server_port parameter */
+    if (transport->trans == GST_RTSP_TRANS_RTP
+        && transport->server_port.min >= 0) {
+      if (transport->server_port.min < 65536
+          && transport->server_port.max < 65536) {
+        g_ptr_array_add (strs, g_strdup (";server_port="));
+        g_ptr_array_add (strs, range_as_text (&transport->server_port));
+      } else
+        goto invalid_transport;
+    }
   }
 
   /* add the ssrc parameter */
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.h	Fri Apr 16 15:15:52 2010 +0300
@@ -81,6 +81,7 @@
  * @GST_RTSP_LOWER_TRANS_UDP: stream data over UDP
  * @GST_RTSP_LOWER_TRANS_UDP_MCAST: stream data over UDP multicast
  * @GST_RTSP_LOWER_TRANS_TCP: stream data over TCP
+ * @GST_RTSP_LOWER_TRANS_HTTP: stream data tunneled over HTTP. Since: 0.10.23
  *
  * The different transport methods.
  */
@@ -88,7 +89,8 @@
   GST_RTSP_LOWER_TRANS_UNKNOWN   = 0,
   GST_RTSP_LOWER_TRANS_UDP       = (1 << 0),
   GST_RTSP_LOWER_TRANS_UDP_MCAST = (1 << 1),
-  GST_RTSP_LOWER_TRANS_TCP       = (1 << 2)
+  GST_RTSP_LOWER_TRANS_TCP       = (1 << 2),
+  GST_RTSP_LOWER_TRANS_HTTP      = (1 << 4)
 } GstRTSPLowerTrans;
 
 /**
@@ -106,11 +108,25 @@
 
 /**
  * GstRTSPTransport:
+ * @trans: the transport mode
+ * @profile: the tansport profile
+ * @lower_transport: the lower transport
+ * @destination: the destination ip/hostname
+ * @source: the source ip/hostname
+ * @layers: the number of layers
+ * @mode_play: if play mode was selected
+ * @mode_record: if record mode was selected
+ * @append: is append mode was selected
+ * @interleaved: the interleave range
+ * @ttl: the time to live for multicast UDP
+ * @port: the port pair for multicast sessions
+ * @client_port: the client port pair for receiving data
+ * @server_port: the server port pair for receiving data
+ * @ssrc: the ssrc that the sender/receiver will use
  *
  * A structure holding the RTSP transport values.
  */
 typedef struct _GstRTSPTransport {
-  /*< private >*/
   GstRTSPTransMode  trans;
   GstRTSPProfile    profile;
   GstRTSPLowerTrans lower_transport;
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c	Fri Apr 16 15:15:52 2010 +0300
@@ -58,14 +58,44 @@
 
 #include "gstrtspurl.h"
 
-#define RTSP_PROTO      "rtsp://"
-#define RTSP_PROTO_LEN  7
-#define RTSPU_PROTO     "rtspu://"
-#define RTSPU_PROTO_LEN 8
-#define RTSPT_PROTO     "rtspt://"
-#define RTSPT_PROTO_LEN 8
+static void
+register_rtsp_url_type (GType * id)
+{
+  *id = g_boxed_type_register_static ("GstRTSPUrl",
+      (GBoxedCopyFunc) gst_rtsp_url_copy, (GBoxedFreeFunc) gst_rtsp_url_free);
+}
+
+GType
+gst_rtsp_url_get_type (void)
+{
+  static GType id;
+  static GOnce once = G_ONCE_INIT;
+
+  g_once (&once, (GThreadFunc) register_rtsp_url_type, &id);
+  return id;
+}
 
-/* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] */
+static const gchar *rtsp_url_schemes[] = {
+  "rtsp",
+  "rtspu",
+  "rtspt",
+  "rtsph",
+  NULL
+};
+
+static GstRTSPLowerTrans rtsp_url_transports[] = {
+  GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
+      GST_RTSP_LOWER_TRANS_UDP_MCAST,
+  GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST,
+  GST_RTSP_LOWER_TRANS_TCP,
+  GST_RTSP_LOWER_TRANS_HTTP | GST_RTSP_LOWER_TRANS_TCP,
+};
+
+/* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] where host
+ * is a host name, an IPv4 dotted decimal address ("aaa.bbb.ccc.ddd") or an
+ * [IPv6] address ("[aabb:ccdd:eeff:gghh::sstt]" note the brackets around the
+ * address to allow the distinction between ':' as an IPv6 hexgroup separator
+ * and as a host/port separator) */
 
 /**
  * gst_rtsp_url_parse:
@@ -82,6 +112,8 @@
 {
   GstRTSPUrl *res;
   gchar *p, *delim, *at, *col;
+  gchar *host_end = NULL;
+  guint scheme;
 
   g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
@@ -89,18 +121,20 @@
   res = g_new0 (GstRTSPUrl, 1);
 
   p = (gchar *) urlstr;
-  if (g_str_has_prefix (p, RTSP_PROTO)) {
-    res->transports =
-        GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
-        GST_RTSP_LOWER_TRANS_UDP_MCAST;
-    p += RTSP_PROTO_LEN;
-  } else if (g_str_has_prefix (p, RTSPU_PROTO)) {
-    res->transports = GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST;
-    p += RTSPU_PROTO_LEN;
-  } else if (g_str_has_prefix (p, RTSPT_PROTO)) {
-    res->transports = GST_RTSP_LOWER_TRANS_TCP;
-    p += RTSPT_PROTO_LEN;
-  } else
+
+  col = strstr (p, "://");
+  if (col == NULL)
+    goto invalid;
+
+  for (scheme = 0; rtsp_url_schemes[scheme] != NULL; scheme++) {
+    if (g_ascii_strncasecmp (rtsp_url_schemes[scheme], p, col - p) == 0) {
+      res->transports = rtsp_url_transports[scheme];
+      p = col + 3;
+      break;
+    }
+  }
+
+  if (res->transports == GST_RTSP_LOWER_TRANS_UNKNOWN)
     goto invalid;
 
   delim = strpbrk (p, "/?");
@@ -124,39 +158,52 @@
     p = at + 1;
   }
 
-  col = strchr (p, ':');
-  /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
-   * not really part of the hostname */
-  if (col && delim && col >= delim)
-    col = NULL;
+  if (*p == '[') {
+    res->family = GST_RTSP_FAM_INET6;
+
+    /* we have an IPv6 address in the URL, find the ending ] which must be
+     * before any delimiter */
+    host_end = strchr (++p, ']');
+    if (!host_end || (delim && host_end >= delim))
+      goto invalid;
+
+    /* a port specifier must follow the address immediately */
+    col = host_end[1] == ':' ? host_end + 1 : NULL;
+  } else {
+    res->family = GST_RTSP_FAM_INET;
+
+    col = strchr (p, ':');
 
-  if (col) {
-    res->host = g_strndup (p, col - p);
-    p = col + 1;
-    res->port = strtoul (p, (char **) &p, 10);
-    if (delim)
-      p = delim;
-  } else {
-    /* no port specified, set to 0. _get_port() will return the default port. */
-    res->port = 0;
-    if (!delim) {
-      res->host = g_strdup (p);
-      p = NULL;
+    /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
+     * not really part of the hostname */
+    if (col && delim && col >= delim)
+      col = NULL;
+
+    host_end = col ? col : delim;
+  }
+
+  if (!host_end)
+    res->host = g_strdup (p);
+  else {
+    res->host = g_strndup (p, host_end - p);
+
+    if (col) {
+      res->port = strtoul (col + 1, NULL, 10);
     } else {
-      res->host = g_strndup (p, delim - p);
-      p = delim;
+      /* no port specified, set to 0. gst_rtsp_url_get_port() will return the
+       * default port */
+      res->port = 0;
     }
   }
+  p = delim;
 
   if (p && *p == '/') {
     delim = strchr (p, '?');
-    if (!delim) {
+    if (!delim)
       res->abspath = g_strdup (p);
-      p = NULL;
-    } else {
+    else
       res->abspath = g_strndup (p, delim - p);
-      p = delim;
-    }
+    p = delim;
   } else {
     res->abspath = g_strdup ("/");
   }
@@ -177,6 +224,37 @@
 }
 
 /**
+ * gst_rtsp_url_copy:
+ * @url: a #GstRTSPUrl
+ *
+ * Make a copy of @url.
+ *
+ * Returns: a copy of @url. Free with gst_rtsp_url_free () after usage.
+ *
+ * Since: 0.10.22
+ */
+GstRTSPUrl *
+gst_rtsp_url_copy (const GstRTSPUrl * url)
+{
+  GstRTSPUrl *res;
+
+  g_return_val_if_fail (url != NULL, NULL);
+
+  res = g_new0 (GstRTSPUrl, 1);
+
+  res->transports = url->transports;
+  res->family = url->family;
+  res->user = g_strdup (url->user);
+  res->passwd = g_strdup (url->passwd);
+  res->host = g_strdup (url->host);
+  res->port = url->port;
+  res->abspath = g_strdup (url->abspath);
+  res->query = g_strdup (url->query);
+
+  return res;
+}
+
+/**
  * gst_rtsp_url_free:
  * @url: a #GstRTSPUrl
  *
@@ -225,7 +303,7 @@
  * Returns: #GST_RTSP_OK.
  */
 GstRTSPResult
-gst_rtsp_url_get_port (GstRTSPUrl * url, guint16 * port)
+gst_rtsp_url_get_port (const GstRTSPUrl * url, guint16 * port)
 {
   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (port != NULL, GST_RTSP_EINVAL);
@@ -248,18 +326,27 @@
  * Returns: a string with the request URI. g_free() after usage.
  */
 gchar *
-gst_rtsp_url_get_request_uri (GstRTSPUrl * url)
+gst_rtsp_url_get_request_uri (const GstRTSPUrl * url)
 {
   gchar *uri;
+  gchar *pre_host;
+  gchar *post_host;
+  gchar *pre_query;
+  gchar *query;
 
   g_return_val_if_fail (url != NULL, NULL);
 
+  pre_host = url->family == GST_RTSP_FAM_INET6 ? "[" : "";
+  post_host = url->family == GST_RTSP_FAM_INET6 ? "]" : "";
+  pre_query = url->query ? "?" : "";
+  query = url->query ? url->query : "";
+
   if (url->port != 0) {
-    uri = g_strdup_printf ("rtsp://%s:%u%s%s%s", url->host, url->port,
-        url->abspath, url->query ? "?" : "", url->query ? url->query : "");
+    uri = g_strdup_printf ("rtsp://%s%s%s:%u%s%s%s", pre_host, url->host,
+        post_host, url->port, url->abspath, pre_query, query);
   } else {
-    uri = g_strdup_printf ("rtsp://%s%s%s%s", url->host, url->abspath,
-        url->query ? "?" : "", url->query ? url->query : "");
+    uri = g_strdup_printf ("rtsp://%s%s%s%s%s%s", pre_host, url->host,
+        post_host, url->abspath, pre_query, query);
   }
 
   return uri;
--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.h	Fri Apr 16 15:15:52 2010 +0300
@@ -44,6 +44,7 @@
 #define __GST_RTSP_URL_H__
 
 #include <glib.h>
+#include <glib-object.h>
 
 #include <gst/rtsp/gstrtspdefs.h>
 #include <gst/rtsp/gstrtsptransport.h>
@@ -57,6 +58,8 @@
  */
 #define GST_RTSP_DEFAULT_PORT       554
 
+#define GST_TYPE_RTSP_URL  (gst_rtsp_url_get_type())
+
 typedef struct _GstRTSPUrl GstRTSPUrl;
 
 /**
@@ -83,12 +86,15 @@
   gchar             *query;
 }; 
 
+GType gst_rtsp_url_get_type (void);
+
 GstRTSPResult      gst_rtsp_url_parse           (const gchar *urlstr, GstRTSPUrl **url);
+GstRTSPUrl*        gst_rtsp_url_copy            (const GstRTSPUrl *url);
 void               gst_rtsp_url_free            (GstRTSPUrl *url);
-gchar*             gst_rtsp_url_get_request_uri (GstRTSPUrl *url);
+gchar*             gst_rtsp_url_get_request_uri (const GstRTSPUrl *url);
 
 GstRTSPResult      gst_rtsp_url_set_port        (GstRTSPUrl *url, guint16 port);
-GstRTSPResult      gst_rtsp_url_get_port        (GstRTSPUrl *url, guint16 *port);
+GstRTSPResult      gst_rtsp_url_get_port        (const GstRTSPUrl *url, guint16 *port);
 
 G_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtsp/md5.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,271 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.	This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* Brutally hacked by John Walker back from ANSI C to K&R (no
+   prototypes) to maintain the tradition that Netfone will compile
+   with Sun's original "cc". */
+
+#include <string.h>             /* for memcpy() */
+#include <glib.h>
+#include "md5.h"
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define HIGHFIRST
+#endif
+
+#ifndef HIGHFIRST
+#define byteReverse(buf, len)   /* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+void
+byteReverse (buf, longs)
+     unsigned char *buf;
+     unsigned longs;
+{
+  uint32 t;
+
+  do {
+    t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+        ((unsigned) buf[1] << 8 | buf[0]);
+    *(uint32 *) buf = t;
+    buf += 4;
+  } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init (ctx)
+     struct MD5Context *ctx;
+{
+  ctx->buf[0] = 0x67452301;
+  ctx->buf[1] = 0xefcdab89;
+  ctx->buf[2] = 0x98badcfe;
+  ctx->buf[3] = 0x10325476;
+
+  ctx->bits[0] = 0;
+  ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update (ctx, buf, len)
+     struct MD5Context *ctx;
+     const char *buf;
+     unsigned len;
+{
+  uint32 t;
+
+  /* Update bitcount */
+
+  t = ctx->bits[0];
+  if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+    ctx->bits[1]++;             /* Carry from low to high */
+  ctx->bits[1] += len >> 29;
+
+  t = (t >> 3) & 0x3f;          /* Bytes already in shsInfo->data */
+
+  /* Handle any leading odd-sized chunks */
+
+  if (t) {
+    unsigned char *p = (unsigned char *) ctx->in + t;
+
+    t = 64 - t;
+    if (len < t) {
+      memcpy (p, buf, len);
+      return;
+    }
+    memcpy (p, buf, t);
+    byteReverse (ctx->in, 16);
+    MD5Transform (ctx->buf, (uint32 *) ctx->in);
+    buf += t;
+    len -= t;
+  }
+  /* Process data in 64-byte chunks */
+
+  while (len >= 64) {
+    memcpy (ctx->in, buf, 64);
+    byteReverse (ctx->in, 16);
+    MD5Transform (ctx->buf, (uint32 *) ctx->in);
+    buf += 64;
+    len -= 64;
+  }
+
+  /* Handle any remaining bytes of data. */
+
+  memcpy (ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final (digest, ctx)
+     unsigned char digest[16];
+     struct MD5Context *ctx;
+{
+  unsigned count;
+  unsigned char *p;
+
+  /* Compute number of bytes mod 64 */
+  count = (ctx->bits[0] >> 3) & 0x3F;
+
+  /* Set the first char of padding to 0x80.  This is safe since there is
+     always at least one byte free */
+  p = ctx->in + count;
+  *p++ = 0x80;
+
+  /* Bytes of padding needed to make 64 bytes */
+  count = 64 - 1 - count;
+
+  /* Pad out to 56 mod 64 */
+  if (count < 8) {
+    /* Two lots of padding:  Pad the first block to 64 bytes */
+    memset (p, 0, count);
+    byteReverse (ctx->in, 16);
+    MD5Transform (ctx->buf, (uint32 *) ctx->in);
+
+    /* Now fill the next block with 56 bytes */
+    memset (ctx->in, 0, 56);
+  } else {
+    /* Pad block to 56 bytes */
+    memset (p, 0, count - 8);
+  }
+  byteReverse (ctx->in, 14);
+
+  /* Append length in bits and transform */
+  ((uint32 *) ctx->in)[14] = ctx->bits[0];
+  ((uint32 *) ctx->in)[15] = ctx->bits[1];
+
+  MD5Transform (ctx->buf, (uint32 *) ctx->in);
+  byteReverse ((unsigned char *) ctx->buf, 4);
+  memcpy (digest, ctx->buf, 16);
+  memset (ctx, 0, sizeof (ctx));        /* In case it's sensitive */
+}
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform (buf, in)
+     uint32 buf[4];
+     uint32 in[16];
+{
+  register uint32 a, b, c, d;
+
+  a = buf[0];
+  b = buf[1];
+  c = buf[2];
+  d = buf[3];
+
+  MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+  MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+  MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17);
+  MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+  MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+  MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+  MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17);
+  MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22);
+  MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7);
+  MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+  MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+  MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+  MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7);
+  MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12);
+  MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17);
+  MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+  MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+  MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9);
+  MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+  MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+  MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+  MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9);
+  MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+  MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+  MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+  MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+  MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+  MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+  MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+  MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+  MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+  MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+  MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+  MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11);
+  MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+  MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+  MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+  MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+  MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+  MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+  MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+  MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+  MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+  MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23);
+  MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+  MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+  MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+  MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+  MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6);
+  MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10);
+  MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+  MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+  MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+  MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+  MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+  MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+  MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+  MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+  MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15);
+  MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+  MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+  MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+  MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+  MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtsp/md5.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,28 @@
+#ifndef MD5_H
+#define MD5_H
+
+#include "_stdint.h"
+
+#ifndef uint32
+typedef uint32_t uint32;
+#endif
+
+struct MD5Context
+{
+  uint32 buf[4];
+  uint32 bits[2];
+  unsigned char in[64];
+};
+
+extern void MD5Init (struct MD5Context *ctx);
+extern void MD5Update (struct MD5Context *ctx, const char *buf,
+    unsigned len);
+extern void MD5Final (unsigned char digest[16], struct MD5Context *ctx);
+extern void MD5Transform (uint32 buf[4], uint32 in[16]);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct MD5Context MD5_CTX;
+
+#endif /* !MD5_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtsp/rtsp-marshal.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,91 @@
+#include "rtsp-marshal.h"
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* ENUM:POINTER,POINTER (rtsp-marshal.list:1) */
+void
+gst_rtsp_marshal_ENUM__POINTER_POINTER (GClosure     *closure,
+                                        GValue       *return_value G_GNUC_UNUSED,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint G_GNUC_UNUSED,
+                                        gpointer      marshal_data)
+{
+  typedef gint (*GMarshalFunc_ENUM__POINTER_POINTER) (gpointer     data1,
+                                                      gpointer     arg_1,
+                                                      gpointer     arg_2,
+                                                      gpointer     data2);
+  register GMarshalFunc_ENUM__POINTER_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gint v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_ENUM__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_pointer (param_values + 1),
+                       g_marshal_value_peek_pointer (param_values + 2),
+                       data2);
+
+  g_value_set_enum (return_value, v_return);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/rtsp/rtsp-marshal.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,20 @@
+
+#ifndef __gst_rtsp_marshal_MARSHAL_H__
+#define __gst_rtsp_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* ENUM:POINTER,POINTER (rtsp-marshal.list:1) */
+extern void gst_rtsp_marshal_ENUM__POINTER_POINTER (GClosure     *closure,
+                                                    GValue       *return_value,
+                                                    guint         n_param_values,
+                                                    const GValue *param_values,
+                                                    gpointer      invocation_hint,
+                                                    gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* __gst_rtsp_marshal_MARSHAL_H__ */
+
--- a/gst_plugins_base/gst-libs/gst/sdp/gstsdpmessage.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/sdp/gstsdpmessage.c	Fri Apr 16 15:15:52 2010 +0300
@@ -69,6 +69,11 @@
 #include <gst/gstinfo.h>        /* For GST_STR_NULL */
 
 #ifdef G_OS_WIN32
+/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
+ * minwg32 headers check WINVER before allowing the use of these */
+#ifndef WINVER
+#define WINVER 0x0501
+#endif
 #ifdef _MSC_VER
 #include <Winsock2.h>
 #endif
@@ -151,10 +156,6 @@
   g_array_append_val (msg->field, v);                                   \
   return GST_SDP_OK;                                                    \
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
 
 static void
 gst_sdp_origin_init (GstSDPOrigin * origin)
@@ -328,14 +329,13 @@
   struct addrinfo *ai;
   struct addrinfo *res;
   gboolean ret = FALSE;
-  int err;
 
   memset (&hints, 0, sizeof (hints));
   hints.ai_socktype = SOCK_DGRAM;
 
   g_return_val_if_fail (host_name, FALSE);
 
-  if ((err = getaddrinfo (host_name, NULL, &hints, &res)) < 0)
+  if (getaddrinfo (host_name, NULL, &hints, &res) < 0)
     return FALSE;
 
   for (ai = res; !ret && ai; ai = ai->ai_next) {
@@ -1742,17 +1742,38 @@
       gst_sdp_message_add_phone (c->msg, buffer);
       break;
     case 'c':
-      READ_STRING (c->msg->connection.nettype);
-      READ_STRING (c->msg->connection.addrtype);
-      READ_STRING (c->msg->connection.address);
-      READ_UINT (c->msg->connection.ttl);
-      READ_UINT (c->msg->connection.addr_number);
+    {
+      GstSDPConnection conn;
+      gchar *str2;
+
+      memset (&conn, 0, sizeof (conn));
+
+      str2 = p;
+      while ((str2 = strchr (str2, '/')))
+        *str2++ = ' ';
+      READ_STRING (conn.nettype);
+      READ_STRING (conn.addrtype);
+      READ_STRING (conn.address);
+      READ_UINT (conn.ttl);
+      READ_UINT (conn.addr_number);
+
+      if (c->state == SDP_SESSION) {
+        gst_sdp_message_set_connection (c->msg, conn.nettype, conn.addrtype,
+            conn.address, conn.ttl, conn.addr_number);
+      } else {
+        gst_sdp_media_add_connection (c->media, conn.nettype, conn.addrtype,
+            conn.address, conn.ttl, conn.addr_number);
+      }
+      gst_sdp_connection_init (&conn);
       break;
+    }
     case 'b':
     {
       gchar str2[MAX_LINE_LEN];
 
       read_string_del (str, sizeof (str), ':', &p);
+      if (*p != '\0')
+        p++;
       read_string (str2, sizeof (str2), &p);
       if (c->state == SDP_SESSION)
         gst_sdp_message_add_bandwidth (c->msg, str, atoi (str2));
@@ -1875,10 +1896,10 @@
 static void
 print_media (GstSDPMedia * media)
 {
-  g_print ("   media:       '%s'\n", media->media);
+  g_print ("   media:       '%s'\n", GST_STR_NULL (media->media));
   g_print ("   port:        '%u'\n", media->port);
   g_print ("   num_ports:   '%u'\n", media->num_ports);
-  g_print ("   proto:       '%s'\n", media->proto);
+  g_print ("   proto:       '%s'\n", GST_STR_NULL (media->proto));
   if (media->fmts->len > 0) {
     guint i;
 
@@ -1887,10 +1908,37 @@
       g_print ("    format  '%s'\n", g_array_index (media->fmts, gchar *, i));
     }
   }
-  g_print ("   information: '%s'\n", media->information);
+  g_print ("   information: '%s'\n", GST_STR_NULL (media->information));
+  if (media->connections->len > 0) {
+    guint i;
+
+    g_print ("   connections:\n");
+    for (i = 0; i < media->connections->len; i++) {
+      GstSDPConnection *conn =
+          &g_array_index (media->connections, GstSDPConnection, i);
+
+      g_print ("    nettype:      '%s'\n", GST_STR_NULL (conn->nettype));
+      g_print ("    addrtype:     '%s'\n", GST_STR_NULL (conn->addrtype));
+      g_print ("    address:      '%s'\n", GST_STR_NULL (conn->address));
+      g_print ("    ttl:          '%u'\n", conn->ttl);
+      g_print ("    addr_number:  '%u'\n", conn->addr_number);
+    }
+  }
+  if (media->bandwidths->len > 0) {
+    guint i;
+
+    g_print ("   bandwidths:\n");
+    for (i = 0; i < media->bandwidths->len; i++) {
+      GstSDPBandwidth *bw =
+          &g_array_index (media->bandwidths, GstSDPBandwidth, i);
+
+      g_print ("    type:         '%s'\n", GST_STR_NULL (bw->bwtype));
+      g_print ("    bandwidth:    '%u'\n", bw->bandwidth);
+    }
+  }
   g_print ("   key:\n");
-  g_print ("    type:       '%s'\n", media->key.type);
-  g_print ("    data:       '%s'\n", media->key.data);
+  g_print ("    type:       '%s'\n", GST_STR_NULL (media->key.type));
+  g_print ("    data:       '%s'\n", GST_STR_NULL (media->key.data));
   if (media->attributes->len > 0) {
     guint i;
 
@@ -1952,6 +2000,18 @@
   g_print ("  address:      '%s'\n", GST_STR_NULL (msg->connection.address));
   g_print ("  ttl:          '%u'\n", msg->connection.ttl);
   g_print ("  addr_number:  '%u'\n", msg->connection.addr_number);
+  if (msg->bandwidths->len > 0) {
+    guint i;
+
+    g_print (" bandwidths:\n");
+    for (i = 0; i < msg->bandwidths->len; i++) {
+      GstSDPBandwidth *bw =
+          &g_array_index (msg->bandwidths, GstSDPBandwidth, i);
+
+      g_print ("  type:         '%s'\n", GST_STR_NULL (bw->bwtype));
+      g_print ("  bandwidth:    '%u'\n", bw->bandwidth);
+    }
+  }
   g_print (" key:\n");
   g_print ("  type:         '%s'\n", GST_STR_NULL (msg->key.type));
   g_print ("  data:         '%s'\n", GST_STR_NULL (msg->key.data));
--- a/gst_plugins_base/gst-libs/gst/tag/gstid3tag.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/gstid3tag.c	Fri Apr 16 15:15:52 2010 +0300
@@ -398,7 +398,7 @@
     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_DATE, date, NULL);
     g_date_free (date);
   }
-  if (data[125] == 0) {
+  if (data[125] == 0 && data[126] != 0) {
     gst_tag_extract_id3v1_string (list, GST_TAG_COMMENT, (gchar *) & data[97],
         28);
     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_TRACK_NUMBER,
@@ -407,7 +407,7 @@
     gst_tag_extract_id3v1_string (list, GST_TAG_COMMENT, (gchar *) & data[97],
         30);
   }
-  if (data[127] < gst_tag_id3_genre_count ()) {
+  if (data[127] < gst_tag_id3_genre_count () && !gst_tag_list_is_empty (list)) {
     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_GENRE,
         gst_tag_id3_genre_get (data[127]), NULL);
   }
@@ -452,3 +452,62 @@
     return NULL;
   return genres[id];
 }
+
+/**
+ * gst_tag_list_add_id3_image:
+ * @tag_list: a tag list
+ * @image_data: the (encoded) image
+ * @image_data_len: the length of the encoded image data at @image_data
+ * @id3_picture_type: picture type as per the ID3 (v2.4.0) specification for
+ *    the APIC frame (0 = unknown/other)
+ *
+ * Adds an image from an ID3 APIC frame (or similar, such as used in FLAC)
+ * to the given tag list. Also see gst_tag_image_data_to_image_buffer() for
+ * more information on image tags in GStreamer.
+ *
+ * Returns: %TRUE if the image was processed, otherwise %FALSE
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_tag_list_add_id3_image (GstTagList * tag_list, const guint8 * image_data,
+    guint image_data_len, guint id3_picture_type)
+{
+  GstTagImageType tag_image_type;
+  const gchar *tag_name;
+  GstBuffer *image;
+
+  g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), FALSE);
+  g_return_val_if_fail (image_data != NULL, FALSE);
+  g_return_val_if_fail (image_data_len > 0, FALSE);
+
+  if (id3_picture_type == 0x01 || id3_picture_type == 0x02) {
+    /* file icon for preview. Don't add image-type to caps, since there
+     * is only supposed to be one of these, and the type is already indicated
+     * via the special tag */
+    tag_name = GST_TAG_PREVIEW_IMAGE;
+    tag_image_type = GST_TAG_IMAGE_TYPE_NONE;
+  } else {
+    tag_name = GST_TAG_IMAGE;
+
+    /* Remap the ID3v2 APIC type our ImageType enum */
+    if (id3_picture_type >= 0x3 && id3_picture_type <= 0x14)
+      tag_image_type = (GstTagImageType) (id3_picture_type - 2);
+    else
+      tag_image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
+  }
+
+  image = gst_tag_image_data_to_image_buffer (image_data, image_data_len,
+      tag_image_type);
+
+  if (image == NULL)
+    return FALSE;
+
+  gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, image, NULL);
+  gst_buffer_unref (image);
+  return TRUE;
+}
--- a/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -75,11 +75,7 @@
 #include "gsttagdemux.h"
 
 #include <gst/base/gsttypefindhelper.h>
-#ifndef __SYMBIAN32__
 #include <gst/gst-i18n-plugin.h>
-#else
-#include "gst/gst-i18n-plugin.h"
-#endif
 #include <string.h>
 
 typedef enum
@@ -115,6 +111,8 @@
   GstSegment segment;
   gboolean need_newseg;
   gboolean newseg_update;
+
+  GList *pending_events;
 };
 
 /* Require at least 8kB of data before we attempt typefind. 
@@ -166,6 +164,27 @@
 static void gst_tag_demux_init (GstTagDemux * obj, GstTagDemuxClass * klass);
 
 static gpointer parent_class;   /* NULL */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GType
+gst_tag_demux_result_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      {GST_TAG_DEMUX_RESULT_BROKEN_TAG, "GST_TAG_DEMUX_RESULT_BROKEN_TAG",
+          "broken-tag"},
+      {GST_TAG_DEMUX_RESULT_AGAIN, "GST_TAG_DEMUX_RESULT_AGAIN", "again"},
+      {GST_TAG_DEMUX_RESULT_OK, "GST_TAG_DEMUX_RESULT_OK", "ok"},
+      {0, NULL, NULL}
+    };
+    etype = g_enum_register_static ("GstTagDemuxResult", values);
+  }
+  return etype;
+}
 
 /* Cannot use boilerplate macros here because we want the abstract flag */
 #ifdef __SYMBIAN32__
@@ -258,6 +277,11 @@
   gst_segment_init (&tagdemux->priv->segment, GST_FORMAT_UNDEFINED);
   tagdemux->priv->need_newseg = TRUE;
   tagdemux->priv->newseg_update = FALSE;
+
+  g_list_foreach (tagdemux->priv->pending_events,
+      (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (tagdemux->priv->pending_events);
+  tagdemux->priv->pending_events = NULL;
 }
 
 static void
@@ -423,8 +447,6 @@
     need_sub = TRUE;
   }
 
-  g_assert (out_size > 0);
-
   if (need_sub == TRUE) {
     if (out_size != GST_BUFFER_SIZE (buf) || !gst_buffer_is_writable (buf)) {
       GstBuffer *sub;
@@ -656,6 +678,8 @@
           return GST_FLOW_UNEXPECTED;
       }
       if (outbuf) {
+        GList *events;
+
         if (G_UNLIKELY (demux->priv->srcpad == NULL)) {
           gst_buffer_unref (outbuf);
           return GST_FLOW_ERROR;
@@ -670,7 +694,20 @@
           demux->priv->need_newseg = FALSE;
         }
 
-        /* Send pending tag event */
+        /* send any pending events we cached */
+        GST_OBJECT_LOCK (demux);
+        events = demux->priv->pending_events;
+        demux->priv->pending_events = NULL;
+        GST_OBJECT_UNLOCK (demux);
+
+        while (events != NULL) {
+          GST_DEBUG_OBJECT (demux->priv->srcpad, "sending cached %s event: %"
+              GST_PTR_FORMAT, GST_EVENT_TYPE_NAME (events->data), events->data);
+          gst_pad_push_event (demux->priv->srcpad, GST_EVENT (events->data));
+          events = g_list_delete_link (events, events);
+        }
+
+        /* Send our own pending tag event */
         if (demux->priv->send_tag_event) {
           gst_tag_demux_send_tag_event (demux);
           demux->priv->send_tag_event = FALSE;
@@ -728,7 +765,18 @@
       break;
     }
     default:
-      ret = gst_pad_event_default (pad, event);
+      if (demux->priv->need_newseg) {
+        /* Cache all events if we have a pending segment, so they don't get
+         * lost (esp. tag events) */
+        GST_INFO_OBJECT (demux, "caching event: %" GST_PTR_FORMAT, event);
+        GST_OBJECT_LOCK (demux);
+        demux->priv->pending_events =
+            g_list_append (demux->priv->pending_events, event);
+        GST_OBJECT_UNLOCK (demux);
+        ret = TRUE;
+      } else {
+        ret = gst_pad_event_default (pad, event);
+      }
       break;
   }
 
@@ -829,12 +877,14 @@
       break;
     }
     default:
-      /* FIXME: shouldn't we pass unknown and unhandled events upstream? */
+      res = gst_pad_push_event (tagdemux->priv->sinkpad, event);
+      event = NULL;
       break;
   }
 
   gst_object_unref (tagdemux);
-  gst_event_unref (event);
+  if (event)
+    gst_event_unref (event);
   return res;
 }
 
@@ -1159,6 +1209,13 @@
     demux->priv->send_tag_event = TRUE;
   }
 
+  if (demux->priv->upstream_size <=
+      demux->priv->strip_start + demux->priv->strip_end) {
+    /* There was no data (probably due to a truncated file) */
+    GST_DEBUG_OBJECT (demux, "No data in file");
+    return FALSE;
+  }
+
   /* 3 - Do typefinding on data */
   caps = gst_type_find_helper_get_range (GST_OBJECT (demux),
       (GstTypeFindHelperGetRangeFunction) gst_tag_demux_read_range,
@@ -1269,7 +1326,7 @@
   {
     GST_DEBUG_OBJECT (demux, "attempted read beyond end of file");
     if (*buffer != NULL) {
-      gst_buffer_unref (buffer);
+      gst_buffer_unref (*buffer);
       *buffer = NULL;
     }
     return GST_FLOW_UNEXPECTED;
--- a/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.h	Fri Apr 16 15:15:52 2010 +0300
@@ -50,9 +50,17 @@
   GST_TAG_DEMUX_RESULT_AGAIN,
   GST_TAG_DEMUX_RESULT_OK
 } GstTagDemuxResult;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_tag_demux_result_get_type (void);
+#define GST_TYPE_TAG_DEMUX_RESULT (gst_tag_demux_result_get_type())
 
 /**
  * GstTagDemux:
+ * @element: parent element
  *
  * Opaque #GstTagDemux structure.
  *
--- a/gst_plugins_base/gst-libs/gst/tag/gstvorbistag.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/gstvorbistag.c	Fri Apr 16 15:15:52 2010 +0300
@@ -62,7 +62,7 @@
   {GST_TAG_COPYRIGHT, "COPYRIGHT"},
   {GST_TAG_LICENSE, "LICENSE"},
   {GST_TAG_LICENSE_URI, "LICENSE"},
-  {GST_TAG_LOCATION, "LOCATION"},
+  {GST_TAG_GEO_LOCATION_NAME, "LOCATION"},
   {GST_TAG_ORGANIZATION, "ORGANIZATION"},
   {GST_TAG_DESCRIPTION, "DESCRIPTION"},
   {GST_TAG_GENRE, "GENRE"},
@@ -90,7 +90,10 @@
   {GST_TAG_LANGUAGE_CODE, "LANGUAGE"},
   {GST_TAG_CDDA_MUSICBRAINZ_DISCID, "MUSICBRAINZ_DISCID"},
   {GST_TAG_CDDA_CDDB_DISCID, "DISCID"},
-  /* some incidence that this makes sense:
+  /* For the apparent de-facto standard for coverart in vorbis comments, see:
+   * http://www.hydrogenaudio.org/forums/lofiversion/index.php/t48386.html */
+  {GST_TAG_PREVIEW_IMAGE, "COVERART"},
+  /* some evidence that "BPM" is used elsewhere:
    * http://mail.kde.org/pipermail/amarok/2006-May/000090.html
    */
   {GST_TAG_BEATS_PER_MINUTE, "BPM"},
@@ -317,6 +320,62 @@
   }
 }
 
+static void
+gst_vorbis_tag_add_coverart (GstTagList * tags, gchar * img_data_base64,
+    gint base64_len)
+{
+  GstBuffer *img;
+  gsize img_len;
+  guchar *out;
+  guint save = 0;
+  gint state = 0;
+
+  if (base64_len < 2)
+    goto not_enough_data;
+
+  /* img_data_base64 points to a temporary copy of the base64 encoded data, so
+   * it's safe to do inpace decoding here
+   * TODO: glib 2.20 and later provides g_base64_decode_inplace, so change this
+   * to use glib's API instead once it's in wider use:
+   *  http://bugzilla.gnome.org/show_bug.cgi?id=564728
+   *  http://svn.gnome.org/viewvc/glib?view=revision&revision=7807 */
+  out = (guchar *) img_data_base64;
+  img_len = g_base64_decode_step (img_data_base64, base64_len,
+      out, &state, &save);
+
+  if (img_len == 0)
+    goto decode_failed;
+
+  img = gst_tag_image_data_to_image_buffer (out, img_len,
+      GST_TAG_IMAGE_TYPE_NONE);
+
+  if (img == NULL)
+    goto convert_failed;
+
+  gst_tag_list_add (tags, GST_TAG_MERGE_APPEND,
+      GST_TAG_PREVIEW_IMAGE, img, NULL);
+
+  gst_buffer_unref (img);
+  return;
+
+/* ERRORS */
+not_enough_data:
+  {
+    GST_WARNING ("COVERART tag with too little base64-encoded data");
+    return;
+  }
+decode_failed:
+  {
+    GST_WARNING ("Couldn't decode base64 image data from COVERART tag");
+    return;
+  }
+convert_failed:
+  {
+    GST_WARNING ("Couldn't extract image or image type from COVERART tag");
+    return;
+  }
+}
+
 /**
  * gst_tag_list_from_vorbiscomment_buffer:
  * @buffer: buffer to convert
@@ -353,7 +412,7 @@
   guint cur_size;
   guint iterations;
   guint8 *data;
-  guint size;
+  guint size, value_len;
   GstTagList *list;
 
   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
@@ -365,14 +424,19 @@
 
   if (size < 11 || size <= id_data_length + 4)
     goto error;
+
   if (id_data_length > 0 && memcmp (data, id_data, id_data_length) != 0)
     goto error;
+
   ADVANCE (id_data_length);
+
   if (vendor_string)
     *vendor_string = g_strndup (cur, cur_size);
+
   ADVANCE (cur_size);
   iterations = cur_size;
   cur_size = 0;
+
   while (iterations) {
     ADVANCE (cur_size);
     iterations--;
@@ -384,11 +448,19 @@
     }
     *value = '\0';
     value++;
-    if (!g_utf8_validate (value, -1, NULL)) {
+    value_len = strlen (value);
+    if (value_len == 0 || !g_utf8_validate (value, value_len, NULL)) {
       g_free (cur);
       continue;
     }
-    gst_vorbis_tag_add (list, cur, value);
+    /* we'll just ignore COVERARTMIME and typefind the image data */
+    if (g_ascii_strcasecmp (cur, "COVERARTMIME") == 0) {
+      continue;
+    } else if (g_ascii_strcasecmp (cur, "COVERART") == 0) {
+      gst_vorbis_tag_add_coverart (list, value, value_len);
+    } else {
+      gst_vorbis_tag_add (list, cur, value);
+    }
     g_free (cur);
   }
 
@@ -399,6 +471,7 @@
   return NULL;
 #undef ADVANCE
 }
+
 typedef struct
 {
   guint count;
@@ -407,6 +480,39 @@
 }
 MyForEach;
 
+static GList *
+gst_tag_to_coverart (const GValue * image_value)
+{
+  gchar *coverart_data, *data_result, *mime_result;
+  const gchar *mime_type;
+  GstStructure *mime_struct;
+  GstBuffer *buffer;
+  GList *l = NULL;
+
+  g_return_val_if_fail (image_value != NULL, NULL);
+
+  buffer = gst_value_get_buffer (image_value);
+  g_return_val_if_fail (gst_caps_is_fixed (buffer->caps), NULL);
+  mime_struct = gst_caps_get_structure (buffer->caps, 0);
+  mime_type = gst_structure_get_name (mime_struct);
+
+  if (strcmp (mime_type, "text/uri-list") == 0) {
+    /* URI reference */
+    coverart_data = g_strndup ((gchar *) buffer->data, buffer->size);
+  } else {
+    coverart_data = g_base64_encode (buffer->data, buffer->size);
+  }
+
+  data_result = g_strdup_printf ("COVERART=%s", coverart_data);
+  mime_result = g_strdup_printf ("COVERARTMIME=%s", mime_type);
+  g_free (coverart_data);
+
+  l = g_list_append (l, data_result);
+  l = g_list_append (l, mime_result);
+
+  return l;
+}
+
 /**
  * gst_tag_to_vorbis_comments:
  * @list: a #GstTagList
@@ -432,6 +538,18 @@
   g_return_val_if_fail (list != NULL, NULL);
   g_return_val_if_fail (tag != NULL, NULL);
 
+  /* Special case: cover art is split into two tags to store data and
+   * MIME-type. Even if the tag list contains multiple entries, there is
+   * no reasonable way to save more than one.
+   * If both, preview image and image, are present we prefer the
+   * image tag.
+   */
+  if ((strcmp (tag, GST_TAG_PREVIEW_IMAGE) == 0 &&
+          gst_tag_list_get_tag_size (list, GST_TAG_IMAGE) == 0) ||
+      strcmp (tag, GST_TAG_IMAGE) == 0) {
+    return gst_tag_to_coverart (gst_tag_list_get_value_index (list, tag, 0));
+  }
+
   if (strcmp (tag, GST_TAG_EXTENDED_COMMENT) != 0) {
     vorbis_tag = gst_tag_to_vorbis_tag (tag);
     if (!vorbis_tag)
--- a/gst_plugins_base/gst-libs/gst/tag/tag.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/tag.h	Fri Apr 16 15:15:52 2010 +0300
@@ -126,6 +126,9 @@
 
 /**
  * GstTagImageType:
+ * @GST_TAG_IMAGE_TYPE_NONE                  : No image type. Can be used to
+ *      tell functions such as gst_tag_image_data_to_image_buffer() that no
+ *      image type should be set. (Since: 0.10.20)
  * @GST_TAG_IMAGE_TYPE_UNDEFINED             : Undefined/other image type
  * @GST_TAG_IMAGE_TYPE_FRONT_COVER           : Cover (front)
  * @GST_TAG_IMAGE_TYPE_BACK_COVER            : Cover (back)
@@ -151,8 +154,10 @@
  *
  * Since: 0.10.9
  */
+/* Note: keep in sync with register_tag_image_type_enum() */
 typedef enum {
-  GST_TAG_IMAGE_TYPE_UNDEFINED,
+  GST_TAG_IMAGE_TYPE_NONE = -1,
+  GST_TAG_IMAGE_TYPE_UNDEFINED = 0,
   GST_TAG_IMAGE_TYPE_FRONT_COVER,
   GST_TAG_IMAGE_TYPE_BACK_COVER,
   GST_TAG_IMAGE_TYPE_LEAFLET_PAGE,
@@ -256,6 +261,15 @@
 #endif
 
 G_CONST_RETURN gchar *  gst_tag_to_id3_tag                      (const gchar *          gst_tag);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean                gst_tag_list_add_id3_image (GstTagList   * tag_list,
+                                                    const guint8 * image_data,
+                                                    guint          image_data_len,
+                                                    guint          id3_picture_type);
 
 /* other tag-related functions */
 #ifdef __SYMBIAN32__
@@ -276,6 +290,14 @@
 gchar                 * gst_tag_freeform_string_to_utf8 (const gchar  * data,
                                                          gint           size,
                                                          const gchar ** env_vars);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstBuffer             * gst_tag_image_data_to_image_buffer (const guint8   * image_data,
+                                                            guint            image_data_len,
+                                                            GstTagImageType  image_type);
 
 /* FIXME 0.11: replace with a more general gst_tag_library_init() */
 #ifdef __SYMBIAN32__
--- a/gst_plugins_base/gst-libs/gst/tag/tags.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/tags.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,6 @@
 /* GStreamer non-core tag registration and tag utility functions
  * Copyright (C) 2005 Ross Burton <ross@burtonini.com>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2006-2008 Tim-Philipp Müller <tim centricular net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -22,11 +22,8 @@
 #include "config.h"
 #endif
 
-#ifndef __SYMBIAN32__
 #include <gst/gst-i18n-plugin.h>
-#else
-#include "gst/gst-i18n-plugin.h"
-#endif
+#include <gst/base/gsttypefindhelper.h>
 #include <gst/gst.h>
 #include "tag.h"
 
@@ -54,6 +51,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif
 
   /* musicbrainz tags */
@@ -114,6 +112,7 @@
 register_tag_image_type_enum (GType * id)
 {
   static const GEnumValue image_types[] = {
+    {GST_TAG_IMAGE_TYPE_NONE, "GST_TAG_IMAGE_TYPE_NONE", "none"},
     {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"},
     {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER",
         "front-cover"},
@@ -152,6 +151,9 @@
   };
 
   *id = g_enum_register_static ("GstTagImageType", image_types);
+
+  /* work around thread-safety issue with class creation in GLib */
+  g_type_class_ref (*id);
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -162,12 +164,27 @@
 gst_tag_image_type_get_type (void)
 {
   static GType id;
+
   static GOnce once = G_ONCE_INIT;
 
   g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id);
   return id;
 }
 
+static inline gboolean
+gst_tag_image_type_is_valid (GstTagImageType type)
+{
+  GEnumClass *klass;
+
+  gboolean res;
+
+  klass = g_type_class_ref (gst_tag_image_type_get_type ());
+  res = (g_enum_get_value (klass, type) != NULL);
+  g_type_class_unref (klass);
+
+  return res;
+}
+
 /**
  * gst_tag_parse_extended_comment:
  * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT
@@ -264,7 +281,9 @@
     const gchar ** env_vars)
 {
   const gchar *cur_loc = NULL;
+
   gsize bytes_read;
+
   gchar *utf8 = NULL;
 
   g_return_val_if_fail (data != NULL, NULL);
@@ -346,3 +365,119 @@
   g_free (utf8);
   return NULL;
 }
+
+/**
+ * gst_tag_image_data_to_image_buffer:
+ * @image_data: the (encoded) image
+ * @image_data_len: the length of the encoded image data at @image_data
+ * @image_type: type of the image, or #GST_TAG_IMAGE_TYPE_UNDEFINED. Pass
+ *     #GST_TAG_IMAGE_TYPE_NONE if no image type should be set at all (e.g.
+ *     for preview images)
+ *
+ * Helper function for tag-reading plugins to create a #GstBuffer suitable to
+ * add to a #GstTagList as an image tag (such as #GST_TAG_IMAGE or
+ * #GST_TAG_PREVIEW_IMAGE) from the encoded image data and an (optional) image
+ * type.
+ *
+ * Background: cover art and other images in tags are usually stored as a
+ * blob of binary image data, often accompanied by a MIME type or some other
+ * content type string (e.g. 'png', 'jpeg', 'jpg'). Sometimes there is also an
+ * 'image type' to indicate what kind of image this is (e.g. front cover,
+ * back cover, artist, etc.). The image data may also be an URI to the image
+ * rather than the image itself.
+ *
+ * In GStreamer, image tags are #GstBuffer<!-- -->s containing the raw image
+ * data, with the buffer caps describing the content type of the image
+ * (e.g. image/jpeg, image/png, text/uri-list). The buffer caps may contain
+ * an additional 'image-type' field of #GST_TYPE_TAG_IMAGE_TYPE to describe
+ * the type of image (front cover, back cover etc.). #GST_TAG_PREVIEW_IMAGE
+ * tags should not carry an image type, their type is already indicated via
+ * the special tag name.
+ *
+ * This function will do various checks and typefind the encoded image
+ * data (we can't trust the declared mime type).
+ *
+ * Returns: a newly-allocated image buffer for use in tag lists, or NULL
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBuffer *
+gst_tag_image_data_to_image_buffer (const guint8 * image_data,
+    guint image_data_len, GstTagImageType image_type)
+{
+  const gchar *name;
+
+  GstBuffer *image;
+
+  GstCaps *caps;
+
+  g_return_val_if_fail (image_data != NULL, NULL);
+  g_return_val_if_fail (image_data_len > 0, NULL);
+  g_return_val_if_fail (gst_tag_image_type_is_valid (image_type), NULL);
+
+  GST_DEBUG ("image data len: %u bytes", image_data_len);
+
+  /* allocate space for a NUL terminator for an uri too */
+  image = gst_buffer_try_new_and_alloc (image_data_len + 1);
+  if (image == NULL) {
+    GST_WARNING ("failed to allocate buffer of %d for image", image_data_len);
+    return NULL;
+  }
+
+  memcpy (GST_BUFFER_DATA (image), image_data, image_data_len);
+  GST_BUFFER_DATA (image)[image_data_len] = '\0';
+
+  /* Find GStreamer media type, can't trust declared type */
+  caps = gst_type_find_helper_for_buffer (NULL, image, NULL);
+
+  if (caps == NULL)
+    goto no_type;
+
+  GST_DEBUG ("Found GStreamer media type: %" GST_PTR_FORMAT, caps);
+
+  /* sanity check: make sure typefound/declared caps are either URI or image */
+  name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+
+  if (!g_str_has_prefix (name, "image/") &&
+      !g_str_has_prefix (name, "video/") &&
+      !g_str_equal (name, "text/uri-list")) {
+    GST_DEBUG ("Unexpected image type '%s', ignoring image frame", name);
+    goto error;
+  }
+
+  /* Decrease size by 1 if we don't have an URI list
+   * to keep the original size of the image
+   */
+  if (!g_str_equal (name, "text/uri-list"))
+    GST_BUFFER_SIZE (image) = image_data_len;
+
+  if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
+    GST_LOG ("Setting image type: %d", image_type);
+    caps = gst_caps_make_writable (caps);
+    gst_caps_set_simple (caps, "image-type", GST_TYPE_TAG_IMAGE_TYPE,
+        image_type, NULL);
+  }
+
+  gst_buffer_set_caps (image, caps);
+  gst_caps_unref (caps);
+  return image;
+
+/* ERRORS */
+no_type:
+  {
+    GST_DEBUG ("Could not determine GStreamer media type, ignoring image");
+    /* fall through */
+  }
+error:
+  {
+    if (image)
+      gst_buffer_unref (image);
+    if (caps)
+      gst_caps_unref (caps);
+    return NULL;
+  }
+}
--- a/gst_plugins_base/gst-libs/gst/video/gstvideofilter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/video/gstvideofilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -39,6 +39,8 @@
 
 #include "gstvideofilter.h"
 
+#include <gst/video/video.h>
+
 GST_DEBUG_CATEGORY_STATIC (gst_video_filter_debug);
 #define GST_CAT_DEFAULT gst_video_filter_debug
 
@@ -75,6 +77,26 @@
   return video_filter_type;
 }
 
+static gboolean
+gst_video_filter_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
+    guint * size)
+{
+  GstVideoFormat fmt;
+  gint width, height;
+
+  if (!gst_video_format_parse_caps (caps, &fmt, &width, &height)) {
+    GST_WARNING_OBJECT (btrans, "Failed to parse caps %" GST_PTR_FORMAT, caps);
+    return FALSE;
+  }
+
+  *size = gst_video_format_get_size (fmt, width, height);
+
+  GST_DEBUG_OBJECT (btrans, "Returning size %u bytes for caps %"
+      GST_PTR_FORMAT, *size, caps);
+
+  return TRUE;
+}
+
 static void
 gst_video_filter_class_init (gpointer g_class, gpointer class_data)
 {
@@ -88,6 +110,9 @@
   gstelement_class = (GstElementClass *) klass;
   trans_class = (GstBaseTransformClass *) klass;
 
+  trans_class->get_unit_size =
+      GST_DEBUG_FUNCPTR (gst_video_filter_get_unit_size);
+
   parent_class = g_type_class_peek_parent (klass);
 
   GST_DEBUG_CATEGORY_INIT (gst_video_filter_debug, "videofilter", 0,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/video/video-enumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,50 @@
+
+/* Generated data (by glib-mkenums) */
+
+#include "video-enumtypes.h"
+
+#include "video.h"
+
+/* enumerations from "video.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_video_format_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    static const GEnumValue values[] = {
+      { GST_VIDEO_FORMAT_UNKNOWN, "GST_VIDEO_FORMAT_UNKNOWN", "unknown" },
+      { GST_VIDEO_FORMAT_I420, "GST_VIDEO_FORMAT_I420", "i420" },
+      { GST_VIDEO_FORMAT_YV12, "GST_VIDEO_FORMAT_YV12", "yv12" },
+      { GST_VIDEO_FORMAT_YUY2, "GST_VIDEO_FORMAT_YUY2", "yuy2" },
+      { GST_VIDEO_FORMAT_UYVY, "GST_VIDEO_FORMAT_UYVY", "uyvy" },
+      { GST_VIDEO_FORMAT_AYUV, "GST_VIDEO_FORMAT_AYUV", "ayuv" },
+      { GST_VIDEO_FORMAT_RGBx, "GST_VIDEO_FORMAT_RGBx", "rgbx" },
+      { GST_VIDEO_FORMAT_BGRx, "GST_VIDEO_FORMAT_BGRx", "bgrx" },
+      { GST_VIDEO_FORMAT_xRGB, "GST_VIDEO_FORMAT_xRGB", "xrgb" },
+      { GST_VIDEO_FORMAT_xBGR, "GST_VIDEO_FORMAT_xBGR", "xbgr" },
+      { GST_VIDEO_FORMAT_RGBA, "GST_VIDEO_FORMAT_RGBA", "rgba" },
+      { GST_VIDEO_FORMAT_BGRA, "GST_VIDEO_FORMAT_BGRA", "bgra" },
+      { GST_VIDEO_FORMAT_ARGB, "GST_VIDEO_FORMAT_ARGB", "argb" },
+      { GST_VIDEO_FORMAT_ABGR, "GST_VIDEO_FORMAT_ABGR", "abgr" },
+      { GST_VIDEO_FORMAT_RGB, "GST_VIDEO_FORMAT_RGB", "rgb" },
+      { GST_VIDEO_FORMAT_BGR, "GST_VIDEO_FORMAT_BGR", "bgr" },
+      { GST_VIDEO_FORMAT_Y41B, "GST_VIDEO_FORMAT_Y41B", "y41b" },
+      { GST_VIDEO_FORMAT_Y42B, "GST_VIDEO_FORMAT_Y42B", "y42b" },
+      { GST_VIDEO_FORMAT_YVYU, "GST_VIDEO_FORMAT_YVYU", "yvyu" },
+      { GST_VIDEO_FORMAT_Y444, "GST_VIDEO_FORMAT_Y444", "y444" },
+      { GST_VIDEO_FORMAT_v210, "GST_VIDEO_FORMAT_v210", "v210" },
+      { GST_VIDEO_FORMAT_v216, "GST_VIDEO_FORMAT_v216", "v216" },
+      { 0, NULL, NULL }
+    };
+    GType g_define_type_id = g_enum_register_static ("GstVideoFormat", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
+
+/* Generated data ends here */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst-libs/gst/video/video-enumtypes.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,23 @@
+
+/* Generated data (by glib-mkenums) */
+
+#ifndef __GST_VIDEO_ENUM_TYPES_H__
+#define __GST_VIDEO_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* enumerations from "video.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_video_format_get_type (void);
+#define GST_TYPE_VIDEO_FORMAT (gst_video_format_get_type())
+G_END_DECLS
+
+#endif /* __GST_VIDEO_ENUM_TYPES_H__ */
+
+/* Generated data ends here */
+
--- a/gst_plugins_base/gst-libs/gst/video/video.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/video/video.c	Fri Apr 16 15:15:52 2010 +0300
@@ -45,7 +45,19 @@
     int green_mask, int blue_mask);
 
 
-/* This is simply a convenience function, nothing more or less */
+/**
+ * gst_video_frame_rate:
+ * @pad: pointer to a #GstPad
+ *
+ * A convenience function to retrieve a GValue holding the framerate
+ * from the caps on a pad.
+ * 
+ * The pad needs to have negotiated caps containing a framerate property.
+ *
+ * Returns: NULL if the pad has no configured caps or the configured caps
+ * do not contain a framerate.
+ *
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -87,11 +99,25 @@
 
   return fps;
 }
+
+/**
+ * gst_video_get_size:
+ * @pad: pointer to a #GstPad
+ * @width: pointer to integer to hold pixel width of the video frames (output)
+ * @height: pointer to integer to hold pixel height of the video frames (output)
+ *
+ * Inspect the caps of the provided pad and retrieve the width and height of
+ * the video frames it is configured for.
+ * 
+ * The pad needs to have negotiated caps containing width and height properties.
+ *
+ * Returns: TRUE if the width and height could be retrieved.
+ *
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 gboolean
 gst_video_get_size (GstPad * pad, gint * width, gint * height)
 {
@@ -206,11 +232,45 @@
 }
 
 /**
+ * gst_video_format_parse_caps_interlaced:
+ * @caps: the fixed #GstCaps to parse
+ * @interlaced: whether @caps represents interlaced video or not, may be NULL (output)
+ *
+ * Extracts whether the caps represents interlaced content or not and places it
+ * in @interlaced.
+ *
+ * Since: 0.10.23
+ *
+ * Returns: TRUE if @caps was parsed correctly.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_video_format_parse_caps_interlaced (GstCaps * caps, gboolean * interlaced)
+{
+  GstStructure *structure;
+
+  if (!gst_caps_is_fixed (caps))
+    return FALSE;
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  if (interlaced) {
+    if (!gst_structure_get_boolean (structure, "interlaced", interlaced))
+      *interlaced = FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
  * gst_video_format_parse_caps:
  * @caps: the #GstCaps to parse
  * @format: the #GstVideoFormat of the video represented by @caps (output)
- * @width: the width of the video represented by @caps (output)
- * @height: the height of the video represented by @caps (output)
+ * @width: the width of the video represented by @caps, may be NULL (output)
+ * @height: the height of the video represented by @caps, may be NULL (output)
  *
  * Determines the #GstVideoFormat of @caps and places it in the location
  * pointed to by @format.  Extracts the size of the video and places it
@@ -304,11 +364,12 @@
   return ok;
 }
 
+
 /**
  * gst_video_parse_caps_framerate:
- * @caps:
- * @fps_n: pointer to numerator of frame rate (output)
- * @fps_d: pointer to denominator of frame rate (output)
+ * @caps: pointer to a #GstCaps instance
+ * @fps_n: pointer to integer to hold numerator of frame rate (output)
+ * @fps_d: pointer to integer to hold denominator of frame rate (output)
  *
  * Extracts the frame rate from @caps and places the values in the locations
  * pointed to by @fps_n and @fps_d.  Returns TRUE if the values could be
@@ -340,7 +401,7 @@
 
 /**
  * gst_video_parse_caps_pixel_aspect_ratio:
- * @caps:
+ * @caps: pointer to a #GstCaps instance
  * @par_n: pointer to numerator of pixel aspect ratio (output)
  * @par_d: pointer to denominator of pixel aspect ratio (output)
  *
@@ -378,6 +439,43 @@
 }
 
 /**
+ * gst_video_format_new_caps_interlaced:
+ * @format: the #GstVideoFormat describing the raw video format
+ * @width: width of video
+ * @height: height of video
+ * @framerate_n: numerator of frame rate
+ * @framerate_d: denominator of frame rate
+ * @par_n: numerator of pixel aspect ratio
+ * @par_d: denominator of pixel aspect ratio
+ * @interlaced: #TRUE if the format is interlaced
+ *
+ * Creates a new #GstCaps object based on the parameters provided.
+ *
+ * Since: 0.10.23
+ *
+ * Returns: a new #GstCaps object, or NULL if there was an error
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstCaps *
+gst_video_format_new_caps_interlaced (GstVideoFormat format, int width,
+    int height, int framerate_n, int framerate_d, int par_n, int par_d,
+    gboolean interlaced)
+{
+  GstCaps *res;
+
+  res =
+      gst_video_format_new_caps (format, width, height, framerate_n,
+      framerate_d, par_n, par_d);
+  if (interlaced && (res != NULL))
+    gst_caps_set_simple (res, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
+
+  return res;
+}
+
+/**
  * gst_video_format_new_caps:
  * @format: the #GstVideoFormat describing the raw video format
  * @width: width of video
@@ -401,6 +499,9 @@
 gst_video_format_new_caps (GstVideoFormat format, int width, int height,
     int framerate_n, int framerate_d, int par_n, int par_d)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
+  g_return_val_if_fail (width > 0 && height > 0, NULL);
+
   if (gst_video_format_is_yuv (format)) {
     return gst_caps_new_simple ("video/x-raw-yuv",
         "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format),
@@ -509,6 +610,8 @@
       return GST_VIDEO_FORMAT_YV12;
     case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
       return GST_VIDEO_FORMAT_YUY2;
+    case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
+      return GST_VIDEO_FORMAT_YVYU;
     case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
       return GST_VIDEO_FORMAT_UYVY;
     case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
@@ -517,6 +620,12 @@
       return GST_VIDEO_FORMAT_Y41B;
     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
       return GST_VIDEO_FORMAT_Y42B;
+    case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
+      return GST_VIDEO_FORMAT_Y444;
+    case GST_MAKE_FOURCC ('v', '2', '1', '0'):
+      return GST_VIDEO_FORMAT_v210;
+    case GST_MAKE_FOURCC ('v', '2', '1', '6'):
+      return GST_VIDEO_FORMAT_v216;
     default:
       return GST_VIDEO_FORMAT_UNKNOWN;
   }
@@ -541,6 +650,8 @@
 guint32
 gst_video_format_to_fourcc (GstVideoFormat format)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
       return GST_MAKE_FOURCC ('I', '4', '2', '0');
@@ -548,6 +659,8 @@
       return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
     case GST_VIDEO_FORMAT_YUY2:
       return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
+    case GST_VIDEO_FORMAT_YVYU:
+      return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
     case GST_VIDEO_FORMAT_UYVY:
       return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
     case GST_VIDEO_FORMAT_AYUV:
@@ -556,12 +669,18 @@
       return GST_MAKE_FOURCC ('Y', '4', '1', 'B');
     case GST_VIDEO_FORMAT_Y42B:
       return GST_MAKE_FOURCC ('Y', '4', '2', 'B');
+    case GST_VIDEO_FORMAT_Y444:
+      return GST_MAKE_FOURCC ('Y', '4', '4', '4');
+    case GST_VIDEO_FORMAT_v210:
+      return GST_MAKE_FOURCC ('v', '2', '1', '0');
+    case GST_VIDEO_FORMAT_v216:
+      return GST_MAKE_FOURCC ('v', '2', '1', '6');
     default:
       return 0;
   }
 }
 
-/**
+/*
  * gst_video_format_from_rgb32_masks:
  * @red_mask: red bit mask
  * @green_mask: green bit mask
@@ -638,6 +757,8 @@
  * gst_video_format_is_rgb:
  * @format: a #GstVideoFormat
  *
+ * Determine whether the video format is an RGB format.
+ *
  * Since: 0.10.16
  *
  * Returns: TRUE if @format represents RGB video
@@ -653,10 +774,14 @@
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
     case GST_VIDEO_FORMAT_AYUV:
     case GST_VIDEO_FORMAT_Y41B:
     case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_v210:
+    case GST_VIDEO_FORMAT_v216:
       return FALSE;
     case GST_VIDEO_FORMAT_RGBx:
     case GST_VIDEO_FORMAT_BGRx:
@@ -678,6 +803,8 @@
  * gst_video_format_is_yuv:
  * @format: a #GstVideoFormat
  *
+ * Determine whether the video format is a YUV format.
+ *
  * Since: 0.10.16
  *
  * Returns: TRUE if @format represents YUV video
@@ -693,10 +820,14 @@
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
     case GST_VIDEO_FORMAT_AYUV:
     case GST_VIDEO_FORMAT_Y41B:
     case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_v210:
+    case GST_VIDEO_FORMAT_v216:
       return TRUE;
     case GST_VIDEO_FORMAT_RGBx:
     case GST_VIDEO_FORMAT_BGRx:
@@ -717,6 +848,9 @@
 /**
  * gst_video_format_has_alpha:
  * @format: a #GstVideoFormat
+ * 
+ * Returns TRUE or FALSE depending on if the video format provides an
+ * alpha channel.
  *
  * Since: 0.10.16
  *
@@ -733,9 +867,13 @@
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
     case GST_VIDEO_FORMAT_Y41B:
     case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_v210:
+    case GST_VIDEO_FORMAT_v216:
       return FALSE;
     case GST_VIDEO_FORMAT_AYUV:
     case GST_VIDEO_FORMAT_RGBA:
@@ -781,6 +919,10 @@
 gst_video_format_get_row_stride (GstVideoFormat format, int component,
     int width)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (component >= 0 && component <= 3, 0);
+  g_return_val_if_fail (width > 0, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
@@ -790,6 +932,7 @@
         return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
       }
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
       return GST_ROUND_UP_4 (width * 2);
     case GST_VIDEO_FORMAT_AYUV:
@@ -817,6 +960,12 @@
       } else {
         return GST_ROUND_UP_8 (width) / 2;
       }
+    case GST_VIDEO_FORMAT_Y444:
+      return GST_ROUND_UP_4 (width);
+    case GST_VIDEO_FORMAT_v210:
+      return ((width + 47) / 48) * 128;
+    case GST_VIDEO_FORMAT_v216:
+      return GST_ROUND_UP_8 (width * 4);
     default:
       return 0;
   }
@@ -843,13 +992,18 @@
 int
 gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (component >= 0 && component <= 3, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_Y41B:
     case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_Y444:
       return 1;
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
       if (component == 0) {
         return 2;
@@ -869,6 +1023,15 @@
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
       return 3;
+    case GST_VIDEO_FORMAT_v210:
+      /* v210 is packed at the bit level, so pixel stride doesn't make sense */
+      return 0;
+    case GST_VIDEO_FORMAT_v216:
+      if (component == 0) {
+        return 4;
+      } else {
+        return 8;
+      }
     default:
       return 0;
   }
@@ -896,27 +1059,29 @@
 gst_video_format_get_component_width (GstVideoFormat format, int component,
     int width)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (component >= 0 && component <= 3, 0);
+  g_return_val_if_fail (width > 0, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_v210:
+    case GST_VIDEO_FORMAT_v216:
       if (component == 0) {
         return width;
       } else {
         return GST_ROUND_UP_2 (width) / 2;
       }
-    case GST_VIDEO_FORMAT_Y41B:        /* CHECKME: component_width for Y41B */
+    case GST_VIDEO_FORMAT_Y41B:
       if (component == 0) {
         return width;
       } else {
-        return GST_ROUND_UP_8 (width) / 4;
-      }
-    case GST_VIDEO_FORMAT_Y42B:        /* CHECKME: component_width for Y42B */
-      if (component == 0) {
-        return width;
-      } else {
-        return GST_ROUND_UP_8 (width) / 2;
+        return GST_ROUND_UP_4 (width) / 4;
       }
     case GST_VIDEO_FORMAT_AYUV:
     case GST_VIDEO_FORMAT_RGBx:
@@ -929,6 +1094,7 @@
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_Y444:
       return width;
     default:
       return 0;
@@ -957,6 +1123,10 @@
 gst_video_format_get_component_height (GstVideoFormat format, int component,
     int height)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (component >= 0 && component <= 3, 0);
+  g_return_val_if_fail (height > 0, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
@@ -968,6 +1138,7 @@
     case GST_VIDEO_FORMAT_Y41B:
     case GST_VIDEO_FORMAT_Y42B:
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
     case GST_VIDEO_FORMAT_AYUV:
     case GST_VIDEO_FORMAT_RGBx:
@@ -980,6 +1151,9 @@
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_v210:
+    case GST_VIDEO_FORMAT_v216:
       return height;
     default:
       return 0;
@@ -1012,6 +1186,10 @@
 gst_video_format_get_component_offset (GstVideoFormat format, int component,
     int width, int height)
 {
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (component >= 0 && component <= 3, 0);
+  g_return_val_if_fail (width > 0 && height > 0, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
       if (component == 0)
@@ -1043,6 +1221,14 @@
       if (component == 2)
         return 3;
       return 0;
+    case GST_VIDEO_FORMAT_YVYU:
+      if (component == 0)
+        return 0;
+      if (component == 1)
+        return 3;
+      if (component == 2)
+        return 1;
+      return 0;
     case GST_VIDEO_FORMAT_UYVY:
       if (component == 0)
         return 1;
@@ -1137,6 +1323,19 @@
       if (component == 2)
         return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height;
       return 0;
+    case GST_VIDEO_FORMAT_Y444:
+      return GST_ROUND_UP_4 (width) * height * component;
+    case GST_VIDEO_FORMAT_v210:
+      /* v210 is bit-packed, so this doesn't make sense */
+      return 0;
+    case GST_VIDEO_FORMAT_v216:
+      if (component == 0)
+        return 0;
+      if (component == 1)
+        return 2;
+      if (component == 2)
+        return 6;
+      return 0;
     default:
       return 0;
   }
@@ -1164,6 +1363,9 @@
 {
   int size;
 
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (width > 0 && height > 0, 0);
+
   switch (format) {
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
@@ -1172,6 +1374,7 @@
           (GST_ROUND_UP_2 (height) / 2) * 2;
       return size;
     case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_YVYU:
     case GST_VIDEO_FORMAT_UYVY:
       return GST_ROUND_UP_4 (width * 2) * height;
     case GST_VIDEO_FORMAT_AYUV:
@@ -1193,6 +1396,12 @@
     case GST_VIDEO_FORMAT_Y42B:
       /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h: */
       return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height;
+    case GST_VIDEO_FORMAT_Y444:
+      return GST_ROUND_UP_4 (width) * height * 3;
+    case GST_VIDEO_FORMAT_v210:
+      return ((width + 47) / 48) * 128 * height;
+    case GST_VIDEO_FORMAT_v216:
+      return GST_ROUND_UP_8 (width * 4) * height;
     default:
       return 0;
   }
@@ -1232,6 +1441,9 @@
   gboolean ret = FALSE;
   int size;
 
+  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0);
+  g_return_val_if_fail (width > 0 && height > 0, 0);
+
   size = gst_video_format_get_size (format, width, height);
 
   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
--- a/gst_plugins_base/gst-libs/gst/video/video.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/video/video.h	Fri Apr 16 15:15:52 2010 +0300
@@ -25,26 +25,32 @@
 
 G_BEGIN_DECLS
 
+#include <gst/video/video-enumtypes.h>
+
 /**
  * GstVideoFormat:
- * @GST_VIDEO_FORMAT_UNKNOWN,
+ * @GST_VIDEO_FORMAT_UNKNOWN: Unknown or unset video format id
  * @GST_VIDEO_FORMAT_I420: planar 4:2:0 YUV
  * @GST_VIDEO_FORMAT_YV12: planar 4:2:0 YVU (like I420 but UV planes swapped)
  * @GST_VIDEO_FORMAT_YUY2: packed 4:2:2 YUV (Y0-U0-Y1-V0 Y2-U2-Y3-V2 Y4 ...)
  * @GST_VIDEO_FORMAT_UYVY: packed 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...) 
  * @GST_VIDEO_FORMAT_AYUV: packed 4:4:4 YUV with alpha channel (A0-Y0-U0-V0 ...)
- * @GST_VIDEO_FORMAT_RGBx:
- * @GST_VIDEO_FORMAT_BGRx:
- * @GST_VIDEO_FORMAT_xRGB:
- * @GST_VIDEO_FORMAT_xBGR:
- * @GST_VIDEO_FORMAT_RGBA:
- * @GST_VIDEO_FORMAT_BGRA:
- * @GST_VIDEO_FORMAT_ARGB:
- * @GST_VIDEO_FORMAT_ABGR:
- * @GST_VIDEO_FORMAT_RGB:
- * @GST_VIDEO_FORMAT_BGR:
+ * @GST_VIDEO_FORMAT_RGBx: sparse rgb packed into 32 bit, space last
+ * @GST_VIDEO_FORMAT_BGRx: sparse reverse rgb packed into 32 bit, space last
+ * @GST_VIDEO_FORMAT_xRGB: sparse rgb packed into 32 bit, space first
+ * @GST_VIDEO_FORMAT_xBGR: sparse reverse rgb packed into 32 bit, space first
+ * @GST_VIDEO_FORMAT_RGBA: rgb with alpha channel last
+ * @GST_VIDEO_FORMAT_BGRA: reverse rgb with alpha channel last
+ * @GST_VIDEO_FORMAT_ARGB: rgb with alpha channel first
+ * @GST_VIDEO_FORMAT_ABGR: reverse rgb with alpha channel first
+ * @GST_VIDEO_FORMAT_RGB: rgb
+ * @GST_VIDEO_FORMAT_BGR: reverse rgb
  * @GST_VIDEO_FORMAT_Y41B: planar 4:1:1 YUV (Since: 0.10.18)
  * @GST_VIDEO_FORMAT_Y42B: planar 4:2:2 YUV (Since: 0.10.18)
+ * @GST_VIDEO_FORMAT_YVYU: packed 4:2:2 YUV (Y0-V0-Y1-U0 Y2-V2-Y3-U2 Y4 ...) (Since: 0.10.23)
+ * @GST_VIDEO_FORMAT_Y444: planar 4:4:4 YUV (Since: 0.10.24)
+ * @GST_VIDEO_FORMAT_v210: packed 4:2:2 10-bit YUV, complex format (Since: 0.10.24)
+ * @GST_VIDEO_FORMAT_v216: packed 4:2:2 16-bit YUV, Y0-U0-Y1-V1 order (Since: 0.10.24)
  *
  * Enum value describing the most common video formats.
  */
@@ -66,7 +72,11 @@
   GST_VIDEO_FORMAT_RGB,
   GST_VIDEO_FORMAT_BGR,
   GST_VIDEO_FORMAT_Y41B,
-  GST_VIDEO_FORMAT_Y42B
+  GST_VIDEO_FORMAT_Y42B,
+  GST_VIDEO_FORMAT_YVYU,
+  GST_VIDEO_FORMAT_Y444,
+  GST_VIDEO_FORMAT_v210,
+  GST_VIDEO_FORMAT_v216
 } GstVideoFormat;
 
 #define GST_VIDEO_BYTE1_MASK_32  "0xFF000000"
@@ -227,6 +237,38 @@
         "height = " GST_VIDEO_SIZE_RANGE ", "                           \
         "framerate = " GST_VIDEO_FPS_RANGE
 
+/* buffer flags */
+
+/**
+ * GST_VIDEO_BUFFER_TFF:
+ *
+ * If the #GstBuffer is interlaced, then the first field in the video frame is
+ * the top field.  If unset, the bottom field is first.
+ *
+ * Since: 0.10.23
+ */
+#define GST_VIDEO_BUFFER_TFF GST_BUFFER_FLAG_MEDIA1
+
+/**
+ * GST_VIDEO_BUFFER_RFF:
+ *
+ * If the #GstBuffer is interlaced, then the first field (as defined by the
+ * %GST_VIDEO_BUFFER_TFF flag setting) is repeated.
+ *
+ * Since: 0.10.23
+ */
+#define GST_VIDEO_BUFFER_RFF GST_BUFFER_FLAG_MEDIA2
+
+/**
+ * GST_VIDEO_BUFFER_ONEFIELD:
+ *
+ * If the #GstBuffer is interlaced, then only the first field (as defined by the
+ * %GST_VIDEO_BUFFER_TFF flag setting) is to be displayed.
+ *
+ * Since: 0.10.23
+ */
+#define GST_VIDEO_BUFFER_ONEFIELD GST_BUFFER_FLAG_MEDIA3
+
 /* functions */
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -260,6 +302,11 @@
 IMPORT_C
 #endif
 
+gboolean gst_video_format_parse_caps_interlaced (GstCaps *caps, gboolean *interlaced);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 gboolean gst_video_parse_caps_framerate (GstCaps *caps,
     int *fps_n, int *fps_d);
 #ifdef __SYMBIAN32__
@@ -279,6 +326,13 @@
 IMPORT_C
 #endif
 
+GstCaps * gst_video_format_new_caps_interlaced (GstVideoFormat format,
+    int width, int height, int framerate_n, int framerate_d,
+						int par_n, int par_d, gboolean interlaced);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstVideoFormat gst_video_format_from_fourcc (guint32 fourcc);
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst/adder/gstadder.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/adder/gstadder.c	Fri Apr 16 15:15:52 2010 +0300
@@ -23,22 +23,17 @@
 /**
  * SECTION:element-adder
  *
+ * The adder allows to mix several streams into one by adding the data.
+ * Mixed data is clamped to the min/max values of the data format.
+ *
+ * The adder currently mixes all data received on the sinkpads as soon as
+ * possible without trying to synchronize the streams.
+ *
  * <refsect2>
- * <para>
- * The Adder allows to mix several streams into one by adding the data.
- * Mixed data is clamped to the min/max values of the data format.
- * </para>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch audiotestsrc freq=100 ! adder name=mix ! audioconvert ! alsasink audiotestsrc freq=500 ! mix.
- * </programlisting>
- * This pipeline produces two sine waves mixed together.
- * </para>
- * <para>
- * The Adder currently mixes all data received on the sinkpads as soon as possible
- * without trying to synchronize the streams.
- * </para>
+ * ]| This pipeline produces two sine waves mixed together.
  * </refsect2>
  *
  * Last reviewed on 2006-05-09 (0.10.7)
@@ -51,10 +46,7 @@
 #include "gstadder.h"
 #include <gst/audio/audio.h>
 #include <string.h>             /* strcmp */
-
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
+/*#include <liboil/liboil.h>*/
 
 /* highest positive/lowest negative x-bit value we can use for clamping */
 #define MAX_INT_32  ((gint32) (0x7fffffff))
@@ -71,34 +63,66 @@
 #define MIN_UINT_16 ((guint16)(0x0000))
 #define MIN_UINT_8  ((guint8) (0x00))
 
+enum
+{
+  PROP_0,
+  PROP_FILTER_CAPS
+};
+
 #define GST_CAT_DEFAULT gst_adder_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
 /* elementfactory information */
-static const GstElementDetails adder_details = GST_ELEMENT_DETAILS ("Adder",
-    "Generic/Audio",
-    "Add N audio channels together",
-    "Thomas <thomas@apestaart.org>");
+
+#define CAPS \
+  "audio/x-raw-int, " \
+  "rate = (int) [ 1, MAX ], " \
+  "channels = (int) [ 1, MAX ], " \
+  "endianness = (int) BYTE_ORDER, " \
+  "width = (int) 32, " \
+  "depth = (int) 32, " \
+  "signed = (boolean) { true, false } ;" \
+  "audio/x-raw-int, " \
+  "rate = (int) [ 1, MAX ], " \
+  "channels = (int) [ 1, MAX ], " \
+  "endianness = (int) BYTE_ORDER, " \
+  "width = (int) 16, " \
+  "depth = (int) 16, " \
+  "signed = (boolean) { true, false } ;" \
+  "audio/x-raw-int, " \
+  "rate = (int) [ 1, MAX ], " \
+  "channels = (int) [ 1, MAX ], " \
+  "endianness = (int) BYTE_ORDER, " \
+  "width = (int) 8, " \
+  "depth = (int) 8, " \
+  "signed = (boolean) { true, false } ;" \
+  "audio/x-raw-float, " \
+  "rate = (int) [ 1, MAX ], " \
+  "channels = (int) [ 1, MAX ], " \
+  "endianness = (int) BYTE_ORDER, " \
+  "width = (int) { 32, 64 }"
 
 static GstStaticPadTemplate gst_adder_src_template =
-    GST_STATIC_PAD_TEMPLATE ("src",
+GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
-        GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS)
+    GST_STATIC_CAPS (CAPS)
     );
 
 static GstStaticPadTemplate gst_adder_sink_template =
-    GST_STATIC_PAD_TEMPLATE ("sink%d",
+GST_STATIC_PAD_TEMPLATE ("sink%d",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
-    GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
-        GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS)
+    GST_STATIC_CAPS (CAPS)
     );
 
 static void gst_adder_class_init (GstAdderClass * klass);
 static void gst_adder_init (GstAdder * adder);
-static void gst_adder_finalize (GObject * object);
+static void gst_adder_dispose (GObject * object);
+static void gst_adder_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_adder_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
 static gboolean gst_adder_setcaps (GstPad * pad, GstCaps * caps);
 static gboolean gst_adder_query (GstPad * pad, GstQuery * query);
@@ -142,34 +166,70 @@
   return adder_type;
 }
 
-/* clipping versions */
+/* clipping versions (for int)
+ * FIXME: what about: oil_add_s16 (out, out, in, bytes / sizeof (type))
+ */
 #define MAKE_FUNC(name,type,ttype,min,max)                      \
 static void name (type *out, type *in, gint bytes) {            \
   gint i;                                                       \
+  ttype add;                                                    \
+  for (i = 0; i < bytes / sizeof (type); i++) {                 \
+    add = (ttype)out[i] + (ttype)in[i];                         \
+    out[i] = CLAMP (add, min, max);                             \
+  }                                                             \
+}
+
+/* unsigned versions (for int) */
+#define MAKE_FUNC_US(name,type,ttype,max)                       \
+static void name (type *out, type *in, gint bytes) {            \
+  gint i;                                                       \
+  ttype add;                                                    \
+  for (i = 0; i < bytes / sizeof (type); i++) {                 \
+    add = (ttype)out[i] + (ttype)in[i];                         \
+    out[i] = ((add <= max) ? add : max);                        \
+  }                                                             \
+}
+
+/* non-clipping versions (for float) */
+#define MAKE_FUNC_NC(name,type)                                 \
+static void name (type *out, type *in, gint bytes) {            \
+  gint i;                                                       \
   for (i = 0; i < bytes / sizeof (type); i++)                   \
-    out[i] = CLAMP ((ttype)out[i] + (ttype)in[i], min, max);    \
+    out[i] += in[i];                                            \
 }
 
-/* non-clipping versions (for float) */
-#define MAKE_FUNC_NC(name,type,ttype)                           \
-static void name (type *out, type *in, gint bytes) {            \
-  gint i;                                                       \
-  for (i = 0; i < bytes / sizeof (type); i++)                   \
-    out[i] = (ttype)out[i] + (ttype)in[i];                      \
+#if 0
+/* right now, the liboil function don't seems to be faster on x86
+ * time gst-launch audiotestsrc num-buffers=50000 ! audio/x-raw-float ! adder name=m ! fakesink audiotestsrc num-buffers=50000 ! audio/x-raw-float ! m.
+ * time gst-launch audiotestsrc num-buffers=50000 ! audio/x-raw-float,width=32 ! adder name=m ! fakesink audiotestsrc num-buffers=50000 ! audio/x-raw-float,width=32 ! m.
+ */
+static void
+add_float32 (gfloat * out, gfloat * in, gint bytes)
+{
+  oil_add_f32 (out, out, in, bytes / sizeof (gfloat));
 }
 
+static void
+add_float64 (gdouble * out, gdouble * in, gint bytes)
+{
+  oil_add_f64 (out, out, in, bytes / sizeof (gdouble));
+}
+#endif
+
 /* *INDENT-OFF* */
 MAKE_FUNC (add_int32, gint32, gint64, MIN_INT_32, MAX_INT_32)
 MAKE_FUNC (add_int16, gint16, gint32, MIN_INT_16, MAX_INT_16)
 MAKE_FUNC (add_int8, gint8, gint16, MIN_INT_8, MAX_INT_8)
-MAKE_FUNC (add_uint32, guint32, guint64, MIN_UINT_32, MAX_UINT_32)
-MAKE_FUNC (add_uint16, guint16, guint32, MIN_UINT_16, MAX_UINT_16)
-MAKE_FUNC (add_uint8, guint8, guint16, MIN_UINT_8, MAX_UINT_8)
-MAKE_FUNC_NC (add_float64, gdouble, gdouble)
-MAKE_FUNC_NC (add_float32, gfloat, gfloat)
+MAKE_FUNC_US (add_uint32, guint32, guint64, MAX_UINT_32)
+MAKE_FUNC_US (add_uint16, guint16, guint32, MAX_UINT_16)
+MAKE_FUNC_US (add_uint8, guint8, guint16, MAX_UINT_8)
+MAKE_FUNC_NC (add_float64, gdouble)
+MAKE_FUNC_NC (add_float32, gfloat)
 /* *INDENT-ON* */
 
-/* we can only accept caps that we and downstream can handle. */
+/* we can only accept caps that we and downstream can handle.
+ * if we have filtercaps set, use those to constrain the target caps.
+ */
 static GstCaps *
 gst_adder_sink_getcaps (GstPad * pad)
 {
@@ -181,10 +241,17 @@
   GST_OBJECT_LOCK (adder);
   /* get the downstream possible caps */
   peercaps = gst_pad_peer_get_caps (adder->srcpad);
+
   /* get the allowed caps on this sinkpad, we use the fixed caps function so
    * that it does not call recursively in this function. */
   sinkcaps = gst_pad_get_fixed_caps_func (pad);
   if (peercaps) {
+    /* restrict with filter-caps if any */
+    if (adder->filter_caps) {
+      result = gst_caps_intersect (peercaps, adder->filter_caps);
+      gst_caps_unref (peercaps);
+      peercaps = result;
+    }
     /* if the peer has caps, intersect */
     GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
     result = gst_caps_intersect (peercaps, sinkcaps);
@@ -198,12 +265,15 @@
   }
   GST_OBJECT_UNLOCK (adder);
 
+  GST_LOG_OBJECT (adder, "getting caps on pad %p,%s to %" GST_PTR_FORMAT, pad,
+      GST_PAD_NAME (pad), result);
+
   return result;
 }
 
 /* the first caps we receive on any of the sinkpads will define the caps for all
  * the other sinkpads because we can only mix streams with the same caps.
- * */
+ */
 static gboolean
 gst_adder_setcaps (GstPad * pad, GstCaps * caps)
 {
@@ -235,13 +305,15 @@
   structure = gst_caps_get_structure (caps, 0);
   media_type = gst_structure_get_name (structure);
   if (strcmp (media_type, "audio/x-raw-int") == 0) {
-    GST_DEBUG_OBJECT (adder, "parse_caps sets adder to format int");
     adder->format = GST_ADDER_FORMAT_INT;
     gst_structure_get_int (structure, "width", &adder->width);
     gst_structure_get_int (structure, "depth", &adder->depth);
     gst_structure_get_int (structure, "endianness", &adder->endianness);
     gst_structure_get_boolean (structure, "signed", &adder->is_signed);
 
+    GST_INFO_OBJECT (pad, "parse_caps sets adder to format int, %d bit",
+        adder->width);
+
     if (adder->endianness != G_BYTE_ORDER)
       goto not_supported;
 
@@ -262,9 +334,15 @@
         goto not_supported;
     }
   } else if (strcmp (media_type, "audio/x-raw-float") == 0) {
-    GST_DEBUG_OBJECT (adder, "parse_caps sets adder to format float");
     adder->format = GST_ADDER_FORMAT_FLOAT;
     gst_structure_get_int (structure, "width", &adder->width);
+    gst_structure_get_int (structure, "endianness", &adder->endianness);
+
+    GST_INFO_OBJECT (pad, "parse_caps sets adder to format float, %d bit",
+        adder->width);
+
+    if (adder->endianness != G_BYTE_ORDER)
+      goto not_supported;
 
     switch (adder->width) {
       case 32:
@@ -330,6 +408,7 @@
   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
   while (!done) {
     GstIteratorResult ires;
+
     gpointer item;
 
     ires = gst_iterator_next (it, &item);
@@ -340,6 +419,7 @@
       case GST_ITERATOR_OK:
       {
         GstPad *pad = GST_PAD_CAST (item);
+
         gint64 duration;
 
         /* ask sink peer for duration */
@@ -355,11 +435,13 @@
           else if (duration > max)
             max = duration;
         }
+        gst_object_unref (pad);
         break;
       }
       case GST_ITERATOR_RESYNC:
         max = -1;
         res = TRUE;
+        gst_iterator_resync (it);
         break;
       default:
         res = FALSE;
@@ -371,6 +453,8 @@
 
   if (res) {
     /* and store the max */
+    GST_DEBUG_OBJECT (adder, "Total duration in format %s: %"
+        GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max));
     gst_query_set_duration (query, format, max);
   }
 
@@ -378,6 +462,91 @@
 }
 
 static gboolean
+gst_adder_query_latency (GstAdder * adder, GstQuery * query)
+{
+  GstClockTime min, max;
+  gboolean live;
+  gboolean res;
+  GstIterator *it;
+  gboolean done;
+
+  res = TRUE;
+  done = FALSE;
+
+  live = FALSE;
+  min = 0;
+  max = GST_CLOCK_TIME_NONE;
+
+  /* Take maximum of all latency values */
+  it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
+  while (!done) {
+    GstIteratorResult ires;
+
+    gpointer item;
+
+    ires = gst_iterator_next (it, &item);
+    switch (ires) {
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+      case GST_ITERATOR_OK:
+      {
+        GstPad *pad = GST_PAD_CAST (item);
+        GstQuery *peerquery;
+        GstClockTime min_cur, max_cur;
+        gboolean live_cur;
+
+        peerquery = gst_query_new_latency ();
+
+        /* Ask peer for latency */
+        res &= gst_pad_peer_query (pad, peerquery);
+
+        /* take max from all valid return values */
+        if (res) {
+          gst_query_parse_latency (peerquery, &live_cur, &min_cur, &max_cur);
+
+          if (min_cur > min)
+            min = min_cur;
+
+          if (max_cur != GST_CLOCK_TIME_NONE &&
+              ((max != GST_CLOCK_TIME_NONE && max_cur > max) ||
+                  (max == GST_CLOCK_TIME_NONE)))
+            max = max_cur;
+
+          live = live || live_cur;
+        }
+
+        gst_query_unref (peerquery);
+        gst_object_unref (pad);
+        break;
+      }
+      case GST_ITERATOR_RESYNC:
+        live = FALSE;
+        min = 0;
+        max = GST_CLOCK_TIME_NONE;
+        res = TRUE;
+        gst_iterator_resync (it);
+        break;
+      default:
+        res = FALSE;
+        done = TRUE;
+        break;
+    }
+  }
+  gst_iterator_free (it);
+
+  if (res) {
+    /* store the results */
+    GST_DEBUG_OBJECT (adder, "Calculated total latency: live %s, min %"
+        GST_TIME_FORMAT ", max %" GST_TIME_FORMAT,
+        (live ? "yes" : "no"), GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+    gst_query_set_latency (query, live, min, max);
+  }
+
+  return res;
+}
+
+static gboolean
 gst_adder_query (GstPad * pad, GstQuery * query)
 {
   GstAdder *adder = GST_ADDER (gst_pad_get_parent (pad));
@@ -408,6 +577,9 @@
     case GST_QUERY_DURATION:
       res = gst_adder_query_duration (adder, query);
       break;
+    case GST_QUERY_LATENCY:
+      res = gst_adder_query_latency (adder, query);
+      break;
     default:
       /* FIXME, needs a custom query handler because we have multiple
        * sinkpads */
@@ -419,20 +591,34 @@
   return res;
 }
 
+typedef struct
+{
+  GstEvent *event;
+  gboolean flush;
+} EventData;
+
 static gboolean
-forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
+forward_event_func (GstPad * pad, GValue * ret, EventData * data)
 {
+  GstEvent *event = data->event;
+
   gst_event_ref (event);
   GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event));
   if (!gst_pad_push_event (pad, event)) {
     g_value_set_boolean (ret, FALSE);
     GST_WARNING_OBJECT (pad, "Sending event  %p (%s) failed.",
         event, GST_EVENT_TYPE_NAME (event));
+    /* quick hack to unflush the pads, ideally we need a way to just unflush
+     * this single collect pad */
+    if (data->flush)
+      gst_pad_send_event (pad, gst_event_new_flush_stop ());
   } else {
     GST_LOG_OBJECT (pad, "Sent event  %p (%s).",
         event, GST_EVENT_TYPE_NAME (event));
   }
   gst_object_unref (pad);
+
+  /* continue on other pads, even if one failed */
   return TRUE;
 }
 
@@ -443,27 +629,48 @@
  * sinkpads.
  */
 static gboolean
-forward_event (GstAdder * adder, GstEvent * event)
+forward_event (GstAdder * adder, GstEvent * event, gboolean flush)
 {
   gboolean ret;
   GstIterator *it;
+  GstIteratorResult ires;
   GValue vret = { 0 };
+  EventData data;
 
   GST_LOG_OBJECT (adder, "Forwarding event %p (%s)", event,
       GST_EVENT_TYPE_NAME (event));
 
   ret = TRUE;
+  data.event = event;
+  data.flush = flush;
 
   g_value_init (&vret, G_TYPE_BOOLEAN);
   g_value_set_boolean (&vret, TRUE);
   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
-  gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret,
-      event);
+  while (TRUE) {
+    ires = gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func,
+        &vret, &data);
+    switch (ires) {
+      case GST_ITERATOR_RESYNC:
+        GST_WARNING ("resync");
+        gst_iterator_resync (it);
+        g_value_set_boolean (&vret, TRUE);
+        break;
+      case GST_ITERATOR_OK:
+      case GST_ITERATOR_DONE:
+        ret = g_value_get_boolean (&vret);
+        goto done;
+      default:
+        ret = FALSE;
+        goto done;
+    }
+  }
+done:
   gst_iterator_free (it);
+  GST_LOG_OBJECT (adder, "Forwarded event %p (%s), ret=%d", event,
+      GST_EVENT_TYPE_NAME (event), ret);
   gst_event_unref (event);
 
-  ret = g_value_get_boolean (&vret);
-
   return ret;
 }
 
@@ -476,22 +683,21 @@
   adder = GST_ADDER (gst_pad_get_parent (pad));
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_QOS:
-      /* QoS might be tricky */
-      result = FALSE;
-      break;
     case GST_EVENT_SEEK:
     {
       GstSeekFlags flags;
       GstSeekType curtype;
       gint64 cur;
+      gboolean flush;
 
       /* parse the seek parameters */
       gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype,
           &cur, NULL, NULL);
 
+      flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH;
+
       /* check if we are flushing */
-      if (flags & GST_SEEK_FLAG_FLUSH) {
+      if (flush) {
         /* make sure we accept nothing anymore and return WRONG_STATE */
         gst_collect_pads_set_flushing (adder->collect, TRUE);
 
@@ -499,27 +705,56 @@
          * when all pads received a FLUSH_STOP. */
         gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ());
       }
+      GST_DEBUG_OBJECT (adder, "handling seek event: %" GST_PTR_FORMAT, event);
 
       /* now wait for the collected to be finished and mark a new
-       * segment */
+       * segment. After we have the lock, no collect function is running and no
+       * new collect function will be called for as long as we're flushing. */
       GST_OBJECT_LOCK (adder->collect);
       if (curtype == GST_SEEK_TYPE_SET)
         adder->segment_position = cur;
       else
         adder->segment_position = 0;
+      /* make sure we push a new segment, to inform about new basetime
+       * see FIXME in gst_adder_collected() */
       adder->segment_pending = TRUE;
+      if (flush) {
+        /* Yes, we need to call _set_flushing again *WHEN* the streaming threads
+         * have stopped so that the cookie gets properly updated. */
+        gst_collect_pads_set_flushing (adder->collect, TRUE);
+      }
+      /* we might have a pending flush_stop event now. This event will either be
+       * sent by an upstream element when it completes the seek or we will push
+       * one in the collected callback ourself */
+      adder->flush_stop_pending = flush;
       GST_OBJECT_UNLOCK (adder->collect);
+      GST_DEBUG_OBJECT (adder, "forwarding seek event: %" GST_PTR_FORMAT,
+          event);
 
-      result = forward_event (adder, event);
+      result = forward_event (adder, event, flush);
+      if (!result) {
+        /* seek failed. maybe source is a live source. */
+        GST_DEBUG_OBJECT (adder, "seeking failed");
+      }
+      /* FIXME: ideally we would like to send a flush-stop event from here but
+       * collectpads does not have a method that allows us to do that. Instead
+       * we forward all flush-stop events we receive on the sinkpads. We might
+       * be sending too many flush-stop events. */
       break;
     }
+    case GST_EVENT_QOS:
+      /* QoS might be tricky */
+      result = FALSE;
+      break;
     case GST_EVENT_NAVIGATION:
       /* navigation is rather pointless. */
       result = FALSE;
       break;
     default:
       /* just forward the rest for now */
-      result = forward_event (adder, event);
+      GST_DEBUG_OBJECT (adder, "forward unhandled event: %s",
+          GST_EVENT_TYPE_NAME (event));
+      result = forward_event (adder, event, FALSE);
       break;
   }
   gst_object_unref (adder);
@@ -531,7 +766,7 @@
 gst_adder_sink_event (GstPad * pad, GstEvent * event)
 {
   GstAdder *adder;
-  gboolean ret;
+  gboolean ret = TRUE;
 
   adder = GST_ADDER (gst_pad_get_parent (pad));
 
@@ -540,14 +775,30 @@
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_STOP:
-      /* mark a pending new segment. This event is synchronized
-       * with the streaming thread so we can safely update the
-       * variable without races. It's somewhat weird because we
-       * assume the collectpads forwarded the FLUSH_STOP past us
-       * and downstream (using our source pad, the bastard!).
+      /* we received a flush-stop. The collect_event function will push the
+       * event past our element. We simply forward all flush-stop events, even
+       * when no flush-stop was pendingk, this is required because collectpads
+       * does not provide an API to handle-but-not-forward the flush-stop.
+       * We unset the pending flush-stop flag so that we don't send anymore
+       * flush-stop from the collect function later.
        */
+      GST_OBJECT_LOCK (adder->collect);
       adder->segment_pending = TRUE;
+      adder->flush_stop_pending = FALSE;
+      /* Clear pending tags */
+      if (adder->pending_events) {
+        g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL);
+        g_list_free (adder->pending_events);
+        adder->pending_events = NULL;
+      }
+      GST_OBJECT_UNLOCK (adder->collect);
       break;
+    case GST_EVENT_TAG:
+      GST_OBJECT_LOCK (adder->collect);
+      /* collectpads is a pile of horse manure. */
+      adder->pending_events = g_list_append (adder->pending_events, event);
+      GST_OBJECT_UNLOCK (adder->collect);
+      goto beach;
     default:
       break;
   }
@@ -555,6 +806,7 @@
   /* now GstCollectPads can take care of the rest, e.g. EOS */
   ret = adder->collect_event (pad, event);
 
+beach:
   gst_object_unref (adder);
   return ret;
 }
@@ -562,26 +814,40 @@
 static void
 gst_adder_class_init (GstAdderClass * klass)
 {
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstElementClass *gstelement_class = (GstElementClass *) klass;
 
-  gobject_class = (GObjectClass *) klass;
-
-  gobject_class->finalize = gst_adder_finalize;
-
-  gstelement_class = (GstElementClass *) klass;
+  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_adder_set_property);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_adder_get_property);
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_adder_dispose);
 
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&gst_adder_src_template));
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&gst_adder_sink_template));
-  gst_element_class_set_details (gstelement_class, &adder_details);
+  gst_element_class_set_details_simple (gstelement_class, "Adder",
+      "Generic/Audio",
+      "Add N audio channels together",
+      "Thomas Vander Stichele <thomas at apestaart dot org>");
 
   parent_class = g_type_class_peek_parent (klass);
 
-  gstelement_class->request_new_pad = gst_adder_request_new_pad;
-  gstelement_class->release_pad = gst_adder_release_pad;
-  gstelement_class->change_state = gst_adder_change_state;
+  /**
+   * GstAdder:caps:
+   *
+   * Since: 0.10.24
+   */
+  g_object_class_install_property (gobject_class, PROP_FILTER_CAPS,
+      g_param_spec_boxed ("caps", "Target caps",
+          "Set target format for mixing (NULL means ANY). "
+          "Setting this property takes a reference to the supplied GstCaps "
+          "object.", GST_TYPE_CAPS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gstelement_class->request_new_pad =
+      GST_DEBUG_FUNCPTR (gst_adder_request_new_pad);
+  gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_adder_release_pad);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_adder_change_state);
 }
 
 static void
@@ -592,6 +858,7 @@
   template = gst_static_pad_template_get (&gst_adder_src_template);
   adder->srcpad = gst_pad_new_from_template (template, "src");
   gst_object_unref (template);
+
   gst_pad_set_getcaps_function (adder->srcpad,
       GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
   gst_pad_set_setcaps_function (adder->srcpad,
@@ -606,6 +873,8 @@
   adder->padcount = 0;
   adder->func = NULL;
 
+  adder->filter_caps = gst_caps_new_any ();
+
   /* keep track of the sinkpads requested */
   adder->collect = gst_collect_pads_new ();
   gst_collect_pads_set_function (adder->collect,
@@ -613,16 +882,78 @@
 }
 
 static void
-gst_adder_finalize (GObject * object)
+gst_adder_dispose (GObject * object)
+{
+  GstAdder *adder = GST_ADDER (object);
+
+  if (adder->collect) {
+    gst_object_unref (adder->collect);
+    adder->collect = NULL;
+  }
+  gst_caps_replace (&adder->filter_caps, NULL);
+  if (adder->pending_events) {
+    g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL);
+    g_list_free (adder->pending_events);
+    adder->pending_events = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_adder_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
 {
   GstAdder *adder = GST_ADDER (object);
 
-  gst_object_unref (adder->collect);
-  adder->collect = NULL;
+  switch (prop_id) {
+    case PROP_FILTER_CAPS:{
+      GstCaps *new_caps;
+      GstCaps *old_caps;
+      const GstCaps *new_caps_val = gst_value_get_caps (value);
+
+      if (new_caps_val == NULL) {
+        new_caps = gst_caps_new_any ();
+      } else {
+        new_caps = (GstCaps *) new_caps_val;
+        gst_caps_ref (new_caps);
+      }
+
+      GST_OBJECT_LOCK (adder);
+      old_caps = adder->filter_caps;
+      adder->filter_caps = new_caps;
+      GST_OBJECT_UNLOCK (adder);
+
+      gst_caps_unref (old_caps);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+      GST_DEBUG_OBJECT (adder, "set new caps %" GST_PTR_FORMAT, new_caps);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
+static void
+gst_adder_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstAdder *adder = GST_ADDER (object);
+
+  switch (prop_id) {
+    case PROP_FILTER_CAPS:
+      GST_OBJECT_LOCK (adder);
+      gst_value_set_caps (value, adder->filter_caps);
+      GST_OBJECT_UNLOCK (adder);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
 static GstPad *
 gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
     const gchar * unused)
@@ -694,7 +1025,7 @@
 gst_adder_collected (GstCollectPads * pads, gpointer user_data)
 {
   /*
-   * combine channels by adding sample values
+   * combine streams by adding data values
    * basic algorithm :
    * - this function is called when all pads have a buffer
    * - get available bytes on all pads.
@@ -702,13 +1033,19 @@
    *   - read available bytes, copy or add to target buffer
    *   - if there's an EOS event, remove the input channel
    * - push out the output buffer
+   *
+   * todo:
+   * - would be nice to have a mixing mode, where instead of adding we mix
+   *   - for float we could downscale after collect loop
+   *   - for int we need to downscale each input to avoid clipping or
+   *     mix into a temp (float) buffer and scale afterwards as well
    */
   GstAdder *adder;
-  guint size;
   GSList *collected;
-  GstBuffer *outbuf;
   GstFlowReturn ret;
-  gpointer outbytes;
+  GstBuffer *outbuf = NULL;
+  gpointer outdata = NULL;
+  guint outsize;
   gboolean empty = TRUE;
 
   adder = GST_ADDER (user_data);
@@ -717,79 +1054,80 @@
   if (G_UNLIKELY (adder->func == NULL))
     goto not_negotiated;
 
-  /* get available bytes for reading, this can be 0 which could mean
-   * empty buffers or EOS, which we will catch when we loop over the
-   * pads. */
-  size = gst_collect_pads_available (pads);
+  if (adder->flush_stop_pending) {
+    gst_pad_push_event (adder->srcpad, gst_event_new_flush_stop ());
+    adder->flush_stop_pending = FALSE;
+  }
+
+  /* get available bytes for reading, this can be 0 which could mean empty
+   * buffers or EOS, which we will catch when we loop over the pads. */
+  outsize = gst_collect_pads_available (pads);
 
   GST_LOG_OBJECT (adder,
-      "starting to cycle through channels, %d bytes available (bps = %d)", size,
-      adder->bps);
-
-  outbuf = NULL;
-  outbytes = NULL;
+      "starting to cycle through channels, %d bytes available (bps = %d)",
+      outsize, adder->bps);
 
   for (collected = pads->data; collected; collected = g_slist_next (collected)) {
-    GstCollectData *data;
-    guint8 *bytes;
-    guint len;
+    GstCollectData *collect_data;
     GstBuffer *inbuf;
+    guint8 *indata;
+    guint insize;
 
-    data = (GstCollectData *) collected->data;
+    collect_data = (GstCollectData *) collected->data;
 
     /* get a subbuffer of size bytes */
-    inbuf = gst_collect_pads_take_buffer (pads, data, size);
+    inbuf = gst_collect_pads_take_buffer (pads, collect_data, outsize);
     /* NULL means EOS or an empty buffer so we still need to flush in
      * case of an empty buffer. */
     if (inbuf == NULL) {
-      GST_LOG_OBJECT (adder, "channel %p: no bytes available", data);
-      goto next;
+      GST_LOG_OBJECT (adder, "channel %p: no bytes available", collect_data);
+      continue;
     }
 
-    bytes = GST_BUFFER_DATA (inbuf);
-    len = GST_BUFFER_SIZE (inbuf);
+    indata = GST_BUFFER_DATA (inbuf);
+    insize = GST_BUFFER_SIZE (inbuf);
 
     if (outbuf == NULL) {
       GST_LOG_OBJECT (adder, "channel %p: making output buffer of %d bytes",
-          data, size);
+          collect_data, outsize);
 
-      /* first buffer, alloc size bytes. FIXME, we can easily subbuffer
-       * and _make_writable. */
-      outbuf = gst_buffer_new_and_alloc (size);
-      outbytes = GST_BUFFER_DATA (outbuf);
+      /* first buffer, alloc outsize.
+       * FIXME: we can easily subbuffer and _make_writable.
+       * FIXME: only create empty buffer for first non-gap buffer, so that we
+       * only use adder function when really adding
+       */
+      outbuf = gst_buffer_new_and_alloc (outsize);
+      outdata = GST_BUFFER_DATA (outbuf);
       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (adder->srcpad));
 
       if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
+        GST_LOG_OBJECT (adder, "channel %p: copying %d bytes from data %p",
+            collect_data, insize, indata);
         /* clear if we are only going to fill a partial buffer */
-        if (G_UNLIKELY (size > len))
-          memset (outbytes, 0, size);
-
-        GST_LOG_OBJECT (adder, "channel %p: copying %d bytes from data %p",
-            data, len, bytes);
-
+        if (G_UNLIKELY (outsize > insize))
+          memset ((guint8 *) outdata + insize, 0, outsize - insize);
         /* and copy the data into it */
-        memcpy (outbytes, bytes, len);
+        memcpy (outdata, indata, insize);
         empty = FALSE;
       } else {
+        /* clear whole buffer */
         GST_LOG_OBJECT (adder, "channel %p: zeroing %d bytes from data %p",
-            data, len, bytes);
-        memset (outbytes, 0, size);
+            collect_data, insize, indata);
+        memset (outdata, 0, outsize);
       }
     } else {
       if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
         GST_LOG_OBJECT (adder, "channel %p: mixing %d bytes from data %p",
-            data, len, bytes);
-        /* other buffers, need to add them */
-        adder->func ((gpointer) outbytes, (gpointer) bytes, len);
+            collect_data, insize, indata);
+        /* further buffers, need to add them */
+        adder->func ((gpointer) outdata, (gpointer) indata, insize);
         empty = FALSE;
       } else {
         GST_LOG_OBJECT (adder, "channel %p: skipping %d bytes from data %p",
-            data, len, bytes);
+            collect_data, insize, indata);
       }
     }
-  next:
-    if (inbuf)
-      gst_buffer_unref (inbuf);
+    gst_buffer_unref (inbuf);
   }
 
   /* can only happen when no pads to collect or all EOS */
@@ -818,9 +1156,31 @@
     event = gst_event_new_new_segment_full (FALSE, adder->segment_rate,
         1.0, GST_FORMAT_TIME, adder->timestamp, -1, adder->segment_position);
 
-    gst_pad_push_event (adder->srcpad, event);
-    adder->segment_pending = FALSE;
-    adder->segment_position = 0;
+    if (event) {
+      if (!gst_pad_push_event (adder->srcpad, event)) {
+        GST_WARNING_OBJECT (adder->srcpad, "Sending event  %p (%s) failed.",
+            event, GST_EVENT_TYPE_NAME (event));
+      }
+      adder->segment_pending = FALSE;
+      adder->segment_position = 0;
+    } else {
+      GST_WARNING_OBJECT (adder->srcpad, "Creating new segment event for "
+          "start:%" G_GINT64_FORMAT "  pos:%" G_GINT64_FORMAT " failed",
+          adder->timestamp, adder->segment_position);
+    }
+  }
+
+  if (G_UNLIKELY (adder->pending_events)) {
+    GList *tmp = adder->pending_events;
+
+    while (tmp) {
+      GstEvent *ev = (GstEvent *) tmp->data;
+
+      gst_pad_push_event (adder->srcpad, ev);
+      tmp = g_list_next (tmp);
+    }
+    g_list_free (adder->pending_events);
+    adder->pending_events = NULL;
   }
 
   /* set timestamps on the output buffer */
@@ -829,7 +1189,7 @@
 
   /* for the next timestamp, use the sample counter, which will
    * never accumulate rounding errors */
-  adder->offset += size / adder->bps;
+  adder->offset += outsize / adder->bps;
   adder->timestamp = gst_util_uint64_scale_int (adder->offset,
       GST_SECOND, adder->rate);
 
@@ -846,6 +1206,8 @@
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
   ret = gst_pad_push (adder->srcpad, outbuf);
 
+  GST_LOG_OBJECT (adder, "pushed outbuf, result = %s", gst_flow_get_name (ret));
+
   return ret;
 
   /* ERRORS */
@@ -877,6 +1239,7 @@
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       adder->timestamp = 0;
       adder->offset = 0;
+      adder->flush_stop_pending = FALSE;
       adder->segment_pending = TRUE;
       adder->segment_position = 0;
       adder->segment_rate = 1.0;
@@ -908,6 +1271,8 @@
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
+  /*oil_init (); */
+
   if (!gst_element_register (plugin, "adder", GST_RANK_NONE, GST_TYPE_ADDER)) {
     return FALSE;
   }
--- a/gst_plugins_base/gst/adder/gstadder.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/adder/gstadder.h	Fri Apr 16 15:15:52 2010 +0300
@@ -87,6 +87,14 @@
   gboolean        segment_pending;
   guint64         segment_position;
   gdouble         segment_rate;
+  /* src event handling */
+  gboolean        flush_stop_pending;
+  
+  /* target caps */
+  GstCaps *filter_caps;
+
+  /* Pending inline events */
+  GList *pending_events;
 };
 
 struct _GstAdderClass {
--- a/gst_plugins_base/gst/app/gstapp.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/app/gstapp.c	Fri Apr 16 15:15:52 2010 +0300
@@ -44,7 +44,7 @@
 #ifdef __SYMBIAN32__
 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
 {
-	return &gst_plugin_desc;
+    return &gst_plugin_desc;
 }
 
 #endif
--- a/gst_plugins_base/gst/audioconvert/audioconvert.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioconvert/audioconvert.c	Fri Apr 16 15:15:52 2010 +0300
@@ -66,7 +66,6 @@
   }                                                                           \
 }
 
-
 /* unpack from float to float 64 (double) */
 #define MAKE_UNPACK_FUNC_FF(name, type, FUNC)                                 \
 static void                                                                   \
@@ -418,7 +417,8 @@
 
 gboolean
 audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
-    AudioConvertFmt * out, DitherType dither, NoiseShapingType ns)
+    AudioConvertFmt * out, GstAudioConvertDithering dither,
+    GstAudioConvertNoiseShaping ns)
 {
   gint idx_in, idx_out;
 
@@ -429,6 +429,9 @@
   /* first clean the existing context */
   audio_convert_clean_context (ctx);
 
+  g_return_val_if_fail (in->unpositioned_layout == out->unpositioned_layout,
+      FALSE);
+
   ctx->in = *in;
   ctx->out = *out;
 
@@ -534,9 +537,9 @@
 audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
     gpointer dst, gint samples, gboolean src_writable)
 {
-  gint insize, outsize, size;
+  guint insize, outsize, size;
   gpointer outbuf, tmpbuf;
-  gint intemp = 0, outtemp = 0, biggest;
+  guint intemp = 0, outtemp = 0, biggest;
 
   g_return_val_if_fail (ctx != NULL, FALSE);
   g_return_val_if_fail (src != NULL, FALSE);
@@ -554,9 +557,9 @@
       : sizeof (gint32);
 
   if (!ctx->in_default)
-    intemp = insize * size * 8 / ctx->in.width;
+    intemp = gst_util_uint64_scale (insize, size * 8, ctx->in.width);
   if (!ctx->mix_passthrough || !ctx->out_default)
-    outtemp = outsize * size * 8 / ctx->out.width;
+    outtemp = gst_util_uint64_scale (outsize, size * 8, ctx->out.width);
   biggest = MAX (intemp, outtemp);
 
   /* see if one of the buffers can be used as temp */
--- a/gst_plugins_base/gst/audioconvert/audioconvert.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioconvert/audioconvert.h	Fri Apr 16 15:15:52 2010 +0300
@@ -25,14 +25,33 @@
 #include <gst/gst.h>
 #include <gst/audio/multichannel.h>
 
+/**
+ * GstAudioConvertDithering:
+ * @DITHER_NONE: No dithering
+ * @DITHER_RPDF: Rectangular dithering
+ * @DITHER_TPDF: Triangular dithering (default)
+ * @DITHER_TPDF_HF: High frequency triangular dithering
+ *
+ * Set of available dithering methods when converting audio.
+ */
 typedef enum
 {
   DITHER_NONE = 0,
   DITHER_RPDF,
   DITHER_TPDF,
   DITHER_TPDF_HF
-} DitherType;
+} GstAudioConvertDithering;
 
+/**
+ * GstAudioConvertNoiseShaping:
+ * @NOISE_SHAPING_NONE: No noise shaping (default)
+ * @NOISE_SHAPING_ERROR_FEEDBACK: Error feedback
+ * @NOISE_SHAPING_SIMPLE: Simple 2-pole noise shaping
+ * @NOISE_SHAPING_MEDIUM: Medium 5-pole noise shaping
+ * @NOISE_SHAPING_HIGH: High 8-pole noise shaping
+ *
+ * Set of available noise shaping methods
+ */
 typedef enum
 {
   NOISE_SHAPING_NONE = 0,
@@ -40,7 +59,7 @@
   NOISE_SHAPING_SIMPLE,
   NOISE_SHAPING_MEDIUM,
   NOISE_SHAPING_HIGH
-} NoiseShapingType;
+} GstAudioConvertNoiseShaping;
 
 typedef struct _AudioConvertCtx AudioConvertCtx;
 typedef struct _AudioConvertFmt AudioConvertFmt;
@@ -54,6 +73,7 @@
   gint rate;
   gint channels;
   GstAudioChannelPosition *pos;
+  gboolean unpositioned_layout;
 
   /* int audio caps */
   gboolean sign;
@@ -98,10 +118,9 @@
   AudioConvertMix channel_mix;
 
   AudioConvertQuantize quantize;
-  DitherType dither;
-  NoiseShapingType ns;
-  /* random number generate for dither noise */
-  GRand *dither_random;
+
+  GstAudioConvertDithering dither;
+  GstAudioConvertNoiseShaping ns;
   /* last random number generated per channel for hifreq TPDF dither */
   gpointer last_random;
   /* contains the past quantization errors, error[out_channels][count] */
@@ -119,8 +138,8 @@
 
 
 gboolean audio_convert_prepare_context (AudioConvertCtx * ctx,
-    AudioConvertFmt * in, AudioConvertFmt * out, DitherType dither,
-    NoiseShapingType ns);
+    AudioConvertFmt * in, AudioConvertFmt * out,
+    GstAudioConvertDithering dither, GstAudioConvertNoiseShaping ns);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst/audioconvert/gstaudioconvert.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioconvert/gstaudioconvert.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,31 +24,20 @@
 /**
  * SECTION:element-audioconvert
  *
- * <refsect2>
- * <para>
  * Audioconvert converts raw audio buffers between various possible formats.
  * It supports integer to float conversion, width/depth conversion,
- * signedness and endianness conversion.
- * </para>
- * <para>
- * Some format conversion are not carried out in an optimal way right now.
- * E.g. converting from double to float would cause a loss of precision.
- * </para>
+ * signedness and endianness conversion and channel transformations.
+ *
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v -m audiotestsrc ! audioconvert ! audio/x-raw-int,channels=2,width=8,depth=8 ! level ! fakesink silent=TRUE
- * </programlisting>
- * This pipeline converts audio to 8-bit.  The level element shows that
+ * ]| This pipeline converts audio to 8-bit.  The level element shows that
  * the output levels still match the one for a sine wave.
- * </para>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v -m audiotestsrc ! audioconvert ! vorbisenc ! fakesink silent=TRUE
- * </programlisting>
- * The vorbis encoder takes float audio data instead of the integer data
+ * ]| The vorbis encoder takes float audio data instead of the integer data
  * generated by audiotestsrc.
- * </para>
  * </refsect2>
  *
  * Last reviewed on 2006-03-02 (0.10.4)
@@ -107,7 +96,8 @@
     const GValue * value, GParamSpec * pspec);
 static void gst_audio_convert_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-
+static gboolean structure_has_fixed_channel_positions (GstStructure * s,
+    gboolean * unpositioned_layout);
 
 /* AudioConvert signals and args */
 enum
@@ -135,37 +125,37 @@
 GST_STATIC_CAPS ( \
   "audio/x-raw-float, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 64;" \
   "audio/x-raw-float, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 32;" \
   "audio/x-raw-int, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 32, " \
     "depth = (int) [ 1, 32 ], " \
     "signed = (boolean) { true, false }; " \
   "audio/x-raw-int, "   \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], "       \
+    "channels = (int) [ 1, MAX ], "       \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "        \
     "width = (int) 24, "        \
     "depth = (int) [ 1, 24 ], " "signed = (boolean) { true, false }; "  \
   "audio/x-raw-int, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 16, " \
     "depth = (int) [ 1, 16 ], " \
     "signed = (boolean) { true, false }; " \
   "audio/x-raw-int, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 8, " \
     "depth = (int) [ 1, 8 ], " \
@@ -263,13 +253,14 @@
   g_object_class_install_property (gobject_class, ARG_DITHERING,
       g_param_spec_enum ("dithering", "Dithering",
           "Selects between different dithering methods.",
-          GST_TYPE_AUDIO_CONVERT_DITHERING, DITHER_TPDF, G_PARAM_READWRITE));
+          GST_TYPE_AUDIO_CONVERT_DITHERING, DITHER_TPDF,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, ARG_NOISE_SHAPING,
       g_param_spec_enum ("noise-shaping", "Noise shaping",
           "Selects between different noise shaping methods.",
           GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING, NOISE_SHAPING_NONE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   basetransform_class->get_unit_size =
       GST_DEBUG_FUNCPTR (gst_audio_convert_get_unit_size);
@@ -293,6 +284,8 @@
   this->dither = DITHER_TPDF;
   this->ns = NOISE_SHAPING_NONE;
   memset (&this->ctx, 0, sizeof (AudioConvertCtx));
+
+  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (this), TRUE);
 }
 
 static void
@@ -330,6 +323,10 @@
     goto no_values;
   if (!(fmt->pos = gst_audio_get_channel_positions (structure)))
     goto no_values;
+
+  fmt->unpositioned_layout = FALSE;
+  structure_has_fixed_channel_positions (structure, &fmt->unpositioned_layout);
+
   if (!gst_structure_get_int (structure, "width", &fmt->width))
     goto no_values;
   if (!gst_structure_get_int (structure, "rate", &fmt->rate))
@@ -529,6 +526,40 @@
   }
 }
 
+static gboolean
+structure_has_fixed_channel_positions (GstStructure * s,
+    gboolean * unpositioned_layout)
+{
+  GstAudioChannelPosition *pos;
+  const GValue *val;
+  gint channels = 0;
+
+  if (!gst_structure_get_int (s, "channels", &channels))
+    return FALSE;               /* probably a range */
+
+  val = gst_structure_get_value (s, "channel-positions");
+  if ((val == NULL || !gst_value_is_fixed (val)) && channels <= 8) {
+    GST_LOG ("no or unfixed channel-positions in %" GST_PTR_FORMAT, s);
+    return FALSE;
+  } else if (val == NULL || !gst_value_is_fixed (val)) {
+    GST_LOG ("implicit undefined channel-positions");
+    *unpositioned_layout = TRUE;
+    return TRUE;
+  }
+
+  pos = gst_audio_get_channel_positions (s);
+  if (pos && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
+    GST_LOG ("fixed undefined channel-positions in %" GST_PTR_FORMAT, s);
+    *unpositioned_layout = TRUE;
+  } else {
+    GST_LOG ("fixed defined channel-positions in %" GST_PTR_FORMAT, s);
+    *unpositioned_layout = FALSE;
+  }
+  g_free (pos);
+
+  return TRUE;
+}
+
 /* Audioconvert can perform all conversions on audio except for resampling. 
  * However, there are some conversions we _prefer_ not to do. For example, it's
  * better to convert format (float<->int, endianness, etc) than the number of
@@ -546,8 +577,8 @@
 {
   GstCaps *ret;
   GstStructure *s, *structure;
-  gboolean isfloat;
-  gint width, depth, channels;
+  gboolean isfloat, allow_mixing;
+  gint width, depth, channels = 0;
   const gchar *fields_used[] = {
     "width", "depth", "rate", "channels", "endianness", "signed"
   };
@@ -603,11 +634,28 @@
     }
   }
 
+  allow_mixing = TRUE;
   if (gst_structure_get_int (structure, "channels", &channels)) {
-    if (channels == 8)
-      gst_structure_set (s, "channels", G_TYPE_INT, 8, NULL);
+    gboolean unpositioned;
+
+    /* we don't support mixing for channels without channel positions */
+    if (structure_has_fixed_channel_positions (structure, &unpositioned))
+      allow_mixing = (unpositioned == FALSE);
+  }
+
+  if (!allow_mixing) {
+    gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
+    if (gst_structure_has_field (structure, "channel-positions"))
+      gst_structure_set_value (s, "channel-positions",
+          gst_structure_get_value (structure, "channel-positions"));
+  } else {
+    if (channels == 0)
+      gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 11, NULL);
+    else if (channels == 11)
+      gst_structure_set (s, "channels", G_TYPE_INT, 11, NULL);
     else
-      gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 8, NULL);
+      gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 11, NULL);
+    gst_structure_remove_field (s, "channel-positions");
   }
   gst_caps_append_structure (ret, s);
 
@@ -636,7 +684,16 @@
    * it's very bad to drop channels entirely.
    */
   s = gst_structure_copy (s);
-  gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 8, NULL);
+  if (allow_mixing) {
+    gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 11, NULL);
+    gst_structure_remove_field (s, "channel-positions");
+  } else {
+    /* allow_mixing can only be FALSE if we got a fixed number of channels */
+    gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
+    if (gst_structure_has_field (structure, "channel-positions"))
+      gst_structure_set_value (s, "channel-positions",
+          gst_structure_get_value (structure, "channel-positions"));
+  }
   gst_caps_append_structure (ret, s);
 
   /* Same, plus a float<->int conversion */
@@ -751,7 +808,7 @@
 gst_audio_convert_fixate_channels (GstBaseTransform * base, GstStructure * ins,
     GstStructure * outs)
 {
-  const GValue *out_layout;
+  const GValue *in_layout, *out_layout;
   gint in_chans, out_chans;
 
   if (!gst_structure_get_int (ins, "channels", &in_chans))
@@ -776,19 +833,18 @@
   /* check if the output has a channel layout (or a list of layouts) */
   out_layout = gst_structure_get_value (outs, "channel-positions");
 
+  /* get the channel layout of the input if any */
+  in_layout = gst_structure_get_value (ins, "channel-positions");
+
   if (out_layout == NULL) {
-    if (out_chans <= 2)
+    if (out_chans <= 2 && (in_chans != out_chans || in_layout == NULL))
       return;                   /* nothing to do, default layout will be assumed */
     GST_WARNING_OBJECT (base, "downstream caps contain no channel layout");
   }
 
-  if (in_chans == out_chans) {
-    const GValue *in_layout;
+  if (in_chans == out_chans && in_layout != NULL) {
     GValue res = { 0, };
 
-    in_layout = gst_structure_get_value (ins, "channel-positions");
-    g_return_if_fail (in_layout != NULL);
-
     /* same number of channels and no output layout: just use input layout */
     if (out_layout == NULL) {
       gst_structure_set_value (outs, "channel-positions", in_layout);
@@ -846,7 +902,7 @@
    * and try to add/remove channels from the input layout, or pick a default
    * layout based on LFE-presence in input layout, but let's save that for
    * another day) */
-  if (out_chans > 0 && out_chans < G_N_ELEMENTS (default_positions[0])) {
+  if (out_chans > 0 && out_chans <= G_N_ELEMENTS (default_positions[0])) {
     GST_DEBUG_OBJECT (base, "using default channel layout as fallback");
     gst_audio_set_channel_positions (outs, default_positions[out_chans - 1]);
   }
@@ -946,6 +1002,79 @@
   return GST_FLOW_OK;
 }
 
+static void
+gst_audio_convert_create_silence_buffer (GstAudioConvert * this, gpointer dst,
+    gint size)
+{
+  if (this->ctx.out.is_int && !this->ctx.out.sign) {
+    gint i;
+
+    switch (this->ctx.out.width) {
+      case 8:{
+        guint8 zero = 0x80 >> (8 - this->ctx.out.depth);
+
+        memset (dst, zero, size);
+        break;
+      }
+      case 16:{
+        guint16 *data = (guint16 *) dst;
+        guint16 zero = 0x8000 >> (16 - this->ctx.out.depth);
+
+        if (this->ctx.out.endianness == G_LITTLE_ENDIAN)
+          zero = GUINT16_TO_LE (zero);
+        else
+          zero = GUINT16_TO_BE (zero);
+
+        size /= 2;
+
+        for (i = 0; i < size; i++)
+          data[i] = zero;
+        break;
+      }
+      case 24:{
+        guint32 zero = 0x800000 >> (24 - this->ctx.out.depth);
+        guint8 *data = (guint8 *) dst;
+
+        if (this->ctx.out.endianness == G_LITTLE_ENDIAN) {
+          for (i = 0; i < size; i += 3) {
+            data[i] = zero & 0xff;
+            data[i + 1] = (zero >> 8) & 0xff;
+            data[i + 2] = (zero >> 16) & 0xff;
+          }
+        } else {
+          for (i = 0; i < size; i += 3) {
+            data[i + 2] = zero & 0xff;
+            data[i + 1] = (zero >> 8) & 0xff;
+            data[i] = (zero >> 16) & 0xff;
+          }
+        }
+        break;
+      }
+      case 32:{
+        guint32 *data = (guint32 *) dst;
+        guint32 zero = (0x80000000 >> (32 - this->ctx.out.depth));
+
+        if (this->ctx.out.endianness == G_LITTLE_ENDIAN)
+          zero = GUINT32_TO_LE (zero);
+        else
+          zero = GUINT32_TO_BE (zero);
+
+        size /= 4;
+
+        for (i = 0; i < size; i++)
+          data[i] = zero;
+        break;
+      }
+      default:
+        memset (dst, 0, size);
+        g_return_if_reached ();
+        break;
+    }
+  } else {
+    memset (dst, 0, size);
+  }
+}
+
 static GstFlowReturn
 gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf,
     GstBuffer * outbuf)
@@ -978,9 +1107,14 @@
   dst = GST_BUFFER_DATA (outbuf);
 
   /* and convert the samples */
-  if (!(res = audio_convert_convert (&this->ctx, src, dst,
-              samples, gst_buffer_is_writable (inbuf))))
-    goto convert_error;
+  if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
+    if (!(res = audio_convert_convert (&this->ctx, src, dst,
+                samples, gst_buffer_is_writable (inbuf))))
+      goto convert_error;
+  } else {
+    /* Create silence buffer */
+    gst_audio_convert_create_silence_buffer (this, dst, outsize);
+  }
 
   GST_BUFFER_SIZE (outbuf) = outsize;
 
--- a/gst_plugins_base/gst/audioconvert/gstaudioconvert.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioconvert/gstaudioconvert.h	Fri Apr 16 15:15:52 2010 +0300
@@ -48,8 +48,8 @@
 
   AudioConvertCtx ctx;
 
-  DitherType dither;
-  NoiseShapingType ns;
+  GstAudioConvertDithering dither;
+  GstAudioConvertNoiseShaping ns;
 };
 
 struct _GstAudioConvertClass
--- a/gst_plugins_base/gst/audioconvert/gstaudioquantize.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioconvert/gstaudioquantize.c	Fri Apr 16 15:15:52 2010 +0300
@@ -37,6 +37,8 @@
 #include "audioconvert.h"
 #include "gstaudioquantize.h"
 
+#include "gstfastrandom.h"
+
 #define MAKE_QUANTIZE_FUNC_NAME(name)                                   \
 gst_audio_quantize_quantize_##name
 
@@ -144,8 +146,8 @@
   gint32 dither = (1<<(scale));
 
 #define ADD_DITHER_RPDF_I()                                             \
-        rand = g_rand_int_range (ctx->dither_random, bias - dither,     \
-               bias + dither);                                          \
+        rand = gst_fast_random_int32_range (bias - dither,              \
+	    bias + dither);                                             \
         if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand)            \
                 tmp = G_MAXINT32;                                       \
         else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand)       \
@@ -157,8 +159,7 @@
   gdouble dither = 1.0/(1U<<(32 - scale - 1));
 
 #define ADD_DITHER_RPDF_F()                                             \
-        tmp += g_rand_double_range (ctx->dither_random, - dither,       \
-               dither);
+        tmp += gst_fast_random_double_range (- dither, dither);
 
 #define INIT_DITHER_TPDF_I()                                            \
   gint32 rand;                                                          \
@@ -166,10 +167,10 @@
   bias = bias >> 1;
 
 #define ADD_DITHER_TPDF_I()                                             \
-        rand = g_rand_int_range (ctx->dither_random, bias - dither,     \
-               bias + dither - 1)                                           \
-               + g_rand_int_range (ctx->dither_random, bias - dither,   \
-               bias + dither - 1);                                          \
+        rand = gst_fast_random_int32_range (bias - dither,              \
+                   bias + dither - 1)                                   \
+               + gst_fast_random_int32_range (bias - dither,            \
+                   bias + dither - 1);                                  \
         if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand)            \
                 tmp = G_MAXINT32;                                       \
         else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand)       \
@@ -181,10 +182,8 @@
   gdouble dither = 1.0/(1U<<(32 - scale));
 
 #define ADD_DITHER_TPDF_F()                                             \
-        tmp += g_rand_double_range (ctx->dither_random, - dither,       \
-               dither)                                                  \
-               + g_rand_double_range (ctx->dither_random, - dither,     \
-               dither);
+        tmp += gst_fast_random_double_range (- dither, dither)          \
+               + gst_fast_random_double_range (- dither, dither);
 
 #define INIT_DITHER_TPDF_HF_I()                                         \
   gint32 rand;                                                          \
@@ -193,8 +192,8 @@
   bias = bias >> 1;
 
 #define ADD_DITHER_TPDF_HF_I()                                          \
-        tmp_rand = g_rand_int_range (ctx->dither_random, bias - dither, \
-                   bias + dither); \
+        tmp_rand = gst_fast_random_int32_range (bias - dither,          \
+                       bias + dither);                                  \
         rand = tmp_rand - last_random[chan_pos];                        \
         last_random[chan_pos] = tmp_rand;                               \
         if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand)            \
@@ -213,8 +212,7 @@
   gdouble *last_random = (gdouble *) ctx->last_random, tmp_rand;
 
 #define ADD_DITHER_TPDF_HF_F()                                          \
-        tmp_rand = g_rand_double_range (ctx->dither_random, - dither,   \
-                   dither);                                             \
+        tmp_rand = gst_fast_random_double_range (- dither, dither);     \
         rand = tmp_rand - last_random[chan_pos];                        \
         last_random[chan_pos] = tmp_rand;                               \
         tmp += rand;
@@ -430,7 +428,6 @@
     default:
       break;
   }
-  return;
 
   g_free (ctx->error_buf);
   ctx->error_buf = NULL;
@@ -446,16 +443,13 @@
         ctx->last_random = g_new0 (gint32, ctx->out.channels);
       else
         ctx->last_random = g_new0 (gdouble, ctx->out.channels);
-      ctx->dither_random = g_rand_new ();
       break;
     case DITHER_RPDF:
     case DITHER_TPDF:
-      ctx->dither_random = g_rand_new ();
       ctx->last_random = NULL;
       break;
     case DITHER_NONE:
     default:
-      ctx->dither_random = NULL;
       ctx->last_random = NULL;
       break;
   }
@@ -466,8 +460,6 @@
 gst_audio_quantize_free_dither (AudioConvertCtx * ctx)
 {
   g_free (ctx->last_random);
-  if (ctx->dither_random)
-    g_rand_free (ctx->dither_random);
 
   return;
 }
--- a/gst_plugins_base/gst/audioconvert/gstchannelmix.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioconvert/gstchannelmix.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
  *
  * gstchannelmix.c: setup of channel conversion matrices
  *
@@ -114,53 +115,64 @@
   };
   gint c;
 
-  /* conversions from compatible (but not the same) channel schemes. This
-   * goes two ways: if the sink has both pos1[0,1] and src has pos2[0] or
-   * if the src has both pos1[0,1] and sink has pos2[0], then we do the
-   * conversion. We hereby assume that the existance of pos1[0,1] and
-   * pos2[0] are mututally exclusive. There are no checks for that,
-   * unfortunately. This shouldn't lead to issues (like crashes or so),
-   * though. */
+  /* conversions from compatible (but not the same) channel schemes */
   for (c = 0; conv[c].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID; c++) {
-    gint pos1_0 = -1, pos1_1 = -1, pos2_0 = -1, n;
+    gint pos1_0 = -1, pos1_1 = -1, pos1_2 = -1;
+    gint pos2_0 = -1, pos2_1 = -1, pos2_2 = -1;
+    gint n;
 
-    /* Try to go from the given 2 channels to the given 1 channel */
     for (n = 0; n < this->in.channels; n++) {
       if (this->in.pos[n] == conv[c].pos1[0])
         pos1_0 = n;
       else if (this->in.pos[n] == conv[c].pos1[1])
         pos1_1 = n;
+      else if (this->in.pos[n] == conv[c].pos2[0])
+        pos1_2 = n;
     }
     for (n = 0; n < this->out.channels; n++) {
-      if (this->out.pos[n] == conv[c].pos2[0])
+      if (this->out.pos[n] == conv[c].pos1[0])
         pos2_0 = n;
-    }
-
-    if (pos1_0 != -1 && pos1_1 != -1 && pos2_0 != -1) {
-      this->matrix[pos1_0][pos2_0] = 1.0;
-      this->matrix[pos1_1][pos2_0] = 1.0;
+      else if (this->out.pos[n] == conv[c].pos1[1])
+        pos2_1 = n;
+      else if (this->out.pos[n] == conv[c].pos2[0])
+        pos2_2 = n;
     }
 
-    /* Try to go from the given 1 channel to the given 2 channels */
-    pos1_0 = -1;
-    pos1_1 = -1;
-    pos2_0 = -1;
+    /* The general idea here is to fill in channels from the same position
+     * as good as possible. This means mixing left<->center and right<->center.
+     */
+
+    /* left -> center */
+    if (pos1_0 != -1 && pos1_2 == -1 && pos2_0 == -1 && pos2_2 != -1)
+      this->matrix[pos1_0][pos2_2] = 1.0;
+    else if (pos1_0 != -1 && pos1_2 != -1 && pos2_0 == -1 && pos2_2 != -1)
+      this->matrix[pos1_0][pos2_2] = 0.5;
+    else if (pos1_0 != -1 && pos1_2 == -1 && pos2_0 != -1 && pos2_2 != -1)
+      this->matrix[pos1_0][pos2_2] = 1.0;
 
-    for (n = 0; n < this->out.channels; n++) {
-      if (this->out.pos[n] == conv[c].pos1[0])
-        pos1_0 = n;
-      else if (this->out.pos[n] == conv[c].pos1[1])
-        pos1_1 = n;
-    }
-    for (n = 0; n < this->in.channels; n++) {
-      if (this->in.pos[n] == conv[c].pos2[0])
-        pos2_0 = n;
-    }
+    /* right -> center */
+    if (pos1_1 != -1 && pos1_2 == -1 && pos2_1 == -1 && pos2_2 != -1)
+      this->matrix[pos1_1][pos2_2] = 1.0;
+    else if (pos1_1 != -1 && pos1_2 != -1 && pos2_1 == -1 && pos2_2 != -1)
+      this->matrix[pos1_1][pos2_2] = 0.5;
+    else if (pos1_1 != -1 && pos1_2 == -1 && pos2_1 != -1 && pos2_2 != -1)
+      this->matrix[pos1_1][pos2_2] = 1.0;
 
-    if (pos1_0 != -1 && pos1_1 != -1 && pos2_0 != -1) {
-      this->matrix[pos2_0][pos1_0] = 1.0;
-      this->matrix[pos2_0][pos1_1] = 1.0;
-    }
+    /* center -> left */
+    if (pos1_2 != -1 && pos1_0 == -1 && pos2_2 == -1 && pos2_0 != -1)
+      this->matrix[pos1_2][pos2_0] = 1.0;
+    else if (pos1_2 != -1 && pos1_0 != -1 && pos2_2 == -1 && pos2_0 != -1)
+      this->matrix[pos1_2][pos2_0] = 0.5;
+    else if (pos1_2 != -1 && pos1_0 == -1 && pos2_2 != -1 && pos2_0 != -1)
+      this->matrix[pos1_2][pos2_0] = 1.0;
+
+    /* center -> right */
+    if (pos1_2 != -1 && pos1_1 == -1 && pos2_2 == -1 && pos2_1 != -1)
+      this->matrix[pos1_2][pos2_1] = 1.0;
+    else if (pos1_2 != -1 && pos1_1 != -1 && pos2_2 == -1 && pos2_1 != -1)
+      this->matrix[pos1_2][pos2_1] = 0.5;
+    else if (pos1_2 != -1 && pos1_1 == -1 && pos2_2 != -1 && pos2_1 != -1)
+      this->matrix[pos1_2][pos2_1] = 1.0;
   }
 }
 
@@ -184,43 +196,52 @@
   for (n = 0; n < caps->channels; n++) {
     switch (caps->pos[n]) {
       case GST_AUDIO_CHANNEL_POSITION_FRONT_MONO:
-      case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
-      case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
+        f[1] = n;
         *has_f = TRUE;
-        if (f[0] == -1)
-          f[0] = n;
-        else
-          f[1] = n;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
+        f[0] = n;
+        *has_f = TRUE;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
+        f[2] = n;
+        *has_f = TRUE;
         break;
       case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER:
-      case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
-      case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
+        c[1] = n;
         *has_c = TRUE;
-        if (c[0] == -1)
-          c[0] = n;
-        else
-          c[1] = n;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
+        c[0] = n;
+        *has_c = TRUE;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
+        c[2] = n;
+        *has_c = TRUE;
         break;
       case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER:
-      case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT:
-      case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT:
+        r[1] = n;
         *has_r = TRUE;
-        if (r[0] == -1)
-          r[0] = n;
-        else
-          r[1] = n;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT:
+        r[0] = n;
+        *has_r = TRUE;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT:
+        r[2] = n;
+        *has_r = TRUE;
         break;
       case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT:
-      case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT:
+        s[0] = n;
         *has_s = TRUE;
-        if (s[0] == -1)
-          s[0] = n;
-        else
-          s[1] = n;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT:
+        s[2] = n;
+        *has_s = TRUE;
         break;
       case GST_AUDIO_CHANNEL_POSITION_LFE:
         *has_b = TRUE;
-        b[0] = n;
+        b[1] = n;
         break;
       default:
         break;
@@ -231,55 +252,69 @@
 static void
 gst_channel_mix_fill_one_other (gfloat ** matrix,
     AudioConvertFmt * from_caps, gint * from_idx,
-    GstAudioChannelPosition from_pos_l,
-    GstAudioChannelPosition from_pos_r,
-    GstAudioChannelPosition from_pos_c,
-    AudioConvertFmt * to_caps, gint * to_idx,
-    GstAudioChannelPosition to_pos_l,
-    GstAudioChannelPosition to_pos_r,
-    GstAudioChannelPosition to_pos_c, gfloat ratio)
+    AudioConvertFmt * to_caps, gint * to_idx, gfloat ratio)
 {
-  gfloat in_r, out_r[2] = { 0.f, 0.f };
+
+  /* src & dst have center => passthrough */
+  if (from_idx[1] != -1 && to_idx[1] != -1) {
+    matrix[from_idx[1]][to_idx[1]] = ratio;
+  }
 
-  /*
-   * The idea is that we add up from the input (which means that if we
-   * have stereo input, we divide their sum by two) and put that in
-   * the matrix for their output ratio (given in $ratio).
-   * For left channels, we need to invert the signal sign (* -1).
-   */
+  /* src & dst have left => passthrough */
+  if (from_idx[0] != -1 && to_idx[0] != -1) {
+    matrix[from_idx[0]][to_idx[0]] = ratio;
+  }
 
-  if (from_caps->pos[from_idx[0]] == from_pos_c)
-    in_r = 1.0;
-  else
-    in_r = 0.5;
-
-  if (to_caps->pos[to_idx[0]] == to_pos_l)
-    out_r[0] = in_r * -ratio;
-  else
-    out_r[0] = in_r * ratio;
-
-  if (to_idx[1] != -1) {
-    if (to_caps->pos[to_idx[1]] == to_pos_l)
-      out_r[1] = in_r * -ratio;
-    else
-      out_r[1] = in_r * ratio;
+  /* src & dst have right => passthrough */
+  if (from_idx[2] != -1 && to_idx[2] != -1) {
+    matrix[from_idx[2]][to_idx[2]] = ratio;
   }
 
-  matrix[from_idx[0]][to_idx[0]] = out_r[0];
-  if (to_idx[1] != -1)
-    matrix[from_idx[0]][to_idx[1]] = out_r[1];
-  if (from_idx[1] != -1) {
-    matrix[from_idx[1]][to_idx[0]] = out_r[0];
-    if (to_idx[1] != -1)
-      matrix[from_idx[1]][to_idx[1]] = out_r[1];
+  /* src has left & dst has center => put into center */
+  if (from_idx[0] != -1 && to_idx[1] != -1 && from_idx[1] != -1) {
+    matrix[from_idx[0]][to_idx[1]] = 0.5 * ratio;
+  } else if (from_idx[0] != -1 && to_idx[1] != -1 && from_idx[1] == -1) {
+    matrix[from_idx[0]][to_idx[1]] = ratio;
+  }
+
+  /* src has right & dst has center => put into center */
+  if (from_idx[2] != -1 && to_idx[1] != -1 && from_idx[1] != -1) {
+    matrix[from_idx[2]][to_idx[1]] = 0.5 * ratio;
+  } else if (from_idx[2] != -1 && to_idx[1] != -1 && from_idx[1] == -1) {
+    matrix[from_idx[2]][to_idx[1]] = ratio;
+  }
+
+  /* src has center & dst has left => passthrough */
+  if (from_idx[1] != -1 && to_idx[0] != -1 && from_idx[0] != -1) {
+    matrix[from_idx[1]][to_idx[0]] = 0.5 * ratio;
+  } else if (from_idx[1] != -1 && to_idx[0] != -1 && from_idx[0] == -1) {
+    matrix[from_idx[1]][to_idx[0]] = ratio;
+  }
+
+  /* src has center & dst has right => passthrough */
+  if (from_idx[1] != -1 && to_idx[2] != -1 && from_idx[2] != -1) {
+    matrix[from_idx[1]][to_idx[2]] = 0.5 * ratio;
+  } else if (from_idx[1] != -1 && to_idx[2] != -1 && from_idx[2] == -1) {
+    matrix[from_idx[1]][to_idx[2]] = ratio;
   }
 }
 
+#define RATIO_CENTER_FRONT (1.0 / sqrt (2.0))
+#define RATIO_CENTER_SIDE (1.0 / 2.0)
+#define RATIO_CENTER_REAR (1.0 / sqrt (8.0))
+
 #define RATIO_FRONT_CENTER (1.0 / sqrt (2.0))
-#define RATIO_FRONT_REAR (1.0 / sqrt (2.0))
+#define RATIO_FRONT_SIDE (1.0 / sqrt (2.0))
+#define RATIO_FRONT_REAR (1.0 / 2.0)
+
+#define RATIO_SIDE_CENTER (1.0 / 2.0)
+#define RATIO_SIDE_FRONT (1.0 / sqrt (2.0))
+#define RATIO_SIDE_REAR (1.0 / sqrt (2.0))
+
+#define RATIO_CENTER_BASS (1.0 / sqrt (2.0))
 #define RATIO_FRONT_BASS (1.0)
+#define RATIO_SIDE_BASS (1.0 / sqrt (2.0))
 #define RATIO_REAR_BASS (1.0 / sqrt (2.0))
-#define RATIO_CENTER_BASS (1.0 / sqrt (2.0))
 
 static void
 gst_channel_mix_fill_others (AudioConvertCtx * this)
@@ -289,16 +324,21 @@
       in_has_rear = FALSE, out_has_rear = FALSE,
       in_has_side = FALSE, out_has_side = FALSE,
       in_has_bass = FALSE, out_has_bass = FALSE;
-  gint in_f[2] = { -1, -1 }, out_f[2] = {
-  -1, -1}, in_c[2] = {
-  -1, -1}, out_c[2] = {
-  -1, -1}, in_r[2] = {
-  -1, -1}, out_r[2] = {
-  -1, -1}, in_s[2] = {
-  -1, -1}, out_s[2] = {
-  -1, -1}, in_b[2] = {
-  -1, -1}, out_b[2] = {
-  -1, -1};
+  /* LEFT, RIGHT, MONO */
+  gint in_f[3] = { -1, -1, -1 };
+  gint out_f[3] = { -1, -1, -1 };
+  /* LOC, ROC, CENTER */
+  gint in_c[3] = { -1, -1, -1 };
+  gint out_c[3] = { -1, -1, -1 };
+  /* RLEFT, RRIGHT, RCENTER */
+  gint in_r[3] = { -1, -1, -1 };
+  gint out_r[3] = { -1, -1, -1 };
+  /* SLEFT, INVALID, SRIGHT */
+  gint in_s[3] = { -1, -1, -1 };
+  gint out_s[3] = { -1, -1, -1 };
+  /* INVALID, LFE, INVALID */
+  gint in_b[3] = { -1, -1, -1 };
+  gint out_b[3] = { -1, -1, -1 };
 
   /* First see where (if at all) the various channels from/to
    * which we want to convert are located in our matrix/array. */
@@ -311,124 +351,164 @@
       out_c, &out_has_center, out_r, &out_has_rear,
       out_s, &out_has_side, out_b, &out_has_bass);
 
-  /* center/front */
+  /* The general idea here is:
+   * - if the source has a channel that the destination doesn't have mix
+   *   it into the nearest available destination channel
+   * - if the destination has a channel that the source doesn't have mix
+   *   the nearest source channel into the destination channel
+   *
+   * The ratio for the mixing becomes lower as the distance between the
+   * channels gets larger
+   */
+
+  /* center <-> front/side/rear */
   if (!in_has_center && in_has_front && out_has_center) {
     gst_channel_mix_fill_one_other (this->matrix,
-        &this->in, in_f,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_MONO,
-        &this->out, out_c,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, RATIO_FRONT_CENTER);
+        &this->in, in_f, &this->out, out_c, RATIO_CENTER_FRONT);
+  } else if (!in_has_center && !in_has_front && in_has_side && out_has_center) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_c, RATIO_CENTER_SIDE);
+  } else if (!in_has_center && !in_has_front && !in_has_side && in_has_rear
+      && out_has_center) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out,
+        out_c, RATIO_CENTER_REAR);
   } else if (in_has_center && !out_has_center && out_has_front) {
     gst_channel_mix_fill_one_other (this->matrix,
-        &this->in, in_c,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-        &this->out, out_f,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, RATIO_FRONT_CENTER);
+        &this->in, in_c, &this->out, out_f, RATIO_CENTER_FRONT);
+  } else if (in_has_center && !out_has_center && !out_has_front && out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_c, &this->out, out_s, RATIO_CENTER_SIDE);
+  } else if (in_has_center && !out_has_center && !out_has_front && !out_has_side
+      && out_has_rear) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out,
+        out_r, RATIO_CENTER_REAR);
+  }
+
+  /* front <-> center/side/rear */
+  if (!in_has_front && in_has_center && !in_has_side && out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_c, &this->out, out_f, RATIO_CENTER_FRONT);
+  } else if (!in_has_front && !in_has_center && in_has_side && out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_f, RATIO_FRONT_SIDE);
+  } else if (!in_has_front && in_has_center && in_has_side && out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_c, &this->out, out_f, 0.5 * RATIO_CENTER_FRONT);
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_f, 0.5 * RATIO_FRONT_SIDE);
+  } else if (!in_has_front && !in_has_center && !in_has_side && in_has_rear
+      && out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out,
+        out_f, RATIO_FRONT_REAR);
+  } else if (in_has_front && out_has_center && !out_has_side && !out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_c, RATIO_CENTER_FRONT);
+  } else if (in_has_front && !out_has_center && out_has_side && !out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_s, RATIO_FRONT_SIDE);
+  } else if (in_has_front && out_has_center && out_has_side && !out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_c, 0.5 * RATIO_CENTER_FRONT);
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_s, 0.5 * RATIO_FRONT_SIDE);
+  } else if (in_has_front && !out_has_center && !out_has_side && !out_has_front
+      && out_has_rear) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_f, &this->out,
+        out_r, RATIO_FRONT_REAR);
   }
 
-  /* rear/front */
-  if (!in_has_rear && in_has_front && out_has_rear) {
+  /* side <-> center/front/rear */
+  if (!in_has_side && in_has_front && !in_has_rear && out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_s, RATIO_FRONT_SIDE);
+  } else if (!in_has_side && !in_has_front && in_has_rear && out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_r, &this->out, out_s, RATIO_SIDE_REAR);
+  } else if (!in_has_side && in_has_front && in_has_rear && out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_s, 0.5 * RATIO_FRONT_SIDE);
     gst_channel_mix_fill_one_other (this->matrix,
-        &this->in, in_f,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_MONO,
-        &this->out, out_r,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, RATIO_FRONT_REAR);
-  } else if (in_has_rear && !out_has_rear && out_has_front) {
+        &this->in, in_r, &this->out, out_s, 0.5 * RATIO_SIDE_REAR);
+  } else if (!in_has_side && !in_has_front && !in_has_rear && in_has_center
+      && out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out,
+        out_s, RATIO_CENTER_SIDE);
+  } else if (in_has_side && out_has_front && !out_has_rear && !out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_f, RATIO_FRONT_SIDE);
+  } else if (in_has_side && !out_has_front && out_has_rear && !out_has_side) {
     gst_channel_mix_fill_one_other (this->matrix,
-        &this->in, in_r,
-        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
-        &this->out, out_f,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-        GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, RATIO_FRONT_REAR);
+        &this->in, in_s, &this->out, out_r, RATIO_SIDE_REAR);
+  } else if (in_has_side && out_has_front && out_has_rear && !out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_f, 0.5 * RATIO_FRONT_SIDE);
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_r, 0.5 * RATIO_SIDE_REAR);
+  } else if (in_has_side && !out_has_front && !out_has_rear && out_has_center
+      && !out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_s, &this->out,
+        out_c, RATIO_CENTER_SIDE);
   }
 
-  /* bass/any */
+  /* rear <-> center/front/side */
+  if (!in_has_rear && in_has_side && out_has_rear) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_s, &this->out, out_r, RATIO_SIDE_REAR);
+  } else if (!in_has_rear && !in_has_side && in_has_front && out_has_rear) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_f, &this->out, out_r, RATIO_FRONT_REAR);
+  } else if (!in_has_rear && !in_has_side && !in_has_front && in_has_center
+      && out_has_rear) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out,
+        out_r, RATIO_CENTER_REAR);
+  } else if (in_has_rear && !out_has_rear && out_has_side) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_r, &this->out, out_s, RATIO_SIDE_REAR);
+  } else if (in_has_rear && !out_has_rear && !out_has_side && out_has_front) {
+    gst_channel_mix_fill_one_other (this->matrix,
+        &this->in, in_r, &this->out, out_f, RATIO_FRONT_REAR);
+  } else if (in_has_rear && !out_has_rear && !out_has_side && !out_has_front
+      && out_has_center) {
+    gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out,
+        out_c, RATIO_CENTER_REAR);
+  }
+
+  /* bass <-> any */
   if (in_has_bass && !out_has_bass) {
+    if (out_has_center) {
+      gst_channel_mix_fill_one_other (this->matrix,
+          &this->in, in_b, &this->out, out_c, RATIO_CENTER_BASS);
+    }
     if (out_has_front) {
       gst_channel_mix_fill_one_other (this->matrix,
-          &this->in, in_b,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_LFE,
-          &this->out, out_f,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, RATIO_FRONT_BASS);
+          &this->in, in_b, &this->out, out_f, RATIO_FRONT_BASS);
     }
-    if (out_has_center) {
+    if (out_has_side) {
       gst_channel_mix_fill_one_other (this->matrix,
-          &this->in, in_b,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_LFE,
-          &this->out, out_c,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, RATIO_CENTER_BASS);
+          &this->in, in_b, &this->out, out_s, RATIO_SIDE_BASS);
     }
     if (out_has_rear) {
       gst_channel_mix_fill_one_other (this->matrix,
-          &this->in, in_b,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_LFE,
-          &this->out, out_r,
-          GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-          GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-          GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, RATIO_REAR_BASS);
+          &this->in, in_b, &this->out, out_r, RATIO_REAR_BASS);
     }
   } else if (!in_has_bass && out_has_bass) {
+    if (in_has_center) {
+      gst_channel_mix_fill_one_other (this->matrix,
+          &this->in, in_c, &this->out, out_b, RATIO_CENTER_BASS);
+    }
     if (in_has_front) {
       gst_channel_mix_fill_one_other (this->matrix,
-          &this->in, in_f,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_MONO,
-          &this->out, out_b,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_LFE, RATIO_FRONT_BASS);
+          &this->in, in_f, &this->out, out_b, RATIO_FRONT_BASS);
     }
-    if (in_has_center) {
+    if (in_has_side) {
       gst_channel_mix_fill_one_other (this->matrix,
-          &this->in, in_c,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-          GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-          &this->out, out_b,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_LFE, RATIO_CENTER_BASS);
+          &this->in, in_s, &this->out, out_b, RATIO_REAR_BASS);
     }
     if (in_has_rear) {
       gst_channel_mix_fill_one_other (this->matrix,
-          &this->in, in_r,
-          GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-          GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-          GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
-          &this->out, out_b,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_INVALID,
-          GST_AUDIO_CHANNEL_POSITION_LFE, RATIO_REAR_BASS);
+          &this->in, in_r, &this->out, out_b, RATIO_REAR_BASS);
     }
   }
-
-  /* FIXME: side */
 }
 
 /*
@@ -453,6 +533,9 @@
   }
 
   /* normalize to this */
+  if (top == 0.0)
+    return;
+
   for (j = 0; j < this->out.channels; j++) {
     for (i = 0; i < this->in.channels; i++) {
       this->matrix[i][j] /= top;
@@ -460,6 +543,39 @@
   }
 }
 
+static gboolean
+gst_channel_mix_fill_special (AudioConvertCtx * this)
+{
+  AudioConvertFmt *in = &this->in, *out = &this->out;
+
+  /* Special, standard conversions here */
+
+  /* Mono<->Stereo, just a fast-path */
+  if (in->channels == 2 && out->channels == 1 &&
+      ((in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT &&
+              in->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) ||
+          (in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT &&
+              in->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) &&
+      out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
+    this->matrix[0][0] = 0.5;
+    this->matrix[1][0] = 0.5;
+    return TRUE;
+  } else if (in->channels == 1 && out->channels == 2 &&
+      ((out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT &&
+              out->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) ||
+          (out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT &&
+              out->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) &&
+      in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
+    this->matrix[0][0] = 1.0;
+    this->matrix[0][1] = 1.0;
+    return TRUE;
+  }
+
+  /* TODO: 5.1 <-> Stereo and other standard conversions */
+
+  return FALSE;
+}
+
 /*
  * Automagically generate conversion matrix.
  */
@@ -467,10 +583,16 @@
 static void
 gst_channel_mix_fill_matrix (AudioConvertCtx * this)
 {
+  if (gst_channel_mix_fill_special (this))
+    return;
+
   gst_channel_mix_fill_identical (this);
-  gst_channel_mix_fill_compatible (this);
-  gst_channel_mix_fill_others (this);
-  gst_channel_mix_fill_normalize (this);
+
+  if (!this->in.unpositioned_layout) {
+    gst_channel_mix_fill_compatible (this);
+    gst_channel_mix_fill_others (this);
+    gst_channel_mix_fill_normalize (this);
+  }
 }
 
 /* only call after this->out and this->in are filled in */
@@ -482,7 +604,6 @@
 gst_channel_mix_setup_matrix (AudioConvertCtx * this)
 {
   gint i, j;
-  GString *s;
 
   /* don't lose memory */
   gst_channel_mix_unset_matrix (this);
@@ -505,25 +626,30 @@
   /* setup the matrix' internal values */
   gst_channel_mix_fill_matrix (this);
 
+#ifndef GST_DISABLE_GST_DEBUG
   /* debug */
-  s = g_string_new ("Matrix for");
-  g_string_append_printf (s, " %d -> %d: ",
-      this->in.channels, this->out.channels);
-  g_string_append (s, "{");
-  for (i = 0; i < this->in.channels; i++) {
-    if (i != 0)
-      g_string_append (s, ",");
-    g_string_append (s, " {");
-    for (j = 0; j < this->out.channels; j++) {
-      if (j != 0)
+  {
+    GString *s;
+    s = g_string_new ("Matrix for");
+    g_string_append_printf (s, " %d -> %d: ",
+        this->in.channels, this->out.channels);
+    g_string_append (s, "{");
+    for (i = 0; i < this->in.channels; i++) {
+      if (i != 0)
         g_string_append (s, ",");
-      g_string_append_printf (s, " %f", this->matrix[i][j]);
+      g_string_append (s, " {");
+      for (j = 0; j < this->out.channels; j++) {
+        if (j != 0)
+          g_string_append (s, ",");
+        g_string_append_printf (s, " %f", this->matrix[i][j]);
+      }
+      g_string_append (s, " }");
     }
     g_string_append (s, " }");
+    GST_DEBUG (s->str);
+    g_string_free (s, TRUE);
   }
-  g_string_append (s, " }");
-  GST_DEBUG (s->str);
-  g_string_free (s, TRUE);
+#endif
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioconvert/gstfastrandom.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,90 @@
+/* GStreamer
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * gstfastrandom.h: Fast, bad PNRG
+ *
+ * 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 <glib.h>
+
+#ifndef __GST_FAST_RANDOM__
+#define __GST_FAST_RANDOM__
+
+/* transform [0..2^32] -> [0..1] */
+#define GST_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
+
+/* This is the base function, implementing a linear congruential generator
+ * and returning a pseudo random number between 0 and 2^32 - 1.
+ */
+static inline guint32
+gst_fast_random_uint32 ()
+{
+  static guint32 state = 0xdeadbeef;
+
+  return (state = state * 1103515245 + 12345);
+}
+
+static inline guint32
+gst_fast_random_uint32_range (gint32 start, gint32 end)
+{
+  guint64 tmp = gst_fast_random_uint32 ();
+
+  tmp = (tmp * (end - start)) / G_MAXUINT32 + start;
+
+  return (guint32) tmp;
+}
+
+static inline gint32
+gst_fast_random_int32 (void)
+{
+  return (gint32) gst_fast_random_uint32 ();
+}
+
+static inline gint32
+gst_fast_random_int32_range (gint32 start, gint32 end)
+{
+  gint64 tmp = gst_fast_random_uint32 ();
+
+  tmp = (tmp * (end - start)) / G_MAXUINT32 + start;
+
+  return (gint32) tmp;
+}
+
+static inline gdouble
+gst_fast_random_double (void)
+{
+  gdouble ret;
+
+  ret = gst_fast_random_uint32 () * GST_RAND_DOUBLE_TRANSFORM;
+  ret = (ret + gst_fast_random_uint32 ()) * GST_RAND_DOUBLE_TRANSFORM;
+
+  if (ret >= 1.0)
+    return gst_fast_random_double ();
+
+  return ret;
+}
+
+static inline gdouble
+gst_fast_random_double_range (gdouble start, gdouble end)
+{
+  return gst_fast_random_double () * (end - start) + start;
+}
+
+#undef GST_RAND_DOUBLE_TRANSFORM
+
+#endif /* __GST_FAST_RANDOM__ */
+
--- a/gst_plugins_base/gst/audiorate/gstaudiorate.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audiorate/gstaudiorate.c	Fri Apr 16 15:15:52 2010 +0300
@@ -141,7 +141,6 @@
 EXPORT_C
 #endif
 
-
 static GType
 gst_audio_rate_get_type (void)
 {
@@ -192,20 +191,21 @@
 
   g_object_class_install_property (object_class, ARG_IN,
       g_param_spec_uint64 ("in", "In",
-          "Number of input samples", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+          "Number of input samples", 0, G_MAXUINT64, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_OUT,
-      g_param_spec_uint64 ("out", "Out",
-          "Number of output samples", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+      g_param_spec_uint64 ("out", "Out", "Number of output samples", 0,
+          G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_ADD,
-      g_param_spec_uint64 ("add", "Add",
-          "Number of added samples", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+      g_param_spec_uint64 ("add", "Add", "Number of added samples", 0,
+          G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_DROP,
-      g_param_spec_uint64 ("drop", "Drop",
-          "Number of dropped samples", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+      g_param_spec_uint64 ("drop", "Drop", "Number of dropped samples", 0,
+          G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_SILENT,
       g_param_spec_boolean ("silent", "silent",
-          "Don't emit notify for dropped and duplicated frames",
-          DEFAULT_SILENT, G_PARAM_READWRITE));
+          "Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   element_class->change_state = gst_audio_rate_change_state;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,336 @@
+ arch.h            
+ fixed_arm4.h      
+ fixed_arm5e.h     
+ fixed_bfin.h      
+ fixed_debug.h     
+ fixed_generic.h   
+ resample.c        
+ speex_resampler.h 
+
+are taken from http://git.xiph.org/speex.git/ as of 2008-10-28.
+
+The only changes are:
+
+--- arch.h	2008-11-28 09:57:15.000000000 +0100
++++ arch.h	2008-11-28 09:57:37.000000000 +0100
+@@ -78,7 +78,10 @@
+ #include "../include/speex/speex_types.h"
+ #endif
+ 
++#ifndef ABS
+ #define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
++#endif
++
+ #define ABS16(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 16-bit value.  */
+ #define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+ #define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+@@ -134,6 +137,28 @@
+ 
+ #else
+ 
++#ifdef DOUBLE_PRECISION
++typedef double spx_mem_t;
++typedef double spx_coef_t;
++typedef double spx_lsp_t;
++typedef double spx_sig_t;
++typedef double spx_word16_t;
++typedef double spx_word32_t;
++
++#define Q15ONE 1.0
++#define LPC_SCALING  1.
++#define SIG_SCALING  1.
++#define LSP_SCALING  1.
++#define GAMMA_SCALING 1.
++#define GAIN_SCALING 1.
++#define GAIN_SCALING_1 1.
++
++
++#define VERY_SMALL 1e-20
++#define VERY_LARGE32 1e20
++#define VERY_LARGE16 1e20
++#define Q15_ONE ((spx_word16_t)1.)
++#else /* !DOUBLE_PRECISION */
+ typedef float spx_mem_t;
+ typedef float spx_coef_t;
+ typedef float spx_lsp_t;
+@@ -154,6 +179,7 @@
+ #define VERY_LARGE32 1e15f
+ #define VERY_LARGE16 1e15f
+ #define Q15_ONE ((spx_word16_t)1.f)
++#endif /* DOUBLE_PRECISION */
+ 
+ #define QCONST16(x,bits) (x)
+ #define QCONST32(x,bits) (x)
+--- resample.c	2008-11-28 09:56:42.000000000 +0100
++++ resample.c	2008-11-01 20:38:35.000000000 +0100
+@@ -63,22 +63,27 @@
+ 
+ #ifdef OUTSIDE_SPEEX
+ #include <stdlib.h>
+-static void *
++
++#include <glib.h>
++
++#define EXPORT G_GNUC_INTERNAL
++
++static inline void *
+ speex_alloc (int size)
+ {
+-  return calloc (size, 1);
++  return g_malloc0 (size);
+ }
+ 
+-static void *
++static inline void *
+ speex_realloc (void *ptr, int size)
+ {
+-  return realloc (ptr, size);
++  return g_realloc (ptr, size);
+ }
+ 
+-static void
++static inline void
+ speex_free (void *ptr)
+ {
+-  free (ptr);
++  g_free (ptr);
+ }
+ 
+ #include "speex_resampler.h"
+@@ -90,7 +95,6 @@
+ #include "os_support.h"
+ #endif /* OUTSIDE_SPEEX */
+ 
+-#include "stack_alloc.h"
+ #include <math.h>
+ 
+ #ifndef M_PI
+@@ -263,10 +267,17 @@
+ };
+ 
+ /*8,24,40,56,80,104,128,160,200,256,320*/
++#ifdef DOUBLE_PRECISION
++static double
++compute_func (double x, struct FuncDef *func)
++{
++  double y, frac;
++#else
+ static double
+ compute_func (float x, struct FuncDef *func)
+ {
+   float y, frac;
++#endif
+   double interp[4];
+   int ind;
+   y = x * func->oversample;
+@@ -317,11 +328,19 @@
+ }
+ #else
+ /* The slow way of computing a sinc for the table. Should improve that some day */
++#ifdef DOUBLE_PRECISION
++static spx_word16_t
++sinc (double cutoff, double x, int N, struct FuncDef *window_func)
++{
++  /*fprintf (stderr, "%f ", x); */
++  double xx = x * cutoff;
++#else
+ static spx_word16_t
+ sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+ {
+   /*fprintf (stderr, "%f ", x); */
+   float xx = x * cutoff;
++#endif
+   if (fabs (x) < 1e-6)
+     return cutoff;
+   else if (fabs (x) > .5 * N)
+@@ -372,6 +391,7 @@
+ }
+ #endif
+ 
++#ifndef DOUBLE_PRECISION
+ static int
+ resampler_basic_direct_single (SpeexResamplerState * st,
+     spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+@@ -421,6 +441,7 @@
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+ }
++#endif
+ 
+ #ifdef FIXED_POINT
+ #else
+@@ -476,6 +497,7 @@
+ }
+ #endif
+ 
++#ifndef DOUBLE_PRECISION
+ static int
+ resampler_basic_interpolate_single (SpeexResamplerState * st,
+     spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+@@ -554,6 +576,7 @@
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+ }
++#endif
+ 
+ #ifdef FIXED_POINT
+ #else
+@@ -584,10 +607,16 @@
+         PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+         st->den_rate);
+ #else
++#ifdef DOUBLE_PRECISION
++    const spx_word16_t frac =
++        ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
++        st->den_rate;
++#else
+     const spx_word16_t frac =
+         ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+         st->den_rate;
+ #endif
++#endif
+     spx_word16_t interp[4];
+ 
+ 
+@@ -688,20 +717,27 @@
+       spx_int32_t j;
+       for (j = 0; j < st->filt_len; j++) {
+         st->sinc_table[i * st->filt_len + j] =
+-            sinc (st->cutoff,
+-            ((j - (spx_int32_t) st->filt_len / 2 + 1) -
++            sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
++#ifdef DOUBLE_PRECISION
++                ((double) i) / st->den_rate), st->filt_len,
++#else
+                 ((float) i) / st->den_rate), st->filt_len,
++#endif
+             quality_map[st->quality].window_func);
+       }
+     }
+ #ifdef FIXED_POINT
+     st->resampler_ptr = resampler_basic_direct_single;
+ #else
++#ifdef DOUBLE_PRECISION
++    st->resampler_ptr = resampler_basic_direct_double;
++#else
+     if (st->quality > 8)
+       st->resampler_ptr = resampler_basic_direct_double;
+     else
+       st->resampler_ptr = resampler_basic_direct_single;
+ #endif
++#endif
+     /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
+   } else {
+     spx_int32_t i;
+@@ -717,16 +753,24 @@
+     }
+     for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
+       st->sinc_table[i + 4] =
++#ifdef DOUBLE_PRECISION
++          sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
++#else
+           sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
++#endif
+           st->filt_len, quality_map[st->quality].window_func);
+ #ifdef FIXED_POINT
+     st->resampler_ptr = resampler_basic_interpolate_single;
+ #else
++#ifdef DOUBLE_PRECISION
++    st->resampler_ptr = resampler_basic_interpolate_double;
++#else
+     if (st->quality > 8)
+       st->resampler_ptr = resampler_basic_interpolate_double;
+     else
+       st->resampler_ptr = resampler_basic_interpolate_single;
+ #endif
++#endif
+     /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
+   }
+   st->int_advance = st->num_rate / st->den_rate;
+@@ -956,11 +1000,18 @@
+     spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+     spx_int16_t * out, spx_uint32_t * out_len)
+ #else
++#ifdef DOUBLE_PRECISION
++EXPORT int
++speex_resampler_process_float (SpeexResamplerState * st,
++    spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
++    double *out, spx_uint32_t * out_len)
++#else
+ EXPORT int
+ speex_resampler_process_float (SpeexResamplerState * st,
+     spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+     float *out, spx_uint32_t * out_len)
+ #endif
++#endif
+ {
+   int j;
+   spx_uint32_t ilen = *in_len;
+@@ -1078,9 +1129,16 @@
+   return RESAMPLER_ERR_SUCCESS;
+ }
+ 
++#ifdef DOUBLE_PRECISION
++EXPORT int
++speex_resampler_process_interleaved_float (SpeexResamplerState * st,
++    const double *in, spx_uint32_t * in_len, double *out,
++    spx_uint32_t * out_len)
++#else
+ EXPORT int
+ speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+     const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
++#endif
+ {
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+--- speex_resampler.h	2008-11-28 09:57:15.000000000 +0100
++++ speex_resampler.h	2008-11-28 09:57:37.000000000 +0100
+@@ -77,10 +77,10 @@
+ #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
+ #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
+ 
+-#define spx_int16_t short
+-#define spx_int32_t int
+-#define spx_uint16_t unsigned short
+-#define spx_uint32_t unsigned int
++#define spx_int16_t gint16
++#define spx_int32_t gint32
++#define spx_uint16_t guint16
++#define spx_uint32_t guint32
+ 
+ #else /* OUTSIDE_SPEEX */
+ 
+@@ -162,10 +162,17 @@
+  * @param out Output buffer
+  * @param out_len Size of the output buffer. Returns the number of samples written
+  */
++#ifdef DOUBLE_PRECISION
++  int speex_resampler_process_float (SpeexResamplerState * st,
++      spx_uint32_t channel_index,
++      const double *in,
++      spx_uint32_t * in_len, double *out, spx_uint32_t * out_len);
++#else
+   int speex_resampler_process_float (SpeexResamplerState * st,
+       spx_uint32_t channel_index,
+       const float *in,
+       spx_uint32_t * in_len, float *out, spx_uint32_t * out_len);
++#endif
+ 
+ /** Resample an int array. The input and output buffers must *not* overlap.
+  * @param st Resampler state
+@@ -191,9 +198,15 @@
+  * @param out_len Size of the output buffer. Returns the number of samples written.
+  * This is all per-channel.
+  */
++#ifdef DOUBLE_PRECISION
++  int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
++      const double *in,
++      spx_uint32_t * in_len, double *out, spx_uint32_t * out_len);
++#else
+   int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+       const float *in,
+       spx_uint32_t * in_len, float *out, spx_uint32_t * out_len);
++#endif
+ 
+ /** Resample an interleaved int array. The input and output buffers must *not* overlap.
+  * @param st Resampler state
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/arch_double.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,265 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file arch.h
+   @brief Various architecture definitions Speex
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARCH_H
+#define ARCH_H
+
+#ifndef SPEEX_VERSION
+#define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */
+#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */
+#define SPEEX_MICRO_VERSION 15        /**< Micro Speex version. */
+#define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */
+#define SPEEX_VERSION "speex-1.2beta3"  /**< Speex version string. */
+#endif
+
+/* A couple test to catch stupid option combinations */
+#ifdef FIXED_POINT
+
+#ifdef FLOATING_POINT
+#error You cannot compile as floating point and fixed point at the same time
+#endif
+#ifdef _USE_SSE
+#error SSE is only for floating-point
+#endif
+#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
+#error Make up your mind. What CPU do you have?
+#endif
+#ifdef VORBIS_PSYCHO
+#error Vorbis-psy model currently not implemented in fixed-point
+#endif
+
+#else
+
+#ifndef FLOATING_POINT
+#error You now need to define either FIXED_POINT or FLOATING_POINT
+#endif
+#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
+#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
+#endif
+#ifdef FIXED_POINT_DEBUG
+#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
+#endif
+
+
+#endif
+
+#ifndef OUTSIDE_SPEEX
+#include "../include/speex/speex_types.h"
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
+#endif
+
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 16-bit value.  */
+#define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 32-bit value.  */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+
+#ifdef FIXED_POINT
+
+typedef spx_int16_t spx_word16_t;
+typedef spx_int32_t spx_word32_t;
+typedef spx_word32_t spx_mem_t;
+typedef spx_word16_t spx_coef_t;
+typedef spx_word16_t spx_lsp_t;
+typedef spx_word32_t spx_sig_t;
+
+#define Q15ONE 32767
+
+#define LPC_SCALING  8192
+#define SIG_SCALING  16384
+#define LSP_SCALING  8192.
+#define GAMMA_SCALING 32768.
+#define GAIN_SCALING 64
+#define GAIN_SCALING_1 0.015625
+
+#define LPC_SHIFT    13
+#define LSP_SHIFT    13
+#define SIG_SHIFT    14
+#define GAIN_SHIFT   6
+
+#define VERY_SMALL 0
+#define VERY_LARGE32 ((spx_word32_t)2147483647)
+#define VERY_LARGE16 ((spx_word16_t)32767)
+#define Q15_ONE ((spx_word16_t)32767)
+
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef ARM5E_ASM
+#include "fixed_arm5e.h"
+#elif defined (ARM4_ASM)
+#include "fixed_arm4.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#endif
+
+#endif
+
+
+#else
+
+#ifdef DOUBLE_PRECISION
+typedef double spx_mem_t;
+typedef double spx_coef_t;
+typedef double spx_lsp_t;
+typedef double spx_sig_t;
+typedef double spx_word16_t;
+typedef double spx_word32_t;
+
+#define Q15ONE 1.0
+#define LPC_SCALING  1.
+#define SIG_SCALING  1.
+#define LSP_SCALING  1.
+#define GAMMA_SCALING 1.
+#define GAIN_SCALING 1.
+#define GAIN_SCALING_1 1.
+
+
+#define VERY_SMALL 1e-20
+#define VERY_LARGE32 1e20
+#define VERY_LARGE16 1e20
+#define Q15_ONE ((spx_word16_t)1.)
+#else /* !DOUBLE_PRECISION */
+typedef float spx_mem_t;
+typedef float spx_coef_t;
+typedef float spx_lsp_t;
+typedef float spx_sig_t;
+typedef float spx_word16_t;
+typedef float spx_word32_t;
+
+#define Q15ONE 1.0f
+#define LPC_SCALING  1.f
+#define SIG_SCALING  1.f
+#define LSP_SCALING  1.f
+#define GAMMA_SCALING 1.f
+#define GAIN_SCALING 1.f
+#define GAIN_SCALING_1 1.f
+
+
+#define VERY_SMALL 1e-15f
+#define VERY_LARGE32 1e15f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((spx_word16_t)1.f)
+#endif /* DOUBLE_PRECISION */
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR16(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+#define SATURATE16(x,a) (x)
+#define SATURATE32(x,a) (x)
+
+#define PSHR(a,shift)       (a)
+#define SHR(a,shift)       (a)
+#define SHL(a,shift)       (a)
+#define SATURATE(x,a) (x)
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
+#define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
+
+#define MULT16_32_Q11(a,b)     ((a)*(b))
+#define MULT16_32_Q13(a,b)     ((a)*(b))
+#define MULT16_32_Q14(a,b)     ((a)*(b))
+#define MULT16_32_Q15(a,b)     ((a)*(b))
+#define MULT16_32_P15(a,b)     ((a)*(b))
+
+#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+
+#define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_Q13(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_P13(c,a,b)     ((c)+(a)*(b))
+#define MULT16_16_Q11_32(a,b)     ((a)*(b))
+#define MULT16_16_Q13(a,b)     ((a)*(b))
+#define MULT16_16_Q14(a,b)     ((a)*(b))
+#define MULT16_16_Q15(a,b)     ((a)*(b))
+#define MULT16_16_P15(a,b)     ((a)*(b))
+#define MULT16_16_P13(a,b)     ((a)*(b))
+#define MULT16_16_P14(a,b)     ((a)*(b))
+
+#define DIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define PDIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define DIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+#define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+
+
+#endif
+
+
+#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+/* 2 on TI C5x DSP */
+#define BYTES_PER_CHAR 2
+#define BITS_PER_CHAR 16
+#define LOG2_BITS_PER_CHAR 4
+
+#else
+
+#define BYTES_PER_CHAR 1
+#define BITS_PER_CHAR 8
+#define LOG2_BITS_PER_CHAR 3
+
+#endif
+
+
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/arch_float.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,265 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file arch.h
+   @brief Various architecture definitions Speex
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARCH_H
+#define ARCH_H
+
+#ifndef SPEEX_VERSION
+#define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */
+#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */
+#define SPEEX_MICRO_VERSION 15        /**< Micro Speex version. */
+#define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */
+#define SPEEX_VERSION "speex-1.2beta3"  /**< Speex version string. */
+#endif
+
+/* A couple test to catch stupid option combinations */
+#ifdef FIXED_POINT
+
+#ifdef FLOATING_POINT
+#error You cannot compile as floating point and fixed point at the same time
+#endif
+#ifdef _USE_SSE
+#error SSE is only for floating-point
+#endif
+#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
+#error Make up your mind. What CPU do you have?
+#endif
+#ifdef VORBIS_PSYCHO
+#error Vorbis-psy model currently not implemented in fixed-point
+#endif
+
+#else
+
+#ifndef FLOATING_POINT
+#error You now need to define either FIXED_POINT or FLOATING_POINT
+#endif
+#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
+#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
+#endif
+#ifdef FIXED_POINT_DEBUG
+#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
+#endif
+
+
+#endif
+
+#ifndef OUTSIDE_SPEEX
+#include "../include/speex/speex_types.h"
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
+#endif
+
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 16-bit value.  */
+#define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 32-bit value.  */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+
+#ifdef FIXED_POINT
+
+typedef spx_int16_t spx_word16_t;
+typedef spx_int32_t spx_word32_t;
+typedef spx_word32_t spx_mem_t;
+typedef spx_word16_t spx_coef_t;
+typedef spx_word16_t spx_lsp_t;
+typedef spx_word32_t spx_sig_t;
+
+#define Q15ONE 32767
+
+#define LPC_SCALING  8192
+#define SIG_SCALING  16384
+#define LSP_SCALING  8192.
+#define GAMMA_SCALING 32768.
+#define GAIN_SCALING 64
+#define GAIN_SCALING_1 0.015625
+
+#define LPC_SHIFT    13
+#define LSP_SHIFT    13
+#define SIG_SHIFT    14
+#define GAIN_SHIFT   6
+
+#define VERY_SMALL 0
+#define VERY_LARGE32 ((spx_word32_t)2147483647)
+#define VERY_LARGE16 ((spx_word16_t)32767)
+#define Q15_ONE ((spx_word16_t)32767)
+
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef ARM5E_ASM
+#include "fixed_arm5e.h"
+#elif defined (ARM4_ASM)
+#include "fixed_arm4.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#endif
+
+#endif
+
+
+#else
+
+#ifdef DOUBLE_PRECISION
+typedef double spx_mem_t;
+typedef double spx_coef_t;
+typedef double spx_lsp_t;
+typedef double spx_sig_t;
+typedef double spx_word16_t;
+typedef double spx_word32_t;
+
+#define Q15ONE 1.0
+#define LPC_SCALING  1.
+#define SIG_SCALING  1.
+#define LSP_SCALING  1.
+#define GAMMA_SCALING 1.
+#define GAIN_SCALING 1.
+#define GAIN_SCALING_1 1.
+
+
+#define VERY_SMALL 1e-20
+#define VERY_LARGE32 1e20
+#define VERY_LARGE16 1e20
+#define Q15_ONE ((spx_word16_t)1.)
+#else /* !DOUBLE_PRECISION */
+typedef float spx_mem_t;
+typedef float spx_coef_t;
+typedef float spx_lsp_t;
+typedef float spx_sig_t;
+typedef float spx_word16_t;
+typedef float spx_word32_t;
+
+#define Q15ONE 1.0f
+#define LPC_SCALING  1.f
+#define SIG_SCALING  1.f
+#define LSP_SCALING  1.f
+#define GAMMA_SCALING 1.f
+#define GAIN_SCALING 1.f
+#define GAIN_SCALING_1 1.f
+
+
+#define VERY_SMALL 1e-15f
+#define VERY_LARGE32 1e15f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((spx_word16_t)1.f)
+#endif /* DOUBLE_PRECISION */
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR16(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+#define SATURATE16(x,a) (x)
+#define SATURATE32(x,a) (x)
+
+#define PSHR(a,shift)       (a)
+#define SHR(a,shift)       (a)
+#define SHL(a,shift)       (a)
+#define SATURATE(x,a) (x)
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
+#define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
+
+#define MULT16_32_Q11(a,b)     ((a)*(b))
+#define MULT16_32_Q13(a,b)     ((a)*(b))
+#define MULT16_32_Q14(a,b)     ((a)*(b))
+#define MULT16_32_Q15(a,b)     ((a)*(b))
+#define MULT16_32_P15(a,b)     ((a)*(b))
+
+#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+
+#define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_Q13(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_P13(c,a,b)     ((c)+(a)*(b))
+#define MULT16_16_Q11_32(a,b)     ((a)*(b))
+#define MULT16_16_Q13(a,b)     ((a)*(b))
+#define MULT16_16_Q14(a,b)     ((a)*(b))
+#define MULT16_16_Q15(a,b)     ((a)*(b))
+#define MULT16_16_P15(a,b)     ((a)*(b))
+#define MULT16_16_P13(a,b)     ((a)*(b))
+#define MULT16_16_P14(a,b)     ((a)*(b))
+
+#define DIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define PDIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define DIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+#define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+
+
+#endif
+
+
+#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+/* 2 on TI C5x DSP */
+#define BYTES_PER_CHAR 2
+#define BITS_PER_CHAR 16
+#define LOG2_BITS_PER_CHAR 4
+
+#else
+
+#define BYTES_PER_CHAR 1
+#define BITS_PER_CHAR 8
+#define LOG2_BITS_PER_CHAR 3
+
+#endif
+
+
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/arch_int.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,265 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file arch.h
+   @brief Various architecture definitions Speex
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARCH_H
+#define ARCH_H
+
+#ifndef SPEEX_VERSION
+#define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */
+#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */
+#define SPEEX_MICRO_VERSION 15        /**< Micro Speex version. */
+#define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */
+#define SPEEX_VERSION "speex-1.2beta3"  /**< Speex version string. */
+#endif
+
+/* A couple test to catch stupid option combinations */
+#ifdef FIXED_POINT
+
+#ifdef FLOATING_POINT
+#error You cannot compile as floating point and fixed point at the same time
+#endif
+#ifdef _USE_SSE
+#error SSE is only for floating-point
+#endif
+#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
+#error Make up your mind. What CPU do you have?
+#endif
+#ifdef VORBIS_PSYCHO
+#error Vorbis-psy model currently not implemented in fixed-point
+#endif
+
+#else
+
+#ifndef FLOATING_POINT
+#error You now need to define either FIXED_POINT or FLOATING_POINT
+#endif
+#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
+#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
+#endif
+#ifdef FIXED_POINT_DEBUG
+#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
+#endif
+
+
+#endif
+
+#ifndef OUTSIDE_SPEEX
+#include "../include/speex/speex_types.h"
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
+#endif
+
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 16-bit value.  */
+#define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 32-bit value.  */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+
+#ifdef FIXED_POINT
+
+typedef spx_int16_t spx_word16_t;
+typedef spx_int32_t spx_word32_t;
+typedef spx_word32_t spx_mem_t;
+typedef spx_word16_t spx_coef_t;
+typedef spx_word16_t spx_lsp_t;
+typedef spx_word32_t spx_sig_t;
+
+#define Q15ONE 32767
+
+#define LPC_SCALING  8192
+#define SIG_SCALING  16384
+#define LSP_SCALING  8192.
+#define GAMMA_SCALING 32768.
+#define GAIN_SCALING 64
+#define GAIN_SCALING_1 0.015625
+
+#define LPC_SHIFT    13
+#define LSP_SHIFT    13
+#define SIG_SHIFT    14
+#define GAIN_SHIFT   6
+
+#define VERY_SMALL 0
+#define VERY_LARGE32 ((spx_word32_t)2147483647)
+#define VERY_LARGE16 ((spx_word16_t)32767)
+#define Q15_ONE ((spx_word16_t)32767)
+
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef ARM5E_ASM
+#include "fixed_arm5e.h"
+#elif defined (ARM4_ASM)
+#include "fixed_arm4.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#endif
+
+#endif
+
+
+#else
+
+#ifdef DOUBLE_PRECISION
+typedef double spx_mem_t;
+typedef double spx_coef_t;
+typedef double spx_lsp_t;
+typedef double spx_sig_t;
+typedef double spx_word16_t;
+typedef double spx_word32_t;
+
+#define Q15ONE 1.0
+#define LPC_SCALING  1.
+#define SIG_SCALING  1.
+#define LSP_SCALING  1.
+#define GAMMA_SCALING 1.
+#define GAIN_SCALING 1.
+#define GAIN_SCALING_1 1.
+
+
+#define VERY_SMALL 1e-20
+#define VERY_LARGE32 1e20
+#define VERY_LARGE16 1e20
+#define Q15_ONE ((spx_word16_t)1.)
+#else /* !DOUBLE_PRECISION */
+typedef float spx_mem_t;
+typedef float spx_coef_t;
+typedef float spx_lsp_t;
+typedef float spx_sig_t;
+typedef float spx_word16_t;
+typedef float spx_word32_t;
+
+#define Q15ONE 1.0f
+#define LPC_SCALING  1.f
+#define SIG_SCALING  1.f
+#define LSP_SCALING  1.f
+#define GAMMA_SCALING 1.f
+#define GAIN_SCALING 1.f
+#define GAIN_SCALING_1 1.f
+
+
+#define VERY_SMALL 1e-15f
+#define VERY_LARGE32 1e15f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((spx_word16_t)1.f)
+#endif /* DOUBLE_PRECISION */
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR16(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+#define SATURATE16(x,a) (x)
+#define SATURATE32(x,a) (x)
+
+#define PSHR(a,shift)       (a)
+#define SHR(a,shift)       (a)
+#define SHL(a,shift)       (a)
+#define SATURATE(x,a) (x)
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
+#define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
+
+#define MULT16_32_Q11(a,b)     ((a)*(b))
+#define MULT16_32_Q13(a,b)     ((a)*(b))
+#define MULT16_32_Q14(a,b)     ((a)*(b))
+#define MULT16_32_Q15(a,b)     ((a)*(b))
+#define MULT16_32_P15(a,b)     ((a)*(b))
+
+#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+
+#define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_Q13(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_P13(c,a,b)     ((c)+(a)*(b))
+#define MULT16_16_Q11_32(a,b)     ((a)*(b))
+#define MULT16_16_Q13(a,b)     ((a)*(b))
+#define MULT16_16_Q14(a,b)     ((a)*(b))
+#define MULT16_16_Q15(a,b)     ((a)*(b))
+#define MULT16_16_P15(a,b)     ((a)*(b))
+#define MULT16_16_P13(a,b)     ((a)*(b))
+#define MULT16_16_P14(a,b)     ((a)*(b))
+
+#define DIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define PDIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define DIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+#define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+
+
+#endif
+
+
+#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+/* 2 on TI C5x DSP */
+#define BYTES_PER_CHAR 2
+#define BITS_PER_CHAR 16
+#define LOG2_BITS_PER_CHAR 4
+
+#else
+
+#define BYTES_PER_CHAR 1
+#define BITS_PER_CHAR 8
+#define LOG2_BITS_PER_CHAR 3
+
+#endif
+
+
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+
+#endif
--- a/gst_plugins_base/gst/audioresample/buffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-
-#ifndef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-#include <string.h>
-
-#include "buffer.h"
-#include "debug.h"
-
-static void audioresample_buffer_free_mem (AudioresampleBuffer * buffer,
-    void *);
-static void audioresample_buffer_free_subbuffer (AudioresampleBuffer * buffer,
-    void *priv);
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-
-AudioresampleBuffer *
-audioresample_buffer_new (void)
-{
-  AudioresampleBuffer *buffer;
-
-  buffer = g_new0 (AudioresampleBuffer, 1);
-  buffer->ref_count = 1;
-  return buffer;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-AudioresampleBuffer *
-audioresample_buffer_new_and_alloc (int size)
-{
-  AudioresampleBuffer *buffer = audioresample_buffer_new ();
-
-  buffer->data = g_malloc (size);
-  buffer->length = size;
-  buffer->free = audioresample_buffer_free_mem;
-
-  return buffer;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-AudioresampleBuffer *
-audioresample_buffer_new_with_data (void *data, int size)
-{
-  AudioresampleBuffer *buffer = audioresample_buffer_new ();
-
-  buffer->data = data;
-  buffer->length = size;
-  buffer->free = audioresample_buffer_free_mem;
-
-  return buffer;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-AudioresampleBuffer *
-audioresample_buffer_new_subbuffer (AudioresampleBuffer * buffer, int offset,
-    int length)
-{
-  AudioresampleBuffer *subbuffer = audioresample_buffer_new ();
-
-  if (buffer->parent) {
-    audioresample_buffer_ref (buffer->parent);
-    subbuffer->parent = buffer->parent;
-  } else {
-    audioresample_buffer_ref (buffer);
-    subbuffer->parent = buffer;
-  }
-  subbuffer->data = buffer->data + offset;
-  subbuffer->length = length;
-  subbuffer->free = audioresample_buffer_free_subbuffer;
-
-  return subbuffer;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-audioresample_buffer_ref (AudioresampleBuffer * buffer)
-{
-  buffer->ref_count++;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-audioresample_buffer_unref (AudioresampleBuffer * buffer)
-{
-  buffer->ref_count--;
-  if (buffer->ref_count == 0) {
-    if (buffer->free)
-      buffer->free (buffer, buffer->priv);
-    g_free (buffer);
-  }
-}
-
-static void
-audioresample_buffer_free_mem (AudioresampleBuffer * buffer, void *priv)
-{
-  g_free (buffer->data);
-}
-
-static void
-audioresample_buffer_free_subbuffer (AudioresampleBuffer * buffer, void *priv)
-{
-  audioresample_buffer_unref (buffer->parent);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-
-AudioresampleBufferQueue *
-audioresample_buffer_queue_new (void)
-{
-  return g_new0 (AudioresampleBufferQueue, 1);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-audioresample_buffer_queue_get_depth (AudioresampleBufferQueue * queue)
-{
-  return queue->depth;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-audioresample_buffer_queue_get_offset (AudioresampleBufferQueue * queue)
-{
-  return queue->offset;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-audioresample_buffer_queue_free (AudioresampleBufferQueue * queue)
-{
-  GList *g;
-
-  for (g = g_list_first (queue->buffers); g; g = g_list_next (g)) {
-    audioresample_buffer_unref ((AudioresampleBuffer *) g->data);
-  }
-  g_list_free (queue->buffers);
-  g_free (queue);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-audioresample_buffer_queue_push (AudioresampleBufferQueue * queue,
-    AudioresampleBuffer * buffer)
-{
-  queue->buffers = g_list_append (queue->buffers, buffer);
-  queue->depth += buffer->length;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-AudioresampleBuffer *
-audioresample_buffer_queue_pull (AudioresampleBufferQueue * queue, int length)
-{
-  GList *g;
-  AudioresampleBuffer *newbuffer;
-  AudioresampleBuffer *buffer;
-  AudioresampleBuffer *subbuffer;
-
-  g_return_val_if_fail (length > 0, NULL);
-
-  if (queue->depth < length) {
-    return NULL;
-  }
-
-  RESAMPLE_LOG ("pulling %d, %d available", length, queue->depth);
-
-  g = g_list_first (queue->buffers);
-  buffer = g->data;
-
-  if (buffer->length > length) {
-    newbuffer = audioresample_buffer_new_subbuffer (buffer, 0, length);
-
-    subbuffer = audioresample_buffer_new_subbuffer (buffer, length,
-        buffer->length - length);
-    g->data = subbuffer;
-    audioresample_buffer_unref (buffer);
-  } else {
-    int offset = 0;
-
-    newbuffer = audioresample_buffer_new_and_alloc (length);
-
-    while (offset < length) {
-      g = g_list_first (queue->buffers);
-      buffer = g->data;
-
-      if (buffer->length > length - offset) {
-        int n = length - offset;
-
-        memcpy (newbuffer->data + offset, buffer->data, n);
-        subbuffer =
-            audioresample_buffer_new_subbuffer (buffer, n, buffer->length - n);
-        g->data = subbuffer;
-        audioresample_buffer_unref (buffer);
-        offset += n;
-      } else {
-        memcpy (newbuffer->data + offset, buffer->data, buffer->length);
-
-        queue->buffers = g_list_delete_link (queue->buffers, g);
-        offset += buffer->length;
-        audioresample_buffer_unref (buffer);
-      }
-    }
-  }
-
-  queue->depth -= length;
-  queue->offset += length;
-
-  return newbuffer;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-AudioresampleBuffer *
-audioresample_buffer_queue_peek (AudioresampleBufferQueue * queue, int length)
-{
-  GList *g;
-  AudioresampleBuffer *newbuffer;
-  AudioresampleBuffer *buffer;
-  int offset = 0;
-
-  g_return_val_if_fail (length > 0, NULL);
-
-  if (queue->depth < length) {
-    return NULL;
-  }
-
-  RESAMPLE_LOG ("peeking %d, %d available", length, queue->depth);
-
-  g = g_list_first (queue->buffers);
-  buffer = g->data;
-  if (buffer->length > length) {
-    newbuffer = audioresample_buffer_new_subbuffer (buffer, 0, length);
-  } else {
-    newbuffer = audioresample_buffer_new_and_alloc (length);
-    while (offset < length) {
-      buffer = g->data;
-
-      if (buffer->length > length - offset) {
-        int n = length - offset;
-
-        memcpy (newbuffer->data + offset, buffer->data, n);
-        offset += n;
-      } else {
-        memcpy (newbuffer->data + offset, buffer->data, buffer->length);
-        offset += buffer->length;
-      }
-      g = g_list_next (g);
-    }
-  }
-
-  return newbuffer;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-audioresample_buffer_queue_flush (AudioresampleBufferQueue * queue)
-{
-  GList *g;
-
-  for (g = g_list_first (queue->buffers); g; g = g_list_next (g)) {
-    audioresample_buffer_unref ((AudioresampleBuffer *) g->data);
-  }
-  g_list_free (queue->buffers);
-  queue->buffers = NULL;
-  queue->depth = 0;
-  queue->offset = 0;
-}
--- a/gst_plugins_base/gst/audioresample/buffer.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-
-#ifndef __AUDIORESAMPLE_BUFFER_H__
-#define __AUDIORESAMPLE_BUFFER_H__
-
-#include <glib.h>
-
-typedef struct _AudioresampleBuffer AudioresampleBuffer;
-typedef struct _AudioresampleBufferQueue AudioresampleBufferQueue;
-
-struct _AudioresampleBuffer
-{
-  unsigned char *data;
-  int length;
-
-  int ref_count;
-
-  AudioresampleBuffer *parent;
-
-  void (*free) (AudioresampleBuffer *, void *);
-  void *priv;
-  void *priv2;
-};
-
-struct _AudioresampleBufferQueue
-{
-  GList *buffers;
-  int depth;
-  int offset;
-};
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-AudioresampleBuffer *   audioresample_buffer_new                (void);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-AudioresampleBuffer *   audioresample_buffer_new_and_alloc      (int size);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-AudioresampleBuffer *   audioresample_buffer_new_with_data      (void *data, int size);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-AudioresampleBuffer *   audioresample_buffer_new_subbuffer      (AudioresampleBuffer * buffer, 
-                                                                 int offset,
-                                                                 int length);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void                    audioresample_buffer_ref                (AudioresampleBuffer * buffer);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void                    audioresample_buffer_unref              (AudioresampleBuffer * buffer);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-AudioresampleBufferQueue *      
-                        audioresample_buffer_queue_new          (void);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void                    audioresample_buffer_queue_free         (AudioresampleBufferQueue * queue);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-int                     audioresample_buffer_queue_get_depth    (AudioresampleBufferQueue * queue);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-int                     audioresample_buffer_queue_get_offset   (AudioresampleBufferQueue * queue);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void                    audioresample_buffer_queue_push         (AudioresampleBufferQueue * queue,
-                                                                 AudioresampleBuffer * buffer);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-AudioresampleBuffer *   audioresample_buffer_queue_pull         (AudioresampleBufferQueue * queue, int len);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-AudioresampleBuffer *   audioresample_buffer_queue_peek         (AudioresampleBufferQueue * queue, int len);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void                    audioresample_buffer_queue_flush        (AudioresampleBufferQueue * queue);
-
-#endif
--- a/gst_plugins_base/gst/audioresample/debug.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-
-#ifndef __RESAMPLE_DEBUG_H__
-#define __RESAMPLE_DEBUG_H__
-
-#if 0
-enum
-{
-  RESAMPLE_LEVEL_NONE = 0,
-  RESAMPLE_LEVEL_ERROR,
-  RESAMPLE_LEVEL_WARNING,
-  RESAMPLE_LEVEL_INFO,
-  RESAMPLE_LEVEL_DEBUG,
-  RESAMPLE_LEVEL_LOG
-};
-
-#define RESAMPLE_ERROR(...) \
-  RESAMPLE_DEBUG_LEVEL(RESAMPLE_LEVEL_ERROR, __VA_ARGS__)
-#define RESAMPLE_WARNING(...) \
-  RESAMPLE_DEBUG_LEVEL(RESAMPLE_LEVEL_WARNING, __VA_ARGS__)
-#define RESAMPLE_INFO(...) \
-  RESAMPLE_DEBUG_LEVEL(RESAMPLE_LEVEL_INFO, __VA_ARGS__)
-#define RESAMPLE_DEBUG(...) \
-  RESAMPLE_DEBUG_LEVEL(RESAMPLE_LEVEL_DEBUG, __VA_ARGS__)
-#define RESAMPLE_LOG(...) \
-  RESAMPLE_DEBUG_LEVEL(RESAMPLE_LEVEL_LOG, __VA_ARGS__)
-
-#define RESAMPLE_DEBUG_LEVEL(level,...) \
-  resample_debug_log ((level), __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
-
-void resample_debug_log (int level, const char *file, const char *function,
-    int line, const char *format, ...);
-void resample_debug_set_level (int level);
-int resample_debug_get_level (void);
-#else
-
-#include <gst/gst.h>
-
-GST_DEBUG_CATEGORY_EXTERN (libaudioresample_debug);
-#define GST_CAT_DEFAULT libaudioresample_debug
-
-#define RESAMPLE_ERROR GST_ERROR
-#define RESAMPLE_WARNING GST_WARNING
-#define RESAMPLE_INFO GST_INFO
-#define RESAMPLE_DEBUG GST_DEBUG
-#define RESAMPLE_LOG GST_LOG
-
-#define resample_debug_set_level(x) do { } while (0)
-
-#endif
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/fixed_arm4.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,130 @@
+/* Copyright (C) 2004 Jean-Marc Valin */
+/**
+   @file fixed_arm4.h
+   @brief ARM4 fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_ARM4_H
+#define FIXED_ARM4_H
+
+#undef MULT16_32_Q14
+static inline spx_word32_t
+MULT16_32_Q14 (spx_word16_t x, spx_word32_t y)
+{
+  int res;
+  int dummy;
+asm ("smull  %0,%1,%2,%3 \n\t" "mov %0, %0, lsr #14 \n\t" "add %0, %0, %1, lsl #18 \n\t":"=&r" (res),
+      "=&r"
+      (dummy)
+:    "r" (y), "r" ((int) x));
+  return (res);
+}
+
+#undef MULT16_32_Q15
+static inline spx_word32_t
+MULT16_32_Q15 (spx_word16_t x, spx_word32_t y)
+{
+  int res;
+  int dummy;
+asm ("smull  %0,%1,%2,%3 \n\t" "mov %0, %0, lsr #15 \n\t" "add %0, %0, %1, lsl #17 \n\t":"=&r" (res),
+      "=&r"
+      (dummy)
+:    "r" (y), "r" ((int) x));
+  return (res);
+}
+
+#undef DIV32_16
+static inline short
+DIV32_16 (int a, int b)
+{
+  int res = 0;
+  int dead1, dead2, dead3, dead4, dead5;
+  __asm__ __volatile__ ("\teor %5, %0, %1\n"
+      "\tmovs %4, %0\n"
+      "\trsbmi %0, %0, #0 \n"
+      "\tmovs %4, %1\n"
+      "\trsbmi %1, %1, #0 \n"
+      "\tmov %4, #1\n"
+      "\tsubs %3, %0, %1, asl #14 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #14 \n"
+      "\tsubs %3, %0, %1, asl #13 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #13 \n"
+      "\tsubs %3, %0, %1, asl #12 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #12 \n"
+      "\tsubs %3, %0, %1, asl #11 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #11 \n"
+      "\tsubs %3, %0, %1, asl #10 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #10 \n"
+      "\tsubs %3, %0, %1, asl #9 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #9 \n"
+      "\tsubs %3, %0, %1, asl #8 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #8 \n"
+      "\tsubs %3, %0, %1, asl #7 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #7 \n"
+      "\tsubs %3, %0, %1, asl #6 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #6 \n"
+      "\tsubs %3, %0, %1, asl #5 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #5 \n"
+      "\tsubs %3, %0, %1, asl #4 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #4 \n"
+      "\tsubs %3, %0, %1, asl #3 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #3 \n"
+      "\tsubs %3, %0, %1, asl #2 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #2 \n"
+      "\tsubs %3, %0, %1, asl #1 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4, asl #1 \n"
+      "\tsubs %3, %0, %1 \n"
+      "\tmovpl %0, %3 \n"
+      "\torrpl %2, %2, %4 \n"
+      "\tmovs %5, %5, lsr #31 \n"
+      "\trsbne %2, %2, #0 \n":"=r" (dead1), "=r" (dead2), "=r" (res),
+      "=r" (dead3), "=r" (dead4), "=r" (dead5)
+      :"0" (a), "1" (b), "2" (res)
+      :"cc");
+  return res;
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/fixed_arm5e.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,166 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file fixed_arm5e.h
+   @brief ARM-tuned fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_ARM5E_H
+#define FIXED_ARM5E_H
+
+#undef MULT16_16
+static inline spx_word32_t
+MULT16_16 (spx_word16_t x, spx_word16_t y)
+{
+  int res;
+asm ("smulbb  %0,%1,%2;\n":"=&r" (res)
+:    "%r" (x), "r" (y));
+  return (res);
+}
+
+#undef MAC16_16
+static inline spx_word32_t
+MAC16_16 (spx_word32_t a, spx_word16_t x, spx_word32_t y)
+{
+  int res;
+asm ("smlabb  %0,%1,%2,%3;\n":"=&r" (res)
+:    "%r" (x), "r" (y), "r" (a));
+  return (res);
+}
+
+#undef MULT16_32_Q15
+static inline spx_word32_t
+MULT16_32_Q15 (spx_word16_t x, spx_word32_t y)
+{
+  int res;
+asm ("smulwb  %0,%1,%2;\n":"=&r" (res)
+:    "%r" (y << 1), "r" (x));
+  return (res);
+}
+
+#undef MAC16_32_Q15
+static inline spx_word32_t
+MAC16_32_Q15 (spx_word32_t a, spx_word16_t x, spx_word32_t y)
+{
+  int res;
+asm ("smlawb  %0,%1,%2,%3;\n":"=&r" (res)
+:    "%r" (y << 1), "r" (x), "r" (a));
+  return (res);
+}
+
+#undef MULT16_32_Q11
+static inline spx_word32_t
+MULT16_32_Q11 (spx_word16_t x, spx_word32_t y)
+{
+  int res;
+asm ("smulwb  %0,%1,%2;\n":"=&r" (res)
+:    "%r" (y << 5), "r" (x));
+  return (res);
+}
+
+#undef MAC16_32_Q11
+static inline spx_word32_t
+MAC16_32_Q11 (spx_word32_t a, spx_word16_t x, spx_word32_t y)
+{
+  int res;
+asm ("smlawb  %0,%1,%2,%3;\n":"=&r" (res)
+:    "%r" (y << 5), "r" (x), "r" (a));
+  return (res);
+}
+
+#undef DIV32_16
+static inline short
+DIV32_16 (int a, int b)
+{
+  int res = 0;
+  int dead1, dead2, dead3, dead4, dead5;
+  __asm__ __volatile__ ("\teor %5, %0, %1\n"
+      "\tmovs %4, %0\n"
+      "\trsbmi %0, %0, #0 \n"
+      "\tmovs %4, %1\n"
+      "\trsbmi %1, %1, #0 \n"
+      "\tmov %4, #1\n"
+      "\tsubs %3, %0, %1, asl #14 \n"
+      "\torrpl %2, %2, %4, asl #14 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #13 \n"
+      "\torrpl %2, %2, %4, asl #13 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #12 \n"
+      "\torrpl %2, %2, %4, asl #12 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #11 \n"
+      "\torrpl %2, %2, %4, asl #11 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #10 \n"
+      "\torrpl %2, %2, %4, asl #10 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #9 \n"
+      "\torrpl %2, %2, %4, asl #9 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #8 \n"
+      "\torrpl %2, %2, %4, asl #8 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #7 \n"
+      "\torrpl %2, %2, %4, asl #7 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #6 \n"
+      "\torrpl %2, %2, %4, asl #6 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #5 \n"
+      "\torrpl %2, %2, %4, asl #5 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #4 \n"
+      "\torrpl %2, %2, %4, asl #4 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #3 \n"
+      "\torrpl %2, %2, %4, asl #3 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #2 \n"
+      "\torrpl %2, %2, %4, asl #2 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1, asl #1 \n"
+      "\torrpl %2, %2, %4, asl #1 \n"
+      "\tmovpl %0, %3 \n"
+      "\tsubs %3, %0, %1 \n"
+      "\torrpl %2, %2, %4 \n"
+      "\tmovpl %0, %3 \n"
+      "\tmovs %5, %5, lsr #31 \n"
+      "\trsbne %2, %2, #0 \n":"=r" (dead1), "=r" (dead2), "=r" (res),
+      "=r" (dead3), "=r" (dead4), "=r" (dead5)
+      :"0" (a), "1" (b), "2" (res)
+      :"memory", "cc");
+  return res;
+}
+
+
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/fixed_bfin.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,134 @@
+/* Copyright (C) 2005 Analog Devices
+   Author: Jean-Marc Valin */
+/**
+   @file fixed_bfin.h
+   @brief Blackfin fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_BFIN_H
+#define FIXED_BFIN_H
+
+#undef PDIV32_16
+static inline spx_word16_t
+PDIV32_16 (spx_word32_t a, spx_word16_t b)
+{
+  spx_word32_t res, bb;
+  bb = b;
+  a += b >> 1;
+  __asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t"
+      //"R0 = R0 + R1;\n\t"
+"R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m"
+      (res)
+:    "m" (a), "m" (bb)
+:    "P0", "R0", "R1", "cc");
+  return res;
+}
+
+#undef DIV32_16
+static inline spx_word16_t
+DIV32_16 (spx_word32_t a, spx_word16_t b)
+{
+  spx_word32_t res, bb;
+  bb = b;
+  /* Make the roundinf consistent with the C version 
+     (do we need to do that?) */
+  if (a < 0)
+    a += (b - 1);
+__asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" "R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" (res)
+:    "m" (a), "m" (bb)
+:    "P0", "R0", "R1", "cc");
+  return res;
+}
+
+#undef MAX16
+static inline spx_word16_t
+MAX16 (spx_word16_t a, spx_word16_t b)
+{
+  spx_word32_t res;
+__asm__ ("%1 = %1.L (X);\n\t" "%2 = %2.L (X);\n\t" "%0 = MAX(%1,%2);":"=d" (res)
+:    "%d" (a), "d" (b)
+      );
+  return res;
+}
+
+#undef MULT16_32_Q15
+static inline spx_word32_t
+MULT16_32_Q15 (spx_word16_t a, spx_word32_t b)
+{
+  spx_word32_t res;
+__asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H) ;\n\t":"=&W" (res),
+      "=&d"
+      (b)
+:    "d" (a), "1" (b)
+:    "A1");
+  return res;
+}
+
+#undef MAC16_32_Q15
+static inline spx_word32_t
+MAC16_32_Q15 (spx_word32_t c, spx_word16_t a, spx_word32_t b)
+{
+  spx_word32_t res;
+__asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res),
+      "=&d"
+      (b)
+:    "d" (a), "1" (b), "d" (c)
+:    "A1");
+  return res;
+}
+
+#undef MULT16_32_Q14
+static inline spx_word32_t
+MULT16_32_Q14 (spx_word16_t a, spx_word32_t b)
+{
+  spx_word32_t res;
+__asm__ ("%2 <<= 1;\n\t" "A1 = %1.L*%2.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %1.L*%2.H);\n\t":"=W" (res), "=d" (a),
+      "=d"
+      (b)
+:    "1" (a), "2" (b)
+:    "A1");
+  return res;
+}
+
+#undef MAC16_32_Q14
+static inline spx_word32_t
+MAC16_32_Q14 (spx_word32_t c, spx_word16_t a, spx_word32_t b)
+{
+  spx_word32_t res;
+__asm__ ("%1 <<= 1;\n\t" "A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res),
+      "=&d"
+      (b)
+:    "d" (a), "1" (b), "d" (c)
+:    "A1");
+  return res;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/fixed_debug.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,525 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file fixed_debug.h
+   @brief Fixed-point operations with debugging
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_DEBUG_H
+#define FIXED_DEBUG_H
+
+#include <stdio.h>
+
+extern long long spx_mips;
+#define MIPS_INC spx_mips++,
+
+#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+
+
+#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
+#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
+
+static inline short
+NEG16 (int x)
+{
+  int res;
+  if (!VERIFY_SHORT (x)) {
+    fprintf (stderr, "NEG16: input is not short: %d\n", (int) x);
+  }
+  res = -x;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "NEG16: output is not short: %d\n", (int) res);
+  spx_mips++;
+  return res;
+}
+
+static inline int
+NEG32 (long long x)
+{
+  long long res;
+  if (!VERIFY_INT (x)) {
+    fprintf (stderr, "NEG16: input is not int: %d\n", (int) x);
+  }
+  res = -x;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "NEG16: output is not int: %d\n", (int) res);
+  spx_mips++;
+  return res;
+}
+
+#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
+static inline short
+_EXTRACT16 (int x, char *file, int line)
+{
+  int res;
+  if (!VERIFY_SHORT (x)) {
+    fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x,
+        file, line);
+  }
+  res = x;
+  spx_mips++;
+  return res;
+}
+
+#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
+static inline int
+_EXTEND32 (int x, char *file, int line)
+{
+  int res;
+  if (!VERIFY_SHORT (x)) {
+    fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x,
+        file, line);
+  }
+  res = x;
+  spx_mips++;
+  return res;
+}
+
+#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
+static inline short
+_SHR16 (int a, int shift, char *file, int line)
+{
+  int res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (shift)) {
+    fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n",
+        a, shift, file, line);
+  }
+  res = a >> shift;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res,
+        file, line);
+  spx_mips++;
+  return res;
+}
+
+#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
+static inline short
+_SHL16 (int a, int shift, char *file, int line)
+{
+  int res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (shift)) {
+    fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a,
+        shift, file, line);
+  }
+  res = a << shift;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res,
+        file, line);
+  spx_mips++;
+  return res;
+}
+
+static inline int
+SHR32 (long long a, int shift)
+{
+  long long res;
+  if (!VERIFY_INT (a) || !VERIFY_SHORT (shift)) {
+    fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int) a, shift);
+  }
+  res = a >> shift;
+  if (!VERIFY_INT (res)) {
+    fprintf (stderr, "SHR32: output is not int: %d\n", (int) res);
+  }
+  spx_mips++;
+  return res;
+}
+
+static inline int
+SHL32 (long long a, int shift)
+{
+  long long res;
+  if (!VERIFY_INT (a) || !VERIFY_SHORT (shift)) {
+    fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int) a, shift);
+  }
+  res = a << shift;
+  if (!VERIFY_INT (res)) {
+    fprintf (stderr, "SHL32: output is not int: %d\n", (int) res);
+  }
+  spx_mips++;
+  return res;
+}
+
+#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
+#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift))
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+
+#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+//#define SHR(a,shift) ((a) >> (shift))
+//#define SHL(a,shift) ((a) << (shift))
+
+#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
+static inline short
+_ADD16 (int a, int b, char *file, int line)
+{
+  int res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a,
+        b, file, line);
+  }
+  res = a + b;
+  if (!VERIFY_SHORT (res)) {
+    fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,
+        b, res, file, line);
+  }
+  spx_mips++;
+  return res;
+}
+
+#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
+static inline short
+_SUB16 (int a, int b, char *file, int line)
+{
+  int res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a,
+        b, file, line);
+  }
+  res = a - b;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res,
+        file, line);
+  spx_mips++;
+  return res;
+}
+
+#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
+static inline int
+_ADD32 (long long a, long long b, char *file, int line)
+{
+  long long res;
+  if (!VERIFY_INT (a) || !VERIFY_INT (b)) {
+    fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n",
+        (int) a, (int) b, file, line);
+  }
+  res = a + b;
+  if (!VERIFY_INT (res)) {
+    fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int) res,
+        file, line);
+  }
+  spx_mips++;
+  return res;
+}
+
+static inline int
+SUB32 (long long a, long long b)
+{
+  long long res;
+  if (!VERIFY_INT (a) || !VERIFY_INT (b)) {
+    fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int) a, (int) b);
+  }
+  res = a - b;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "SUB32: output is not int: %d\n", (int) res);
+  spx_mips++;
+  return res;
+}
+
+#define ADD64(a,b) (MIPS_INC(a)+(b))
+
+/* result fits in 16 bits */
+static inline short
+MULT16_16_16 (int a, int b)
+{
+  int res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
+  }
+  res = a * b;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
+  spx_mips++;
+  return res;
+}
+
+#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
+static inline int
+_MULT16_16 (int a, int b, char *file, int line)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n",
+        a, b, file, line);
+  }
+  res = ((long long) a) * b;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n",
+        (int) res, file, line);
+  spx_mips++;
+  return res;
+}
+
+#define MAC16_16(c,a,b)     (spx_mips--,ADD32((c),MULT16_16((a),(b))))
+#define MAC16_16_Q11(c,a,b)     (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11)))))
+#define MAC16_16_Q13(c,a,b)     (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13)))))
+#define MAC16_16_P13(c,a,b)     (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13))))
+
+
+#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
+static inline int
+_MULT16_32_QX (int a, long long b, int Q, char *file, int line)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_INT (b)) {
+    fprintf (stderr,
+        "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q,
+        (int) a, (int) b, file, line);
+  }
+  if (ABS32 (b) >= (EXTEND32 (1) << (15 + Q)))
+    fprintf (stderr,
+        "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q,
+        (int) a, (int) b, file, line);
+  res = (((long long) a) * (long long) b) >> Q;
+  if (!VERIFY_INT (res))
+    fprintf (stderr,
+        "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q,
+        (int) a, (int) b, (int) res, file, line);
+  spx_mips += 5;
+  return res;
+}
+
+static inline int
+MULT16_32_PX (int a, long long b, int Q)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_INT (b)) {
+    fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q,
+        (int) a, (int) b);
+  }
+  if (ABS32 (b) >= (EXTEND32 (1) << (15 + Q)))
+    fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q,
+        (int) a, (int) b);
+  res = ((((long long) a) * (long long) b) + ((EXTEND32 (1) << Q) >> 1)) >> Q;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int) a,
+        (int) b, (int) res);
+  spx_mips += 5;
+  return res;
+}
+
+
+#define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
+#define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
+#define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
+#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
+#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
+#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
+#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
+#define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
+
+static inline int
+SATURATE (int a, int b)
+{
+  if (a > b)
+    a = b;
+  if (a < -b)
+    a = -b;
+  return a;
+}
+
+static inline int
+MULT16_16_Q11_32 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res >>= 11;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int) a,
+        (int) b, (int) res);
+  spx_mips += 3;
+  return res;
+}
+
+static inline short
+MULT16_16_Q13 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res >>= 13;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b,
+        (int) res);
+  spx_mips += 3;
+  return res;
+}
+
+static inline short
+MULT16_16_Q14 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res >>= 14;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int) res);
+  spx_mips += 3;
+  return res;
+}
+
+static inline short
+MULT16_16_Q15 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res >>= 15;
+  if (!VERIFY_SHORT (res)) {
+    fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int) res);
+  }
+  spx_mips += 3;
+  return res;
+}
+
+static inline short
+MULT16_16_P13 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res += 4096;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int) res);
+  res >>= 13;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b,
+        (int) res);
+  spx_mips += 4;
+  return res;
+}
+
+static inline short
+MULT16_16_P14 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res += 8192;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int) res);
+  res >>= 14;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b,
+        (int) res);
+  spx_mips += 4;
+  return res;
+}
+
+static inline short
+MULT16_16_P15 (int a, int b)
+{
+  long long res;
+  if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
+  }
+  res = ((long long) a) * b;
+  res += 16384;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int) res);
+  res >>= 15;
+  if (!VERIFY_SHORT (res))
+    fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b,
+        (int) res);
+  spx_mips += 4;
+  return res;
+}
+
+#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
+
+static inline int
+_DIV32_16 (long long a, long long b, char *file, int line)
+{
+  long long res;
+  if (b == 0) {
+    fprintf (stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n",
+        (int) a, (int) b, file, line);
+    return 0;
+  }
+  if (!VERIFY_INT (a) || !VERIFY_SHORT (b)) {
+    fprintf (stderr,
+        "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int) a,
+        (int) b, file, line);
+  }
+  res = a / b;
+  if (!VERIFY_SHORT (res)) {
+    fprintf (stderr,
+        "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int) a,
+        (int) b, (int) res, file, line);
+    if (res > 32767)
+      res = 32767;
+    if (res < -32768)
+      res = -32768;
+  }
+  spx_mips += 20;
+  return res;
+}
+
+#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
+static inline int
+_DIV32 (long long a, long long b, char *file, int line)
+{
+  long long res;
+  if (b == 0) {
+    fprintf (stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int) a,
+        (int) b, file, line);
+    return 0;
+  }
+
+  if (!VERIFY_INT (a) || !VERIFY_INT (b)) {
+    fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n",
+        (int) a, (int) b, file, line);
+  }
+  res = a / b;
+  if (!VERIFY_INT (res))
+    fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int) res,
+        file, line);
+  spx_mips += 36;
+  return res;
+}
+
+#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
+#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/fixed_generic.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,106 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file fixed_generic.h
+   @brief Generic fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_GENERIC_H
+#define FIXED_GENERIC_H
+
+#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) ((spx_word16_t)(x))
+#define EXTEND32(x) ((spx_word32_t)(x))
+#define SHR16(a,shift) ((a) >> (shift))
+#define SHL16(a,shift) ((a) << (shift))
+#define SHR32(a,shift) ((a) >> (shift))
+#define SHL32(a,shift) ((a) << (shift))
+#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
+#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+#define SHR(a,shift) ((a) >> (shift))
+#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
+#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+
+#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b)))
+#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b))
+#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b))
+#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b))
+
+
+/* result fits in 16 bits */
+#define MULT16_16_16(a,b)     ((((spx_word16_t)(a))*((spx_word16_t)(b))))
+
+/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
+#define MULT16_16(a,b)     (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
+
+#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
+#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
+#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
+#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
+
+#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
+#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
+
+#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
+
+
+#define MAC16_16_Q11(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),11)))
+#define MAC16_16_Q13(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),13)))
+#define MAC16_16_P13(c,a,b)     (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13)))
+
+#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
+#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
+#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
+
+#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
+#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
+#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
+
+#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15))
+
+#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b))))
+#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b))))
+#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b)))
+#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b)))
+
+#endif
--- a/gst_plugins_base/gst/audioresample/functable.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
- *
- * 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 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#ifndef __SYMBIAN32__
-#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "functable.h"
-#include "debug.h"
-
-
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-functable_func_sinc (double *fx, double *dfx, double x, void *closure)
-{
-  if (x == 0) {
-    *fx = 1;
-    *dfx = 0;
-    return;
-  }
-
-  *fx = sin (x) / x;
-  *dfx = (cos (x) - sin (x) / x) / x;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_func_boxcar (double *fx, double *dfx, double x, void *closure)
-{
-  double width = *(double *) closure;
-
-  if (x < width && x > -width) {
-    *fx = 1;
-  } else {
-    *fx = 0;
-  }
-  *dfx = 0;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_func_hanning (double *fx, double *dfx, double x, void *closure)
-{
-  double width = *(double *) closure;
-
-  if (x < width && x > -width) {
-    x /= width;
-    *fx = (1 - x * x) * (1 - x * x);
-    *dfx = -2 * 2 * x / width * (1 - x * x);
-  } else {
-    *fx = 0;
-    *dfx = 0;
-  }
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-
-Functable *
-functable_new (void)
-{
-  Functable *ft;
-
-  ft = malloc (sizeof (Functable));
-  memset (ft, 0, sizeof (Functable));
-
-  return ft;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_free (Functable * ft)
-{
-  free (ft);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_set_length (Functable * t, int length)
-{
-  t->length = length;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_set_offset (Functable * t, double offset)
-{
-  t->offset = offset;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_set_multiplier (Functable * t, double multiplier)
-{
-  t->multiplier = multiplier;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_calculate (Functable * t, FunctableFunc func, void *closure)
-{
-  int i;
-  double x;
-
-  if (t->fx)
-    free (t->fx);
-  if (t->dfx)
-    free (t->dfx);
-
-  t->fx = malloc (sizeof (double) * (t->length + 1));
-  t->dfx = malloc (sizeof (double) * (t->length + 1));
-
-  t->inv_multiplier = 1.0 / t->multiplier;
-
-  for (i = 0; i < t->length + 1; i++) {
-    x = t->offset + t->multiplier * i;
-
-    func (&t->fx[i], &t->dfx[i], x, closure);
-  }
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_calculate_multiply (Functable * t, FunctableFunc func, void *closure)
-{
-  int i;
-  double x;
-
-  for (i = 0; i < t->length + 1; i++) {
-    double afx, adfx, bfx, bdfx;
-
-    afx = t->fx[i];
-    adfx = t->dfx[i];
-    x = t->offset + t->multiplier * i;
-    func (&bfx, &bdfx, x, closure);
-    t->fx[i] = afx * bfx;
-    t->dfx[i] = afx * bdfx + adfx * bfx;
-  }
-
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-double
-functable_evaluate (Functable * t, double x)
-{
-  int i;
-  double f0, f1, w0, w1;
-  double x2, x3;
-  double w;
-
-  if (x < t->offset || x > (t->offset + t->length * t->multiplier)) {
-    RESAMPLE_DEBUG ("x out of range %g", x);
-  }
-
-  x -= t->offset;
-  x *= t->inv_multiplier;
-  i = floor (x);
-  x -= i;
-
-  x2 = x * x;
-  x3 = x2 * x;
-
-  f1 = 3 * x2 - 2 * x3;
-  f0 = 1 - f1;
-  w0 = (x - 2 * x2 + x3) * t->multiplier;
-  w1 = (-x2 + x3) * t->multiplier;
-
-  w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->dfx[i] * w0 + t->dfx[i + 1] * w1;
-
-  /*w = t->fx[i] * (1-x) + t->fx[i+1] * x; */
-
-  return w;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-
-double
-functable_fir (Functable * t, double x, int n, double *data, int len)
-{
-  int i, j;
-  double f0, f1, w0, w1;
-  double x2, x3;
-  double w;
-  double sum;
-
-  x -= t->offset;
-  x /= t->multiplier;
-  i = floor (x);
-  x -= i;
-
-  x2 = x * x;
-  x3 = x2 * x;
-
-  f1 = 3 * x2 - 2 * x3;
-  f0 = 1 - f1;
-  w0 = (x - 2 * x2 + x3) * t->multiplier;
-  w1 = (-x2 + x3) * t->multiplier;
-
-  sum = 0;
-  for (j = 0; j < len; j++) {
-    w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->dfx[i] * w0 + t->dfx[i + 1] * w1;
-    sum += data[j * 2] * w;
-    i += n;
-  }
-
-  return sum;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-functable_fir2 (Functable * t, double *r0, double *r1, double x,
-    int n, double *data, int len)
-{
-  int i, j;
-  double f0, f1, w0, w1;
-  double x2, x3;
-  double w;
-  double sum0, sum1;
-  double floor_x;
-
-  x -= t->offset;
-  x *= t->inv_multiplier;
-  floor_x = floor (x);
-  i = floor_x;
-  x -= floor_x;
-
-  x2 = x * x;
-  x3 = x2 * x;
-
-  f1 = 3 * x2 - 2 * x3;
-  f0 = 1 - f1;
-  w0 = (x - 2 * x2 + x3) * t->multiplier;
-  w1 = (-x2 + x3) * t->multiplier;
-
-  sum0 = 0;
-  sum1 = 0;
-  for (j = 0; j < len; j++) {
-    w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->dfx[i] * w0 + t->dfx[i + 1] * w1;
-    sum0 += data[j * 2] * w;
-    sum1 += data[j * 2 + 1] * w;
-    i += n;
-  }
-
-  *r0 = sum0;
-  *r1 = sum1;
-}
--- a/gst_plugins_base/gst/audioresample/functable.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David Schleef <ds@schleef.org>
- *
- * 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 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 __FUNCTABLE_H__
-#define __FUNCTABLE_H__
-
-typedef void FunctableFunc (double *fx, double *dfx, double x, void *closure);
-
-typedef struct _Functable Functable;
-struct _Functable {
-  int length;
-
-  double offset;
-  double multiplier;
-
-  double inv_multiplier;
-
-  double *fx;
-  double *dfx;
-};
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-Functable *functable_new (void);
-void functable_setup (Functable *t);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_free (Functable *t);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-void functable_set_length (Functable *t, int length);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_set_offset (Functable *t, double offset);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_set_multiplier (Functable *t, double multiplier);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_calculate (Functable *t, FunctableFunc func, void *closure);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_calculate_multiply (Functable *t, FunctableFunc func, void *closure);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-
-double functable_evaluate (Functable *t,double x);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-double functable_fir(Functable *t,double x0,int n,double *data,int len);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_fir2(Functable *t,double *r0, double *r1, double x0,
-        int n,double *data,int len);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-void functable_func_sinc(double *fx, double *dfx, double x, void *closure);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_func_boxcar(double *fx, double *dfx, double x, void *closure);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void functable_func_hanning(double *fx, double *dfx, double x, void *closure);
-
-#endif /* __PRIVATE_H__ */
-
--- a/gst_plugins_base/gst/audioresample/gstaudioresample.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioresample/gstaudioresample.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
  * Copyright (C) 2003,2004 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -17,25 +18,24 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-/* Element-Checklist-Version: 5 */
 
 /**
  * SECTION:element-audioresample
  *
- * <refsect2>
- * Audioresample resamples raw audio buffers to different sample rates using
+ * audioresample resamples raw audio buffers to different sample rates using
  * a configurable windowing function to enhance quality.
+ *
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! audio/x-raw-int, rate=8000 ! alsasink
- * </programlisting>
- * Decode an Ogg/Vorbis downsample to 8Khz and play sound through alsa. 
+ * ]| Decode an Ogg/Vorbis downsample to 8Khz and play sound through alsa.
  * To create the Ogg/Vorbis file refer to the documentation of vorbisenc.
- * </para>
  * </refsect2>
- *
- * Last reviewed on 2006-03-02 (0.10.4)
+ */
+
+/* TODO:
+ *  - Enable SSE/ARM optimizations and select at runtime
  */
 
 #ifdef HAVE_CONFIG_H
@@ -45,286 +45,436 @@
 #include <string.h>
 #include <math.h>
 
-/*#define DEBUG_ENABLED */
 #include "gstaudioresample.h"
 #include <gst/audio/audio.h>
 #include <gst/base/gstbasetransform.h>
 
-GST_DEBUG_CATEGORY_STATIC (audioresample_debug);
-#define GST_CAT_DEFAULT audioresample_debug
+#if defined AUDIORESAMPLE_FORMAT_AUTO
+#define OIL_ENABLE_UNSTABLE_API
+#include <liboil/liboilprofile.h>
+#include <liboil/liboil.h>
+#endif
 
-/* elementfactory information */
-static const GstElementDetails gst_audioresample_details =
-GST_ELEMENT_DETAILS ("Audio scaler",
-    "Filter/Converter/Audio",
-    "Resample audio",
-    "David Schleef <ds@schleef.org>");
-
-#define DEFAULT_FILTERLEN       16
+GST_DEBUG_CATEGORY (audio_resample_debug);
+#define GST_CAT_DEFAULT audio_resample_debug
 
 enum
 {
   PROP_0,
-  PROP_FILTERLEN
+  PROP_QUALITY,
+  PROP_FILTER_LENGTH
 };
 
 #define SUPPORTED_CAPS \
 GST_STATIC_CAPS ( \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
+    "audio/x-raw-float, " \
+      "rate = (int) [ 1, MAX ], "	\
       "channels = (int) [ 1, MAX ], " \
       "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 16, " \
-      "depth = (int) 16, " \
-      "signed = (boolean) true;" \
+      "width = (int) { 32, 64 }; " \
     "audio/x-raw-int, " \
       "rate = (int) [ 1, MAX ], " \
       "channels = (int) [ 1, MAX ], " \
       "endianness = (int) BYTE_ORDER, " \
       "width = (int) 32, " \
       "depth = (int) 32, " \
-      "signed = (boolean) true;" \
-    "audio/x-raw-float, " \
-      "rate = (int) [ 1, MAX ], "	\
+      "signed = (boolean) true; " \
+    "audio/x-raw-int, " \
+      "rate = (int) [ 1, MAX ], " \
+      "channels = (int) [ 1, MAX ], " \
+      "endianness = (int) BYTE_ORDER, " \
+      "width = (int) 24, " \
+      "depth = (int) 24, " \
+      "signed = (boolean) true; " \
+    "audio/x-raw-int, " \
+      "rate = (int) [ 1, MAX ], " \
       "channels = (int) [ 1, MAX ], " \
       "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 32; " \
-    "audio/x-raw-float, " \
-      "rate = (int) [ 1, MAX ], "	\
+      "width = (int) 16, " \
+      "depth = (int) 16, " \
+      "signed = (boolean) true; " \
+    "audio/x-raw-int, " \
+      "rate = (int) [ 1, MAX ], " \
       "channels = (int) [ 1, MAX ], " \
       "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 64" \
+      "width = (int) 8, " \
+      "depth = (int) 8, " \
+      "signed = (boolean) true" \
 )
 
-static GstStaticPadTemplate gst_audioresample_sink_template =
+/* If TRUE integer arithmetic resampling is faster and will be used if appropiate */
+#if defined AUDIORESAMPLE_FORMAT_INT
+static gboolean gst_audio_resample_use_int = TRUE;
+#elif defined AUDIORESAMPLE_FORMAT_FLOAT
+static gboolean gst_audio_resample_use_int = FALSE;
+#else
+static gboolean gst_audio_resample_use_int = FALSE;
+#endif
+
+static GstStaticPadTemplate gst_audio_resample_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS);
 
-static GstStaticPadTemplate gst_audioresample_src_template =
+static GstStaticPadTemplate gst_audio_resample_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC, GST_PAD_ALWAYS, SUPPORTED_CAPS);
 
-static void gst_audioresample_set_property (GObject * object,
+static void gst_audio_resample_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_audioresample_get_property (GObject * object,
+static void gst_audio_resample_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
 /* vmethods */
-static gboolean audioresample_get_unit_size (GstBaseTransform * base,
+static gboolean gst_audio_resample_get_unit_size (GstBaseTransform * base,
     GstCaps * caps, guint * size);
-static GstCaps *audioresample_transform_caps (GstBaseTransform * base,
+static GstCaps *gst_audio_resample_transform_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps);
-static gboolean audioresample_transform_size (GstBaseTransform * trans,
+static void gst_audio_resample_fixate_caps (GstBaseTransform * base,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
+static gboolean gst_audio_resample_transform_size (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * incaps, guint insize,
     GstCaps * outcaps, guint * outsize);
-static gboolean audioresample_set_caps (GstBaseTransform * base,
+static gboolean gst_audio_resample_set_caps (GstBaseTransform * base,
     GstCaps * incaps, GstCaps * outcaps);
-static GstFlowReturn audioresample_pushthrough (GstAudioresample *
-    audioresample);
-static GstFlowReturn audioresample_transform (GstBaseTransform * base,
+static GstFlowReturn gst_audio_resample_transform (GstBaseTransform * base,
     GstBuffer * inbuf, GstBuffer * outbuf);
-static gboolean audioresample_event (GstBaseTransform * base, GstEvent * event);
-static gboolean audioresample_start (GstBaseTransform * base);
-static gboolean audioresample_stop (GstBaseTransform * base);
+static gboolean gst_audio_resample_event (GstBaseTransform * base,
+    GstEvent * event);
+static gboolean gst_audio_resample_start (GstBaseTransform * base);
+static gboolean gst_audio_resample_stop (GstBaseTransform * base);
+static gboolean gst_audio_resample_query (GstPad * pad, GstQuery * query);
+static const GstQueryType *gst_audio_resample_query_type (GstPad * pad);
 
-static gboolean audioresample_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *audioresample_query_type (GstPad * pad);
-
-#define DEBUG_INIT(bla) \
-  GST_DEBUG_CATEGORY_INIT (audioresample_debug, "audioresample", 0, "audio resampling element");
-
-GST_BOILERPLATE_FULL (GstAudioresample, gst_audioresample, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
+GST_BOILERPLATE (GstAudioResample, gst_audio_resample, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM);
 
 static void
-gst_audioresample_base_init (gpointer g_class)
+gst_audio_resample_base_init (gpointer g_class)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 
   gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_audioresample_src_template));
+      gst_static_pad_template_get (&gst_audio_resample_src_template));
   gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_audioresample_sink_template));
+      gst_static_pad_template_get (&gst_audio_resample_sink_template));
 
-  gst_element_class_set_details (gstelement_class, &gst_audioresample_details);
+  gst_element_class_set_details_simple (gstelement_class, "Audio resampler",
+      "Filter/Converter/Audio", "Resamples audio",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 }
 
 static void
-gst_audioresample_class_init (GstAudioresampleClass * klass)
+gst_audio_resample_class_init (GstAudioResampleClass * klass)
 {
-  GObjectClass *gobject_class;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+
+  gobject_class->set_property = gst_audio_resample_set_property;
+  gobject_class->get_property = gst_audio_resample_get_property;
 
-  gobject_class = (GObjectClass *) klass;
+  g_object_class_install_property (gobject_class, PROP_QUALITY,
+      g_param_spec_int ("quality", "Quality", "Resample quality with 0 being "
+          "the lowest and 10 being the best",
+          SPEEX_RESAMPLER_QUALITY_MIN, SPEEX_RESAMPLER_QUALITY_MAX,
+          SPEEX_RESAMPLER_QUALITY_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
-  gobject_class->set_property = gst_audioresample_set_property;
-  gobject_class->get_property = gst_audioresample_get_property;
-
-  g_object_class_install_property (gobject_class, PROP_FILTERLEN,
-      g_param_spec_int ("filter_length", "filter_length", "filter_length",
-          0, G_MAXINT, DEFAULT_FILTERLEN,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  /* FIXME 0.11: Remove this property, it's just for compatibility
+   * with old audioresample
+   */
+  /**
+   * GstAudioResample:filter-length:
+   *
+   * Length of the resample filter
+   *
+   * Deprectated: Use #GstAudioResample:quality property instead
+   */
+  g_object_class_install_property (gobject_class, PROP_FILTER_LENGTH,
+      g_param_spec_int ("filter-length", "Filter length",
+          "Length of the resample filter", 0, G_MAXINT, 64, G_PARAM_READWRITE));
 
   GST_BASE_TRANSFORM_CLASS (klass)->start =
-      GST_DEBUG_FUNCPTR (audioresample_start);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_start);
   GST_BASE_TRANSFORM_CLASS (klass)->stop =
-      GST_DEBUG_FUNCPTR (audioresample_stop);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_stop);
   GST_BASE_TRANSFORM_CLASS (klass)->transform_size =
-      GST_DEBUG_FUNCPTR (audioresample_transform_size);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_transform_size);
   GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
-      GST_DEBUG_FUNCPTR (audioresample_get_unit_size);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_get_unit_size);
   GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
-      GST_DEBUG_FUNCPTR (audioresample_transform_caps);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_transform_caps);
+  GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps =
+      GST_DEBUG_FUNCPTR (gst_audio_resample_fixate_caps);
   GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
-      GST_DEBUG_FUNCPTR (audioresample_set_caps);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_set_caps);
   GST_BASE_TRANSFORM_CLASS (klass)->transform =
-      GST_DEBUG_FUNCPTR (audioresample_transform);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_transform);
   GST_BASE_TRANSFORM_CLASS (klass)->event =
-      GST_DEBUG_FUNCPTR (audioresample_event);
+      GST_DEBUG_FUNCPTR (gst_audio_resample_event);
 
   GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
 }
 
-
 static void
-gst_audioresample_init (GstAudioresample * audioresample,
-    GstAudioresampleClass * klass)
+gst_audio_resample_init (GstAudioResample * resample,
+    GstAudioResampleClass * klass)
 {
-  GstBaseTransform *trans;
-
-  trans = GST_BASE_TRANSFORM (audioresample);
+  GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
 
-  /* buffer alloc passthrough is too impossible. FIXME, it
-   * is trivial in the passthrough case. */
-  gst_pad_set_bufferalloc_function (trans->sinkpad, NULL);
+  resample->quality = SPEEX_RESAMPLER_QUALITY_DEFAULT;
+
+  resample->need_discont = FALSE;
 
-  audioresample->filter_length = DEFAULT_FILTERLEN;
-
-  audioresample->need_discont = FALSE;
-
-  gst_pad_set_query_function (trans->srcpad, audioresample_query);
-  gst_pad_set_query_type_function (trans->srcpad, audioresample_query_type);
+  gst_pad_set_query_function (trans->srcpad, gst_audio_resample_query);
+  gst_pad_set_query_type_function (trans->srcpad,
+      gst_audio_resample_query_type);
 }
 
 /* vmethods */
 static gboolean
-audioresample_start (GstBaseTransform * base)
+gst_audio_resample_start (GstBaseTransform * base)
 {
-  GstAudioresample *audioresample = GST_AUDIORESAMPLE (base);
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
 
-  audioresample->resample = resample_new ();
-  audioresample->ts_offset = -1;
-  audioresample->offset = -1;
-  audioresample->next_ts = -1;
-
-  resample_set_filter_length (audioresample->resample,
-      audioresample->filter_length);
+  resample->next_offset = -1;
+  resample->next_ts = -1;
+  resample->next_upstream_ts = -1;
 
   return TRUE;
 }
 
 static gboolean
-audioresample_stop (GstBaseTransform * base)
+gst_audio_resample_stop (GstBaseTransform * base)
 {
-  GstAudioresample *audioresample = GST_AUDIORESAMPLE (base);
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
 
-  if (audioresample->resample) {
-    resample_free (audioresample->resample);
-    audioresample->resample = NULL;
+  if (resample->state) {
+    resample->funcs->destroy (resample->state);
+    resample->state = NULL;
   }
 
-  gst_caps_replace (&audioresample->sinkcaps, NULL);
-  gst_caps_replace (&audioresample->srccaps, NULL);
+  resample->funcs = NULL;
+
+  g_free (resample->tmp_in);
+  resample->tmp_in = NULL;
+  resample->tmp_in_size = 0;
+
+  g_free (resample->tmp_out);
+  resample->tmp_out = NULL;
+  resample->tmp_out_size = 0;
+
+  gst_caps_replace (&resample->sinkcaps, NULL);
+  gst_caps_replace (&resample->srccaps, NULL);
 
   return TRUE;
 }
 
 static gboolean
-audioresample_get_unit_size (GstBaseTransform * base, GstCaps * caps,
+gst_audio_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps,
     guint * size)
 {
   gint width, channels;
   GstStructure *structure;
   gboolean ret;
 
-  g_assert (size);
+  g_return_val_if_fail (size != NULL, FALSE);
 
   /* this works for both float and int */
   structure = gst_caps_get_structure (caps, 0);
   ret = gst_structure_get_int (structure, "width", &width);
   ret &= gst_structure_get_int (structure, "channels", &channels);
-  g_return_val_if_fail (ret, FALSE);
 
-  *size = width * channels / 8;
+  if (G_UNLIKELY (!ret))
+    return FALSE;
+
+  *size = (width / 8) * channels;
 
   return TRUE;
 }
 
 static GstCaps *
-audioresample_transform_caps (GstBaseTransform * base,
+gst_audio_resample_transform_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps)
 {
+  const GValue *val;
+  GstStructure *s;
   GstCaps *res;
-  GstStructure *structure;
+
+  /* transform single caps into input_caps + input_caps with the rate
+   * field set to our supported range. This ensures that upstream knows
+   * about downstream's prefered rate(s) and can negotiate accordingly. */
+  res = gst_caps_copy (caps);
 
-  /* transform caps gives one single caps so we can just replace
-   * the rate property with our range. */
-  res = gst_caps_copy (caps);
-  structure = gst_caps_get_structure (res, 0);
-  gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+  /* first, however, check if the caps contain a range for the rate field, in
+   * which case that side isn't going to care much about the exact sample rate
+   * chosen and we should just assume things will get fixated to something sane
+   * and we may just as well offer our full range instead of the range in the
+   * caps. If the rate is not an int range value, it's likely to express a
+   * real preference or limitation and we should maintain that structure as
+   * preference by putting it first into the transformed caps, and only add
+   * our full rate range as second option  */
+  s = gst_caps_get_structure (res, 0);
+  val = gst_structure_get_value (s, "rate");
+  if (val == NULL || GST_VALUE_HOLDS_INT_RANGE (val)) {
+    /* overwrite existing range, or add field if it doesn't exist yet */
+    gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+  } else {
+    /* append caps with full range to existing caps with non-range rate field */
+    s = gst_structure_copy (s);
+    gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+    gst_caps_append_structure (res, s);
+  }
 
   return res;
 }
 
+/* Fixate rate to the allowed rate that has the smallest difference */
+static void
+gst_audio_resample_fixate_caps (GstBaseTransform * base,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
+{
+  GstStructure *s;
+  gint rate;
+
+  s = gst_caps_get_structure (caps, 0);
+  if (G_UNLIKELY (!gst_structure_get_int (s, "rate", &rate)))
+    return;
+
+  s = gst_caps_get_structure (othercaps, 0);
+  gst_structure_fixate_field_nearest_int (s, "rate", rate);
+}
+
+static const SpeexResampleFuncs *
+gst_audio_resample_get_funcs (gint width, gboolean fp)
+{
+  const SpeexResampleFuncs *funcs = NULL;
+
+  if (gst_audio_resample_use_int && (width == 8 || width == 16) && !fp)
+    funcs = &int_funcs;
+  else if ((!gst_audio_resample_use_int && (width == 8 || width == 16) && !fp)
+      || (width == 32 && fp))
+    funcs = &float_funcs;
+  else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp))
+    funcs = &double_funcs;
+  else
+    g_assert_not_reached ();
+
+  return funcs;
+}
+
+static SpeexResamplerState *
+gst_audio_resample_init_state (GstAudioResample * resample, gint width,
+    gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
+{
+  SpeexResamplerState *ret = NULL;
+  gint err = RESAMPLER_ERR_SUCCESS;
+  const SpeexResampleFuncs *funcs = gst_audio_resample_get_funcs (width, fp);
+
+  ret = funcs->init (channels, inrate, outrate, quality, &err);
+
+  if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
+    GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s",
+        funcs->strerror (err));
+    return NULL;
+  }
+
+  funcs->skip_zeros (ret);
+
+  return ret;
+}
+
 static gboolean
-resample_set_state_from_caps (ResampleState * state, GstCaps * incaps,
-    GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate)
+gst_audio_resample_update_state (GstAudioResample * resample, gint width,
+    gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
+{
+  gboolean ret = TRUE;
+  gboolean updated_latency = FALSE;
+
+  updated_latency = (resample->inrate != inrate
+      || quality != resample->quality) && resample->state != NULL;
+
+  if (resample->state == NULL) {
+    ret = TRUE;
+  } else if (resample->channels != channels || fp != resample->fp
+      || width != resample->width) {
+    resample->funcs->destroy (resample->state);
+    resample->state =
+        gst_audio_resample_init_state (resample, width, channels, inrate,
+        outrate, quality, fp);
+
+    resample->funcs = gst_audio_resample_get_funcs (width, fp);
+    ret = (resample->state != NULL);
+  } else if (resample->inrate != inrate || resample->outrate != outrate) {
+    gint err = RESAMPLER_ERR_SUCCESS;
+
+    err = resample->funcs->set_rate (resample->state, inrate, outrate);
+
+    if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
+      GST_ERROR_OBJECT (resample, "Failed to update rate: %s",
+          resample->funcs->strerror (err));
+
+    ret = (err == RESAMPLER_ERR_SUCCESS);
+  } else if (quality != resample->quality) {
+    gint err = RESAMPLER_ERR_SUCCESS;
+
+    err = resample->funcs->set_quality (resample->state, quality);
+
+    if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
+      GST_ERROR_OBJECT (resample, "Failed to update quality: %s",
+          resample->funcs->strerror (err));
+
+    ret = (err == RESAMPLER_ERR_SUCCESS);
+  }
+
+  resample->width = width;
+  resample->channels = channels;
+  resample->fp = fp;
+  resample->quality = quality;
+  resample->inrate = inrate;
+  resample->outrate = outrate;
+
+  if (updated_latency)
+    gst_element_post_message (GST_ELEMENT (resample),
+        gst_message_new_latency (GST_OBJECT (resample)));
+
+  return ret;
+}
+
+static void
+gst_audio_resample_reset_state (GstAudioResample * resample)
+{
+  if (resample->state)
+    resample->funcs->reset_mem (resample->state);
+}
+
+static gboolean
+gst_audio_resample_parse_caps (GstCaps * incaps,
+    GstCaps * outcaps, gint * width, gint * channels, gint * inrate,
+    gint * outrate, gboolean * fp)
 {
   GstStructure *structure;
   gboolean ret;
-  gint myinrate, myoutrate;
-  int mychannels;
-  gint width, depth;
-  ResampleFormat format;
+  gint mywidth, myinrate, myoutrate, mychannels;
+  gboolean myfp;
 
   GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %"
       GST_PTR_FORMAT, incaps, outcaps);
 
   structure = gst_caps_get_structure (incaps, 0);
 
-  /* get width */
-  ret = gst_structure_get_int (structure, "width", &width);
-  if (!ret)
-    goto no_width;
+  if (g_str_equal (gst_structure_get_name (structure), "audio/x-raw-float"))
+    myfp = TRUE;
+  else
+    myfp = FALSE;
 
-  /* figure out the format */
-  if (g_str_equal (gst_structure_get_name (structure), "audio/x-raw-float")) {
-    if (width == 32)
-      format = RESAMPLE_FORMAT_F32;
-    else if (width == 64)
-      format = RESAMPLE_FORMAT_F64;
-    else
-      goto wrong_depth;
-  } else {
-    /* for int, depth and width must be the same */
-    ret = gst_structure_get_int (structure, "depth", &depth);
-    if (!ret || width != depth)
-      goto not_equal;
-
-    if (width == 16)
-      format = RESAMPLE_FORMAT_S16;
-    else if (width == 32)
-      format = RESAMPLE_FORMAT_S32;
-    else
-      goto wrong_depth;
-  }
   ret = gst_structure_get_int (structure, "rate", &myinrate);
   ret &= gst_structure_get_int (structure, "channels", &mychannels);
-  if (!ret)
+  ret &= gst_structure_get_int (structure, "width", &mywidth);
+  if (G_UNLIKELY (!ret))
     goto no_in_rate_channels;
 
   structure = gst_caps_get_structure (outcaps, 0);
   ret = gst_structure_get_int (structure, "rate", &myoutrate);
-  if (!ret)
+  if (G_UNLIKELY (!ret))
     goto no_out_rate;
 
   if (channels)
@@ -333,30 +483,14 @@
     *inrate = myinrate;
   if (outrate)
     *outrate = myoutrate;
-
-  resample_set_format (state, format);
-  resample_set_n_channels (state, mychannels);
-  resample_set_input_rate (state, myinrate);
-  resample_set_output_rate (state, myoutrate);
+  if (width)
+    *width = mywidth;
+  if (fp)
+    *fp = myfp;
 
   return TRUE;
 
   /* ERRORS */
-no_width:
-  {
-    GST_DEBUG ("failed to get width from caps");
-    return FALSE;
-  }
-not_equal:
-  {
-    GST_DEBUG ("width %d and depth %d must be the same", width, depth);
-    return FALSE;
-  }
-wrong_depth:
-  {
-    GST_DEBUG ("unknown depth %d found", depth);
-    return FALSE;
-  }
 no_in_rate_channels:
   {
     GST_DEBUG ("could not get input rate and channels");
@@ -369,16 +503,29 @@
   }
 }
 
+static gint
+_gcd (gint a, gint b)
+{
+  while (b != 0) {
+    int temp = a;
+
+    a = b;
+    b = temp % b;
+  }
+
+  return ABS (a);
+}
+
 static gboolean
-audioresample_transform_size (GstBaseTransform * base,
+gst_audio_resample_transform_size (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
     guint * othersize)
 {
-  GstAudioresample *audioresample = GST_AUDIORESAMPLE (base);
-  ResampleState *state;
   GstCaps *srccaps, *sinkcaps;
-  gboolean use_internal = FALSE;        /* whether we use the internal state */
   gboolean ret = TRUE;
+  guint32 ratio_den, ratio_num;
+  gint inrate, outrate, gcd;
+  gint bytes_per_samp, channels;
 
   GST_LOG_OBJECT (base, "asked to transform size %d in direction %s",
       size, direction == GST_PAD_SINK ? "SINK" : "SRC");
@@ -390,216 +537,386 @@
     srccaps = caps;
   }
 
-  /* if the caps are the ones that _set_caps got called with; we can use
-   * our own state; otherwise we'll have to create a state */
-  if (gst_caps_is_equal (sinkcaps, audioresample->sinkcaps) &&
-      gst_caps_is_equal (srccaps, audioresample->srccaps)) {
-    use_internal = TRUE;
-    state = audioresample->resample;
-  } else {
-    GST_DEBUG_OBJECT (audioresample,
-        "caps are not the set caps, creating state");
-    state = resample_new ();
-    resample_set_filter_length (state, audioresample->filter_length);
-    resample_set_state_from_caps (state, sinkcaps, srccaps, NULL, NULL, NULL);
+  /* Get sample width -> bytes_per_samp, channels, inrate, outrate */
+  ret =
+      gst_audio_resample_parse_caps (caps, othercaps, &bytes_per_samp,
+      &channels, &inrate, &outrate, NULL);
+  if (G_UNLIKELY (!ret)) {
+    GST_ERROR_OBJECT (base, "Wrong caps");
+    return FALSE;
   }
+  /* Number of samples in either buffer is size / (width*channels) ->
+   * calculate the factor */
+  bytes_per_samp = bytes_per_samp * channels / 8;
+  /* Convert source buffer size to samples */
+  size /= bytes_per_samp;
+
+  /* Simplify the conversion ratio factors */
+  gcd = _gcd (inrate, outrate);
+  ratio_num = inrate / gcd;
+  ratio_den = outrate / gcd;
 
   if (direction == GST_PAD_SINK) {
-    /* asked to convert size of an incoming buffer */
-    *othersize = resample_get_output_size_for_input (state, size);
+    /* asked to convert size of an incoming buffer. Round up the output size */
+    *othersize = (size * ratio_den + ratio_num - 1) / ratio_num;
+    *othersize *= bytes_per_samp;
   } else {
-    /* asked to convert size of an outgoing buffer */
-    *othersize = resample_get_input_size_for_output (state, size);
+    /* asked to convert size of an outgoing buffer. Round down the input size */
+    *othersize = (size * ratio_num) / ratio_den;
+    *othersize *= bytes_per_samp;
   }
-  g_assert (*othersize % state->sample_size == 0);
 
-  /* we make room for one extra sample, given that the resampling filter
-   * can output an extra one for non-integral i_rate/o_rate */
-  GST_LOG_OBJECT (base, "transformed size %d to %d", size, *othersize);
-
-  if (!use_internal) {
-    resample_free (state);
-  }
+  GST_LOG_OBJECT (base, "transformed size %d to %d", size * bytes_per_samp,
+      *othersize);
 
   return ret;
 }
 
 static gboolean
-audioresample_set_caps (GstBaseTransform * base, GstCaps * incaps,
+gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
     GstCaps * outcaps)
 {
   gboolean ret;
-  gint inrate, outrate;
-  int channels;
-  GstAudioresample *audioresample = GST_AUDIORESAMPLE (base);
+  gint width = 0, inrate = 0, outrate = 0, channels = 0;
+  gboolean fp;
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
 
-  GST_DEBUG_OBJECT (base, "incaps %" GST_PTR_FORMAT ", outcaps %"
+  GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %"
       GST_PTR_FORMAT, incaps, outcaps);
 
-  ret = resample_set_state_from_caps (audioresample->resample, incaps, outcaps,
-      &channels, &inrate, &outrate);
+  ret = gst_audio_resample_parse_caps (incaps, outcaps,
+      &width, &channels, &inrate, &outrate, &fp);
 
-  g_return_val_if_fail (ret, FALSE);
+  if (G_UNLIKELY (!ret))
+    return FALSE;
 
-  audioresample->channels = channels;
-  GST_DEBUG_OBJECT (audioresample, "set channels to %d", channels);
-  audioresample->i_rate = inrate;
-  GST_DEBUG_OBJECT (audioresample, "set i_rate to %d", inrate);
-  audioresample->o_rate = outrate;
-  GST_DEBUG_OBJECT (audioresample, "set o_rate to %d", outrate);
+  ret =
+      gst_audio_resample_update_state (resample, width, channels, inrate,
+      outrate, resample->quality, fp);
+
+  if (G_UNLIKELY (!ret))
+    return FALSE;
 
   /* save caps so we can short-circuit in the size_transform if the caps
    * are the same */
-  gst_caps_replace (&audioresample->sinkcaps, incaps);
-  gst_caps_replace (&audioresample->srccaps, outcaps);
-
-  return TRUE;
-}
-
-static gboolean
-audioresample_event (GstBaseTransform * base, GstEvent * event)
-{
-  GstAudioresample *audioresample;
-
-  audioresample = GST_AUDIORESAMPLE (base);
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      resample_input_flush (audioresample->resample);
-      audioresample->ts_offset = -1;
-      audioresample->next_ts = -1;
-      audioresample->offset = -1;
-      break;
-    case GST_EVENT_NEWSEGMENT:
-      resample_input_pushthrough (audioresample->resample);
-      audioresample_pushthrough (audioresample);
-      audioresample->ts_offset = -1;
-      audioresample->next_ts = -1;
-      audioresample->offset = -1;
-      break;
-    case GST_EVENT_EOS:
-      resample_input_eos (audioresample->resample);
-      audioresample_pushthrough (audioresample);
-      break;
-    default:
-      break;
-  }
-  parent_class->event (base, event);
+  gst_caps_replace (&resample->sinkcaps, incaps);
+  gst_caps_replace (&resample->srccaps, outcaps);
 
   return TRUE;
 }
 
-static GstFlowReturn
-audioresample_do_output (GstAudioresample * audioresample, GstBuffer * outbuf)
+#define GST_MAXINT24 (8388607)
+#define GST_MININT24 (-8388608)
+
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+#define GST_READ_UINT24 GST_READ_UINT24_LE
+#define GST_WRITE_UINT24 GST_WRITE_UINT24_LE
+#else
+#define GST_READ_UINT24 GST_READ_UINT24_BE
+#define GST_WRITE_UINT24 GST_WRITE_UINT24_BE
+#endif
+
+static void
+gst_audio_resample_convert_buffer (GstAudioResample * resample,
+    const guint8 * in, guint8 * out, guint len, gboolean inverse)
 {
-  int outsize;
-  int outsamples;
-  ResampleState *r;
+  len *= resample->channels;
+
+  if (inverse) {
+    if (gst_audio_resample_use_int && resample->width == 8 && !resample->fp) {
+      gint8 *o = (gint8 *) out;
+      gint16 *i = (gint16 *) in;
+      gint32 tmp;
+
+      while (len) {
+        tmp = *i + (G_MAXINT8 >> 1);
+        *o = CLAMP (tmp >> 8, G_MININT8, G_MAXINT8);
+        o++;
+        i++;
+        len--;
+      }
+    } else if (!gst_audio_resample_use_int && resample->width == 8
+        && !resample->fp) {
+      gint8 *o = (gint8 *) out;
+      gfloat *i = (gfloat *) in;
+      gfloat tmp;
+
+      while (len) {
+        tmp = *i;
+        *o = (gint8) CLAMP (tmp * G_MAXINT8 + 0.5, G_MININT8, G_MAXINT8);
+        o++;
+        i++;
+        len--;
+      }
+    } else if (!gst_audio_resample_use_int && resample->width == 16
+        && !resample->fp) {
+      gint16 *o = (gint16 *) out;
+      gfloat *i = (gfloat *) in;
+      gfloat tmp;
 
-  r = audioresample->resample;
+      while (len) {
+        tmp = *i;
+        *o = (gint16) CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16);
+        o++;
+        i++;
+        len--;
+      }
+    } else if (resample->width == 24 && !resample->fp) {
+      guint8 *o = (guint8 *) out;
+      gdouble *i = (gdouble *) in;
+      gdouble tmp;
 
-  outsize = resample_get_output_size (r);
-  GST_LOG_OBJECT (audioresample, "audioresample can give me %d bytes", outsize);
+      while (len) {
+        tmp = *i;
+        GST_WRITE_UINT24 (o, (gint32) CLAMP (tmp * GST_MAXINT24 + 0.5,
+                GST_MININT24, GST_MAXINT24));
+        o += 3;
+        i++;
+        len--;
+      }
+    } else if (resample->width == 32 && !resample->fp) {
+      gint32 *o = (gint32 *) out;
+      gdouble *i = (gdouble *) in;
+      gdouble tmp;
+
+      while (len) {
+        tmp = *i;
+        *o = (gint32) CLAMP (tmp * G_MAXINT32 + 0.5, G_MININT32, G_MAXINT32);
+        o++;
+        i++;
+        len--;
+      }
+    } else {
+      g_assert_not_reached ();
+    }
+  } else {
+    if (gst_audio_resample_use_int && resample->width == 8 && !resample->fp) {
+      gint8 *i = (gint8 *) in;
+      gint16 *o = (gint16 *) out;
+      gint32 tmp;
 
-  /* protect against mem corruption */
-  if (outsize > GST_BUFFER_SIZE (outbuf)) {
-    GST_WARNING_OBJECT (audioresample,
-        "overriding audioresample's outsize %d with outbuffer's size %d",
-        outsize, GST_BUFFER_SIZE (outbuf));
-    outsize = GST_BUFFER_SIZE (outbuf);
+      while (len) {
+        tmp = *i;
+        *o = tmp << 8;
+        o++;
+        i++;
+        len--;
+      }
+    } else if (!gst_audio_resample_use_int && resample->width == 8
+        && !resample->fp) {
+      gint8 *i = (gint8 *) in;
+      gfloat *o = (gfloat *) out;
+      gfloat tmp;
+
+      while (len) {
+        tmp = *i;
+        *o = tmp / G_MAXINT8;
+        o++;
+        i++;
+        len--;
+      }
+    } else if (!gst_audio_resample_use_int && resample->width == 16
+        && !resample->fp) {
+      gint16 *i = (gint16 *) in;
+      gfloat *o = (gfloat *) out;
+      gfloat tmp;
+
+      while (len) {
+        tmp = *i;
+        *o = tmp / G_MAXINT16;
+        o++;
+        i++;
+        len--;
+      }
+    } else if (resample->width == 24 && !resample->fp) {
+      guint8 *i = (guint8 *) in;
+      gdouble *o = (gdouble *) out;
+      gdouble tmp;
+      guint32 tmp2;
+
+      while (len) {
+        tmp2 = GST_READ_UINT24 (i);
+        if (tmp2 & 0x00800000)
+          tmp2 |= 0xff000000;
+        tmp = (gint32) tmp2;
+        *o = tmp / GST_MAXINT24;
+        o++;
+        i += 3;
+        len--;
+      }
+    } else if (resample->width == 32 && !resample->fp) {
+      gint32 *i = (gint32 *) in;
+      gdouble *o = (gdouble *) out;
+      gdouble tmp;
+
+      while (len) {
+        tmp = *i;
+        *o = tmp / G_MAXINT32;
+        o++;
+        i++;
+        len--;
+      }
+    } else {
+      g_assert_not_reached ();
+    }
   }
-  /* catch possibly wrong size differences */
-  if (GST_BUFFER_SIZE (outbuf) - outsize > r->sample_size) {
-    GST_WARNING_OBJECT (audioresample,
-        "audioresample's outsize %d too far from outbuffer's size %d",
-        outsize, GST_BUFFER_SIZE (outbuf));
+}
+
+static void
+gst_audio_resample_push_drain (GstAudioResample * resample)
+{
+  GstBuffer *buf;
+  GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
+  GstFlowReturn res;
+  gint outsize;
+  guint out_len, out_processed;
+  gint err;
+  guint num, den, len;
+  guint8 *outtmp = NULL;
+  gboolean need_convert = FALSE;
+
+  if (!resample->state)
+    return;
+
+  /* Don't drain samples if we were resetted. */
+  if (resample->next_ts == -1)
+    return;
+
+  need_convert = (resample->funcs->width != resample->width);
+
+  resample->funcs->get_ratio (resample->state, &num, &den);
+
+  out_len = resample->funcs->get_input_latency (resample->state);
+  out_len = out_processed = (out_len * den + num - 1) / num;
+  outsize = (resample->width / 8) * out_len * resample->channels;
+
+  if (need_convert) {
+    guint outsize_tmp =
+        (resample->funcs->width / 8) * out_len * resample->channels;
+    if (outsize_tmp <= resample->tmp_out_size) {
+      outtmp = resample->tmp_out;
+    } else {
+      resample->tmp_out_size = outsize_tmp;
+      resample->tmp_out = outtmp = g_realloc (resample->tmp_out, outsize_tmp);
+    }
   }
 
-  outsize = resample_get_output_data (r, GST_BUFFER_DATA (outbuf), outsize);
-  outsamples = outsize / r->sample_size;
-  GST_LOG_OBJECT (audioresample, "resample gave me %d bytes or %d samples",
-      outsize, outsamples);
+  res =
+      gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE,
+      outsize, GST_PAD_CAPS (trans->srcpad), &buf);
 
-  GST_BUFFER_OFFSET (outbuf) = audioresample->offset;
-  GST_BUFFER_TIMESTAMP (outbuf) = audioresample->next_ts;
+  if (G_UNLIKELY (res != GST_FLOW_OK)) {
+    GST_WARNING_OBJECT (resample, "failed allocating buffer of %d bytes",
+        outsize);
+    return;
+  }
+
+  len = resample->funcs->get_input_latency (resample->state);
 
-  if (audioresample->ts_offset != -1) {
-    audioresample->offset += outsamples;
-    audioresample->ts_offset += outsamples;
-    audioresample->next_ts =
-        gst_util_uint64_scale_int (audioresample->ts_offset, GST_SECOND,
-        audioresample->o_rate);
-    GST_BUFFER_OFFSET_END (outbuf) = audioresample->offset;
+  err =
+      resample->funcs->process (resample->state,
+      NULL, &len, (need_convert) ? outtmp : GST_BUFFER_DATA (buf),
+      &out_processed);
 
-    /* we calculate DURATION as the difference between "next" timestamp
-     * and current timestamp so we ensure a contiguous stream, instead of
-     * having rounding errors. */
-    GST_BUFFER_DURATION (outbuf) = audioresample->next_ts -
-        GST_BUFFER_TIMESTAMP (outbuf);
-  } else {
-    /* no valid offset know, we can still sortof calculate the duration though */
-    GST_BUFFER_DURATION (outbuf) =
-        gst_util_uint64_scale_int (outsamples, GST_SECOND,
-        audioresample->o_rate);
+  if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
+    GST_WARNING_OBJECT (resample, "Failed to process drain: %s",
+        resample->funcs->strerror (err));
+    gst_buffer_unref (buf);
+    return;
+  }
+
+  if (G_UNLIKELY (out_processed == 0)) {
+    GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer");
+    gst_buffer_unref (buf);
+    return;
   }
 
-  /* check for possible mem corruption */
-  if (outsize > GST_BUFFER_SIZE (outbuf)) {
-    /* this is an error that when it happens, would need fixing in the
-     * resample library; we told it we wanted only GST_BUFFER_SIZE (outbuf),
-     * and it gave us more ! */
-    GST_WARNING_OBJECT (audioresample,
-        "audioresample, you memory corrupting bastard. "
-        "you gave me outsize %d while my buffer was size %d",
-        outsize, GST_BUFFER_SIZE (outbuf));
-    return GST_FLOW_ERROR;
-  }
-  /* catch possibly wrong size differences */
-  if (GST_BUFFER_SIZE (outbuf) - outsize > r->sample_size) {
-    GST_WARNING_OBJECT (audioresample,
-        "audioresample's written outsize %d too far from outbuffer's size %d",
-        outsize, GST_BUFFER_SIZE (outbuf));
-  }
-  GST_BUFFER_SIZE (outbuf) = outsize;
+  /* If we wrote more than allocated something is really wrong now
+   * and we should better abort immediately */
+  g_assert (out_len >= out_processed);
+
+  if (need_convert)
+    gst_audio_resample_convert_buffer (resample, outtmp, GST_BUFFER_DATA (buf),
+        out_processed, TRUE);
 
-  if (G_UNLIKELY (audioresample->need_discont)) {
-    GST_DEBUG_OBJECT (audioresample,
-        "marking this buffer with the DISCONT flag");
-    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
-    audioresample->need_discont = FALSE;
+  GST_BUFFER_DURATION (buf) =
+      GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
+  GST_BUFFER_SIZE (buf) =
+      out_processed * resample->channels * (resample->width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
+    GST_BUFFER_OFFSET (buf) = resample->next_offset;
+    GST_BUFFER_OFFSET_END (buf) = resample->next_offset + out_processed;
+    GST_BUFFER_TIMESTAMP (buf) = resample->next_ts;
+
+    resample->next_ts += GST_BUFFER_DURATION (buf);
+    resample->next_offset += out_processed;
   }
 
-  GST_LOG_OBJECT (audioresample, "transformed to buffer of %d bytes, ts %"
-      GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %"
-      G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
-      outsize, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
-      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
-      GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
+  GST_LOG_OBJECT (resample,
+      "Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT
+      " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
+      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf),
+      GST_BUFFER_OFFSET_END (buf));
 
+  res = gst_pad_push (trans->srcpad, buf);
 
-  return GST_FLOW_OK;
+  if (G_UNLIKELY (res != GST_FLOW_OK))
+    GST_WARNING_OBJECT (resample, "Failed to push drain: %s",
+        gst_flow_get_name (res));
+
+  return;
 }
 
 static gboolean
-audioresample_check_discont (GstAudioresample * audioresample,
+gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
+{
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_STOP:
+      gst_audio_resample_reset_state (resample);
+      resample->next_offset = -1;
+      resample->next_ts = -1;
+      resample->next_upstream_ts = -1;
+      break;
+    case GST_EVENT_NEWSEGMENT:
+      gst_audio_resample_push_drain (resample);
+      gst_audio_resample_reset_state (resample);
+      resample->next_offset = -1;
+      resample->next_ts = -1;
+      resample->next_upstream_ts = -1;
+      break;
+    case GST_EVENT_EOS:
+      gst_audio_resample_push_drain (resample);
+      gst_audio_resample_reset_state (resample);
+      break;
+    default:
+      break;
+  }
+
+  return parent_class->event (base, event);
+}
+
+static gboolean
+gst_audio_resample_check_discont (GstAudioResample * resample,
     GstClockTime timestamp)
 {
   if (timestamp != GST_CLOCK_TIME_NONE &&
-      audioresample->prev_ts != GST_CLOCK_TIME_NONE &&
-      audioresample->prev_duration != GST_CLOCK_TIME_NONE &&
-      timestamp != audioresample->prev_ts + audioresample->prev_duration) {
+      resample->next_upstream_ts != GST_CLOCK_TIME_NONE &&
+      timestamp != resample->next_upstream_ts) {
     /* Potentially a discontinuous buffer. However, it turns out that many
      * elements generate imperfect streams due to rounding errors, so we permit
      * a small error (up to one sample) without triggering a filter 
      * flush/restart (if triggered incorrectly, this will be audible) */
-    GstClockTimeDiff diff = timestamp -
-        (audioresample->prev_ts + audioresample->prev_duration);
+    GstClockTimeDiff diff = timestamp - resample->next_upstream_ts;
 
-    if (ABS (diff) > GST_SECOND / audioresample->i_rate) {
-      GST_WARNING_OBJECT (audioresample,
-          "encountered timestamp discontinuity of %" G_GINT64_FORMAT, diff);
+    if (ABS (diff) > (GST_SECOND + resample->inrate - 1) / resample->inrate) {
+      GST_WARNING_OBJECT (resample,
+          "encountered timestamp discontinuity of %s%" GST_TIME_FORMAT,
+          (diff < 0) ? "-" : "", GST_TIME_ARGS ((GstClockTime) ABS (diff)));
       return TRUE;
     }
   }
@@ -608,23 +925,136 @@
 }
 
 static GstFlowReturn
-audioresample_transform (GstBaseTransform * base, GstBuffer * inbuf,
+gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
     GstBuffer * outbuf)
 {
-  GstAudioresample *audioresample;
-  ResampleState *r;
-  guchar *data, *datacopy;
+  guint32 in_len, in_processed;
+  guint32 out_len, out_processed;
+  gint err = RESAMPLER_ERR_SUCCESS;
+  guint8 *in_tmp = NULL, *out_tmp = NULL;
+  gboolean need_convert = (resample->funcs->width != resample->width);
+
+  in_len = GST_BUFFER_SIZE (inbuf) / resample->channels;
+  out_len = GST_BUFFER_SIZE (outbuf) / resample->channels;
+
+  in_len /= (resample->width / 8);
+  out_len /= (resample->width / 8);
+
+  in_processed = in_len;
+  out_processed = out_len;
+
+  if (need_convert) {
+    guint in_size_tmp =
+        in_len * resample->channels * (resample->funcs->width / 8);
+    guint out_size_tmp =
+        out_len * resample->channels * (resample->funcs->width / 8);
+
+    if (in_size_tmp <= resample->tmp_in_size) {
+      in_tmp = resample->tmp_in;
+    } else {
+      resample->tmp_in = in_tmp = g_realloc (resample->tmp_in, in_size_tmp);
+      resample->tmp_in_size = in_size_tmp;
+    }
+
+    gst_audio_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf),
+        in_tmp, in_len, FALSE);
+
+    if (out_size_tmp <= resample->tmp_out_size) {
+      out_tmp = resample->tmp_out;
+    } else {
+      resample->tmp_out = out_tmp = g_realloc (resample->tmp_out, out_size_tmp);
+      resample->tmp_out_size = out_size_tmp;
+    }
+  }
+
+  if (need_convert) {
+    err = resample->funcs->process (resample->state,
+        in_tmp, &in_processed, out_tmp, &out_processed);
+  } else {
+    err = resample->funcs->process (resample->state,
+        (const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed,
+        (guint8 *) GST_BUFFER_DATA (outbuf), &out_processed);
+  }
+
+  if (G_UNLIKELY (in_len != in_processed))
+    GST_WARNING_OBJECT (resample, "Converted %d of %d input samples",
+        in_processed, in_len);
+
+  if (out_len != out_processed) {
+    if (out_processed == 0) {
+      GST_DEBUG_OBJECT (resample, "Converted to 0 samples, buffer dropped");
+
+      return GST_BASE_TRANSFORM_FLOW_DROPPED;
+    }
+
+    /* If we wrote more than allocated something is really wrong now
+     * and we should better abort immediately */
+    g_assert (out_len >= out_processed);
+  }
+
+  if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
+    GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
+        resample->funcs->strerror (err));
+    return GST_FLOW_ERROR;
+  } else {
+
+    if (need_convert)
+      gst_audio_resample_convert_buffer (resample, out_tmp,
+          GST_BUFFER_DATA (outbuf), out_processed, TRUE);
+
+    GST_BUFFER_DURATION (outbuf) =
+        GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
+    GST_BUFFER_SIZE (outbuf) =
+        out_processed * resample->channels * (resample->width / 8);
+
+    if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
+      GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts;
+      GST_BUFFER_OFFSET (outbuf) = resample->next_offset;
+      GST_BUFFER_OFFSET_END (outbuf) = resample->next_offset + out_processed;
+
+      resample->next_ts += GST_BUFFER_DURATION (outbuf);
+      resample->next_offset += out_processed;
+    }
+
+    GST_LOG_OBJECT (resample,
+        "Converted to buffer of %u bytes with timestamp %" GST_TIME_FORMAT
+        ", duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
+        ", offset_end %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (outbuf),
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
+        GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
+
+    return GST_FLOW_OK;
+  }
+}
+
+static GstFlowReturn
+gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
+    GstBuffer * outbuf)
+{
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
+  guint8 *data;
   gulong size;
   GstClockTime timestamp;
+  guint outsamples, insamples;
+  GstFlowReturn ret;
 
-  audioresample = GST_AUDIORESAMPLE (base);
-  r = audioresample->resample;
+  if (resample->state == NULL) {
+    if (G_UNLIKELY (!(resample->state =
+                gst_audio_resample_init_state (resample, resample->width,
+                    resample->channels, resample->inrate, resample->outrate,
+                    resample->quality, resample->fp))))
+      return GST_FLOW_ERROR;
+
+    resample->funcs =
+        gst_audio_resample_get_funcs (resample->width, resample->fp);
+  }
 
   data = GST_BUFFER_DATA (inbuf);
   size = GST_BUFFER_SIZE (inbuf);
   timestamp = GST_BUFFER_TIMESTAMP (inbuf);
 
-  GST_LOG_OBJECT (audioresample, "transforming buffer of %ld bytes, ts %"
+  GST_LOG_OBJECT (resample, "transforming buffer of %ld bytes, ts %"
       GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %"
       G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
       size, GST_TIME_ARGS (timestamp),
@@ -632,88 +1062,57 @@
       GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf));
 
   /* check for timestamp discontinuities and flush/reset if needed */
-  if (G_UNLIKELY (audioresample_check_discont (audioresample, timestamp))) {
+  if (G_UNLIKELY (gst_audio_resample_check_discont (resample, timestamp)
+          || GST_BUFFER_IS_DISCONT (inbuf))) {
     /* Flush internal samples */
-    audioresample_pushthrough (audioresample);
+    gst_audio_resample_reset_state (resample);
     /* Inform downstream element about discontinuity */
-    audioresample->need_discont = TRUE;
-    /* We want to recalculate the offset */
-    audioresample->ts_offset = -1;
+    resample->need_discont = TRUE;
+    /* We want to recalculate the timestamps */
+    resample->next_ts = -1;
+    resample->next_upstream_ts = -1;
+    resample->next_offset = -1;
   }
 
-  if (audioresample->ts_offset == -1) {
-    /* if we don't know the initial offset yet, calculate it based on the 
-     * input timestamp. */
-    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-      GstClockTime stime;
+  insamples = GST_BUFFER_SIZE (inbuf) / resample->channels;
+  insamples /= (resample->width / 8);
 
-      /* offset used to calculate the timestamps. We use the sample offset for
-       * this to make it more accurate. We want the first buffer to have the
-       * same timestamp as the incoming timestamp. */
-      audioresample->next_ts = timestamp;
-      audioresample->ts_offset =
-          gst_util_uint64_scale_int (timestamp, r->o_rate, GST_SECOND);
-      /* offset used to set as the buffer offset, this offset is always
-       * relative to the stream time, note that timestamp is not... */
-      stime = (timestamp - base->segment.start) + base->segment.time;
-      audioresample->offset =
-          gst_util_uint64_scale_int (stime, r->o_rate, GST_SECOND);
-    }
-  }
-  audioresample->prev_ts = timestamp;
-  audioresample->prev_duration = GST_BUFFER_DURATION (inbuf);
+  outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels;
+  outsamples /= (resample->width / 8);
 
-  /* need to memdup, resample takes ownership. */
-  datacopy = g_memdup (data, size);
-  resample_add_input_data (r, datacopy, size, g_free, datacopy);
-
-  return audioresample_do_output (audioresample, outbuf);
-}
-
-/* push remaining data in the buffers out */
-static GstFlowReturn
-audioresample_pushthrough (GstAudioresample * audioresample)
-{
-  int outsize;
-  ResampleState *r;
-  GstBuffer *outbuf;
-  GstFlowReturn res = GST_FLOW_OK;
-  GstBaseTransform *trans;
-
-  r = audioresample->resample;
-
-  outsize = resample_get_output_size (r);
-  if (outsize == 0) {
-    GST_DEBUG_OBJECT (audioresample, "no internal buffers needing flush");
-    goto done;
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)
+      && !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
+    resample->next_ts = timestamp;
+    resample->next_offset =
+        GST_CLOCK_TIME_TO_FRAMES (timestamp, resample->outrate);
   }
 
-  trans = GST_BASE_TRANSFORM (audioresample);
-
-  res = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET_NONE, outsize,
-      GST_PAD_CAPS (trans->srcpad), &outbuf);
-  if (G_UNLIKELY (res != GST_FLOW_OK)) {
-    GST_WARNING_OBJECT (audioresample, "failed allocating buffer of %d bytes",
-        outsize);
-    goto done;
+  if (G_UNLIKELY (resample->need_discont)) {
+    GST_DEBUG_OBJECT (resample, "marking this buffer with the DISCONT flag");
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+    resample->need_discont = FALSE;
   }
 
-  res = audioresample_do_output (audioresample, outbuf);
-  if (G_UNLIKELY (res != GST_FLOW_OK))
-    goto done;
+  ret = gst_audio_resample_process (resample, inbuf, outbuf);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    return ret;
 
-  res = gst_pad_push (trans->srcpad, outbuf);
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)
+      && !GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts))
+    resample->next_upstream_ts = timestamp;
 
-done:
-  return res;
+  if (GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts))
+    resample->next_upstream_ts +=
+        GST_FRAMES_TO_CLOCK_TIME (insamples, resample->inrate);
+
+  return GST_FLOW_OK;
 }
 
 static gboolean
-audioresample_query (GstPad * pad, GstQuery * query)
+gst_audio_resample_query (GstPad * pad, GstQuery * query)
 {
-  GstAudioresample *audioresample =
-      GST_AUDIORESAMPLE (gst_pad_get_parent (pad));
-  GstBaseTransform *trans = GST_BASE_TRANSFORM (audioresample);
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (gst_pad_get_parent (pad));
+  GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
   gboolean res = TRUE;
 
   switch (GST_QUERY_TYPE (query)) {
@@ -723,8 +1122,14 @@
       gboolean live;
       guint64 latency;
       GstPad *peer;
-      gint rate = audioresample->i_rate;
-      gint resampler_latency = audioresample->filter_length / 2;
+      gint rate = resample->inrate;
+      gint resampler_latency;
+
+      if (resample->state)
+        resampler_latency =
+            resample->funcs->get_input_latency (resample->state);
+      else
+        resampler_latency = 0;
 
       if (gst_base_transform_is_passthrough (trans))
         resampler_latency = 0;
@@ -733,7 +1138,7 @@
         if ((res = gst_pad_query (peer, query))) {
           gst_query_parse_latency (query, &live, &min, &max);
 
-          GST_DEBUG ("Peer latency: min %"
+          GST_DEBUG_OBJECT (resample, "Peer latency: min %"
               GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
               GST_TIME_ARGS (min), GST_TIME_ARGS (max));
 
@@ -744,13 +1149,14 @@
           else
             latency = 0;
 
-          GST_DEBUG ("Our latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
+          GST_DEBUG_OBJECT (resample, "Our latency: %" GST_TIME_FORMAT,
+              GST_TIME_ARGS (latency));
 
           min += latency;
           if (max != GST_CLOCK_TIME_NONE)
             max += latency;
 
-          GST_DEBUG ("Calculated total latency : min %"
+          GST_DEBUG_OBJECT (resample, "Calculated total latency : min %"
               GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
               GST_TIME_ARGS (min), GST_TIME_ARGS (max));
 
@@ -764,12 +1170,12 @@
       res = gst_pad_query_default (pad, query);
       break;
   }
-  gst_object_unref (audioresample);
+  gst_object_unref (resample);
   return res;
 }
 
 static const GstQueryType *
-audioresample_query_type (GstPad * pad)
+gst_audio_resample_query_type (GstPad * pad)
 {
   static const GstQueryType types[] = {
     GST_QUERY_LATENCY,
@@ -780,23 +1186,112 @@
 }
 
 static void
-gst_audioresample_set_property (GObject * object, guint prop_id,
+gst_audio_resample_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  GstAudioresample *audioresample;
+  GstAudioResample *resample;
 
-  audioresample = GST_AUDIORESAMPLE (object);
+  resample = GST_AUDIO_RESAMPLE (object);
 
   switch (prop_id) {
-    case PROP_FILTERLEN:
-      audioresample->filter_length = g_value_get_int (value);
-      GST_DEBUG_OBJECT (GST_ELEMENT (audioresample), "new filter length %d",
-          audioresample->filter_length);
-      if (audioresample->resample) {
-        resample_set_filter_length (audioresample->resample,
-            audioresample->filter_length);
-        gst_element_post_message (GST_ELEMENT (audioresample),
-            gst_message_new_latency (GST_OBJECT (audioresample)));
+    case PROP_QUALITY:
+      GST_BASE_TRANSFORM_LOCK (resample);
+      resample->quality = g_value_get_int (value);
+      GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
+
+      gst_audio_resample_update_state (resample, resample->width,
+          resample->channels, resample->inrate, resample->outrate,
+          resample->quality, resample->fp);
+      GST_BASE_TRANSFORM_UNLOCK (resample);
+      break;
+    case PROP_FILTER_LENGTH:{
+      gint filter_length = g_value_get_int (value);
+
+      GST_BASE_TRANSFORM_LOCK (resample);
+      if (filter_length <= 8)
+        resample->quality = 0;
+      else if (filter_length <= 16)
+        resample->quality = 1;
+      else if (filter_length <= 32)
+        resample->quality = 2;
+      else if (filter_length <= 48)
+        resample->quality = 3;
+      else if (filter_length <= 64)
+        resample->quality = 4;
+      else if (filter_length <= 80)
+        resample->quality = 5;
+      else if (filter_length <= 96)
+        resample->quality = 6;
+      else if (filter_length <= 128)
+        resample->quality = 7;
+      else if (filter_length <= 160)
+        resample->quality = 8;
+      else if (filter_length <= 192)
+        resample->quality = 9;
+      else
+        resample->quality = 10;
+
+      GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
+
+      gst_audio_resample_update_state (resample, resample->width,
+          resample->channels, resample->inrate, resample->outrate,
+          resample->quality, resample->fp);
+      GST_BASE_TRANSFORM_UNLOCK (resample);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_resample_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioResample *resample;
+
+  resample = GST_AUDIO_RESAMPLE (object);
+
+  switch (prop_id) {
+    case PROP_QUALITY:
+      g_value_set_int (value, resample->quality);
+      break;
+    case PROP_FILTER_LENGTH:
+      switch (resample->quality) {
+        case 0:
+          g_value_set_int (value, 8);
+          break;
+        case 1:
+          g_value_set_int (value, 16);
+          break;
+        case 2:
+          g_value_set_int (value, 32);
+          break;
+        case 3:
+          g_value_set_int (value, 48);
+          break;
+        case 4:
+          g_value_set_int (value, 64);
+          break;
+        case 5:
+          g_value_set_int (value, 80);
+          break;
+        case 6:
+          g_value_set_int (value, 96);
+          break;
+        case 7:
+          g_value_set_int (value, 128);
+          break;
+        case 8:
+          g_value_set_int (value, 160);
+          break;
+        case 9:
+          g_value_set_int (value, 192);
+          break;
+        case 10:
+          g_value_set_int (value, 256);
+          break;
       }
       break;
     default:
@@ -805,32 +1300,133 @@
   }
 }
 
-static void
-gst_audioresample_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
+#if defined AUDIORESAMPLE_FORMAT_AUTO
+#define BENCHMARK_SIZE 512
+
+static gboolean
+_benchmark_int_float (SpeexResamplerState * st)
 {
-  GstAudioresample *audioresample;
+  gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2];
+  gfloat in_tmp[BENCHMARK_SIZE], out_tmp[BENCHMARK_SIZE / 2];
+  gint i;
+  guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2;
 
-  audioresample = GST_AUDIORESAMPLE (object);
+  for (i = 0; i < BENCHMARK_SIZE; i++) {
+    gfloat tmp = in[i];
+    in_tmp[i] = tmp / G_MAXINT16;
+  }
+
+  resample_float_resampler_process_interleaved_float (st,
+      (const guint8 *) in_tmp, &inlen, (guint8 *) out_tmp, &outlen);
+
+  if (outlen == 0) {
+    GST_ERROR ("Failed to use float resampler");
+    return FALSE;
+  }
 
-  switch (prop_id) {
-    case PROP_FILTERLEN:
-      g_value_set_int (value, audioresample->filter_length);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+  for (i = 0; i < outlen; i++) {
+    gfloat tmp = out_tmp[i];
+    out[i] = CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16);
   }
+
+  return TRUE;
+}
+
+static gboolean
+_benchmark_int_int (SpeexResamplerState * st)
+{
+  gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2];
+  guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2;
+
+  resample_int_resampler_process_interleaved_int (st, (const guint8 *) in,
+      &inlen, (guint8 *) out, &outlen);
+
+  if (outlen == 0) {
+    GST_ERROR ("Failed to use int resampler");
+    return FALSE;
+  }
+
+  return TRUE;
 }
 
+static gboolean
+_benchmark_integer_resampling (void)
+{
+  OilProfile a, b;
+  gdouble av, bv;
+  SpeexResamplerState *sta, *stb;
+  int i;
+
+  oil_profile_init (&a);
+  oil_profile_init (&b);
+
+  sta = resample_float_resampler_init (1, 48000, 24000, 4, NULL);
+  if (sta == NULL) {
+    GST_ERROR ("Failed to create float resampler state");
+    return FALSE;
+  }
+
+  stb = resample_int_resampler_init (1, 48000, 24000, 4, NULL);
+  if (stb == NULL) {
+    resample_float_resampler_destroy (sta);
+    GST_ERROR ("Failed to create int resampler state");
+    return FALSE;
+  }
+
+  /* Benchmark */
+  for (i = 0; i < 10; i++) {
+    oil_profile_start (&a);
+    if (!_benchmark_int_float (sta))
+      goto error;
+    oil_profile_stop (&a);
+  }
+
+  /* Benchmark */
+  for (i = 0; i < 10; i++) {
+    oil_profile_start (&b);
+    if (!_benchmark_int_int (stb))
+      goto error;
+    oil_profile_stop (&b);
+  }
+
+  /* Handle results */
+  oil_profile_get_ave_std (&a, &av, NULL);
+  oil_profile_get_ave_std (&b, &bv, NULL);
+
+  /* Remember benchmark result in global variable */
+  gst_audio_resample_use_int = (av > bv);
+  resample_float_resampler_destroy (sta);
+  resample_int_resampler_destroy (stb);
+
+  if (av > bv)
+    GST_INFO ("Using integer resampler if appropiate: %lf < %lf", bv, av);
+  else
+    GST_INFO ("Using float resampler for everything: %lf <= %lf", av, bv);
+
+  return TRUE;
+
+error:
+  resample_float_resampler_destroy (sta);
+  resample_int_resampler_destroy (stb);
+
+  return FALSE;
+}
+#endif
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  resample_init ();
+  GST_DEBUG_CATEGORY_INIT (audio_resample_debug, "audioresample", 0,
+      "audio resampling element");
+#if defined AUDIORESAMPLE_FORMAT_AUTO
+  oil_init ();
+
+  if (!_benchmark_integer_resampling ())
+    return FALSE;
+#endif
 
   if (!gst_element_register (plugin, "audioresample", GST_RANK_PRIMARY,
-          GST_TYPE_AUDIORESAMPLE)) {
+          GST_TYPE_AUDIO_RESAMPLE)) {
     return FALSE;
   }
 
--- a/gst_plugins_base/gst/audioresample/gstaudioresample.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audioresample/gstaudioresample.h	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2007-2008> Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -18,57 +19,67 @@
  */
 
 
-#ifndef __AUDIORESAMPLE_H__
-#define __AUDIORESAMPLE_H__
+#ifndef __AUDIO_RESAMPLE_H__
+#define __AUDIO_RESAMPLE_H__
 
 #include <gst/gst.h>
 #include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
 
-#include "resample.h"
+#include "speex_resampler_wrapper.h"
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_AUDIORESAMPLE \
-  (gst_audioresample_get_type())
-#define GST_AUDIORESAMPLE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORESAMPLE,GstAudioresample))
-#define GST_AUDIORESAMPLE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORESAMPLE,GstAudioresampleClass))
-#define GST_IS_AUDIORESAMPLE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORESAMPLE))
-#define GST_IS_AUDIORESAMPLE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORESAMPLE))
+#define GST_TYPE_AUDIO_RESAMPLE \
+  (gst_audio_resample_get_type())
+#define GST_AUDIO_RESAMPLE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_RESAMPLE,GstAudioResample))
+#define GST_AUDIO_RESAMPLE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_RESAMPLE,GstAudioResampleClass))
+#define GST_IS_AUDIO_RESAMPLE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_RESAMPLE))
+#define GST_IS_AUDIO_RESAMPLE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_RESAMPLE))
 
-typedef struct _GstAudioresample GstAudioresample;
-typedef struct _GstAudioresampleClass GstAudioresampleClass;
+typedef struct _GstAudioResample GstAudioResample;
+typedef struct _GstAudioResampleClass GstAudioResampleClass;
 
 /**
- * GstAudioresample:
+ * GstAudioResample:
  *
  * Opaque data structure.
  */
-struct _GstAudioresample {
+struct _GstAudioResample {
   GstBaseTransform element;
 
+  /* <private> */
+
   GstCaps *srccaps, *sinkcaps;
 
-  gboolean passthru;
   gboolean need_discont;
 
-  guint64 offset;
-  guint64 ts_offset;
+  guint64 next_offset;
   GstClockTime next_ts;
-  GstClockTime prev_ts, prev_duration;
-  int channels;
+  GstClockTime next_upstream_ts;
+  
+  gint channels;
+  gint inrate;
+  gint outrate;
+  gint quality;
+  gint width;
+  gboolean fp;
 
-  int i_rate;
-  int o_rate;
-  int filter_length;
+  guint8 *tmp_in;
+  guint tmp_in_size;
 
-  ResampleState * resample;
+  guint8 *tmp_out;
+  guint tmp_out_size;
+
+  SpeexResamplerState *state;
+  const SpeexResampleFuncs *funcs;
 };
 
-struct _GstAudioresampleClass {
+struct _GstAudioResampleClass {
   GstBaseTransformClass parent_class;
 };
 #ifdef __SYMBIAN32__
@@ -76,8 +87,8 @@
 #endif
 
 
-GType gst_audioresample_get_type(void);
+GType gst_audio_resample_get_type(void);
 
 G_END_DECLS
 
-#endif /* __AUDIORESAMPLE_H__ */
+#endif /* __AUDIO_RESAMPLE_H__ */
--- a/gst_plugins_base/gst/audioresample/resample.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,395 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
- *
- * 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 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#ifndef __SYMBIAN32__
-#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
-
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#ifndef __SYMBIAN32__
-#include <liboil/liboil.h>
-#endif
-
-#include "resample.h"
-#include "buffer.h"
-#include "debug.h"
-
-void resample_scale_ref (ResampleState * r);
-void resample_scale_functable (ResampleState * r);
-
-GST_DEBUG_CATEGORY (libaudioresample_debug);
-
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-void
-resample_init (void)
-{
-  static int inited = 0;
-#ifndef __SYMBIAN32__
-  if (!inited) {
-    oil_init ();
-    inited = 1;
-    GST_DEBUG_CATEGORY_INIT (libaudioresample_debug, "libaudioresample", 0,
-        "audio resampling library");
-
-  }
-#endif  
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-ResampleState *
-resample_new (void)
-{
-  ResampleState *r;
-
-  r = malloc (sizeof (ResampleState));
-  memset (r, 0, sizeof (ResampleState));
-
-  r->filter_length = 16;
-
-  r->i_start = 0;
-  if (r->filter_length & 1) {
-    r->o_start = 0;
-  } else {
-    r->o_start = r->o_inc * 0.5;
-  }
-
-  r->queue = audioresample_buffer_queue_new ();
-  r->out_tmp = malloc (10000 * sizeof (double));
-
-  r->need_reinit = 1;
-
-  return r;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_free (ResampleState * r)
-{
-  if (r->buffer) {
-    free (r->buffer);
-  }
-  if (r->ft) {
-    functable_free (r->ft);
-  }
-  if (r->queue) {
-    audioresample_buffer_queue_free (r->queue);
-  }
-  if (r->out_tmp) {
-    free (r->out_tmp);
-  }
-
-  free (r);
-}
-
-static void
-resample_buffer_free (AudioresampleBuffer * buffer, void *priv)
-{
-  if (buffer->priv2) {
-    ((void (*)(void *)) buffer->priv2) (buffer->priv);
-  }
-}
-
-/*
- * free_func: a function that frees the given closure.  If NULL, caller is
- *            responsible for freeing.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-resample_add_input_data (ResampleState * r, void *data, int size,
-    void (*free_func) (void *), void *closure)
-{
-  AudioresampleBuffer *buffer;
-
-  RESAMPLE_DEBUG ("data %p size %d", data, size);
-
-  buffer = audioresample_buffer_new_with_data (data, size);
-  buffer->free = resample_buffer_free;
-  buffer->priv2 = (void *) free_func;
-  buffer->priv = closure;
-
-  audioresample_buffer_queue_push (r->queue, buffer);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_input_flush (ResampleState * r)
-{
-  RESAMPLE_DEBUG ("flush");
-
-  audioresample_buffer_queue_flush (r->queue);
-  r->buffer_filled = 0;
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_input_pushthrough (ResampleState * r)
-{
-  AudioresampleBuffer *buffer;
-  int filter_bytes;
-  int buffer_filled;
-
-  if (r->sample_size == 0)
-    return;
-
-  filter_bytes = r->filter_length * r->sample_size;
-  buffer_filled = r->buffer_filled;
-
-  RESAMPLE_DEBUG ("pushthrough filter_bytes %d, filled %d",
-      filter_bytes, buffer_filled);
-
-  /* if we have no pending samples, we don't need to do anything. */
-  if (buffer_filled <= 0)
-    return;
-
-  /* send filter_length/2 number of samples so we can get to the
-   * last queued samples */
-  buffer = audioresample_buffer_new_and_alloc (filter_bytes / 2);
-  memset (buffer->data, 0, buffer->length);
-
-  RESAMPLE_DEBUG ("pushthrough %u", buffer->length);
-
-  audioresample_buffer_queue_push (r->queue, buffer);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_input_eos (ResampleState * r)
-{
-  RESAMPLE_DEBUG ("EOS");
-  resample_input_pushthrough (r);
-  r->eos = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-resample_get_output_size_for_input (ResampleState * r, int size)
-{
-  int outsize;
-  double outd;
-  int avail;
-  int filter_bytes;
-  int buffer_filled;
-
-  if (r->sample_size == 0)
-    return 0;
-
-  filter_bytes = r->filter_length * r->sample_size;
-  buffer_filled = filter_bytes / 2 - r->buffer_filled / 2;
-
-  avail =
-      audioresample_buffer_queue_get_depth (r->queue) + size - buffer_filled;
-
-  RESAMPLE_DEBUG ("avail %d, o_rate %f, i_rate %f, filter_bytes %d, filled %d",
-      avail, r->o_rate, r->i_rate, filter_bytes, buffer_filled);
-  if (avail <= 0)
-    return 0;
-
-  outd = (double) avail *r->o_rate / r->i_rate;
-
-  outsize = (int) floor (outd);
-
-  /* round off for sample size */
-  outsize -= outsize % r->sample_size;
-
-  return outsize;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-resample_get_input_size_for_output (ResampleState * r, int size)
-{
-  int outsize;
-  double outd;
-  int avail;
-
-  if (r->sample_size == 0)
-    return 0;
-
-  avail = size;
-
-  RESAMPLE_DEBUG ("size %d, o_rate %f, i_rate %f", avail, r->o_rate, r->i_rate);
-  outd = (double) avail *r->i_rate / r->o_rate;
-
-  outsize = (int) ceil (outd);
-
-  /* round off for sample size */
-  outsize -= outsize % r->sample_size;
-
-  return outsize;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-resample_get_output_size (ResampleState * r)
-{
-  return resample_get_output_size_for_input (r, 0);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-resample_get_output_data (ResampleState * r, void *data, int size)
-{
-  r->o_buf = data;
-  r->o_size = size;
-
-  if (size == 0)
-    return 0;
-
-  switch (r->method) {
-    case 0:
-      resample_scale_ref (r);
-      break;
-    case 1:
-      resample_scale_functable (r);
-      break;
-    default:
-      break;
-  }
-
-  return size - r->o_size;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_set_filter_length (ResampleState * r, int length)
-{
-  r->filter_length = length;
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_set_input_rate (ResampleState * r, double rate)
-{
-  r->i_rate = rate;
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_set_output_rate (ResampleState * r, double rate)
-{
-  r->o_rate = rate;
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_set_n_channels (ResampleState * r, int n_channels)
-{
-  r->n_channels = n_channels;
-  r->sample_size = r->n_channels * resample_format_size (r->format);
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_set_format (ResampleState * r, ResampleFormat format)
-{
-  r->format = format;
-  r->sample_size = r->n_channels * resample_format_size (r->format);
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_set_method (ResampleState * r, int method)
-{
-  r->method = method;
-  r->need_reinit = 1;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-int
-resample_format_size (ResampleFormat format)
-{
-  switch (format) {
-    case RESAMPLE_FORMAT_S16:
-      return 2;
-    case RESAMPLE_FORMAT_S32:
-    case RESAMPLE_FORMAT_F32:
-      return 4;
-    case RESAMPLE_FORMAT_F64:
-      return 8;
-  }
-  return 0;
-}
--- a/gst_plugins_base/gst/audioresample/resample.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David Schleef <ds@schleef.org>
- *
- * 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 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 __RESAMPLE_H__
-#define __RESAMPLE_H__
-
-#include "functable.h"
-#include "buffer.h"
-
-#ifndef M_PI
-#define M_PI  3.14159265358979323846
-#endif
-
-#ifdef WIN32
-#define rint(x) (floor((x)+0.5))  
-#endif 
-
-typedef enum {
-        RESAMPLE_FORMAT_S16 = 0,
-        RESAMPLE_FORMAT_S32,
-        RESAMPLE_FORMAT_F32,
-        RESAMPLE_FORMAT_F64
-} ResampleFormat;
-
-typedef void (*ResampleCallback) (void *);
-
-typedef struct _ResampleState ResampleState;
-
-struct _ResampleState {
-        /* parameters */
-
-        int n_channels;
-        ResampleFormat format;
-
-        int filter_length;
-
-        double i_rate;
-        double o_rate;
-
-        int method;
-
-        /* internal parameters */
-
-        int need_reinit;
-
-        double halftaps;
-
-        /* filter state */
-
-        unsigned char *o_buf;
-        int o_size;
-
-        AudioresampleBufferQueue *queue;
-        int eos;
-        int started;
-
-        int sample_size;
-
-        unsigned char *buffer;
-        int buffer_len;
-        int buffer_filled;
-
-        double i_start;
-        double o_start;
-
-        double i_inc;
-        double o_inc;
-
-        double sinc_scale;
-
-        double i_end;
-        double o_end;
-
-        int i_samples;
-        int o_samples;
-
-        //void *i_buf;
-
-        Functable *ft;
-
-        double *out_tmp;
-};
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-void resample_init (void);
-void resample_cleanup (void);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-ResampleState *resample_new (void);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_free (ResampleState *state);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-void resample_add_input_data (ResampleState * r, void *data, int size,
-    ResampleCallback free_func, void *closure);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_input_eos (ResampleState *r);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_input_flush (ResampleState *r);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_input_pushthrough (ResampleState *r);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-int resample_get_output_size_for_input (ResampleState * r, int size);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-int resample_get_input_size_for_output (ResampleState * r, int size);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-int resample_get_output_size (ResampleState *r);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-int resample_get_output_data (ResampleState *r, void *data, int size);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
-void resample_set_filter_length (ResampleState *r, int length);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_set_input_rate (ResampleState *r, double rate);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_set_output_rate (ResampleState *r, double rate);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_set_n_channels (ResampleState *r, int n_channels);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_set_format (ResampleState *r, ResampleFormat format);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void resample_set_method (ResampleState *r, int method);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-int resample_format_size (ResampleFormat format);
-
-#endif /* __RESAMPLE_H__ */
-
--- a/gst_plugins_base/gst/audioresample/resample_chunk.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
- *
- * 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 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#ifndef __SYMBIAN32__
-#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
-
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#ifndef __SYMBIAN32__
-#include <liboil/liboil.h>
-#endif
-
-#include "resample.h"
-#include "buffer.h"
-#include "debug.h"
-
-
-static double
-resample_sinc_window (double x, double halfwidth, double scale)
-{
-  double y;
-
-  if (x == 0)
-    return 1.0;
-  if (x < -halfwidth || x > halfwidth)
-    return 0.0;
-
-  y = sin (x * M_PI * scale) / (x * M_PI * scale) * scale;
-
-  x /= halfwidth;
-  y *= (1 - x * x) * (1 - x * x);
-
-  return y;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_scale_chunk (ResampleState * r)
-{
-  if (r->need_reinit) {
-    RESAMPLE_DEBUG ("sample size %d", r->sample_size);
-
-    if (r->buffer)
-      free (r->buffer);
-    r->buffer_len = r->sample_size * 1000;
-    r->buffer = malloc (r->buffer_len);
-    memset (r->buffer, 0, r->buffer_len);
-
-    r->i_inc = r->o_rate / r->i_rate;
-    r->o_inc = r->i_rate / r->o_rate;
-    RESAMPLE_DEBUG ("i_inc %g o_inc %g", r->i_inc, r->o_inc);
-
-    r->i_start = -r->i_inc * r->filter_length;
-
-    r->need_reinit = 0;
-
-#if 0
-    if (r->i_inc < 1.0) {
-      r->sinc_scale = r->i_inc;
-      if (r->sinc_scale == 0.5) {
-        /* strange things happen at integer multiples */
-        r->sinc_scale = 1.0;
-      }
-    } else {
-      r->sinc_scale = 1.0;
-    }
-#else
-    r->sinc_scale = 1.0;
-#endif
-  }
-
-  while (r->o_size > 0) {
-    double midpoint;
-    int i;
-    int j;
-
-    RESAMPLE_DEBUG ("i_start %g", r->i_start);
-    midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
-    if (midpoint > 0.5 * r->i_inc) {
-      RESAMPLE_ERROR ("inconsistent state");
-    }
-    while (midpoint < -0.5 * r->i_inc) {
-      AudioresampleBuffer *buffer;
-
-      buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
-      if (buffer == NULL) {
-        RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
-        return;
-      }
-
-      r->i_start += r->i_inc;
-      RESAMPLE_DEBUG ("pulling (i_start = %g)", r->i_start);
-
-      midpoint += r->i_inc;
-      memmove (r->buffer, r->buffer + r->sample_size,
-          r->buffer_len - r->sample_size);
-
-      memcpy (r->buffer + r->buffer_len - r->sample_size, buffer->data,
-          r->sample_size);
-      audioresample_buffer_unref (buffer);
-    }
-
-    switch (r->format) {
-      case RESAMPLE_FORMAT_S16:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(int16_t *) (r->buffer + i * sizeof (int16_t) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-          if (acc < -32768.0)
-            acc = -32768.0;
-          if (acc > 32767.0)
-            acc = 32767.0;
-
-          *(int16_t *) (r->o_buf + i * sizeof (int16_t)) = rint (acc);
-        }
-        break;
-      case RESAMPLE_FORMAT_S32:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(int32_t *) (r->buffer + i * sizeof (int32_t) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-          if (acc < -2147483648.0)
-            acc = -2147483648.0;
-          if (acc > 2147483647.0)
-            acc = 2147483647.0;
-
-          *(int32_t *) (r->o_buf + i * sizeof (int32_t)) = rint (acc);
-        }
-        break;
-      case RESAMPLE_FORMAT_F32:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(float *) (r->buffer + i * sizeof (float) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-
-          *(float *) (r->o_buf + i * sizeof (float)) = acc;
-        }
-        break;
-      case RESAMPLE_FORMAT_F64:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(double *) (r->buffer + i * sizeof (double) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-
-          *(double *) (r->o_buf + i * sizeof (double)) = acc;
-        }
-        break;
-    }
-
-    r->i_start -= 1.0;
-    r->o_buf += r->sample_size;
-    r->o_size -= r->sample_size;
-  }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/resample_double.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1346 @@
+/* Copyright (C) 2007-2008 Jean-Marc Valin
+   Copyright (C) 2008      Thorvald Natvig
+      
+   File: resample.c
+   Arbitrary resampling code
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+   The design goals of this code are:
+      - Very fast algorithm
+      - SIMD-friendly algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Warning: This resampler is relatively new. Although I think I got rid of 
+   all the major bugs and I don't expect the API to change anymore, there
+   may be something I've missed. So use with caution.
+
+   This algorithm is based on this original resampling algorithm:
+   Smith, Julius O. Digital Audio Resampling Home Page
+   Center for Computer Research in Music and Acoustics (CCRMA), 
+   Stanford University, 2007.
+   Web published at http://www-ccrma.stanford.edu/~jos/resample/.
+
+   There is one main difference, though. This resampler uses cubic 
+   interpolation instead of linear interpolation in the above paper. This
+   makes the table much smaller and makes it possible to compute that table
+   on a per-stream basis. In turn, being able to tweak the table for each 
+   stream makes it possible to both reduce complexity on simple ratios 
+   (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
+   The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef OUTSIDE_SPEEX
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glibconfig.h>
+#include <e32def.h>
+
+#ifndef __SYMBIAN32__
+#define EXPORT EXPORT_C
+#else
+#define EXPORT G_GNUC_INTERNAL
+#endif
+
+static inline void *
+speex_alloc (int size)
+{
+  return g_malloc0 (size);
+}
+
+static inline void *
+speex_realloc (void *ptr, int size)
+{
+  return g_realloc (ptr, size);
+}
+
+static inline void
+speex_free (void *ptr)
+{
+  g_free (ptr);
+}
+
+#include "speex_resampler.h"
+#include "arch_double.h"
+#else /* OUTSIDE_SPEEX */
+
+#include "speex_resampler.h"
+#include "arch.h"
+//#include "os_support.h"
+#endif /* OUTSIDE_SPEEX */
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159263
+#endif
+
+#ifdef FIXED_POINT
+#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
+#else
+#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
+#endif
+
+#define IMAX(a,b) ((a) > (b) ? (a) : (b))
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef _USE_SSE
+#include "resample_sse.h"
+#endif
+
+/* Numer of elements to allocate on the stack */
+#ifdef VAR_ARRAYS
+#define FIXED_STACK_ALLOC 8192
+#else
+#define FIXED_STACK_ALLOC 1024
+#endif
+
+typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t,
+    const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
+
+struct SpeexResamplerState_
+{
+  spx_uint32_t in_rate;
+  spx_uint32_t out_rate;
+  spx_uint32_t num_rate;
+  spx_uint32_t den_rate;
+
+  int quality;
+  spx_uint32_t nb_channels;
+  spx_uint32_t filt_len;
+  spx_uint32_t mem_alloc_size;
+  spx_uint32_t buffer_size;
+  int int_advance;
+  int frac_advance;
+  float cutoff;
+  spx_uint32_t oversample;
+  int initialised;
+  int started;
+
+  /* These are per-channel */
+  spx_int32_t *last_sample;
+  spx_uint32_t *samp_frac_num;
+  spx_uint32_t *magic_samples;
+
+  spx_word16_t *mem;
+  spx_word16_t *sinc_table;
+  spx_uint32_t sinc_table_length;
+  resampler_basic_func resampler_ptr;
+
+  int in_stride;
+  int out_stride;
+};
+
+static double kaiser12_table[68] = {
+  0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
+  0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
+  0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
+  0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
+  0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
+  0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
+  0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
+  0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
+  0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
+  0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
+  0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
+  0.00001000, 0.00000000
+};
+
+/*
+static double kaiser12_table[36] = {
+   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
+   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
+   0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
+   0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
+   0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
+   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
+*/
+static double kaiser10_table[36] = {
+  0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
+  0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
+  0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
+  0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
+  0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
+  0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000
+};
+
+static double kaiser8_table[36] = {
+  0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
+  0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
+  0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
+  0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
+  0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
+  0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000
+};
+
+static double kaiser6_table[36] = {
+  0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
+  0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
+  0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
+  0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
+  0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
+  0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000
+};
+
+struct FuncDef
+{
+  double *table;
+  int oversample;
+};
+
+static struct FuncDef _KAISER12 = { kaiser12_table, 64 };
+
+#define KAISER12 (&_KAISER12)
+/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
+#define KAISER12 (&_KAISER12)*/
+static struct FuncDef _KAISER10 = { kaiser10_table, 32 };
+
+#define KAISER10 (&_KAISER10)
+static struct FuncDef _KAISER8 = { kaiser8_table, 32 };
+
+#define KAISER8 (&_KAISER8)
+static struct FuncDef _KAISER6 = { kaiser6_table, 32 };
+
+#define KAISER6 (&_KAISER6)
+
+struct QualityMapping
+{
+  int base_length;
+  int oversample;
+  float downsample_bandwidth;
+  float upsample_bandwidth;
+  struct FuncDef *window_func;
+};
+
+
+/* This table maps conversion quality to internal parameters. There are two
+   reasons that explain why the up-sampling bandwidth is larger than the 
+   down-sampling bandwidth:
+   1) When up-sampling, we can assume that the spectrum is already attenuated
+      close to the Nyquist rate (from an A/D or a previous resampling filter)
+   2) Any aliasing that occurs very close to the Nyquist rate will be masked
+      by the sinusoids/noise just below the Nyquist rate (guaranteed only for
+      up-sampling).
+*/
+static const struct QualityMapping quality_map[11] = {
+  {8, 4, 0.830f, 0.860f, KAISER6},      /* Q0 */
+  {16, 4, 0.850f, 0.880f, KAISER6},     /* Q1 */
+  {32, 4, 0.882f, 0.910f, KAISER6},     /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6  */
+  {48, 8, 0.895f, 0.917f, KAISER8},     /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8  */
+  {64, 8, 0.921f, 0.940f, KAISER8},     /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8  */
+  {80, 16, 0.922f, 0.940f, KAISER10},   /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */
+  {96, 16, 0.940f, 0.945f, KAISER10},   /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */
+  {128, 16, 0.950f, 0.950f, KAISER10},  /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */
+  {160, 16, 0.960f, 0.960f, KAISER10},  /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */
+  {192, 32, 0.968f, 0.968f, KAISER12},  /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */
+  {256, 32, 0.975f, 0.975f, KAISER12},  /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */
+};
+
+/*8,24,40,56,80,104,128,160,200,256,320*/
+#ifdef DOUBLE_PRECISION
+static double
+compute_func (double x, struct FuncDef *func)
+{
+  double y, frac;
+#else
+static double
+compute_func (float x, struct FuncDef *func)
+{
+  float y, frac;
+#endif
+  double interp[4];
+  int ind;
+  y = x * func->oversample;
+  ind = (int) floor (y);
+  frac = (y - ind);
+  /* CSE with handle the repeated powers */
+  interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
+  interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
+  /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
+  interp[0] =
+      -0.3333333333 * frac + 0.5 * (frac * frac) -
+      0.1666666667 * (frac * frac * frac);
+  /* Just to make sure we don't have rounding problems */
+  interp[1] = 1.f - interp[3] - interp[2] - interp[0];
+
+  /*sum = frac*accum[1] + (1-frac)*accum[2]; */
+  return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] +
+      interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3];
+}
+
+#if 0
+#include <stdio.h>
+int
+main (int argc, char **argv)
+{
+  int i;
+  for (i = 0; i < 256; i++) {
+    printf ("%f\n", compute_func (i / 256., KAISER12));
+  }
+  return 0;
+}
+#endif
+
+#ifdef FIXED_POINT
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t
+sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  float xx = x * cutoff;
+  if (fabs (x) < 1e-6f)
+    return WORD2INT (32768. * cutoff);
+  else if (fabs (x) > .5f * N)
+    return 0;
+  /*FIXME: Can it really be any slower than this? */
+  return WORD2INT (32768. * cutoff * sin (M_PI * xx) / (M_PI * xx) *
+      compute_func (fabs (2. * x / N), window_func));
+}
+#else
+/* The slow way of computing a sinc for the table. Should improve that some day */
+#ifdef DOUBLE_PRECISION
+static spx_word16_t
+sinc (double cutoff, double x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  double xx = x * cutoff;
+#else
+static spx_word16_t
+sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  float xx = x * cutoff;
+#endif
+  if (fabs (x) < 1e-6)
+    return cutoff;
+  else if (fabs (x) > .5 * N)
+    return 0;
+  /*FIXME: Can it really be any slower than this? */
+  return cutoff * sin (M_PI * xx) / (M_PI * xx) * compute_func (fabs (2. * x /
+          N), window_func);
+}
+#endif
+
+#ifdef FIXED_POINT
+static void
+cubic_coef (spx_word16_t x, spx_word16_t interp[4])
+{
+  /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+     but I know it's MMSE-optimal on a sinc */
+  spx_word16_t x2, x3;
+  x2 = MULT16_16_P15 (x, x);
+  x3 = MULT16_16_P15 (x, x2);
+  interp[0] =
+      PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15),
+          x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
+  interp[1] =
+      EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)),
+          1));
+  interp[3] =
+      PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15),
+          x) + MULT16_16 (QCONST16 (.5f, 15),
+          x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
+  /* Just to make sure we don't have rounding problems */
+  interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3];
+  if (interp[2] < 32767)
+    interp[2] += 1;
+}
+#else
+static void
+cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
+{
+  /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+     but I know it's MMSE-optimal on a sinc */
+  interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac;
+  interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac;
+  /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
+  interp[3] =
+      -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac;
+  /* Just to make sure we don't have rounding problems */
+  interp[2] = 1. - interp[0] - interp[1] - interp[3];
+}
+#endif
+
+#ifndef DOUBLE_PRECISION
+static int
+resampler_basic_direct_single (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const spx_word16_t *sinc_table = st->sinc_table;
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  spx_word32_t sum;
+  int j;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
+    const spx_word16_t *iptr = &in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
+    float accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j += 4) {
+      accum[0] += sinc[j] * iptr[j];
+      accum[1] += sinc[j + 1] * iptr[j + 1];
+      accum[2] += sinc[j + 2] * iptr[j + 2];
+      accum[3] += sinc[j + 3] * iptr[j + 3];
+    }
+    sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+    sum = inner_product_single (sinc, iptr, N);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int
+resampler_basic_direct_double (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const spx_word16_t *sinc_table = st->sinc_table;
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  double sum;
+  int j;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
+    const spx_word16_t *iptr = &in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
+    double accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j += 4) {
+      accum[0] += sinc[j] * iptr[j];
+      accum[1] += sinc[j + 1] * iptr[j + 1];
+      accum[2] += sinc[j + 2] * iptr[j + 2];
+      accum[3] += sinc[j + 3] * iptr[j + 3];
+    }
+    sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+    sum = inner_product_double (sinc, iptr, N);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifndef DOUBLE_PRECISION
+static int
+resampler_basic_interpolate_single (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  int j;
+  spx_word32_t sum;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *iptr = &in[last_sample];
+
+    const int offset = samp_frac_num * st->oversample / st->den_rate;
+#ifdef FIXED_POINT
+    const spx_word16_t frac =
+        PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+        st->den_rate);
+#else
+    const spx_word16_t frac =
+        ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#endif
+    spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
+    spx_word32_t accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j++) {
+      const spx_word16_t curr_in = iptr[j];
+      accum[0] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
+      accum[1] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
+      accum[2] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset]);
+      accum[3] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
+    }
+
+    cubic_coef (frac, interp);
+    sum =
+        MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
+        accum[1]) + MULT16_32_Q15 (interp[2],
+        accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
+#else
+    cubic_coef (frac, interp);
+    sum =
+        interpolate_product_single (iptr,
+        st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
+        interp);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int
+resampler_basic_interpolate_double (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  int j;
+  spx_word32_t sum;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *iptr = &in[last_sample];
+
+    const int offset = samp_frac_num * st->oversample / st->den_rate;
+#ifdef FIXED_POINT
+    const spx_word16_t frac =
+        PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+        st->den_rate);
+#else
+#ifdef DOUBLE_PRECISION
+    const spx_word16_t frac =
+        ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#else
+    const spx_word16_t frac =
+        ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#endif
+#endif
+    spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
+    double accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j++) {
+      const double curr_in = iptr[j];
+      accum[0] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
+      accum[1] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
+      accum[2] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset]);
+      accum[3] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
+    }
+
+    cubic_coef (frac, interp);
+    sum =
+        MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
+        accum[1]) + MULT16_32_Q15 (interp[2],
+        accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
+#else
+    cubic_coef (frac, interp);
+    sum =
+        interpolate_product_double (iptr,
+        st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
+        interp);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+static void
+update_filter (SpeexResamplerState * st)
+{
+  spx_uint32_t old_length;
+
+  old_length = st->filt_len;
+  st->oversample = quality_map[st->quality].oversample;
+  st->filt_len = quality_map[st->quality].base_length;
+
+  if (st->num_rate > st->den_rate) {
+    /* down-sampling */
+    st->cutoff =
+        quality_map[st->quality].downsample_bandwidth * st->den_rate /
+        st->num_rate;
+    /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
+    st->filt_len = st->filt_len * st->num_rate / st->den_rate;
+    /* Round down to make sure we have a multiple of 4 */
+    st->filt_len &= (~0x3);
+    if (2 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (4 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (8 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (16 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (st->oversample < 1)
+      st->oversample = 1;
+  } else {
+    /* up-sampling */
+    st->cutoff = quality_map[st->quality].upsample_bandwidth;
+  }
+
+  /* Choose the resampling type that requires the least amount of memory */
+  if (st->den_rate <= st->oversample) {
+    spx_uint32_t i;
+    if (!st->sinc_table)
+      st->sinc_table =
+          (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate *
+          sizeof (spx_word16_t));
+    else if (st->sinc_table_length < st->filt_len * st->den_rate) {
+      st->sinc_table =
+          (spx_word16_t *) speex_realloc (st->sinc_table,
+          st->filt_len * st->den_rate * sizeof (spx_word16_t));
+      st->sinc_table_length = st->filt_len * st->den_rate;
+    }
+    for (i = 0; i < st->den_rate; i++) {
+      spx_int32_t j;
+      for (j = 0; j < st->filt_len; j++) {
+        st->sinc_table[i * st->filt_len + j] =
+            sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
+#ifdef DOUBLE_PRECISION
+                ((double) i) / st->den_rate), st->filt_len,
+#else
+                ((float) i) / st->den_rate), st->filt_len,
+#endif
+            quality_map[st->quality].window_func);
+      }
+    }
+#ifdef FIXED_POINT
+    st->resampler_ptr = resampler_basic_direct_single;
+#else
+#ifdef DOUBLE_PRECISION
+    st->resampler_ptr = resampler_basic_direct_double;
+#else
+    if (st->quality > 8)
+      st->resampler_ptr = resampler_basic_direct_double;
+    else
+      st->resampler_ptr = resampler_basic_direct_single;
+#endif
+#endif
+    /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
+  } else {
+    spx_int32_t i;
+    if (!st->sinc_table)
+      st->sinc_table =
+          (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample +
+              8) * sizeof (spx_word16_t));
+    else if (st->sinc_table_length < st->filt_len * st->oversample + 8) {
+      st->sinc_table =
+          (spx_word16_t *) speex_realloc (st->sinc_table,
+          (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t));
+      st->sinc_table_length = st->filt_len * st->oversample + 8;
+    }
+    for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
+      st->sinc_table[i + 4] =
+#ifdef DOUBLE_PRECISION
+          sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
+#else
+          sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
+#endif
+          st->filt_len, quality_map[st->quality].window_func);
+#ifdef FIXED_POINT
+    st->resampler_ptr = resampler_basic_interpolate_single;
+#else
+#ifdef DOUBLE_PRECISION
+    st->resampler_ptr = resampler_basic_interpolate_double;
+#else
+    if (st->quality > 8)
+      st->resampler_ptr = resampler_basic_interpolate_double;
+    else
+      st->resampler_ptr = resampler_basic_interpolate_single;
+#endif
+#endif
+    /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
+  }
+  st->int_advance = st->num_rate / st->den_rate;
+  st->frac_advance = st->num_rate % st->den_rate;
+
+
+  /* Here's the place where we update the filter memory to take into account
+     the change in filter length. It's probably the messiest part of the code
+     due to handling of lots of corner cases. */
+  if (!st->mem) {
+    spx_uint32_t i;
+    st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+    st->mem =
+        (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size *
+        sizeof (spx_word16_t));
+    for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
+      st->mem[i] = 0;
+    /*speex_warning("init filter"); */
+  } else if (!st->started) {
+    spx_uint32_t i;
+    st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+    st->mem =
+        (spx_word16_t *) speex_realloc (st->mem,
+        st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
+    for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
+      st->mem[i] = 0;
+    /*speex_warning("reinit filter"); */
+  } else if (st->filt_len > old_length) {
+    spx_int32_t i;
+    /* Increase the filter length */
+    /*speex_warning("increase filter size"); */
+    int old_alloc_size = st->mem_alloc_size;
+    if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) {
+      st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+      st->mem =
+          (spx_word16_t *) speex_realloc (st->mem,
+          st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
+    }
+    for (i = st->nb_channels - 1; i >= 0; i--) {
+      spx_int32_t j;
+      spx_uint32_t olen = old_length;
+      /*if (st->magic_samples[i]) */
+      {
+        /* Try and remove the magic samples as if nothing had happened */
+
+        /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
+        olen = old_length + 2 * st->magic_samples[i];
+        for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--)
+          st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] =
+              st->mem[i * old_alloc_size + j];
+        for (j = 0; j < st->magic_samples[i]; j++)
+          st->mem[i * st->mem_alloc_size + j] = 0;
+        st->magic_samples[i] = 0;
+      }
+      if (st->filt_len > olen) {
+        /* If the new filter length is still bigger than the "augmented" length */
+        /* Copy data going backward */
+        for (j = 0; j < olen - 1; j++)
+          st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] =
+              st->mem[i * st->mem_alloc_size + (olen - 2 - j)];
+        /* Then put zeros for lack of anything better */
+        for (; j < st->filt_len - 1; j++)
+          st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0;
+        /* Adjust last_sample */
+        st->last_sample[i] += (st->filt_len - olen) / 2;
+      } else {
+        /* Put back some of the magic! */
+        st->magic_samples[i] = (olen - st->filt_len) / 2;
+        for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++)
+          st->mem[i * st->mem_alloc_size + j] =
+              st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
+      }
+    }
+  } else if (st->filt_len < old_length) {
+    spx_uint32_t i;
+    /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
+       samples so they can be used directly as input the next time(s) */
+    for (i = 0; i < st->nb_channels; i++) {
+      spx_uint32_t j;
+      spx_uint32_t old_magic = st->magic_samples[i];
+      st->magic_samples[i] = (old_length - st->filt_len) / 2;
+      /* We must copy some of the memory that's no longer used */
+      /* Copy data going backward */
+      for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++)
+        st->mem[i * st->mem_alloc_size + j] =
+            st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
+      st->magic_samples[i] += old_magic;
+    }
+  }
+
+}
+
+EXPORT SpeexResamplerState *
+speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
+    spx_uint32_t out_rate, int quality, int *err)
+{
+  return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
+      out_rate, quality, err);
+}
+
+EXPORT SpeexResamplerState *
+speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
+    spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
+    int quality, int *err)
+{
+  spx_uint32_t i;
+  SpeexResamplerState *st;
+  if (quality > 10 || quality < 0) {
+    if (err)
+      *err = RESAMPLER_ERR_INVALID_ARG;
+    return NULL;
+  }
+  st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
+  st->initialised = 0;
+  st->started = 0;
+  st->in_rate = 0;
+  st->out_rate = 0;
+  st->num_rate = 0;
+  st->den_rate = 0;
+  st->quality = -1;
+  st->sinc_table_length = 0;
+  st->mem_alloc_size = 0;
+  st->filt_len = 0;
+  st->mem = 0;
+  st->resampler_ptr = 0;
+
+  st->cutoff = 1.f;
+  st->nb_channels = nb_channels;
+  st->in_stride = 1;
+  st->out_stride = 1;
+
+#ifdef FIXED_POINT
+  st->buffer_size = 160;
+#else
+  st->buffer_size = 160;
+#endif
+
+  /* Per channel data */
+  st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int));
+  st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
+  st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
+  for (i = 0; i < nb_channels; i++) {
+    st->last_sample[i] = 0;
+    st->magic_samples[i] = 0;
+    st->samp_frac_num[i] = 0;
+  }
+
+  speex_resampler_set_quality (st, quality);
+  speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
+
+
+  update_filter (st);
+
+  st->initialised = 1;
+  if (err)
+    *err = RESAMPLER_ERR_SUCCESS;
+
+  return st;
+}
+
+EXPORT void
+speex_resampler_destroy (SpeexResamplerState * st)
+{
+  speex_free (st->mem);
+  speex_free (st->sinc_table);
+  speex_free (st->last_sample);
+  speex_free (st->magic_samples);
+  speex_free (st->samp_frac_num);
+  speex_free (st);
+}
+
+static int
+speex_resampler_process_native (SpeexResamplerState * st,
+    spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out,
+    spx_uint32_t * out_len)
+{
+  int j = 0;
+  const int N = st->filt_len;
+  int out_sample = 0;
+  spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+  spx_uint32_t ilen;
+
+  st->started = 1;
+
+  /* Call the right resampler through the function ptr */
+  out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len);
+
+  if (st->last_sample[channel_index] < (spx_int32_t) * in_len)
+    *in_len = st->last_sample[channel_index];
+  *out_len = out_sample;
+  st->last_sample[channel_index] -= *in_len;
+
+  ilen = *in_len;
+
+  for (j = 0; j < N - 1; ++j)
+    mem[j] = mem[j + ilen];
+
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+static int
+speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index,
+    spx_word16_t ** out, spx_uint32_t out_len)
+{
+  spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
+  spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+  const int N = st->filt_len;
+
+  speex_resampler_process_native (st, channel_index, &tmp_in_len, *out,
+      &out_len);
+
+  st->magic_samples[channel_index] -= tmp_in_len;
+
+  /* If we couldn't process all "magic" input samples, save the rest for next time */
+  if (st->magic_samples[channel_index]) {
+    spx_uint32_t i;
+    for (i = 0; i < st->magic_samples[channel_index]; i++)
+      mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len];
+  }
+  *out += out_len * st->out_stride;
+  return out_len;
+}
+
+#ifdef FIXED_POINT
+EXPORT int
+speex_resampler_process_int (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+    spx_int16_t * out, spx_uint32_t * out_len)
+#else
+#ifdef DOUBLE_PRECISION
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
+    double *out, spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+    float *out, spx_uint32_t * out_len)
+#endif
+#endif
+{
+  int j;
+  spx_uint32_t ilen = *in_len;
+  spx_uint32_t olen = *out_len;
+  spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+  const int filt_offs = st->filt_len - 1;
+  const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
+  const int istride = st->in_stride;
+
+  if (st->magic_samples[channel_index])
+    olen -= speex_resampler_magic (st, channel_index, &out, olen);
+  if (!st->magic_samples[channel_index]) {
+    while (ilen && olen) {
+      spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+      spx_uint32_t ochunk = olen;
+
+      if (in) {
+        for (j = 0; j < ichunk; ++j)
+          x[j + filt_offs] = in[j * istride];
+      } else {
+        for (j = 0; j < ichunk; ++j)
+          x[j + filt_offs] = 0;
+      }
+      speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk);
+      ilen -= ichunk;
+      olen -= ochunk;
+      out += ochunk * st->out_stride;
+      if (in)
+        in += ichunk * istride;
+    }
+  }
+  *in_len -= ilen;
+  *out_len -= olen;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef FIXED_POINT
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+    float *out, spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_int (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+    spx_int16_t * out, spx_uint32_t * out_len)
+#endif
+{
+  int j;
+  const int istride_save = st->in_stride;
+  const int ostride_save = st->out_stride;
+  spx_uint32_t ilen = *in_len;
+  spx_uint32_t olen = *out_len;
+  spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+  const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
+#ifdef VAR_ARRAYS
+  const unsigned int ylen =
+      (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
+  VARDECL (spx_word16_t * ystack);
+  ALLOC (ystack, ylen, spx_word16_t);
+#else
+  const unsigned int ylen = FIXED_STACK_ALLOC;
+  spx_word16_t ystack[FIXED_STACK_ALLOC];
+#endif
+
+  st->out_stride = 1;
+
+  while (ilen && olen) {
+    spx_word16_t *y = ystack;
+    spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+    spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
+    spx_uint32_t omagic = 0;
+
+    if (st->magic_samples[channel_index]) {
+      omagic = speex_resampler_magic (st, channel_index, &y, ochunk);
+      ochunk -= omagic;
+      olen -= omagic;
+    }
+    if (!st->magic_samples[channel_index]) {
+      if (in) {
+        for (j = 0; j < ichunk; ++j)
+#ifdef FIXED_POINT
+          x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]);
+#else
+          x[j + st->filt_len - 1] = in[j * istride_save];
+#endif
+      } else {
+        for (j = 0; j < ichunk; ++j)
+          x[j + st->filt_len - 1] = 0;
+      }
+
+      speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk);
+    } else {
+      ichunk = 0;
+      ochunk = 0;
+    }
+
+    for (j = 0; j < ochunk + omagic; ++j)
+#ifdef FIXED_POINT
+      out[j * ostride_save] = ystack[j];
+#else
+      out[j * ostride_save] = WORD2INT (ystack[j]);
+#endif
+
+    ilen -= ichunk;
+    olen -= ochunk;
+    out += (ochunk + omagic) * ostride_save;
+    if (in)
+      in += ichunk * istride_save;
+  }
+  st->out_stride = ostride_save;
+  *in_len -= ilen;
+  *out_len -= olen;
+
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef DOUBLE_PRECISION
+EXPORT int
+speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+    const double *in, spx_uint32_t * in_len, double *out,
+    spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+    const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
+#endif
+{
+  spx_uint32_t i;
+  int istride_save, ostride_save;
+  spx_uint32_t bak_len = *out_len;
+  istride_save = st->in_stride;
+  ostride_save = st->out_stride;
+  st->in_stride = st->out_stride = st->nb_channels;
+  for (i = 0; i < st->nb_channels; i++) {
+    *out_len = bak_len;
+    if (in != NULL)
+      speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len);
+    else
+      speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len);
+  }
+  st->in_stride = istride_save;
+  st->out_stride = ostride_save;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_process_interleaved_int (SpeexResamplerState * st,
+    const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out,
+    spx_uint32_t * out_len)
+{
+  spx_uint32_t i;
+  int istride_save, ostride_save;
+  spx_uint32_t bak_len = *out_len;
+  istride_save = st->in_stride;
+  ostride_save = st->out_stride;
+  st->in_stride = st->out_stride = st->nb_channels;
+  for (i = 0; i < st->nb_channels; i++) {
+    *out_len = bak_len;
+    if (in != NULL)
+      speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len);
+    else
+      speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len);
+  }
+  st->in_stride = istride_save;
+  st->out_stride = ostride_save;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate,
+    spx_uint32_t out_rate)
+{
+  return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate,
+      out_rate);
+}
+
+EXPORT void
+speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate,
+    spx_uint32_t * out_rate)
+{
+  *in_rate = st->in_rate;
+  *out_rate = st->out_rate;
+}
+
+EXPORT int
+speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num,
+    spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+  spx_uint32_t fact;
+  spx_uint32_t old_den;
+  spx_uint32_t i;
+  if (st->in_rate == in_rate && st->out_rate == out_rate
+      && st->num_rate == ratio_num && st->den_rate == ratio_den)
+    return RESAMPLER_ERR_SUCCESS;
+
+  old_den = st->den_rate;
+  st->in_rate = in_rate;
+  st->out_rate = out_rate;
+  st->num_rate = ratio_num;
+  st->den_rate = ratio_den;
+  /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
+  for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) {
+    while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) {
+      st->num_rate /= fact;
+      st->den_rate /= fact;
+    }
+  }
+
+  if (old_den > 0) {
+    for (i = 0; i < st->nb_channels; i++) {
+      st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den;
+      /* Safety net */
+      if (st->samp_frac_num[i] >= st->den_rate)
+        st->samp_frac_num[i] = st->den_rate - 1;
+    }
+  }
+
+  if (st->initialised)
+    update_filter (st);
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void
+speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num,
+    spx_uint32_t * ratio_den)
+{
+  *ratio_num = st->num_rate;
+  *ratio_den = st->den_rate;
+}
+
+EXPORT int
+speex_resampler_set_quality (SpeexResamplerState * st, int quality)
+{
+  if (quality > 10 || quality < 0)
+    return RESAMPLER_ERR_INVALID_ARG;
+  if (st->quality == quality)
+    return RESAMPLER_ERR_SUCCESS;
+  st->quality = quality;
+  if (st->initialised)
+    update_filter (st);
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void
+speex_resampler_get_quality (SpeexResamplerState * st, int *quality)
+{
+  *quality = st->quality;
+}
+
+EXPORT void
+speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride)
+{
+  st->in_stride = stride;
+}
+
+EXPORT void
+speex_resampler_get_input_stride (SpeexResamplerState * st,
+    spx_uint32_t * stride)
+{
+  *stride = st->in_stride;
+}
+
+EXPORT void
+speex_resampler_set_output_stride (SpeexResamplerState * st,
+    spx_uint32_t stride)
+{
+  st->out_stride = stride;
+}
+
+EXPORT void
+speex_resampler_get_output_stride (SpeexResamplerState * st,
+    spx_uint32_t * stride)
+{
+  *stride = st->out_stride;
+}
+
+EXPORT int
+speex_resampler_get_input_latency (SpeexResamplerState * st)
+{
+  return st->filt_len / 2;
+}
+
+EXPORT int
+speex_resampler_get_output_latency (SpeexResamplerState * st)
+{
+  return ((st->filt_len / 2) * st->den_rate +
+      (st->num_rate >> 1)) / st->num_rate;
+}
+
+EXPORT int
+speex_resampler_skip_zeros (SpeexResamplerState * st)
+{
+  spx_uint32_t i;
+  for (i = 0; i < st->nb_channels; i++)
+    st->last_sample[i] = st->filt_len / 2;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_reset_mem (SpeexResamplerState * st)
+{
+  spx_uint32_t i;
+  for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++)
+    st->mem[i] = 0;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT const char *
+speex_resampler_strerror (int err)
+{
+  switch (err) {
+    case RESAMPLER_ERR_SUCCESS:
+      return "Success.";
+    case RESAMPLER_ERR_ALLOC_FAILED:
+      return "Memory allocation failed.";
+    case RESAMPLER_ERR_BAD_STATE:
+      return "Bad resampler state.";
+    case RESAMPLER_ERR_INVALID_ARG:
+      return "Invalid argument.";
+    case RESAMPLER_ERR_PTR_OVERLAP:
+      return "Input and output buffers overlap.";
+    default:
+      return "Unknown error. Bad error code or strange version mismatch.";
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/resample_float.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1346 @@
+/* Copyright (C) 2007-2008 Jean-Marc Valin
+   Copyright (C) 2008      Thorvald Natvig
+      
+   File: resample.c
+   Arbitrary resampling code
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+   The design goals of this code are:
+      - Very fast algorithm
+      - SIMD-friendly algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Warning: This resampler is relatively new. Although I think I got rid of 
+   all the major bugs and I don't expect the API to change anymore, there
+   may be something I've missed. So use with caution.
+
+   This algorithm is based on this original resampling algorithm:
+   Smith, Julius O. Digital Audio Resampling Home Page
+   Center for Computer Research in Music and Acoustics (CCRMA), 
+   Stanford University, 2007.
+   Web published at http://www-ccrma.stanford.edu/~jos/resample/.
+
+   There is one main difference, though. This resampler uses cubic 
+   interpolation instead of linear interpolation in the above paper. This
+   makes the table much smaller and makes it possible to compute that table
+   on a per-stream basis. In turn, being able to tweak the table for each 
+   stream makes it possible to both reduce complexity on simple ratios 
+   (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
+   The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef OUTSIDE_SPEEX
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glibconfig.h>
+#include <e32def.h>
+
+#ifndef __SYMBIAN32__
+#define EXPORT EXPORT_C
+#else
+#define EXPORT G_GNUC_INTERNAL
+#endif
+
+static inline void *
+speex_alloc (int size)
+{
+  return g_malloc0 (size);
+}
+
+static inline void *
+speex_realloc (void *ptr, int size)
+{
+  return g_realloc (ptr, size);
+}
+
+static inline void
+speex_free (void *ptr)
+{
+  g_free (ptr);
+}
+
+#include "speex_resampler.h"
+#include "arch_float.h"
+#else /* OUTSIDE_SPEEX */
+
+#include "speex_resampler.h"
+#include "arch.h"
+//#include "os_support.h"
+#endif /* OUTSIDE_SPEEX */
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159263
+#endif
+
+#ifdef FIXED_POINT
+#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
+#else
+#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
+#endif
+
+#define IMAX(a,b) ((a) > (b) ? (a) : (b))
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef _USE_SSE
+#include "resample_sse.h"
+#endif
+
+/* Numer of elements to allocate on the stack */
+#ifdef VAR_ARRAYS
+#define FIXED_STACK_ALLOC 8192
+#else
+#define FIXED_STACK_ALLOC 1024
+#endif
+
+typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t,
+    const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
+
+struct SpeexResamplerState_
+{
+  spx_uint32_t in_rate;
+  spx_uint32_t out_rate;
+  spx_uint32_t num_rate;
+  spx_uint32_t den_rate;
+
+  int quality;
+  spx_uint32_t nb_channels;
+  spx_uint32_t filt_len;
+  spx_uint32_t mem_alloc_size;
+  spx_uint32_t buffer_size;
+  int int_advance;
+  int frac_advance;
+  float cutoff;
+  spx_uint32_t oversample;
+  int initialised;
+  int started;
+
+  /* These are per-channel */
+  spx_int32_t *last_sample;
+  spx_uint32_t *samp_frac_num;
+  spx_uint32_t *magic_samples;
+
+  spx_word16_t *mem;
+  spx_word16_t *sinc_table;
+  spx_uint32_t sinc_table_length;
+  resampler_basic_func resampler_ptr;
+
+  int in_stride;
+  int out_stride;
+};
+
+static double kaiser12_table[68] = {
+  0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
+  0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
+  0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
+  0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
+  0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
+  0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
+  0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
+  0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
+  0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
+  0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
+  0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
+  0.00001000, 0.00000000
+};
+
+/*
+static double kaiser12_table[36] = {
+   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
+   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
+   0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
+   0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
+   0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
+   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
+*/
+static double kaiser10_table[36] = {
+  0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
+  0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
+  0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
+  0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
+  0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
+  0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000
+};
+
+static double kaiser8_table[36] = {
+  0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
+  0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
+  0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
+  0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
+  0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
+  0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000
+};
+
+static double kaiser6_table[36] = {
+  0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
+  0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
+  0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
+  0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
+  0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
+  0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000
+};
+
+struct FuncDef
+{
+  double *table;
+  int oversample;
+};
+
+static struct FuncDef _KAISER12 = { kaiser12_table, 64 };
+
+#define KAISER12 (&_KAISER12)
+/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
+#define KAISER12 (&_KAISER12)*/
+static struct FuncDef _KAISER10 = { kaiser10_table, 32 };
+
+#define KAISER10 (&_KAISER10)
+static struct FuncDef _KAISER8 = { kaiser8_table, 32 };
+
+#define KAISER8 (&_KAISER8)
+static struct FuncDef _KAISER6 = { kaiser6_table, 32 };
+
+#define KAISER6 (&_KAISER6)
+
+struct QualityMapping
+{
+  int base_length;
+  int oversample;
+  float downsample_bandwidth;
+  float upsample_bandwidth;
+  struct FuncDef *window_func;
+};
+
+
+/* This table maps conversion quality to internal parameters. There are two
+   reasons that explain why the up-sampling bandwidth is larger than the 
+   down-sampling bandwidth:
+   1) When up-sampling, we can assume that the spectrum is already attenuated
+      close to the Nyquist rate (from an A/D or a previous resampling filter)
+   2) Any aliasing that occurs very close to the Nyquist rate will be masked
+      by the sinusoids/noise just below the Nyquist rate (guaranteed only for
+      up-sampling).
+*/
+static const struct QualityMapping quality_map[11] = {
+  {8, 4, 0.830f, 0.860f, KAISER6},      /* Q0 */
+  {16, 4, 0.850f, 0.880f, KAISER6},     /* Q1 */
+  {32, 4, 0.882f, 0.910f, KAISER6},     /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6  */
+  {48, 8, 0.895f, 0.917f, KAISER8},     /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8  */
+  {64, 8, 0.921f, 0.940f, KAISER8},     /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8  */
+  {80, 16, 0.922f, 0.940f, KAISER10},   /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */
+  {96, 16, 0.940f, 0.945f, KAISER10},   /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */
+  {128, 16, 0.950f, 0.950f, KAISER10},  /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */
+  {160, 16, 0.960f, 0.960f, KAISER10},  /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */
+  {192, 32, 0.968f, 0.968f, KAISER12},  /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */
+  {256, 32, 0.975f, 0.975f, KAISER12},  /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */
+};
+
+/*8,24,40,56,80,104,128,160,200,256,320*/
+#ifdef DOUBLE_PRECISION
+static double
+compute_func (double x, struct FuncDef *func)
+{
+  double y, frac;
+#else
+static double
+compute_func (float x, struct FuncDef *func)
+{
+  float y, frac;
+#endif
+  double interp[4];
+  int ind;
+  y = x * func->oversample;
+  ind = (int) floor (y);
+  frac = (y - ind);
+  /* CSE with handle the repeated powers */
+  interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
+  interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
+  /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
+  interp[0] =
+      -0.3333333333 * frac + 0.5 * (frac * frac) -
+      0.1666666667 * (frac * frac * frac);
+  /* Just to make sure we don't have rounding problems */
+  interp[1] = 1.f - interp[3] - interp[2] - interp[0];
+
+  /*sum = frac*accum[1] + (1-frac)*accum[2]; */
+  return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] +
+      interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3];
+}
+
+#if 0
+#include <stdio.h>
+int
+main (int argc, char **argv)
+{
+  int i;
+  for (i = 0; i < 256; i++) {
+    printf ("%f\n", compute_func (i / 256., KAISER12));
+  }
+  return 0;
+}
+#endif
+
+#ifdef FIXED_POINT
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t
+sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  float xx = x * cutoff;
+  if (fabs (x) < 1e-6f)
+    return WORD2INT (32768. * cutoff);
+  else if (fabs (x) > .5f * N)
+    return 0;
+  /*FIXME: Can it really be any slower than this? */
+  return WORD2INT (32768. * cutoff * sin (M_PI * xx) / (M_PI * xx) *
+      compute_func (fabs (2. * x / N), window_func));
+}
+#else
+/* The slow way of computing a sinc for the table. Should improve that some day */
+#ifdef DOUBLE_PRECISION
+static spx_word16_t
+sinc (double cutoff, double x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  double xx = x * cutoff;
+#else
+static spx_word16_t
+sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  float xx = x * cutoff;
+#endif
+  if (fabs (x) < 1e-6)
+    return cutoff;
+  else if (fabs (x) > .5 * N)
+    return 0;
+  /*FIXME: Can it really be any slower than this? */
+  return cutoff * sin (M_PI * xx) / (M_PI * xx) * compute_func (fabs (2. * x /
+          N), window_func);
+}
+#endif
+
+#ifdef FIXED_POINT
+static void
+cubic_coef (spx_word16_t x, spx_word16_t interp[4])
+{
+  /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+     but I know it's MMSE-optimal on a sinc */
+  spx_word16_t x2, x3;
+  x2 = MULT16_16_P15 (x, x);
+  x3 = MULT16_16_P15 (x, x2);
+  interp[0] =
+      PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15),
+          x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
+  interp[1] =
+      EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)),
+          1));
+  interp[3] =
+      PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15),
+          x) + MULT16_16 (QCONST16 (.5f, 15),
+          x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
+  /* Just to make sure we don't have rounding problems */
+  interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3];
+  if (interp[2] < 32767)
+    interp[2] += 1;
+}
+#else
+static void
+cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
+{
+  /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+     but I know it's MMSE-optimal on a sinc */
+  interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac;
+  interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac;
+  /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
+  interp[3] =
+      -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac;
+  /* Just to make sure we don't have rounding problems */
+  interp[2] = 1. - interp[0] - interp[1] - interp[3];
+}
+#endif
+
+#ifndef DOUBLE_PRECISION
+static int
+resampler_basic_direct_single (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const spx_word16_t *sinc_table = st->sinc_table;
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  spx_word32_t sum;
+  int j;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
+    const spx_word16_t *iptr = &in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
+    float accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j += 4) {
+      accum[0] += sinc[j] * iptr[j];
+      accum[1] += sinc[j + 1] * iptr[j + 1];
+      accum[2] += sinc[j + 2] * iptr[j + 2];
+      accum[3] += sinc[j + 3] * iptr[j + 3];
+    }
+    sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+    sum = inner_product_single (sinc, iptr, N);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int
+resampler_basic_direct_double (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const spx_word16_t *sinc_table = st->sinc_table;
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  double sum;
+  int j;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
+    const spx_word16_t *iptr = &in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
+    double accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j += 4) {
+      accum[0] += sinc[j] * iptr[j];
+      accum[1] += sinc[j + 1] * iptr[j + 1];
+      accum[2] += sinc[j + 2] * iptr[j + 2];
+      accum[3] += sinc[j + 3] * iptr[j + 3];
+    }
+    sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+    sum = inner_product_double (sinc, iptr, N);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifndef DOUBLE_PRECISION
+static int
+resampler_basic_interpolate_single (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  int j;
+  spx_word32_t sum;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *iptr = &in[last_sample];
+
+    const int offset = samp_frac_num * st->oversample / st->den_rate;
+#ifdef FIXED_POINT
+    const spx_word16_t frac =
+        PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+        st->den_rate);
+#else
+    const spx_word16_t frac =
+        ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#endif
+    spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
+    spx_word32_t accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j++) {
+      const spx_word16_t curr_in = iptr[j];
+      accum[0] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
+      accum[1] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
+      accum[2] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset]);
+      accum[3] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
+    }
+
+    cubic_coef (frac, interp);
+    sum =
+        MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
+        accum[1]) + MULT16_32_Q15 (interp[2],
+        accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
+#else
+    cubic_coef (frac, interp);
+    sum =
+        interpolate_product_single (iptr,
+        st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
+        interp);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int
+resampler_basic_interpolate_double (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  int j;
+  spx_word32_t sum;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *iptr = &in[last_sample];
+
+    const int offset = samp_frac_num * st->oversample / st->den_rate;
+#ifdef FIXED_POINT
+    const spx_word16_t frac =
+        PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+        st->den_rate);
+#else
+#ifdef DOUBLE_PRECISION
+    const spx_word16_t frac =
+        ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#else
+    const spx_word16_t frac =
+        ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#endif
+#endif
+    spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
+    double accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j++) {
+      const double curr_in = iptr[j];
+      accum[0] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
+      accum[1] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
+      accum[2] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset]);
+      accum[3] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
+    }
+
+    cubic_coef (frac, interp);
+    sum =
+        MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
+        accum[1]) + MULT16_32_Q15 (interp[2],
+        accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
+#else
+    cubic_coef (frac, interp);
+    sum =
+        interpolate_product_double (iptr,
+        st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
+        interp);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+static void
+update_filter (SpeexResamplerState * st)
+{
+  spx_uint32_t old_length;
+
+  old_length = st->filt_len;
+  st->oversample = quality_map[st->quality].oversample;
+  st->filt_len = quality_map[st->quality].base_length;
+
+  if (st->num_rate > st->den_rate) {
+    /* down-sampling */
+    st->cutoff =
+        quality_map[st->quality].downsample_bandwidth * st->den_rate /
+        st->num_rate;
+    /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
+    st->filt_len = st->filt_len * st->num_rate / st->den_rate;
+    /* Round down to make sure we have a multiple of 4 */
+    st->filt_len &= (~0x3);
+    if (2 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (4 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (8 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (16 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (st->oversample < 1)
+      st->oversample = 1;
+  } else {
+    /* up-sampling */
+    st->cutoff = quality_map[st->quality].upsample_bandwidth;
+  }
+
+  /* Choose the resampling type that requires the least amount of memory */
+  if (st->den_rate <= st->oversample) {
+    spx_uint32_t i;
+    if (!st->sinc_table)
+      st->sinc_table =
+          (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate *
+          sizeof (spx_word16_t));
+    else if (st->sinc_table_length < st->filt_len * st->den_rate) {
+      st->sinc_table =
+          (spx_word16_t *) speex_realloc (st->sinc_table,
+          st->filt_len * st->den_rate * sizeof (spx_word16_t));
+      st->sinc_table_length = st->filt_len * st->den_rate;
+    }
+    for (i = 0; i < st->den_rate; i++) {
+      spx_int32_t j;
+      for (j = 0; j < st->filt_len; j++) {
+        st->sinc_table[i * st->filt_len + j] =
+            sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
+#ifdef DOUBLE_PRECISION
+                ((double) i) / st->den_rate), st->filt_len,
+#else
+                ((float) i) / st->den_rate), st->filt_len,
+#endif
+            quality_map[st->quality].window_func);
+      }
+    }
+#ifdef FIXED_POINT
+    st->resampler_ptr = resampler_basic_direct_single;
+#else
+#ifdef DOUBLE_PRECISION
+    st->resampler_ptr = resampler_basic_direct_double;
+#else
+    if (st->quality > 8)
+      st->resampler_ptr = resampler_basic_direct_double;
+    else
+      st->resampler_ptr = resampler_basic_direct_single;
+#endif
+#endif
+    /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
+  } else {
+    spx_int32_t i;
+    if (!st->sinc_table)
+      st->sinc_table =
+          (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample +
+              8) * sizeof (spx_word16_t));
+    else if (st->sinc_table_length < st->filt_len * st->oversample + 8) {
+      st->sinc_table =
+          (spx_word16_t *) speex_realloc (st->sinc_table,
+          (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t));
+      st->sinc_table_length = st->filt_len * st->oversample + 8;
+    }
+    for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
+      st->sinc_table[i + 4] =
+#ifdef DOUBLE_PRECISION
+          sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
+#else
+          sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
+#endif
+          st->filt_len, quality_map[st->quality].window_func);
+#ifdef FIXED_POINT
+    st->resampler_ptr = resampler_basic_interpolate_single;
+#else
+#ifdef DOUBLE_PRECISION
+    st->resampler_ptr = resampler_basic_interpolate_double;
+#else
+    if (st->quality > 8)
+      st->resampler_ptr = resampler_basic_interpolate_double;
+    else
+      st->resampler_ptr = resampler_basic_interpolate_single;
+#endif
+#endif
+    /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
+  }
+  st->int_advance = st->num_rate / st->den_rate;
+  st->frac_advance = st->num_rate % st->den_rate;
+
+
+  /* Here's the place where we update the filter memory to take into account
+     the change in filter length. It's probably the messiest part of the code
+     due to handling of lots of corner cases. */
+  if (!st->mem) {
+    spx_uint32_t i;
+    st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+    st->mem =
+        (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size *
+        sizeof (spx_word16_t));
+    for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
+      st->mem[i] = 0;
+    /*speex_warning("init filter"); */
+  } else if (!st->started) {
+    spx_uint32_t i;
+    st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+    st->mem =
+        (spx_word16_t *) speex_realloc (st->mem,
+        st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
+    for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
+      st->mem[i] = 0;
+    /*speex_warning("reinit filter"); */
+  } else if (st->filt_len > old_length) {
+    spx_int32_t i;
+    /* Increase the filter length */
+    /*speex_warning("increase filter size"); */
+    int old_alloc_size = st->mem_alloc_size;
+    if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) {
+      st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+      st->mem =
+          (spx_word16_t *) speex_realloc (st->mem,
+          st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
+    }
+    for (i = st->nb_channels - 1; i >= 0; i--) {
+      spx_int32_t j;
+      spx_uint32_t olen = old_length;
+      /*if (st->magic_samples[i]) */
+      {
+        /* Try and remove the magic samples as if nothing had happened */
+
+        /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
+        olen = old_length + 2 * st->magic_samples[i];
+        for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--)
+          st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] =
+              st->mem[i * old_alloc_size + j];
+        for (j = 0; j < st->magic_samples[i]; j++)
+          st->mem[i * st->mem_alloc_size + j] = 0;
+        st->magic_samples[i] = 0;
+      }
+      if (st->filt_len > olen) {
+        /* If the new filter length is still bigger than the "augmented" length */
+        /* Copy data going backward */
+        for (j = 0; j < olen - 1; j++)
+          st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] =
+              st->mem[i * st->mem_alloc_size + (olen - 2 - j)];
+        /* Then put zeros for lack of anything better */
+        for (; j < st->filt_len - 1; j++)
+          st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0;
+        /* Adjust last_sample */
+        st->last_sample[i] += (st->filt_len - olen) / 2;
+      } else {
+        /* Put back some of the magic! */
+        st->magic_samples[i] = (olen - st->filt_len) / 2;
+        for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++)
+          st->mem[i * st->mem_alloc_size + j] =
+              st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
+      }
+    }
+  } else if (st->filt_len < old_length) {
+    spx_uint32_t i;
+    /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
+       samples so they can be used directly as input the next time(s) */
+    for (i = 0; i < st->nb_channels; i++) {
+      spx_uint32_t j;
+      spx_uint32_t old_magic = st->magic_samples[i];
+      st->magic_samples[i] = (old_length - st->filt_len) / 2;
+      /* We must copy some of the memory that's no longer used */
+      /* Copy data going backward */
+      for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++)
+        st->mem[i * st->mem_alloc_size + j] =
+            st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
+      st->magic_samples[i] += old_magic;
+    }
+  }
+
+}
+
+EXPORT SpeexResamplerState *
+speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
+    spx_uint32_t out_rate, int quality, int *err)
+{
+  return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
+      out_rate, quality, err);
+}
+
+EXPORT SpeexResamplerState *
+speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
+    spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
+    int quality, int *err)
+{
+  spx_uint32_t i;
+  SpeexResamplerState *st;
+  if (quality > 10 || quality < 0) {
+    if (err)
+      *err = RESAMPLER_ERR_INVALID_ARG;
+    return NULL;
+  }
+  st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
+  st->initialised = 0;
+  st->started = 0;
+  st->in_rate = 0;
+  st->out_rate = 0;
+  st->num_rate = 0;
+  st->den_rate = 0;
+  st->quality = -1;
+  st->sinc_table_length = 0;
+  st->mem_alloc_size = 0;
+  st->filt_len = 0;
+  st->mem = 0;
+  st->resampler_ptr = 0;
+
+  st->cutoff = 1.f;
+  st->nb_channels = nb_channels;
+  st->in_stride = 1;
+  st->out_stride = 1;
+
+#ifdef FIXED_POINT
+  st->buffer_size = 160;
+#else
+  st->buffer_size = 160;
+#endif
+
+  /* Per channel data */
+  st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int));
+  st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
+  st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
+  for (i = 0; i < nb_channels; i++) {
+    st->last_sample[i] = 0;
+    st->magic_samples[i] = 0;
+    st->samp_frac_num[i] = 0;
+  }
+
+  speex_resampler_set_quality (st, quality);
+  speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
+
+
+  update_filter (st);
+
+  st->initialised = 1;
+  if (err)
+    *err = RESAMPLER_ERR_SUCCESS;
+
+  return st;
+}
+
+EXPORT void
+speex_resampler_destroy (SpeexResamplerState * st)
+{
+  speex_free (st->mem);
+  speex_free (st->sinc_table);
+  speex_free (st->last_sample);
+  speex_free (st->magic_samples);
+  speex_free (st->samp_frac_num);
+  speex_free (st);
+}
+
+static int
+speex_resampler_process_native (SpeexResamplerState * st,
+    spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out,
+    spx_uint32_t * out_len)
+{
+  int j = 0;
+  const int N = st->filt_len;
+  int out_sample = 0;
+  spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+  spx_uint32_t ilen;
+
+  st->started = 1;
+
+  /* Call the right resampler through the function ptr */
+  out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len);
+
+  if (st->last_sample[channel_index] < (spx_int32_t) * in_len)
+    *in_len = st->last_sample[channel_index];
+  *out_len = out_sample;
+  st->last_sample[channel_index] -= *in_len;
+
+  ilen = *in_len;
+
+  for (j = 0; j < N - 1; ++j)
+    mem[j] = mem[j + ilen];
+
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+static int
+speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index,
+    spx_word16_t ** out, spx_uint32_t out_len)
+{
+  spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
+  spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+  const int N = st->filt_len;
+
+  speex_resampler_process_native (st, channel_index, &tmp_in_len, *out,
+      &out_len);
+
+  st->magic_samples[channel_index] -= tmp_in_len;
+
+  /* If we couldn't process all "magic" input samples, save the rest for next time */
+  if (st->magic_samples[channel_index]) {
+    spx_uint32_t i;
+    for (i = 0; i < st->magic_samples[channel_index]; i++)
+      mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len];
+  }
+  *out += out_len * st->out_stride;
+  return out_len;
+}
+
+#ifdef FIXED_POINT
+EXPORT int
+speex_resampler_process_int (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+    spx_int16_t * out, spx_uint32_t * out_len)
+#else
+#ifdef DOUBLE_PRECISION
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
+    double *out, spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+    float *out, spx_uint32_t * out_len)
+#endif
+#endif
+{
+  int j;
+  spx_uint32_t ilen = *in_len;
+  spx_uint32_t olen = *out_len;
+  spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+  const int filt_offs = st->filt_len - 1;
+  const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
+  const int istride = st->in_stride;
+
+  if (st->magic_samples[channel_index])
+    olen -= speex_resampler_magic (st, channel_index, &out, olen);
+  if (!st->magic_samples[channel_index]) {
+    while (ilen && olen) {
+      spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+      spx_uint32_t ochunk = olen;
+
+      if (in) {
+        for (j = 0; j < ichunk; ++j)
+          x[j + filt_offs] = in[j * istride];
+      } else {
+        for (j = 0; j < ichunk; ++j)
+          x[j + filt_offs] = 0;
+      }
+      speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk);
+      ilen -= ichunk;
+      olen -= ochunk;
+      out += ochunk * st->out_stride;
+      if (in)
+        in += ichunk * istride;
+    }
+  }
+  *in_len -= ilen;
+  *out_len -= olen;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef FIXED_POINT
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+    float *out, spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_int (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+    spx_int16_t * out, spx_uint32_t * out_len)
+#endif
+{
+  int j;
+  const int istride_save = st->in_stride;
+  const int ostride_save = st->out_stride;
+  spx_uint32_t ilen = *in_len;
+  spx_uint32_t olen = *out_len;
+  spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+  const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
+#ifdef VAR_ARRAYS
+  const unsigned int ylen =
+      (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
+  VARDECL (spx_word16_t * ystack);
+  ALLOC (ystack, ylen, spx_word16_t);
+#else
+  const unsigned int ylen = FIXED_STACK_ALLOC;
+  spx_word16_t ystack[FIXED_STACK_ALLOC];
+#endif
+
+  st->out_stride = 1;
+
+  while (ilen && olen) {
+    spx_word16_t *y = ystack;
+    spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+    spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
+    spx_uint32_t omagic = 0;
+
+    if (st->magic_samples[channel_index]) {
+      omagic = speex_resampler_magic (st, channel_index, &y, ochunk);
+      ochunk -= omagic;
+      olen -= omagic;
+    }
+    if (!st->magic_samples[channel_index]) {
+      if (in) {
+        for (j = 0; j < ichunk; ++j)
+#ifdef FIXED_POINT
+          x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]);
+#else
+          x[j + st->filt_len - 1] = in[j * istride_save];
+#endif
+      } else {
+        for (j = 0; j < ichunk; ++j)
+          x[j + st->filt_len - 1] = 0;
+      }
+
+      speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk);
+    } else {
+      ichunk = 0;
+      ochunk = 0;
+    }
+
+    for (j = 0; j < ochunk + omagic; ++j)
+#ifdef FIXED_POINT
+      out[j * ostride_save] = ystack[j];
+#else
+      out[j * ostride_save] = WORD2INT (ystack[j]);
+#endif
+
+    ilen -= ichunk;
+    olen -= ochunk;
+    out += (ochunk + omagic) * ostride_save;
+    if (in)
+      in += ichunk * istride_save;
+  }
+  st->out_stride = ostride_save;
+  *in_len -= ilen;
+  *out_len -= olen;
+
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef DOUBLE_PRECISION
+EXPORT int
+speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+    const double *in, spx_uint32_t * in_len, double *out,
+    spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+    const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
+#endif
+{
+  spx_uint32_t i;
+  int istride_save, ostride_save;
+  spx_uint32_t bak_len = *out_len;
+  istride_save = st->in_stride;
+  ostride_save = st->out_stride;
+  st->in_stride = st->out_stride = st->nb_channels;
+  for (i = 0; i < st->nb_channels; i++) {
+    *out_len = bak_len;
+    if (in != NULL)
+      speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len);
+    else
+      speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len);
+  }
+  st->in_stride = istride_save;
+  st->out_stride = ostride_save;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_process_interleaved_int (SpeexResamplerState * st,
+    const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out,
+    spx_uint32_t * out_len)
+{
+  spx_uint32_t i;
+  int istride_save, ostride_save;
+  spx_uint32_t bak_len = *out_len;
+  istride_save = st->in_stride;
+  ostride_save = st->out_stride;
+  st->in_stride = st->out_stride = st->nb_channels;
+  for (i = 0; i < st->nb_channels; i++) {
+    *out_len = bak_len;
+    if (in != NULL)
+      speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len);
+    else
+      speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len);
+  }
+  st->in_stride = istride_save;
+  st->out_stride = ostride_save;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate,
+    spx_uint32_t out_rate)
+{
+  return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate,
+      out_rate);
+}
+
+EXPORT void
+speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate,
+    spx_uint32_t * out_rate)
+{
+  *in_rate = st->in_rate;
+  *out_rate = st->out_rate;
+}
+
+EXPORT int
+speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num,
+    spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+  spx_uint32_t fact;
+  spx_uint32_t old_den;
+  spx_uint32_t i;
+  if (st->in_rate == in_rate && st->out_rate == out_rate
+      && st->num_rate == ratio_num && st->den_rate == ratio_den)
+    return RESAMPLER_ERR_SUCCESS;
+
+  old_den = st->den_rate;
+  st->in_rate = in_rate;
+  st->out_rate = out_rate;
+  st->num_rate = ratio_num;
+  st->den_rate = ratio_den;
+  /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
+  for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) {
+    while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) {
+      st->num_rate /= fact;
+      st->den_rate /= fact;
+    }
+  }
+
+  if (old_den > 0) {
+    for (i = 0; i < st->nb_channels; i++) {
+      st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den;
+      /* Safety net */
+      if (st->samp_frac_num[i] >= st->den_rate)
+        st->samp_frac_num[i] = st->den_rate - 1;
+    }
+  }
+
+  if (st->initialised)
+    update_filter (st);
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void
+speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num,
+    spx_uint32_t * ratio_den)
+{
+  *ratio_num = st->num_rate;
+  *ratio_den = st->den_rate;
+}
+
+EXPORT int
+speex_resampler_set_quality (SpeexResamplerState * st, int quality)
+{
+  if (quality > 10 || quality < 0)
+    return RESAMPLER_ERR_INVALID_ARG;
+  if (st->quality == quality)
+    return RESAMPLER_ERR_SUCCESS;
+  st->quality = quality;
+  if (st->initialised)
+    update_filter (st);
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void
+speex_resampler_get_quality (SpeexResamplerState * st, int *quality)
+{
+  *quality = st->quality;
+}
+
+EXPORT void
+speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride)
+{
+  st->in_stride = stride;
+}
+
+EXPORT void
+speex_resampler_get_input_stride (SpeexResamplerState * st,
+    spx_uint32_t * stride)
+{
+  *stride = st->in_stride;
+}
+
+EXPORT void
+speex_resampler_set_output_stride (SpeexResamplerState * st,
+    spx_uint32_t stride)
+{
+  st->out_stride = stride;
+}
+
+EXPORT void
+speex_resampler_get_output_stride (SpeexResamplerState * st,
+    spx_uint32_t * stride)
+{
+  *stride = st->out_stride;
+}
+
+EXPORT int
+speex_resampler_get_input_latency (SpeexResamplerState * st)
+{
+  return st->filt_len / 2;
+}
+
+EXPORT int
+speex_resampler_get_output_latency (SpeexResamplerState * st)
+{
+  return ((st->filt_len / 2) * st->den_rate +
+      (st->num_rate >> 1)) / st->num_rate;
+}
+
+EXPORT int
+speex_resampler_skip_zeros (SpeexResamplerState * st)
+{
+  spx_uint32_t i;
+  for (i = 0; i < st->nb_channels; i++)
+    st->last_sample[i] = st->filt_len / 2;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_reset_mem (SpeexResamplerState * st)
+{
+  spx_uint32_t i;
+  for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++)
+    st->mem[i] = 0;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT const char *
+speex_resampler_strerror (int err)
+{
+  switch (err) {
+    case RESAMPLER_ERR_SUCCESS:
+      return "Success.";
+    case RESAMPLER_ERR_ALLOC_FAILED:
+      return "Memory allocation failed.";
+    case RESAMPLER_ERR_BAD_STATE:
+      return "Bad resampler state.";
+    case RESAMPLER_ERR_INVALID_ARG:
+      return "Invalid argument.";
+    case RESAMPLER_ERR_PTR_OVERLAP:
+      return "Input and output buffers overlap.";
+    default:
+      return "Unknown error. Bad error code or strange version mismatch.";
+  }
+}
--- a/gst_plugins_base/gst/audioresample/resample_functable.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
- *
- * 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 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#ifndef __SYMBIAN32__
-#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
-
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#ifndef __SYMBIAN32__
-#include <liboil/liboil.h>
-#endif
-
-#include "resample.h"
-#include "buffer.h"
-#include "debug.h"
-
-static void
-func_sinc (double *fx, double *dfx, double x, void *closure)
-{
-  //double scale = *(double *)closure;
-  double scale = M_PI;
-
-  if (x == 0) {
-    *fx = 1;
-    *dfx = 0;
-    return;
-  }
-
-  x *= scale;
-  *fx = sin (x) / x;
-  *dfx = scale * (cos (x) - sin (x) / x) / x;
-}
-
-static void
-func_hanning (double *fx, double *dfx, double x, void *closure)
-{
-  double width = *(double *) closure;
-
-  if (x < width && x > -width) {
-    x /= width;
-    *fx = (1 - x * x) * (1 - x * x);
-    *dfx = -2 * 2 * x / width * (1 - x * x);
-  } else {
-    *fx = 0;
-    *dfx = 0;
-  }
-}
-
-#if 0
-static double
-resample_sinc_window (double x, double halfwidth, double scale)
-{
-  double y;
-
-  if (x == 0)
-    return 1.0;
-  if (x < -halfwidth || x > halfwidth)
-    return 0.0;
-
-  y = sin (x * M_PI * scale) / (x * M_PI * scale) * scale;
-
-  x /= halfwidth;
-  y *= (1 - x * x) * (1 - x * x);
-
-  return y;
-}
-#endif
-
-#if 0
-static void
-functable_test (Functable * ft, double halfwidth)
-{
-  int i;
-  double x;
-
-  for (i = 0; i < 100; i++) {
-    x = i * 0.1;
-    printf ("%d %g %g\n", i, resample_sinc_window (x, halfwidth, 1.0),
-        functable_evaluate (ft, x));
-  }
-  exit (0);
-
-}
-#endif
-
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-void
-resample_scale_functable (ResampleState * r)
-{
-  if (r->need_reinit) {
-    double hanning_width;
-
-    RESAMPLE_DEBUG ("sample size %d", r->sample_size);
-
-    if (r->buffer)
-      free (r->buffer);
-    r->buffer_len = r->sample_size * r->filter_length;
-    r->buffer = malloc (r->buffer_len);
-    memset (r->buffer, 0, r->buffer_len);
-
-    r->i_inc = r->o_rate / r->i_rate;
-    r->o_inc = r->i_rate / r->o_rate;
-    RESAMPLE_DEBUG ("i_inc %g o_inc %g", r->i_inc, r->o_inc);
-
-    r->i_start = -r->i_inc * r->filter_length;
-
-    if (r->ft) {
-      functable_free (r->ft);
-    }
-    r->ft = functable_new ();
-    functable_set_length (r->ft, r->filter_length * 16);
-    functable_set_offset (r->ft, -r->filter_length / 2);
-    functable_set_multiplier (r->ft, 1 / 16.0);
-
-    hanning_width = r->filter_length / 2;
-    functable_calculate (r->ft, func_sinc, NULL);
-    functable_calculate_multiply (r->ft, func_hanning, &hanning_width);
-
-    //functable_test(r->ft, 0.5 * r->filter_length);
-#if 0
-    if (r->i_inc < 1.0) {
-      r->sinc_scale = r->i_inc;
-      if (r->sinc_scale == 0.5) {
-        /* strange things happen at integer multiples */
-        r->sinc_scale = 1.0;
-      }
-    } else {
-      r->sinc_scale = 1.0;
-    }
-#else
-    r->sinc_scale = 1.0;
-#endif
-
-    r->need_reinit = 0;
-  }
-
-  while (r->o_size > 0) {
-    double midpoint;
-    int i;
-    int j;
-
-    RESAMPLE_DEBUG ("i_start %g", r->i_start);
-    midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
-    if (midpoint > 0.5 * r->i_inc) {
-      RESAMPLE_ERROR ("inconsistent state");
-    }
-    while (midpoint < -0.5 * r->i_inc) {
-      AudioresampleBuffer *buffer;
-
-      buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
-      if (buffer == NULL) {
-        RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
-        return;
-      }
-
-      r->i_start += r->i_inc;
-      RESAMPLE_DEBUG ("pulling (i_start = %g)", r->i_start);
-
-      midpoint += r->i_inc;
-      memmove (r->buffer, r->buffer + r->sample_size,
-          r->buffer_len - r->sample_size);
-
-      memcpy (r->buffer + r->buffer_len - r->sample_size, buffer->data,
-          r->sample_size);
-      audioresample_buffer_unref (buffer);
-    }
-
-    switch (r->format) {
-      case RESAMPLE_FORMAT_S16:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(int16_t *) (r->buffer + i * sizeof (int16_t) +
-                j * r->sample_size);
-            acc += functable_evaluate (r->ft, offset) * x;
-            //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
-          }
-          if (acc < -32768.0)
-            acc = -32768.0;
-          if (acc > 32767.0)
-            acc = 32767.0;
-
-          *(int16_t *) (r->o_buf + i * sizeof (int16_t)) = rint (acc);
-        }
-        break;
-      case RESAMPLE_FORMAT_S32:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(int32_t *) (r->buffer + i * sizeof (int32_t) +
-                j * r->sample_size);
-            acc += functable_evaluate (r->ft, offset) * x;
-            //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
-          }
-          if (acc < -2147483648.0)
-            acc = -2147483648.0;
-          if (acc > 2147483647.0)
-            acc = 2147483647.0;
-
-          *(int32_t *) (r->o_buf + i * sizeof (int32_t)) = rint (acc);
-        }
-        break;
-      case RESAMPLE_FORMAT_F32:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(float *) (r->buffer + i * sizeof (float) +
-                j * r->sample_size);
-            acc += functable_evaluate (r->ft, offset) * x;
-            //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
-          }
-
-          *(float *) (r->o_buf + i * sizeof (float)) = acc;
-        }
-        break;
-      case RESAMPLE_FORMAT_F64:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(double *) (r->buffer + i * sizeof (double) +
-                j * r->sample_size);
-            acc += functable_evaluate (r->ft, offset) * x;
-            //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
-          }
-
-          *(double *) (r->o_buf + i * sizeof (double)) = acc;
-        }
-        break;
-    }
-
-    r->i_start -= 1.0;
-    r->o_buf += r->sample_size;
-    r->o_size -= r->sample_size;
-  }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/resample_int.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1346 @@
+/* Copyright (C) 2007-2008 Jean-Marc Valin
+   Copyright (C) 2008      Thorvald Natvig
+      
+   File: resample.c
+   Arbitrary resampling code
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+   The design goals of this code are:
+      - Very fast algorithm
+      - SIMD-friendly algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Warning: This resampler is relatively new. Although I think I got rid of 
+   all the major bugs and I don't expect the API to change anymore, there
+   may be something I've missed. So use with caution.
+
+   This algorithm is based on this original resampling algorithm:
+   Smith, Julius O. Digital Audio Resampling Home Page
+   Center for Computer Research in Music and Acoustics (CCRMA), 
+   Stanford University, 2007.
+   Web published at http://www-ccrma.stanford.edu/~jos/resample/.
+
+   There is one main difference, though. This resampler uses cubic 
+   interpolation instead of linear interpolation in the above paper. This
+   makes the table much smaller and makes it possible to compute that table
+   on a per-stream basis. In turn, being able to tweak the table for each 
+   stream makes it possible to both reduce complexity on simple ratios 
+   (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
+   The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef OUTSIDE_SPEEX
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glibconfig.h>
+#include <e32def.h>
+
+#ifndef __SYMBIAN32__
+#define EXPORT EXPORT_C
+#else
+#define EXPORT G_GNUC_INTERNAL
+#endif
+
+static inline void *
+speex_alloc (int size)
+{
+  return g_malloc0 (size);
+}
+
+static inline void *
+speex_realloc (void *ptr, int size)
+{
+  return g_realloc (ptr, size);
+}
+
+static inline void
+speex_free (void *ptr)
+{
+  g_free (ptr);
+}
+
+#include "speex_resampler.h"
+#include "arch_int.h"
+#else /* OUTSIDE_SPEEX */
+
+#include "speex_resampler.h"
+#include "arch.h"
+//#include "os_support.h"
+#endif /* OUTSIDE_SPEEX */
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159263
+#endif
+
+#ifdef FIXED_POINT
+#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
+#else
+#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
+#endif
+
+#define IMAX(a,b) ((a) > (b) ? (a) : (b))
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef _USE_SSE
+#include "resample_sse.h"
+#endif
+
+/* Numer of elements to allocate on the stack */
+#ifdef VAR_ARRAYS
+#define FIXED_STACK_ALLOC 8192
+#else
+#define FIXED_STACK_ALLOC 1024
+#endif
+
+typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t,
+    const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
+
+struct SpeexResamplerState_
+{
+  spx_uint32_t in_rate;
+  spx_uint32_t out_rate;
+  spx_uint32_t num_rate;
+  spx_uint32_t den_rate;
+
+  int quality;
+  spx_uint32_t nb_channels;
+  spx_uint32_t filt_len;
+  spx_uint32_t mem_alloc_size;
+  spx_uint32_t buffer_size;
+  int int_advance;
+  int frac_advance;
+  float cutoff;
+  spx_uint32_t oversample;
+  int initialised;
+  int started;
+
+  /* These are per-channel */
+  spx_int32_t *last_sample;
+  spx_uint32_t *samp_frac_num;
+  spx_uint32_t *magic_samples;
+
+  spx_word16_t *mem;
+  spx_word16_t *sinc_table;
+  spx_uint32_t sinc_table_length;
+  resampler_basic_func resampler_ptr;
+
+  int in_stride;
+  int out_stride;
+};
+
+static double kaiser12_table[68] = {
+  0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
+  0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
+  0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
+  0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
+  0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
+  0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
+  0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
+  0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
+  0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
+  0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
+  0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
+  0.00001000, 0.00000000
+};
+
+/*
+static double kaiser12_table[36] = {
+   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
+   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
+   0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
+   0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
+   0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
+   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
+*/
+static double kaiser10_table[36] = {
+  0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
+  0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
+  0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
+  0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
+  0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
+  0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000
+};
+
+static double kaiser8_table[36] = {
+  0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
+  0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
+  0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
+  0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
+  0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
+  0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000
+};
+
+static double kaiser6_table[36] = {
+  0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
+  0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
+  0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
+  0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
+  0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
+  0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000
+};
+
+struct FuncDef
+{
+  double *table;
+  int oversample;
+};
+
+static struct FuncDef _KAISER12 = { kaiser12_table, 64 };
+
+#define KAISER12 (&_KAISER12)
+/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
+#define KAISER12 (&_KAISER12)*/
+static struct FuncDef _KAISER10 = { kaiser10_table, 32 };
+
+#define KAISER10 (&_KAISER10)
+static struct FuncDef _KAISER8 = { kaiser8_table, 32 };
+
+#define KAISER8 (&_KAISER8)
+static struct FuncDef _KAISER6 = { kaiser6_table, 32 };
+
+#define KAISER6 (&_KAISER6)
+
+struct QualityMapping
+{
+  int base_length;
+  int oversample;
+  float downsample_bandwidth;
+  float upsample_bandwidth;
+  struct FuncDef *window_func;
+};
+
+
+/* This table maps conversion quality to internal parameters. There are two
+   reasons that explain why the up-sampling bandwidth is larger than the 
+   down-sampling bandwidth:
+   1) When up-sampling, we can assume that the spectrum is already attenuated
+      close to the Nyquist rate (from an A/D or a previous resampling filter)
+   2) Any aliasing that occurs very close to the Nyquist rate will be masked
+      by the sinusoids/noise just below the Nyquist rate (guaranteed only for
+      up-sampling).
+*/
+static const struct QualityMapping quality_map[11] = {
+  {8, 4, 0.830f, 0.860f, KAISER6},      /* Q0 */
+  {16, 4, 0.850f, 0.880f, KAISER6},     /* Q1 */
+  {32, 4, 0.882f, 0.910f, KAISER6},     /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6  */
+  {48, 8, 0.895f, 0.917f, KAISER8},     /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8  */
+  {64, 8, 0.921f, 0.940f, KAISER8},     /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8  */
+  {80, 16, 0.922f, 0.940f, KAISER10},   /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */
+  {96, 16, 0.940f, 0.945f, KAISER10},   /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */
+  {128, 16, 0.950f, 0.950f, KAISER10},  /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */
+  {160, 16, 0.960f, 0.960f, KAISER10},  /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */
+  {192, 32, 0.968f, 0.968f, KAISER12},  /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */
+  {256, 32, 0.975f, 0.975f, KAISER12},  /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */
+};
+
+/*8,24,40,56,80,104,128,160,200,256,320*/
+#ifdef DOUBLE_PRECISION
+static double
+compute_func (double x, struct FuncDef *func)
+{
+  double y, frac;
+#else
+static double
+compute_func (float x, struct FuncDef *func)
+{
+  float y, frac;
+#endif
+  double interp[4];
+  int ind;
+  y = x * func->oversample;
+  ind = (int) floor (y);
+  frac = (y - ind);
+  /* CSE with handle the repeated powers */
+  interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
+  interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
+  /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
+  interp[0] =
+      -0.3333333333 * frac + 0.5 * (frac * frac) -
+      0.1666666667 * (frac * frac * frac);
+  /* Just to make sure we don't have rounding problems */
+  interp[1] = 1.f - interp[3] - interp[2] - interp[0];
+
+  /*sum = frac*accum[1] + (1-frac)*accum[2]; */
+  return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] +
+      interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3];
+}
+
+#if 0
+#include <stdio.h>
+int
+main (int argc, char **argv)
+{
+  int i;
+  for (i = 0; i < 256; i++) {
+    printf ("%f\n", compute_func (i / 256., KAISER12));
+  }
+  return 0;
+}
+#endif
+
+#ifdef FIXED_POINT
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t
+sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  float xx = x * cutoff;
+  if (fabs (x) < 1e-6f)
+    return WORD2INT (32768. * cutoff);
+  else if (fabs (x) > .5f * N)
+    return 0;
+  /*FIXME: Can it really be any slower than this? */
+  return WORD2INT (32768. * cutoff * sin (M_PI * xx) / (M_PI * xx) *
+      compute_func (fabs (2. * x / N), window_func));
+}
+#else
+/* The slow way of computing a sinc for the table. Should improve that some day */
+#ifdef DOUBLE_PRECISION
+static spx_word16_t
+sinc (double cutoff, double x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  double xx = x * cutoff;
+#else
+static spx_word16_t
+sinc (float cutoff, float x, int N, struct FuncDef *window_func)
+{
+  /*fprintf (stderr, "%f ", x); */
+  float xx = x * cutoff;
+#endif
+  if (fabs (x) < 1e-6)
+    return cutoff;
+  else if (fabs (x) > .5 * N)
+    return 0;
+  /*FIXME: Can it really be any slower than this? */
+  return cutoff * sin (M_PI * xx) / (M_PI * xx) * compute_func (fabs (2. * x /
+          N), window_func);
+}
+#endif
+
+#ifdef FIXED_POINT
+static void
+cubic_coef (spx_word16_t x, spx_word16_t interp[4])
+{
+  /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+     but I know it's MMSE-optimal on a sinc */
+  spx_word16_t x2, x3;
+  x2 = MULT16_16_P15 (x, x);
+  x3 = MULT16_16_P15 (x, x2);
+  interp[0] =
+      PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15),
+          x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
+  interp[1] =
+      EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)),
+          1));
+  interp[3] =
+      PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15),
+          x) + MULT16_16 (QCONST16 (.5f, 15),
+          x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15);
+  /* Just to make sure we don't have rounding problems */
+  interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3];
+  if (interp[2] < 32767)
+    interp[2] += 1;
+}
+#else
+static void
+cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
+{
+  /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+     but I know it's MMSE-optimal on a sinc */
+  interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac;
+  interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac;
+  /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */
+  interp[3] =
+      -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac;
+  /* Just to make sure we don't have rounding problems */
+  interp[2] = 1. - interp[0] - interp[1] - interp[3];
+}
+#endif
+
+#ifndef DOUBLE_PRECISION
+static int
+resampler_basic_direct_single (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const spx_word16_t *sinc_table = st->sinc_table;
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  spx_word32_t sum;
+  int j;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
+    const spx_word16_t *iptr = &in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
+    float accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j += 4) {
+      accum[0] += sinc[j] * iptr[j];
+      accum[1] += sinc[j + 1] * iptr[j + 1];
+      accum[2] += sinc[j + 2] * iptr[j + 2];
+      accum[3] += sinc[j + 3] * iptr[j + 3];
+    }
+    sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+    sum = inner_product_single (sinc, iptr, N);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int
+resampler_basic_direct_double (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const spx_word16_t *sinc_table = st->sinc_table;
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  double sum;
+  int j;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *sinc = &sinc_table[samp_frac_num * N];
+    const spx_word16_t *iptr = &in[last_sample];
+
+#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
+    double accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j += 4) {
+      accum[0] += sinc[j] * iptr[j];
+      accum[1] += sinc[j + 1] * iptr[j + 1];
+      accum[2] += sinc[j + 2] * iptr[j + 2];
+      accum[3] += sinc[j + 3] * iptr[j + 3];
+    }
+    sum = accum[0] + accum[1] + accum[2] + accum[3];
+#else
+    sum = inner_product_double (sinc, iptr, N);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifndef DOUBLE_PRECISION
+static int
+resampler_basic_interpolate_single (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  int j;
+  spx_word32_t sum;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *iptr = &in[last_sample];
+
+    const int offset = samp_frac_num * st->oversample / st->den_rate;
+#ifdef FIXED_POINT
+    const spx_word16_t frac =
+        PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+        st->den_rate);
+#else
+    const spx_word16_t frac =
+        ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#endif
+    spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
+    spx_word32_t accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j++) {
+      const spx_word16_t curr_in = iptr[j];
+      accum[0] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
+      accum[1] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
+      accum[2] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset]);
+      accum[3] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
+    }
+
+    cubic_coef (frac, interp);
+    sum =
+        MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
+        accum[1]) + MULT16_32_Q15 (interp[2],
+        accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
+#else
+    cubic_coef (frac, interp);
+    sum =
+        interpolate_product_single (iptr,
+        st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
+        interp);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int
+resampler_basic_interpolate_double (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
+    spx_word16_t * out, spx_uint32_t * out_len)
+{
+  const int N = st->filt_len;
+  int out_sample = 0;
+  int last_sample = st->last_sample[channel_index];
+  spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+  const int out_stride = st->out_stride;
+  const int int_advance = st->int_advance;
+  const int frac_advance = st->frac_advance;
+  const spx_uint32_t den_rate = st->den_rate;
+  int j;
+  spx_word32_t sum;
+
+  while (!(last_sample >= (spx_int32_t) * in_len
+          || out_sample >= (spx_int32_t) * out_len)) {
+    const spx_word16_t *iptr = &in[last_sample];
+
+    const int offset = samp_frac_num * st->oversample / st->den_rate;
+#ifdef FIXED_POINT
+    const spx_word16_t frac =
+        PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
+        st->den_rate);
+#else
+#ifdef DOUBLE_PRECISION
+    const spx_word16_t frac =
+        ((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#else
+    const spx_word16_t frac =
+        ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
+        st->den_rate;
+#endif
+#endif
+    spx_word16_t interp[4];
+
+
+#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
+    double accum[4] = { 0, 0, 0, 0 };
+
+    for (j = 0; j < N; j++) {
+      const double curr_in = iptr[j];
+      accum[0] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]);
+      accum[1] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]);
+      accum[2] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset]);
+      accum[3] +=
+          MULT16_16 (curr_in,
+          st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]);
+    }
+
+    cubic_coef (frac, interp);
+    sum =
+        MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1],
+        accum[1]) + MULT16_32_Q15 (interp[2],
+        accum[2]) + MULT16_32_Q15 (interp[3], accum[3]);
+#else
+    cubic_coef (frac, interp);
+    sum =
+        interpolate_product_double (iptr,
+        st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample,
+        interp);
+#endif
+
+    out[out_stride * out_sample++] = PSHR32 (sum, 15);
+    last_sample += int_advance;
+    samp_frac_num += frac_advance;
+    if (samp_frac_num >= den_rate) {
+      samp_frac_num -= den_rate;
+      last_sample++;
+    }
+  }
+
+  st->last_sample[channel_index] = last_sample;
+  st->samp_frac_num[channel_index] = samp_frac_num;
+  return out_sample;
+}
+#endif
+
+static void
+update_filter (SpeexResamplerState * st)
+{
+  spx_uint32_t old_length;
+
+  old_length = st->filt_len;
+  st->oversample = quality_map[st->quality].oversample;
+  st->filt_len = quality_map[st->quality].base_length;
+
+  if (st->num_rate > st->den_rate) {
+    /* down-sampling */
+    st->cutoff =
+        quality_map[st->quality].downsample_bandwidth * st->den_rate /
+        st->num_rate;
+    /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
+    st->filt_len = st->filt_len * st->num_rate / st->den_rate;
+    /* Round down to make sure we have a multiple of 4 */
+    st->filt_len &= (~0x3);
+    if (2 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (4 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (8 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (16 * st->den_rate < st->num_rate)
+      st->oversample >>= 1;
+    if (st->oversample < 1)
+      st->oversample = 1;
+  } else {
+    /* up-sampling */
+    st->cutoff = quality_map[st->quality].upsample_bandwidth;
+  }
+
+  /* Choose the resampling type that requires the least amount of memory */
+  if (st->den_rate <= st->oversample) {
+    spx_uint32_t i;
+    if (!st->sinc_table)
+      st->sinc_table =
+          (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate *
+          sizeof (spx_word16_t));
+    else if (st->sinc_table_length < st->filt_len * st->den_rate) {
+      st->sinc_table =
+          (spx_word16_t *) speex_realloc (st->sinc_table,
+          st->filt_len * st->den_rate * sizeof (spx_word16_t));
+      st->sinc_table_length = st->filt_len * st->den_rate;
+    }
+    for (i = 0; i < st->den_rate; i++) {
+      spx_int32_t j;
+      for (j = 0; j < st->filt_len; j++) {
+        st->sinc_table[i * st->filt_len + j] =
+            sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
+#ifdef DOUBLE_PRECISION
+                ((double) i) / st->den_rate), st->filt_len,
+#else
+                ((float) i) / st->den_rate), st->filt_len,
+#endif
+            quality_map[st->quality].window_func);
+      }
+    }
+#ifdef FIXED_POINT
+    st->resampler_ptr = resampler_basic_direct_single;
+#else
+#ifdef DOUBLE_PRECISION
+    st->resampler_ptr = resampler_basic_direct_double;
+#else
+    if (st->quality > 8)
+      st->resampler_ptr = resampler_basic_direct_double;
+    else
+      st->resampler_ptr = resampler_basic_direct_single;
+#endif
+#endif
+    /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
+  } else {
+    spx_int32_t i;
+    if (!st->sinc_table)
+      st->sinc_table =
+          (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample +
+              8) * sizeof (spx_word16_t));
+    else if (st->sinc_table_length < st->filt_len * st->oversample + 8) {
+      st->sinc_table =
+          (spx_word16_t *) speex_realloc (st->sinc_table,
+          (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t));
+      st->sinc_table_length = st->filt_len * st->oversample + 8;
+    }
+    for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
+      st->sinc_table[i + 4] =
+#ifdef DOUBLE_PRECISION
+          sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
+#else
+          sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
+#endif
+          st->filt_len, quality_map[st->quality].window_func);
+#ifdef FIXED_POINT
+    st->resampler_ptr = resampler_basic_interpolate_single;
+#else
+#ifdef DOUBLE_PRECISION
+    st->resampler_ptr = resampler_basic_interpolate_double;
+#else
+    if (st->quality > 8)
+      st->resampler_ptr = resampler_basic_interpolate_double;
+    else
+      st->resampler_ptr = resampler_basic_interpolate_single;
+#endif
+#endif
+    /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
+  }
+  st->int_advance = st->num_rate / st->den_rate;
+  st->frac_advance = st->num_rate % st->den_rate;
+
+
+  /* Here's the place where we update the filter memory to take into account
+     the change in filter length. It's probably the messiest part of the code
+     due to handling of lots of corner cases. */
+  if (!st->mem) {
+    spx_uint32_t i;
+    st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+    st->mem =
+        (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size *
+        sizeof (spx_word16_t));
+    for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
+      st->mem[i] = 0;
+    /*speex_warning("init filter"); */
+  } else if (!st->started) {
+    spx_uint32_t i;
+    st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+    st->mem =
+        (spx_word16_t *) speex_realloc (st->mem,
+        st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
+    for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++)
+      st->mem[i] = 0;
+    /*speex_warning("reinit filter"); */
+  } else if (st->filt_len > old_length) {
+    spx_int32_t i;
+    /* Increase the filter length */
+    /*speex_warning("increase filter size"); */
+    int old_alloc_size = st->mem_alloc_size;
+    if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) {
+      st->mem_alloc_size = st->filt_len - 1 + st->buffer_size;
+      st->mem =
+          (spx_word16_t *) speex_realloc (st->mem,
+          st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t));
+    }
+    for (i = st->nb_channels - 1; i >= 0; i--) {
+      spx_int32_t j;
+      spx_uint32_t olen = old_length;
+      /*if (st->magic_samples[i]) */
+      {
+        /* Try and remove the magic samples as if nothing had happened */
+
+        /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
+        olen = old_length + 2 * st->magic_samples[i];
+        for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--)
+          st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] =
+              st->mem[i * old_alloc_size + j];
+        for (j = 0; j < st->magic_samples[i]; j++)
+          st->mem[i * st->mem_alloc_size + j] = 0;
+        st->magic_samples[i] = 0;
+      }
+      if (st->filt_len > olen) {
+        /* If the new filter length is still bigger than the "augmented" length */
+        /* Copy data going backward */
+        for (j = 0; j < olen - 1; j++)
+          st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] =
+              st->mem[i * st->mem_alloc_size + (olen - 2 - j)];
+        /* Then put zeros for lack of anything better */
+        for (; j < st->filt_len - 1; j++)
+          st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0;
+        /* Adjust last_sample */
+        st->last_sample[i] += (st->filt_len - olen) / 2;
+      } else {
+        /* Put back some of the magic! */
+        st->magic_samples[i] = (olen - st->filt_len) / 2;
+        for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++)
+          st->mem[i * st->mem_alloc_size + j] =
+              st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
+      }
+    }
+  } else if (st->filt_len < old_length) {
+    spx_uint32_t i;
+    /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
+       samples so they can be used directly as input the next time(s) */
+    for (i = 0; i < st->nb_channels; i++) {
+      spx_uint32_t j;
+      spx_uint32_t old_magic = st->magic_samples[i];
+      st->magic_samples[i] = (old_length - st->filt_len) / 2;
+      /* We must copy some of the memory that's no longer used */
+      /* Copy data going backward */
+      for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++)
+        st->mem[i * st->mem_alloc_size + j] =
+            st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]];
+      st->magic_samples[i] += old_magic;
+    }
+  }
+
+}
+
+EXPORT SpeexResamplerState *
+speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
+    spx_uint32_t out_rate, int quality, int *err)
+{
+  return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
+      out_rate, quality, err);
+}
+
+EXPORT SpeexResamplerState *
+speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
+    spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
+    int quality, int *err)
+{
+  spx_uint32_t i;
+  SpeexResamplerState *st;
+  if (quality > 10 || quality < 0) {
+    if (err)
+      *err = RESAMPLER_ERR_INVALID_ARG;
+    return NULL;
+  }
+  st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
+  st->initialised = 0;
+  st->started = 0;
+  st->in_rate = 0;
+  st->out_rate = 0;
+  st->num_rate = 0;
+  st->den_rate = 0;
+  st->quality = -1;
+  st->sinc_table_length = 0;
+  st->mem_alloc_size = 0;
+  st->filt_len = 0;
+  st->mem = 0;
+  st->resampler_ptr = 0;
+
+  st->cutoff = 1.f;
+  st->nb_channels = nb_channels;
+  st->in_stride = 1;
+  st->out_stride = 1;
+
+#ifdef FIXED_POINT
+  st->buffer_size = 160;
+#else
+  st->buffer_size = 160;
+#endif
+
+  /* Per channel data */
+  st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int));
+  st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
+  st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int));
+  for (i = 0; i < nb_channels; i++) {
+    st->last_sample[i] = 0;
+    st->magic_samples[i] = 0;
+    st->samp_frac_num[i] = 0;
+  }
+
+  speex_resampler_set_quality (st, quality);
+  speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
+
+
+  update_filter (st);
+
+  st->initialised = 1;
+  if (err)
+    *err = RESAMPLER_ERR_SUCCESS;
+
+  return st;
+}
+
+EXPORT void
+speex_resampler_destroy (SpeexResamplerState * st)
+{
+  speex_free (st->mem);
+  speex_free (st->sinc_table);
+  speex_free (st->last_sample);
+  speex_free (st->magic_samples);
+  speex_free (st->samp_frac_num);
+  speex_free (st);
+}
+
+static int
+speex_resampler_process_native (SpeexResamplerState * st,
+    spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out,
+    spx_uint32_t * out_len)
+{
+  int j = 0;
+  const int N = st->filt_len;
+  int out_sample = 0;
+  spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+  spx_uint32_t ilen;
+
+  st->started = 1;
+
+  /* Call the right resampler through the function ptr */
+  out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len);
+
+  if (st->last_sample[channel_index] < (spx_int32_t) * in_len)
+    *in_len = st->last_sample[channel_index];
+  *out_len = out_sample;
+  st->last_sample[channel_index] -= *in_len;
+
+  ilen = *in_len;
+
+  for (j = 0; j < N - 1; ++j)
+    mem[j] = mem[j + ilen];
+
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+static int
+speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index,
+    spx_word16_t ** out, spx_uint32_t out_len)
+{
+  spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
+  spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
+  const int N = st->filt_len;
+
+  speex_resampler_process_native (st, channel_index, &tmp_in_len, *out,
+      &out_len);
+
+  st->magic_samples[channel_index] -= tmp_in_len;
+
+  /* If we couldn't process all "magic" input samples, save the rest for next time */
+  if (st->magic_samples[channel_index]) {
+    spx_uint32_t i;
+    for (i = 0; i < st->magic_samples[channel_index]; i++)
+      mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len];
+  }
+  *out += out_len * st->out_stride;
+  return out_len;
+}
+
+#ifdef FIXED_POINT
+EXPORT int
+speex_resampler_process_int (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+    spx_int16_t * out, spx_uint32_t * out_len)
+#else
+#ifdef DOUBLE_PRECISION
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
+    double *out, spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+    float *out, spx_uint32_t * out_len)
+#endif
+#endif
+{
+  int j;
+  spx_uint32_t ilen = *in_len;
+  spx_uint32_t olen = *out_len;
+  spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+  const int filt_offs = st->filt_len - 1;
+  const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
+  const int istride = st->in_stride;
+
+  if (st->magic_samples[channel_index])
+    olen -= speex_resampler_magic (st, channel_index, &out, olen);
+  if (!st->magic_samples[channel_index]) {
+    while (ilen && olen) {
+      spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+      spx_uint32_t ochunk = olen;
+
+      if (in) {
+        for (j = 0; j < ichunk; ++j)
+          x[j + filt_offs] = in[j * istride];
+      } else {
+        for (j = 0; j < ichunk; ++j)
+          x[j + filt_offs] = 0;
+      }
+      speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk);
+      ilen -= ichunk;
+      olen -= ochunk;
+      out += ochunk * st->out_stride;
+      if (in)
+        in += ichunk * istride;
+    }
+  }
+  *in_len -= ilen;
+  *out_len -= olen;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef FIXED_POINT
+EXPORT int
+speex_resampler_process_float (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
+    float *out, spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_int (SpeexResamplerState * st,
+    spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
+    spx_int16_t * out, spx_uint32_t * out_len)
+#endif
+{
+  int j;
+  const int istride_save = st->in_stride;
+  const int ostride_save = st->out_stride;
+  spx_uint32_t ilen = *in_len;
+  spx_uint32_t olen = *out_len;
+  spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
+  const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
+#ifdef VAR_ARRAYS
+  const unsigned int ylen =
+      (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
+  VARDECL (spx_word16_t * ystack);
+  ALLOC (ystack, ylen, spx_word16_t);
+#else
+  const unsigned int ylen = FIXED_STACK_ALLOC;
+  spx_word16_t ystack[FIXED_STACK_ALLOC];
+#endif
+
+  st->out_stride = 1;
+
+  while (ilen && olen) {
+    spx_word16_t *y = ystack;
+    spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
+    spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
+    spx_uint32_t omagic = 0;
+
+    if (st->magic_samples[channel_index]) {
+      omagic = speex_resampler_magic (st, channel_index, &y, ochunk);
+      ochunk -= omagic;
+      olen -= omagic;
+    }
+    if (!st->magic_samples[channel_index]) {
+      if (in) {
+        for (j = 0; j < ichunk; ++j)
+#ifdef FIXED_POINT
+          x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]);
+#else
+          x[j + st->filt_len - 1] = in[j * istride_save];
+#endif
+      } else {
+        for (j = 0; j < ichunk; ++j)
+          x[j + st->filt_len - 1] = 0;
+      }
+
+      speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk);
+    } else {
+      ichunk = 0;
+      ochunk = 0;
+    }
+
+    for (j = 0; j < ochunk + omagic; ++j)
+#ifdef FIXED_POINT
+      out[j * ostride_save] = ystack[j];
+#else
+      out[j * ostride_save] = WORD2INT (ystack[j]);
+#endif
+
+    ilen -= ichunk;
+    olen -= ochunk;
+    out += (ochunk + omagic) * ostride_save;
+    if (in)
+      in += ichunk * istride_save;
+  }
+  st->out_stride = ostride_save;
+  *in_len -= ilen;
+  *out_len -= olen;
+
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+#ifdef DOUBLE_PRECISION
+EXPORT int
+speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+    const double *in, spx_uint32_t * in_len, double *out,
+    spx_uint32_t * out_len)
+#else
+EXPORT int
+speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+    const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
+#endif
+{
+  spx_uint32_t i;
+  int istride_save, ostride_save;
+  spx_uint32_t bak_len = *out_len;
+  istride_save = st->in_stride;
+  ostride_save = st->out_stride;
+  st->in_stride = st->out_stride = st->nb_channels;
+  for (i = 0; i < st->nb_channels; i++) {
+    *out_len = bak_len;
+    if (in != NULL)
+      speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len);
+    else
+      speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len);
+  }
+  st->in_stride = istride_save;
+  st->out_stride = ostride_save;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_process_interleaved_int (SpeexResamplerState * st,
+    const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out,
+    spx_uint32_t * out_len)
+{
+  spx_uint32_t i;
+  int istride_save, ostride_save;
+  spx_uint32_t bak_len = *out_len;
+  istride_save = st->in_stride;
+  ostride_save = st->out_stride;
+  st->in_stride = st->out_stride = st->nb_channels;
+  for (i = 0; i < st->nb_channels; i++) {
+    *out_len = bak_len;
+    if (in != NULL)
+      speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len);
+    else
+      speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len);
+  }
+  st->in_stride = istride_save;
+  st->out_stride = ostride_save;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate,
+    spx_uint32_t out_rate)
+{
+  return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate,
+      out_rate);
+}
+
+EXPORT void
+speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate,
+    spx_uint32_t * out_rate)
+{
+  *in_rate = st->in_rate;
+  *out_rate = st->out_rate;
+}
+
+EXPORT int
+speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num,
+    spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+  spx_uint32_t fact;
+  spx_uint32_t old_den;
+  spx_uint32_t i;
+  if (st->in_rate == in_rate && st->out_rate == out_rate
+      && st->num_rate == ratio_num && st->den_rate == ratio_den)
+    return RESAMPLER_ERR_SUCCESS;
+
+  old_den = st->den_rate;
+  st->in_rate = in_rate;
+  st->out_rate = out_rate;
+  st->num_rate = ratio_num;
+  st->den_rate = ratio_den;
+  /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
+  for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) {
+    while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) {
+      st->num_rate /= fact;
+      st->den_rate /= fact;
+    }
+  }
+
+  if (old_den > 0) {
+    for (i = 0; i < st->nb_channels; i++) {
+      st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den;
+      /* Safety net */
+      if (st->samp_frac_num[i] >= st->den_rate)
+        st->samp_frac_num[i] = st->den_rate - 1;
+    }
+  }
+
+  if (st->initialised)
+    update_filter (st);
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void
+speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num,
+    spx_uint32_t * ratio_den)
+{
+  *ratio_num = st->num_rate;
+  *ratio_den = st->den_rate;
+}
+
+EXPORT int
+speex_resampler_set_quality (SpeexResamplerState * st, int quality)
+{
+  if (quality > 10 || quality < 0)
+    return RESAMPLER_ERR_INVALID_ARG;
+  if (st->quality == quality)
+    return RESAMPLER_ERR_SUCCESS;
+  st->quality = quality;
+  if (st->initialised)
+    update_filter (st);
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT void
+speex_resampler_get_quality (SpeexResamplerState * st, int *quality)
+{
+  *quality = st->quality;
+}
+
+EXPORT void
+speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride)
+{
+  st->in_stride = stride;
+}
+
+EXPORT void
+speex_resampler_get_input_stride (SpeexResamplerState * st,
+    spx_uint32_t * stride)
+{
+  *stride = st->in_stride;
+}
+
+EXPORT void
+speex_resampler_set_output_stride (SpeexResamplerState * st,
+    spx_uint32_t stride)
+{
+  st->out_stride = stride;
+}
+
+EXPORT void
+speex_resampler_get_output_stride (SpeexResamplerState * st,
+    spx_uint32_t * stride)
+{
+  *stride = st->out_stride;
+}
+
+EXPORT int
+speex_resampler_get_input_latency (SpeexResamplerState * st)
+{
+  return st->filt_len / 2;
+}
+
+EXPORT int
+speex_resampler_get_output_latency (SpeexResamplerState * st)
+{
+  return ((st->filt_len / 2) * st->den_rate +
+      (st->num_rate >> 1)) / st->num_rate;
+}
+
+EXPORT int
+speex_resampler_skip_zeros (SpeexResamplerState * st)
+{
+  spx_uint32_t i;
+  for (i = 0; i < st->nb_channels; i++)
+    st->last_sample[i] = st->filt_len / 2;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT int
+speex_resampler_reset_mem (SpeexResamplerState * st)
+{
+  spx_uint32_t i;
+  for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++)
+    st->mem[i] = 0;
+  return RESAMPLER_ERR_SUCCESS;
+}
+
+EXPORT const char *
+speex_resampler_strerror (int err)
+{
+  switch (err) {
+    case RESAMPLER_ERR_SUCCESS:
+      return "Success.";
+    case RESAMPLER_ERR_ALLOC_FAILED:
+      return "Memory allocation failed.";
+    case RESAMPLER_ERR_BAD_STATE:
+      return "Bad resampler state.";
+    case RESAMPLER_ERR_INVALID_ARG:
+      return "Invalid argument.";
+    case RESAMPLER_ERR_PTR_OVERLAP:
+      return "Input and output buffers overlap.";
+    default:
+      return "Unknown error. Bad error code or strange version mismatch.";
+  }
+}
--- a/gst_plugins_base/gst/audioresample/resample_ref.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/* Resampling library
- * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
- *
- * 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 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#ifndef __SYMBIAN32__
-#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
-
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#ifndef __SYMBIAN32__
-#include <liboil/liboil.h>
-#endif
-
-#include "resample.h"
-#include "buffer.h"
-#include "debug.h"
-
-
-static double
-resample_sinc_window (double x, double halfwidth, double scale)
-{
-  double y;
-
-  if (x == 0)
-    return 1.0;
-  if (x < -halfwidth || x > halfwidth)
-    return 0.0;
-
-  y = sin (x * M_PI * scale) / (x * M_PI * scale) * scale;
-
-  x /= halfwidth;
-  y *= (1 - x * x) * (1 - x * x);
-
-  return y;
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-void
-resample_scale_ref (ResampleState * r)
-{
-  if (r->need_reinit) {
-    RESAMPLE_DEBUG ("sample size %d", r->sample_size);
-
-    if (r->buffer)
-      free (r->buffer);
-    r->buffer_len = r->sample_size * r->filter_length;
-    r->buffer = malloc (r->buffer_len);
-    memset (r->buffer, 0, r->buffer_len);
-    r->buffer_filled = 0;
-
-    r->i_inc = r->o_rate / r->i_rate;
-    r->o_inc = r->i_rate / r->o_rate;
-    RESAMPLE_DEBUG ("i_inc %g o_inc %g", r->i_inc, r->o_inc);
-
-    r->i_start = -r->i_inc * r->filter_length;
-
-    r->need_reinit = 0;
-
-#if 0
-    if (r->i_inc < 1.0) {
-      r->sinc_scale = r->i_inc;
-      if (r->sinc_scale == 0.5) {
-        /* strange things happen at integer multiples */
-        r->sinc_scale = 1.0;
-      }
-    } else {
-      r->sinc_scale = 1.0;
-    }
-#else
-    r->sinc_scale = 1.0;
-#endif
-  }
-
-  RESAMPLE_DEBUG ("asked to resample %d bytes", r->o_size);
-  RESAMPLE_DEBUG ("%d bytes in queue",
-      audioresample_buffer_queue_get_depth (r->queue));
-
-  while (r->o_size >= r->sample_size) {
-    double midpoint;
-    int i;
-    int j;
-
-    midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
-    RESAMPLE_DEBUG
-        ("still need to output %d bytes, %d input left, i_start %g, midpoint %f",
-        r->o_size, audioresample_buffer_queue_get_depth (r->queue), r->i_start,
-        midpoint);
-    if (midpoint > 0.5 * r->i_inc) {
-      RESAMPLE_ERROR ("inconsistent state");
-    }
-    while (midpoint < -0.5 * r->i_inc) {
-      AudioresampleBuffer *buffer;
-
-      RESAMPLE_DEBUG ("midpoint %f < %f, r->i_inc %f", midpoint,
-          -0.5 * r->i_inc, r->i_inc);
-      buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
-      if (buffer == NULL) {
-        /* FIXME: for the first buffer, this isn't necessarily an error,
-         * since because of the filter length we'll output less buffers.
-         * deal with that so we don't print to console */
-        RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
-        return;
-      }
-
-      r->i_start += r->i_inc;
-      RESAMPLE_DEBUG ("pulling (i_start = %g)", r->i_start);
-
-      midpoint += r->i_inc;
-      memmove (r->buffer, r->buffer + r->sample_size,
-          r->buffer_len - r->sample_size);
-
-      memcpy (r->buffer + r->buffer_len - r->sample_size, buffer->data,
-          r->sample_size);
-      r->buffer_filled = MIN (r->buffer_filled + r->sample_size, r->buffer_len);
-
-      audioresample_buffer_unref (buffer);
-    }
-
-    switch (r->format) {
-      case RESAMPLE_FORMAT_S16:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(int16_t *) (r->buffer + i * sizeof (int16_t) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-          if (acc < -32768.0)
-            acc = -32768.0;
-          if (acc > 32767.0)
-            acc = 32767.0;
-
-          *(int16_t *) (r->o_buf + i * sizeof (int16_t)) = rint (acc);
-        }
-        break;
-      case RESAMPLE_FORMAT_S32:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(int32_t *) (r->buffer + i * sizeof (int32_t) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-          if (acc < -2147483648.0)
-            acc = -2147483648.0;
-          if (acc > 2147483647.0)
-            acc = 2147483647.0;
-
-          *(int32_t *) (r->o_buf + i * sizeof (int32_t)) = rint (acc);
-        }
-        break;
-      case RESAMPLE_FORMAT_F32:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(float *) (r->buffer + i * sizeof (float) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-
-          *(float *) (r->o_buf + i * sizeof (float)) = acc;
-        }
-        break;
-      case RESAMPLE_FORMAT_F64:
-        for (i = 0; i < r->n_channels; i++) {
-          double acc = 0;
-          double offset;
-          double x;
-
-          for (j = 0; j < r->filter_length; j++) {
-            offset = (r->i_start + j * r->i_inc) * r->o_inc;
-            x = *(double *) (r->buffer + i * sizeof (double) +
-                j * r->sample_size);
-            acc +=
-                resample_sinc_window (offset, r->filter_length * 0.5,
-                r->sinc_scale) * x;
-          }
-
-          *(double *) (r->o_buf + i * sizeof (double)) = acc;
-        }
-        break;
-    }
-
-    r->i_start -= 1.0;
-    r->o_buf += r->sample_size;
-    r->o_size -= r->sample_size;
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/resample_sse.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,128 @@
+/* Copyright (C) 2007-2008 Jean-Marc Valin
+ * Copyright (C) 2008 Thorvald Natvig
+ */
+/**
+   @file resample_sse.h
+   @brief Resampler functions (SSE version)
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <xmmintrin.h>
+
+#define OVERRIDE_INNER_PRODUCT_SINGLE
+static inline float inner_product_single(const float *a, const float *b, unsigned int len)
+{
+   int i;
+   float ret;
+   __m128 sum = _mm_setzero_ps();
+   for (i=0;i<len;i+=8)
+   {
+      sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)));
+      sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)));
+   }
+   sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
+   sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
+   _mm_store_ss(&ret, sum);
+   return ret;
+}
+
+#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
+static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
+  int i;
+  float ret;
+  __m128 sum = _mm_setzero_ps();
+  __m128 f = _mm_loadu_ps(frac);
+  for(i=0;i<len;i+=2)
+  {
+    sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)));
+    sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)));
+  }
+   sum = _mm_mul_ps(f, sum);
+   sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
+   sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
+   _mm_store_ss(&ret, sum);
+   return ret;
+}
+
+#ifdef _USE_SSE2
+#include <emmintrin.h>
+#define OVERRIDE_INNER_PRODUCT_DOUBLE
+
+static inline double inner_product_double(const float *a, const float *b, unsigned int len)
+{
+   int i;
+   double ret;
+   __m128d sum = _mm_setzero_pd();
+   __m128 t;
+   for (i=0;i<len;i+=8)
+   {
+      t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i));
+      sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
+      sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
+
+      t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4));
+      sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
+      sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
+   }
+   sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum));
+   _mm_store_sd(&ret, sum);
+   return ret;
+}
+
+#define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
+static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
+  int i;
+  double ret;
+  __m128d sum;
+  __m128d sum1 = _mm_setzero_pd();
+  __m128d sum2 = _mm_setzero_pd();
+  __m128 f = _mm_loadu_ps(frac);
+  __m128d f1 = _mm_cvtps_pd(f);
+  __m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f));
+  __m128 t;
+  for(i=0;i<len;i+=2)
+  {
+    t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample));
+    sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
+    sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
+
+    t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample));
+    sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
+    sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
+  }
+  sum1 = _mm_mul_pd(f1, sum1);
+  sum2 = _mm_mul_pd(f2, sum2);
+  sum = _mm_add_pd(sum1, sum2);
+  sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum));
+  _mm_store_sd(&ret, sum);
+  return ret;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/speex_resampler.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,341 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+      
+   File: speex_resampler.h
+   Resampling code
+      
+   The design goals of this code are:
+      - Very fast algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef SPEEX_RESAMPLER_H
+#define SPEEX_RESAMPLER_H
+
+#include <glib.h>
+
+#define OUTSIDE_SPEEX
+//#define RANDOM_PREFIX gst_audioresample
+#ifdef OUTSIDE_SPEEX
+
+/********* WARNING: MENTAL SANITY ENDS HERE *************/
+/* If the resampler is defined outside of Speex, we change the symbol names so that 
+   there won't be any clash if linking with Speex later on. */
+
+/* #define RANDOM_PREFIX your software name here */
+#ifndef RANDOM_PREFIX
+#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
+#endif
+
+#define CAT_PREFIX2(a,b) a ## b
+#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
+
+#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
+#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
+#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
+#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
+#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
+#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
+#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
+#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
+#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
+#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
+#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
+#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
+#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
+#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
+#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
+#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
+#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
+#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
+#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
+#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
+#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
+#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
+
+#define spx_int16_t gint16
+#define spx_int32_t gint32
+#define spx_uint16_t guint16
+#define spx_uint32_t guint32
+
+#else /* OUTSIDE_SPEEX */
+
+#ifdef _BUILD_SPEEX
+# include "speex_types.h"
+#else
+# include <speex/speex_types.h>
+#endif
+
+#endif /* OUTSIDE_SPEEX */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define SPEEX_RESAMPLER_QUALITY_MAX 10
+#define SPEEX_RESAMPLER_QUALITY_MIN 0
+#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
+#define SPEEX_RESAMPLER_QUALITY_VOIP 3
+#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
+
+  enum
+  {
+    RESAMPLER_ERR_SUCCESS = 0,
+    RESAMPLER_ERR_ALLOC_FAILED = 1,
+    RESAMPLER_ERR_BAD_STATE = 2,
+    RESAMPLER_ERR_INVALID_ARG = 3,
+    RESAMPLER_ERR_PTR_OVERLAP = 4,
+
+    RESAMPLER_ERR_MAX_ERROR
+  };
+
+  struct SpeexResamplerState_;
+  typedef struct SpeexResamplerState_ SpeexResamplerState;
+
+/** Create a new resampler with integer input and output rates.
+ * @param nb_channels Number of channels to be processed
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+  SpeexResamplerState *speex_resampler_init (spx_uint32_t nb_channels,
+      spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err);
+
+/** Create a new resampler with fractional input/output rates. The sampling 
+ * rate ratio is an arbitrary rational number with both the numerator and 
+ * denominator being 32-bit integers.
+ * @param nb_channels Number of channels to be processed
+ * @param ratio_num Numerator of the sampling rate ratio
+ * @param ratio_den Denominator of the sampling rate ratio
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+  SpeexResamplerState *speex_resampler_init_frac (spx_uint32_t nb_channels,
+      spx_uint32_t ratio_num,
+      spx_uint32_t ratio_den,
+      spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err);
+
+/** Destroy a resampler state.
+ * @param st Resampler state
+ */
+  void speex_resampler_destroy (SpeexResamplerState * st);
+
+/** Resample a float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param channel_index Index of the channel to process for the multi-channel 
+ * base (0 otherwise)
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the 
+ * number of samples processed
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written
+ */
+#ifdef DOUBLE_PRECISION
+  int speex_resampler_process_float (SpeexResamplerState * st,
+      spx_uint32_t channel_index,
+      const double *in,
+      spx_uint32_t * in_len, double *out, spx_uint32_t * out_len);
+#else
+  int speex_resampler_process_float (SpeexResamplerState * st,
+      spx_uint32_t channel_index,
+      const float *in,
+      spx_uint32_t * in_len, float *out, spx_uint32_t * out_len);
+#endif
+
+/** Resample an int array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param channel_index Index of the channel to process for the multi-channel 
+ * base (0 otherwise)
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written
+ */
+  int speex_resampler_process_int (SpeexResamplerState * st,
+      spx_uint32_t channel_index,
+      const spx_int16_t * in,
+      spx_uint32_t * in_len, spx_int16_t * out, spx_uint32_t * out_len);
+
+/** Resample an interleaved float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+#ifdef DOUBLE_PRECISION
+  int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+      const double *in,
+      spx_uint32_t * in_len, double *out, spx_uint32_t * out_len);
+#else
+  int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
+      const float *in,
+      spx_uint32_t * in_len, float *out, spx_uint32_t * out_len);
+#endif
+
+/** Resample an interleaved int array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+  int speex_resampler_process_interleaved_int (SpeexResamplerState * st,
+      const spx_int16_t * in,
+      spx_uint32_t * in_len, spx_int16_t * out, spx_uint32_t * out_len);
+
+/** Set (change) the input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ */
+  int speex_resampler_set_rate (SpeexResamplerState * st,
+      spx_uint32_t in_rate, spx_uint32_t out_rate);
+
+/** Get the current input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz) copied.
+ * @param out_rate Output sampling rate (integer number of Hz) copied.
+ */
+  void speex_resampler_get_rate (SpeexResamplerState * st,
+      spx_uint32_t * in_rate, spx_uint32_t * out_rate);
+
+/** Set (change) the input/output sampling rates and resampling ratio 
+ * (fractional values in Hz supported).
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio
+ * @param ratio_den Denominator of the sampling rate ratio
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ */
+  int speex_resampler_set_rate_frac (SpeexResamplerState * st,
+      spx_uint32_t ratio_num,
+      spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate);
+
+/** Get the current resampling ratio. This will be reduced to the least
+ * common denominator.
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio copied
+ * @param ratio_den Denominator of the sampling rate ratio copied
+ */
+  void speex_resampler_get_ratio (SpeexResamplerState * st,
+      spx_uint32_t * ratio_num, spx_uint32_t * ratio_den);
+
+/** Set (change) the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor 
+ * quality and 10 has very high quality.
+ */
+  int speex_resampler_set_quality (SpeexResamplerState * st, int quality);
+
+/** Get the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor 
+ * quality and 10 has very high quality.
+ */
+  void speex_resampler_get_quality (SpeexResamplerState * st, int *quality);
+
+/** Set (change) the input stride.
+ * @param st Resampler state
+ * @param stride Input stride
+ */
+  void speex_resampler_set_input_stride (SpeexResamplerState * st,
+      spx_uint32_t stride);
+
+/** Get the input stride.
+ * @param st Resampler state
+ * @param stride Input stride copied
+ */
+  void speex_resampler_get_input_stride (SpeexResamplerState * st,
+      spx_uint32_t * stride);
+
+/** Set (change) the output stride.
+ * @param st Resampler state
+ * @param stride Output stride
+ */
+  void speex_resampler_set_output_stride (SpeexResamplerState * st,
+      spx_uint32_t stride);
+
+/** Get the output stride.
+ * @param st Resampler state copied
+ * @param stride Output stride
+ */
+  void speex_resampler_get_output_stride (SpeexResamplerState * st,
+      spx_uint32_t * stride);
+
+/** Get the latency in input samples introduced by the resampler.
+ * @param st Resampler state
+ */
+  int speex_resampler_get_input_latency (SpeexResamplerState * st);
+
+/** Get the latency in output samples introduced by the resampler.
+ * @param st Resampler state
+ */
+  int speex_resampler_get_output_latency (SpeexResamplerState * st);
+
+/** Make sure that the first samples to go out of the resamplers don't have 
+ * leading zeros. This is only useful before starting to use a newly created 
+ * resampler. It is recommended to use that when resampling an audio file, as
+ * it will generate a file with the same length. For real-time processing,
+ * it is probably easier not to use this call (so that the output duration
+ * is the same for the first frame).
+ * @param st Resampler state
+ */
+  int speex_resampler_skip_zeros (SpeexResamplerState * st);
+
+/** Reset a resampler so a new (unrelated) stream can be processed.
+ * @param st Resampler state
+ */
+  int speex_resampler_reset_mem (SpeexResamplerState * st);
+
+/** Returns the English meaning for an error code
+ * @param err Error code
+ * @return English string
+ */
+  const char *speex_resampler_strerror (int err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/speex_resampler_double.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,27 @@
+/* GStreamer
+ * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#define FLOATING_POINT
+#define DOUBLE_PRECISION
+#define OUTSIDE_SPEEX
+#define RANDOM_PREFIX resample_double
+
+#include "resample_double.c"
+
+#undef FLOATING_POINT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/speex_resampler_float.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,26 @@
+/* GStreamer
+ * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#define FLOATING_POINT
+#define OUTSIDE_SPEEX
+#define RANDOM_PREFIX resample_float
+
+#include "resample_float.c"
+
+#undef FLOATING_POINT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/speex_resampler_int.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,26 @@
+/* GStreamer
+ * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#define FIXED_POINT
+#define OUTSIDE_SPEEX
+#define RANDOM_PREFIX resample_int
+
+#include "resample_int.c"
+
+#undef FIXED_POINT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/audioresample/speex_resampler_wrapper.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,161 @@
+/* GStreamer
+ * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 __SPEEX_RESAMPLER_WRAPPER_H__
+#define __SPEEX_RESAMPLER_WRAPPER_H__
+
+#define SPEEX_RESAMPLER_QUALITY_MAX 10
+#define SPEEX_RESAMPLER_QUALITY_MIN 0
+#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
+#define SPEEX_RESAMPLER_QUALITY_VOIP 3
+#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
+
+enum
+{
+  RESAMPLER_ERR_SUCCESS = 0,
+  RESAMPLER_ERR_ALLOC_FAILED = 1,
+  RESAMPLER_ERR_BAD_STATE = 2,
+  RESAMPLER_ERR_INVALID_ARG = 3,
+  RESAMPLER_ERR_PTR_OVERLAP = 4,
+
+  RESAMPLER_ERR_MAX_ERROR
+};
+
+typedef struct SpeexResamplerState_ SpeexResamplerState;
+
+typedef struct {
+  SpeexResamplerState *(*init) (guint32 nb_channels,
+    guint32 in_rate, guint32 out_rate, gint quality, gint * err);
+  void (*destroy) (SpeexResamplerState * st);
+  int (*process) (SpeexResamplerState *
+    st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
+  int (*set_rate) (SpeexResamplerState * st,
+    guint32 in_rate, guint32 out_rate);
+  void (*get_rate) (SpeexResamplerState * st,
+    guint32 * in_rate, guint32 * out_rate);
+  void (*get_ratio) (SpeexResamplerState * st,
+    guint32 * ratio_num, guint32 * ratio_den);
+  int (*get_input_latency) (SpeexResamplerState * st);
+  int (*set_quality) (SpeexResamplerState * st, gint quality);
+  int (*reset_mem) (SpeexResamplerState * st);
+  int (*skip_zeros) (SpeexResamplerState * st);
+  const char * (*strerror) (gint err);
+  unsigned int width;
+} SpeexResampleFuncs;
+
+SpeexResamplerState *resample_float_resampler_init (guint32 nb_channels,
+    guint32 in_rate, guint32 out_rate, gint quality, gint * err);
+void resample_float_resampler_destroy (SpeexResamplerState * st);
+int resample_float_resampler_process_interleaved_float (SpeexResamplerState *
+    st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
+int resample_float_resampler_set_rate (SpeexResamplerState * st,
+    guint32 in_rate, guint32 out_rate);
+void resample_float_resampler_get_rate (SpeexResamplerState * st,
+    guint32 * in_rate, guint32 * out_rate);
+void resample_float_resampler_get_ratio (SpeexResamplerState * st,
+    guint32 * ratio_num, guint32 * ratio_den);
+int resample_float_resampler_get_input_latency (SpeexResamplerState * st);
+int resample_float_resampler_set_quality (SpeexResamplerState * st, gint quality);
+int resample_float_resampler_reset_mem (SpeexResamplerState * st);
+int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
+const char * resample_float_resampler_strerror (gint err);
+
+static const SpeexResampleFuncs float_funcs =
+{
+  resample_float_resampler_init,
+  resample_float_resampler_destroy,
+  resample_float_resampler_process_interleaved_float,
+  resample_float_resampler_set_rate,
+  resample_float_resampler_get_rate,
+  resample_float_resampler_get_ratio,
+  resample_float_resampler_get_input_latency,
+  resample_float_resampler_set_quality,
+  resample_float_resampler_reset_mem,
+  resample_float_resampler_skip_zeros,
+  resample_float_resampler_strerror,
+  32
+};
+
+SpeexResamplerState *resample_double_resampler_init (guint32 nb_channels,
+    guint32 in_rate, guint32 out_rate, gint quality, gint * err);
+void resample_double_resampler_destroy (SpeexResamplerState * st);
+int resample_double_resampler_process_interleaved_float (SpeexResamplerState *
+    st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
+int resample_double_resampler_set_rate (SpeexResamplerState * st,
+    guint32 in_rate, guint32 out_rate);
+void resample_double_resampler_get_rate (SpeexResamplerState * st,
+    guint32 * in_rate, guint32 * out_rate);
+void resample_double_resampler_get_ratio (SpeexResamplerState * st,
+    guint32 * ratio_num, guint32 * ratio_den);
+int resample_double_resampler_get_input_latency (SpeexResamplerState * st);
+int resample_double_resampler_set_quality (SpeexResamplerState * st, gint quality);
+int resample_double_resampler_reset_mem (SpeexResamplerState * st);
+int resample_double_resampler_skip_zeros (SpeexResamplerState * st);
+const char * resample_double_resampler_strerror (gint err);
+
+static const SpeexResampleFuncs double_funcs =
+{
+  resample_double_resampler_init,
+  resample_double_resampler_destroy,
+  resample_double_resampler_process_interleaved_float,
+  resample_double_resampler_set_rate,
+  resample_double_resampler_get_rate,
+  resample_double_resampler_get_ratio,
+  resample_double_resampler_get_input_latency,
+  resample_double_resampler_set_quality,
+  resample_double_resampler_reset_mem,
+  resample_double_resampler_skip_zeros,
+  resample_double_resampler_strerror,
+  64
+};
+
+SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels,
+    guint32 in_rate, guint32 out_rate, gint quality, gint * err);
+void resample_int_resampler_destroy (SpeexResamplerState * st);
+int resample_int_resampler_process_interleaved_int (SpeexResamplerState *
+    st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
+int resample_int_resampler_set_rate (SpeexResamplerState * st,
+    guint32 in_rate, guint32 out_rate);
+void resample_int_resampler_get_rate (SpeexResamplerState * st,
+    guint32 * in_rate, guint32 * out_rate);
+void resample_int_resampler_get_ratio (SpeexResamplerState * st,
+    guint32 * ratio_num, guint32 * ratio_den);
+int resample_int_resampler_get_input_latency (SpeexResamplerState * st);
+int resample_int_resampler_set_quality (SpeexResamplerState * st, gint quality);
+int resample_int_resampler_reset_mem (SpeexResamplerState * st);
+int resample_int_resampler_skip_zeros (SpeexResamplerState * st);
+const char * resample_int_resampler_strerror (gint err);
+
+static const SpeexResampleFuncs int_funcs =
+{
+  resample_int_resampler_init,
+  resample_int_resampler_destroy,
+  resample_int_resampler_process_interleaved_int,
+  resample_int_resampler_set_rate,
+  resample_int_resampler_get_rate,
+  resample_int_resampler_get_ratio,
+  resample_int_resampler_get_input_latency,
+  resample_int_resampler_set_quality,
+  resample_int_resampler_reset_mem,
+  resample_int_resampler_skip_zeros,
+  resample_int_resampler_strerror,
+  16
+};
+
+#endif /* __SPEEX_RESAMPLER_WRAPPER_H__ */
--- a/gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,26 +19,20 @@
 /**
  * SECTION:element-audiotestsrc
  *
+ * AudioTestSrc can be used to generate basic audio signals. It support several
+ * different waveforms and allows to set the base frequency and volume.
+ *
  * <refsect2>
- * <para>
- * AudioTestSrc can be used to generate basic audio signals. It support several
- * different waveforms and allows you to set the base frequency and volume.
- * </para>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch audiotestsrc ! audioconvert ! alsasink
- * </programlisting>
- * This pipeline produces a sine with default frequency (mid-C) and volume.
- * </para>
- * <para>
- * <programlisting>
+ * ]| This pipeline produces a sine with default frequency, 440 Hz, and the
+ * default volume, 0.8 (relative to a maximum 1.0).
+ * |[
  * gst-launch audiotestsrc wave=2 freq=200 ! audioconvert ! tee name=t ! queue ! alsasink t. ! queue ! libvisual_lv_scope ! ffmpegcolorspace ! xvimagesink
- * </programlisting>
- * In this example a saw wave is generated. The wave is shown using a
+ * ]| In this example a saw wave is generated. The wave is shown using a
  * scope visualizer from libvisual, allowing you to visually verify that
  * the saw wave is correct.
- * </para>
  * </refsect2>
  */
 
@@ -50,7 +44,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <gst/controller/gstcontroller.h>
-#include <glib_global.h>
+
 #include "gstaudiotestsrc.h"
 
 
@@ -73,6 +67,14 @@
     "Creates audio test signals of given frequency and volume",
     "Stefan Kost <ensonic@users.sf.net>");
 
+#define DEFAULT_SAMPLES_PER_BUFFER   1024
+#define DEFAULT_WAVE                 GST_AUDIO_TEST_SRC_WAVE_SINE
+#define DEFAULT_FREQ                 440.0
+#define DEFAULT_VOLUME               0.8
+#define DEFAULT_IS_LIVE              FALSE
+#define DEFAULT_TIMESTAMP_OFFSET     G_GINT64_CONSTANT (0)
+#define DEFAULT_CAN_ACTIVATE_PUSH    TRUE
+#define DEFAULT_CAN_ACTIVATE_PULL    FALSE
 
 enum
 {
@@ -83,6 +85,9 @@
   PROP_VOLUME,
   PROP_IS_LIVE,
   PROP_TIMESTAMP_OFFSET,
+  PROP_CAN_ACTIVATE_PUSH,
+  PROP_CAN_ACTIVATE_PULL,
+  PROP_LAST
 };
 
 
@@ -96,18 +101,18 @@
         "width = (int) 16, "
         "depth = (int) 16, "
         "rate = (int) [ 1, MAX ], "
-        "channels = (int) 1; "
+        "channels = (int) [ 1, 2 ]; "
         "audio/x-raw-int, "
         "endianness = (int) BYTE_ORDER, "
         "signed = (boolean) true, "
         "width = (int) 32, "
         "depth = (int) 32,"
         "rate = (int) [ 1, MAX ], "
-        "channels = (int) 1; "
+        "channels = (int) [ 1, 2 ]; "
         "audio/x-raw-float, "
         "endianness = (int) BYTE_ORDER, "
         "width = (int) { 32, 64 }, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) 1")
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
     );
 
 
@@ -125,9 +130,12 @@
     {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"},
     {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"},
     {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"},
-    {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White noise", "white-noise"},
+    {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"},
     {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"},
-    {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine table"},
+    {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"},
+    {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
+    {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
+        "gaussian-noise"},
     {0, NULL, NULL},
   };
 
@@ -148,6 +156,7 @@
 static void gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps);
 
 static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
+static gboolean gst_audio_test_src_check_get_range (GstBaseSrc * basesrc);
 static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
     GstSegment * segment);
 static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
@@ -157,6 +166,8 @@
 
 static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
     GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
+static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
+static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
 static GstFlowReturn gst_audio_test_src_create (GstBaseSrc * basesrc,
     guint64 offset, guint length, GstBuffer ** buffer);
 
@@ -186,32 +197,50 @@
   g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
       g_param_spec_int ("samplesperbuffer", "Samples per buffer",
           "Number of samples in each outgoing buffer",
-          1, G_MAXINT, 1024, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_WAVE, g_param_spec_enum ("wave", "Waveform", "Oscillator waveform", GST_TYPE_AUDIO_TEST_SRC_WAVE,        /* enum type */
-          GST_AUDIO_TEST_SRC_WAVE_SINE, /* default value */
-          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+          1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_WAVE,
+      g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
+          GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_FREQ,
       g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
-          0.0, 20000.0, 440.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+          0.0, 20000.0, DEFAULT_FREQ,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_VOLUME,
-      g_param_spec_double ("volume", "Volume", "Volume of test signal",
-          0.0, 1.0, 0.8, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+      g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
+          1.0, DEFAULT_VOLUME,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_IS_LIVE,
       g_param_spec_boolean ("is-live", "Is Live",
-          "Whether to act as a live source", FALSE, G_PARAM_READWRITE));
+          "Whether to act as a live source", DEFAULT_IS_LIVE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass),
-      PROP_TIMESTAMP_OFFSET,
-      g_param_spec_int64 ("timestamp-offset", "Timestamp offset",
+      PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
+          "Timestamp offset",
           "An offset added to timestamps set on buffers (in ns)", G_MININT64,
-          G_MAXINT64, 0, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
+      g_param_spec_boolean ("can-activate-push", "Can activate push",
+          "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
+      g_param_spec_boolean ("can-activate-pull", "Can activate pull",
+          "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
   gstbasesrc_class->is_seekable =
       GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
+  gstbasesrc_class->check_get_range =
+      GST_DEBUG_FUNCPTR (gst_audio_test_src_check_get_range);
   gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
   gstbasesrc_class->get_times =
       GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
+  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
+  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create);
 }
 
@@ -224,18 +253,21 @@
 
   src->samplerate = 44100;
   src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE;
-  src->volume = 0.8;
-  src->freq = 440.0;
+
+  src->volume = DEFAULT_VOLUME;
+  src->freq = DEFAULT_FREQ;
 
   /* we operate in time */
   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
-  gst_base_src_set_live (GST_BASE_SRC (src), FALSE);
+  gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
 
-  src->samples_per_buffer = 1024;
+  src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
   src->generate_samples_per_buffer = src->samples_per_buffer;
-  src->timestamp_offset = G_GINT64_CONSTANT (0);
+  src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
+  src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
 
-  src->wave = GST_AUDIO_TEST_SRC_WAVE_SINE;
+  src->wave = DEFAULT_WAVE;
+  gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
 }
 
 static void
@@ -247,6 +279,8 @@
 
   structure = gst_caps_get_structure (caps, 0);
 
+  GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate);
+
   gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
 
   name = gst_structure_get_name (structure);
@@ -254,6 +288,9 @@
     gst_structure_fixate_field_nearest_int (structure, "width", 32);
   else if (strcmp (name, "audio/x-raw-float") == 0)
     gst_structure_fixate_field_nearest_int (structure, "width", 64);
+
+  /* fixate to mono unless downstream requires stereo, for backwards compat */
+  gst_structure_fixate_field_nearest_int (structure, "channels", 1);
 }
 
 static gboolean
@@ -268,6 +305,8 @@
   structure = gst_caps_get_structure (caps, 0);
   ret = gst_structure_get_int (structure, "rate", &src->samplerate);
 
+  GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate);
+
   name = gst_structure_get_name (structure);
   if (strcmp (name, "audio/x-raw-int") == 0) {
     ret &= gst_structure_get_int (structure, "width", &width);
@@ -279,6 +318,29 @@
         GST_AUDIO_TEST_SRC_FORMAT_F64;
   }
 
+  /* allocate a new buffer suitable for this pad */
+  switch (src->format) {
+    case GST_AUDIO_TEST_SRC_FORMAT_S16:
+      src->sample_size = sizeof (gint16);
+      break;
+    case GST_AUDIO_TEST_SRC_FORMAT_S32:
+      src->sample_size = sizeof (gint32);
+      break;
+    case GST_AUDIO_TEST_SRC_FORMAT_F32:
+      src->sample_size = sizeof (gfloat);
+      break;
+    case GST_AUDIO_TEST_SRC_FORMAT_F64:
+      src->sample_size = sizeof (gdouble);
+      break;
+    default:
+      /* can't really happen */
+      ret = FALSE;
+      break;
+  }
+
+  ret &= gst_structure_get_int (structure, "channels", &src->channels);
+  GST_DEBUG_OBJECT (src, "negotiated to %d channels", src->channels);
+
   gst_audio_test_src_change_wave (src);
 
   return ret;
@@ -353,18 +415,21 @@
 static void \
 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
   gdouble step, amp; \
   \
   step = M_PI_M2 * src->freq / src->samplerate; \
   amp = src->volume * scale; \
   \
-  for (i = 0; i < src->generate_samples_per_buffer; i++) { \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    samples[i] = (g##type) (sin (src->accumulator) * amp); \
+    for (c = 0; c < src->channels; ++c) { \
+      samples[i++] = (g##type) (sin (src->accumulator) * amp); \
+    } \
   } \
 }
 
@@ -373,7 +438,7 @@
 DEFINE_SINE (float, 1.0);
 DEFINE_SINE (double, 1.0);
 
-static ProcessFunc sine_funcs[] = {
+static const ProcessFunc sine_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_sine_int16,
   (ProcessFunc) gst_audio_test_src_create_sine_int32,
   (ProcessFunc) gst_audio_test_src_create_sine_float,
@@ -384,18 +449,21 @@
 static void \
 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
   gdouble step, amp; \
   \
   step = M_PI_M2 * src->freq / src->samplerate; \
   amp = src->volume * scale; \
   \
-  for (i = 0; i < src->generate_samples_per_buffer; i++) { \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    samples[i] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \
+    for (c = 0; c < src->channels; ++c) { \
+      samples[i++] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \
+    } \
   } \
 }
 
@@ -404,7 +472,7 @@
 DEFINE_SQUARE (float, 1.0);
 DEFINE_SQUARE (double, 1.0);
 
-static ProcessFunc square_funcs[] = {
+static const ProcessFunc square_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_square_int16,
   (ProcessFunc) gst_audio_test_src_create_square_int32,
   (ProcessFunc) gst_audio_test_src_create_square_float,
@@ -415,21 +483,24 @@
 static void \
 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
   gdouble step, amp; \
   \
   step = M_PI_M2 * src->freq / src->samplerate; \
   amp = (src->volume * scale) / M_PI; \
   \
-  for (i = 0; i < src->generate_samples_per_buffer; i++) { \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
     if (src->accumulator < M_PI) { \
-      samples[i] = (g##type) (src->accumulator * amp); \
+      for (c = 0; c < src->channels; ++c) \
+        samples[i++] = (g##type) (src->accumulator * amp); \
     } else { \
-      samples[i] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
+      for (c = 0; c < src->channels; ++c) \
+        samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
     } \
   } \
 }
@@ -439,7 +510,7 @@
 DEFINE_SAW (float, 1.0);
 DEFINE_SAW (double, 1.0);
 
-static ProcessFunc saw_funcs[] = {
+static const ProcessFunc saw_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_saw_int16,
   (ProcessFunc) gst_audio_test_src_create_saw_int32,
   (ProcessFunc) gst_audio_test_src_create_saw_float,
@@ -450,23 +521,27 @@
 static void \
 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
   gdouble step, amp; \
   \
   step = M_PI_M2 * src->freq / src->samplerate; \
   amp = (src->volume * scale) / M_PI_2; \
   \
-  for (i = 0; i < src->generate_samples_per_buffer; i++) { \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
     if (src->accumulator < (M_PI * 0.5)) { \
-      samples[i] = (g##type) (src->accumulator * amp); \
+      for (c = 0; c < src->channels; ++c) \
+        samples[i++] = (g##type) (src->accumulator * amp); \
     } else if (src->accumulator < (M_PI * 1.5)) { \
-      samples[i] = (g##type) ((src->accumulator - M_PI) * -amp); \
+      for (c = 0; c < src->channels; ++c) \
+        samples[i++] = (g##type) ((src->accumulator - M_PI) * -amp); \
     } else { \
-      samples[i] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
+      for (c = 0; c < src->channels; ++c) \
+        samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
     } \
   } \
 }
@@ -476,7 +551,7 @@
 DEFINE_TRIANGLE (float, 1.0);
 DEFINE_TRIANGLE (double, 1.0);
 
-static ProcessFunc triangle_funcs[] = {
+static const ProcessFunc triangle_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_triangle_int16,
   (ProcessFunc) gst_audio_test_src_create_triangle_int32,
   (ProcessFunc) gst_audio_test_src_create_triangle_float,
@@ -487,7 +562,7 @@
 static void \
 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type)); \
+  memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \
 }
 
 DEFINE_SILENCE (int16);
@@ -495,7 +570,7 @@
 DEFINE_SILENCE (float);
 DEFINE_SILENCE (double);
 
-static ProcessFunc silence_funcs[] = {
+static const ProcessFunc silence_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_silence_int16,
   (ProcessFunc) gst_audio_test_src_create_silence_int32,
   (ProcessFunc) gst_audio_test_src_create_silence_float,
@@ -506,11 +581,13 @@
 static void \
 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
   gdouble amp = (src->volume * scale); \
   \
-  for (i = 0; i < src->generate_samples_per_buffer; i++) { \
-    samples[i] = (g##type) (amp * g_random_double_range (-1.0, 1.0)); \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+    for (c = 0; c < src->channels; ++c) \
+      samples[i++] = (g##type) (amp * g_random_double_range (-1.0, 1.0)); \
   } \
 }
 
@@ -519,7 +596,7 @@
 DEFINE_WHITE_NOISE (float, 1.0);
 DEFINE_WHITE_NOISE (double, 1.0);
 
-static ProcessFunc white_noise_funcs[] = {
+static const ProcessFunc white_noise_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
   (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
   (ProcessFunc) gst_audio_test_src_create_white_noise_float,
@@ -577,7 +654,6 @@
      * values together. Only one changes each time.
      */
     pink->running_sum -= pink->rows[num_zeros];
-    //new_random = ((glong)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
     new_random = 32768.0 - (65536.0 * (gulong) rand () / (RAND_MAX + 1.0));
     pink->running_sum += new_random;
     pink->rows[num_zeros] = new_random;
@@ -595,15 +671,18 @@
 static void \
 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
   gdouble amp; \
   \
   amp = src->volume * scale; \
   \
-  for (i = 0; i < src->generate_samples_per_buffer; i++) { \
-    samples[i] = \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+    for (c = 0; c < src->channels; ++c) { \
+      samples[i++] = \
         (g##type) (gst_audio_test_src_generate_pink_noise_value (&src->pink) * \
         amp); \
+    } \
   } \
 }
 
@@ -612,7 +691,7 @@
 DEFINE_PINK (float, 1.0);
 DEFINE_PINK (double, 1.0);
 
-static ProcessFunc pink_noise_funcs[] = {
+static const ProcessFunc pink_noise_funcs[] = {
   (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
   (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
   (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
@@ -637,7 +716,40 @@
 static void \
 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i; \
+  gint i, c; \
+  gdouble step, scl; \
+  \
+  step = M_PI_M2 * src->freq / src->samplerate; \
+  scl = 1024.0 / M_PI_M2; \
+  \
+  i = 0; \
+  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+    src->accumulator += step; \
+    if (src->accumulator >= M_PI_M2) \
+      src->accumulator -= M_PI_M2; \
+    \
+    for (c = 0; c < src->channels; ++c) \
+      samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
+  } \
+}
+
+DEFINE_SINE_TABLE (int16, 32767.0);
+DEFINE_SINE_TABLE (int32, 2147483647.0);
+DEFINE_SINE_TABLE (float, 1.0);
+DEFINE_SINE_TABLE (double, 1.0);
+
+static const ProcessFunc sine_table_funcs[] = {
+  (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
+  (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
+  (ProcessFunc) gst_audio_test_src_create_sine_table_float,
+  (ProcessFunc) gst_audio_test_src_create_sine_table_double
+};
+
+#define DEFINE_TICKS(type,scale) \
+static void \
+gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
+{ \
+  gint i, c; \
   gdouble step, scl; \
   \
   step = M_PI_M2 * src->freq / src->samplerate; \
@@ -648,20 +760,64 @@
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    samples[i] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
+    if ((src->next_sample + i)%src->samplerate < 1600) { \
+      for (c = 0; c < src->channels; ++c) \
+        samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
+    } else { \
+      for (c = 0; c < src->channels; ++c) \
+        samples[(i * src->channels) + c] = 0; \
+    } \
   } \
 }
 
-DEFINE_SINE_TABLE (int16, 32767.0);
-DEFINE_SINE_TABLE (int32, 2147483647.0);
-DEFINE_SINE_TABLE (float, 1.0);
-DEFINE_SINE_TABLE (double, 1.0);
+DEFINE_TICKS (int16, 32767.0);
+DEFINE_TICKS (int32, 2147483647.0);
+DEFINE_TICKS (float, 1.0);
+DEFINE_TICKS (double, 1.0);
+
+static const ProcessFunc tick_funcs[] = {
+  (ProcessFunc) gst_audio_test_src_create_tick_int16,
+  (ProcessFunc) gst_audio_test_src_create_tick_int32,
+  (ProcessFunc) gst_audio_test_src_create_tick_float,
+  (ProcessFunc) gst_audio_test_src_create_tick_double
+};
+
+/* Gaussian white noise using Box-Muller algorithm.  unit variance
+ * normally-distributed random numbers are generated in pairs as the real
+ * and imaginary parts of a compex random variable with
+ * uniformly-distributed argument and \chi^{2}-distributed modulus.
+ */
 
-static ProcessFunc sine_table_funcs[] = {
-  (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
-  (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
-  (ProcessFunc) gst_audio_test_src_create_sine_table_float,
-  (ProcessFunc) gst_audio_test_src_create_sine_table_double
+#define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
+static void \
+gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
+{ \
+  gint i, c; \
+  gdouble amp = (src->volume * scale); \
+  \
+  for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
+    for (c = 0; c < src->channels; ++c) { \
+      gdouble mag = sqrt (-2 * log (1.0 - g_random_double ())); \
+      gdouble phs = g_random_double_range (0.0, M_PI_M2); \
+      \
+      samples[i++] = (g##type) (amp * mag * cos (phs)); \
+      if (++c >= src->channels) \
+        break; \
+      samples[i++] = (g##type) (amp * mag * sin (phs)); \
+    } \
+  } \
+}
+
+DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
+DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
+DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
+DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
+
+static const ProcessFunc gaussian_white_noise_funcs[] = {
+  (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
+  (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
+  (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
+  (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
 };
 
 /*
@@ -703,6 +859,13 @@
       gst_audio_test_src_init_sine_table (src);
       src->process = sine_table_funcs[src->format];
       break;
+    case GST_AUDIO_TEST_SRC_WAVE_TICKS:
+      gst_audio_test_src_init_sine_table (src);
+      src->process = tick_funcs[src->format];
+      break;
+    case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
+      src->process = gaussian_white_noise_funcs[src->format];
+      break;
     default:
       GST_ERROR ("invalid wave-form");
       break;
@@ -749,6 +912,30 @@
 }
 
 static gboolean
+gst_audio_test_src_start (GstBaseSrc * basesrc)
+{
+  GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
+
+  src->next_sample = 0;
+  src->next_byte = 0;
+  src->next_time = 0;
+  src->check_seek_stop = FALSE;
+  src->eos_reached = FALSE;
+  src->tags_pushed = FALSE;
+  src->accumulator = 0;
+
+  return TRUE;
+}
+
+static gboolean
+gst_audio_test_src_stop (GstBaseSrc * basesrc)
+{
+  return TRUE;
+}
+
+/* seek to time, will be called when we operate in push mode. In pull mode we
+ * get the requested byte offset. */
+static gboolean
 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
 {
   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
@@ -758,16 +945,17 @@
   time = segment->last_stop;
 
   /* now move to the time indicated */
-  src->n_samples =
+  src->next_sample =
       gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND);
-  src->running_time =
-      gst_util_uint64_scale_int (src->n_samples, GST_SECOND, src->samplerate);
+  src->next_byte = src->next_sample * src->sample_size * src->channels;
+  src->next_time =
+      gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate);
 
-  g_assert (src->running_time <= time);
+  g_assert (src->next_time <= time);
 
   if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
     time = segment->stop;
-    src->n_samples_stop = gst_util_uint64_scale_int (time, src->samplerate,
+    src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate,
         GST_SECOND);
     src->check_seek_stop = TRUE;
   } else {
@@ -785,6 +973,17 @@
   return TRUE;
 }
 
+static gboolean
+gst_audio_test_src_check_get_range (GstBaseSrc * basesrc)
+{
+  GstAudioTestSrc *src;
+
+  src = GST_AUDIO_TEST_SRC (basesrc);
+
+  /* if we can operate in pull mode */
+  return src->can_activate_pull;
+}
+
 static GstFlowReturn
 gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
     guint length, GstBuffer ** buffer)
@@ -793,85 +992,97 @@
   GstAudioTestSrc *src;
   GstBuffer *buf;
   GstClockTime next_time;
-  gint64 n_samples;
-  gint sample_size;
+  gint64 next_sample, next_byte;
+  guint bytes, samples;
+  GstElementClass *eclass;
 
   src = GST_AUDIO_TEST_SRC (basesrc);
 
-  if (src->eos_reached)
-    return GST_FLOW_UNEXPECTED;
-
   /* example for tagging generated data */
   if (!src->tags_pushed) {
     GstTagList *taglist;
-    GstEvent *event;
 
     taglist = gst_tag_list_new ();
 
     gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
         GST_TAG_DESCRIPTION, "audiotest wave", NULL);
 
-    event = gst_event_new_tag (taglist);
-    gst_pad_push_event (basesrc->srcpad, event);
+    eclass = GST_ELEMENT_CLASS (parent_class);
+    if (eclass->send_event)
+      eclass->send_event (GST_ELEMENT_CAST (basesrc),
+          gst_event_new_tag (taglist));
     src->tags_pushed = TRUE;
   }
 
+  if (src->eos_reached)
+    return GST_FLOW_UNEXPECTED;
+
+  /* if no length was given, use our default length in samples otherwise convert
+   * the length in bytes to samples. */
+  if (length == -1)
+    samples = src->samples_per_buffer;
+  else
+    samples = length / (src->sample_size * src->channels);
+
+  /* if no offset was given, use our next logical byte */
+  if (offset == -1)
+    offset = src->next_byte;
+
+  /* now see if we are at the byteoffset we think we are */
+  if (offset != src->next_byte) {
+    GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
+    /* we have a discont in the expected sample offset, do a 'seek' */
+    src->next_sample = offset / (src->sample_size * src->channels);
+    src->next_time =
+        gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
+        src->samplerate);
+    src->next_byte = offset;
+  }
+
   /* check for eos */
   if (src->check_seek_stop &&
-      (src->n_samples_stop > src->n_samples) &&
-      (src->n_samples_stop < src->n_samples + src->samples_per_buffer)
+      (src->sample_stop > src->next_sample) &&
+      (src->sample_stop < src->next_sample + samples)
       ) {
     /* calculate only partial buffer */
-    src->generate_samples_per_buffer = src->n_samples_stop - src->n_samples;
-    n_samples = src->n_samples_stop;
+    src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
+    next_sample = src->sample_stop;
     src->eos_reached = TRUE;
   } else {
     /* calculate full buffer */
-    src->generate_samples_per_buffer = src->samples_per_buffer;
-    n_samples = src->n_samples + src->samples_per_buffer;
-  }
-  next_time = gst_util_uint64_scale (n_samples, GST_SECOND,
-      (guint64) src->samplerate);
-
-  /* allocate a new buffer suitable for this pad */
-  switch (src->format) {
-    case GST_AUDIO_TEST_SRC_FORMAT_S16:
-      sample_size = sizeof (gint16);
-      break;
-    case GST_AUDIO_TEST_SRC_FORMAT_S32:
-      sample_size = sizeof (gint32);
-      break;
-    case GST_AUDIO_TEST_SRC_FORMAT_F32:
-      sample_size = sizeof (gfloat);
-      break;
-    case GST_AUDIO_TEST_SRC_FORMAT_F64:
-      sample_size = sizeof (gdouble);
-      break;
-    default:
-      sample_size = -1;
-      GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL),
-          ("format wasn't negotiated before get function"));
-      return GST_FLOW_NOT_NEGOTIATED;
-      break;
+    src->generate_samples_per_buffer = samples;
+    next_sample = src->next_sample + samples;
   }
 
-  if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->n_samples,
-              src->generate_samples_per_buffer * sample_size,
-              GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
+  bytes = src->generate_samples_per_buffer * src->sample_size * src->channels;
+
+  if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->next_sample,
+              bytes, GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
     return res;
   }
 
-  GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->running_time;
-  GST_BUFFER_OFFSET_END (buf) = n_samples;
-  GST_BUFFER_DURATION (buf) = next_time - src->running_time;
+  next_byte = src->next_byte + bytes;
+  next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND,
+      src->samplerate);
+
+  GST_LOG_OBJECT (src, "samplerate %d", src->samplerate);
+  GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
+      next_sample, GST_TIME_ARGS (next_time));
 
-  gst_object_sync_values (G_OBJECT (src), src->running_time);
+  GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time;
+  GST_BUFFER_OFFSET (buf) = src->next_sample;
+  GST_BUFFER_OFFSET_END (buf) = next_sample;
+  GST_BUFFER_DURATION (buf) = next_time - src->next_time;
 
-  src->running_time = next_time;
-  src->n_samples = n_samples;
+  gst_object_sync_values (G_OBJECT (src), src->next_time);
+
+  src->next_time = next_time;
+  src->next_sample = next_sample;
+  src->next_byte = next_byte;
 
   GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
-      length, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+      src->generate_samples_per_buffer,
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
 
   src->process (src, GST_BUFFER_DATA (buf));
 
@@ -912,6 +1123,12 @@
     case PROP_TIMESTAMP_OFFSET:
       src->timestamp_offset = g_value_get_int64 (value);
       break;
+    case PROP_CAN_ACTIVATE_PUSH:
+      GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
+      break;
+    case PROP_CAN_ACTIVATE_PULL:
+      src->can_activate_pull = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -943,6 +1160,12 @@
     case PROP_TIMESTAMP_OFFSET:
       g_value_set_int64 (value, src->timestamp_offset);
       break;
+    case PROP_CAN_ACTIVATE_PUSH:
+      g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
+      break;
+    case PROP_CAN_ACTIVATE_PULL:
+      g_value_set_boolean (value, src->can_activate_pull);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
--- a/gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -45,9 +45,11 @@
  * @GST_AUDIO_TEST_SRC_WAVE_SAW: a saw wave
  * @GST_AUDIO_TEST_SRC_WAVE_TRIANGLE: a tringle wave
  * @GST_AUDIO_TEST_SRC_WAVE_SILENCE: silence
- * @GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: white noise
+ * @GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: white uniform noise
  * @GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE: pink noise
  * @GST_AUDIO_TEST_SRC_WAVE_SINE_TAB: sine wave using a table
+ * @GST_AUDIO_TEST_SRC_WAVE_TICKS: periodic ticks
+ * @GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE: white (zero mean) Gaussian noise;  volume sets the standard deviation of the noise in units of the range of values of the sample type, e.g. volume=0.1 produces noise with a standard deviation of 0.1*32767=3277 with 16-bit integer samples, or 0.1*1.0=0.1 with floating-point samples.
  *
  * Different types of supported sound waves.
  */
@@ -59,7 +61,9 @@
   GST_AUDIO_TEST_SRC_WAVE_SILENCE,
   GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE,
   GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE,
-  GST_AUDIO_TEST_SRC_WAVE_SINE_TAB
+  GST_AUDIO_TEST_SRC_WAVE_SINE_TAB,
+  GST_AUDIO_TEST_SRC_WAVE_TICKS,
+  GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE
 } GstAudioTestSrcWave; 
 
 #define PINK_MAX_RANDOM_ROWS   (30)
@@ -103,19 +107,23 @@
   gdouble freq;
     
   /* audio parameters */
+  gint channels;
   gint samplerate;
   gint samples_per_buffer;
+  gint sample_size;
   GstAudioTestSrcFormat format;
   
   /*< private >*/
   gboolean tags_pushed;			/* send tags just once ? */
   GstClockTimeDiff timestamp_offset;    /* base offset */
-  GstClockTime running_time;            /* total running time */
-  gint64 n_samples;                     /* total samples sent */
-  gint64 n_samples_stop;
+  GstClockTime next_time;               /* next timestamp */
+  gint64 next_sample;                   /* next sample to send */
+  gint64 next_byte;                     /* next byte to send */
+  gint64 sample_stop;
   gboolean check_seek_stop;
   gboolean eos_reached;
   gint generate_samples_per_buffer;	/* used to generate a partial buffer */
+  gboolean can_activate_pull;
   
   /* waveform specific context data */
   gdouble accumulator;			/* phase angle */
--- a/gst_plugins_base/gst/ffmpegcolorspace/avcodec.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/ffmpegcolorspace/avcodec.h	Fri Apr 16 15:15:52 2010 +0300
@@ -53,6 +53,8 @@
  */
 enum PixelFormat {
     PIX_FMT_YUV420P,   ///< Planar YUV 4:2:0 (1 Cr & Cb sample per 2x2 Y samples) (I420)
+    PIX_FMT_NV12,      ///< Packed YUV 4:2:0 (separate Y plane, interleaved Cb & Cr planes)
+    PIX_FMT_NV21,      ///< Packed YUV 4:2:0 (separate Y plane, interleaved Cb & Cr planes)
     PIX_FMT_YVU420P,   ///< Planar YUV 4:2:0 (1 Cb & Cr sample per 2x2 Y samples) (YV12)
     PIX_FMT_YUV422,    ///< Packed pixel, Y0 Cb Y1 Cr 
     PIX_FMT_RGB24,     ///< Packed pixel, 3 bytes per pixel, RGBRGB...
@@ -60,9 +62,9 @@
     PIX_FMT_YUV422P,   ///< Planar YUV 4:2:2 (1 Cr & Cb sample per 2x1 Y samples)
     PIX_FMT_YUV444P,   ///< Planar YUV 4:4:4 (1 Cr & Cb sample per 1x1 Y samples)
     PIX_FMT_RGBA32,    ///< Packed pixel, 4 bytes per pixel, BGRABGRA..., stored in cpu endianness
-    PIX_FMT_BGRA32,     ///< Packed pixel, 4 bytes per pixel, ARGBARGB...
+    PIX_FMT_BGRA32,    ///< Packed pixel, 4 bytes per pixel, ARGBARGB...
     PIX_FMT_ARGB32,    ///< Packed pixel, 4 bytes per pixel, ABGRABGR..., stored in cpu endianness
-    PIX_FMT_ABGR32,     ///< Packed pixel, 4 bytes per pixel, RGBARGBA...
+    PIX_FMT_ABGR32,    ///< Packed pixel, 4 bytes per pixel, RGBARGBA...
     PIX_FMT_RGB32,     ///< Packed pixel, 4 bytes per pixel, BGRxBGRx..., stored in cpu endianness
     PIX_FMT_xRGB32,    ///< Packed pixel, 4 bytes per pixel, xBGRxBGR..., stored in cpu endianness
     PIX_FMT_BGR32,     ///< Packed pixel, 4 bytes per pixel, xRGBxRGB...
@@ -73,6 +75,8 @@
     PIX_FMT_RGB565,    ///< always stored in cpu endianness 
     PIX_FMT_RGB555,    ///< always stored in cpu endianness, most significant bit to 1 
     PIX_FMT_GRAY8,
+    PIX_FMT_GRAY16_L,
+    PIX_FMT_GRAY16_B,
     PIX_FMT_MONOWHITE, ///< 0 is white 
     PIX_FMT_MONOBLACK, ///< 0 is black 
     PIX_FMT_PAL8,      ///< 8 bit with RGBA palette 
@@ -82,7 +86,9 @@
     PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
     PIX_FMT_XVMC_MPEG2_IDCT,
     PIX_FMT_UYVY422,   ///< Packed pixel, Cb Y0 Cr Y1 
+    PIX_FMT_YVYU422,   ///< Packed pixel, Y0 Cr Y1 Cb 
     PIX_FMT_UYVY411,   ///< Packed pixel, Cb Y0 Y1 Cr Y2 Y3
+    PIX_FMT_V308,      ///< Packed pixel, Y0 Cb Cr
 
     PIX_FMT_AYUV4444,  ///< Packed pixel, A0 Y0 Cb Cr
     PIX_FMT_NB
--- a/gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcodecmap.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcodecmap.c	Fri Apr 16 15:15:52 2010 +0300
@@ -167,6 +167,12 @@
     case PIX_FMT_YUV420P:
       fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
       break;
+    case PIX_FMT_NV12:
+      fmt = GST_MAKE_FOURCC ('N', 'V', '1', '2');
+      break;
+    case PIX_FMT_NV21:
+      fmt = GST_MAKE_FOURCC ('N', 'V', '2', '1');
+      break;
     case PIX_FMT_YVU420P:
       fmt = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
       break;
@@ -176,6 +182,9 @@
     case PIX_FMT_UYVY422:
       fmt = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
       break;
+    case PIX_FMT_YVYU422:
+      fmt = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
+      break;
     case PIX_FMT_UYVY411:
       fmt = GST_MAKE_FOURCC ('I', 'Y', 'U', '1');
       break;
@@ -347,13 +356,35 @@
       bpp = depth = 8;
       endianness = G_BYTE_ORDER;
       break;
+    case PIX_FMT_V308:
+      fmt = GST_MAKE_FOURCC ('v', '3', '0', '8');
+      break;
     case PIX_FMT_AYUV4444:
       fmt = GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
       break;
-    case PIX_FMT_GRAY8:
+    case PIX_FMT_GRAY8:{
+      GstCaps *tmp;
+
       bpp = depth = 8;
       caps = gst_ff_vid_caps_new (context, "video/x-raw-gray",
           "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL);
+      tmp = gst_ff_vid_caps_new (context, "video/x-raw-yuv",
+          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', '8', '0', '0'),
+          NULL);
+      gst_caps_append (caps, tmp);
+    }
+      break;
+    case PIX_FMT_GRAY16_L:
+      bpp = depth = 16;
+      caps = gst_ff_vid_caps_new (context, "video/x-raw-gray",
+          "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth,
+          "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
+      break;
+    case PIX_FMT_GRAY16_B:
+      bpp = depth = 16;
+      caps = gst_ff_vid_caps_new (context, "video/x-raw-gray",
+          "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth,
+          "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
       break;
     default:
       /* give up ... */
@@ -384,7 +415,7 @@
             "bpp", G_TYPE_INT, bpp,
             "depth", G_TYPE_INT, depth,
             "endianness", G_TYPE_INT, endianness, NULL);
-        if (context) {
+        if (context && context->pix_fmt == PIX_FMT_PAL8) {
           gst_ffmpeg_set_palette (caps, context);
         }
       }
@@ -395,10 +426,7 @@
   }
 
   if (caps != NULL) {
-    char *str = gst_caps_to_string (caps);
-
-    GST_DEBUG ("caps for pix_fmt=%d: %s", pix_fmt, str);
-    g_free (str);
+    GST_DEBUG ("caps for pix_fmt=%d: %" GST_PTR_FORMAT, pix_fmt, caps);
   } else {
     GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
   }
@@ -441,10 +469,7 @@
   }
 
   if (caps != NULL) {
-    char *str = gst_caps_to_string (caps);
-
-    GST_DEBUG ("caps for sample_fmt=%d: %s", sample_fmt, str);
-    g_free (str);
+    GST_DEBUG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
   } else {
     GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
   }
@@ -591,12 +616,21 @@
         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
           context->pix_fmt = PIX_FMT_UYVY422;
           break;
+        case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
+          context->pix_fmt = PIX_FMT_YVYU422;
+          break;
         case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
           context->pix_fmt = PIX_FMT_UYVY411;
           break;
         case GST_MAKE_FOURCC ('I', '4', '2', '0'):
           context->pix_fmt = PIX_FMT_YUV420P;
           break;
+        case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
+          context->pix_fmt = PIX_FMT_NV12;
+          break;
+        case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
+          context->pix_fmt = PIX_FMT_NV21;
+          break;
         case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
           context->pix_fmt = PIX_FMT_YVU420P;
           break;
@@ -612,12 +646,18 @@
         case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
           context->pix_fmt = PIX_FMT_YVU410P;
           break;
+        case GST_MAKE_FOURCC ('v', '3', '0', '8'):
+          context->pix_fmt = PIX_FMT_V308;
+          break;
         case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
           context->pix_fmt = PIX_FMT_AYUV4444;
           break;
         case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
           context->pix_fmt = PIX_FMT_YUV444P;
           break;
+        case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
+          context->pix_fmt = PIX_FMT_GRAY8;
+          break;
       }
     }
   } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
@@ -708,6 +748,17 @@
         case 8:
           context->pix_fmt = PIX_FMT_GRAY8;
           break;
+        case 16:{
+          gint endianness = 0;
+
+          if (gst_structure_get_int (structure, "endianness", &endianness)) {
+            if (endianness == G_LITTLE_ENDIAN)
+              context->pix_fmt = PIX_FMT_GRAY16_L;
+            else if (endianness == G_BIG_ENDIAN)
+              context->pix_fmt = PIX_FMT_GRAY16_B;
+          }
+        }
+          break;
       }
     }
   }
@@ -811,6 +862,22 @@
       picture->linesize[1] = stride2;
       picture->linesize[2] = stride2;
       return size + 2 * size2;
+    case PIX_FMT_NV12:
+    case PIX_FMT_NV21:
+      stride = GST_ROUND_UP_4 (width);
+      h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
+      size = stride * h2;
+      w2 = 2 * DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
+      stride2 = GST_ROUND_UP_4 (w2);
+      h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
+      size2 = stride2 * h2;
+      picture->data[0] = ptr;
+      picture->data[1] = picture->data[0] + size;
+      picture->data[2] = NULL;
+      picture->linesize[0] = stride;
+      picture->linesize[1] = stride2;
+      picture->linesize[2] = 0;
+      return size + size2;
     case PIX_FMT_RGB24:
     case PIX_FMT_BGR24:
       stride = GST_ROUND_UP_4 (width * 3);
@@ -840,6 +907,7 @@
     case PIX_FMT_RGB565:
     case PIX_FMT_YUV422:
     case PIX_FMT_UYVY422:
+    case PIX_FMT_YVYU422:
       stride = GST_ROUND_UP_4 (width * 2);
       size = stride * height;
       picture->data[0] = ptr;
@@ -847,6 +915,14 @@
       picture->data[2] = NULL;
       picture->linesize[0] = stride;
       return size;
+    case PIX_FMT_V308:
+      stride = GST_ROUND_UP_4 (width * 3);
+      size = stride * height;
+      picture->data[0] = ptr;
+      picture->data[1] = NULL;
+      picture->data[2] = NULL;
+      picture->linesize[0] = stride;
+      return size;
     case PIX_FMT_UYVY411:
       /* FIXME, probably not the right stride */
       stride = GST_ROUND_UP_4 (width);
@@ -864,6 +940,15 @@
       picture->data[2] = NULL;
       picture->linesize[0] = stride;
       return size;
+    case PIX_FMT_GRAY16_L:
+    case PIX_FMT_GRAY16_B:
+      stride = GST_ROUND_UP_4 (width * 2);
+      size = stride * height;
+      picture->data[0] = ptr;
+      picture->data[1] = NULL;
+      picture->data[2] = NULL;
+      picture->linesize[0] = stride;
+      return size;
     case PIX_FMT_MONOWHITE:
     case PIX_FMT_MONOBLACK:
       stride = GST_ROUND_UP_4 ((width + 7) >> 3);
--- a/gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcolorspace.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcolorspace.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,13 +22,13 @@
 /**
  * SECTION:element-ffmpegcolorspace
  *
+ * Convert video frames between a great variety of colorspace formats.
+ *
  * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v videotestsrc ! video/x-raw-yuv,format=\(fourcc\)YUY2 ! ffmpegcolorspace ! ximagesink
- * </programlisting>
- * </para>
+ * ]|
  * </refsect2>
  */
 
@@ -139,12 +139,9 @@
 gst_ffmpegcsp_transform_caps (GstBaseTransform * btrans,
     GstPadDirection direction, GstCaps * caps)
 {
-  GstFFMpegCsp *space;
   GstCaps *template;
   GstCaps *result;
 
-  space = GST_FFMPEGCSP (btrans);
-
   template = gst_ffmpegcsp_codectype_to_caps (CODEC_TYPE_VIDEO, NULL);
   result = gst_caps_intersect (caps, template);
   gst_caps_unref (template);
@@ -379,7 +376,6 @@
 gst_ffmpegcsp_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
     guint * size)
 {
-  GstFFMpegCsp *space = NULL;
   GstStructure *structure = NULL;
   AVCodecContext *ctx = NULL;
   gboolean ret = TRUE;
@@ -387,8 +383,6 @@
 
   g_assert (size);
 
-  space = GST_FFMPEGCSP (btrans);
-
   structure = gst_caps_get_structure (caps, 0);
   gst_structure_get_int (structure, "width", &width);
   gst_structure_get_int (structure, "height", &height);
@@ -412,7 +406,8 @@
    * GStreamer currently puts it into the caps as 'palette_data' field,
    * so for paletted data the frame size avpicture_get_size() returns is
    * 1024 bytes larger than what GStreamer expects. */
-  if (gst_structure_has_field (structure, "palette_data")) {
+  if (gst_structure_has_field (structure, "palette_data") &&
+      ctx->pix_fmt == PIX_FMT_PAL8) {
     *size -= 4 * 256;           /* = AVPALETTE_SIZE */
   }
 
--- a/gst_plugins_base/gst/ffmpegcolorspace/imgconvert.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/ffmpegcolorspace/imgconvert.c	Fri Apr 16 15:15:52 2010 +0300
@@ -64,6 +64,28 @@
         /* .y_chroma_shift = */ 1,
         /* .depth          = */ 8,
       },
+  /* [PIX_FMT_NV12] = */ {
+        /* .format         = */ PIX_FMT_NV12,
+        /* .name           = */ "nv12",
+        /* .nb_channels    = */ 2,
+        /* .color_type     = */ FF_COLOR_YUV,
+        /* .pixel_type     = */ FF_PIXEL_PACKED,
+        /* .is_alpha       = */ 0,
+        /* .x_chroma_shift = */ 1,
+        /* .y_chroma_shift = */ 1,
+        /* .depth          = */ 8,
+      },
+  /* [PIX_FMT_NV21] = */ {
+        /* .format         = */ PIX_FMT_NV21,
+        /* .name           = */ "nv21",
+        /* .nb_channels    = */ 2,
+        /* .color_type     = */ FF_COLOR_YUV,
+        /* .pixel_type     = */ FF_PIXEL_PACKED,
+        /* .is_alpha       = */ 0,
+        /* .x_chroma_shift = */ 1,
+        /* .y_chroma_shift = */ 1,
+        /* .depth          = */ 8,
+      },
   /* [PIX_FMT_YUV422P] = */ {
         /* .format         = */ PIX_FMT_YUV422P,
         /* .name           = */ "yuv422p",
@@ -108,6 +130,28 @@
         /* .y_chroma_shift = */ 0,
         /* .depth          = */ 8,
       },
+  /* [PIX_FMT_YVYU422] = */ {
+        /* .format         = */ PIX_FMT_YVYU422,
+        /* .name           = */ "yvyu422",
+        /* .nb_channels    = */ 1,
+        /* .color_type     = */ FF_COLOR_YUV,
+        /* .pixel_type     = */ FF_PIXEL_PACKED,
+        /* .is_alpha       = */ 0,
+        /* .x_chroma_shift = */ 1,
+        /* .y_chroma_shift = */ 0,
+        /* .depth          = */ 8,
+      },
+  /* [PIX_FMT_V308] = */ {
+        /* .format         = */ PIX_FMT_V308,
+        /* .name           = */ "v308",
+        /* .nb_channels    = */ 1,
+        /* .color_type     = */ FF_COLOR_YUV,
+        /* .pixel_type     = */ FF_PIXEL_PACKED,
+        /* .is_alpha       = */ 0,
+        /* .x_chroma_shift = */ 0,
+        /* .y_chroma_shift = */ 0,
+        /* .depth          = */ 8,
+      },
   /* [PIX_FMT_YUV410P] = */ {
         /* .format         = */ PIX_FMT_YUV410P,
         /* .name           = */ "yuv410p",
@@ -323,6 +367,28 @@
         /* .y_chroma_shift = */ 0,
         /* .depth          = */ 8,
       },
+  /* [PIX_FMT_GRAY16_L] = */ {
+        /* .format         = */ PIX_FMT_GRAY16_L,
+        /* .name           = */ "gray",
+        /* .nb_channels    = */ 1,
+        /* .color_type     = */ FF_COLOR_GRAY,
+        /* .pixel_type     = */ FF_PIXEL_PLANAR,
+        /* .is_alpha       = */ 0,
+        /* .x_chroma_shift = */ 0,
+        /* .y_chroma_shift = */ 0,
+        /* .depth          = */ 16,
+      },
+  /* [PIX_FMT_GRAY16_B] = */ {
+        /* .format         = */ PIX_FMT_GRAY16_B,
+        /* .name           = */ "gray",
+        /* .nb_channels    = */ 1,
+        /* .color_type     = */ FF_COLOR_GRAY,
+        /* .pixel_type     = */ FF_PIXEL_PLANAR,
+        /* .is_alpha       = */ 0,
+        /* .x_chroma_shift = */ 0,
+        /* .y_chroma_shift = */ 0,
+        /* .depth          = */ 16,
+      },
   /* [PIX_FMT_MONOWHITE] = */ {
         /* .format         = */ PIX_FMT_MONOWHITE,
         /* .name           = */ "monow",
@@ -508,7 +574,6 @@
   return size;
 }
 #endif
-
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -591,6 +656,7 @@
       switch (pix_fmt) {
         case PIX_FMT_YUV422:
         case PIX_FMT_UYVY422:
+        case PIX_FMT_YVYU422:
         case PIX_FMT_RGB565:
         case PIX_FMT_RGB555:
           bits = 16;
@@ -704,7 +770,7 @@
     int pix_fmt, int width, int height)
 {
   int bwidth, bits, i;
-  PixFmtInfo *pf = get_pix_fmt_info (pix_fmt);
+  const PixFmtInfo *pf;
 
   pf = get_pix_fmt_info (pix_fmt);
   switch (pf->pixel_type) {
@@ -712,6 +778,7 @@
       switch (pix_fmt) {
         case PIX_FMT_YUV422:
         case PIX_FMT_UYVY422:
+        case PIX_FMT_YVYU422:
         case PIX_FMT_RGB565:
         case PIX_FMT_RGB555:
           bits = 16;
@@ -812,6 +879,31 @@
 }
 
 static void
+uyvy422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const uint8_t *p, *p1;
+  uint8_t *lum, *lum1;
+  int w;
+
+  p1 = src->data[0];
+  lum1 = dst->data[0];
+  for (; height > 0; height--) {
+    p = p1;
+    lum = lum1;
+
+    for (w = width; w >= 2; w -= 2) {
+      lum[0] = p[1];
+      lum[1] = p[3];
+      p += 4;
+      lum += 2;
+    }
+    p1 += src->linesize[0];
+    lum1 += dst->linesize[0];
+  }
+}
+
+
+static void
 uyvy422_to_yuv420p (AVPicture * dst, const AVPicture * src,
     int width, int height)
 {
@@ -904,6 +996,122 @@
   }
 }
 
+static void
+yvyu422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const uint8_t *p, *p1;
+  uint8_t *lum, *lum1;
+  int w;
+
+  p1 = src->data[0];
+  lum1 = dst->data[0];
+  for (; height > 0; height--) {
+    p = p1;
+    lum = lum1;
+
+    for (w = width; w >= 2; w -= 2) {
+      lum[0] = p[0];
+      lum[1] = p[2];
+      p += 4;
+      lum += 2;
+    }
+    p1 += src->linesize[0];
+    lum1 += dst->linesize[0];
+  }
+}
+
+
+static void
+yvyu422_to_yuv420p (AVPicture * dst, const AVPicture * src,
+    int width, int height)
+{
+  const uint8_t *p, *p1;
+  uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+  int w;
+
+  p1 = src->data[0];
+
+  lum1 = dst->data[0];
+  cb1 = dst->data[1];
+  cr1 = dst->data[2];
+
+  for (; height >= 1; height -= 2) {
+    p = p1;
+    lum = lum1;
+    cb = cb1;
+    cr = cr1;
+    for (w = width; w >= 2; w -= 2) {
+      lum[0] = p[0];
+      cb[0] = p[3];
+      lum[1] = p[2];
+      cr[0] = p[1];
+      p += 4;
+      lum += 2;
+      cb++;
+      cr++;
+    }
+    if (w) {
+      lum[0] = p[0];
+      cb[0] = p[3];
+      cr[0] = p[1];
+      cb++;
+      cr++;
+    }
+    p1 += src->linesize[0];
+    lum1 += dst->linesize[0];
+    if (height > 1) {
+      p = p1;
+      lum = lum1;
+      for (w = width; w >= 2; w -= 2) {
+        lum[0] = p[0];
+        lum[1] = p[2];
+        p += 4;
+        lum += 2;
+      }
+      if (w) {
+        lum[0] = p[0];
+      }
+      p1 += src->linesize[0];
+      lum1 += dst->linesize[0];
+    }
+    cb1 += dst->linesize[1];
+    cr1 += dst->linesize[2];
+  }
+}
+
+static void
+yvyu422_to_yuv422p (AVPicture * dst, const AVPicture * src,
+    int width, int height)
+{
+  const uint8_t *p, *p1;
+  uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+  int w;
+
+  p1 = src->data[0];
+  lum1 = dst->data[0];
+  cb1 = dst->data[1];
+  cr1 = dst->data[2];
+  for (; height > 0; height--) {
+    p = p1;
+    lum = lum1;
+    cb = cb1;
+    cr = cr1;
+    for (w = width; w >= 2; w -= 2) {
+      lum[0] = p[0];
+      cb[0] = p[3];
+      lum[1] = p[2];
+      cr[0] = p[1];
+      p += 4;
+      lum += 2;
+      cb++;
+      cr++;
+    }
+    p1 += src->linesize[0];
+    lum1 += dst->linesize[0];
+    cb1 += dst->linesize[1];
+    cr1 += dst->linesize[2];
+  }
+}
 
 static void
 yuv422_to_yuv422p (AVPicture * dst, const AVPicture * src,
@@ -1012,6 +1220,40 @@
 }
 
 static void
+yuv422p_to_yvyu422 (AVPicture * dst, const AVPicture * src,
+    int width, int height)
+{
+  uint8_t *p, *p1;
+  const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+  int w;
+
+  p1 = dst->data[0];
+  lum1 = src->data[0];
+  cb1 = src->data[1];
+  cr1 = src->data[2];
+  for (; height > 0; height--) {
+    p = p1;
+    lum = lum1;
+    cb = cb1;
+    cr = cr1;
+    for (w = width; w >= 2; w -= 2) {
+      p[0] = lum[0];
+      p[3] = cb[0];
+      p[2] = lum[1];
+      p[1] = cr[0];
+      p += 4;
+      lum += 2;
+      cb++;
+      cr++;
+    }
+    p1 += dst->linesize[0];
+    lum1 += src->linesize[0];
+    cb1 += src->linesize[1];
+    cr1 += src->linesize[2];
+  }
+}
+
+static void
 uyvy411_to_yuv411p (AVPicture * dst, const AVPicture * src,
     int width, int height)
 {
@@ -1047,7 +1289,6 @@
   }
 }
 
-
 static void
 yuv420p_to_yuv422 (AVPicture * dst, const AVPicture * src,
     int width, int height)
@@ -1109,6 +1350,226 @@
   }
 }
 
+static void
+nv12_to_nv21 (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const uint8_t *s_c_ptr;
+  uint8_t *d_c_ptr;
+  int w, c_wrap;
+
+  memcpy (dst->data[0], src->data[0], src->linesize[0] * height);
+
+  s_c_ptr = src->data[1];
+  d_c_ptr = dst->data[1];
+  c_wrap = src->linesize[1] - ((width + 1) & ~0x01);
+
+  for (; height >= 2; height -= 2) {
+    for (w = width; w >= 2; w -= 2) {
+      d_c_ptr[0] = s_c_ptr[1];
+      d_c_ptr[1] = s_c_ptr[0];
+      s_c_ptr += 2;
+      d_c_ptr += 2;
+    }
+
+    /* handle odd width */
+    if (w) {
+      d_c_ptr[0] = s_c_ptr[1];
+      d_c_ptr[1] = s_c_ptr[0];
+      s_c_ptr += 2;
+      d_c_ptr += 2;
+    }
+    s_c_ptr += c_wrap;
+    d_c_ptr += c_wrap;
+  }
+
+  /* handle odd height */
+  if (height) {
+    for (w = width; w >= 2; w -= 2) {
+      d_c_ptr[0] = s_c_ptr[1];
+      d_c_ptr[1] = s_c_ptr[0];
+      s_c_ptr += 2;
+      d_c_ptr += 2;
+    }
+
+    /* handle odd width */
+    if (w) {
+      d_c_ptr[0] = s_c_ptr[1];
+      d_c_ptr[1] = s_c_ptr[0];
+      s_c_ptr += 2;
+      d_c_ptr += 2;
+    }
+  }
+}
+
+static void
+nv12_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  int w, h;
+  uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0];
+  uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1];
+  uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2];
+  uint8_t *lum1, *lum2, *src_lum_line = src->data[0];
+  uint8_t *src_c1, *src_c_line = src->data[1];
+  uint8_t cb, cr;
+
+  for (h = height / 2; h--;) {
+    dst_lum1 = dst_line;
+    dst_lum2 = dst_line + dst->linesize[0];
+
+    dst_cb1 = dst_cb_line;
+    dst_cb2 = dst_cb_line + dst->linesize[1];
+    dst_cr1 = dst_cr_line;
+    dst_cr2 = dst_cr_line + dst->linesize[2];
+
+    lum1 = src_lum_line;
+    lum2 = src_lum_line + src->linesize[0];
+
+    src_c1 = src_c_line;
+
+    for (w = width / 2; w--;) {
+      cb = *src_c1++;
+      cr = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_lum2++ = *lum2++;
+      *dst_cb1++ = *dst_cb2++ = cb;
+      *dst_cr1++ = *dst_cr2++ = cr;
+      *dst_lum1++ = *lum1++;
+      *dst_lum2++ = *lum2++;
+      *dst_cb1++ = *dst_cb2++ = cb;
+      *dst_cr1++ = *dst_cr2++ = cr;
+    }
+    /* odd width */
+    if (width % 2 != 0) {
+      cb = *src_c1++;
+      cr = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_lum2++ = *lum2++;
+      *dst_cb1++ = *dst_cb2++ = *src_c1++;
+      *dst_cr1++ = *dst_cr2++ = *src_c1++;
+    }
+
+    dst_line += dst->linesize[0] * 2;
+    dst_cb_line += dst->linesize[1] * 2;
+    dst_cr_line += dst->linesize[2] * 2;
+    src_lum_line += src->linesize[0] * 2;
+    src_c_line += src->linesize[1];
+  }
+
+  /* odd height */
+  if (height % 2 != 0) {
+    dst_lum1 = dst_line;
+    lum1 = src_lum_line;
+    src_c1 = src_c_line;
+    dst_cb1 = dst_cb_line;
+    dst_cr1 = dst_cr_line;
+
+    for (w = width / 2; w--;) {
+      cb = *src_c1++;
+      cr = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_cb1++ = cb;
+      *dst_cr1++ = cr;
+      *dst_lum1++ = *lum1++;
+      *dst_cb1++ = cb;
+      *dst_cr1++ = cr;
+    }
+    /* odd width */
+    if (width % 2 != 0) {
+      cb = *src_c1++;
+      cr = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_cb1++ = cb;
+      *dst_cr1++ = cr;
+    }
+  }
+}
+
+#define nv21_to_nv12 nv12_to_nv21
+
+static void
+nv21_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  int w, h;
+  uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0];
+  uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1];
+  uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2];
+  uint8_t *lum1, *lum2, *src_lum_line = src->data[0];
+  uint8_t *src_c1, *src_c_line = src->data[1];
+  uint8_t cb, cr;
+
+  for (h = height / 2; h--;) {
+    dst_lum1 = dst_line;
+    dst_lum2 = dst_line + dst->linesize[0];
+
+    dst_cb1 = dst_cb_line;
+    dst_cb2 = dst_cb_line + dst->linesize[1];
+    dst_cr1 = dst_cr_line;
+    dst_cr2 = dst_cr_line + dst->linesize[2];
+
+    lum1 = src_lum_line;
+    lum2 = src_lum_line + src->linesize[0];
+
+    src_c1 = src_c_line;
+
+    for (w = width / 2; w--;) {
+      cr = *src_c1++;
+      cb = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_lum2++ = *lum2++;
+      *dst_cb1++ = *dst_cb2++ = cb;
+      *dst_cr1++ = *dst_cr2++ = cr;
+      *dst_lum1++ = *lum1++;
+      *dst_lum2++ = *lum2++;
+      *dst_cb1++ = *dst_cb2++ = cb;
+      *dst_cr1++ = *dst_cr2++ = cr;
+    }
+    /* odd width */
+    if (width % 2 != 0) {
+      cr = *src_c1++;
+      cb = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_lum2++ = *lum2++;
+      *dst_cb1++ = *dst_cb2++ = *src_c1++;
+      *dst_cr1++ = *dst_cr2++ = *src_c1++;
+    }
+
+    dst_line += dst->linesize[0] * 2;
+    dst_cb_line += dst->linesize[1] * 2;
+    dst_cr_line += dst->linesize[2] * 2;
+    src_lum_line += src->linesize[0] * 2;
+    src_c_line += src->linesize[1];
+  }
+
+  /* odd height */
+  if (height % 2 != 0) {
+    dst_lum1 = dst_line;
+    lum1 = src_lum_line;
+    src_c1 = src_c_line;
+
+    dst_cb1 = dst_cb_line;
+    dst_cr1 = dst_cr_line;
+
+    for (w = width / 2; w--;) {
+      cr = *src_c1++;
+      cb = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_cb1++ = cb;
+      *dst_cr1++ = cr;
+      *dst_lum1++ = *lum1++;
+      *dst_cb1++ = cb;
+      *dst_cr1++ = cr;
+    }
+    /* odd width */
+    if (width % 2 != 0) {
+      cr = *src_c1++;
+      cb = *src_c1++;
+      *dst_lum1++ = *lum1++;
+      *dst_cb1++ = cb;
+      *dst_cr1++ = cr;
+    }
+  }
+}
+
 #define SCALEBITS 10
 #define ONE_HALF  (1 << (SCALEBITS - 1))
 #define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
@@ -1910,6 +2371,133 @@
 #include "imgconvert_template.h"
 
 static void
+gray_to_gray16_l (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const unsigned char *p;
+  unsigned char *q;
+  int dst_wrap, src_wrap;
+  int x, y;
+
+  p = src->data[0];
+  src_wrap = src->linesize[0] - width;
+
+  q = dst->data[0];
+  dst_wrap = dst->linesize[0] - 2 * width;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      GST_WRITE_UINT16_LE (q, (*p << 8));
+      q += 2;
+      p++;
+    }
+    p += src_wrap;
+    q += dst_wrap;
+  }
+}
+
+static void
+gray_to_gray16_b (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const unsigned char *p;
+  unsigned char *q;
+  int dst_wrap, src_wrap;
+  int x, y;
+
+  p = src->data[0];
+  src_wrap = src->linesize[0] - width;
+
+  q = dst->data[0];
+  dst_wrap = dst->linesize[0] - 2 * width;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      GST_WRITE_UINT16_BE (q, (*p << 8));
+      q += 2;
+      p++;
+    }
+    p += src_wrap;
+    q += dst_wrap;
+  }
+}
+
+static void
+gray16_l_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const unsigned char *p;
+  unsigned char *q;
+  int dst_wrap, src_wrap;
+  int x, y;
+
+  p = src->data[0];
+  src_wrap = src->linesize[0] - 2 * width;
+
+  q = dst->data[0];
+  dst_wrap = dst->linesize[0] - width;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      q[0] = GST_READ_UINT16_LE (p) >> 8;
+      q++;
+      p += 2;
+    }
+    p += src_wrap;
+    q += dst_wrap;
+  }
+}
+
+static void
+gray16_b_to_gray (AVPicture * dst, const AVPicture * src, int width, int height)
+{
+  const unsigned char *p;
+  unsigned char *q;
+  int dst_wrap, src_wrap;
+  int x, y;
+
+  p = src->data[0];
+  src_wrap = src->linesize[0] - 2 * width;
+
+  q = dst->data[0];
+  dst_wrap = dst->linesize[0] - width;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      q[0] = GST_READ_UINT16_BE (p) >> 8;
+      q++;
+      p += 2;
+    }
+    p += src_wrap;
+    q += dst_wrap;
+  }
+}
+
+static void
+gray16_b_to_gray16_l (AVPicture * dst, const AVPicture * src,
+    int width, int height)
+{
+  const unsigned char *p;
+  unsigned char *q;
+  int dst_wrap, src_wrap;
+  int x, y;
+
+  p = src->data[0];
+  src_wrap = src->linesize[0] - 2 * width;
+
+  q = dst->data[0];
+  dst_wrap = dst->linesize[0] - 2 * width;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      q[0] = p[1];
+      q[1] = p[0];
+      q += 2;
+      p += 2;
+    }
+    p += src_wrap;
+    q += dst_wrap;
+  }
+}
+
+static void
 mono_to_gray (AVPicture * dst, const AVPicture * src,
     int width, int height, int xor_mask)
 {
@@ -2064,8 +2652,39 @@
   {PIX_FMT_YUV420P, PIX_FMT_ARGB32, yuv420p_to_argb32},
   {PIX_FMT_YUV420P, PIX_FMT_ABGR32, yuv420p_to_abgr32},
 
+  {PIX_FMT_NV12, PIX_FMT_RGB555, nv12_to_rgb555},
+  {PIX_FMT_NV12, PIX_FMT_RGB565, nv12_to_rgb565},
+  {PIX_FMT_NV12, PIX_FMT_BGR24, nv12_to_bgr24},
+  {PIX_FMT_NV12, PIX_FMT_RGB24, nv12_to_rgb24},
+  {PIX_FMT_NV12, PIX_FMT_RGB32, nv12_to_rgb32},
+  {PIX_FMT_NV12, PIX_FMT_BGR32, nv12_to_bgr32},
+  {PIX_FMT_NV12, PIX_FMT_xRGB32, nv12_to_xrgb32},
+  {PIX_FMT_NV12, PIX_FMT_BGRx32, nv12_to_bgrx32},
+  {PIX_FMT_NV12, PIX_FMT_RGBA32, nv12_to_rgba32},
+  {PIX_FMT_NV12, PIX_FMT_BGRA32, nv12_to_bgra32},
+  {PIX_FMT_NV12, PIX_FMT_ARGB32, nv12_to_argb32},
+  {PIX_FMT_NV12, PIX_FMT_ABGR32, nv12_to_abgr32},
+  {PIX_FMT_NV12, PIX_FMT_NV21, nv12_to_nv21},
+  {PIX_FMT_NV12, PIX_FMT_YUV444P, nv12_to_yuv444p},
+
+  {PIX_FMT_NV21, PIX_FMT_RGB555, nv21_to_rgb555},
+  {PIX_FMT_NV21, PIX_FMT_RGB565, nv21_to_rgb565},
+  {PIX_FMT_NV21, PIX_FMT_BGR24, nv21_to_bgr24},
+  {PIX_FMT_NV21, PIX_FMT_RGB24, nv21_to_rgb24},
+  {PIX_FMT_NV21, PIX_FMT_RGB32, nv21_to_rgb32},
+  {PIX_FMT_NV21, PIX_FMT_BGR32, nv21_to_bgr32},
+  {PIX_FMT_NV21, PIX_FMT_xRGB32, nv21_to_xrgb32},
+  {PIX_FMT_NV21, PIX_FMT_BGRx32, nv21_to_bgrx32},
+  {PIX_FMT_NV21, PIX_FMT_RGBA32, nv21_to_rgba32},
+  {PIX_FMT_NV21, PIX_FMT_BGRA32, nv21_to_bgra32},
+  {PIX_FMT_NV21, PIX_FMT_ARGB32, nv21_to_argb32},
+  {PIX_FMT_NV21, PIX_FMT_ABGR32, nv21_to_abgr32},
+  {PIX_FMT_NV21, PIX_FMT_YUV444P, nv21_to_yuv444p},
+  {PIX_FMT_NV21, PIX_FMT_NV12, nv21_to_nv12},
+
   {PIX_FMT_YUV422P, PIX_FMT_YUV422, yuv422p_to_yuv422},
   {PIX_FMT_YUV422P, PIX_FMT_UYVY422, yuv422p_to_uyvy422},
+  {PIX_FMT_YUV422P, PIX_FMT_YVYU422, yuv422p_to_yvyu422},
 
   {PIX_FMT_YUV444P, PIX_FMT_RGB24, yuv444p_to_rgb24},
 
@@ -2089,8 +2708,15 @@
 
   {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p},
   {PIX_FMT_UYVY422, PIX_FMT_YUV422P, uyvy422_to_yuv422p},
+  {PIX_FMT_UYVY422, PIX_FMT_GRAY8, uyvy422_to_gray},
+
+  {PIX_FMT_YVYU422, PIX_FMT_YUV420P, yvyu422_to_yuv420p},
+  {PIX_FMT_YVYU422, PIX_FMT_YUV422P, yvyu422_to_yuv422p},
+  {PIX_FMT_YVYU422, PIX_FMT_GRAY8, yvyu422_to_gray},
 
   {PIX_FMT_RGB24, PIX_FMT_YUV420P, rgb24_to_yuv420p},
+  {PIX_FMT_RGB24, PIX_FMT_NV12, rgb24_to_nv12},
+  {PIX_FMT_RGB24, PIX_FMT_NV21, rgb24_to_nv21},
   {PIX_FMT_RGB24, PIX_FMT_RGB565, rgb24_to_rgb565},
   {PIX_FMT_RGB24, PIX_FMT_RGB555, rgb24_to_rgb555},
   {PIX_FMT_RGB24, PIX_FMT_RGB32, rgb24_to_rgb32},
@@ -2103,22 +2729,33 @@
   {PIX_FMT_RGB24, PIX_FMT_ARGB32, rgb24_to_argb32},
   {PIX_FMT_RGB24, PIX_FMT_ABGR32, rgb24_to_abgr32},
   {PIX_FMT_RGB24, PIX_FMT_GRAY8, rgb24_to_gray},
+  {PIX_FMT_RGB24, PIX_FMT_GRAY16_L, rgb24_to_gray16_l},
+  {PIX_FMT_RGB24, PIX_FMT_GRAY16_B, rgb24_to_gray16_b},
   {PIX_FMT_RGB24, PIX_FMT_PAL8, rgb24_to_pal8},
   {PIX_FMT_RGB24, PIX_FMT_YUV444P, rgb24_to_yuv444p},
   {PIX_FMT_RGB24, PIX_FMT_YUVJ420P, rgb24_to_yuvj420p},
   {PIX_FMT_RGB24, PIX_FMT_YUVJ444P, rgb24_to_yuvj444p},
   {PIX_FMT_RGB24, PIX_FMT_AYUV4444, rgb24_to_ayuv4444},
+  {PIX_FMT_RGB24, PIX_FMT_V308, rgb24_to_v308},
 
   {PIX_FMT_RGB32, PIX_FMT_RGB24, rgb32_to_rgb24},
   {PIX_FMT_RGB32, PIX_FMT_RGB555, rgba32_to_rgb555},
   {PIX_FMT_RGB32, PIX_FMT_PAL8, rgb32_to_pal8},
   {PIX_FMT_RGB32, PIX_FMT_YUV420P, rgb32_to_yuv420p},
+  {PIX_FMT_RGB32, PIX_FMT_NV12, rgb32_to_nv12},
+  {PIX_FMT_RGB32, PIX_FMT_NV21, rgb32_to_nv21},
   {PIX_FMT_RGB32, PIX_FMT_GRAY8, rgb32_to_gray},
+  {PIX_FMT_RGB32, PIX_FMT_GRAY16_L, rgb32_to_gray16_l},
+  {PIX_FMT_RGB32, PIX_FMT_GRAY16_B, rgb32_to_gray16_b},
 
   {PIX_FMT_xRGB32, PIX_FMT_RGB24, xrgb32_to_rgb24},
   {PIX_FMT_xRGB32, PIX_FMT_PAL8, xrgb32_to_pal8},
   {PIX_FMT_xRGB32, PIX_FMT_YUV420P, xrgb32_to_yuv420p},
+  {PIX_FMT_xRGB32, PIX_FMT_NV12, xrgb32_to_nv12},
+  {PIX_FMT_xRGB32, PIX_FMT_NV21, xrgb32_to_nv21},
   {PIX_FMT_xRGB32, PIX_FMT_GRAY8, xrgb32_to_gray},
+  {PIX_FMT_xRGB32, PIX_FMT_GRAY16_L, xrgb32_to_gray16_l},
+  {PIX_FMT_xRGB32, PIX_FMT_GRAY16_B, xrgb32_to_gray16_b},
 
   {PIX_FMT_RGBA32, PIX_FMT_BGRA32, rgba32_to_bgra32},
   {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32},
@@ -2130,48 +2767,84 @@
   {PIX_FMT_RGBA32, PIX_FMT_RGB555, rgba32_to_rgb555},
   {PIX_FMT_RGBA32, PIX_FMT_PAL8, rgba32_to_pal8},
   {PIX_FMT_RGBA32, PIX_FMT_YUV420P, rgba32_to_yuv420p},
+  {PIX_FMT_RGBA32, PIX_FMT_NV12, rgba32_to_nv12},
+  {PIX_FMT_RGBA32, PIX_FMT_NV21, rgba32_to_nv21},
   {PIX_FMT_RGBA32, PIX_FMT_GRAY8, rgba32_to_gray},
+  {PIX_FMT_RGBA32, PIX_FMT_GRAY16_L, rgba32_to_gray16_l},
+  {PIX_FMT_RGBA32, PIX_FMT_GRAY16_B, rgba32_to_gray16_b},
   {PIX_FMT_RGBA32, PIX_FMT_AYUV4444, rgba32_to_ayuv4444},
 
   {PIX_FMT_BGR24, PIX_FMT_RGB24, bgr24_to_rgb24},
   {PIX_FMT_BGR24, PIX_FMT_YUV420P, bgr24_to_yuv420p},
+  {PIX_FMT_BGR24, PIX_FMT_NV12, bgr24_to_nv12},
+  {PIX_FMT_BGR24, PIX_FMT_NV21, bgr24_to_nv21},
   {PIX_FMT_BGR24, PIX_FMT_GRAY8, bgr24_to_gray},
+  {PIX_FMT_BGR24, PIX_FMT_GRAY16_L, bgr24_to_gray16_l},
+  {PIX_FMT_BGR24, PIX_FMT_GRAY16_B, bgr24_to_gray16_b},
 
   {PIX_FMT_BGR32, PIX_FMT_RGB24, bgr32_to_rgb24},
   {PIX_FMT_BGR32, PIX_FMT_RGBA32, bgr32_to_rgba32},
   {PIX_FMT_BGR32, PIX_FMT_YUV420P, bgr32_to_yuv420p},
+  {PIX_FMT_BGR32, PIX_FMT_NV12, bgr32_to_nv12},
+  {PIX_FMT_BGR32, PIX_FMT_NV21, bgr32_to_nv21},
   {PIX_FMT_BGR32, PIX_FMT_GRAY8, bgr32_to_gray},
+  {PIX_FMT_BGR32, PIX_FMT_GRAY16_L, bgr32_to_gray16_l},
+  {PIX_FMT_BGR32, PIX_FMT_GRAY16_B, bgr32_to_gray16_b},
 
   {PIX_FMT_BGRx32, PIX_FMT_RGB24, bgrx32_to_rgb24},
   {PIX_FMT_BGRx32, PIX_FMT_RGBA32, bgrx32_to_rgba32},
   {PIX_FMT_BGRx32, PIX_FMT_YUV420P, bgrx32_to_yuv420p},
+  {PIX_FMT_BGRx32, PIX_FMT_NV12, bgrx32_to_nv12},
+  {PIX_FMT_BGRx32, PIX_FMT_NV21, bgrx32_to_nv21},
   {PIX_FMT_BGRx32, PIX_FMT_GRAY8, bgrx32_to_gray},
+  {PIX_FMT_BGRx32, PIX_FMT_GRAY16_L, bgrx32_to_gray16_l},
+  {PIX_FMT_BGRx32, PIX_FMT_GRAY16_B, bgrx32_to_gray16_b},
 
   {PIX_FMT_BGRA32, PIX_FMT_RGB24, bgra32_to_rgb24},
   {PIX_FMT_BGRA32, PIX_FMT_RGBA32, bgra32_to_rgba32},
   {PIX_FMT_BGRA32, PIX_FMT_YUV420P, bgra32_to_yuv420p},
+  {PIX_FMT_BGRA32, PIX_FMT_NV12, bgra32_to_nv12},
+  {PIX_FMT_BGRA32, PIX_FMT_NV21, bgra32_to_nv21},
   {PIX_FMT_BGRA32, PIX_FMT_GRAY8, bgra32_to_gray},
+  {PIX_FMT_BGRA32, PIX_FMT_GRAY16_L, bgra32_to_gray16_l},
+  {PIX_FMT_BGRA32, PIX_FMT_GRAY16_B, bgra32_to_gray16_b},
   {PIX_FMT_BGRA32, PIX_FMT_AYUV4444, bgra32_to_ayuv4444},
 
   {PIX_FMT_ABGR32, PIX_FMT_RGB24, abgr32_to_rgb24},
   {PIX_FMT_ABGR32, PIX_FMT_RGBA32, abgr32_to_rgba32},
   {PIX_FMT_ABGR32, PIX_FMT_YUV420P, abgr32_to_yuv420p},
+  {PIX_FMT_ABGR32, PIX_FMT_NV12, abgr32_to_nv12},
+  {PIX_FMT_ABGR32, PIX_FMT_NV21, abgr32_to_nv21},
   {PIX_FMT_ABGR32, PIX_FMT_GRAY8, abgr32_to_gray},
+  {PIX_FMT_ABGR32, PIX_FMT_GRAY16_L, abgr32_to_gray16_l},
+  {PIX_FMT_ABGR32, PIX_FMT_GRAY16_B, abgr32_to_gray16_b},
 
   {PIX_FMT_ARGB32, PIX_FMT_RGB24, argb32_to_rgb24},
   {PIX_FMT_ARGB32, PIX_FMT_RGBA32, argb32_to_rgba32},
   {PIX_FMT_ARGB32, PIX_FMT_YUV420P, argb32_to_yuv420p},
+  {PIX_FMT_ARGB32, PIX_FMT_NV12, argb32_to_nv12},
+  {PIX_FMT_ARGB32, PIX_FMT_NV21, argb32_to_nv21},
   {PIX_FMT_ARGB32, PIX_FMT_GRAY8, argb32_to_gray},
+  {PIX_FMT_ARGB32, PIX_FMT_GRAY16_L, argb32_to_gray16_l},
+  {PIX_FMT_ARGB32, PIX_FMT_GRAY16_B, argb32_to_gray16_b},
 
   {PIX_FMT_RGB555, PIX_FMT_RGB24, rgb555_to_rgb24},
   {PIX_FMT_RGB555, PIX_FMT_RGB32, rgb555_to_rgba32},
   {PIX_FMT_RGB555, PIX_FMT_RGBA32, rgb555_to_rgba32},
   {PIX_FMT_RGB555, PIX_FMT_YUV420P, rgb555_to_yuv420p},
+  {PIX_FMT_RGB555, PIX_FMT_NV12, rgb555_to_nv12},
+  {PIX_FMT_RGB555, PIX_FMT_NV21, rgb555_to_nv21},
   {PIX_FMT_RGB555, PIX_FMT_GRAY8, rgb555_to_gray},
+  {PIX_FMT_RGB555, PIX_FMT_GRAY16_L, rgb555_to_gray16_l},
+  {PIX_FMT_RGB555, PIX_FMT_GRAY16_B, rgb555_to_gray16_b},
 
   {PIX_FMT_RGB565, PIX_FMT_RGB24, rgb565_to_rgb24},
   {PIX_FMT_RGB565, PIX_FMT_YUV420P, rgb565_to_yuv420p},
+  {PIX_FMT_RGB565, PIX_FMT_NV12, rgb565_to_nv12},
+  {PIX_FMT_RGB565, PIX_FMT_NV21, rgb565_to_nv21},
   {PIX_FMT_RGB565, PIX_FMT_GRAY8, rgb565_to_gray},
+  {PIX_FMT_RGB565, PIX_FMT_GRAY16_L, rgb565_to_gray16_l},
+  {PIX_FMT_RGB565, PIX_FMT_GRAY16_B, rgb565_to_gray16_b},
 
   {PIX_FMT_GRAY8, PIX_FMT_RGB555, gray_to_rgb555},
   {PIX_FMT_GRAY8, PIX_FMT_RGB565, gray_to_rgb565},
@@ -2187,11 +2860,43 @@
   {PIX_FMT_GRAY8, PIX_FMT_ABGR32, gray_to_abgr32},
   {PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, gray_to_monowhite},
   {PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, gray_to_monoblack},
+  {PIX_FMT_GRAY8, PIX_FMT_GRAY16_L, gray_to_gray16_l},
+  {PIX_FMT_GRAY8, PIX_FMT_GRAY16_B, gray_to_gray16_b},
 
   {PIX_FMT_MONOWHITE, PIX_FMT_GRAY8, monowhite_to_gray},
 
   {PIX_FMT_MONOBLACK, PIX_FMT_GRAY8, monoblack_to_gray},
 
+  {PIX_FMT_GRAY16_L, PIX_FMT_GRAY8, gray16_l_to_gray},
+  {PIX_FMT_GRAY16_L, PIX_FMT_RGB555, gray16_l_to_rgb555},
+  {PIX_FMT_GRAY16_L, PIX_FMT_RGB565, gray16_l_to_rgb565},
+  {PIX_FMT_GRAY16_L, PIX_FMT_BGR24, gray16_l_to_bgr24},
+  {PIX_FMT_GRAY16_L, PIX_FMT_RGB24, gray16_l_to_rgb24},
+  {PIX_FMT_GRAY16_L, PIX_FMT_BGR32, gray16_l_to_bgr32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_RGB32, gray16_l_to_rgb32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_xRGB32, gray16_l_to_xrgb32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_BGRx32, gray16_l_to_bgrx32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_ABGR32, gray16_l_to_abgr32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_ARGB32, gray16_l_to_argb32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_BGRA32, gray16_l_to_bgra32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_RGBA32, gray16_l_to_rgba32},
+  {PIX_FMT_GRAY16_L, PIX_FMT_GRAY16_B, gray16_b_to_gray16_l},
+
+  {PIX_FMT_GRAY16_B, PIX_FMT_GRAY8, gray16_b_to_gray},
+  {PIX_FMT_GRAY16_B, PIX_FMT_RGB555, gray16_b_to_rgb555},
+  {PIX_FMT_GRAY16_B, PIX_FMT_RGB565, gray16_b_to_rgb565},
+  {PIX_FMT_GRAY16_B, PIX_FMT_BGR24, gray16_b_to_bgr24},
+  {PIX_FMT_GRAY16_B, PIX_FMT_RGB24, gray16_b_to_rgb24},
+  {PIX_FMT_GRAY16_B, PIX_FMT_BGR32, gray16_b_to_bgr32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_RGB32, gray16_b_to_rgb32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_xRGB32, gray16_b_to_xrgb32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_BGRx32, gray16_b_to_bgrx32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_ABGR32, gray16_b_to_abgr32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_ARGB32, gray16_b_to_argb32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_BGRA32, gray16_b_to_bgra32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_RGBA32, gray16_b_to_rgba32},
+  {PIX_FMT_GRAY16_B, PIX_FMT_GRAY16_L, gray16_b_to_gray16_l},
+
   {PIX_FMT_PAL8, PIX_FMT_RGB555, pal8_to_rgb555},
   {PIX_FMT_PAL8, PIX_FMT_RGB565, pal8_to_rgb565},
   {PIX_FMT_PAL8, PIX_FMT_BGR24, pal8_to_bgr24},
@@ -2207,9 +2912,10 @@
 
   {PIX_FMT_UYVY411, PIX_FMT_YUV411P, uyvy411_to_yuv411p},
 
+  {PIX_FMT_V308, PIX_FMT_RGB24, v308_to_rgb24},
+
   {PIX_FMT_AYUV4444, PIX_FMT_RGBA32, ayuv4444_to_rgba32},
-
-  {PIX_FMT_AYUV4444, PIX_FMT_RGB24, ayuv4444_to_rgb24}
+  {PIX_FMT_AYUV4444, PIX_FMT_RGB24, ayuv4444_to_rgb24},
 };
 
 static ConvertEntry *
@@ -2450,7 +3156,8 @@
   if (src_pix_fmt == PIX_FMT_YUV422 || dst_pix_fmt == PIX_FMT_YUV422) {
     /* specific case: convert to YUV422P first */
     int_pix_fmt = PIX_FMT_YUV422P;
-  } else if (src_pix_fmt == PIX_FMT_UYVY422 || dst_pix_fmt == PIX_FMT_UYVY422) {
+  } else if (src_pix_fmt == PIX_FMT_UYVY422 || dst_pix_fmt == PIX_FMT_UYVY422 ||
+      src_pix_fmt == PIX_FMT_YVYU422 || dst_pix_fmt == PIX_FMT_YVYU422) {
     /* specific case: convert to YUV422P first */
     int_pix_fmt = PIX_FMT_YUV422P;
   } else if (src_pix_fmt == PIX_FMT_UYVY411 || dst_pix_fmt == PIX_FMT_UYVY411) {
@@ -2536,7 +3243,7 @@
 int
 img_get_alpha_info (const AVPicture * src, int pix_fmt, int width, int height)
 {
-  PixFmtInfo *pf = get_pix_fmt_info (pix_fmt);
+  const PixFmtInfo *pf;
   int ret;
 
   pf = get_pix_fmt_info (pix_fmt);
@@ -2678,6 +3385,7 @@
   }
 #endif
 }
+
 static void
 deinterlace_line_inplace (uint8_t * lum_m4, uint8_t * lum_m3, uint8_t * lum_m2,
     uint8_t * lum_m1, uint8_t * lum, int size)
--- a/gst_plugins_base/gst/ffmpegcolorspace/imgconvert_template.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/ffmpegcolorspace/imgconvert_template.h	Fri Apr 16 15:15:52 2010 +0300
@@ -103,7 +103,7 @@
         /* handle width */
         if (w) {
             YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
-            /* output 2 pixels */
+            /* output 2 pixel */
             YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
             RGB_OUT(d1, r, g, b);
             d1 += BPP;
@@ -115,6 +115,182 @@
     }
 }
 
+static void glue(nv12_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+                                        int width, int height)
+{
+    const uint8_t *y1_ptr, *y2_ptr, *c_ptr;
+    uint8_t *d, *d1, *d2;
+    int w, y, cb, cr, r_add, g_add, b_add;
+    uint8_t *cm = cropTbl + MAX_NEG_CROP;
+    unsigned int r, g, b;
+    int c_wrap = src->linesize[1] - ((width+1) & ~0x01);
+
+    d = dst->data[0];
+    y1_ptr = src->data[0];
+    c_ptr = src->data[1];
+    for(;height >= 2; height -= 2) {
+        d1 = d;
+        d2 = d + dst->linesize[0];
+        y2_ptr = y1_ptr + src->linesize[0];
+        for(w = width; w >= 2; w -= 2) {
+            YUV_TO_RGB1_CCIR(c_ptr[0], c_ptr[1]);
+            /* output 4 pixels */
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
+            RGB_OUT(d1 + BPP, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
+            RGB_OUT(d2, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]);
+            RGB_OUT(d2 + BPP, r, g, b);
+
+            d1 += 2 * BPP;
+            d2 += 2 * BPP;
+
+            y1_ptr += 2;
+            y2_ptr += 2;
+            c_ptr += 2;
+        }
+        /* handle odd width */
+        if (w) {
+            YUV_TO_RGB1_CCIR(c_ptr[0], c_ptr[1]);
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
+            RGB_OUT(d2, r, g, b);
+            d1 += BPP;
+            d2 += BPP;
+            y1_ptr++;
+            y2_ptr++;
+            c_ptr += 2;
+        }
+        d += 2 * dst->linesize[0];
+        y1_ptr += 2 * src->linesize[0] - width;
+        c_ptr += c_wrap;
+    }
+    /* handle odd height */
+    if (height) {
+        d1 = d;
+        for(w = width; w >= 2; w -= 2) {
+            YUV_TO_RGB1_CCIR(c_ptr[0], c_ptr[1]);
+            /* output 2 pixels */
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
+            RGB_OUT(d1 + BPP, r, g, b);
+
+            d1 += 2 * BPP;
+
+            y1_ptr += 2;
+            c_ptr += 2;
+        }
+        /* handle odd width */
+        if (w) {
+            YUV_TO_RGB1_CCIR(c_ptr[0], c_ptr[1]);
+            /* output 1 pixel */
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+            d1 += BPP;
+
+            y1_ptr++;
+            c_ptr += 2;
+        }
+    }
+}
+
+static void glue(nv21_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+                                        int width, int height)
+{
+    const uint8_t *y1_ptr, *y2_ptr, *c_ptr;
+    uint8_t *d, *d1, *d2;
+    int w, y, cb, cr, r_add, g_add, b_add;
+    uint8_t *cm = cropTbl + MAX_NEG_CROP;
+    unsigned int r, g, b;
+    int c_wrap = src->linesize[1] - ((width+1) & ~0x01);
+
+    d = dst->data[0];
+    y1_ptr = src->data[0];
+    c_ptr = src->data[1];
+    for(;height >= 2; height -= 2) {
+        d1 = d;
+        d2 = d + dst->linesize[0];
+        y2_ptr = y1_ptr + src->linesize[0];
+        for(w = width; w >= 2; w -= 2) {
+            YUV_TO_RGB1_CCIR(c_ptr[1], c_ptr[0]);
+            /* output 4 pixels */
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
+            RGB_OUT(d1 + BPP, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
+            RGB_OUT(d2, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]);
+            RGB_OUT(d2 + BPP, r, g, b);
+
+            d1 += 2 * BPP;
+            d2 += 2 * BPP;
+
+            y1_ptr += 2;
+            y2_ptr += 2;
+            c_ptr += 2;
+        }
+        /* handle odd width */
+        if (w) {
+            YUV_TO_RGB1_CCIR(c_ptr[1], c_ptr[0]);
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
+            RGB_OUT(d2, r, g, b);
+            d1 += BPP;
+            d2 += BPP;
+            y1_ptr++;
+            y2_ptr++;
+            c_ptr += 2;
+        }
+        d += 2 * dst->linesize[0];
+        y1_ptr += 2 * src->linesize[0] - width;
+        c_ptr += c_wrap;
+    }
+    /* handle odd height */
+    if (height) {
+        d1 = d;
+        for(w = width; w >= 2; w -= 2) {
+            YUV_TO_RGB1_CCIR(c_ptr[1], c_ptr[0]);
+            /* output 2 pixels */
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
+            RGB_OUT(d1 + BPP, r, g, b);
+
+            d1 += 2 * BPP;
+
+            y1_ptr += 2;
+            c_ptr += 2;
+        }
+        /* handle odd width */
+        if (w) {
+            YUV_TO_RGB1_CCIR(c_ptr[1], c_ptr[0]);
+            /* output 1 pixel */
+            YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+            RGB_OUT(d1, r, g, b);
+            d1 += BPP;
+
+            y1_ptr++;
+            c_ptr += 2;
+        }
+    }
+}
+
 static void glue(yuvj420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
                                          int width, int height)
 {
@@ -317,6 +493,214 @@
     }
 }
 
+static void glue(RGB_NAME, _to_nv12)(AVPicture *dst, const AVPicture *src,
+                                        int width, int height)
+{
+    int wrap, wrap3;
+    int r, g, b, r1, g1, b1, w;
+    uint8_t *lum, *c;
+    const uint8_t *p;
+
+    lum = dst->data[0];
+    c = dst->data[1];
+
+    wrap = dst->linesize[0];
+    wrap3 = src->linesize[0];
+    p = src->data[0];
+    for(;height>=2;height -= 2) {
+        for(w = width; w >= 2; w -= 2) {
+            RGB_IN(r, g, b, p);
+            r1 = r;
+            g1 = g;
+            b1 = b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+            RGB_IN(r, g, b, p + BPP);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[1] = RGB_TO_Y_CCIR(r, g, b);
+            p += wrap3;
+            lum += wrap;
+
+            RGB_IN(r, g, b, p);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+            RGB_IN(r, g, b, p + BPP);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[1] = RGB_TO_Y_CCIR(r, g, b);
+
+            c[0] = RGB_TO_U_CCIR(r1, g1, b1, 2);
+            c[1] = RGB_TO_V_CCIR(r1, g1, b1, 2);
+
+
+            c += 2;
+            p += -wrap3 + 2 * BPP;
+            lum += -wrap + 2;
+        }
+	/* handle odd width */
+        if (w) {
+            RGB_IN(r, g, b, p);
+            r1 = r;
+            g1 = g;
+            b1 = b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+            p += wrap3;
+            lum += wrap;
+            RGB_IN(r, g, b, p);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+            c[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
+            c[1] = RGB_TO_V_CCIR(r1, g1, b1, 1);
+            c += 2;
+            p += -wrap3 + BPP;
+            lum += -wrap + 1;
+        }
+        p += wrap3 + (wrap3 - width * BPP);
+        lum += wrap + (wrap - width);
+        c += dst->linesize[1] - width;
+    }
+    /* handle odd height */
+    if (height) {
+        for(w = width; w >= 2; w -= 2) {
+            RGB_IN(r, g, b, p);
+            r1 = r;
+            g1 = g;
+            b1 = b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+            RGB_IN(r, g, b, p + BPP);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[1] = RGB_TO_Y_CCIR(r, g, b);
+            c[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
+            c[1] = RGB_TO_V_CCIR(r1, g1, b1, 1);
+            c += 2;
+            p += 2 * BPP;
+            lum += 2;
+        }
+	/* handle odd width */
+        if (w) {
+            RGB_IN(r, g, b, p);
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+            c[0] = RGB_TO_U_CCIR(r, g, b, 0);
+            c[1] = RGB_TO_V_CCIR(r, g, b, 0);
+        }
+    }
+}
+
+static void glue(RGB_NAME, _to_nv21)(AVPicture *dst, const AVPicture *src,
+                                        int width, int height)
+{
+    int wrap, wrap3;
+    int r, g, b, r1, g1, b1, w;
+    uint8_t *lum, *c;
+    const uint8_t *p;
+
+    lum = dst->data[0];
+    c = dst->data[1];
+
+    wrap = dst->linesize[0];
+    wrap3 = src->linesize[0];
+    p = src->data[0];
+    for(;height>=2;height -= 2) {
+        for(w = width; w >= 2; w -= 2) {
+            RGB_IN(r, g, b, p);
+            r1 = r;
+            g1 = g;
+            b1 = b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+            RGB_IN(r, g, b, p + BPP);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[1] = RGB_TO_Y_CCIR(r, g, b);
+            p += wrap3;
+            lum += wrap;
+
+            RGB_IN(r, g, b, p);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+            RGB_IN(r, g, b, p + BPP);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[1] = RGB_TO_Y_CCIR(r, g, b);
+
+            c[1] = RGB_TO_U_CCIR(r1, g1, b1, 2);
+            c[0] = RGB_TO_V_CCIR(r1, g1, b1, 2);
+
+
+            c += 2;
+            p += -wrap3 + 2 * BPP;
+            lum += -wrap + 2;
+        }
+	/* handle odd width */
+        if (w) {
+            RGB_IN(r, g, b, p);
+            r1 = r;
+            g1 = g;
+            b1 = b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+            p += wrap3;
+            lum += wrap;
+            RGB_IN(r, g, b, p);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+            c[1] = RGB_TO_U_CCIR(r1, g1, b1, 1);
+            c[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
+            c += 2;
+            p += -wrap3 + BPP;
+            lum += -wrap + 1;
+        }
+        p += wrap3 + (wrap3 - width * BPP);
+        lum += wrap + (wrap - width);
+        c += dst->linesize[1] - width;
+    }
+    /* handle odd height */
+    if (height) {
+        for(w = width; w >= 2; w -= 2) {
+            RGB_IN(r, g, b, p);
+            r1 = r;
+            g1 = g;
+            b1 = b;
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+            RGB_IN(r, g, b, p + BPP);
+            r1 += r;
+            g1 += g;
+            b1 += b;
+            lum[1] = RGB_TO_Y_CCIR(r, g, b);
+            c[1] = RGB_TO_U_CCIR(r1, g1, b1, 1);
+            c[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
+            c += 2;
+            p += 2 * BPP;
+            lum += 2;
+        }
+	/* handle odd width */
+        if (w) {
+            RGB_IN(r, g, b, p);
+            lum[0] = RGB_TO_Y_CCIR(r, g, b);
+            c[1] = RGB_TO_U_CCIR(r, g, b, 0);
+            c[0] = RGB_TO_V_CCIR(r, g, b, 0);
+        }
+    }
+}
+
 static void glue(RGB_NAME, _to_gray)(AVPicture *dst, const AVPicture *src,
                                      int width, int height)
 {
@@ -369,6 +753,110 @@
     }
 }
 
+static void glue(RGB_NAME, _to_gray16_l)(AVPicture *dst, const AVPicture *src,
+                                     int width, int height)
+{
+    const unsigned char *p;
+    unsigned char *q;
+    int r, g, b, dst_wrap, src_wrap;
+    int x, y;
+
+    p = src->data[0];
+    src_wrap = src->linesize[0] - BPP * width;
+
+    q = dst->data[0];
+    dst_wrap = dst->linesize[0] - 2 * width;
+
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            RGB_IN(r, g, b, p);
+            GST_WRITE_UINT16_LE (q, RGB_TO_Y(r, g, b) << 8);
+            q += 2;
+            p += BPP;
+        }
+        p += src_wrap;
+        q += dst_wrap;
+    }
+}
+
+static void glue(gray16_l_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+                                     int width, int height)
+{
+    const unsigned char *p;
+    unsigned char *q;
+    int r, dst_wrap, src_wrap;
+    int x, y;
+
+    p = src->data[0];
+    src_wrap = src->linesize[0] - 2 * width;
+
+    q = dst->data[0];
+    dst_wrap = dst->linesize[0] - BPP * width;
+
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            r = GST_READ_UINT16_LE (p) >> 8;
+            RGB_OUT(q, r, r, r);
+            q += BPP;
+            p += 2;
+        }
+        p += src_wrap;
+        q += dst_wrap;
+    }
+}
+
+static void glue(RGB_NAME, _to_gray16_b)(AVPicture *dst, const AVPicture *src,
+                                     int width, int height)
+{
+    const unsigned char *p;
+    unsigned char *q;
+    int r, g, b, dst_wrap, src_wrap;
+    int x, y;
+
+    p = src->data[0];
+    src_wrap = src->linesize[0] - BPP * width;
+
+    q = dst->data[0];
+    dst_wrap = dst->linesize[0] - 2 * width;
+
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            RGB_IN(r, g, b, p);
+            GST_WRITE_UINT16_BE (q, RGB_TO_Y(r, g, b) << 8);
+            q += 2;
+            p += BPP;
+        }
+        p += src_wrap;
+        q += dst_wrap;
+    }
+}
+
+static void glue(gray16_b_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+                                     int width, int height)
+{
+    const unsigned char *p;
+    unsigned char *q;
+    int r, dst_wrap, src_wrap;
+    int x, y;
+
+    p = src->data[0];
+    src_wrap = src->linesize[0] - 2 * width;
+
+    q = dst->data[0];
+    dst_wrap = dst->linesize[0] - BPP * width;
+
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            r = GST_READ_UINT16_BE (p) >> 8;
+            RGB_OUT(q, r, r, r);
+            q += BPP;
+            p += 2;
+        }
+        p += src_wrap;
+        q += dst_wrap;
+    }
+}
+
 static void glue(pal8_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
                                      int width, int height)
 {
@@ -918,6 +1406,58 @@
         d += dst_wrap;
     }
 }
+
+static void v308_to_rgb24(AVPicture *dst, const AVPicture *src,
+                             int width, int height)
+{
+    uint8_t *s, *d, *d1, *s1;
+    int w, y, cb, cr, r_add, g_add, b_add;
+    uint8_t *cm = cropTbl + MAX_NEG_CROP;
+    unsigned int r, g, b;
+
+    d = dst->data[0];
+    s = src->data[0];
+    for(;height > 0; height --) {
+        d1 = d;
+        s1 = s;
+        for(w = width; w > 0; w--) {
+            YUV_TO_RGB1_CCIR(s1[1], s1[2]);
+
+            YUV_TO_RGB2_CCIR(r, g, b, s1[0]);
+            RGB_OUT(d1, r, g, b);
+            d1 += BPP;
+            s1 += 3;
+        }
+        d += dst->linesize[0];
+        s += src->linesize[0];
+    }
+}
+
+static void rgb24_to_v308(AVPicture *dst, const AVPicture *src,
+                             int width, int height)
+{
+    int src_wrap, dst_wrap, x, y;
+    int r, g, b;
+    uint8_t *d;
+    const uint8_t *p;
+
+    src_wrap = src->linesize[0] - width * BPP;
+    dst_wrap = dst->linesize[0] - width * 3;
+    d = dst->data[0];
+    p = src->data[0];
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            RGB_IN(r, g, b, p);
+            d[0] = RGB_TO_Y_CCIR(r, g, b);
+            d[1] = RGB_TO_U_CCIR(r, g, b, 0);
+            d[2] = RGB_TO_V_CCIR(r, g, b, 0);
+            p += BPP;
+            d += 3;
+        }
+        p += src_wrap;
+        d += dst_wrap;
+    }
+}
 #endif /* FMT_RGB24 */
 
 #if defined(FMT_RGB24) || defined(FMT_RGBA32)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/gdp/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,22 @@
+Sample pipelines:
+- replacing tcpserversink protocol=gdp with gdppay ! tcpserversink:
+  - raw audio:
+    - server:
+      gst-launch -v audiotestsrc ! gdppay version=0.2 ! tcpserversink
+    - client:
+      gst-launch -v tcpclientsrc protocol=gdp ! alsasink sync=FALSE
+
+  - vorbis packets:
+    - server:
+      gst-launch -v audiotestsrc ! audioconvert ! vorbisenc ! gdppay version=0.2 ! tcpserversink
+    - client:
+      gst-launch -v tcpclientsrc protocol=gdp ! vorbisdec ! audioconvert ! alsasink sync=FALSE
+
+  - ogg packets:
+    - server:
+      gst-launch -v audiotestsrc ! audioconvert ! vorbisenc ! oggmux ! gdppay version=0.2 ! tcpserversink
+    - client:
+      gst-launch -v tcpclientsrc protocol=gdp ! oggdemux ! vorbisdec ! audioconvert ! alsasink sync=FALSE
+
+  In all the client pipelines, tcpclientsrc protocol=gdp can be replaced with
+  tcpclientsrc ! gdpdepay
--- a/gst_plugins_base/gst/gdp/gstgdpdepay.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/gdp/gstgdpdepay.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,18 +21,14 @@
  * SECTION:element-gdpdepay
  * @see_also: gdppay
  *
- * <refsect2>
- * <para>
  * This element depayloads GStreamer Data Protocol buffers back to deserialized
  * buffers and events.
- * </para>
- * <para>
- * <programlisting>
+ *
+ * <refsect2>
+ * |[
  * gst-launch -v -m filesrc location=test.gdp ! gdpdepay ! xvimagesink
- * </programlisting>
- * This pipeline plays back a serialized video stream as created in the
+ * ]| This pipeline plays back a serialized video stream as created in the
  * example for gdppay.
- * </para>
  * </refsect2>
  */
 
@@ -260,8 +256,8 @@
         this->header = header;
 
         GST_LOG_OBJECT (this,
-            "read GDP header, payload size %d, switching to state PAYLOAD",
-            this->payload_length);
+            "read GDP header, payload size %d, payload type %d, switching to state PAYLOAD",
+            this->payload_length, this->payload_type);
         this->state = GST_GDP_DEPAY_STATE_PAYLOAD;
         break;
       }
@@ -287,6 +283,13 @@
         } else {
           goto wrong_type;
         }
+
+        if (this->payload_length
+            && (!gst_dp_validate_payload (GST_DP_HEADER_LENGTH, this->header,
+                    gst_adapter_peek (this->adapter, this->payload_length)))) {
+          goto payload_validate_error;
+        }
+
         break;
       }
       case GST_GDP_DEPAY_STATE_BUFFER:
@@ -392,6 +395,13 @@
     ret = GST_FLOW_ERROR;
     goto done;
   }
+payload_validate_error:
+  {
+    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
+        ("GDP packet payload does not validate"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
 wrong_type:
   {
     GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
--- a/gst_plugins_base/gst/gdp/gstgdpdepay.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/gdp/gstgdpdepay.h	Fri Apr 16 15:15:52 2010 +0300
@@ -48,6 +48,11 @@
 typedef struct _GstGDPDepay GstGDPDepay;
 typedef struct _GstGDPDepayClass GstGDPDepayClass;
 
+/**
+ * GstGDPDepay:
+ *
+ * Private gdpdepay element structure.
+ */
 struct _GstGDPDepay
 {
   GstElement element;
--- a/gst_plugins_base/gst/gdp/gstgdppay.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/gdp/gstgdppay.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,18 +21,14 @@
  * SECTION:element-gdppay
  * @see_also: gdpdepay
  *
- * <refsect2>
- * <para>
  * This element payloads GStreamer buffers and events using the
  * GStreamer Data Protocol.
- * </para>
- * <para>
- * <programlisting>
+ *
+ * <refsect2>
+ * |[
  * gst-launch -v -m videotestsrc num-buffers=50 ! gdppay ! filesink location=test.gdp
- * </programlisting>
- * This pipeline creates a serialized video stream that can be played back
+ * ]| This pipeline creates a serialized video stream that can be played back
  * with the example shown in gdpdepay.
- * </para>
  * </refsect2>
  */
 
@@ -86,9 +82,11 @@
     GST_TYPE_ELEMENT, _do_init);
 
 static void gst_gdp_pay_reset (GstGDPPay * this);
+
 static GstFlowReturn gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer);
 
 static gboolean gst_gdp_pay_src_event (GstPad * pad, GstEvent * event);
+
 static gboolean gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event);
 
 static GstStateChangeReturn gst_gdp_pay_change_state (GstElement *
@@ -118,6 +116,7 @@
 gst_gdp_pay_class_init (GstGDPPayClass * klass)
 {
   GObjectClass *gobject_class;
+
   GstElementClass *gstelement_class;
 
   gobject_class = (GObjectClass *) klass;
@@ -130,15 +129,16 @@
   g_object_class_install_property (gobject_class, PROP_CRC_HEADER,
       g_param_spec_boolean ("crc-header", "CRC Header",
           "Calculate and store a CRC checksum on the header",
-          DEFAULT_CRC_HEADER, G_PARAM_READWRITE));
+          DEFAULT_CRC_HEADER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_CRC_PAYLOAD,
       g_param_spec_boolean ("crc-payload", "CRC Payload",
           "Calculate and store a CRC checksum on the payload",
-          DEFAULT_CRC_PAYLOAD, G_PARAM_READWRITE));
+          DEFAULT_CRC_PAYLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_VERSION,
       g_param_spec_enum ("version", "Version",
           "Version of the GStreamer Data Protocol",
-          GST_TYPE_DP_VERSION, DEFAULT_VERSION, G_PARAM_READWRITE));
+          GST_TYPE_DP_VERSION, DEFAULT_VERSION,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_gdp_pay_change_state);
 }
@@ -189,10 +189,11 @@
     GstBuffer *buffer;
 
     buffer = GST_BUFFER_CAST (this->queue->data);
-    GST_DEBUG_OBJECT (this, "Pushing queued GDP buffer %p", buffer);
 
     /* delete buffer from queue now */
     this->queue = g_list_delete_link (this->queue, this->queue);
+
+    gst_buffer_unref (buffer);
   }
   if (this->caps) {
     gst_caps_unref (this->caps);
@@ -227,8 +228,11 @@
 gst_gdp_buffer_from_caps (GstGDPPay * this, GstCaps * caps)
 {
   GstBuffer *headerbuf;
+
   GstBuffer *payloadbuf;
+
   guint8 *header, *payload;
+
   guint len;
 
   if (!this->packetizer->packet_from_caps (caps, this->header_flag, &len,
@@ -259,7 +263,9 @@
 gst_gdp_pay_buffer_from_buffer (GstGDPPay * this, GstBuffer * buffer)
 {
   GstBuffer *headerbuf;
+
   guint8 *header;
+
   guint len;
 
   if (!this->packetizer->header_from_buffer (buffer, this->header_flag, &len,
@@ -288,9 +294,13 @@
 gst_gdp_buffer_from_event (GstGDPPay * this, GstEvent * event)
 {
   GstBuffer *headerbuf;
+
   GstBuffer *payloadbuf;
+
   guint8 *header, *payload;
+
   guint len;
+
   gboolean ret;
 
   ret =
@@ -330,8 +340,11 @@
 
   /* We use copies of these to avoid circular refcounts */
   GstBuffer *new_segment_buf, *caps_buf, *tag_buf;
+
   GstStructure *structure;
+
   GstFlowReturn r = GST_FLOW_OK;
+
   gboolean version_one_zero = TRUE;
 
   GValue array = { 0 };
@@ -364,6 +377,7 @@
     GST_DEBUG_OBJECT (this, "1.0, appending copy of new segment buffer %p",
         this->new_segment_buf);
     new_segment_buf = gst_buffer_copy (this->new_segment_buf);
+    gst_buffer_set_caps (new_segment_buf, NULL);
     g_value_init (&value, GST_TYPE_BUFFER);
     gst_value_set_buffer (&value, new_segment_buf);
     gst_value_array_append_value (&array, &value);
@@ -375,6 +389,7 @@
       GST_DEBUG_OBJECT (this, "1.0, appending copy of tag buffer %p",
           this->tag_buf);
       tag_buf = gst_buffer_copy (this->tag_buf);
+      gst_buffer_set_caps (tag_buf, NULL);
       g_value_init (&value, GST_TYPE_BUFFER);
       gst_value_set_buffer (&value, tag_buf);
       gst_value_array_append_value (&array, &value);
@@ -386,6 +401,7 @@
   gst_gdp_stamp_buffer (this, this->caps_buf);
   GST_DEBUG_OBJECT (this, "appending copy of caps buffer %p", this->caps_buf);
   caps_buf = gst_buffer_copy (this->caps_buf);
+  gst_buffer_set_caps (caps_buf, NULL);
   g_value_init (&value, GST_TYPE_BUFFER);
   gst_value_set_buffer (&value, caps_buf);
   gst_value_array_append_value (&array, &value);
@@ -397,8 +413,11 @@
   structure = gst_caps_get_structure (this->caps, 0);
   if (gst_structure_has_field (structure, "streamheader")) {
     const GValue *sh;
+
     GArray *buffers;
+
     GstBuffer *buffer;
+
     int i;
 
     sh = gst_structure_get_value (structure, "streamheader");
@@ -408,6 +427,7 @@
         buffers->len);
     for (i = 0; i < buffers->len; ++i) {
       GValue *bufval;
+
       GstBuffer *outbuffer;
 
       bufval = &g_array_index (buffers, GValue, i);
@@ -466,6 +486,7 @@
     goto done;
   }
   if (this->tag_buf) {
+    gst_buffer_set_caps (this->tag_buf, caps);
     GST_DEBUG_OBJECT (this, "Pushing GDP tag buffer %p", this->tag_buf);
     /* we stored these bufs with refcount 1, so make sure we keep a ref */
     r = gst_pad_push (this->srcpad, gst_buffer_ref (this->tag_buf));
@@ -523,6 +544,7 @@
   if (this->sent_streamheader) {
     GST_LOG_OBJECT (this, "Pushing GDP buffer %p, caps %" GST_PTR_FORMAT,
         buffer, this->caps);
+    gst_buffer_set_caps (buffer, GST_PAD_CAPS (this->srcpad));
     return gst_pad_push (this->srcpad, buffer);
   }
 
@@ -539,8 +561,11 @@
 gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer)
 {
   GstGDPPay *this;
+
   GstCaps *caps;
+
   GstBuffer *outbuffer;
+
   GstFlowReturn ret;
 
   this = GST_GDP_PAY (gst_pad_get_parent (pad));
@@ -586,6 +611,9 @@
     GST_BUFFER_TIMESTAMP (outbuffer) = GST_BUFFER_TIMESTAMP (buffer);
     GST_BUFFER_DURATION (outbuffer) = 0;
     GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS);
+
+    if (this->caps_buf)
+      gst_buffer_unref (this->caps_buf);
     this->caps_buf = outbuffer;
     gst_gdp_pay_reset_streamheader (this);
   }
@@ -652,8 +680,11 @@
 gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event)
 {
   GstBuffer *outbuffer;
+
   GstGDPPay *this = GST_GDP_PAY (gst_pad_get_parent (pad));
+
   GstFlowReturn flowret;
+
   gboolean ret = TRUE;
 
   GST_DEBUG_OBJECT (this, "received event %p of type %s (%d)",
@@ -735,6 +766,7 @@
 gst_gdp_pay_src_event (GstPad * pad, GstEvent * event)
 {
   GstGDPPay *this;
+
   gboolean res = TRUE;
 
   this = GST_GDP_PAY (gst_pad_get_parent (pad));
@@ -815,6 +847,7 @@
 gst_gdp_pay_change_state (GstElement * element, GstStateChange transition)
 {
   GstStateChangeReturn ret;
+
   GstGDPPay *this = GST_GDP_PAY (element);
 
   switch (transition) {
--- a/gst_plugins_base/gst/gdp/gstgdppay.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/gdp/gstgdppay.h	Fri Apr 16 15:15:52 2010 +0300
@@ -38,6 +38,11 @@
 typedef struct _GstGDPPay GstGDPPay;
 typedef struct _GstGDPPayClass GstGDPPayClass;
 
+/**
+ * GstGDPPay:
+ *
+ * Private gdppay element structure.
+ */
 struct _GstGDPPay
 {
   GstElement element;
--- a/gst_plugins_base/gst/oil/liboil.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#ifndef __LIBOIL__
-#define __LIBOIL__
-
-#include<stdint.h>
-#include <stdio.h>
-
-IMPORT_C  void resample_linear_u8_ref (uint8_t *dest, uint8_t *src, int n, uint32_t *in);
-IMPORT_C  void resample_linear_argb_ref (uint32_t *d, uint32_t *s, int n, uint32_t *in);
-IMPORT_C  void merge_linear_argb_ref (uint32_t *d, uint32_t *s1, uint32_t *s2, uint32_t *src3, int n);
-//IMPORT_C  void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n);
-IMPORT_C  void oil_scalarmultiply_f32_ns (float * d, const float * s1, const float * s2_1, int n);
-IMPORT_C  void oil_merge_linear_argb (uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n);
-IMPORT_C  void oil_merge_linear_u8 (uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n);
-IMPORT_C  void oil_resample_linear_argb (uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2);
-IMPORT_C  void oil_resample_linear_u8 (uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2);
-IMPORT_C  void oil_splat_u8 (uint8_t * dest, int dstr, const uint8_t * s1_1, int n);
-IMPORT_C  void oil_splat_u8_ns (uint8_t * dest, const uint8_t * s1_1, int n);
-
-#endif
--- a/gst_plugins_base/gst/oil/stub.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,501 +0,0 @@
-#include"liboil.h"
-
-//Arun's changes
-typedef struct _OilFunctionImpl OilFunctionImpl;
-typedef struct _OilFunctionClass OilFunctionClass;
-typedef void (*OilTestFunction) (OilFunctionClass *klass,OilFunctionImpl *impl);
-
-#define OIL_CHECK_PROTOTYPE(a)
-/**
- * OilFunctionClass:
- *
- * An opaque structure representing a function class.
- *
- */
-struct _OilFunctionClass {
-  /*< private >*/
-	void *func;
-	const char *name;
-	const char *desc;
-	OilTestFunction test_func;
-
-	OilFunctionImpl *first_impl;
-	OilFunctionImpl *reference_impl;
-
-	OilFunctionImpl *chosen_impl;
-
-	const char *prototype;
-};
-
-
-/**
- * OilFunctionImpl:
- *
- * An opaque structure representing a function implementation.
- *
- */
-struct _OilFunctionImpl {
-  /*< private >*/
-    void *next;
-    OilFunctionClass *klass;
-    void *func;
-    unsigned int flags;
-    const char *name;
-        double profile_ave;
-        double profile_std;
-};
-
-#ifndef OIL_NO_CLASSES
-/**
- * OIL_DEFINE_CLASS_FULL:
- * @klass: name of class to declare (without oil_ prefix)
- * @string: prototype of class
- * @test: test function
- *
- * Defines a #OilFunctionClass structure for @klass.  Classes
- * defined this way will be automatically at Liboil initialization
- * time.
- */
-
-#define OIL_DEFINE_CLASS_FULL(klass, string, test) \
-OilFunctionClass _oil_function_class_ ## klass = { \
-	NULL, \
-	#klass , \
-	NULL, \
-        test, \
-        NULL, \
-        NULL, \
-        NULL, \
-        string \
-}; \
-OilFunctionClass *oil_function_class_ptr_ ## klass = \
-  &_oil_function_class_ ## klass
-#else
-#define OIL_DEFINE_CLASS_FULL(klass, string, test) \
-  OIL_DECLARE_CLASS(klass)
-#endif
-
-/**
- * OIL_DEFINE_CLASS:
- * @klass: name of class to declare (without oil_ prefix)
- * @string: prototype of class
- *
- * Defines a #OilFunctionClass structure for @klass.  Classes
- * defined this way will be automatically at Liboil initialization
- * time.
- */
-#define OIL_DEFINE_CLASS(klass, string) \
-  OIL_DEFINE_CLASS_FULL (klass, string, NULL)
-
-
-OIL_DEFINE_CLASS (scalarmultiply_f32_ns, "float *d, float *s1, float *s2_1, int n");
-
-OIL_DEFINE_CLASS_FULL (resample_linear_argb,
-    "uint32_t *d_n, uint32_t *s_2xn, int n, uint32_t *i_2",
-    NULL);
-
-OIL_DEFINE_CLASS_FULL (resample_linear_u8,
-    "uint8_t *d_n, uint8_t *s_2xn, int n, uint32_t *i_2",
-    NULL);
-
-OIL_DEFINE_CLASS_FULL (merge_linear_argb,
-    "uint32_t *d_n, uint32_t *s_n, uint32_t *s2_n, uint32_t *s3_1, int n",
-    NULL);
-OIL_DEFINE_CLASS_FULL (merge_linear_u8,
-    "uint8_t *d_n, uint8_t *s_n, uint8_t *s2_n, uint32_t *s3_1, int n",
-    NULL);
-
-OIL_DEFINE_CLASS(splat_u8_ns,"uint8_t *dest, uint8_t *s1_1, int n");
-
-OIL_DEFINE_CLASS(splat_u8,"uint8_t *dest, int dstr, uint8_t *s1_1, int n");
-
-typedef enum {
-  OIL_IMPL_FLAG_REF = (1<<0),
-  OIL_IMPL_FLAG_OPT = (1<<1),
-  OIL_IMPL_FLAG_ASM = (1<<2),
-  OIL_IMPL_FLAG_DISABLED = (1<<3),
-  OIL_IMPL_FLAG_CMOV = (1<<16),
-  OIL_IMPL_FLAG_MMX = (1<<17),
-  OIL_IMPL_FLAG_SSE = (1<<18),
-  OIL_IMPL_FLAG_MMXEXT = (1<<19),
-  OIL_IMPL_FLAG_SSE2 = (1<<20),
-  OIL_IMPL_FLAG_3DNOW = (1<<21),
-  OIL_IMPL_FLAG_3DNOWEXT = (1<<22),
-  OIL_IMPL_FLAG_SSE3 = (1<<23),
-  OIL_IMPL_FLAG_ALTIVEC = (1<<24),
-  OIL_IMPL_FLAG_EDSP = (1<<25),
-  OIL_IMPL_FLAG_ARM6 = (1<<26),
-  OIL_IMPL_FLAG_VFP = (1<<27),
-  OIL_IMPL_FLAG_SSSE3 = (1<<28)
-} OilImplFlag;
-
-#ifndef OIL_OPT_MANGLE
-#define OIL_OPT_MANGLE(a) a
-#define OIL_OPT_FLAG_MANGLE(a) a
-#else
-#define OIL_NO_CLASSES
-#define OIL_OPT_FLAG_MANGLE(a) (((a)&(~OIL_IMPL_FLAG_REF)) | OIL_IMPL_FLAG_OPT)
-#endif
-#ifndef OIL_OPT_SUFFIX
-#define OIL_OPT_SUFFIX
-#endif
-
-/**
- * OIL_DEFINE_IMPL_FULL:
- * @function: name of function
- * @klass: name of class to declare (without oil_ prefix)
- * @flags: implementation flags and CPU requirements
- *
- * Defines a #OilFunctionImpl structure for the function @function
- * and class @klass.  CPU-dependent flags in @flags will indicate
- * that this implementation requires the given CPU flags.
- */
-#define OIL_DEFINE_IMPL_FULL(function,klass,flags) \
-OilFunctionImpl OIL_OPT_MANGLE(_oil_function_impl_ ## function) = { \
-    NULL, \
-    &_oil_function_class_ ## klass , \
-    (void *)function, \
-    OIL_OPT_FLAG_MANGLE(flags), \
-        #function OIL_OPT_SUFFIX \
-} \
-OIL_CHECK_PROTOTYPE(;_oil_type_ ## klass _ignore_me_ ## function = function)
-
-/**
- * OIL_DEFINE_IMPL:
- * @function: name of function
- * @klass: name of class to declare (without oil_ prefix)
- *
- * Shorthand for defining a C implementation.  See OIL_DEFINE_IMPL_FULL().
- */
-#define OIL_DEFINE_IMPL(function,klass) \
-    OIL_DEFINE_IMPL_FULL(function,klass,0)
-/**
- * OIL_DEFINE_IMPL_REF:
- * @function: name of function
- * @klass: name of class to declare (without oil_ prefix)
- *
- * Shorthand for defining a reference implementation.  See OIL_DEFINE_IMPL_FULL().
- */
-#define OIL_DEFINE_IMPL_REF(function,klass) \
-    OIL_DEFINE_IMPL_FULL(function,klass,OIL_IMPL_FLAG_REF)
-
-
-
-
-typedef void (*_oil_type_scalarmultiply_f32_ns)(float * d, const float * s1, const float * s2_1, int n);
-//#define oil_scalarmultiply_f32_ns ((_oil_type_scalarmultiply_f32_ns)(*(void **)oil_function_class_ptr_scalarmultiply_f32_ns))
-
-
-
-#define OIL_GET(ptr, offset, type) (*(type *)((uint8_t *)(ptr) + (offset)) )
-
-/**************'_oil_resample_linear_u8'****************************/
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-static void
-resample_linear_u8_ref (uint8_t *dest, uint8_t *src, int n,
-    uint32_t *in)
-{
-  int acc = in[0];
-  int increment = in[1];
-  int i;
-  int j;
-  int x;
-
-  for(i=0;i<n;i++){
-    j = acc>>16;
-    x = (acc&0xffff)>>8;
-    dest[i] = (src[j]*(256-x) + src[j+1]*x) >> 8;
-
-    acc += increment;
-  }
-
-  in[0] = acc;
-}
-
-/************************'_oil_resample_linear_argb'***************************/
-static  void
-resample_linear_argb_ref (uint32_t *d, uint32_t *s, int n, uint32_t *in)
-{
-  uint8_t *src = (uint8_t *)s;
-  uint8_t *dest = (uint8_t *)d;
-  int acc = in[0];
-  int increment = in[1];
-  int i;
-  int j;
-  int x;
-
-  for(i=0;i<n;i++){
-    j = acc>>16;
-    x = (acc&0xffff)>>8;
-    dest[4*i+0] = (src[4*j+0]*(256-x) + src[4*j+4]*x) >> 8;
-    dest[4*i+1] = (src[4*j+1]*(256-x) + src[4*j+5]*x) >> 8;
-    dest[4*i+2] = (src[4*j+2]*(256-x) + src[4*j+6]*x) >> 8;
-    dest[4*i+3] = (src[4*j+3]*(256-x) + src[4*j+7]*x) >> 8;
-
-    acc += increment;
-  }
-
-  in[0] = acc;
-}
-
-/****************** '_oil_merge_linear_argb'**************************/
-static  void
-merge_linear_argb_ref (uint32_t *d, uint32_t *s1, uint32_t *s2,
-    uint32_t *src3, int n)
-{
-  uint8_t *src1 = (uint8_t *)s1;
-  uint8_t *src2 = (uint8_t *)s2;
-  uint8_t *dest = (uint8_t *)d;
-  int i;
-  int x = src3[0];
-
-  for(i=0;i<n;i++){
-    dest[4*i+0] = (src1[4*i+0]*(256-x) + src2[4*i+0]*x) >> 8;
-    dest[4*i+1] = (src1[4*i+1]*(256-x) + src2[4*i+1]*x) >> 8;
-    dest[4*i+2] = (src1[4*i+2]*(256-x) + src2[4*i+2]*x) >> 8;
-    dest[4*i+3] = (src1[4*i+3]*(256-x) + src2[4*i+3]*x) >> 8;
-  }
-}
-
-static void
-merge_linear_u8_ref (uint8_t *dest, uint8_t *src1, uint8_t *src2,
-    uint32_t *src3, int n)
-{
-  int i;
-  int x = src3[0];
-
-  for(i=0;i<n;i++){
-    dest[i] = (src1[i]*(256-x) + src2[i]*x) >> 8;
-  }
-}
-
-static void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n)
-{
-  int i;
-  for(i=0;i<n;i++){
-    OIL_GET(dest,i*dstr, uint8_t) = *param;
-  }
-}
-
-static void splat_u8_ns_ref (uint8_t *dest, uint8_t *param, int n)
-{
-  int i;
-  for(i=0;i<n;i++){
-    dest[i] = *param;
-  }
-}
-
-static void
-scalarmultiply_f32_ns_ref (float *dest, float *src1, float *src2, int n)
-{
-  int i;
-
-  for(i=0;i<n;i++){
-    dest[i] = src1[i] * src2[0];
-  }
-}
-
-/********oil_splat_u8*******/
-/*
-EXPORT_C  void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n)
-{
-  int i;
-  for(i=0;i<n;i++){
-    OIL_GET(dest,i*dstr, uint8_t) = *param;
-  }
-}
-*/
-
-unsigned long oil_cpu_flags;
-
-/**
- * oil_cpu_get_flags:
- *
- * Returns a bitmask containing the available CPU features.
- *
- * Returns: the CPU features.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-unsigned int
-oil_cpu_get_flags (void)
-{
-  return oil_cpu_flags;
-}
-
-/**
- * OIL_CPU_FLAG_MASK:
- *
- * Mask describing which bits in #OilImplFlag depend on the current
- * CPU.
- */
-#define OIL_CPU_FLAG_MASK 0xffff0000
-
-/**
- * oil_impl_is_runnable:
- * @impl: an @OilFunctionImpl
- *
- * Determines whether the function implementation given by @impl
- * can be executed by the current CPU.
- *
- * Returns: 1 if the implementation can be executed, otherwise 0
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-int
-oil_impl_is_runnable (OilFunctionImpl *impl)
-{
-  unsigned int oil_cpu_flags = oil_cpu_get_flags();
-
-  if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags))
-    return 0;
-  return 1;
-}
-
-/**
- * oil_class_optimize:
- * @klass: a function class
- *
- * Tests and profiles each implementation for the given function
- * class.  Testing compares the output of running each implementation
- * on random input against the reference implementation for the
- * same input.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-oil_class_optimize (OilFunctionClass * klass)
-{
-  OilFunctionImpl *impl;
-  OilFunctionImpl *min_impl;
-  int ret;
-
-
-  if (klass->reference_impl == NULL) {
-    return;
-  }
-  if (klass->first_impl == NULL) {
-    return;
-  }
-
-  min_impl = NULL;
-  
-  for (impl = klass->first_impl; impl; impl = impl->next) {
-    if (!oil_impl_is_runnable (impl))
-      continue;
-  }
-  
-  if (min_impl == NULL) {
-    return;
-  }
-
-  klass->chosen_impl = min_impl;
-  klass->func = min_impl->func;
-
-}
-
-
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
- void oil_scalarmultiply_f32_ns (float * d, const float * s1, const float * s2_1, int n)
-{
-  /*  
-  if (_oil_function_class_scalarmultiply_f32_ns.func == NULL) {
-    oil_class_optimize (&_oil_function_class_scalarmultiply_f32_ns);
-  }
-  */
-  scalarmultiply_f32_ns_ref(d,(float*) s1,(float*) s2_1, n);
-  //((void (*)(float * d, const float * s1, const float * s2_1, int n))(_oil_function_class_scalarmultiply_f32_ns.func))(d, s1, s2_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
- void
-oil_merge_linear_argb (uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n)
-{
-  if (_oil_function_class_merge_linear_argb.func == NULL) {
-    oil_class_optimize (&_oil_function_class_merge_linear_argb);
-  }
-  ((void (*)(uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n))(_oil_function_class_merge_linear_argb.func))(d_n, s_n, s2_n, s3_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
- void
-oil_merge_linear_u8 (uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n)
-{
-  if (_oil_function_class_merge_linear_u8.func == NULL) {
-    oil_class_optimize (&_oil_function_class_merge_linear_u8);
-  }
-  ((void (*)(uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n))(_oil_function_class_merge_linear_u8.func))(d_n, s_n, s2_n, s3_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
- void
-oil_resample_linear_argb (uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2)
-{
-  if (_oil_function_class_resample_linear_argb.func == NULL) {
-    oil_class_optimize (&_oil_function_class_resample_linear_argb);
-  }
-  ((void (*)(uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2))(_oil_function_class_resample_linear_argb.func))(d_n, s_2xn, n, i_2);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
- void
-oil_resample_linear_u8 (uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2)
-{
-  if (_oil_function_class_resample_linear_u8.func == NULL) {
-    oil_class_optimize (&_oil_function_class_resample_linear_u8);
-  }
-  ((void (*)(uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2))(_oil_function_class_resample_linear_u8.func))(d_n, s_2xn, n, i_2);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
- void
-oil_splat_u8 (uint8_t * dest, int dstr, const uint8_t * s1_1, int n)
-{
-  if (_oil_function_class_splat_u8.func == NULL) {
-    oil_class_optimize (&_oil_function_class_splat_u8);
-  }
-  ((void (*)(uint8_t * dest, int dstr, const uint8_t * s1_1, int n))(_oil_function_class_splat_u8.func))(dest, dstr, s1_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-oil_splat_u8_ns (uint8_t * dest, const uint8_t * s1_1, int n)
-{
-  if (_oil_function_class_splat_u8_ns.func == NULL) {
-    oil_class_optimize (&_oil_function_class_splat_u8_ns);
-  }
-  ((void (*)(uint8_t * dest, const uint8_t * s1_1, int n))(_oil_function_class_splat_u8_ns.func))(dest, s1_1, n);
-}
-
-OIL_DEFINE_IMPL_REF (scalarmultiply_f32_ns_ref, scalarmultiply_f32_ns);
-OIL_DEFINE_IMPL_REF (resample_linear_u8_ref, resample_linear_u8);
-OIL_DEFINE_IMPL_REF (resample_linear_argb_ref, resample_linear_argb);
-OIL_DEFINE_IMPL_REF (merge_linear_argb_ref, merge_linear_argb);
-OIL_DEFINE_IMPL_REF (merge_linear_u8_ref, merge_linear_u8);
-OIL_DEFINE_IMPL_REF(splat_u8_ref, splat_u8);
-OIL_DEFINE_IMPL_REF(splat_u8_ns_ref, splat_u8_ns);
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/playback/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,91 @@
+decodebin:
+
+  A bin with a sinkpad that decodes the data into raw formats. It works by sending
+  the input data through a typefind element and then recursively autoplugs elements 
+  from the registry until a raw format is obtained. It will then create a new ghostpad
+  on itself to signal the app of the new pad. 
+
+  Decodebin will also remove pads when they are removed from the stream.
+
+  TODO
+   - reuse of decoderbin, cleanup in READY state
+   - threading after demuxing?
+   - new_media events should be handled.
+   - caching of elements.
+   - abstract more elements, pads (typefind, ...);
+
+   The autoplugging happens as follows:
+
+   1) typefind is added internally to the bin.
+   2) the have_type signal is connected to typefind.
+   3) in the have_type callback the close_pad_link function is called
+   4) close_pad_link checks the type on the pad, if it is raw, a ghostpad
+      is created and autoplugging for that pad stops.
+   5) if the type of the pad is not raw, a list of possible elements that
+      can connect to this type is generated in find_compatibles.
+   6) try_to_link_1 with the element list is called. The function will loop
+      over the element list and will try to connect one of the elements to
+      the pad. If the link works, a call is made to close_link.
+   7) close_link loops over all the source pads of the element and 
+      recursively calls 4) for any ALWAYS pad. For elements with
+      a SOMETIMES pad, a structure is set up and is passed to the callback
+      of the new_pad signal.
+   8) in the new_pad callback, 4) is called to try to autoplug the
+      new pad.
+
+
+playbasebin:
+
+  A bin with an uri property. It will find the right source element from the registry
+  and connect a decoderbin to it. When going to the PAUSED state, it will iterate the
+  decoderbin and listen for new pad signals from it. It will connect a queue to each
+  new pad and will iterate the decoderbin until one of the queues is filled. It is
+  assumed that by that time all the streams will be found so that when leaving the
+  PAUSED state, one can query the number of streams in the media file with the given
+  uri.
+
+  Playbasebin internally groups related streams together in a GstPlayBaseGroup. This
+  is particulary important for chained oggs. Initially, a new group is created in 
+  the 'building' state. All new streams will be added to the building group until
+  no-more-pads is signaled or one of the preroll queues overflows. When this happens,
+  the group is commited to a list of groups ready for playback. PlaybaseBin will then
+  attach a padprobe to each stream to figure out when it finished. It will remove
+  the current group and install the next playable group, then.
+
+  Before going to the PLAYING state, it is possible to connect a custom element to
+  each of the streams. To do that, you have to add the element to the bin and then
+  connect the pad(s) from the stream(s). You do not have to add the elements in
+  a thread, the bin will take care of then when it's needed. You are allowed to use
+  threads inside the elements, of course.
+  The bin tries to be smart and doesn't add a queue when there is only one possible 
+  stream.
+
+  
+  TODO
+  - reuse, cleanup in ready state
+  - when the first pad is closed, it's possible that another dynamic element is
+    added somewhere so that we need a queue for the first pad as well.
+
+
+playbin:
+  
+   Extends playbasebin, sets up default audiosink and videosink for first audio/video
+   stream detected. implements seeking and querying on the configured sinks.
+
+   It also waits for new notifications from playbasebin about any new groups that are
+   becomming active. It then disconnects the sinks and reconnects them to the new
+   pads in the group.
+
+   TODO
+   - reuse, refcounting, cleanup in READY state
+   - be smarter about replugging the sinks instead of removing them and readding them.
+   - Do not crap out when the audio device is in use.
+
+
+general
+
+   TODO
+   - playlist support. maybe use a playlist bin that streams the contents of the
+     playlist on a pad, interleaved with new_media events. Also add a tuner 
+     interface while we're at it.
+   
--- a/gst_plugins_base/gst/playback/decodetest.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/decodetest.c	Fri Apr 16 15:15:52 2010 +0300
@@ -32,10 +32,6 @@
   g_error_free (err);
   g_free (dbg);
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
 
 static void
 error_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop)
@@ -83,7 +79,7 @@
   GstPad *fakesink_pad;
 
   fakesink = gst_element_factory_make ("fakesink", NULL);
-  fakesink_pad = gst_element_get_pad (fakesink, "sink");
+  fakesink_pad = gst_element_get_static_pad (fakesink, "sink");
 
   gst_bin_add (GST_BIN (pipeline), fakesink);
 
--- a/gst_plugins_base/gst/playback/gstdecodebin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstdecodebin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -17,6 +17,17 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:element-decodebin
+ *
+ * #GstBin that auto-magically constructs a decoding pipeline using available
+ * decoders and demuxers via auto-plugging.
+ *
+ * When using decodebin in your application, connect a signal handler to
+ * #GstDecodeBin::new-decoded-pad and connect your sinks from within the
+ * callback function.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -26,7 +37,6 @@
 #include <string.h>
 #include <gst/gst.h>
 #include <gst/pbutils/pbutils.h>
-#include <glib_global.h>
 
 #include "gstplay-marshal.h"
 
@@ -55,6 +65,11 @@
 typedef struct _GstDecodeBin GstDecodeBin;
 typedef struct _GstDecodeBinClass GstDecodeBinClass;
 
+/**
+ * GstDecodeBin:
+ *
+ * Auto-plugging decoder element structure
+ */
 struct _GstDecodeBin
 {
   GstBin bin;                   /* we extend GstBin */
@@ -104,6 +119,13 @@
   LAST_SIGNAL
 };
 
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_SINK_CAPS,
+};
+
 
 typedef struct
 {
@@ -129,6 +151,10 @@
 
 static void gst_decode_bin_class_init (GstDecodeBinClass * klass);
 static void gst_decode_bin_init (GstDecodeBin * decode_bin);
+static void gst_decode_bin_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_decode_bin_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 static void gst_decode_bin_dispose (GObject * object);
 static void gst_decode_bin_finalize (GObject * object);
 
@@ -156,6 +182,8 @@
 static void queue_filled_cb (GstElement * queue, GstDecodeBin * decode_bin);
 static void queue_underrun_cb (GstElement * queue, GstDecodeBin * decode_bin);
 
+static gboolean is_demuxer_element (GstElement * srcelement);
+
 static GstElementClass *parent_class;
 static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 };
 
@@ -206,25 +234,58 @@
 
   parent_class = g_type_class_peek_parent (klass);
 
+  gobject_klass->set_property = GST_DEBUG_FUNCPTR (gst_decode_bin_set_property);
+  gobject_klass->get_property = GST_DEBUG_FUNCPTR (gst_decode_bin_get_property);
+  gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
+  gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize);
+
+  /**
+   * GstDecodeBin::new-decoded-pad:
+   * @bin: The decodebin
+   * @pad: The newly created pad
+   * @islast: #TRUE if this is the last pad to be added. Deprecated.
+   *
+   * This signal gets emitted as soon as a new pad of the same type as one of
+   * the valid 'raw' types is added.
+   */
   gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] =
       g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL,
       gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD,
       G_TYPE_BOOLEAN);
+  /**
+   * GstDecodeBin::removed-decoded-pad:
+   * @bin: The decodebin
+   * @pad: The pad that was removed
+   *
+   * This signal is emitted when a 'final' caps pad has been removed.
+   */
   gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
       g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL,
       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+  /**
+   * GstDecodeBin::unknown-type:
+   * @bin: The decodebin
+   * @pad: The new pad containing caps that cannot be resolved to a 'final'
+   *       stream type.
+   * @caps: The #GstCaps of the pad that cannot be resolved.
+   *
+   * This signal is emitted when a pad for which there is no further possible
+   * decoding is added to the decodebin.
+   */
   gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
-      NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
+      NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
-  gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
-  gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize);
+  g_object_class_install_property (gobject_klass, PROP_SINK_CAPS,
+      g_param_spec_boxed ("sink-caps", "Sink Caps",
+          "The caps of the input data. (NULL = use typefind element)",
+          GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gst_element_class_add_pad_template (gstelement_klass,
       gst_static_pad_template_get (&decoder_bin_sink_template));
@@ -338,7 +399,7 @@
     }
 
     /* get the sinkpad */
-    pad = gst_element_get_pad (decode_bin->typefind, "sink");
+    pad = gst_element_get_static_pad (decode_bin->typefind, "sink");
 
     /* ghost the sink pad to ourself */
     gpad = gst_ghost_pad_new ("sink", pad);
@@ -380,6 +441,61 @@
 }
 
 static void
+gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps)
+{
+  GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
+
+  g_object_set (dbin->typefind, "force-caps", caps, NULL);
+}
+
+static GstCaps *
+gst_decode_bin_get_sink_caps (GstDecodeBin * dbin)
+{
+  GstCaps *caps;
+
+  GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
+
+  g_object_get (dbin->typefind, "force-caps", &caps, NULL);
+
+  return caps;
+}
+
+static void
+gst_decode_bin_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstDecodeBin *dbin;
+
+  dbin = GST_DECODE_BIN (object);
+
+  switch (prop_id) {
+    case PROP_SINK_CAPS:
+      gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_decode_bin_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstDecodeBin *dbin;
+
+  dbin = GST_DECODE_BIN (object);
+  switch (prop_id) {
+    case PROP_SINK_CAPS:
+      g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 gst_decode_bin_finalize (GObject * object)
 {
   GstDecodeBin *decode_bin = GST_DECODE_BIN (object);
@@ -570,6 +686,25 @@
   decode_bin->probes = NULL;
 }
 
+/* used when we need to remove a probe because the decoder we plugged failed
+ * to activate */
+static void
+free_pad_probe_for_element (GstDecodeBin * decode_bin, GstElement * element)
+{
+  GList *l;
+
+  for (l = decode_bin->probes; l != NULL; l = g_list_next (l)) {
+    PadProbeData *data = (PadProbeData *) l->data;
+
+    if (GST_ELEMENT_CAST (GST_PAD_PARENT (data->pad)) == element) {
+      gst_pad_remove_data_probe (data->pad, data->sigid);
+      decode_bin->probes = g_list_delete_link (decode_bin->probes, l);
+      g_free (data);
+      return;
+    }
+  }
+}
+
 static gboolean
 add_fakesink (GstDecodeBin * decode_bin)
 {
@@ -616,6 +751,9 @@
   if (decode_bin->fakesink) {
     GST_DEBUG_OBJECT (decode_bin, "Removing fakesink and marking state dirty");
 
+    /* Lock the state to prevent it from changing state to non-NULL
+     * before it's removed */
+    gst_element_set_locked_state (decode_bin->fakesink, TRUE);
     /* setting the state to NULL is never async */
     gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL);
     gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink);
@@ -667,6 +805,47 @@
   return TRUE;
 }
 
+/* FIXME: this should be somehow merged with the queue code in
+ * try_to_link_1() to reduce code duplication */
+static GstPad *
+add_raw_queue (GstDecodeBin * decode_bin, GstPad * pad)
+{
+  GstElement *queue = NULL;
+  GstPad *queuesinkpad = NULL, *queuesrcpad = NULL;
+
+  queue = gst_element_factory_make ("queue", NULL);
+  decode_bin->queue_type = G_OBJECT_TYPE (queue);
+
+  g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL);
+  g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), NULL);
+  g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL);
+  gst_bin_add (GST_BIN (decode_bin), queue);
+  gst_element_set_state (queue, GST_STATE_READY);
+  queuesinkpad = gst_element_get_static_pad (queue, "sink");
+  queuesrcpad = gst_element_get_static_pad (queue, "src");
+
+  if (gst_pad_link (pad, queuesinkpad) != GST_PAD_LINK_OK) {
+    GST_WARNING_OBJECT (decode_bin,
+        "Linking queue failed, trying without queue");
+    gst_element_set_state (queue, GST_STATE_NULL);
+    gst_object_unref (queuesrcpad);
+    gst_object_unref (queuesinkpad);
+    gst_bin_remove (GST_BIN (decode_bin), queue);
+    return gst_object_ref (pad);
+  }
+
+  decode_bin->queues = g_list_append (decode_bin->queues, queue);
+  g_signal_connect (G_OBJECT (queue),
+      "overrun", G_CALLBACK (queue_filled_cb), decode_bin);
+  g_signal_connect (G_OBJECT (queue),
+      "underrun", G_CALLBACK (queue_underrun_cb), decode_bin);
+
+  gst_element_set_state (queue, GST_STATE_PAUSED);
+  gst_object_unref (queuesinkpad);
+
+  return queuesrcpad;
+}
+
 /* given a pad and a caps from an element, find the list of elements
  * that could connect to the pad
  *
@@ -719,6 +898,17 @@
     GstPad *ghost;
     PadProbeData *data;
 
+    /* If we're at a demuxer element but have raw data already
+     * we have to add a queue here. For non-raw data this is done
+     * in try_to_link_1() */
+    if (is_demuxer_element (element)) {
+      GST_DEBUG_OBJECT (decode_bin,
+          "Element %s is a demuxer, inserting a queue",
+          GST_OBJECT_NAME (element));
+
+      pad = add_raw_queue (decode_bin, pad);
+    }
+
     /* make a unique name for this new pad */
     padname = g_strdup_printf ("src%d", decode_bin->numpads);
     decode_bin->numpads++;
@@ -748,6 +938,11 @@
     GST_DEBUG_OBJECT (decode_bin, "emitted new-decoded-pad");
 
     g_free (padname);
+
+    /* If we're at a demuxer element pad was set to a queue's
+     * srcpad and must be unref'd here */
+    if (is_demuxer_element (element))
+      gst_object_unref (pad);
   } else {
     GList *to_try;
 
@@ -901,8 +1096,8 @@
     g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL);
     gst_bin_add (GST_BIN (decode_bin), queue);
     gst_element_set_state (queue, GST_STATE_READY);
-    queuesinkpad = gst_element_get_pad (queue, "sink");
-    usedsrcpad = queuesrcpad = gst_element_get_pad (queue, "src");
+    queuesinkpad = gst_element_get_static_pad (queue, "sink");
+    usedsrcpad = queuesrcpad = gst_element_get_static_pad (queue, "src");
 
     dqlink = gst_pad_link (pad, queuesinkpad);
     g_return_val_if_fail (dqlink == GST_PAD_LINK_OK, NULL);
@@ -929,7 +1124,7 @@
     /* try to link the given pad to a sinkpad */
     /* FIXME, find the sinkpad by looping over the pads instead of
      * looking it up by name */
-    if ((sinkpad = gst_element_get_pad (element, "sink")) == NULL) {
+    if ((sinkpad = gst_element_get_static_pad (element, "sink")) == NULL) {
       /* if no pad is found we can't do anything */
       GST_WARNING_OBJECT (decode_bin, "could not find sinkpad in element");
       continue;
@@ -993,6 +1188,8 @@
                   GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
         GST_WARNING_OBJECT (decode_bin, "Couldn't set %s to PAUSED",
             GST_ELEMENT_NAME (element));
+        /* close_link -> close_pad_link -> might have set up a pad probe */
+        free_pad_probe_for_element (decode_bin, element);
         gst_element_set_state (element, GST_STATE_NULL);
         gst_bin_remove (GST_BIN (decode_bin), element);
         continue;
@@ -1089,7 +1286,9 @@
 static void
 remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad)
 {
-  GList *int_links, *walk;
+  GstIterator *iter;
+  gboolean done = FALSE;
+  gpointer item;
   GstElement *elem = GST_ELEMENT (GST_OBJECT_PARENT (pad));
 
   while (GST_OBJECT_PARENT (elem) &&
@@ -1103,69 +1302,86 @@
   }
 
   GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad));
-  int_links = gst_pad_get_internal_links (pad);
+  iter = gst_pad_iterate_internal_links (pad);
+  if (!iter)
+    goto no_iter;
 
   /* remove all elements linked to this pad up to the ghostpad
    * that we created for this stream */
-  for (walk = int_links; walk; walk = g_list_next (walk)) {
-    GstPad *pad;
-    GstPad *ghostpad;
-    GstPad *peer;
+  while (!done) {
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:{
+        GstPad *pad;
+        GstPad *ghostpad;
+        GstPad *peer;
 
-    pad = GST_PAD (walk->data);
-    GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s",
-        GST_DEBUG_PAD_NAME (pad));
+        pad = GST_PAD (item);
+        GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s",
+            GST_DEBUG_PAD_NAME (pad));
+
+        ghostpad = get_our_ghost_pad (decode_bin, pad);
+        if (ghostpad) {
+          GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s",
+              GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad));
 
-    ghostpad = get_our_ghost_pad (decode_bin, pad);
-    if (ghostpad) {
-      GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s",
-          GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad));
+          g_signal_emit (G_OBJECT (decode_bin),
+              gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad);
 
-      g_signal_emit (G_OBJECT (decode_bin),
-          gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad);
+          gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad);
+          gst_object_unref (ghostpad);
+          continue;
+        } else {
+          GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads");
+        }
 
-      gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad);
-      gst_object_unref (ghostpad);
-      continue;
-    } else {
-      GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads");
-    }
+        peer = gst_pad_get_peer (pad);
+        if (peer) {
+          GstObject *parent = gst_pad_get_parent (peer);
+
+          GST_DEBUG_OBJECT (decode_bin,
+              "internal pad %s:%s linked to pad %s:%s",
+              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer));
 
-    peer = gst_pad_get_peer (pad);
-    if (peer == NULL)
-      continue;
-
-    GST_DEBUG_OBJECT (decode_bin, "internal pad %s:%s linked to pad %s:%s",
-        GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer));
-
-    {
-      GstObject *parent = gst_pad_get_parent (peer);
-
-      if (parent) {
-        GstObject *grandparent = gst_object_get_parent (parent);
+          if (parent) {
+            GstObject *grandparent = gst_object_get_parent (parent);
 
-        if (grandparent != NULL) {
-          if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) {
-            GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s",
-                GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent));
-          } else {
-            GST_DEBUG_OBJECT (decode_bin, "recursing element %s on pad %s:%s",
-                GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad));
-            remove_element_chain (decode_bin, peer);
+            if (grandparent != NULL) {
+              if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) {
+                GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s",
+                    GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent));
+              } else {
+                GST_DEBUG_OBJECT (decode_bin,
+                    "recursing element %s on pad %s:%s",
+                    GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad));
+                remove_element_chain (decode_bin, peer);
+              }
+              gst_object_unref (grandparent);
+            }
+            gst_object_unref (parent);
           }
-          gst_object_unref (grandparent);
+          gst_object_unref (peer);
         }
-        gst_object_unref (parent);
+        gst_object_unref (item);
       }
+        break;
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
     }
-    gst_object_unref (peer);
   }
   GST_DEBUG_OBJECT (decode_bin, "removing %s", GST_ELEMENT_NAME (elem));
 
-  g_list_free (int_links);
+  gst_iterator_free (iter);
 
+no_iter:
   gst_element_set_state (elem, GST_STATE_NULL);
-
   gst_bin_remove (GST_BIN (decode_bin), elem);
 }
 
@@ -1398,7 +1614,7 @@
       {
         /* try to get the pad to see if it is already created or
          * not */
-        GstPad *pad = gst_element_get_pad (element, templ_name);
+        GstPad *pad = gst_element_get_static_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s",
@@ -1485,7 +1701,7 @@
       case GST_PAD_ALWAYS:
       {
         /* get the pad that we need to autoplug */
-        GstPad *pad = gst_element_get_pad (element, templ_name);
+        GstPad *pad = gst_element_get_static_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (decode_bin, "got the pad for always template %s",
@@ -1504,7 +1720,7 @@
       {
         /* try to get the pad to see if it is already created or
          * not */
-        GstPad *pad = gst_element_get_pad (element, templ_name);
+        GstPad *pad = gst_element_get_static_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s",
@@ -1605,7 +1821,7 @@
   }
 
   /* autoplug the new pad with the caps that the signal gave us. */
-  pad = gst_element_get_pad (typefind, "src");
+  pad = gst_element_get_static_pad (typefind, "src");
   close_pad_link (typefind, pad, caps, decode_bin, FALSE);
   gst_object_unref (pad);
 
@@ -1671,7 +1887,7 @@
 
   GST_DEBUG_OBJECT (decode_bin, "cleaning up decodebin");
 
-  typefind_pad = gst_element_get_pad (decode_bin->typefind, "src");
+  typefind_pad = gst_element_get_static_pad (decode_bin->typefind, "src");
   if (GST_IS_PAD (typefind_pad)) {
     g_signal_handlers_block_by_func (typefind_pad, (gpointer) unlinked,
         decode_bin);
@@ -1822,6 +2038,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
   return gst_element_register (plugin, "decodebin", GST_RANK_NONE,
--- a/gst_plugins_base/gst/playback/gstdecodebin2.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstdecodebin2.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,17 +19,16 @@
 
 /**
  * SECTION:element-decodebin2
- * @short_description: Next-generation automatic decoding bin
  *
  * #GstBin that auto-magically constructs a decoding pipeline using available
  * decoders and demuxers via auto-plugging.
  *
  * At this stage, decodebin2 is considered UNSTABLE. The API provided in the
- * signals is expected to change in the near future. 
+ * signals is expected to change in the near future.
  *
- * To try out decodebin2, you can set the USE_DECODEBIN2 environment 
+ * To try out decodebin2, you can set the USE_DECODEBIN2 environment
  * variable (USE_DECODEBIN2=1 for example). This will cause playbin to use
- * decodebin2 instead of the older decodebin for its internal auto-plugging.
+ * decodebin2 instead of the older #GstDecodeBin for its internal auto-plugging.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -46,9 +45,6 @@
 #include "gstplay-enum.h"
 #include "gstfactorylists.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
 /* generic templates */
 static GstStaticPadTemplate decoder_bin_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
@@ -67,6 +63,7 @@
 
 typedef struct _GstDecodeGroup GstDecodeGroup;
 typedef struct _GstDecodePad GstDecodePad;
+typedef GstGhostPadClass GstDecodePadClass;
 typedef struct _GstDecodeBin GstDecodeBin;
 typedef struct _GstDecodeBin GstDecodeBin2;
 typedef struct _GstDecodeBinClass GstDecodeBinClass;
@@ -92,7 +89,6 @@
   gchar *encoding;              /* encoding of subtitles */
 
   GstElement *typefind;         /* this holds the typefind object */
-  GstElement *fakesink;
 
   GMutex *lock;                 /* Protects activegroup and groups */
   GstDecodeGroup *activegroup;  /* group currently active */
@@ -103,9 +99,16 @@
   gint nbpads;                  /* unique identifier for source pads */
 
   GValueArray *factories;       /* factories we can use for selecting elements */
+  GList *subtitles;             /* List of elements with subtitle-encoding */
 
   gboolean have_type;           /* if we received the have_type signal */
   guint have_type_id;           /* signal id for have-type from typefind */
+
+  gboolean async_pending;       /* async-start has been emited */
+
+  GMutex *dyn_lock;             /* lock protecting pad blocking */
+  gboolean shutdown;            /* if we are shutting down */
+  GList *blocked_pads;          /* pads that have set to block */
 };
 
 struct _GstDecodeBinClass
@@ -155,7 +158,9 @@
 {
   PROP_0,
   PROP_CAPS,
-  PROP_SUBTITLE_ENCODING
+  PROP_SUBTITLE_ENCODING,
+  PROP_SINK_CAPS,
+  PROP_LAST
 };
 
 static GstBinClass *parent_class;
@@ -168,8 +173,8 @@
     "Edward Hervey <edward@fluendo.com>");
 
 
-static gboolean add_fakesink (GstDecodeBin * decode_bin);
-static void remove_fakesink (GstDecodeBin * decode_bin);
+static void do_async_start (GstDecodeBin * dbin);
+static void do_async_done (GstDecodeBin * dbin);
 
 static void type_found (GstElement * typefind, guint probability,
     GstCaps * caps, GstDecodeBin * decode_bin);
@@ -215,6 +220,23 @@
     g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->lock);			\
 } G_STMT_END
 
+#define DECODE_BIN_DYN_LOCK(dbin) G_STMT_START {			\
+    GST_LOG_OBJECT (dbin,						\
+		    "dynlocking from thread %p",			\
+		    g_thread_self ());					\
+    g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->dyn_lock);			\
+    GST_LOG_OBJECT (dbin,						\
+		    "dynlocked from thread %p",				\
+		    g_thread_self ());					\
+} G_STMT_END
+
+#define DECODE_BIN_DYN_UNLOCK(dbin) G_STMT_START {			\
+    GST_LOG_OBJECT (dbin,						\
+		    "dynunlocking from thread %p",			\
+		    g_thread_self ());					\
+    g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->dyn_lock);		\
+} G_STMT_END
+
 /* GstDecodeGroup
  *
  * Streams belonging to the same group/chain of a media file
@@ -225,17 +247,16 @@
   GstDecodeBin *dbin;
   GMutex *lock;
   GstElement *multiqueue;
+
   gboolean exposed;             /* TRUE if this group is exposed */
-  gboolean drained;             /* TRUE if EOS went throug all endpads */
+  gboolean drained;             /* TRUE if EOS went through all endpads */
   gboolean blocked;             /* TRUE if all endpads are blocked */
   gboolean complete;            /* TRUE if we are not expecting anymore streams 
                                  * on this group */
-  gulong overrunsig;
-  gulong underrunsig;
+  gulong overrunsig;            /* the overrun signal for multiqueue */
   guint nbdynamic;              /* number of dynamic pads in the group. */
 
   GList *endpads;               /* List of GstDecodePad of source pads to be exposed */
-  GList *ghosts;                /* List of GstGhostPad for the endpads */
   GList *reqpads;               /* List of RequestPads for multiqueue. */
 };
 
@@ -262,9 +283,9 @@
 static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group,
     GstPad * pad);
 static gboolean gst_decode_group_control_source_pad (GstDecodeGroup * group,
-    GstPad * pad);
+    GstDecodePad * pad);
 static gboolean gst_decode_group_expose (GstDecodeGroup * group);
-static void gst_decode_group_check_if_blocked (GstDecodeGroup * group);
+static gboolean gst_decode_group_check_if_blocked (GstDecodeGroup * group);
 static void gst_decode_group_set_complete (GstDecodeGroup * group);
 static void gst_decode_group_hide (GstDecodeGroup * group);
 static void gst_decode_group_free (GstDecodeGroup * group);
@@ -273,28 +294,26 @@
  *
  * GstPad private used for source pads of groups
  */
-
 struct _GstDecodePad
 {
-  GstPad *pad;
-  GstDecodeGroup *group;
-  gboolean blocked;
-  gboolean drained;
-};
-
-static GstDecodePad *gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad,
-    gboolean block);
-static void source_pad_blocked_cb (GstPad * pad, gboolean blocked,
-    GstDecodePad * dpad);
-
-/* TempPadStruct
- * Internal structure used for pads which have more than one structure.
- */
-typedef struct _TempPadStruct
-{
+  GstGhostPad parent;
   GstDecodeBin *dbin;
   GstDecodeGroup *group;
-} TempPadStruct;
+
+  gboolean blocked;             /* the pad is blocked */
+  gboolean drained;             /* an EOS has been seen on the pad */
+  gboolean added;               /* the pad is added to decodebin */
+};
+
+G_DEFINE_TYPE (GstDecodePad, gst_decode_pad, GST_TYPE_GHOST_PAD);
+#define GST_TYPE_DECODE_PAD (gst_decode_pad_get_type ())
+#define GST_DECODE_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_PAD,GstDecodePad))
+
+static GstDecodePad *gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad,
+    GstDecodeGroup * group);
+static void gst_decode_pad_activate (GstDecodePad * dpad,
+    GstDecodeGroup * group);
+static void gst_decode_pad_unblock (GstDecodePad * dpad);
 
 /********************************
  * Standard GObject boilerplate *
@@ -393,7 +412,8 @@
 
   /**
    * GstDecodeBin2::new-decoded-pad:
-   * @pad: the newly created pad
+   * @bin: The decodebin
+   * @pad: The newly created pad
    * @islast: #TRUE if this is the last pad to be added. Deprecated.
    *
    * This signal gets emitted as soon as a new pad of the same type as one of
@@ -408,7 +428,8 @@
 
   /**
    * GstDecodeBin2::removed-decoded-pad:
-   * @pad: the pad that was removed
+   * @bin: The decodebin
+   * @pad: The pad that was removed
    *
    * This signal is emitted when a 'final' caps pad has been removed.
    */
@@ -420,8 +441,10 @@
 
   /**
    * GstDecodeBin2::unknown-type:
-   * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type.
-   * @caps: the #GstCaps of the pad that cannot be resolved.
+   * @bin: The decodebin
+   * @pad: The new pad containing caps that cannot be resolved to a 'final'
+   *       stream type.
+   * @caps: The #GstCaps of the pad that cannot be resolved.
    *
    * This signal is emitted when a pad for which there is no further possible
    * decoding is added to the decodebin.
@@ -429,11 +452,12 @@
   gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
-      NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
+      NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
    * GstDecodeBin2::autoplug-continue:
+   * @bin: The decodebin
    * @pad: The #GstPad.
    * @caps: The #GstCaps found.
    *
@@ -448,11 +472,12 @@
   gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
       g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue),
-      _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_OBJECT,
+      _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_BOXED,
       G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
    * GstDecodeBin2::autoplug-factories:
+   * @bin: The decodebin
    * @pad: The #GstPad.
    * @caps: The #GstCaps found.
    *
@@ -473,11 +498,12 @@
       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass,
           autoplug_factories), _gst_array_accumulator, NULL,
-      gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
+      gst_play_marshal_BOXED__OBJECT_BOXED, G_TYPE_VALUE_ARRAY, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
    * GstDecodeBin2::autoplug-sort:
+   * @bin: The decodebin
    * @pad: The #GstPad.
    * @caps: The #GstCaps.
    * @factories: A #GValueArray of possible #GstElementFactory to use.
@@ -494,34 +520,47 @@
   gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
       g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
-      NULL, NULL, gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED,
+      NULL, NULL, gst_play_marshal_BOXED__OBJECT_BOXED_BOXED,
       G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
 
   /**
    * GstDecodeBin2::autoplug-select:
+   * @bin: The decodebin
    * @pad: The #GstPad.
    * @caps: The #GstCaps.
-   * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by
-   * rank (higher ranks come first).
+   * @factory: A #GstElementFactory to use
    *
    * This signal is emitted once decodebin2 has found all the possible
-   * #GstElementFactory that can be used to handle the given @caps.
+   * #GstElementFactory that can be used to handle the given @caps. For each of
+   * those factories, this signal is emited.
+   *
+   * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum
+   * value indicating what decodebin2 should do next.
+   *
+   * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from
+   * @factory.
    *
-   * Returns: A #gint indicating what factory index from the @factories array
-   * that you wish decodebin2 to use for trying to decode the given @caps.
-   * Return -1 to stop selection of a factory and expose the pad as a raw type. 
-   * The default handler always returns the first possible factory (index 0).
+   * A value of #GST_AUTOPLUG_SELECT_EXPOSE will expose @pad without plugging
+   * any element to it.
+   *
+   * A value of #GST_AUTOPLUG_SELECT_SKIP will skip @factory and move to the
+   * next factory.
+   *
+   * Returns: a #GST_TYPE_AUTOPLUG_SELECT_RESULT that indicates the required
+   * operation. the default handler will always return
+   * #GST_AUTOPLUG_SELECT_TRY.
    */
   gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select),
       _gst_select_accumulator, NULL,
-      gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
+      gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT,
       GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
       GST_TYPE_ELEMENT_FACTORY);
 
   /**
    * GstDecodeBin2::drained
+   * @bin: The decodebin
    *
    * This signal is emitted once decodebin2 has finished decoding all the data.
    *
@@ -534,14 +573,20 @@
 
   g_object_class_install_property (gobject_klass, PROP_CAPS,
       g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.",
-          GST_TYPE_CAPS, G_PARAM_READWRITE));
+          GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
           "be checked for an encoding to use. If that is not set either, "
-          "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
+          "ISO-8859-15 will be assumed.", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_klass, PROP_SINK_CAPS,
+      g_param_spec_boxed ("sink-caps", "Sink Caps",
+          "The caps of the input data. (NULL = use typefind element)",
+          GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   klass->autoplug_continue =
       GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
@@ -584,7 +629,7 @@
     }
 
     /* get the sinkpad */
-    pad = gst_element_get_pad (decode_bin->typefind, "sink");
+    pad = gst_element_get_static_pad (decode_bin->typefind, "sink");
 
     /* ghost the sink pad to ourself */
     gpad = gst_ghost_pad_new ("sink", pad);
@@ -604,20 +649,96 @@
   decode_bin->activegroup = NULL;
   decode_bin->groups = NULL;
 
+  decode_bin->dyn_lock = g_mutex_new ();
+  decode_bin->shutdown = FALSE;
+  decode_bin->blocked_pads = NULL;
+
   decode_bin->caps =
       gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;"
-      "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup");
-
-  add_fakesink (decode_bin);
-
-  /* FILLME */
+      "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup;"
+      "video/x-dvd-subpicture; subpicture/x-pgs");
+}
+
+static void
+gst_decode_bin_remove_groups (GstDecodeBin * dbin)
+{
+  GList *tmp;
+  GstIterator *it;
+  gpointer point;
+  gboolean done;
+  GstIteratorResult res;
+
+  GST_DEBUG_OBJECT (dbin, "cleaning up");
+
+  if (dbin->activegroup) {
+    GST_DEBUG_OBJECT (dbin, "free active group %p", dbin->activegroup);
+    gst_decode_group_free (dbin->activegroup);
+    dbin->activegroup = NULL;
+  }
+
+  /* remove groups */
+  for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) {
+    GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
+
+    GST_DEBUG_OBJECT (dbin, "free group %p", group);
+    gst_decode_group_free (group);
+  }
+  g_list_free (dbin->groups);
+  dbin->groups = NULL;
+
+  for (tmp = dbin->oldgroups; tmp; tmp = g_list_next (tmp)) {
+    GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
+
+    GST_DEBUG_OBJECT (dbin, "free old group %p", group);
+    gst_decode_group_free (group);
+  }
+  g_list_free (dbin->oldgroups);
+  dbin->oldgroups = NULL;
+
+  GST_DEBUG_OBJECT (dbin, "removing last elements");
+
+  /* remove all remaining elements */
+  it = gst_bin_iterate_elements (GST_BIN_CAST (dbin));
+restart:
+  done = FALSE;
+  while (!done) {
+    res = gst_iterator_next (it, &point);
+    switch (res) {
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (it);
+        goto restart;
+      case GST_ITERATOR_ERROR:
+        GST_WARNING_OBJECT (dbin,
+            "Had an error while iterating bin %s", GST_ELEMENT_NAME (dbin));
+        done = TRUE;
+        break;
+      case GST_ITERATOR_OK:
+      {
+        GstElement *elem = GST_ELEMENT_CAST (point);
+
+        /* don't remove the typefind element */
+        if (elem != dbin->typefind) {
+          GST_DEBUG_OBJECT (dbin, "remove element %s", GST_ELEMENT_NAME (elem));
+          gst_bin_remove (GST_BIN_CAST (dbin), elem);
+          gst_element_set_state (elem, GST_STATE_NULL);
+        }
+        gst_object_unref (elem);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  gst_iterator_free (it);
 }
 
 static void
 gst_decode_bin_dispose (GObject * object)
 {
   GstDecodeBin *decode_bin;
-  GList *tmp;
 
   decode_bin = GST_DECODE_BIN (object);
 
@@ -625,27 +746,7 @@
     g_value_array_free (decode_bin->factories);
   decode_bin->factories = NULL;
 
-  if (decode_bin->activegroup) {
-    gst_decode_group_free (decode_bin->activegroup);
-    decode_bin->activegroup = NULL;
-  }
-
-  /* remove groups */
-  for (tmp = decode_bin->groups; tmp; tmp = g_list_next (tmp)) {
-    GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
-
-    gst_decode_group_free (group);
-  }
-  g_list_free (decode_bin->groups);
-  decode_bin->groups = NULL;
-
-  for (tmp = decode_bin->oldgroups; tmp; tmp = g_list_next (tmp)) {
-    GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
-
-    gst_decode_group_free (group);
-  }
-  g_list_free (decode_bin->oldgroups);
-  decode_bin->oldgroups = NULL;
+  gst_decode_bin_remove_groups (decode_bin);
 
   if (decode_bin->caps)
     gst_caps_unref (decode_bin->caps);
@@ -654,7 +755,8 @@
   g_free (decode_bin->encoding);
   decode_bin->encoding = NULL;
 
-  remove_fakesink (decode_bin);
+  g_list_free (decode_bin->subtitles);
+  decode_bin->subtitles = NULL;
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -671,6 +773,11 @@
     decode_bin->lock = NULL;
   }
 
+  if (decode_bin->dyn_lock) {
+    g_mutex_free (decode_bin->dyn_lock);
+    decode_bin->dyn_lock = NULL;
+  }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -685,15 +792,22 @@
 static void
 gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps)
 {
+  GstCaps *old;
+
   GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
 
-  DECODE_BIN_LOCK (dbin);
-  if (dbin->caps)
-    gst_caps_unref (dbin->caps);
-  if (caps)
-    gst_caps_ref (caps);
-  dbin->caps = caps;
-  DECODE_BIN_UNLOCK (dbin);
+  GST_OBJECT_LOCK (dbin);
+  old = dbin->caps;
+  if (old != caps) {
+    if (caps)
+      gst_caps_ref (caps);
+
+    dbin->caps = caps;
+
+    if (old)
+      gst_caps_unref (old);
+  }
+  GST_OBJECT_UNLOCK (dbin);
 }
 
 /* _get_caps
@@ -702,7 +816,6 @@
  *
  * MT-safe
  */
-
 static GstCaps *
 gst_decode_bin_get_caps (GstDecodeBin * dbin)
 {
@@ -710,11 +823,31 @@
 
   GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
 
-  DECODE_BIN_LOCK (dbin);
+  GST_OBJECT_LOCK (dbin);
   caps = dbin->caps;
   if (caps)
     gst_caps_ref (caps);
-  DECODE_BIN_UNLOCK (dbin);
+  GST_OBJECT_UNLOCK (dbin);
+
+  return caps;
+}
+
+static void
+gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps)
+{
+  GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
+
+  g_object_set (dbin->typefind, "force-caps", caps, NULL);
+}
+
+static GstCaps *
+gst_decode_bin_get_sink_caps (GstDecodeBin * dbin)
+{
+  GstCaps *caps;
+
+  GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
+
+  g_object_get (dbin->typefind, "force-caps", &caps, NULL);
 
   return caps;
 }
@@ -722,11 +855,21 @@
 static void
 gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding)
 {
+  GList *walk;
+
   GST_DEBUG_OBJECT (dbin, "Setting new encoding: %s", GST_STR_NULL (encoding));
 
   DECODE_BIN_LOCK (dbin);
+  GST_OBJECT_LOCK (dbin);
   g_free (dbin->encoding);
   dbin->encoding = g_strdup (encoding);
+  GST_OBJECT_UNLOCK (dbin);
+
+  /* set the subtitle encoding on all added elements */
+  for (walk = dbin->subtitles; walk; walk = g_list_next (walk)) {
+    g_object_set (G_OBJECT (walk->data), "subtitle-encoding", dbin->encoding,
+        NULL);
+  }
   DECODE_BIN_UNLOCK (dbin);
 }
 
@@ -737,9 +880,9 @@
 
   GST_DEBUG_OBJECT (dbin, "Getting currently set encoding");
 
-  DECODE_BIN_LOCK (dbin);
+  GST_OBJECT_LOCK (dbin);
   encoding = g_strdup (dbin->encoding);
-  DECODE_BIN_UNLOCK (dbin);
+  GST_OBJECT_UNLOCK (dbin);
 
   return encoding;
 }
@@ -759,6 +902,9 @@
     case PROP_SUBTITLE_ENCODING:
       gst_decode_bin_set_subs_encoding (dbin, g_value_get_string (value));
       break;
+    case PROP_SINK_CAPS:
+      gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -779,6 +925,9 @@
     case PROP_SUBTITLE_ENCODING:
       g_value_take_string (value, gst_decode_bin_get_subs_encoding (dbin));
       break;
+    case PROP_SINK_CAPS:
+      g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -786,9 +935,6 @@
 }
 
 
-static GValueArray *find_compatibles (GstDecodeBin * decode_bin,
-    GstPad * pad, const GstCaps * caps);
-
 /*****
  * Default autoplug signal handlers
  *****/
@@ -808,8 +954,11 @@
 {
   GValueArray *result;
 
+  GST_DEBUG_OBJECT (element, "finding factories");
+
   /* return all compatible factories for caps */
-  result = find_compatibles (GST_DECODE_BIN (element), pad, caps);
+  result =
+      gst_factory_list_filter (GST_DECODE_BIN_CAST (element)->factories, caps);
 
   GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result);
 
@@ -848,12 +997,12 @@
 static gboolean is_demuxer_element (GstElement * srcelement);
 
 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
-    GstPad * pad, GstCaps * caps, GValueArray * factories,
+    GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GValueArray * factories,
     GstDecodeGroup * group);
 static gboolean connect_element (GstDecodeBin * dbin, GstElement * element,
     GstDecodeGroup * group);
-static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
-    GstDecodeGroup * group);
+static void expose_pad (GstDecodeBin * dbin, GstElement * src,
+    GstDecodePad * dpad, GstPad * pad, GstDecodeGroup * group);
 
 static void pad_added_group_cb (GstElement * element, GstPad * pad,
     GstDecodeGroup * group);
@@ -867,7 +1016,8 @@
     GstDecodeBin * dbin);
 static void no_more_pads_cb (GstElement * element, GstDecodeBin * dbin);
 
-static GstDecodeGroup *get_current_group (GstDecodeBin * dbin);
+static GstDecodeGroup *get_current_group (GstDecodeBin * dbin,
+    gboolean create, gboolean demux, gboolean * created);
 
 /* called when a new pad is discovered. It will perform some basic actions
  * before trying to link something to it.
@@ -887,6 +1037,7 @@
 {
   gboolean apcontinue = TRUE;
   GValueArray *factories = NULL, *result = NULL;
+  GstDecodePad *dpad;
 
   GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
       GST_DEBUG_PAD_NAME (pad), caps);
@@ -897,10 +1048,12 @@
   if (gst_caps_is_any (caps))
     goto any_caps;
 
+  dpad = gst_decode_pad_new (dbin, pad, group);
+
   /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs
    * further autoplugging. */
   g_signal_emit (G_OBJECT (dbin),
-      gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, pad, caps,
+      gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, dpad, caps,
       &apcontinue);
 
   /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */
@@ -915,7 +1068,7 @@
   /* 1.c else get the factories and if there's no compatible factory goto
    * unknown_type */
   g_signal_emit (G_OBJECT (dbin),
-      gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps,
+      gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, dpad, caps,
       &factories);
 
   /* NULL means that we can expose the pad */
@@ -926,20 +1079,22 @@
   if (factories->n_values == 0) {
     /* no compatible factories */
     g_value_array_free (factories);
+    gst_object_unref (dpad);
     goto unknown_type;
   }
 
   /* 1.d sort some more. */
   g_signal_emit (G_OBJECT (dbin),
-      gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps, factories,
+      gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, dpad, caps, factories,
       &result);
   g_value_array_free (factories);
   factories = result;
 
   /* 1.e else continue autoplugging something from the list. */
   GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
-  connect_pad (dbin, src, pad, caps, factories, group);
-
+  connect_pad (dbin, src, dpad, pad, caps, factories, group);
+
+  gst_object_unref (dpad);
   g_value_array_free (factories);
 
   return;
@@ -947,7 +1102,8 @@
 expose_pad:
   {
     GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue);
-    expose_pad (dbin, src, pad, group);
+    expose_pad (dbin, src, dpad, pad, group);
+    gst_object_unref (dpad);
     return;
   }
 unknown_type:
@@ -956,9 +1112,10 @@
     g_signal_emit (G_OBJECT (dbin),
         gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
 
-    /* Check if there are no pending groups, if so, remove fakesink */
-    if (dbin->groups == NULL)
-      remove_fakesink (dbin);
+    /* Check if there are no pending groups, if so, commit our state */
+    if (dbin->groups == NULL) {
+      do_async_done (dbin);
+    }
 
     if (src == dbin->typefind) {
       gchar *desc;
@@ -979,6 +1136,7 @@
 non_fixed:
   {
     GST_DEBUG_OBJECT (pad, "pad has non-fixed caps delay autoplugging");
+    gst_object_unref (dpad);
     goto setup_caps_delay;
   }
 any_caps:
@@ -993,7 +1151,8 @@
     if (group) {
       GROUP_MUTEX_LOCK (group);
       group->nbdynamic++;
-      GST_LOG ("Group %p has now %d dynamic elements", group, group->nbdynamic);
+      GST_LOG_OBJECT (dbin, "Group %p has now %d dynamic elements", group,
+          group->nbdynamic);
       GROUP_MUTEX_UNLOCK (group);
       g_signal_connect (G_OBJECT (pad), "notify::caps",
           G_CALLBACK (caps_notify_group_cb), group);
@@ -1010,11 +1169,15 @@
  * Try to connect the given pad to an element created from one of the factories,
  * and recursively.
  *
+ * Note that dpad is ghosting pad, and so pad is linked; be sure to unset dpad's
+ * target before trying to link pad.
+ *
  * Returns TRUE if an element was properly created and linked
  */
 static gboolean
-connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
-    GstCaps * caps, GValueArray * factories, GstDecodeGroup * group)
+connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
+    GstPad * pad, GstCaps * caps, GValueArray * factories,
+    GstDecodeGroup * group)
 {
   gboolean res = FALSE;
   GstPad *mqpad = NULL;
@@ -1030,17 +1193,14 @@
     GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue");
 
     if (!group)
-      if (!(group = get_current_group (dbin))) {
-        group = gst_decode_group_new (dbin, TRUE);
-        DECODE_BIN_LOCK (dbin);
-        dbin->groups = g_list_append (dbin->groups, group);
-        DECODE_BIN_UNLOCK (dbin);
-      }
-
+      group = get_current_group (dbin, TRUE, TRUE, NULL);
+
+    gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL);
     if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad)))
       goto beach;
     src = group->multiqueue;
     pad = mqpad;
+    gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad);
   }
 
   /* 2. Try to create an element and link to it */
@@ -1049,6 +1209,7 @@
     GstElementFactory *factory;
     GstElement *element;
     GstPad *sinkpad;
+    gboolean subtitle;
 
     /* take first factory */
     factory = g_value_get_object (g_value_array_get_nth (factories, 0));
@@ -1058,7 +1219,7 @@
     /* emit autoplug-select to see what we should do with it. */
     g_signal_emit (G_OBJECT (dbin),
         gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT],
-        0, pad, caps, factory, &ret);
+        0, dpad, caps, factory, &ret);
 
     switch (ret) {
       case GST_AUTOPLUG_SELECT_TRY:
@@ -1067,7 +1228,7 @@
       case GST_AUTOPLUG_SELECT_EXPOSE:
         GST_DEBUG_OBJECT (dbin, "autoplug select requested expose");
         /* expose the pad, we don't have the source element */
-        expose_pad (dbin, src, pad, group);
+        expose_pad (dbin, src, dpad, pad, group);
         res = TRUE;
         goto beach;
       case GST_AUTOPLUG_SELECT_SKIP:
@@ -1078,6 +1239,9 @@
         break;
     }
 
+    /* 2.0. Unlink pad */
+    gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL);
+
     /* 2.1. Try to create an element */
     if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
       GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
@@ -1100,6 +1264,7 @@
     if (!(sinkpad = find_sink_pad (element))) {
       GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
           GST_ELEMENT_NAME (element));
+      gst_element_set_state (element, GST_STATE_NULL);
       gst_object_unref (element);
       continue;
     }
@@ -1109,6 +1274,7 @@
       GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
           GST_ELEMENT_NAME (element));
       gst_object_unref (sinkpad);
+      gst_element_set_state (element, GST_STATE_NULL);
       gst_object_unref (element);
       continue;
     }
@@ -1128,6 +1294,17 @@
     /* link this element further */
     connect_element (dbin, element, group);
 
+    /* try to configure the subtitle encoding property when we can */
+    if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
+            "subtitle-encoding")) {
+      GST_DEBUG_OBJECT (dbin,
+          "setting subtitle-encoding=%s to element", dbin->encoding);
+      g_object_set (G_OBJECT (element), "subtitle-encoding", dbin->encoding,
+          NULL);
+      subtitle = TRUE;
+    } else
+      subtitle = FALSE;
+
     /* Bring the element to the state of the parent */
     if ((gst_element_set_state (element,
                 GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
@@ -1137,6 +1314,13 @@
       gst_bin_remove (GST_BIN (dbin), element);
       continue;
     }
+    if (subtitle) {
+      DECODE_BIN_LOCK (dbin);
+      /* we added the element now, add it to the list of subtitle-encoding
+       * elements when we can set the property */
+      dbin->subtitles = g_list_prepend (dbin->subtitles, element);
+      DECODE_BIN_UNLOCK (dbin);
+    }
 
     res = TRUE;
     break;
@@ -1179,7 +1363,7 @@
       case GST_PAD_ALWAYS:
       {
         /* get the pad that we need to autoplug */
-        GstPad *pad = gst_element_get_pad (element, templ_name);
+        GstPad *pad = gst_element_get_static_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (dbin, "got the pad for always template %s",
@@ -1198,7 +1382,7 @@
       {
         /* try to get the pad to see if it is already created or
          * not */
-        GstPad *pad = gst_element_get_pad (element, templ_name);
+        GstPad *pad = gst_element_get_static_pad (element, templ_name);
 
         if (pad) {
           GST_DEBUG_OBJECT (dbin, "got the pad for sometimes template %s",
@@ -1223,11 +1407,12 @@
   /* 2. if there are more potential pads, connect to relevent signals */
   if (dynamic) {
     if (group) {
-      GST_LOG ("Adding signals to element %s in group %p",
+      GST_LOG_OBJECT (dbin, "Adding signals to element %s in group %p",
           GST_ELEMENT_NAME (element), group);
       GROUP_MUTEX_LOCK (group);
       group->nbdynamic++;
-      GST_LOG ("Group %p has now %d dynamic elements", group, group->nbdynamic);
+      GST_LOG_OBJECT (dbin, "Group %p has now %d dynamic elements", group,
+          group->nbdynamic);
       GROUP_MUTEX_UNLOCK (group);
       g_signal_connect (G_OBJECT (element), "pad-added",
           G_CALLBACK (pad_added_group_cb), group);
@@ -1269,8 +1454,8 @@
  * If group is NULL, a GstDecodeGroup will be created and setup properly.
  */
 static void
-expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
-    GstDecodeGroup * group)
+expose_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
+    GstPad * pad, GstDecodeGroup * group)
 {
   gboolean newgroup = FALSE;
   gboolean isdemux;
@@ -1282,23 +1467,19 @@
   isdemux = is_demuxer_element (src);
 
   if (!group)
-    if (!(group = get_current_group (dbin))) {
-      group = gst_decode_group_new (dbin, isdemux);
-      DECODE_BIN_LOCK (dbin);
-      dbin->groups = g_list_append (dbin->groups, group);
-      DECODE_BIN_UNLOCK (dbin);
-      newgroup = TRUE;
-    }
+    group = get_current_group (dbin, TRUE, isdemux, &newgroup);
 
   if (isdemux) {
     GST_LOG_OBJECT (src, "connecting the pad through multiqueue");
 
+    gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL);
     if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad)))
       goto beach;
     pad = mqpad;
+    gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad);
   }
 
-  gst_decode_group_control_source_pad (group, pad);
+  gst_decode_group_control_source_pad (group, dpad);
 
   if (newgroup && !isdemux) {
     /* If we have discovered a raw pad and it doesn't belong to any group,
@@ -1321,6 +1502,16 @@
 
   GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps);
 
+  /* If the typefinder (but not something else) finds text/plain - i.e. that's
+   * the top-level type of the file - then error out.
+   */
+  if (gst_structure_has_name (gst_caps_get_structure (caps, 0), "text/plain")) {
+    GST_ELEMENT_ERROR (decode_bin, STREAM, WRONG_TYPE,
+        (_("This appears to be a text file")),
+        ("decodebin2 cannot decode plain text files"));
+    goto exit;
+  }
+
   /* we can only deal with one type, we don't yet support dynamically changing
    * caps from the typefind element */
   if (decode_bin->have_type)
@@ -1343,27 +1534,33 @@
 {
   GstCaps *caps;
   gboolean expose = FALSE;
+  GstDecodeBin *dbin;
+
+  dbin = group->dbin;
 
   GST_DEBUG_OBJECT (pad, "pad added, group:%p", group);
 
   caps = gst_pad_get_caps (pad);
-  analyze_new_pad (group->dbin, element, pad, caps, group);
+  analyze_new_pad (dbin, element, pad, caps, group);
   if (caps)
     gst_caps_unref (caps);
 
   GROUP_MUTEX_LOCK (group);
-  group->nbdynamic--;
-  GST_LOG ("Group %p has now %d dynamic objects", group, group->nbdynamic);
+  if (group->nbdynamic > 0)
+    group->nbdynamic--;
+  GST_LOG_OBJECT (dbin, "Group %p has now %d dynamic objects", group,
+      group->nbdynamic);
   if (group->nbdynamic == 0)
     expose = TRUE;
   GROUP_MUTEX_UNLOCK (group);
 
   if (expose) {
-    GST_LOG
-        ("That was the last dynamic object, now attempting to expose the group");
-    DECODE_BIN_LOCK (group->dbin);
-    gst_decode_group_expose (group);
-    DECODE_BIN_UNLOCK (group->dbin);
+    GST_LOG_OBJECT (dbin,
+        "That was the last dynamic object, now attempting to expose the group");
+    DECODE_BIN_LOCK (dbin);
+    if (!gst_decode_group_expose (group))
+      GST_WARNING_OBJECT (dbin, "Couldn't expose group");
+    DECODE_BIN_UNLOCK (dbin);
   }
 }
 
@@ -1382,7 +1579,7 @@
 {
   GST_LOG_OBJECT (element, "no more pads, setting group %p to complete", group);
 
-  /* FIXME : FILLME */
+  /* when we received no_more_pads, we can complete the pads of the group */
   gst_decode_group_set_complete (group);
 }
 
@@ -1413,15 +1610,16 @@
   GST_LOG_OBJECT (element, "No more pads, setting current group to complete");
 
   /* Find the non-complete group, there should only be one */
-  if (!(group = get_current_group (dbin)))
+  if (!(group = get_current_group (dbin, FALSE, FALSE, NULL)))
     goto no_group;
 
   gst_decode_group_set_complete (group);
+
   return;
 
 no_group:
   {
-    GST_WARNING_OBJECT (dbin, "We couldn't find a non-completed group !!");
+    GST_DEBUG_OBJECT (dbin, "We couldn't find a non-completed group");
     return;
   }
 }
@@ -1434,6 +1632,10 @@
   GST_LOG_OBJECT (dbin, "Notified caps for pad %s:%s",
       GST_DEBUG_PAD_NAME (pad));
 
+  /* Disconnect this; if we still need it, we'll reconnect to this in
+   * analyze_new_pad */
+  g_signal_handlers_disconnect_by_func (pad, (gpointer*)caps_notify_cb, dbin);
+
   element = GST_ELEMENT_CAST (gst_pad_get_parent (pad));
 
   pad_added_cb (element, pad, dbin);
@@ -1448,6 +1650,10 @@
 
   GST_LOG_OBJECT (pad, "Notified caps for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
+  /* Disconnect this; if we still need it, we'll reconnect to this in
+   * analyze_new_pad */
+  g_signal_handlers_disconnect_by_func (pad, (gpointer*)caps_notify_group_cb, group);
+
   element = GST_ELEMENT_CAST (gst_pad_get_parent (pad));
 
   pad_added_group_cb (element, pad, group);
@@ -1455,21 +1661,6 @@
   gst_object_unref (element);
 }
 
-/* this function runs through the element factories and returns a value array of
- * all elements that are able to sink the given caps
- */
-static GValueArray *
-find_compatibles (GstDecodeBin * decode_bin, GstPad * pad, const GstCaps * caps)
-{
-  GValueArray *result;
-
-  GST_DEBUG_OBJECT (decode_bin, "finding factories");
-
-  result = gst_factory_list_filter (decode_bin->factories, caps);
-
-  return result;
-}
-
 /* Decide whether an element is a demuxer based on the 
  * klass and number/type of src pad templates it has */
 static gboolean
@@ -1533,7 +1724,10 @@
 
   GST_LOG_OBJECT (dbin, "Checking with caps %" GST_PTR_FORMAT, caps);
 
+  /* lock for getting the caps */
+  GST_OBJECT_LOCK (dbin);
   intersection = gst_caps_intersect (dbin->caps, caps);
+  GST_OBJECT_UNLOCK (dbin);
 
   res = (!(gst_caps_is_empty (intersection)));
 
@@ -1549,38 +1743,45 @@
  * GstDecodeGroup functions
  ****/
 
+/* The overrun callback is used to expose groups that have not yet had their
+ * no_more_pads called while the (large) multiqueue overflowed. When this
+ * happens we must assume that the no_more_pads will not arrive anymore and we
+ * must expose the pads that we have. 
+ */
 static void
 multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group)
 {
-  GST_LOG_OBJECT (group->dbin, "multiqueue is full");
-
-  /* if we haven't exposed the group, do it */
-  DECODE_BIN_LOCK (group->dbin);
-  gst_decode_group_expose (group);
-  DECODE_BIN_UNLOCK (group->dbin);
+  GstDecodeBin *dbin;
+  gboolean expose;
+
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "multiqueue %p is full", queue);
+
+  GROUP_MUTEX_LOCK (group);
+  if (group->complete) {
+    /* the group was already complete (had the no_more_pads called), we
+     * can ignore the overrun signal, the last remaining dynamic element
+     * will expose the group eventually. */
+    GST_LOG_OBJECT (dbin, "group %p was already complete", group);
+    expose = FALSE;
+  } else {
+    /* set number of dynamic element to 0, we don't expect anything anymore
+     * and we need the groups to be 0 for the expose to work */
+    group->nbdynamic = 0;
+    expose = TRUE;
+  }
+  GROUP_MUTEX_UNLOCK (group);
+
+  if (expose) {
+    DECODE_BIN_LOCK (dbin);
+    if (!gst_decode_group_expose (group))
+      GST_WARNING_OBJECT (dbin, "Couldn't expose group");
+    DECODE_BIN_UNLOCK (group->dbin);
+  }
 }
 
-static void
-multi_queue_underrun_cb (GstElement * queue, GstDecodeGroup * group)
-{
-  GstDecodeBin *dbin = group->dbin;
-
-  GST_LOG_OBJECT (dbin, "multiqueue is empty for group %p", group);
-
-  /* Check if we need to activate another group */
-  DECODE_BIN_LOCK (dbin);
-  if ((group == dbin->activegroup) && dbin->groups) {
-    GST_DEBUG_OBJECT (dbin, "Switching to new group");
-    /* unexpose current active */
-    gst_decode_group_hide (group);
-
-    /* expose first group of groups */
-    gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
-  }
-  DECODE_BIN_UNLOCK (dbin);
-}
-
-/* gst_decode_group_new
+/* gst_decode_group_new:
  *
  * Creates a new GstDecodeGroup. It is up to the caller to add it to the list
  * of groups.
@@ -1595,7 +1796,7 @@
 
   if (use_queue) {
     if (!(mq = gst_element_factory_make ("multiqueue", NULL))) {
-      GST_WARNING ("Couldn't create multiqueue element");
+      GST_ERROR_OBJECT (dbin, "Couldn't create multiqueue element");
       return NULL;
     }
   } else {
@@ -1619,15 +1820,11 @@
      * memory. When this queue overruns, we assume the group is complete and can
      * be exposed. */
     g_object_set (G_OBJECT (mq),
-        "max-size-bytes", 2 * 1024 * 1024,
-        "max-size-time", 5 * GST_SECOND, "max-size-buffers", 0, NULL);
+        "max-size-bytes", (guint) 2 * 1024 * 1024,
+        "max-size-time", (guint64) 0, "max-size-buffers", (guint) 0, NULL);
     /* will expose the group */
     group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun",
         G_CALLBACK (multi_queue_overrun_cb), group);
-    /* will hide the group again, this is usually called when the multiqueue is
-     * drained because of EOS. */
-    group->underrunsig = g_signal_connect (G_OBJECT (mq), "underrun",
-        G_CALLBACK (multi_queue_underrun_cb), group);
 
     gst_bin_add (GST_BIN (dbin), mq);
     gst_element_set_state (mq, GST_STATE_PAUSED);
@@ -1638,14 +1835,20 @@
   return group;
 }
 
-/** get_current_group:
+/* get_current_group:
+ * @dbin: the decodebin
+ * @create: create the group when not present
+ * @as_demux: create the group as a demuxer
+ * @created: result when the group was created
  *
- * Returns the current non-completed group.
+ * Returns the current non-completed group. The dynamic refcount of the group is
+ * increased when dealing with a demuxer.
  *
- * Returns NULL if no groups are available, or all groups are completed.
+ * Returns: %NULL if no groups are available, or all groups are completed.
  */
 static GstDecodeGroup *
-get_current_group (GstDecodeBin * dbin)
+get_current_group (GstDecodeBin * dbin, gboolean create, gboolean as_demux,
+    gboolean * created)
 {
   GList *tmp;
   GstDecodeGroup *group = NULL;
@@ -1654,13 +1857,27 @@
   for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) {
     GstDecodeGroup *this = (GstDecodeGroup *) tmp->data;
 
+    GROUP_MUTEX_LOCK (this);
     GST_LOG_OBJECT (dbin, "group %p, complete:%d", this, this->complete);
 
     if (!this->complete) {
       group = this;
+      GROUP_MUTEX_UNLOCK (this);
       break;
+    } else {
+      GROUP_MUTEX_UNLOCK (this);
     }
   }
+  if (group == NULL && create) {
+    group = gst_decode_group_new (dbin, as_demux);
+    GST_LOG_OBJECT (dbin, "added group %p, demux %d", group, as_demux);
+    dbin->groups = g_list_prepend (dbin->groups, group);
+    if (created)
+      *created = TRUE;
+    /* demuxers are dynamic, we need no-more-pads or overrun now */
+    if (as_demux)
+      group->nbdynamic++;
+  }
   DECODE_BIN_UNLOCK (dbin);
 
   GST_LOG_OBJECT (dbin, "Returning group %p", group);
@@ -1668,20 +1885,6 @@
   return group;
 }
 
-static gboolean
-group_demuxer_event_probe (GstPad * pad, GstEvent * event,
-    GstDecodeGroup * group)
-{
-  if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
-    GST_DEBUG_OBJECT (group->dbin,
-        "Got EOS on group input pads, exposing group if it wasn't before");
-    DECODE_BIN_LOCK (group->dbin);
-    gst_decode_group_expose (group);
-    DECODE_BIN_UNLOCK (group->dbin);
-  }
-  return TRUE;
-}
-
 /* gst_decode_group_control_demuxer_pad
  *
  * Adds a new demuxer srcpad to the given group.
@@ -1692,24 +1895,27 @@
 static GstPad *
 gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad)
 {
+  GstDecodeBin *dbin;
   GstPad *srcpad, *sinkpad;
   gchar *nb, *sinkname, *srcname;
 
-  GST_LOG ("group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
 
   srcpad = NULL;
 
   if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink%d"))) {
-    GST_ERROR ("Couldn't get sinkpad from multiqueue");
+    GST_ERROR_OBJECT (dbin, "Couldn't get sinkpad from multiqueue");
     return NULL;
   }
 
   if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) {
-    GST_ERROR ("Couldn't link demuxer and multiqueue");
+    GST_ERROR_OBJECT (dbin, "Couldn't link demuxer and multiqueue");
     goto beach;
   }
 
-  group->reqpads = g_list_append (group->reqpads, sinkpad);
+  group->reqpads = g_list_prepend (group->reqpads, sinkpad);
 
   sinkname = gst_pad_get_name (sinkpad);
   nb = sinkname + 4;
@@ -1718,14 +1924,11 @@
 
   GROUP_MUTEX_LOCK (group);
 
-  if (!(srcpad = gst_element_get_pad (group->multiqueue, srcname))) {
-    GST_ERROR ("Couldn't get srcpad %s from multiqueue", srcname);
+  if (!(srcpad = gst_element_get_static_pad (group->multiqueue, srcname))) {
+    GST_ERROR_OBJECT (dbin, "Couldn't get srcpad %s from multiqueue", srcname);
     goto chiringuito;
   }
 
-  /* connect event handler on pad to intercept EOS events */
-  gst_pad_add_event_probe (pad, G_CALLBACK (group_demuxer_event_probe), group);
-
 chiringuito:
   g_free (srcname);
   GROUP_MUTEX_UNLOCK (group);
@@ -1736,23 +1939,18 @@
 }
 
 static gboolean
-gst_decode_group_control_source_pad (GstDecodeGroup * group, GstPad * pad)
+gst_decode_group_control_source_pad (GstDecodeGroup * group,
+    GstDecodePad * dpad)
 {
-  GstDecodePad *dpad;
-
   g_return_val_if_fail (group != NULL, FALSE);
 
-  GST_LOG ("group:%p , pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
+  GST_DEBUG_OBJECT (dpad, "adding decode pad to group %p", group);
 
   /* FIXME : check if pad is already controlled */
+  gst_decode_pad_activate (dpad, group);
 
   GROUP_MUTEX_LOCK (group);
-
-  /* Create GstDecodePad for the pad */
-  dpad = gst_decode_pad_new (group, pad, TRUE);
-
-  group->endpads = g_list_append (group->endpads, dpad);
-
+  group->endpads = g_list_prepend (group->endpads, gst_object_ref (dpad));
   GROUP_MUTEX_UNLOCK (group);
 
   return TRUE;
@@ -1765,20 +1963,25 @@
  * and will ghost/expose all pads on decodebin if the group is the current one.
  *
  * Call with the group lock taken ! MT safe
+ *
+ * Returns: TRUE when the group is completely blocked and ready to be exposed.
  */
-static void
+static gboolean
 gst_decode_group_check_if_blocked (GstDecodeGroup * group)
 {
+  GstDecodeBin *dbin;
   GList *tmp;
   gboolean blocked = TRUE;
 
-  GST_LOG ("group : %p , ->complete:%d , ->nbdynamic:%d",
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "group : %p , ->complete:%d , ->nbdynamic:%d",
       group, group->complete, group->nbdynamic);
 
-  /* 1. don't do anything if group is not complete */
+  /* don't do anything if group is not complete */
   if (!group->complete || group->nbdynamic) {
     GST_DEBUG_OBJECT (group->dbin, "Group isn't complete yet");
-    return;
+    return FALSE;
   }
 
   for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
@@ -1790,64 +1993,100 @@
     }
   }
 
-  /* 2. Update status of group */
+  /* Update status of group */
   group->blocked = blocked;
-  GST_LOG ("group is blocked:%d", blocked);
-
-  /* 3. don't do anything if not blocked completely */
-  if (!blocked)
-    return;
-
-  /* 4. if we're the current group, expose pads */
-  DECODE_BIN_LOCK (group->dbin);
-  if (!gst_decode_group_expose (group))
-    GST_WARNING_OBJECT (group->dbin, "Couldn't expose group");
-  DECODE_BIN_UNLOCK (group->dbin);
+  GST_LOG_OBJECT (dbin, "group is blocked:%d", blocked);
+
+  return blocked;
 }
 
+/* activate the next group when there is one
+ *
+ * Returns: TRUE when group was the active group and there was a
+ * next group to activate.
+ */
+static gboolean
+gst_decode_bin_activate_next_group (GstDecodeBin * dbin, GstDecodeGroup * group)
+{
+  gboolean have_next = FALSE;
+
+  DECODE_BIN_LOCK (dbin);
+  /* Check if there is a next group to activate */
+  if ((group == dbin->activegroup) && dbin->groups) {
+    GstDecodeGroup *newgroup;
+
+    /* get the next group */
+    newgroup = (GstDecodeGroup *) dbin->groups->data;
+
+    GST_DEBUG_OBJECT (dbin, "Switching to new group");
+
+    /* hide current group */
+    gst_decode_group_hide (group);
+    /* expose next group */
+    gst_decode_group_expose (newgroup);
+
+    /* we have a next group */
+    have_next = TRUE;
+  }
+  DECODE_BIN_UNLOCK (dbin);
+
+  return have_next;
+}
+
+/* check if the group is drained, meaning all pads have seen an EOS 
+ * event.  */
 static void
-gst_decode_group_check_if_drained (GstDecodeGroup * group)
+gst_decode_pad_handle_eos (GstDecodePad * pad)
 {
   GList *tmp;
-  GstDecodeBin *dbin = group->dbin;
+  GstDecodeBin *dbin;
+  GstDecodeGroup *group;
   gboolean drained = TRUE;
 
-  GST_LOG ("group : %p", group);
+  group = pad->group;
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "group : %p, pad %p", group, pad);
+
+  GROUP_MUTEX_LOCK (group);
+  /* mark pad as drained */
+  pad->drained = TRUE;
+
+  /* Ensure we only emit the drained signal once, for this group */
+  if (group->drained)
+    goto was_drained;
 
   for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
 
-    GST_LOG ("testing dpad %p", dpad);
+    GST_LOG_OBJECT (dbin, "testing dpad %p %d", dpad, dpad->drained);
 
     if (!dpad->drained) {
       drained = FALSE;
       break;
     }
   }
-
   group->drained = drained;
-  if (!drained)
-    return;
-
-  /* we are drained. Check if there is a next group to activate */
-  DECODE_BIN_LOCK (dbin);
-  if ((group == dbin->activegroup) && dbin->groups) {
-    GST_DEBUG_OBJECT (dbin, "Switching to new group");
-
-    /* hide current group */
-    gst_decode_group_hide (group);
-    /* expose next group */
-    gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
-    /* we're not yet drained now */
-    drained = FALSE;
-  }
-  DECODE_BIN_UNLOCK (dbin);
+  GROUP_MUTEX_UNLOCK (group);
 
   if (drained) {
-    /* no more groups to activate, we're completely drained now */
-    GST_LOG ("all groups drained, fire signal");
-    g_signal_emit (G_OBJECT (dbin), gst_decode_bin_signals[SIGNAL_DRAINED], 0,
-        NULL);
+    /* the current group is completely drained, try to activate the next
+     * group. this function returns FALSE if there was no next group activated
+     * and so we are really drained. */
+    if (!gst_decode_bin_activate_next_group (dbin, group)) {
+      /* no more groups to activate, we're completely drained now */
+      GST_LOG_OBJECT (dbin, "all groups drained, fire signal");
+      g_signal_emit (G_OBJECT (dbin), gst_decode_bin_signals[SIGNAL_DRAINED], 0,
+          NULL);
+    }
+  }
+  return;
+
+was_drained:
+  {
+    GST_LOG_OBJECT (dbin, "group was already drained");
+    GROUP_MUTEX_UNLOCK (group);
+    return;
   }
 }
 
@@ -1863,17 +2102,13 @@
 static gint
 sort_end_pads (GstDecodePad * da, GstDecodePad * db)
 {
-  GstPad *a, *b;
   gint va, vb;
   GstCaps *capsa, *capsb;
   GstStructure *sa, *sb;
   const gchar *namea, *nameb;
 
-  a = da->pad;
-  b = db->pad;
-
-  capsa = gst_pad_get_caps (a);
-  capsb = gst_pad_get_caps (b);
+  capsa = gst_pad_get_caps (GST_PAD (da));
+  capsb = gst_pad_get_caps (GST_PAD (db));
 
   sa = gst_caps_get_structure ((const GstCaps *) capsa, 0);
   sb = gst_caps_get_structure ((const GstCaps *) capsb, 0);
@@ -1913,146 +2148,159 @@
  *
  * Expose this group's pads.
  *
- * Not MT safe, please take the group lock
+ * Not MT safe, please take the decodebin lock
  */
 static gboolean
 gst_decode_group_expose (GstDecodeGroup * group)
 {
   GList *tmp;
   GList *next = NULL;
-
-  if (group->dbin->activegroup) {
-    GST_DEBUG_OBJECT (group->dbin, "A group is already active and exposed");
-    return TRUE;
+  GstDecodeBin *dbin;
+
+  dbin = group->dbin;
+
+  GST_DEBUG_OBJECT (dbin, "going to expose group %p", group);
+
+  if (group->nbdynamic) {
+    GST_DEBUG_OBJECT (dbin,
+        "Group %p still has %d dynamic objects, not exposing yet", group,
+        group->nbdynamic);
+    return FALSE;
   }
 
-  if (group->dbin->activegroup == group) {
-    GST_WARNING ("Group %p is already exposed", group);
+  if (dbin->activegroup == group) {
+    GST_DEBUG_OBJECT (dbin, "Group %p is already exposed, all is fine", group);
     return TRUE;
   }
 
-  if (!group->dbin->groups
-      || (group != (GstDecodeGroup *) group->dbin->groups->data)) {
-    GST_WARNING ("Group %p is not the first group to expose", group);
-    return FALSE;
-  }
-
-  if (group->nbdynamic) {
-    GST_WARNING ("Group %p still has %d dynamic objects, not exposing yet",
-        group, group->nbdynamic);
-    return FALSE;
-  }
-
-  GST_LOG ("Exposing group %p", group);
-
   if (group->multiqueue) {
     /* update runtime limits. At runtime, we try to keep the amount of buffers
      * in the queues as low as possible (but at least 5 buffers). */
     g_object_set (G_OBJECT (group->multiqueue),
-        "max-size-bytes", 2 * 1024 * 1024,
-        "max-size-time", 2 * GST_SECOND, "max-size-buffers", 5, NULL);
+        "max-size-bytes", 2 * 1024 * 1024, "max-size-buffers", 5, NULL);
     /* we can now disconnect any overrun signal, which is used to expose the
      * group. */
     if (group->overrunsig) {
-      GST_LOG ("Disconnecting overrun");
+      GST_LOG_OBJECT (dbin, "Disconnecting overrun");
       g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
       group->overrunsig = 0;
     }
   }
 
+  if (dbin->activegroup) {
+    GST_DEBUG_OBJECT (dbin,
+        "another group %p is already exposed, waiting for EOS",
+        dbin->activegroup);
+    return TRUE;
+  }
+
+  if (!dbin->groups || (group != (GstDecodeGroup *) dbin->groups->data)) {
+    GST_WARNING_OBJECT (dbin, "Group %p is not the first group to expose",
+        group);
+    return FALSE;
+  }
+
+  GST_LOG_OBJECT (dbin, "Exposing group %p", group);
+
   /* re-order pads : video, then audio, then others */
   group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads);
 
   /* Expose pads */
-
   for (tmp = group->endpads; tmp; tmp = next) {
     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
     gchar *padname;
-    GstPad *ghost;
 
     next = g_list_next (tmp);
 
-    /* 1. ghost pad */
-    padname = g_strdup_printf ("src%d", group->dbin->nbpads);
-    group->dbin->nbpads++;
-
-    GST_LOG_OBJECT (group->dbin, "About to expose pad %s:%s",
-        GST_DEBUG_PAD_NAME (dpad->pad));
-
-    ghost = gst_ghost_pad_new (padname, dpad->pad);
-    gst_pad_set_active (ghost, TRUE);
-    gst_element_add_pad (GST_ELEMENT (group->dbin), ghost);
-    group->ghosts = g_list_append (group->ghosts, ghost);
-
+    /* 1. rewrite name */
+    padname = g_strdup_printf ("src%d", dbin->nbpads);
+    dbin->nbpads++;
+    GST_DEBUG_OBJECT (dbin, "About to expose dpad %s as %s",
+        GST_OBJECT_NAME (dpad), padname);
+    gst_object_set_name (GST_OBJECT (dpad), padname);
     g_free (padname);
 
-    /* 2. emit signal */
-    GST_DEBUG_OBJECT (group->dbin, "emitting new-decoded-pad");
-    g_signal_emit (G_OBJECT (group->dbin),
-        gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost,
+    /* 2. activate and add */
+    if (!gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD (dpad))) {
+      /* not really fatal, we can try to add the other pads */
+      g_warning ("error adding pad to decodebin2");
+      continue;
+    }
+    dpad->added = TRUE;
+
+    /* 3. emit signal */
+    GST_DEBUG_OBJECT (dbin, "emitting new-decoded-pad");
+    g_signal_emit (G_OBJECT (dbin),
+        gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, dpad,
         (next == NULL));
-    GST_DEBUG_OBJECT (group->dbin, "emitted new-decoded-pad");
+    GST_DEBUG_OBJECT (dbin, "emitted new-decoded-pad");
   }
 
   /* signal no-more-pads. This allows the application to hook stuff to the
    * exposed pads */
-  GST_LOG_OBJECT (group->dbin, "signalling no-more-pads");
-  gst_element_no_more_pads (GST_ELEMENT (group->dbin));
-
-  /* 3. Unblock internal pads. The application should have connected stuff now
+  GST_LOG_OBJECT (dbin, "signalling no-more-pads");
+  gst_element_no_more_pads (GST_ELEMENT (dbin));
+
+  /* 4. Unblock internal pads. The application should have connected stuff now
    * so that streaming can continue. */
   for (tmp = group->endpads; tmp; tmp = next) {
     GstDecodePad *dpad = (GstDecodePad *) tmp->data;
 
     next = g_list_next (tmp);
 
-    GST_DEBUG_OBJECT (dpad->pad, "unblocking");
-    gst_pad_set_blocked_async (dpad->pad, FALSE,
-        (GstPadBlockCallback) source_pad_blocked_cb, dpad);
-    GST_DEBUG_OBJECT (dpad->pad, "unblocked");
+    GST_DEBUG_OBJECT (dpad, "unblocking");
+    gst_decode_pad_unblock (dpad);
+    GST_DEBUG_OBJECT (dpad, "unblocked");
   }
 
-  group->dbin->activegroup = group;
+  dbin->activegroup = group;
 
   /* pop off the first group */
-  group->dbin->groups =
-      g_list_delete_link (group->dbin->groups, group->dbin->groups);
-
-  remove_fakesink (group->dbin);
+  if (dbin->groups && dbin->groups->data) {
+    GST_LOG_OBJECT (dbin, "removed group %p", dbin->groups->data);
+    dbin->groups = g_list_delete_link (dbin->groups, dbin->groups);
+  } else {
+    GST_LOG_OBJECT (dbin, "no more groups");
+  }
+
+  do_async_done (dbin);
 
   group->exposed = TRUE;
 
-  GST_LOG_OBJECT (group->dbin, "Group %p exposed", group);
+  GST_LOG_OBJECT (dbin, "Group %p exposed", group);
   return TRUE;
 }
 
+/* must be called with the decodebin lock */
 static void
 gst_decode_group_hide (GstDecodeGroup * group)
 {
   GList *tmp;
-
-  GST_LOG ("Hiding group %p", group);
-
-  if (group != group->dbin->activegroup) {
-    GST_WARNING ("This group is not the active one, aborting");
+  GstDecodeBin *dbin;
+
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "Hiding group %p", group);
+
+  if (group != dbin->activegroup) {
+    GST_WARNING_OBJECT (dbin, "This group is not the active one, ignoring");
     return;
   }
 
   GROUP_MUTEX_LOCK (group);
-
   /* Remove ghost pads */
-  for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp))
-    gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data);
-
-  g_list_free (group->ghosts);
-  group->ghosts = NULL;
-
+  for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
+    GstDecodePad *dpad = (GstDecodePad *) tmp->data;
+
+    if (dpad->added)
+      gst_element_remove_pad (GST_ELEMENT (group->dbin), GST_PAD (dpad));
+    dpad->added = FALSE;
+  }
   group->exposed = FALSE;
-
   GROUP_MUTEX_UNLOCK (group);
 
   group->dbin->activegroup = NULL;
-  group->dbin->oldgroups = g_list_append (group->dbin->oldgroups, group);
+  group->dbin->oldgroups = g_list_prepend (group->dbin->oldgroups, group);
 }
 
 static void
@@ -2061,8 +2309,11 @@
   GstIterator *it;
   GstIteratorResult res;
   gpointer point;
-
-  GST_LOG ("element:%s", GST_ELEMENT_NAME (element));
+  GstDecodeBin *dbin;
+
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "element:%s", GST_ELEMENT_NAME (element));
 
   /* call on downstream elements */
   it = gst_element_iterate_src_pads (element);
@@ -2079,7 +2330,8 @@
         goto restart;
       case GST_ITERATOR_ERROR:
       {
-        GST_WARNING ("Had an error while iterating source pads of element: %s",
+        GST_WARNING_OBJECT (dbin,
+            "Had an error while iterating source pads of element: %s",
             GST_ELEMENT_NAME (element));
         goto beach;
       }
@@ -2108,7 +2360,11 @@
 
 done:
   gst_element_set_state (element, GST_STATE_NULL);
-  gst_bin_remove (GST_BIN (group->dbin), element);
+  DECODE_BIN_LOCK (dbin);
+  /* remove possible subtitle element */
+  dbin->subtitles = g_list_remove (dbin->subtitles, element);
+  DECODE_BIN_UNLOCK (dbin);
+  gst_bin_remove (GST_BIN (dbin), element);
 
 beach:
   gst_iterator_free (it);
@@ -2119,27 +2375,29 @@
 static void
 gst_decode_group_free (GstDecodeGroup * group)
 {
+  GstDecodeBin *dbin;
   GList *tmp;
 
-  GST_LOG ("group %p", group);
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "group %p", group);
 
   GROUP_MUTEX_LOCK (group);
 
-  /* free ghost pads */
-  if (group == group->dbin->activegroup) {
-    for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp))
-      gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data);
-
-    g_list_free (group->ghosts);
-    group->ghosts = NULL;
+  /* remove exposed pads */
+  if (group == dbin->activegroup) {
+    for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
+      GstDecodePad *dpad = (GstDecodePad *) tmp->data;
+
+      if (dpad->added)
+        gst_element_remove_pad (GST_ELEMENT (dbin), GST_PAD (dpad));
+      dpad->added = FALSE;
+    }
   }
 
   /* Clear all GstDecodePad */
-  for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
-    GstDecodePad *dpad = (GstDecodePad *) tmp->data;
-
-    g_free (dpad);
-  }
+  for (tmp = group->endpads; tmp; tmp = g_list_next (tmp))
+    gst_object_unref (tmp->data);
   g_list_free (group->endpads);
   group->endpads = NULL;
 
@@ -2152,8 +2410,6 @@
 
   /* disconnect signal handlers on multiqueue */
   if (group->multiqueue) {
-    if (group->underrunsig)
-      g_signal_handler_disconnect (group->multiqueue, group->underrunsig);
     if (group->overrunsig)
       g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
     deactivate_free_recursive (group, group->multiqueue);
@@ -2170,40 +2426,85 @@
 /* gst_decode_group_set_complete:
  *
  * Mark the group as complete. This means no more streams will be controlled
- * through this group.
+ * through this group. This method is usually called when we got no_more_pads or
+ * when we added the last pad not from a demuxer.
+ *
+ * When this method is called, it is possible that some dynamic plugging is
+ * going on in streaming threads. We decrement the dynamic counter and when it
+ * reaches zero, we check if all of our pads are blocked before we finally
+ * expose the group.
  *
  * MT safe
  */
 static void
 gst_decode_group_set_complete (GstDecodeGroup * group)
 {
-  GST_LOG_OBJECT (group->dbin, "Setting group %p to COMPLETE", group);
+  gboolean expose = FALSE;
+  GstDecodeBin *dbin;
+
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dbin, "Setting group %p to COMPLETE", group);
 
   GROUP_MUTEX_LOCK (group);
   group->complete = TRUE;
-  gst_decode_group_check_if_blocked (group);
+  if (group->nbdynamic > 0)
+    group->nbdynamic--;
+  expose = gst_decode_group_check_if_blocked (group);
   GROUP_MUTEX_UNLOCK (group);
+
+  /* don't do anything if not blocked completely */
+  if (expose) {
+    DECODE_BIN_LOCK (dbin);
+    if (!gst_decode_group_expose (group))
+      GST_WARNING_OBJECT (dbin, "Couldn't expose group");
+    DECODE_BIN_UNLOCK (dbin);
+  }
 }
 
-
-
 /*************************
  * GstDecodePad functions
  *************************/
 
 static void
-source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad)
+gst_decode_pad_class_init (GstDecodePadClass * klass)
+{
+}
+
+static void
+gst_decode_pad_init (GstDecodePad * pad)
 {
-  GST_LOG_OBJECT (pad, "blocked:%d , dpad:%p, dpad->group:%p",
-      blocked, dpad, dpad->group);
-
+  pad->group = NULL;
+  pad->blocked = FALSE;
+  pad->drained = FALSE;
+  gst_object_ref (pad);
+  gst_object_sink (pad);
+}
+
+static void
+source_pad_blocked_cb (GstDecodePad * dpad, gboolean blocked, gpointer unused)
+{
+  GstDecodeGroup *group;
+  GstDecodeBin *dbin;
+  gboolean expose = FALSE;
+
+  group = dpad->group;
+  dbin = group->dbin;
+
+  GST_LOG_OBJECT (dpad, "blocked:%d, dpad->group:%p", blocked, group);
+
+  GROUP_MUTEX_LOCK (group);
   /* Update this GstDecodePad status */
   dpad->blocked = blocked;
-
-  if (blocked) {
-    GROUP_MUTEX_LOCK (dpad->group);
-    gst_decode_group_check_if_blocked (dpad->group);
-    GROUP_MUTEX_UNLOCK (dpad->group);
+  if (blocked)
+    expose = gst_decode_group_check_if_blocked (group);
+  GROUP_MUTEX_UNLOCK (group);
+
+  if (expose) {
+    DECODE_BIN_LOCK (dbin);
+    if (!gst_decode_group_expose (group))
+      GST_WARNING_OBJECT (dbin, "Couldn't expose group");
+    DECODE_BIN_UNLOCK (dbin);
   }
 }
 
@@ -2213,40 +2514,82 @@
   GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad);
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
-    /* Set our pad as drained */
-    dpad->drained = TRUE;
-
     GST_DEBUG_OBJECT (pad, "we received EOS");
 
     /* Check if all pads are drained. If there is a next group to expose, we
      * will remove the ghostpad of the current group first, which unlinks the
      * peer and so drops the EOS. */
-    gst_decode_group_check_if_drained (dpad->group);
+    gst_decode_pad_handle_eos (dpad);
   }
   /* never drop events */
   return TRUE;
 }
 
+static void
+gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked)
+{
+  GstDecodeBin *dbin = dpad->dbin;
+
+  DECODE_BIN_DYN_LOCK (dbin);
+  gst_pad_set_blocked_async (GST_PAD (dpad), blocked,
+      (GstPadBlockCallback) source_pad_blocked_cb, NULL);
+  if (blocked) {
+    if (dbin->shutdown) {
+      /* deactivate to force flushing state to prevent NOT_LINKED errors */
+      gst_pad_set_active (GST_PAD (dpad), FALSE);
+    } else {
+      gst_object_ref (dpad);
+      dbin->blocked_pads = g_list_prepend (dbin->blocked_pads, dpad);
+    }
+  } else {
+    if (g_list_find (dbin->blocked_pads, dpad))
+      gst_object_unref (dpad);
+    dbin->blocked_pads = g_list_remove (dbin->blocked_pads, dpad);
+  }
+  DECODE_BIN_DYN_UNLOCK (dbin);
+}
+
+static void
+gst_decode_pad_add_drained_check (GstDecodePad * dpad)
+{
+  gst_pad_add_event_probe (GST_PAD (dpad),
+      G_CALLBACK (source_pad_event_probe), dpad);
+}
+
+static void
+gst_decode_pad_activate (GstDecodePad * dpad, GstDecodeGroup * group)
+{
+  g_return_if_fail (group != NULL);
+
+  dpad->group = group;
+  gst_pad_set_active (GST_PAD (dpad), TRUE);
+  gst_decode_pad_set_blocked (dpad, TRUE);
+  gst_decode_pad_add_drained_check (dpad);
+}
+
+static void
+gst_decode_pad_unblock (GstDecodePad * dpad)
+{
+  gst_decode_pad_set_blocked (dpad, FALSE);
+}
+
 /*gst_decode_pad_new:
  *
  * Creates a new GstDecodePad for the given pad.
- * If block is TRUE, Sets the pad blocking asynchronously
  */
 static GstDecodePad *
-gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, gboolean block)
+gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad, GstDecodeGroup * group)
 {
   GstDecodePad *dpad;
 
-  dpad = g_new0 (GstDecodePad, 1);
-  dpad->pad = pad;
+  dpad =
+      g_object_new (GST_TYPE_DECODE_PAD, "direction", GST_PAD_DIRECTION (pad),
+      NULL);
+  gst_ghost_pad_construct (GST_GHOST_PAD (dpad));
+  gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad);
   dpad->group = group;
-  dpad->blocked = FALSE;
-  dpad->drained = TRUE;
-
-  if (block)
-    gst_pad_set_blocked_async (pad, TRUE,
-        (GstPadBlockCallback) source_pad_blocked_cb, dpad);
-  gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), dpad);
+  dpad->dbin = dbin;
+
   return dpad;
 }
 
@@ -2255,73 +2598,28 @@
  * Element add/remove
  *****/
 
-/*
- * add_fakesink / remove_fakesink
- *
- * We use a sink so that the parent ::change_state returns GST_STATE_CHANGE_ASYNC
- * when that sink is present (since it's not connected to anything it will 
- * always return GST_STATE_CHANGE_ASYNC).
- *
- * But this is an ugly way of achieving this goal.
- * Ideally, we shouldn't use a sink and just return GST_STATE_CHANGE_ASYNC in
- * our ::change_state if we have not exposed the active group.
- * We also need to override ::get_state to fake the asynchronous behaviour.
- * Once the active group is exposed, we would then post a
- * GST_MESSAGE_STATE_DIRTY and return GST_STATE_CHANGE_SUCCESS (which will call
- * ::get_state .
- */
-
-static gboolean
-add_fakesink (GstDecodeBin * decode_bin)
+static void
+do_async_start (GstDecodeBin * dbin)
 {
-  GST_DEBUG_OBJECT (decode_bin, "Adding the fakesink");
-
-  if (decode_bin->fakesink)
-    return TRUE;
-
-  decode_bin->fakesink =
-      gst_element_factory_make ("fakesink", "async-fakesink");
-  if (!decode_bin->fakesink)
-    goto no_fakesink;
-
-  /* enable sync so that we force ASYNC preroll */
-  g_object_set (G_OBJECT (decode_bin->fakesink), "sync", TRUE, NULL);
-
-  /* hacky, remove sink flag, we don't want our decodebin to become a sink
-   * just because we add a fakesink element to make us ASYNC */
-  GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK);
-
-  if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink))
-    goto could_not_add;
-
-  return TRUE;
-
-  /* ERRORS */
-no_fakesink:
-  {
-    g_warning ("can't find fakesink element, decodebin will not work");
-    return FALSE;
-  }
-could_not_add:
-  {
-    g_warning ("Could not add fakesink to decodebin, decodebin will not work");
-    gst_object_unref (decode_bin->fakesink);
-    decode_bin->fakesink = NULL;
-    return FALSE;
-  }
+  GstMessage *message;
+
+  dbin->async_pending = TRUE;
+
+  message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE);
+  parent_class->handle_message (GST_BIN_CAST (dbin), message);
 }
 
 static void
-remove_fakesink (GstDecodeBin * decode_bin)
+do_async_done (GstDecodeBin * dbin)
 {
-  if (decode_bin->fakesink == NULL)
-    return;
-
-  GST_DEBUG_OBJECT (decode_bin, "Removing the fakesink");
-
-  gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL);
-  gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink);
-  decode_bin->fakesink = NULL;
+  GstMessage *message;
+
+  if (dbin->async_pending) {
+    message = gst_message_new_async_done (GST_OBJECT_CAST (dbin));
+    parent_class->handle_message (GST_BIN_CAST (dbin), message);
+
+    dbin->async_pending = FALSE;
+  }
 }
 
 /*****
@@ -2351,10 +2649,35 @@
   return pad;
 }
 
+/* call with dyn_lock held */
+static void
+unblock_pads (GstDecodeBin * dbin)
+{
+  GList *tmp, *next;
+
+  for (tmp = dbin->blocked_pads; tmp; tmp = next) {
+    GstDecodePad *dpad = (GstDecodePad *) tmp->data;
+
+    next = g_list_next (tmp);
+
+    GST_DEBUG_OBJECT (dpad, "unblocking");
+    gst_pad_set_blocked_async (GST_PAD (dpad), FALSE,
+        (GstPadBlockCallback) source_pad_blocked_cb, NULL);
+    /* make flushing, prevent NOT_LINKED */
+    GST_PAD_SET_FLUSHING (GST_PAD (dpad));
+    gst_object_unref (dpad);
+    GST_DEBUG_OBJECT (dpad, "unblocked");
+  }
+
+  /* clear, no more blocked pads */
+  g_list_free (dbin->blocked_pads);
+  dbin->blocked_pads = NULL;
+}
+
 static GstStateChangeReturn
 gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
 {
-  GstStateChangeReturn ret;
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
   GstDecodeBin *dbin = GST_DECODE_BIN (element);
 
   switch (transition) {
@@ -2362,19 +2685,47 @@
       if (dbin->typefind == NULL)
         goto missing_typefind;
       break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:{
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      DECODE_BIN_DYN_LOCK (dbin);
+      GST_LOG_OBJECT (dbin, "clearing shutdown flag");
+      dbin->shutdown = FALSE;
+      DECODE_BIN_DYN_UNLOCK (dbin);
       dbin->have_type = FALSE;
-      if (!add_fakesink (dbin))
-        goto missing_fakesink;
+      ret = GST_STATE_CHANGE_ASYNC;
+      do_async_start (dbin);
       break;
-    }
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      DECODE_BIN_DYN_LOCK (dbin);
+      GST_LOG_OBJECT (dbin, "setting shutdown flag");
+      dbin->shutdown = TRUE;
+      unblock_pads (dbin);
+      DECODE_BIN_DYN_UNLOCK (dbin);
     default:
       break;
   }
 
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  /* FIXME : put some cleanup functions here.. if needed */
+  {
+    GstStateChangeReturn bret;
+
+    bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+    if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE))
+      goto activate_failed;
+    else if (G_UNLIKELY (bret == GST_STATE_CHANGE_NO_PREROLL)) {
+      do_async_done (dbin);
+      ret = bret;
+    }
+  }
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      do_async_done (dbin);
+      gst_decode_bin_remove_groups (dbin);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      gst_decode_bin_remove_groups (dbin);
+      break;
+    default:
+      break;
+  }
 
   return ret;
 
@@ -2386,16 +2737,19 @@
     GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!"));
     return GST_STATE_CHANGE_FAILURE;
   }
-missing_fakesink:
+activate_failed:
   {
-    gst_element_post_message (element,
-        gst_missing_element_message_new (element, "fakesink"));
-    GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!"));
+    GST_DEBUG_OBJECT (element,
+        "element failed to change states -- activation problem?");
     return GST_STATE_CHANGE_FAILURE;
   }
 }
-
-static gboolean
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
 gst_decode_bin_plugin_init (GstPlugin * plugin)
 {
   GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0,
@@ -2405,6 +2759,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
   return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/playback/gstinputselector.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1433 @@
+/* GStreamer
+ * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
+ * Copyright (C) 2007 Wim Taymans <wim.taymans@gmail.com>
+ * Copyright (C) 2007 Andy Wingo <wingo@pobox.com>
+ * Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.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.
+ */
+
+/**
+ * SECTION:element-input-selector
+ * @see_also: #GstOutputSelector
+ *
+ * Direct one out of N input streams to the output pad.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstinputselector.h"
+#include "gstplay-marshal.h"
+
+GST_DEBUG_CATEGORY_STATIC (input_selector_debug);
+#define GST_CAT_DEFAULT input_selector_debug
+
+static const GstElementDetails gst_input_selector_details =
+GST_ELEMENT_DETAILS ("Input selector",
+    "Generic",
+    "N-to-1 input stream selectoring",
+    "Julien Moutte <julien@moutte.net>\n"
+    "Ronald S. Bultje <rbultje@ronald.bitfreak.net>\n"
+    "Jan Schmidt <thaytan@mad.scientist.com>\n"
+    "Wim Taymans <wim.taymans@gmail.com>");
+
+static GstStaticPadTemplate gst_input_selector_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink%d",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate gst_input_selector_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+enum
+{
+  PROP_0,
+  PROP_N_PADS,
+  PROP_ACTIVE_PAD,
+  PROP_SELECT_ALL,
+  PROP_LAST
+};
+
+#define DEFAULT_PAD_ALWAYS_OK	TRUE
+
+enum
+{
+  PROP_PAD_0,
+  PROP_PAD_RUNNING_TIME,
+  PROP_PAD_TAGS,
+  PROP_PAD_ACTIVE,
+  PROP_PAD_ALWAYS_OK,
+  PROP_PAD_LAST
+};
+
+enum
+{
+  /* methods */
+  SIGNAL_BLOCK,
+  SIGNAL_SWITCH,
+  LAST_SIGNAL
+};
+static guint gst_input_selector_signals[LAST_SIGNAL] = { 0 };
+
+static gboolean gst_input_selector_is_active_sinkpad (GstInputSelector * sel,
+    GstPad * pad);
+static GstPad *gst_input_selector_activate_sinkpad (GstInputSelector * sel,
+    GstPad * pad);
+static GstPad *gst_input_selector_get_linked_pad (GstPad * pad,
+    gboolean strict);
+static gboolean gst_input_selector_check_eos (GstElement * selector);
+
+#define GST_TYPE_SELECTOR_PAD \
+  (gst_selector_pad_get_type())
+#define GST_SELECTOR_PAD(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SELECTOR_PAD, GstSelectorPad))
+#define GST_SELECTOR_PAD_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SELECTOR_PAD, GstSelectorPadClass))
+#define GST_IS_SELECTOR_PAD(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SELECTOR_PAD))
+#define GST_IS_SELECTOR_PAD_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SELECTOR_PAD))
+#define GST_SELECTOR_PAD_CAST(obj) \
+  ((GstSelectorPad *)(obj))
+
+typedef struct _GstSelectorPad GstSelectorPad;
+typedef struct _GstSelectorPadClass GstSelectorPadClass;
+
+struct _GstSelectorPad
+{
+  GstPad parent;
+
+  gboolean active;              /* when buffer have passed the pad */
+  gboolean eos;                 /* when EOS has been received */
+  gboolean discont;             /* after switching we create a discont */
+  gboolean always_ok;
+  GstSegment segment;           /* the current segment on the pad */
+  GstTagList *tags;             /* last tags received on the pad */
+
+  gboolean segment_pending;
+};
+
+struct _GstSelectorPadClass
+{
+  GstPadClass parent;
+};
+
+static void gst_selector_pad_class_init (GstSelectorPadClass * klass);
+static void gst_selector_pad_init (GstSelectorPad * pad);
+static void gst_selector_pad_finalize (GObject * object);
+static void gst_selector_pad_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_selector_pad_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+
+static GstPadClass *selector_pad_parent_class = NULL;
+
+static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad);
+static void gst_selector_pad_reset (GstSelectorPad * pad);
+static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event);
+static GstCaps *gst_selector_pad_getcaps (GstPad * pad);
+static GList *gst_selector_pad_get_linked_pads (GstPad * pad);
+static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf);
+static GstFlowReturn gst_selector_pad_bufferalloc (GstPad * pad,
+    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
+
+GType
+gst_selector_pad_get_type (void)
+{
+  static GType selector_pad_type = 0;
+
+  if (!selector_pad_type) {
+    static const GTypeInfo selector_pad_info = {
+      sizeof (GstSelectorPadClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_selector_pad_class_init,
+      NULL,
+      NULL,
+      sizeof (GstSelectorPad),
+      0,
+      (GInstanceInitFunc) gst_selector_pad_init,
+    };
+
+    selector_pad_type =
+        g_type_register_static (GST_TYPE_PAD, "GstPlaybin2SelectorPad",
+        &selector_pad_info, 0);
+  }
+  return selector_pad_type;
+}
+
+static void
+gst_selector_pad_class_init (GstSelectorPadClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+
+  selector_pad_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_selector_pad_finalize;
+
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_selector_pad_get_property);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_selector_pad_set_property);
+
+  g_object_class_install_property (gobject_class, PROP_PAD_RUNNING_TIME,
+      g_param_spec_int64 ("running-time", "Running time",
+          "Running time of stream on pad", 0, G_MAXINT64, 0, G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class, PROP_PAD_TAGS,
+      g_param_spec_boxed ("tags", "Tags",
+          "The currently active tags on the pad", GST_TYPE_TAG_LIST,
+          G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE,
+      g_param_spec_boolean ("active", "Active",
+          "If the pad is currently active", FALSE, G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class, PROP_PAD_ALWAYS_OK,
+      g_param_spec_boolean ("always-ok", "Always OK",
+          "Make an inactive pad return OK instead of NOT_LINKED",
+          DEFAULT_PAD_ALWAYS_OK, G_PARAM_READWRITE));
+}
+
+static void
+gst_selector_pad_init (GstSelectorPad * pad)
+{
+  pad->always_ok = DEFAULT_PAD_ALWAYS_OK;
+  gst_selector_pad_reset (pad);
+}
+
+static void
+gst_selector_pad_finalize (GObject * object)
+{
+  GstSelectorPad *pad;
+
+  pad = GST_SELECTOR_PAD_CAST (object);
+
+  if (pad->tags)
+    gst_tag_list_free (pad->tags);
+
+  G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object);
+}
+
+static void
+gst_selector_pad_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object);
+
+  switch (prop_id) {
+    case PROP_PAD_ALWAYS_OK:
+      GST_OBJECT_LOCK (object);
+      spad->always_ok = g_value_get_boolean (value);
+      GST_OBJECT_UNLOCK (object);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_selector_pad_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object);
+
+  switch (prop_id) {
+    case PROP_PAD_RUNNING_TIME:
+      g_value_set_int64 (value, gst_selector_pad_get_running_time (spad));
+      break;
+    case PROP_PAD_TAGS:
+      GST_OBJECT_LOCK (object);
+      g_value_set_boxed (value, spad->tags);
+      GST_OBJECT_UNLOCK (object);
+      break;
+    case PROP_PAD_ACTIVE:
+    {
+      GstInputSelector *sel;
+
+      sel = GST_INPUT_SELECTOR (gst_pad_get_parent (spad));
+      g_value_set_boolean (value, gst_input_selector_is_active_sinkpad (sel,
+              GST_PAD_CAST (spad)));
+      gst_object_unref (sel);
+      break;
+    }
+    case PROP_PAD_ALWAYS_OK:
+      GST_OBJECT_LOCK (object);
+      g_value_set_boolean (value, spad->always_ok);
+      GST_OBJECT_UNLOCK (object);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gint64
+gst_selector_pad_get_running_time (GstSelectorPad * pad)
+{
+  gint64 ret = 0;
+
+  GST_OBJECT_LOCK (pad);
+  if (pad->active) {
+    gint64 last_stop = pad->segment.last_stop;
+
+    if (last_stop >= 0)
+      ret = gst_segment_to_running_time (&pad->segment, GST_FORMAT_TIME,
+          last_stop);
+  }
+  GST_OBJECT_UNLOCK (pad);
+
+  GST_DEBUG_OBJECT (pad, "running time: %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (ret));
+
+  return ret;
+}
+
+static void
+gst_selector_pad_reset (GstSelectorPad * pad)
+{
+  GST_OBJECT_LOCK (pad);
+  pad->active = FALSE;
+  pad->eos = FALSE;
+  pad->segment_pending = FALSE;
+  pad->discont = FALSE;
+  gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED);
+  GST_OBJECT_UNLOCK (pad);
+}
+
+/* strictly get the linked pad from the sinkpad. If the pad is active we return
+ * the srcpad else we return NULL */
+static GList *
+gst_selector_pad_get_linked_pads (GstPad * pad)
+{
+  GstPad *otherpad;
+
+  otherpad = gst_input_selector_get_linked_pad (pad, TRUE);
+  if (!otherpad)
+    return NULL;
+
+  /* need to drop the ref, internal linked pads is not MT safe */
+  gst_object_unref (otherpad);
+
+  return g_list_append (NULL, otherpad);
+}
+
+static gboolean
+gst_selector_pad_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res = TRUE;
+  gboolean forward = TRUE;
+  GstInputSelector *sel;
+  GstSelectorPad *selpad;
+  GstPad *prev_active_sinkpad;
+  GstPad *active_sinkpad;
+
+  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+  selpad = GST_SELECTOR_PAD_CAST (pad);
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  prev_active_sinkpad = sel->active_sinkpad;
+  active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+
+  /* only forward if we are dealing with the active sinkpad or if select_all
+   * is enabled */
+  if (pad != active_sinkpad && !sel->select_all)
+    forward = FALSE;
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+
+  if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad)
+    g_object_notify (G_OBJECT (sel), "active-pad");
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_START:
+      /* FIXME, flush out the waiter */
+      break;
+    case GST_EVENT_FLUSH_STOP:
+      GST_INPUT_SELECTOR_LOCK (sel);
+      gst_selector_pad_reset (selpad);
+      sel->pending_close = FALSE;
+      GST_INPUT_SELECTOR_UNLOCK (sel);
+      break;
+    case GST_EVENT_NEWSEGMENT:
+    {
+      gboolean update;
+      GstFormat format;
+      gdouble rate, arate;
+      gint64 start, stop, time;
+
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+          &start, &stop, &time);
+
+      GST_DEBUG_OBJECT (pad,
+          "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
+          "format %d, "
+          "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
+          G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
+
+      GST_INPUT_SELECTOR_LOCK (sel);
+      GST_OBJECT_LOCK (selpad);
+      gst_segment_set_newsegment_full (&selpad->segment, update,
+          rate, arate, format, start, stop, time);
+      GST_OBJECT_UNLOCK (selpad);
+
+      /* If we aren't forwarding the event (because the pad is not the
+       * active_sinkpad, and select_all is not set, then set the flag on the
+       * that says a segment needs sending if/when that pad is activated.
+       * For all other cases, we send the event immediately, which makes
+       * sparse streams and other segment updates work correctly downstream.
+       */
+      if (!forward)
+        selpad->segment_pending = TRUE;
+
+      GST_INPUT_SELECTOR_UNLOCK (sel);
+      break;
+    }
+    case GST_EVENT_TAG:
+    {
+      GstTagList *tags, *oldtags, *newtags;
+
+      gst_event_parse_tag (event, &tags);
+
+      GST_OBJECT_LOCK (selpad);
+      oldtags = selpad->tags;
+
+      newtags = gst_tag_list_merge (oldtags, tags, GST_TAG_MERGE_REPLACE);
+      selpad->tags = newtags;
+      if (oldtags)
+        gst_tag_list_free (oldtags);
+      GST_DEBUG_OBJECT (pad, "received tags %" GST_PTR_FORMAT, newtags);
+      GST_OBJECT_UNLOCK (selpad);
+
+      g_object_notify (G_OBJECT (selpad), "tags");
+      break;
+    }
+    case GST_EVENT_EOS:
+      selpad->eos = TRUE;
+      GST_DEBUG_OBJECT (pad, "received EOS");
+      /* don't forward eos in select_all mode until all sink pads have eos */
+      if (sel->select_all && !gst_input_selector_check_eos (GST_ELEMENT (sel))) {
+        forward = FALSE;
+      }
+      break;
+    default:
+      break;
+  }
+  if (forward) {
+    GST_DEBUG_OBJECT (pad, "forwarding event");
+    res = gst_pad_push_event (sel->srcpad, event);
+  } else
+    gst_event_unref (event);
+
+  gst_object_unref (sel);
+
+  return res;
+}
+
+static GstCaps *
+gst_selector_pad_getcaps (GstPad * pad)
+{
+  GstInputSelector *sel;
+  GstCaps *caps;
+
+  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+
+  GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer");
+  caps = gst_pad_peer_get_caps (sel->srcpad);
+  if (caps == NULL)
+    caps = gst_caps_new_any ();
+
+  gst_object_unref (sel);
+
+  return caps;
+}
+
+static GstFlowReturn
+gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset,
+    guint size, GstCaps * caps, GstBuffer ** buf)
+{
+  GstInputSelector *sel;
+  GstFlowReturn result;
+  GstPad *active_sinkpad;
+  GstPad *prev_active_sinkpad;
+  GstSelectorPad *selpad;
+
+  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+  selpad = GST_SELECTOR_PAD_CAST (pad);
+
+  GST_DEBUG_OBJECT (pad, "received alloc");
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  prev_active_sinkpad = sel->active_sinkpad;
+  active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+
+  if (pad != active_sinkpad)
+    goto not_active;
+
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+
+  if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad)
+    g_object_notify (G_OBJECT (sel), "active-pad");
+
+  result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf);
+
+done:
+  gst_object_unref (sel);
+
+  return result;
+
+  /* ERRORS */
+not_active:
+  {
+    GST_INPUT_SELECTOR_UNLOCK (sel);
+
+    /* unselected pad, perform fallback alloc or return unlinked when
+     * asked */
+    GST_OBJECT_LOCK (selpad);
+    if (selpad->always_ok) {
+      GST_DEBUG_OBJECT (pad, "Not selected, performing fallback allocation");
+      *buf = NULL;
+      result = GST_FLOW_OK;
+    } else {
+      GST_DEBUG_OBJECT (pad, "Not selected, return NOT_LINKED");
+      result = GST_FLOW_NOT_LINKED;
+    }
+    GST_OBJECT_UNLOCK (selpad);
+
+    goto done;
+  }
+}
+
+/* must be called with the SELECTOR_LOCK, will block while the pad is blocked 
+ * or return TRUE when flushing */
+static gboolean
+gst_input_selector_wait (GstInputSelector * self, GstPad * pad)
+{
+  while (self->blocked && !self->flushing) {
+    /* we can be unlocked here when we are shutting down (flushing) or when we
+     * get unblocked */
+    GST_INPUT_SELECTOR_WAIT (self);
+  }
+  return self->flushing;
+}
+
+static GstFlowReturn
+gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstInputSelector *sel;
+  GstFlowReturn res;
+  GstPad *active_sinkpad;
+  GstPad *prev_active_sinkpad;
+  GstSelectorPad *selpad;
+  GstClockTime end_time, duration;
+  GstSegment *seg;
+  GstEvent *close_event = NULL, *start_event = NULL;
+
+  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+  selpad = GST_SELECTOR_PAD_CAST (pad);
+  seg = &selpad->segment;
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  /* wait or check for flushing */
+  if (gst_input_selector_wait (sel, pad))
+    goto flushing;
+
+  GST_DEBUG_OBJECT (pad, "getting active pad");
+
+  prev_active_sinkpad = sel->active_sinkpad;
+  active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+
+  /* update the segment on the srcpad */
+  end_time = GST_BUFFER_TIMESTAMP (buf);
+  if (GST_CLOCK_TIME_IS_VALID (end_time)) {
+    duration = GST_BUFFER_DURATION (buf);
+    if (GST_CLOCK_TIME_IS_VALID (duration))
+      end_time += duration;
+    GST_DEBUG_OBJECT (pad, "received end time %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (end_time));
+
+    GST_OBJECT_LOCK (pad);
+    gst_segment_set_last_stop (seg, seg->format, end_time);
+    GST_OBJECT_UNLOCK (pad);
+  }
+
+  /* Ignore buffers from pads except the selected one */
+  if (pad != active_sinkpad)
+    goto ignore;
+
+  if (G_UNLIKELY (sel->pending_close)) {
+    GstSegment *cseg = &sel->segment;
+
+    GST_DEBUG_OBJECT (sel,
+        "pushing NEWSEGMENT update %d, rate %lf, applied rate %lf, "
+        "format %d, "
+        "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
+        G_GINT64_FORMAT, TRUE, cseg->rate, cseg->applied_rate, cseg->format,
+        cseg->start, cseg->stop, cseg->time);
+
+    /* create update segment */
+    close_event = gst_event_new_new_segment_full (TRUE, cseg->rate,
+        cseg->applied_rate, cseg->format, cseg->start, cseg->stop, cseg->time);
+
+    sel->pending_close = FALSE;
+  }
+  /* if we have a pending segment, push it out now */
+  if (G_UNLIKELY (selpad->segment_pending)) {
+    GST_DEBUG_OBJECT (pad,
+        "pushing NEWSEGMENT update %d, rate %lf, applied rate %lf, "
+        "format %d, "
+        "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
+        G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format,
+        seg->start, seg->stop, seg->time);
+
+    start_event = gst_event_new_new_segment_full (FALSE, seg->rate,
+        seg->applied_rate, seg->format, seg->start, seg->stop, seg->time);
+
+    selpad->segment_pending = FALSE;
+  }
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+
+  if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad)
+    g_object_notify (G_OBJECT (sel), "active-pad");
+
+  if (close_event)
+    gst_pad_push_event (sel->srcpad, close_event);
+
+  if (start_event)
+    gst_pad_push_event (sel->srcpad, start_event);
+
+  if (selpad->discont) {
+    buf = gst_buffer_make_metadata_writable (buf);
+
+    GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf);
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+    selpad->discont = FALSE;
+  }
+
+  /* forward */
+  GST_DEBUG_OBJECT (pad, "Forwarding buffer %p from pad %s:%s", buf,
+      GST_DEBUG_PAD_NAME (pad));
+
+  res = gst_pad_push (sel->srcpad, buf);
+
+done:
+  gst_object_unref (sel);
+  return res;
+
+  /* dropped buffers */
+ignore:
+  {
+    GST_DEBUG_OBJECT (pad, "Pad not active, discard buffer %p", buf);
+    /* when we drop a buffer, we're creating a discont on this pad */
+    selpad->discont = TRUE;
+    GST_INPUT_SELECTOR_UNLOCK (sel);
+    gst_buffer_unref (buf);
+
+    /* figure out what to return upstream */
+    GST_OBJECT_LOCK (selpad);
+    if (selpad->always_ok)
+      res = GST_FLOW_OK;
+    else
+      res = GST_FLOW_NOT_LINKED;
+    GST_OBJECT_UNLOCK (selpad);
+
+    goto done;
+  }
+flushing:
+  {
+    GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf);
+    GST_INPUT_SELECTOR_UNLOCK (sel);
+    gst_buffer_unref (buf);
+    res = GST_FLOW_WRONG_STATE;
+    goto done;
+  }
+}
+
+static void gst_input_selector_init (GstInputSelector * sel);
+static void gst_input_selector_base_init (GstInputSelectorClass * klass);
+static void gst_input_selector_class_init (GstInputSelectorClass * klass);
+
+static void gst_input_selector_dispose (GObject * object);
+
+static void gst_input_selector_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_input_selector_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstPad *gst_input_selector_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * unused);
+static void gst_input_selector_release_pad (GstElement * element, GstPad * pad);
+
+static GstStateChangeReturn gst_input_selector_change_state (GstElement *
+    element, GstStateChange transition);
+
+static GstCaps *gst_input_selector_getcaps (GstPad * pad);
+static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event);
+static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query);
+static gint64 gst_input_selector_block (GstInputSelector * self);
+static void gst_input_selector_switch (GstInputSelector * self,
+    GstPad * pad, gint64 stop_time, gint64 start_time);
+
+static GstElementClass *parent_class = NULL;
+
+GType
+gst_input_selector_get_type (void)
+{
+  static GType input_selector_type = 0;
+
+  if (!input_selector_type) {
+    static const GTypeInfo input_selector_info = {
+      sizeof (GstInputSelectorClass),
+      (GBaseInitFunc) gst_input_selector_base_init,
+      NULL,
+      (GClassInitFunc) gst_input_selector_class_init,
+      NULL,
+      NULL,
+      sizeof (GstInputSelector),
+      0,
+      (GInstanceInitFunc) gst_input_selector_init,
+    };
+    input_selector_type =
+        g_type_register_static (GST_TYPE_ELEMENT,
+        "GstPlaybin2InputSelector", &input_selector_info, 0);
+    GST_DEBUG_CATEGORY_INIT (input_selector_debug,
+        "playbin2-input-selector", 0, "Playbin2 input stream selector element");
+  }
+
+  return input_selector_type;
+}
+
+static void
+gst_input_selector_base_init (GstInputSelectorClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details (element_class, &gst_input_selector_details);
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_input_selector_sink_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_input_selector_src_factory));
+}
+
+static void
+gst_input_selector_class_init (GstInputSelectorClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->dispose = gst_input_selector_dispose;
+
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_input_selector_set_property);
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_input_selector_get_property);
+
+  g_object_class_install_property (gobject_class, PROP_N_PADS,
+      g_param_spec_uint ("n-pads", "Number of Pads",
+          "The number of sink pads", 0, G_MAXUINT, 0, G_PARAM_READABLE));
+
+  g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
+      g_param_spec_object ("active-pad", "Active pad",
+          "The currently active sink pad", GST_TYPE_PAD, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_SELECT_ALL,
+      g_param_spec_boolean ("select-all", "Select all mode",
+          "Forwards data from all input pads", FALSE, G_PARAM_READWRITE));
+
+  /**
+   * GstInputSelector::block:
+   * @inputselector: the #GstInputSelector
+   *
+   * Block all sink pads in preparation for a switch. Returns the stop time of
+   * the current switch segment, as a running time, or 0 if there is no current
+   * active pad or the current active pad never received data.
+   */
+  gst_input_selector_signals[SIGNAL_BLOCK] =
+      g_signal_new ("block", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+      G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL,
+      gst_play_marshal_INT64__VOID, G_TYPE_INT64, 0);
+  /**
+   * GstInputSelector::switch:
+   * @inputselector: the #GstInputSelector
+   * @pad:            the pad to switch to
+   * @stop_time:      running time at which to close the previous segment, or -1
+   *                  to use the running time of the previously active sink pad
+   * @start_time:     running time at which to start the new segment, or -1 to
+   *                  use the running time of the newly active sink pad
+   *
+   * Switch to a new feed. The segment opened by the previously active pad, if
+   * any, will be closed, and a new segment opened before data flows again.
+   *
+   * This signal must be emitted when the element has been blocked via the <link
+   * linkend="GstInputSelector-block">block</link> signal.
+   *
+   * If you have a stream with only one switch element, such as an audio-only
+   * stream, a stream switch should be performed by first emitting the block
+   * signal, and then emitting the switch signal with -1 for the stop and start
+   * time values.
+   *
+   * The intention of the @stop_time and @start_time arguments is to allow
+   * multiple switch elements to switch and maintain stream synchronization.
+   * When switching a stream with multiple feeds, you will need as many switch
+   * elements as you have feeds. For example, a feed with audio and video will
+   * have one switch element between the audio feeds and one for video.
+   *
+   * A switch over multiple switch elements should be performed as follows:
+   * First, emit the <link linkend="GstInputSelector-block">block</link>
+   * signal, collecting the returned values. The maximum running time returned
+   * by block should then be used as the time at which to close the previous
+   * segment.
+   *
+   * Then, query the running times of the new audio and video pads that you will
+   * switch to. Naturally, these pads are on separate switch elements. Take the
+   * minimum running time for those streams and use it for the time at which to
+   * open the new segment.
+   *
+   * If @pad is the same as the current active pad, the element will cancel any
+   * previous block without adjusting segments.
+   *
+   * <note><simpara>
+   * the signal changed from accepting the pad name to the pad object.
+   * </simpara></note>
+   *
+   * Since: 0.10.7
+   */
+  gst_input_selector_signals[SIGNAL_SWITCH] =
+      g_signal_new ("switch", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstInputSelectorClass, switch_),
+      NULL, NULL, gst_play_marshal_VOID__OBJECT_INT64_INT64,
+      G_TYPE_NONE, 3, GST_TYPE_PAD, G_TYPE_INT64, G_TYPE_INT64);
+
+  gstelement_class->request_new_pad = gst_input_selector_request_new_pad;
+  gstelement_class->release_pad = gst_input_selector_release_pad;
+  gstelement_class->change_state = gst_input_selector_change_state;
+
+  klass->block = GST_DEBUG_FUNCPTR (gst_input_selector_block);
+  /* note the underscore because switch is a keyword otherwise */
+  klass->switch_ = GST_DEBUG_FUNCPTR (gst_input_selector_switch);
+}
+
+static void
+gst_input_selector_init (GstInputSelector * sel)
+{
+  sel->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+  gst_pad_set_internal_link_function (sel->srcpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_get_linked_pads));
+  gst_pad_set_getcaps_function (sel->srcpad,
+      GST_DEBUG_FUNCPTR (gst_input_selector_getcaps));
+  gst_pad_set_query_function (sel->srcpad,
+      GST_DEBUG_FUNCPTR (gst_input_selector_query));
+  gst_pad_set_event_function (sel->srcpad,
+      GST_DEBUG_FUNCPTR (gst_input_selector_event));
+  gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
+  /* sinkpad management */
+  sel->active_sinkpad = NULL;
+  sel->padcount = 0;
+  gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
+
+  sel->lock = g_mutex_new ();
+  sel->cond = g_cond_new ();
+  sel->blocked = FALSE;
+
+  sel->select_all = FALSE;
+}
+
+static void
+gst_input_selector_dispose (GObject * object)
+{
+  GstInputSelector *sel = GST_INPUT_SELECTOR (object);
+
+  if (sel->active_sinkpad) {
+    gst_object_unref (sel->active_sinkpad);
+    sel->active_sinkpad = NULL;
+  }
+  if (sel->lock) {
+    g_mutex_free (sel->lock);
+    sel->lock = NULL;
+  }
+  if (sel->cond) {
+    g_cond_free (sel->cond);
+    sel->cond = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/* Solve the following equation for B.timestamp, and set that as the segment
+ * stop:
+ * B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
+ */
+static gint64
+gst_segment_get_timestamp (GstSegment * segment, gint64 running_time)
+{
+  return (running_time - segment->accum) * segment->abs_rate + segment->start;
+}
+
+static void
+gst_segment_set_stop (GstSegment * segment, gint64 running_time)
+{
+  segment->stop = gst_segment_get_timestamp (segment, running_time);
+  segment->last_stop = -1;
+}
+
+static void
+gst_segment_set_start (GstSegment * segment, gint64 running_time)
+{
+  gint64 new_start, duration;
+
+  new_start = gst_segment_get_timestamp (segment, running_time);
+
+  /* this is the duration we skipped */
+  duration = new_start - segment->start;
+  /* add the duration to the accumulated segment time */
+  segment->accum += duration;
+  /* move position in the segment */
+  segment->time += duration;
+  segment->start += duration;
+}
+
+/* this function must be called with the SELECTOR_LOCK. It returns TRUE when the
+ * active pad changed. */
+static gboolean
+gst_input_selector_set_active_pad (GstInputSelector * self,
+    GstPad * pad, gint64 stop_time, gint64 start_time)
+{
+  GstSelectorPad *old, *new;
+  GstPad **active_pad_p;
+
+  if (pad == self->active_sinkpad)
+    return FALSE;
+
+  old = GST_SELECTOR_PAD_CAST (self->active_sinkpad);
+  new = GST_SELECTOR_PAD_CAST (pad);
+
+  GST_DEBUG_OBJECT (self, "setting active pad to %s:%s",
+      GST_DEBUG_PAD_NAME (new));
+
+  if (stop_time == -1 && old) {
+    /* no stop time given, get the latest running_time on the active pad to 
+     * close and open the new segment */
+    stop_time = start_time = gst_selector_pad_get_running_time (old);
+    GST_DEBUG_OBJECT (self, "using start/stop of %" G_GINT64_FORMAT,
+        start_time);
+  }
+
+  if (old && old->active && !self->pending_close && stop_time >= 0) {
+    /* schedule a last_stop update if one isn't already scheduled, and a
+       segment has been pushed before. */
+    memcpy (&self->segment, &old->segment, sizeof (self->segment));
+
+    GST_DEBUG_OBJECT (self, "setting stop_time to %" G_GINT64_FORMAT,
+        stop_time);
+    gst_segment_set_stop (&self->segment, stop_time);
+    self->pending_close = TRUE;
+  }
+
+  if (new && new->active && start_time >= 0) {
+    GST_DEBUG_OBJECT (self, "setting start_time to %" G_GINT64_FORMAT,
+        start_time);
+    /* schedule a new segment push */
+    gst_segment_set_start (&new->segment, start_time);
+    new->segment_pending = TRUE;
+  }
+
+  active_pad_p = &self->active_sinkpad;
+  gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad));
+  GST_DEBUG_OBJECT (self, "New active pad is %" GST_PTR_FORMAT,
+      self->active_sinkpad);
+
+  return TRUE;
+}
+
+static void
+gst_input_selector_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstInputSelector *sel = GST_INPUT_SELECTOR (object);
+
+  switch (prop_id) {
+    case PROP_ACTIVE_PAD:
+    {
+      GstPad *pad;
+
+      pad = g_value_get_object (value);
+
+      GST_INPUT_SELECTOR_LOCK (sel);
+      gst_input_selector_set_active_pad (sel, pad,
+          GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE);
+      GST_INPUT_SELECTOR_UNLOCK (sel);
+      break;
+    }
+    case PROP_SELECT_ALL:
+      GST_INPUT_SELECTOR_LOCK (object);
+      sel->select_all = g_value_get_boolean (value);
+      GST_INPUT_SELECTOR_UNLOCK (object);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_input_selector_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstInputSelector *sel = GST_INPUT_SELECTOR (object);
+
+  switch (prop_id) {
+    case PROP_N_PADS:
+      GST_INPUT_SELECTOR_LOCK (object);
+      g_value_set_uint (value, sel->n_pads);
+      GST_INPUT_SELECTOR_UNLOCK (object);
+      break;
+    case PROP_ACTIVE_PAD:
+      GST_INPUT_SELECTOR_LOCK (object);
+      g_value_set_object (value, sel->active_sinkpad);
+      GST_INPUT_SELECTOR_UNLOCK (object);
+      break;
+    case PROP_SELECT_ALL:
+      GST_INPUT_SELECTOR_LOCK (object);
+      g_value_set_boolean (value, sel->select_all);
+      GST_INPUT_SELECTOR_UNLOCK (object);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstPad *
+gst_input_selector_get_linked_pad (GstPad * pad, gboolean strict)
+{
+  GstInputSelector *sel;
+  GstPad *otherpad = NULL;
+
+  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  if (pad == sel->srcpad)
+    otherpad = sel->active_sinkpad;
+  else if (pad == sel->active_sinkpad || !strict)
+    otherpad = sel->srcpad;
+  if (otherpad)
+    gst_object_ref (otherpad);
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+
+  gst_object_unref (sel);
+
+  return otherpad;
+}
+
+static gboolean
+gst_input_selector_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res = FALSE;
+  GstPad *otherpad;
+
+  otherpad = gst_input_selector_get_linked_pad (pad, TRUE);
+
+  if (otherpad) {
+    res = gst_pad_push_event (otherpad, event);
+
+    gst_object_unref (otherpad);
+  } else
+    gst_event_unref (event);
+  return res;
+}
+
+/* query on the srcpad. We override this function because by default it will
+ * only forward the query to one random sinkpad */
+static gboolean
+gst_input_selector_query (GstPad * pad, GstQuery * query)
+{
+  gboolean res = TRUE;
+  GstInputSelector *sel;
+  GstPad *otherpad;
+
+  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+
+  otherpad = gst_input_selector_get_linked_pad (pad, TRUE);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_LATENCY:
+    {
+      GList *walk;
+      GstClockTime resmin, resmax;
+      gboolean reslive;
+
+      resmin = 0;
+      resmax = -1;
+      reslive = FALSE;
+
+      /* assume FALSE, we become TRUE if one query succeeds */
+      res = FALSE;
+
+      /* perform the query on all sinkpads and combine the results. We take the
+       * max of min and the min of max for the result latency. */
+      GST_INPUT_SELECTOR_LOCK (sel);
+      for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk;
+          walk = g_list_next (walk)) {
+        GstPad *sinkpad = GST_PAD_CAST (walk->data);
+
+        if (gst_pad_peer_query (sinkpad, query)) {
+          GstClockTime min, max;
+          gboolean live;
+
+          /* one query succeeded, we succeed too */
+          res = TRUE;
+
+          gst_query_parse_latency (query, &live, &min, &max);
+
+          GST_DEBUG_OBJECT (sinkpad,
+              "peer latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
+              ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live);
+
+          if (live) {
+            if (min > resmin)
+              resmin = min;
+            if (resmax == -1)
+              resmax = max;
+            else if (max < resmax)
+              resmax = max;
+            if (reslive == FALSE)
+              reslive = live;
+          }
+        }
+      }
+      GST_INPUT_SELECTOR_UNLOCK (sel);
+      if (res) {
+        gst_query_set_latency (query, reslive, resmin, resmax);
+
+        GST_DEBUG_OBJECT (sel,
+            "total latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
+            ", live %d", GST_TIME_ARGS (resmin), GST_TIME_ARGS (resmax),
+            reslive);
+      }
+
+      break;
+    }
+    default:
+      if (otherpad)
+        res = gst_pad_peer_query (otherpad, query);
+      break;
+  }
+  if (otherpad)
+    gst_object_unref (otherpad);
+  gst_object_unref (sel);
+
+  return res;
+}
+
+static GstCaps *
+gst_input_selector_getcaps (GstPad * pad)
+{
+  GstPad *otherpad;
+  GstObject *parent;
+  GstCaps *caps;
+
+  parent = gst_object_get_parent (GST_OBJECT (pad));
+
+  otherpad = gst_input_selector_get_linked_pad (pad, FALSE);
+
+  if (!otherpad) {
+    if (GST_INPUT_SELECTOR (parent)->select_all) {
+      GST_DEBUG_OBJECT (parent,
+          "Pad %s:%s not linked, returning merge of caps",
+          GST_DEBUG_PAD_NAME (pad));
+      caps = gst_pad_proxy_getcaps (pad);
+    } else {
+      GST_DEBUG_OBJECT (parent,
+          "Pad %s:%s not linked, returning ANY", GST_DEBUG_PAD_NAME (pad));
+      caps = gst_caps_new_any ();
+    }
+  } else {
+    GST_DEBUG_OBJECT (parent,
+        "Pad %s:%s is linked (to %s:%s), returning peer caps",
+        GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (otherpad));
+    /* if the peer has caps, use those. If the pad is not linked, this function
+     * returns NULL and we return ANY */
+    if (!(caps = gst_pad_peer_get_caps (otherpad)))
+      caps = gst_caps_new_any ();
+    gst_object_unref (otherpad);
+  }
+
+  gst_object_unref (parent);
+  return caps;
+}
+
+/* check if the pad is the active sinkpad */
+static gboolean
+gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad)
+{
+  GstSelectorPad *selpad;
+  gboolean res;
+
+  selpad = GST_SELECTOR_PAD_CAST (pad);
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  res = (pad == sel->active_sinkpad);
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+
+  return res;
+}
+
+/* Get or create the active sinkpad, must be called with SELECTOR_LOCK */
+static GstPad *
+gst_input_selector_activate_sinkpad (GstInputSelector * sel, GstPad * pad)
+{
+  GstPad *active_sinkpad;
+  GstSelectorPad *selpad;
+
+  selpad = GST_SELECTOR_PAD_CAST (pad);
+
+  selpad->active = TRUE;
+  active_sinkpad = sel->active_sinkpad;
+  if (active_sinkpad == NULL || sel->select_all) {
+    /* first pad we get activity on becomes the activated pad by default, if we
+     * select all, we also remember the last used pad. */
+    if (sel->active_sinkpad)
+      gst_object_unref (sel->active_sinkpad);
+    active_sinkpad = sel->active_sinkpad = gst_object_ref (pad);
+    GST_DEBUG_OBJECT (sel, "Activating pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+  }
+
+  return active_sinkpad;
+}
+
+static GstPad *
+gst_input_selector_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * unused)
+{
+  GstInputSelector *sel;
+  gchar *name = NULL;
+  GstPad *sinkpad = NULL;
+
+  g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
+
+  sel = GST_INPUT_SELECTOR (element);
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+
+  GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount);
+  name = g_strdup_printf ("sink%d", sel->padcount++);
+  sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD,
+      "name", name, "direction", templ->direction, "template", templ, NULL);
+  g_free (name);
+
+  sel->n_pads++;
+
+  gst_pad_set_event_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_event));
+  gst_pad_set_getcaps_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps));
+  gst_pad_set_chain_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_chain));
+  gst_pad_set_internal_link_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_get_linked_pads));
+  gst_pad_set_bufferalloc_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_bufferalloc));
+
+  gst_pad_set_active (sinkpad, TRUE);
+  gst_element_add_pad (GST_ELEMENT (sel), sinkpad);
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+
+  return sinkpad;
+}
+
+static void
+gst_input_selector_release_pad (GstElement * element, GstPad * pad)
+{
+  GstInputSelector *sel;
+
+  sel = GST_INPUT_SELECTOR (element);
+  GST_LOG_OBJECT (sel, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  /* if the pad was the active pad, makes us select a new one */
+  if (sel->active_sinkpad == pad) {
+    GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+    gst_object_unref (sel->active_sinkpad);
+    sel->active_sinkpad = NULL;
+  }
+  sel->n_pads--;
+
+  gst_pad_set_active (pad, FALSE);
+  gst_element_remove_pad (GST_ELEMENT (sel), pad);
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+}
+
+static void
+gst_input_selector_reset (GstInputSelector * sel)
+{
+  GList *walk;
+
+  GST_INPUT_SELECTOR_LOCK (sel);
+  /* clear active pad */
+  if (sel->active_sinkpad) {
+    gst_object_unref (sel->active_sinkpad);
+    sel->active_sinkpad = NULL;
+  }
+  /* reset segment */
+  gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
+  sel->pending_close = FALSE;
+  /* reset each of our sinkpads state */
+  for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) {
+    GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data);
+
+    gst_selector_pad_reset (selpad);
+
+    if (selpad->tags) {
+      gst_tag_list_free (selpad->tags);
+      selpad->tags = NULL;
+    }
+  }
+  GST_INPUT_SELECTOR_UNLOCK (sel);
+}
+
+static GstStateChangeReturn
+gst_input_selector_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstInputSelector *self = GST_INPUT_SELECTOR (element);
+  GstStateChangeReturn result;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      GST_INPUT_SELECTOR_LOCK (self);
+      self->blocked = FALSE;
+      self->flushing = FALSE;
+      GST_INPUT_SELECTOR_UNLOCK (self);
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      /* first unlock before we call the parent state change function, which
+       * tries to acquire the stream lock when going to ready. */
+      GST_INPUT_SELECTOR_LOCK (self);
+      self->blocked = FALSE;
+      self->flushing = TRUE;
+      GST_INPUT_SELECTOR_BROADCAST (self);
+      GST_INPUT_SELECTOR_UNLOCK (self);
+      break;
+    default:
+      break;
+  }
+
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_input_selector_reset (self);
+      break;
+    default:
+      break;
+  }
+
+  return result;
+}
+
+static gint64
+gst_input_selector_block (GstInputSelector * self)
+{
+  gint64 ret = 0;
+  GstSelectorPad *spad;
+
+  GST_INPUT_SELECTOR_LOCK (self);
+
+  if (self->blocked)
+    GST_WARNING_OBJECT (self, "switch already blocked");
+
+  self->blocked = TRUE;
+  spad = GST_SELECTOR_PAD_CAST (self->active_sinkpad);
+
+  if (spad)
+    ret = gst_selector_pad_get_running_time (spad);
+  else
+    GST_DEBUG_OBJECT (self, "no active pad while blocking");
+
+  GST_INPUT_SELECTOR_UNLOCK (self);
+
+  return ret;
+}
+
+/* stop_time and start_time are running times */
+static void
+gst_input_selector_switch (GstInputSelector * self, GstPad * pad,
+    gint64 stop_time, gint64 start_time)
+{
+  gboolean changed;
+
+  g_return_if_fail (self->blocked == TRUE);
+
+  GST_INPUT_SELECTOR_LOCK (self);
+  changed =
+      gst_input_selector_set_active_pad (self, pad, stop_time, start_time);
+
+  self->blocked = FALSE;
+  GST_INPUT_SELECTOR_BROADCAST (self);
+  GST_INPUT_SELECTOR_UNLOCK (self);
+
+  if (changed)
+    g_object_notify (G_OBJECT (self), "active-pad");
+}
+
+static gboolean
+gst_input_selector_check_eos (GstElement * selector)
+{
+  GstIterator *it = gst_element_iterate_sink_pads (selector);
+  GstIteratorResult ires;
+  gpointer item;
+  gboolean done = FALSE, is_eos = FALSE;
+  GstSelectorPad *pad;
+
+  while (!done) {
+    ires = gst_iterator_next (it, &item);
+    switch (ires) {
+      case GST_ITERATOR_DONE:
+        GST_INFO_OBJECT (selector, "all sink pads have eos");
+        done = TRUE;
+        is_eos = TRUE;
+        break;
+      case GST_ITERATOR_OK:
+        pad = GST_SELECTOR_PAD_CAST (item);
+        if (!pad->eos) {
+          done = TRUE;
+        }
+        gst_object_unref (pad);
+        break;
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (it);
+        break;
+      default:
+        done = TRUE;
+        break;
+    }
+  }
+  gst_iterator_free (it);
+
+  return is_eos;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/playback/gstinputselector.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,85 @@
+/* GStreamer
+ * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.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_INPUT_SELECTOR_H__
+#define __GST_INPUT_SELECTOR_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_INPUT_SELECTOR \
+  (gst_input_selector_get_type())
+#define GST_INPUT_SELECTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INPUT_SELECTOR, GstInputSelector))
+#define GST_INPUT_SELECTOR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INPUT_SELECTOR, GstInputSelectorClass))
+#define GST_IS_INPUT_SELECTOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INPUT_SELECTOR))
+#define GST_IS_INPUT_SELECTOR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INPUT_SELECTOR))
+
+typedef struct _GstInputSelector GstInputSelector;
+typedef struct _GstInputSelectorClass GstInputSelectorClass;
+
+#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock)
+#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond)
+#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
+#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
+#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \
+			GST_INPUT_SELECTOR_GET_LOCK(sel)))
+#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel)))
+
+struct _GstInputSelector {
+  GstElement element;
+
+  GstPad *srcpad;
+
+  GstPad *active_sinkpad;
+  guint n_pads;
+  guint padcount;
+
+  GstSegment segment;      /* the output segment */
+  gboolean pending_close;  /* if we should push a close first */
+
+  GMutex *lock;
+  GCond *cond;
+  gboolean blocked;
+  gboolean flushing;
+
+  /* select all mode, send data from all input pads forward */
+  gboolean select_all;
+};
+
+struct _GstInputSelectorClass {
+  GstElementClass parent_class;
+
+  gint64 (*block)	(GstInputSelector *self);
+  void (*switch_)	(GstInputSelector *self, GstPad *pad,
+                         gint64 stop_time, gint64 start_time);
+};
+
+GType gst_input_selector_get_type (void);
+GType gst_selector_pad_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_INPUT_SELECTOR_H__ */
--- a/gst_plugins_base/gst/playback/gstplay-enum.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplay-enum.c	Fri Apr 16 15:15:52 2010 +0300
@@ -28,7 +28,7 @@
   static const GEnumValue values[] = {
     {C_ENUM (GST_AUTOPLUG_SELECT_TRY), "GST_AUTOPLUG_SELECT_TRY", "try"},
     {C_ENUM (GST_AUTOPLUG_SELECT_EXPOSE), "GST_AUTOPLUG_SELECT_EXPOSE",
-          "expose"},
+        "expose"},
     {C_ENUM (GST_AUTOPLUG_SELECT_SKIP), "GST_AUTOPLUG_SELECT_SKIP", "skip"},
     {0, NULL, NULL}
   };
@@ -57,12 +57,14 @@
     {C_FLAGS (GST_PLAY_FLAG_AUDIO), "Render the audio stream", "audio"},
     {C_FLAGS (GST_PLAY_FLAG_TEXT), "Render subtitles", "text"},
     {C_FLAGS (GST_PLAY_FLAG_VIS),
-          "Render visualisation when no video is present", "vis"},
+        "Render visualisation when no video is present", "vis"},
     {C_FLAGS (GST_PLAY_FLAG_SOFT_VOLUME), "Use software volume", "soft-volume"},
     {C_FLAGS (GST_PLAY_FLAG_NATIVE_AUDIO), "Only use native audio formats",
-          "native-audio"},
+        "native-audio"},
     {C_FLAGS (GST_PLAY_FLAG_NATIVE_VIDEO), "Only use native video formats",
-          "native-video"},
+        "native-video"},
+    {C_FLAGS (GST_PLAY_FLAG_DOWNLOAD), "Attempt progressive download buffering",
+        "download"},
     {0, NULL, NULL}
   };
   *id = g_flags_register_static ("GstPlayFlags", values);
--- a/gst_plugins_base/gst/playback/gstplay-enum.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplay-enum.h	Fri Apr 16 15:15:52 2010 +0300
@@ -53,6 +53,8 @@
  *   configuration of audioconvert and audioresample.
  * @GST_PLAY_FLAG_NATIVE_VIDEO: only allow native video formats, this omits
  *   configuration of ffmpegcolorspace and videoscale.
+ * @GST_PLAY_FLAG_DOWNLOAD: enable progressice download buffering for selected
+ *   formats.
  *
  * Extra flags to configure the behaviour of the sinks.
  */
@@ -63,7 +65,8 @@
   GST_PLAY_FLAG_VIS           = (1 << 3),
   GST_PLAY_FLAG_SOFT_VOLUME   = (1 << 4),
   GST_PLAY_FLAG_NATIVE_AUDIO  = (1 << 5),
-  GST_PLAY_FLAG_NATIVE_VIDEO  = (1 << 6)
+  GST_PLAY_FLAG_NATIVE_VIDEO  = (1 << 6),
+  GST_PLAY_FLAG_DOWNLOAD      = (1 << 7)
 } GstPlayFlags;
 
 #define GST_TYPE_PLAY_FLAGS (gst_play_flags_get_type())
--- a/gst_plugins_base/gst/playback/gstplay-marshal.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplay-marshal.c	Fri Apr 16 15:15:52 2010 +0300
@@ -48,24 +48,24 @@
 #endif /* !G_ENABLE_DEBUG */
 
 
-/* BOOLEAN:OBJECT,OBJECT (gstplay-marshal.list:1) */
+/* BOOLEAN:OBJECT,BOXED (gstplay-marshal.list:1) */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 void
-gst_play_marshal_BOOLEAN__OBJECT_OBJECT (GClosure     *closure,
-                                         GValue       *return_value G_GNUC_UNUSED,
-                                         guint         n_param_values,
-                                         const GValue *param_values,
-                                         gpointer      invocation_hint G_GNUC_UNUSED,
-                                         gpointer      marshal_data)
+gst_play_marshal_BOOLEAN__OBJECT_BOXED (GClosure     *closure,
+                                        GValue       *return_value G_GNUC_UNUSED,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint G_GNUC_UNUSED,
+                                        gpointer      marshal_data)
 {
-  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT_OBJECT) (gpointer     data1,
-                                                           gpointer     arg_1,
-                                                           gpointer     arg_2,
-                                                           gpointer     data2);
-  register GMarshalFunc_BOOLEAN__OBJECT_OBJECT callback;
+  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT_BOXED) (gpointer     data1,
+                                                          gpointer     arg_1,
+                                                          gpointer     arg_2,
+                                                          gpointer     data2);
+  register GMarshalFunc_BOOLEAN__OBJECT_BOXED callback;
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
   gboolean v_return;
@@ -83,11 +83,11 @@
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_BOOLEAN__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_BOOLEAN__OBJECT_BOXED) (marshal_data ? marshal_data : cc->callback);
 
   v_return = callback (data1,
                        g_marshal_value_peek_object (param_values + 1),
-                       g_marshal_value_peek_object (param_values + 2),
+                       g_marshal_value_peek_boxed (param_values + 2),
                        data2);
 
   g_value_set_boolean (return_value, v_return);
@@ -140,24 +140,24 @@
   g_value_set_boolean (return_value, v_return);
 }
 
-/* BOXED:OBJECT,OBJECT (gstplay-marshal.list:3) */
+/* BOXED:OBJECT,BOXED (gstplay-marshal.list:3) */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 void
-gst_play_marshal_BOXED__OBJECT_OBJECT (GClosure     *closure,
-                                       GValue       *return_value G_GNUC_UNUSED,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint G_GNUC_UNUSED,
-                                       gpointer      marshal_data)
+gst_play_marshal_BOXED__OBJECT_BOXED (GClosure     *closure,
+                                      GValue       *return_value G_GNUC_UNUSED,
+                                      guint         n_param_values,
+                                      const GValue *param_values,
+                                      gpointer      invocation_hint G_GNUC_UNUSED,
+                                      gpointer      marshal_data)
 {
-  typedef gpointer (*GMarshalFunc_BOXED__OBJECT_OBJECT) (gpointer     data1,
-                                                         gpointer     arg_1,
-                                                         gpointer     arg_2,
-                                                         gpointer     data2);
-  register GMarshalFunc_BOXED__OBJECT_OBJECT callback;
+  typedef gpointer (*GMarshalFunc_BOXED__OBJECT_BOXED) (gpointer     data1,
+                                                        gpointer     arg_1,
+                                                        gpointer     arg_2,
+                                                        gpointer     data2);
+  register GMarshalFunc_BOXED__OBJECT_BOXED callback;
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
   gpointer v_return;
@@ -175,11 +175,11 @@
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_BOXED__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_BOXED__OBJECT_BOXED) (marshal_data ? marshal_data : cc->callback);
 
   v_return = callback (data1,
                        g_marshal_value_peek_object (param_values + 1),
-                       g_marshal_value_peek_object (param_values + 2),
+                       g_marshal_value_peek_boxed (param_values + 2),
                        data2);
 
   g_value_take_boxed (return_value, v_return);
@@ -273,25 +273,25 @@
   g_value_set_enum (return_value, v_return);
 }
 
-/* ENUM:OBJECT,OBJECT,OBJECT (gstplay-marshal.list:6) */
+/* ENUM:OBJECT,BOXED,OBJECT (gstplay-marshal.list:6) */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 void
-gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT (GClosure     *closure,
-                                             GValue       *return_value G_GNUC_UNUSED,
-                                             guint         n_param_values,
-                                             const GValue *param_values,
-                                             gpointer      invocation_hint G_GNUC_UNUSED,
-                                             gpointer      marshal_data)
+gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT (GClosure     *closure,
+                                            GValue       *return_value G_GNUC_UNUSED,
+                                            guint         n_param_values,
+                                            const GValue *param_values,
+                                            gpointer      invocation_hint G_GNUC_UNUSED,
+                                            gpointer      marshal_data)
 {
-  typedef gint (*GMarshalFunc_ENUM__OBJECT_OBJECT_OBJECT) (gpointer     data1,
-                                                           gpointer     arg_1,
-                                                           gpointer     arg_2,
-                                                           gpointer     arg_3,
-                                                           gpointer     data2);
-  register GMarshalFunc_ENUM__OBJECT_OBJECT_OBJECT callback;
+  typedef gint (*GMarshalFunc_ENUM__OBJECT_BOXED_OBJECT) (gpointer     data1,
+                                                          gpointer     arg_1,
+                                                          gpointer     arg_2,
+                                                          gpointer     arg_3,
+                                                          gpointer     data2);
+  register GMarshalFunc_ENUM__OBJECT_BOXED_OBJECT callback;
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
   gint v_return;
@@ -309,36 +309,36 @@
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_ENUM__OBJECT_OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_ENUM__OBJECT_BOXED_OBJECT) (marshal_data ? marshal_data : cc->callback);
 
   v_return = callback (data1,
                        g_marshal_value_peek_object (param_values + 1),
-                       g_marshal_value_peek_object (param_values + 2),
+                       g_marshal_value_peek_boxed (param_values + 2),
                        g_marshal_value_peek_object (param_values + 3),
                        data2);
 
   g_value_set_enum (return_value, v_return);
 }
 
-/* BOXED:OBJECT,OBJECT,BOXED (gstplay-marshal.list:7) */
+/* BOXED:OBJECT,BOXED,BOXED (gstplay-marshal.list:7) */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 void
-gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED (GClosure     *closure,
-                                             GValue       *return_value G_GNUC_UNUSED,
-                                             guint         n_param_values,
-                                             const GValue *param_values,
-                                             gpointer      invocation_hint G_GNUC_UNUSED,
-                                             gpointer      marshal_data)
+gst_play_marshal_BOXED__OBJECT_BOXED_BOXED (GClosure     *closure,
+                                            GValue       *return_value G_GNUC_UNUSED,
+                                            guint         n_param_values,
+                                            const GValue *param_values,
+                                            gpointer      invocation_hint G_GNUC_UNUSED,
+                                            gpointer      marshal_data)
 {
-  typedef gpointer (*GMarshalFunc_BOXED__OBJECT_OBJECT_BOXED) (gpointer     data1,
-                                                               gpointer     arg_1,
-                                                               gpointer     arg_2,
-                                                               gpointer     arg_3,
-                                                               gpointer     data2);
-  register GMarshalFunc_BOXED__OBJECT_OBJECT_BOXED callback;
+  typedef gpointer (*GMarshalFunc_BOXED__OBJECT_BOXED_BOXED) (gpointer     data1,
+                                                              gpointer     arg_1,
+                                                              gpointer     arg_2,
+                                                              gpointer     arg_3,
+                                                              gpointer     data2);
+  register GMarshalFunc_BOXED__OBJECT_BOXED_BOXED callback;
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
   gpointer v_return;
@@ -356,11 +356,11 @@
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_BOXED__OBJECT_OBJECT_BOXED) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_BOXED__OBJECT_BOXED_BOXED) (marshal_data ? marshal_data : cc->callback);
 
   v_return = callback (data1,
                        g_marshal_value_peek_object (param_values + 1),
-                       g_marshal_value_peek_object (param_values + 2),
+                       g_marshal_value_peek_boxed (param_values + 2),
                        g_marshal_value_peek_boxed (param_values + 3),
                        data2);
 
@@ -453,3 +453,122 @@
   g_value_take_object (return_value, v_return);
 }
 
+/* OBJECT:INT (gstplay-marshal.list:10) */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_play_marshal_OBJECT__INT (GClosure     *closure,
+                              GValue       *return_value G_GNUC_UNUSED,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint G_GNUC_UNUSED,
+                              gpointer      marshal_data)
+{
+  typedef GObject* (*GMarshalFunc_OBJECT__INT) (gpointer     data1,
+                                                gint         arg_1,
+                                                gpointer     data2);
+  register GMarshalFunc_OBJECT__INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  GObject* v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_OBJECT__INT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_int (param_values + 1),
+                       data2);
+
+  g_value_take_object (return_value, v_return);
+}
+
+/* INT64:VOID (gstplay-marshal.list:11) */
+void
+gst_play_marshal_INT64__VOID (GClosure     *closure,
+                              GValue       *return_value G_GNUC_UNUSED,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint G_GNUC_UNUSED,
+                              gpointer      marshal_data)
+{
+  typedef gint64 (*GMarshalFunc_INT64__VOID) (gpointer     data1,
+                                              gpointer     data2);
+  register GMarshalFunc_INT64__VOID callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gint64 v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_INT64__VOID) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       data2);
+
+  g_value_set_int64 (return_value, v_return);
+}
+
+/* VOID:OBJECT,INT64,INT64 (gstplay-marshal.list:12) */
+void
+gst_play_marshal_VOID__OBJECT_INT64_INT64 (GClosure     *closure,
+                                           GValue       *return_value G_GNUC_UNUSED,
+                                           guint         n_param_values,
+                                           const GValue *param_values,
+                                           gpointer      invocation_hint G_GNUC_UNUSED,
+                                           gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__OBJECT_INT64_INT64) (gpointer     data1,
+                                                         gpointer     arg_1,
+                                                         gint64       arg_2,
+                                                         gint64       arg_3,
+                                                         gpointer     data2);
+  register GMarshalFunc_VOID__OBJECT_INT64_INT64 callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__OBJECT_INT64_INT64) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_object (param_values + 1),
+            g_marshal_value_peek_int64 (param_values + 2),
+            g_marshal_value_peek_int64 (param_values + 3),
+            data2);
+}
+
--- a/gst_plugins_base/gst/playback/gstplay-marshal.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplay-marshal.h	Fri Apr 16 15:15:52 2010 +0300
@@ -6,17 +6,17 @@
 
 G_BEGIN_DECLS
 
-/* BOOLEAN:OBJECT,OBJECT (gstplay-marshal.list:1) */
+/* BOOLEAN:OBJECT,BOXED (gstplay-marshal.list:1) */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-extern void gst_play_marshal_BOOLEAN__OBJECT_OBJECT (GClosure     *closure,
-                                                     GValue       *return_value,
-                                                     guint         n_param_values,
-                                                     const GValue *param_values,
-                                                     gpointer      invocation_hint,
-                                                     gpointer      marshal_data);
+extern void gst_play_marshal_BOOLEAN__OBJECT_BOXED (GClosure     *closure,
+                                                    GValue       *return_value,
+                                                    guint         n_param_values,
+                                                    const GValue *param_values,
+                                                    gpointer      invocation_hint,
+                                                    gpointer      marshal_data);
 
 /* BOOLEAN:OBJECT,OBJECT,OBJECT (gstplay-marshal.list:2) */
 #ifdef __SYMBIAN32__
@@ -30,17 +30,17 @@
                                                             gpointer      invocation_hint,
                                                             gpointer      marshal_data);
 
-/* BOXED:OBJECT,OBJECT (gstplay-marshal.list:3) */
+/* BOXED:OBJECT,BOXED (gstplay-marshal.list:3) */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-extern void gst_play_marshal_BOXED__OBJECT_OBJECT (GClosure     *closure,
-                                                   GValue       *return_value,
-                                                   guint         n_param_values,
-                                                   const GValue *param_values,
-                                                   gpointer      invocation_hint,
-                                                   gpointer      marshal_data);
+extern void gst_play_marshal_BOXED__OBJECT_BOXED (GClosure     *closure,
+                                                  GValue       *return_value,
+                                                  guint         n_param_values,
+                                                  const GValue *param_values,
+                                                  gpointer      invocation_hint,
+                                                  gpointer      marshal_data);
 
 /* VOID:OBJECT,BOOLEAN (gstplay-marshal.list:4) */
 #ifdef __SYMBIAN32__
@@ -66,29 +66,29 @@
                                                         gpointer      invocation_hint,
                                                         gpointer      marshal_data);
 
-/* ENUM:OBJECT,OBJECT,OBJECT (gstplay-marshal.list:6) */
+/* ENUM:OBJECT,BOXED,OBJECT (gstplay-marshal.list:6) */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-extern void gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT (GClosure     *closure,
-                                                         GValue       *return_value,
-                                                         guint         n_param_values,
-                                                         const GValue *param_values,
-                                                         gpointer      invocation_hint,
-                                                         gpointer      marshal_data);
+extern void gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT (GClosure     *closure,
+                                                        GValue       *return_value,
+                                                        guint         n_param_values,
+                                                        const GValue *param_values,
+                                                        gpointer      invocation_hint,
+                                                        gpointer      marshal_data);
 
-/* BOXED:OBJECT,OBJECT,BOXED (gstplay-marshal.list:7) */
+/* BOXED:OBJECT,BOXED,BOXED (gstplay-marshal.list:7) */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-extern void gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED (GClosure     *closure,
-                                                         GValue       *return_value,
-                                                         guint         n_param_values,
-                                                         const GValue *param_values,
-                                                         gpointer      invocation_hint,
-                                                         gpointer      marshal_data);
+extern void gst_play_marshal_BOXED__OBJECT_BOXED_BOXED (GClosure     *closure,
+                                                        GValue       *return_value,
+                                                        guint         n_param_values,
+                                                        const GValue *param_values,
+                                                        gpointer      invocation_hint,
+                                                        gpointer      marshal_data);
 
 /* BOXED:INT (gstplay-marshal.list:8) */
 #ifdef __SYMBIAN32__
@@ -114,6 +114,34 @@
                                             gpointer      invocation_hint,
                                             gpointer      marshal_data);
 
+/* OBJECT:INT (gstplay-marshal.list:10) */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+extern void gst_play_marshal_OBJECT__INT (GClosure     *closure,
+                                          GValue       *return_value,
+                                          guint         n_param_values,
+                                          const GValue *param_values,
+                                          gpointer      invocation_hint,
+                                          gpointer      marshal_data);
+
+/* INT64:VOID (gstplay-marshal.list:11) */
+extern void gst_play_marshal_INT64__VOID (GClosure     *closure,
+                                          GValue       *return_value,
+                                          guint         n_param_values,
+                                          const GValue *param_values,
+                                          gpointer      invocation_hint,
+                                          gpointer      marshal_data);
+
+/* VOID:OBJECT,INT64,INT64 (gstplay-marshal.list:12) */
+extern void gst_play_marshal_VOID__OBJECT_INT64_INT64 (GClosure     *closure,
+                                                       GValue       *return_value,
+                                                       guint         n_param_values,
+                                                       const GValue *param_values,
+                                                       gpointer      invocation_hint,
+                                                       gpointer      marshal_data);
+
 G_END_DECLS
 
 #endif /* __gst_play_marshal_MARSHAL_H__ */
--- a/gst_plugins_base/gst/playback/gstplay-marshal.list	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplay-marshal.list	Fri Apr 16 15:15:52 2010 +0300
@@ -1,9 +1,12 @@
-BOOLEAN:OBJECT,OBJECT
+BOOLEAN:OBJECT,BOXED
 BOOLEAN:OBJECT,OBJECT,OBJECT
-BOXED:OBJECT,OBJECT
+BOXED:OBJECT,BOXED
 VOID:OBJECT,BOOLEAN
 ENUM:OBJECT,OBJECT,BOXED
-ENUM:OBJECT,OBJECT,OBJECT
-BOXED:OBJECT,OBJECT,BOXED
+ENUM:OBJECT,BOXED,OBJECT
+BOXED:OBJECT,BOXED,BOXED
 BOXED:INT
 OBJECT:BOXED
+OBJECT:INT
+INT64:VOID
+VOID:OBJECT,INT64,INT64
--- a/gst_plugins_base/gst/playback/gstplayback.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplayback.c	Fri Apr 16 15:15:52 2010 +0300
@@ -27,6 +27,9 @@
 #include <gst/gst-i18n-plugin.h>
 #include <gst/pbutils/pbutils.h>
 
+#include "gststreamselector.h"
+#include "gststreaminfo.h"
+
 gboolean gst_play_bin_plugin_init (GstPlugin * plugin);
 gboolean gst_play_bin2_plugin_init (GstPlugin * plugin);
 
@@ -41,8 +44,14 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
+  /* ref class from a thread-safe context to work around missing bit of
+   * thread-safety in GObject */
+  g_type_class_ref (GST_TYPE_STREAM_INFO);
+  g_type_class_ref (GST_TYPE_STREAM_SELECTOR);
+
   res = gst_play_bin_plugin_init (plugin);
   res &= gst_play_bin2_plugin_init (plugin);
 
--- a/gst_plugins_base/gst/playback/gstplaybasebin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplaybasebin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,10 +29,6 @@
 
 #include <gst/pbutils/pbutils.h>
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug);
 #define GST_CAT_DEFAULT gst_play_base_bin_debug
 
@@ -153,68 +149,76 @@
 
   g_object_class_install_property (gobject_klass, ARG_URI,
       g_param_spec_string ("uri", "URI", "URI of the media to play",
-          NULL, G_PARAM_READWRITE));
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_SUBURI,
       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
-          NULL, G_PARAM_READWRITE));
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, ARG_QUEUE_SIZE,
       g_param_spec_uint64 ("queue-size", "Queue size",
           "Size of internal queues in nanoseconds", 0, G_MAXINT64,
-          DEFAULT_QUEUE_SIZE, G_PARAM_READWRITE));
+          DEFAULT_QUEUE_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_QUEUE_THRESHOLD,
       g_param_spec_uint64 ("queue-threshold", "Queue threshold",
           "Buffering threshold of internal queues in nanoseconds", 0,
-          G_MAXINT64, DEFAULT_QUEUE_THRESHOLD, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_QUEUE_THRESHOLD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_QUEUE_MIN_THRESHOLD,
       g_param_spec_uint64 ("queue-min-threshold", "Queue min threshold",
           "Buffering low threshold of internal queues in nanoseconds", 0,
-          G_MAXINT64, DEFAULT_QUEUE_MIN_THRESHOLD, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_QUEUE_MIN_THRESHOLD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, ARG_NSTREAMS,
       g_param_spec_int ("nstreams", "NStreams", "number of streams",
-          0, G_MAXINT, 0, G_PARAM_READABLE));
+          0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_STREAMINFO,
       g_param_spec_pointer ("stream-info", "Stream info", "List of streaminfo",
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_STREAMINFO_VALUES,
       g_param_spec_value_array ("stream-info-value-array",
           "StreamInfo GValueArray", "value array of streaminfo",
           g_param_spec_object ("streaminfo", "StreamInfo", "Streaminfo object",
-              GST_TYPE_STREAM_INFO, G_PARAM_READABLE), G_PARAM_READABLE));
+              GST_TYPE_STREAM_INFO, G_PARAM_READABLE),
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_SOURCE,
       g_param_spec_object ("source", "Source", "Source element",
-          GST_TYPE_ELEMENT, G_PARAM_READABLE));
+          GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, ARG_VIDEO,
       g_param_spec_int ("current-video", "Current video",
           "Currently playing video stream (-1 = none)",
-          -1, G_MAXINT, -1, G_PARAM_READWRITE));
+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_AUDIO,
       g_param_spec_int ("current-audio", "Current audio",
           "Currently playing audio stream (-1 = none)",
-          -1, G_MAXINT, -1, G_PARAM_READWRITE));
+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_TEXT,
       g_param_spec_int ("current-text", "Current text",
           "Currently playing text stream (-1 = none)",
-          -1, G_MAXINT, -1, G_PARAM_READWRITE));
+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_SUBTITLE_ENCODING,
       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
           "be checked for an encoding to use. If that is not set either, "
-          "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
+          "ISO-8859-15 will be assumed.", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlayBin::connection-speed
+   * GstPlayBaseBin:connection-speed
    *
    * Network connection speed in kbps (0 = unknown)
+   * <note><simpara>
+   * Since version 0.10.10 in #GstPlayBin, at 0.10.15 moved to #GstPlayBaseBin
+   * </simpara></note>
    *
-   * Since: 0.10.10 at gstplaybin.c, 0.10.15 moved to gstplaybasebin
-   **/
+   * Since: 0.10.10
+   */
   g_object_class_install_property (gobject_klass, ARG_CONNECTION_SPEED,
       g_param_spec_uint ("connection-speed", "Connection Speed",
           "Network connection speed in kbps (0 = unknown)",
-          0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
+          0, G_MAXUINT, DEFAULT_CONNECTION_SPEED,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0,
       "playbasebin");
@@ -486,8 +490,9 @@
 
     setup_substreams (play_base_bin);
     GST_DEBUG_OBJECT (play_base_bin, "Emitting signal");
-    res = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
-        setup_output_pads (play_base_bin, group);
+    res =
+        GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->setup_output_pads
+        (play_base_bin, group);
     GST_DEBUG_OBJECT (play_base_bin, "done");
 
     GROUP_UNLOCK (play_base_bin);
@@ -631,7 +636,7 @@
   GstPad *sinkpad;
 
   data = g_object_get_data (G_OBJECT (queue), "probe");
-  sinkpad = gst_element_get_pad (queue, "sink");
+  sinkpad = gst_element_get_static_pad (queue, "sink");
 
   if (data) {
     GST_DEBUG_OBJECT (play_base_bin,
@@ -755,7 +760,7 @@
     GstPad *sinkpad;
     guint id;
 
-    sinkpad = gst_element_get_pad (queue, "sink");
+    sinkpad = gst_element_get_static_pad (queue, "sink");
     id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), queue);
     g_object_set_data (G_OBJECT (queue), "probe", GINT_TO_POINTER (id));
     GST_DEBUG_OBJECT (play_base_bin,
@@ -794,6 +799,8 @@
     prename = "text";
   else if (type == GST_STREAM_TYPE_AUDIO)
     prename = "audio";
+  else if (type == GST_STREAM_TYPE_SUBPICTURE)
+    prename = "subpicture";
   else
     g_return_if_reached ();
 
@@ -823,10 +830,22 @@
    * after the source that measures the datarate and scales this
    * queue of encoded data instead.
    */
-  g_object_set (G_OBJECT (preroll),
-      "max-size-buffers", 0, "max-size-bytes",
-      ((type == GST_STREAM_TYPE_VIDEO) ? 25 : 2) * 1024 * 1024,
-      "max-size-time", play_base_bin->queue_size, NULL);
+  if (play_base_bin->raw_decoding_mode) {
+    if (type == GST_STREAM_TYPE_VIDEO) {
+      g_object_set (G_OBJECT (preroll),
+          "max-size-buffers", 2, "max-size-bytes", 0,
+          "max-size-time", (guint64) 0, NULL);
+    } else {
+      g_object_set (G_OBJECT (preroll),
+          "max-size-buffers", 0, "max-size-bytes",
+          2 * 1024 * 1024, "max-size-time", play_base_bin->queue_size, NULL);
+    }
+  } else {
+    g_object_set (G_OBJECT (preroll),
+        "max-size-buffers", 0, "max-size-bytes",
+        ((type == GST_STREAM_TYPE_VIDEO) ? 25 : 2) * 1024 * 1024,
+        "max-size-time", play_base_bin->queue_size, NULL);
+  }
 
   /* the overrun signal is always attached and serves two purposes:
    *
@@ -866,11 +885,10 @@
     g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin);
 
     /* give updates on queue size */
-    sinkpad = gst_element_get_pad (preroll, "sink");
+    sinkpad = gst_element_get_static_pad (preroll, "sink");
     id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), preroll);
     GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)",
         GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
-    gst_object_unref (sinkpad);
     g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id));
 
     /* catch eos and flush events so that we can ignore underruns */
@@ -878,6 +896,8 @@
         preroll);
     g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id));
 
+    gst_object_unref (sinkpad);
+
     /* When we connect this queue, it will start running and immediatly
      * fire an underrun. */
     g_signal_connect (G_OBJECT (preroll), "underrun",
@@ -887,7 +907,7 @@
   }
 
   /* listen for EOS so we can switch groups when one ended. */
-  preroll_pad = gst_element_get_pad (preroll, "src");
+  preroll_pad = gst_element_get_static_pad (preroll, "src");
   gst_pad_add_event_probe (preroll_pad, G_CALLBACK (probe_triggered), info);
   gst_object_unref (preroll_pad);
 
@@ -1217,8 +1237,9 @@
       setup_substreams (play_base_bin);
       GST_DEBUG ("switching to next group %p - emitting signal", group);
       /* and signal the new group */
-      res = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
-          setup_output_pads (play_base_bin, group);
+      res =
+          GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->setup_output_pads
+          (play_base_bin, group);
 
       GROUP_UNLOCK (play_base_bin);
 
@@ -1249,11 +1270,11 @@
 
   /* make a fakesrc that will just emit one EOS */
   fakesrc = gst_element_factory_make ("fakesrc", NULL);
-  g_object_set (G_OBJECT (fakesrc), "num_buffers", 0, NULL);
+  g_object_set (G_OBJECT (fakesrc), "num-buffers", 0, NULL);
 
   GST_DEBUG ("patching unlinked pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
-  srcpad = gst_element_get_pad (fakesrc, "src");
+  srcpad = gst_element_get_static_pad (fakesrc, "src");
   gst_bin_add (GST_BIN_CAST (play_base_bin), fakesrc);
   gst_pad_link (srcpad, pad);
   gst_object_unref (srcpad);
@@ -1340,6 +1361,9 @@
   if (g_str_has_prefix (mimetype, "audio/") &&
       parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
     type = GST_STREAM_TYPE_AUDIO;
+  } else if (g_str_has_prefix (mimetype, "video/x-dvd-subpicture") &&
+      parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
+    type = GST_STREAM_TYPE_SUBPICTURE;
   } else if (g_str_has_prefix (mimetype, "video/") &&
       parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
     type = GST_STREAM_TYPE_VIDEO;
@@ -1572,7 +1596,7 @@
 
 /* mime types we consider raw media */
 static const gchar *raw_mimes[] = {
-  "audio/x-raw", "video/x-raw", NULL
+  "audio/x-raw", "video/x-raw", "video/x-dvd-subpicture", NULL
 };
 
 #define IS_STREAM_URI(uri)          (array_has_value (stream_uris, uri))
@@ -1690,6 +1714,7 @@
 
   /* if this is a pad with all raw caps, we can expose it */
   if (has_all_raw_caps (pad, &is_raw) && is_raw) {
+    bin->raw_decoding_mode = TRUE;
     /* it's all raw, create output pads. */
     new_decoded_pad_full (element, pad, FALSE, bin, FALSE);
     return;
@@ -1939,6 +1964,19 @@
     GstElement *decoder = GST_ELEMENT_CAST (walk->data);
 
     GST_DEBUG_OBJECT (bin, "removing old decoder element");
+    /* Disconnect all the signal handlers we attached to the decodebin before
+     * we dispose of it */
+    g_signal_handlers_disconnect_by_func (decoder,
+        (gpointer) (decodebin_element_added_cb), bin);
+    g_signal_handlers_disconnect_by_func (decoder,
+        (gpointer) (decodebin_element_removed_cb), bin);
+    g_signal_handlers_disconnect_by_func (decoder,
+        (gpointer) (new_decoded_pad), bin);
+    g_signal_handlers_disconnect_by_func (decoder,
+        (gpointer) (no_more_pads), bin);
+    g_signal_handlers_disconnect_by_func (decoder,
+        (gpointer) (unknown_type), bin);
+
     gst_element_set_state (decoder, GST_STATE_NULL);
     gst_bin_remove (GST_BIN_CAST (bin), decoder);
   }
@@ -2045,6 +2083,7 @@
 
   if (!play_base_bin->need_rebuild)
     return TRUE;
+  play_base_bin->raw_decoding_mode = FALSE;
 
   GST_DEBUG_OBJECT (play_base_bin, "setup source");
 
@@ -2348,13 +2387,13 @@
   gboolean active = !mute;
   GstPad *pad;
 
-  pad = gst_element_get_pad (group->type[type - 1].preroll, "src");
+  pad = gst_element_get_static_pad (group->type[type - 1].preroll, "src");
   gst_pad_set_active (pad, active);
   gst_object_unref (pad);
-  pad = gst_element_get_pad (group->type[type - 1].preroll, "sink");
+  pad = gst_element_get_static_pad (group->type[type - 1].preroll, "sink");
   gst_pad_set_active (pad, active);
   gst_object_unref (pad);
-  pad = gst_element_get_pad (group->type[type - 1].selector, "src");
+  pad = gst_element_get_static_pad (group->type[type - 1].selector, "src");
   gst_pad_set_active (pad, active);
   gst_object_unref (pad);
 
@@ -2403,6 +2442,17 @@
     klass->set_subtitles_visible (play_base_bin, visible);
 }
 
+static void
+set_audio_mute (GstPlayBaseBin * play_base_bin, gboolean mute)
+{
+  GstPlayBaseBinClass *klass = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin);
+
+  /* we use a vfunc for this since we don't have a reference to the
+   * textoverlay element, but playbin does */
+  if (klass != NULL && klass->set_audio_mute != NULL)
+    klass->set_audio_mute (play_base_bin, mute);
+}
+
 /*
  * Caller has group-lock held.
  */
@@ -2435,6 +2485,13 @@
     set_subtitles_visible (play_base_bin, visible);
     if (!visible)
       return;
+  } else if (type == GST_STREAM_TYPE_AUDIO) {
+    gboolean mute = (source_num == -1);
+
+    set_audio_mute (play_base_bin, mute);
+
+    if (mute)
+      return;
   }
 
   sel = group->type[type - 1].selector;
--- a/gst_plugins_base/gst/playback/gstplaybasebin.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplaybasebin.h	Fri Apr 16 15:15:52 2010 +0300
@@ -63,8 +63,8 @@
     GstElement  *preroll;
     GstElement  *selector;
     gboolean     done;
-#define NUM_TYPES 3
-  } type[NUM_TYPES]; /* AUDIO, VIDEO, TEXT */
+#define NUM_TYPES 4
+  } type[NUM_TYPES]; /* AUDIO, VIDEO, TEXT, SUBPIC */
 } GstPlayBaseGroup;
 
 struct _GstPlayBaseBin {
@@ -87,6 +87,7 @@
   GstElement    *subtitle;              /* additional filesrc ! subparse bin */
   gboolean       subtitle_done;
   gboolean       need_rebuild;
+  gboolean       raw_decoding_mode;     /* Use smaller queues when source outputs raw data */
 
   GSList        *subtitle_elements;     /* subtitle elements that have 'subtitle-encoding' property */
   gchar         *subencoding;           /* encoding to propagate to the above subtitle elements     */
@@ -113,6 +114,8 @@
 
   void     (*set_subtitles_visible) (GstPlayBaseBin *play_base_bin,
                                      gboolean visible);
+  void     (*set_audio_mute)        (GstPlayBaseBin *play_base_bin,
+                                     gboolean mute);
 };
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst/playback/gstplaybin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplaybin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,12 +20,9 @@
 /**
  * SECTION:element-playbin
  *
- * <refsect2>
- * <para>
  * Playbin provides a stand-alone everything-in-one abstraction for an
  * audio and/or video player.
- * </para>
- * <para>
+ *
  * It can handle both audio and video files and features
  * <itemizedlist>
  * <listitem>
@@ -54,36 +51,33 @@
  * volume control
  * </listitem>
  * </itemizedlist>
- * </para>
+ *
+ * <refsect2>
  * <title>Usage</title>
  * <para>
  * A playbin element can be created just like any other element using
- * gst_element_factory_make(). The file/URI to play should be set via the "uri"
+ * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin:uri
  * property. This must be an absolute URI, relative file paths are not allowed.
  * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
- * </para>
- * <para>
+ *
  * Playbin is a #GstPipeline. It will notify the application of everything
  * that's happening (errors, end of stream, tags found, state changes, etc.)
  * by posting messages on its #GstBus. The application needs to watch the
  * bus.
- * </para>
- * <para>
+ *
  * Playback can be initiated by setting the element to PLAYING state using
  * gst_element_set_state(). Note that the state change will take place in
  * the background in a separate thread, when the function returns playback
  * is probably not happening yet and any errors might not have occured yet.
  * Applications using playbin should ideally be written to deal with things
  * completely asynchroneous.
- * </para>
- * <para>
+ *
  * When playback has finished (an EOS message has been received on the bus)
  * or an error has occured (an ERROR message has been received on the bus) or
  * the user wants to play a different track, playbin should be set back to
- * READY or NULL state, then the "uri" property should be set to the new
- * location and then playbin be set to PLAYING state again.
- * </para>
- * <para>
+ * READY or NULL state, then the #GstPlayBin:uri property should be set to the
+ * new location and then playbin be set to PLAYING state again.
+ *
  * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
  * on the playbin element. Again, the seek will not be executed
  * instantaneously, but will be done in a background thread. When the seek
@@ -91,35 +85,34 @@
  * may wait for the seek to finish (or fail) using gst_element_get_state() with
  * -1 as the timeout, but this will block the user interface and is not
  * recommended at all.
- * </para>
- * <para>
+ *
  * Applications may query the current position and duration of the stream
  * via gst_element_query_position() and gst_element_query_duration() and
  * setting the format passed to GST_FORMAT_TIME. If the query was successful,
  * the duration or position will have been returned in units of nanoseconds.
  * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Advanced Usage: specifying the audio and video sink</title>
  * <para>
  * By default, if no audio sink or video sink has been specified via the
- * "audio-sink" or "video-sink" property, playbin will use the autoaudiosink
- * and autovideosink elements to find the first-best available output method.
+ * #GstPlayBin:audio-sink or #GstPlayBin:video-sink property, playbin will use
+ * the autoaudiosink and autovideosink elements to find the first-best
+ * available output method.
  * This should work in most cases, but is not always desirable. Often either
  * the user or application might want to specify more explicitly what to use
  * for audio and video output.
- * </para>
- * <para>
+ *
  * If the application wants more control over how audio or video should be
  * output, it may create the audio/video sink elements itself (for example
  * using gst_element_factory_make()) and provide them to playbin using the
- * "audio-sink" or "video-sink" property.
- * </para>
- * <para>
+ * #GstPlayBin:audio-sink or #GstPlayBin:video-sink property.
+ *
  * GNOME-based applications, for example, will usually want to create
  * gconfaudiosink and gconfvideosink elements and make playbin use those,
  * so that output happens to whatever the user has configured in the GNOME
  * Multimedia System Selector confinguration dialog.
- * </para>
- * <para>
+ *
  * The sink elements do not necessarily need to be ready-made sinks. It is
  * possible to create container elements that look like a sink to playbin,
  * but in reality contain a number of custom elements linked together. This
@@ -128,23 +121,23 @@
  * it to the sink pad of the first element within the bin. This can be used
  * for a number of purposes, for example to force output to a particular
  * format or to modify or observe the data before it is output.
- * </para>
- * <para>
+ *
  * It is also possible to 'suppress' audio and/or video output by using
  * 'fakesink' elements (or capture it from there using the fakesink element's
  * "handoff" signal, which, nota bene, is fired from the streaming thread!).
  * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Retrieving Tags and Other Meta Data</title>
  * <para>
  * Most of the common meta data (artist, title, etc.) can be retrieved by
  * watching for TAG messages on the pipeline's bus (see above).
- * </para>
- * <para>
+ *
  * Other more specific meta information like width/height/framerate of video
  * streams or samplerate/number of channels of audio streams can be obtained
- * using the "stream-info" property, which will return a GList of stream info
- * objects, one for each stream. These are opaque objects that can only be
- * accessed via the standard GObject property interface, ie. g_object_get().
+ * using the  #GstPlayBaseBin:stream-info property, which will return a GList of
+ * stream info objects, one for each stream. These are opaque objects that can
+ * only be accessed via the standard GObject property interface, ie. g_object_get().
  * Each stream info object has the following properties:
  * <itemizedlist>
  * <listitem>"object" (GstObject) (the decoder source pad usually)</listitem>
@@ -155,14 +148,15 @@
  * <listitem>"language-code" (string) (ISO-639 language code for this stream, mostly used for audio/subtitle streams)</listitem>
  * <listitem>"codec" (string) (format this stream was encoded in)</listitem>
  * </itemizedlist>
- * Stream information from the stream-info properties is best queried once
+ * Stream information from the #GstPlayBaseBin:stream-info property is best queried once
  * playbin has changed into PAUSED or PLAYING state (which can be detected
- * via a state-changed message on the bus where old_state=READY and
+ * via a state-changed message on the #GstBus where old_state=READY and
  * new_state=PAUSED), since before that the list might not be complete yet or
  * not contain all available information (like language-codes).
  * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Buffering</title>
- * <para>
  * Playbin handles buffering automatically for the most part, but applications
  * need to handle parts of the buffering process as well. Whenever playbin is
  * buffering, it will post BUFFERING messages on the bus with a percentage
@@ -171,9 +165,7 @@
  * They may also want to convey the buffering progress to the user in some
  * way. Here is how to extract the percentage information from the message
  * (requires GStreamer >= 0.10.11):
- * </para>
- * <para>
- * <programlisting>
+ * |[
  * switch (GST_MESSAGE_TYPE (msg)) {
  *   case GST_MESSAGE_BUFFERING: {
  *     gint percent = 0;
@@ -183,21 +175,21 @@
  *   }
  *   ...
  * }
- * </programlisting>
+ * ]|
  * Note that applications should keep/set the pipeline in the PAUSED state when
  * a BUFFERING message is received with a buffer percent value < 100 and set
  * the pipeline back to PLAYING state when a BUFFERING message with a value
  * of 100 percent is received (if PLAYING is the desired state, that is).
- * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Embedding the video window in your application</title>
- * <para>
  * By default, playbin (or rather the video sinks used) will create their own
  * window. Applications will usually want to force output to a window of their
- * own, however. This can be done using the GstXOverlay interface, which most
+ * own, however. This can be done using the #GstXOverlay interface, which most
  * video sinks implement. See the documentation there for more details.
- * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Specifying which CD/DVD device to use</title>
- * <para>
  * The device to use for CDs/DVDs needs to be set on the source element
  * playbin creates before it is opened. The only way to do this at the moment
  * is to connect to playbin's "notify::source" signal, which will be emitted
@@ -206,35 +198,24 @@
  * property and set it appropriately. In future ways might be added to specify
  * the device as part of the URI, but at the time of writing this is not
  * possible yet.
- * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Examples</title>
- * <para>
- * Here is a simple pipeline to play back a video or audio file:
- * <programlisting>
+ * |[
  * gst-launch -v playbin uri=file:///path/to/somefile.avi
- * </programlisting>
- * This will play back the given AVI video file, given that the video and
+ * ]| This will play back the given AVI video file, given that the video and
  * audio decoders required to decode the content are installed. Since no
  * special audio sink or video sink is supplied (not possible via gst-launch),
  * playbin will try to find a suitable audio and video sink automatically
  * using the autoaudiosink and autovideosink elements.
- * </para>
- * <para>
- * Here is a another pipeline to play track 4 of an audio CD:
- * <programlisting>
+ * |[
  * gst-launch -v playbin uri=cdda://4
- * </programlisting>
- * This will play back track 4 on an audio CD in your disc drive (assuming
+ * ]| This will play back track 4 on an audio CD in your disc drive (assuming
  * the drive is detected automatically by the plugin).
- * </para>
- * <para>
- * Here is a another pipeline to play title 1 of a DVD:
- * <programlisting>
+ * |[
  * gst-launch -v playbin uri=dvd://1
- * </programlisting>
- * This will play back title 1 of a DVD in your disc drive (assuming
+ * ]| This will play back title 1 of a DVD in your disc drive (assuming
  * the drive is detected automatically by the plugin).
- * </para>
  * </refsect2>
  */
 
@@ -250,10 +231,6 @@
 
 #include "gstplaybasebin.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
 #define GST_CAT_DEFAULT gst_play_bin_debug
 
@@ -268,6 +245,11 @@
 typedef struct _GstPlayBin GstPlayBin;
 typedef struct _GstPlayBinClass GstPlayBinClass;
 
+/**
+ * GstPlayBin:
+ *
+ * High-level player element
+ */
 struct _GstPlayBin
 {
   GstPlayBaseBin parent;
@@ -280,6 +262,7 @@
   GstElement *pending_visualisation;
   GstElement *volume_element;
   GstElement *textoverlay_element;
+  GstElement *spu_element;
   gfloat volume;
 
   /* these are the currently active sinks */
@@ -330,6 +313,8 @@
 static void remove_sinks (GstPlayBin * play_bin);
 static void playbin_set_subtitles_visible (GstPlayBaseBin * play_base_bin,
     gboolean visible);
+static void playbin_set_audio_mute (GstPlayBaseBin * play_base_bin,
+    gboolean mute);
 
 static void gst_play_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * spec);
@@ -400,27 +385,27 @@
   g_object_class_install_property (gobject_klass, ARG_VIDEO_SINK,
       g_param_spec_object ("video-sink", "Video Sink",
           "the video output element to use (NULL = default sink)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_AUDIO_SINK,
       g_param_spec_object ("audio-sink", "Audio Sink",
           "the audio output element to use (NULL = default sink)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_VIS_PLUGIN,
       g_param_spec_object ("vis-plugin", "Vis plugin",
           "the visualization element to use (NULL = none)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_VOLUME,
       g_param_spec_double ("volume", "volume", "volume",
-          0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE));
+          0.0, VOLUME_MAX_DOUBLE, 1.0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_FRAME,
       gst_param_spec_mini_object ("frame", "Frame",
-          "The last frame (NULL = no video available)",
-          GST_TYPE_BUFFER, G_PARAM_READABLE));
+          "The last frame (NULL = no video available)", GST_TYPE_BUFFER,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_FONT_DESC,
-      g_param_spec_string ("subtitle-font-desc",
-          "Subtitle font description",
-          "Pango font description of font "
-          "to be used for subtitle rendering", NULL, G_PARAM_WRITABLE));
+      g_param_spec_string ("subtitle-font-desc", "Subtitle font description",
+          "Pango font description of font " "to be used for subtitle rendering",
+          NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
 
   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_dispose);
 
@@ -435,6 +420,7 @@
 
   playbasebin_klass->setup_output_pads = setup_sinks;
   playbasebin_klass->set_subtitles_visible = playbin_set_subtitles_visible;
+  playbasebin_klass->set_audio_mute = playbin_set_audio_mute;
 }
 
 static void
@@ -446,6 +432,7 @@
   play_bin->pending_visualisation = NULL;
   play_bin->volume_element = NULL;
   play_bin->textoverlay_element = NULL;
+  play_bin->spu_element = NULL;
   play_bin->volume = 1.0;
   play_bin->sinks = NULL;
   play_bin->frame = NULL;
@@ -491,6 +478,10 @@
     gst_object_unref (play_bin->textoverlay_element);
     play_bin->textoverlay_element = NULL;
   }
+  if (play_bin->spu_element != NULL) {
+    gst_object_unref (play_bin->spu_element);
+    play_bin->spu_element = NULL;
+  }
   g_free (play_bin->font_desc);
   play_bin->font_desc = NULL;
 
@@ -538,7 +529,7 @@
     goto beach;
   }
 
-  vis_src_pad = gst_element_get_pad (play_bin->visualisation, "src");
+  vis_src_pad = gst_element_get_static_pad (play_bin->visualisation, "src");
   vis_sink_pad = gst_pad_get_peer (tee_pad);
 
   /* Can be fakesink */
@@ -581,8 +572,8 @@
     /* Synchronizing state */
     gst_element_set_state (pending_visualisation, bin_state);
 
-    vis_sink_pad = gst_element_get_pad (pending_visualisation, "sink");
-    vis_src_pad = gst_element_get_pad (pending_visualisation, "src");
+    vis_sink_pad = gst_element_get_static_pad (pending_visualisation, "sink");
+    vis_src_pad = gst_element_get_static_pad (pending_visualisation, "src");
 
     if (!GST_IS_PAD (vis_sink_pad) || !GST_IS_PAD (vis_src_pad)) {
       goto beach;
@@ -682,7 +673,7 @@
             GstPad *vis_sink_pad = NULL, *tee_pad = NULL;
 
             /* Now get tee pad and block it async */
-            vis_sink_pad = gst_element_get_pad (play_bin->visualisation,
+            vis_sink_pad = gst_element_get_static_pad (play_bin->visualisation,
                 "sink");
             if (!GST_IS_PAD (vis_sink_pad)) {
               goto beach;
@@ -781,7 +772,7 @@
   if (GST_BUFFER_CAPS (frame) == NULL) {
     GstPad *pad;
 
-    if ((pad = gst_element_get_pad (identity, "sink"))) {
+    if ((pad = gst_element_get_static_pad (identity, "sink"))) {
       gst_buffer_set_caps (frame, GST_PAD_CAPS (pad));
       gst_object_unref (pad);
     }
@@ -870,7 +861,7 @@
   if (!gst_element_link_pads (scale, "src", sink, NULL))
     goto link_failed;
 
-  pad = gst_element_get_pad (identity, "sink");
+  pad = gst_element_get_static_pad (identity, "sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
   gst_object_unref (pad);
 
@@ -926,7 +917,7 @@
  *  | tbin                  +-------------+            |
  *  |          +-----+      | textoverlay |   +------+ |
  *  |          | csp | +--video_sink      |   | vbin | |
- * video_sink-sink  src+ +-text_sink     src-sink    | |
+ * video_sink-sink  src+ +-text_sink    src---sink   | |
  *  |          +-----+   |  +-------------+   +------+ |
  * text_sink-------------+                             |
  *  +--------------------------------------------------+
@@ -935,16 +926,11 @@
  *  videosink without the text_sink pad.
  */
 static GstElement *
-gen_text_element (GstPlayBin * play_bin)
+add_text_element (GstPlayBin * play_bin, GstElement * vbin)
 {
-  GstElement *element, *csp, *overlay, *vbin;
+  GstElement *element, *csp, *overlay;
   GstPad *pad;
 
-  /* Create the video rendering bin, error is posted when this fails. */
-  vbin = gen_video_element (play_bin);
-  if (!vbin)
-    return NULL;
-
   /* Text overlay */
   overlay = gst_element_factory_make ("textoverlay", "overlay");
 
@@ -976,14 +962,21 @@
   gst_element_link_pads (overlay, "src", vbin, "sink");
 
   /* Add ghost pads on the subtitle bin */
-  pad = gst_element_get_pad (overlay, "text_sink");
+  pad = gst_element_get_static_pad (overlay, "text_sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("text_sink", pad));
   gst_object_unref (pad);
 
-  pad = gst_element_get_pad (csp, "sink");
+  pad = gst_element_get_static_pad (csp, "sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
   gst_object_unref (pad);
 
+  /* If the vbin provides a subpicture sink pad, ghost it too */
+  pad = gst_element_get_static_pad (vbin, "subpicture_sink");
+  if (pad) {
+    gst_element_add_pad (element, gst_ghost_pad_new ("subpicture_sink", pad));
+    gst_object_unref (pad);
+  }
+
   /* Set state to READY */
   gst_element_set_state (element, GST_STATE_READY);
 
@@ -999,6 +992,74 @@
   }
 }
 
+/* make an element for rendering DVD subpictures onto output video
+ *
+ *  +---------------------------------------------+
+ *  | tbin                   +--------+           |
+ *  |          +-----+       |        |  +------+ |
+ *  |          | csp | src-videosink  |  | vbin | |
+ * video_sink-sink  src+     |       src-sink   | |
+ *  |          +-----+   +subpicture  |  +------+ |
+ * subpicture_pad--------+   +--------+           |
+ *  +---------- ----------------------------------+
+ *
+ */
+static GstElement *
+add_spu_element (GstPlayBin * play_bin, GstElement * vbin)
+{
+  GstElement *element, *csp, *overlay;
+  GstPad *pad;
+
+  /* DVD spu overlay */
+  GST_DEBUG_OBJECT (play_bin, "Attempting to insert DVD SPU element");
+
+  overlay = gst_element_factory_make ("dvdspu", "overlay");
+
+  /* If no overlay return the video bin without subpicture support. */
+  if (!overlay)
+    goto no_overlay;
+
+  /* Create our bin */
+  element = gst_bin_new ("spubin");
+
+  /* Take a ref */
+  play_bin->spu_element = GST_ELEMENT_CAST (gst_object_ref (overlay));
+
+  /* we know this will succeed, as the video bin already created one before */
+  csp = gst_element_factory_make ("ffmpegcolorspace", "spucsp");
+
+  /* Add our elements */
+  gst_bin_add_many (GST_BIN_CAST (element), csp, overlay, vbin, NULL);
+
+  /* Link */
+  gst_element_link_pads (csp, "src", overlay, "video");
+  gst_element_link_pads (overlay, "src", vbin, "sink");
+
+  /* Add ghost pad on the subpicture bin so it looks like vbin */
+  pad = gst_element_get_static_pad (csp, "sink");
+  gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
+  gst_object_unref (pad);
+
+  pad = gst_element_get_static_pad (overlay, "subpicture");
+  gst_element_add_pad (element, gst_ghost_pad_new ("subpicture_sink", pad));
+  gst_object_unref (pad);
+
+  /* Set state to READY */
+  gst_element_set_state (element, GST_STATE_READY);
+
+  return element;
+
+  /* ERRORS */
+no_overlay:
+  {
+    post_missing_element_message (play_bin, "dvdspu");
+    GST_WARNING_OBJECT (play_bin,
+        "No DVD overlay (dvdspu) element. "
+        "menu highlight/subtitles unavailable");
+    return vbin;
+  }
+}
+
 /* make the element (bin) that contains the elements needed to perform
  * audio playback.
  *
@@ -1058,28 +1119,21 @@
   if (scale == NULL)
     goto no_audioresample;
   gst_bin_add (GST_BIN_CAST (element), scale);
-#ifndef __SYMBIAN32__
+
   volume = gst_element_factory_make ("volume", "volume");
   if (volume == NULL)
     goto no_volume;
   g_object_set (G_OBJECT (volume), "volume", play_bin->volume, NULL);
   play_bin->volume_element = volume;
   gst_bin_add (GST_BIN_CAST (element), volume);
-#endif
 
   res = gst_element_link_pads (conv, "src", scale, "sink");
-#ifndef __SYMBIAN32__
   res &= gst_element_link_pads (scale, "src", volume, "sink");
-#else
-  res &= gst_element_link_pads (scale, "src", sink, NULL);
-#endif
-#ifndef __SYMBIAN32__
   res &= gst_element_link_pads (volume, "src", sink, NULL);
-#endif
   if (!res)
     goto link_failed;
 
-  pad = gst_element_get_pad (conv, "sink");
+  pad = gst_element_get_static_pad (conv, "sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
   gst_object_unref (pad);
 
@@ -1229,20 +1283,20 @@
   if (!res)
     goto link_failed;
 
-  pad = gst_element_get_pad (aqueue, "sink");
+  pad = gst_element_get_static_pad (aqueue, "sink");
   rpad = gst_element_get_request_pad (tee, "src%d");
   gst_pad_link (rpad, pad);
   gst_object_unref (rpad);
   gst_object_unref (pad);
   gst_element_link_pads (aqueue, "src", asink, "sink");
 
-  pad = gst_element_get_pad (vqueue, "sink");
+  pad = gst_element_get_static_pad (vqueue, "sink");
   rpad = gst_element_get_request_pad (tee, "src%d");
   gst_pad_link (rpad, pad);
   gst_object_unref (rpad);
   gst_object_unref (pad);
 
-  pad = gst_element_get_pad (tee, "sink");
+  pad = gst_element_get_static_pad (tee, "sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
   gst_object_unref (pad);
 
@@ -1310,7 +1364,7 @@
       gst_bin_remove (GST_BIN_CAST (parent), element);
       gst_object_unref (parent);
     }
-    pad = gst_element_get_pad (element, "sink");
+    pad = gst_element_get_static_pad (element, "sink");
     if (pad != NULL) {
       peer = gst_pad_get_peer (pad);
       if (peer != NULL) {
@@ -1329,7 +1383,7 @@
       gst_bin_remove (GST_BIN_CAST (parent), element);
       gst_object_unref (parent);
     }
-    pad = gst_element_get_pad (element, "sink");
+    pad = gst_element_get_static_pad (element, "sink");
     if (pad != NULL) {
       peer = gst_pad_get_peer (pad);
       if (peer != NULL) {
@@ -1345,7 +1399,7 @@
     GstPad *pad;
     GstPad *peer;
 
-    pad = gst_element_get_pad (element, "sink");
+    pad = gst_element_get_static_pad (element, "sink");
 
     GST_LOG ("removing sink %p", element);
 
@@ -1429,7 +1483,7 @@
     goto state_failed;
 
   /* we found a sink for this stream, now try to install it */
-  sinkpad = gst_element_get_pad (sink, "sink");
+  sinkpad = gst_element_get_static_pad (sink, "sink");
   linkres = gst_pad_link (srcpad, sinkpad);
   gst_object_unref (sinkpad);
 
@@ -1438,7 +1492,7 @@
     goto link_failed;
 
   if (GST_IS_PAD (subtitle_pad)) {
-    sinkpad = gst_element_get_pad (sink, "text_sink");
+    sinkpad = gst_element_get_static_pad (sink, "text_sink");
     linkres = gst_pad_link (subtitle_pad, sinkpad);
     gst_object_unref (sinkpad);
   }
@@ -1505,9 +1559,10 @@
 setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
 {
   GstPlayBin *play_bin = GST_PLAY_BIN (play_base_bin);
-  GList *streaminfo = NULL, *s;
+  gboolean have_video = FALSE;
   gboolean need_vis = FALSE;
   gboolean need_text = FALSE;
+  gboolean need_spu = FALSE;
   GstPad *textsrcpad = NULL, *pad = NULL, *origtextsrcpad = NULL;
   GstElement *sink;
   gboolean res = TRUE;
@@ -1519,25 +1574,18 @@
   GST_DEBUG_OBJECT (play_base_bin, "setupsinks");
 
   /* find out what to do */
-  if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0 &&
-      group->type[GST_STREAM_TYPE_TEXT - 1].npads > 0) {
+  have_video = (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0);
+  need_spu = (group->type[GST_STREAM_TYPE_SUBPICTURE - 1].npads != 0);
+
+  if (have_video && group->type[GST_STREAM_TYPE_TEXT - 1].npads > 0) {
     need_text = TRUE;
-  } else if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0 &&
+  } else if (!have_video &&
       group->type[GST_STREAM_TYPE_AUDIO - 1].npads > 0 &&
       play_bin->visualisation != NULL) {
     need_vis = TRUE;
   }
 
   /* now actually connect everything */
-  g_object_get (G_OBJECT (play_base_bin), "stream-info", &streaminfo, NULL);
-  for (s = streaminfo; s; s = g_list_next (s)) {
-    GObject *obj = G_OBJECT (s->data);
-    gint type;
-    GstObject *object;
-
-    g_object_get (obj, "type", &type, NULL);
-    g_object_get (obj, "object", &object, NULL);
-  }
 
   /* link audio */
   if (group->type[GST_STREAM_TYPE_AUDIO - 1].npads > 0) {
@@ -1549,22 +1597,34 @@
     if (!sink)
       return FALSE;
 
-    pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_AUDIO - 1].preroll,
-        "src");
+    pad =
+        gst_element_get_static_pad (group->type[GST_STREAM_TYPE_AUDIO -
+            1].preroll, "src");
     res = add_sink (play_bin, sink, pad, NULL);
     gst_object_unref (pad);
   }
 
   /* link video */
-  if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0) {
+  if (have_video) {
+    /* Create the video rendering bin, error is posted when this fails. */
+    sink = gen_video_element (play_bin);
+    if (!sink)
+      return FALSE;
+    if (need_spu) {
+      sink = add_spu_element (play_bin, sink);
+    }
+
     if (need_text) {
       GstObject *parent = NULL, *grandparent = NULL;
       GstPad *ghost = NULL;
 
-      sink = gen_text_element (play_bin);
+      /* Add the subtitle overlay element into the video sink */
+      sink = add_text_element (play_bin, sink);
+
+      /* Link the incoming subtitle stream into the output bin */
       textsrcpad =
-          gst_element_get_pad (group->type[GST_STREAM_TYPE_TEXT - 1].preroll,
-          "src");
+          gst_element_get_static_pad (group->type[GST_STREAM_TYPE_TEXT -
+              1].preroll, "src");
 
       /* This pad is from subtitle-bin, we need to create a ghost pad to have
          common grandparents */
@@ -1624,14 +1684,13 @@
 
       gst_object_unref (parent);
       gst_object_unref (grandparent);
-    } else {
-      sink = gen_video_element (play_bin);
     }
   beach:
     if (!sink)
       return FALSE;
-    pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_VIDEO - 1].preroll,
-        "src");
+    pad =
+        gst_element_get_static_pad (group->type[GST_STREAM_TYPE_VIDEO -
+            1].preroll, "src");
     res = add_sink (play_bin, sink, pad, textsrcpad);
     gst_object_unref (pad);
     if (textsrcpad)
@@ -1640,6 +1699,30 @@
       gst_pad_set_blocked_async (origtextsrcpad, FALSE, dummy_blocked_cb, NULL);
       gst_object_unref (origtextsrcpad);
     }
+
+    /* If we have a DVD subpicture stream, link it to the SPU now */
+    if (need_spu) {
+      GstPad *subpic_pad;
+      GstPad *spu_sink_pad;
+
+      subpic_pad =
+          gst_element_get_static_pad (group->type[GST_STREAM_TYPE_SUBPICTURE
+              - 1].preroll, "src");
+      spu_sink_pad = gst_element_get_static_pad (sink, "subpicture_sink");
+      if (subpic_pad && spu_sink_pad) {
+        GST_LOG_OBJECT (play_bin, "Linking DVD subpicture stream onto SPU");
+        gst_pad_set_blocked_async (subpic_pad, TRUE, dummy_blocked_cb, NULL);
+        if (gst_pad_link (subpic_pad, spu_sink_pad) != GST_PAD_LINK_OK) {
+          GST_WARNING_OBJECT (play_bin,
+              "Failed to link DVD subpicture stream onto SPU");
+        }
+        gst_pad_set_blocked_async (subpic_pad, FALSE, dummy_blocked_cb, NULL);
+      }
+      if (subpic_pad)
+        gst_object_unref (subpic_pad);
+      if (spu_sink_pad)
+        gst_object_unref (spu_sink_pad);
+    }
   }
 
   /* remove the sinks now, pipeline get_state will now wait for the
@@ -1667,6 +1750,16 @@
   }
 }
 
+static void
+playbin_set_audio_mute (GstPlayBaseBin * play_base_bin, gboolean mute)
+{
+  GstPlayBin *playbin = GST_PLAY_BIN (play_base_bin);
+
+  if (playbin->volume_element) {
+    g_object_set (G_OBJECT (playbin->volume_element), "mute", mute, NULL);
+  }
+}
+
 /* Send an event to our sinks until one of them works; don't then send to the
  * remaining sinks (unlike GstBin)
  */
--- a/gst_plugins_base/gst/playback/gstplaybin2.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplaybin2.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,12 +20,13 @@
 /**
  * SECTION:element-playbin2
  *
- * <refsect2>
- * <para>
- * Playbin provides a stand-alone everything-in-one abstraction for an
+ * Playbin2 provides a stand-alone everything-in-one abstraction for an
  * audio and/or video player.
- * </para>
- * <para>
+ *
+ * At this stage, playbin2 is considered UNSTABLE. The API provided in the
+ * signals and properties may yet change in the near future. When playbin2
+ * is stable, it will probably replace #playbin
+ *
  * It can handle both audio and video files and features
  * <itemizedlist>
  * <listitem>
@@ -36,10 +37,11 @@
  * visualisations for audio files
  * </listitem>
  * <listitem>
- * subtitle support for video files
+ * subtitle support for video files. Subtitles can be store in external
+ * files.
  * </listitem>
  * <listitem>
- * stream selection between different audio/subtitles streams
+ * stream selection between different video/audio/subtitles streams
  * </listitem>
  * <listitem>
  * meta info (tag) extraction
@@ -51,39 +53,36 @@
  * buffering when playing streams over a network
  * </listitem>
  * <listitem>
- * volume control
+ * volume control with mute option
  * </listitem>
  * </itemizedlist>
- * </para>
+ *
+ * <refsect2>
  * <title>Usage</title>
  * <para>
  * A playbin element can be created just like any other element using
- * gst_element_factory_make(). The file/URI to play should be set via the "uri"
+ * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin2:uri
  * property. This must be an absolute URI, relative file paths are not allowed.
  * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
- * </para>
- * <para>
+ *
  * Playbin is a #GstPipeline. It will notify the application of everything
  * that's happening (errors, end of stream, tags found, state changes, etc.)
  * by posting messages on its #GstBus. The application needs to watch the
  * bus.
- * </para>
- * <para>
+ *
  * Playback can be initiated by setting the element to PLAYING state using
  * gst_element_set_state(). Note that the state change will take place in
  * the background in a separate thread, when the function returns playback
  * is probably not happening yet and any errors might not have occured yet.
  * Applications using playbin should ideally be written to deal with things
  * completely asynchroneous.
- * </para>
- * <para>
+ *
  * When playback has finished (an EOS message has been received on the bus)
  * or an error has occured (an ERROR message has been received on the bus) or
  * the user wants to play a different track, playbin should be set back to
- * READY or NULL state, then the "uri" property should be set to the new
- * location and then playbin be set to PLAYING state again.
- * </para>
- * <para>
+ * READY or NULL state, then the #GstPlayBin2:uri property should be set to the 
+ * new location and then playbin be set to PLAYING state again.
+ *
  * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
  * on the playbin element. Again, the seek will not be executed
  * instantaneously, but will be done in a background thread. When the seek
@@ -91,35 +90,33 @@
  * may wait for the seek to finish (or fail) using gst_element_get_state() with
  * -1 as the timeout, but this will block the user interface and is not
  * recommended at all.
- * </para>
- * <para>
+ *
  * Applications may query the current position and duration of the stream
  * via gst_element_query_position() and gst_element_query_duration() and
  * setting the format passed to GST_FORMAT_TIME. If the query was successful,
  * the duration or position will have been returned in units of nanoseconds.
  * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Advanced Usage: specifying the audio and video sink</title>
  * <para>
  * By default, if no audio sink or video sink has been specified via the
- * "audio-sink" or "video-sink" property, playbin will use the autoaudiosink
+ * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property, playbin will use the autoaudiosink
  * and autovideosink elements to find the first-best available output method.
  * This should work in most cases, but is not always desirable. Often either
  * the user or application might want to specify more explicitly what to use
  * for audio and video output.
- * </para>
- * <para>
+ *
  * If the application wants more control over how audio or video should be
  * output, it may create the audio/video sink elements itself (for example
  * using gst_element_factory_make()) and provide them to playbin using the
- * "audio-sink" or "video-sink" property.
- * </para>
- * <para>
+ * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property.
+ *
  * GNOME-based applications, for example, will usually want to create
  * gconfaudiosink and gconfvideosink elements and make playbin use those,
  * so that output happens to whatever the user has configured in the GNOME
- * Multimedia System Selector confinguration dialog.
- * </para>
- * <para>
+ * Multimedia System Selector configuration dialog.
+ *
  * The sink elements do not necessarily need to be ready-made sinks. It is
  * possible to create container elements that look like a sink to playbin,
  * but in reality contain a number of custom elements linked together. This
@@ -128,41 +125,25 @@
  * it to the sink pad of the first element within the bin. This can be used
  * for a number of purposes, for example to force output to a particular
  * format or to modify or observe the data before it is output.
- * </para>
- * <para>
+ *
  * It is also possible to 'suppress' audio and/or video output by using
  * 'fakesink' elements (or capture it from there using the fakesink element's
  * "handoff" signal, which, nota bene, is fired from the streaming thread!).
  * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Retrieving Tags and Other Meta Data</title>
  * <para>
  * Most of the common meta data (artist, title, etc.) can be retrieved by
  * watching for TAG messages on the pipeline's bus (see above).
- * </para>
- * <para>
+ *
  * Other more specific meta information like width/height/framerate of video
  * streams or samplerate/number of channels of audio streams can be obtained
- * using the "stream-info" property, which will return a GList of stream info
- * objects, one for each stream. These are opaque objects that can only be
- * accessed via the standard GObject property interface, ie. g_object_get().
- * Each stream info object has the following properties:
- * <itemizedlist>
- * <listitem>"object" (GstObject) (the decoder source pad usually)</listitem>
- * <listitem>"type" (enum) (if this is an audio/video/subtitle stream)</listitem>
- * <listitem>"decoder" (string) (name of decoder used to decode this stream)</listitem>
- * <listitem>"mute" (boolean) (to mute or unmute this stream)</listitem>
- * <listitem>"caps" (GstCaps) (caps of the decoded stream)</listitem>
- * <listitem>"language-code" (string) (ISO-639 language code for this stream, mostly used for audio/subtitle streams)</listitem>
- * <listitem>"codec" (string) (format this stream was encoded in)</listitem>
- * </itemizedlist>
- * Stream information from the stream-info properties is best queried once
- * playbin has changed into PAUSED or PLAYING state (which can be detected
- * via a state-changed message on the bus where old_state=READY and
- * new_state=PAUSED), since before that the list might not be complete yet or
- * not contain all available information (like language-codes).
+ * from the negotiated caps on the sink pads of the sinks.
  * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Buffering</title>
- * <para>
  * Playbin handles buffering automatically for the most part, but applications
  * need to handle parts of the buffering process as well. Whenever playbin is
  * buffering, it will post BUFFERING messages on the bus with a percentage
@@ -171,9 +152,7 @@
  * They may also want to convey the buffering progress to the user in some
  * way. Here is how to extract the percentage information from the message
  * (requires GStreamer >= 0.10.11):
- * </para>
- * <para>
- * <programlisting>
+ * |[
  * switch (GST_MESSAGE_TYPE (msg)) {
  *   case GST_MESSAGE_BUFFERING: {
  *     gint percent = 0;
@@ -183,21 +162,21 @@
  *   }
  *   ...
  * }
- * </programlisting>
+ * ]|
  * Note that applications should keep/set the pipeline in the PAUSED state when
  * a BUFFERING message is received with a buffer percent value < 100 and set
  * the pipeline back to PLAYING state when a BUFFERING message with a value
  * of 100 percent is received (if PLAYING is the desired state, that is).
- * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Embedding the video window in your application</title>
- * <para>
  * By default, playbin (or rather the video sinks used) will create their own
  * window. Applications will usually want to force output to a window of their
- * own, however. This can be done using the GstXOverlay interface, which most
+ * own, however. This can be done using the #GstXOverlay interface, which most
  * video sinks implement. See the documentation there for more details.
- * </para>
+ * </refsect2>
+ * <refsect2>
  * <title>Specifying which CD/DVD device to use</title>
- * <para>
  * The device to use for CDs/DVDs needs to be set on the source element
  * playbin creates before it is opened. The only way to do this at the moment
  * is to connect to playbin's "notify::source" signal, which will be emitted
@@ -206,35 +185,34 @@
  * property and set it appropriately. In future ways might be added to specify
  * the device as part of the URI, but at the time of writing this is not
  * possible yet.
- * </para>
- * <title>Examples</title>
+ * </refsect2>
+ * <refsect2>
+ * <title>Handling redirects</title>
  * <para>
- * Here is a simple pipeline to play back a video or audio file:
- * <programlisting>
+ * Some elements may post 'redirect' messages on the bus to tell the
+ * application to open another location. These are element messages containing
+ * a structure named 'redirect' along with a 'new-location' field of string
+ * type. The new location may be a relative or an absolute URI. Examples
+ * for such redirects can be found in many quicktime movie trailers.
+ * </para>
+ * </refsect2>
+ * <refsect2>
+ * <title>Examples</title>
+ * |[
  * gst-launch -v playbin uri=file:///path/to/somefile.avi
- * </programlisting>
- * This will play back the given AVI video file, given that the video and
+ * ]| This will play back the given AVI video file, given that the video and
  * audio decoders required to decode the content are installed. Since no
  * special audio sink or video sink is supplied (not possible via gst-launch),
  * playbin will try to find a suitable audio and video sink automatically
  * using the autoaudiosink and autovideosink elements.
- * </para>
- * <para>
- * Here is a another pipeline to play track 4 of an audio CD:
- * <programlisting>
+ * |[
  * gst-launch -v playbin uri=cdda://4
- * </programlisting>
- * This will play back track 4 on an audio CD in your disc drive (assuming
+ * ]| This will play back track 4 on an audio CD in your disc drive (assuming
  * the drive is detected automatically by the plugin).
- * </para>
- * <para>
- * Here is a another pipeline to play title 1 of a DVD:
- * <programlisting>
+ * |[
  * gst-launch -v playbin uri=dvd://1
- * </programlisting>
- * This will play back title 1 of a DVD in your disc drive (assuming
+ * ]| This will play back title 1 of a DVD in your disc drive (assuming
  * the drive is detected automatically by the plugin).
- * </para>
  * </refsect2>
  */
 
@@ -252,13 +230,9 @@
 #include "gstplay-marshal.h"
 #include "gstplaysink.h"
 #include "gstfactorylists.h"
+#include "gstinputselector.h"
 #include "gstscreenshot.h"
-#include "gststreaminfo.h"
-#include "gststreamselector.h"
-
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
+
 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
 #define GST_CAT_DEFAULT gst_play_bin_debug
 
@@ -278,7 +252,7 @@
 /* has the info for a selector and provides the link to the sink */
 struct _GstSourceSelect
 {
-  const gchar *media;           /* the media type of the selector */
+  const gchar *media_list[3];   /* the media types for the selector */
   GstPlaySinkType type;         /* the sink pad type of the selector */
 
   GstElement *selector;         /* the selector */
@@ -287,12 +261,18 @@
   GstPad *sinkpad;              /* the sinkpad of the sink when the selector is linked */
 };
 
+#define GST_SOURCE_GROUP_GET_LOCK(group) (((GstSourceGroup*)(group))->lock)
+#define GST_SOURCE_GROUP_LOCK(group) (g_mutex_lock (GST_SOURCE_GROUP_GET_LOCK(group)))
+#define GST_SOURCE_GROUP_UNLOCK(group) (g_mutex_unlock (GST_SOURCE_GROUP_GET_LOCK(group)))
+
 /* a structure to hold the objects for decoding a uri and the subtitle uri
  */
 struct _GstSourceGroup
 {
   GstPlayBin *playbin;
 
+  GMutex *lock;
+
   gboolean valid;               /* the group has valid info to start playback */
   gboolean active;              /* the group is active */
 
@@ -301,41 +281,107 @@
   gchar *suburi;
   GValueArray *streaminfo;
   GstElement *source;
-  gchar *subencoding;           /* encoding to propagate to the subtitle elements */
 
   GPtrArray *video_channels;    /* links to selector pads */
   GPtrArray *audio_channels;    /* links to selector pads */
   GPtrArray *text_channels;     /* links to selector pads */
+  GPtrArray *subp_channels;     /* links to selector pads */
+
+  GstElement *audio_sink;       /* autoplugged audio and video sinks */
+  GstElement *video_sink;
 
   /* uridecodebins for uri and subtitle uri */
   GstElement *uridecodebin;
   GstElement *suburidecodebin;
+  gint pending;
+
+  gulong pad_added_id;
+  gulong pad_removed_id;
+  gulong no_more_pads_id;
+  gulong notify_source_id;
+  gulong drained_id;
+  gulong autoplug_factories_id;
+  gulong autoplug_select_id;
+
+  gulong sub_pad_added_id;
+  gulong sub_pad_removed_id;
+  gulong sub_no_more_pads_id;
 
   /* selectors for different streams */
   GstSourceSelect selector[GST_PLAY_SINK_TYPE_LAST];
 };
 
+#define GST_PLAY_BIN_GET_LOCK(bin) (((GstPlayBin*)(bin))->lock)
+#define GST_PLAY_BIN_LOCK(bin) (g_mutex_lock (GST_PLAY_BIN_GET_LOCK(bin)))
+#define GST_PLAY_BIN_UNLOCK(bin) (g_mutex_unlock (GST_PLAY_BIN_GET_LOCK(bin)))
+
+/* lock to protect dynamic callbacks, like no-more-pads */
+#define GST_PLAY_BIN_DYN_LOCK(bin)    g_mutex_lock ((bin)->dyn_lock)
+#define GST_PLAY_BIN_DYN_UNLOCK(bin)  g_mutex_unlock ((bin)->dyn_lock)
+
+/* lock for shutdown */
+#define GST_PLAY_BIN_SHUTDOWN_LOCK(bin,label)           \
+G_STMT_START {                                          \
+  if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown)))   \
+    goto label;                                         \
+  GST_PLAY_BIN_DYN_LOCK (bin);                          \
+  if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) { \
+    GST_PLAY_BIN_DYN_UNLOCK (bin);                      \
+    goto label;                                         \
+  }                                                     \
+} G_STMT_END
+
+/* unlock for shutdown */
+#define GST_PLAY_BIN_SHUTDOWN_UNLOCK(bin)         \
+  GST_PLAY_BIN_DYN_UNLOCK (bin);                  \
+
+/**
+ * GstPlayBin2:
+ *
+ * playbin element structure
+ */
 struct _GstPlayBin
 {
   GstPipeline parent;
 
+  GMutex *lock;                 /* to protect group switching */
+
   /* the groups, we use a double buffer to switch between current and next */
   GstSourceGroup groups[2];     /* array with group info */
   GstSourceGroup *curr_group;   /* pointer to the currently playing group */
   GstSourceGroup *next_group;   /* pointer to the next group */
 
-  gboolean about_to_finish;     /* the about-to-finish signal is emited */
-
   /* properties */
   guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
   gint current_video;           /* the currently selected stream */
   gint current_audio;           /* the currently selected stream */
   gint current_text;            /* the currently selected stream */
+  gchar *encoding;              /* subtitle encoding */
+
+  guint64 buffer_duration;      /* When buffering, the max buffer duration (ns) */
+  guint buffer_size;            /* When buffering, the max buffer size (bytes) */
 
   /* our play sink */
   GstPlaySink *playsink;
 
+  /* the last activated source */
+  GstElement *source;
+
+  /* lock protecting dynamic adding/removing */
+  GMutex *dyn_lock;
+  /* if we are shutting down or not */
+  gint shutdown;
+
   GValueArray *elements;        /* factories we can use for selecting elements */
+
+  gboolean have_selector;       /* set to FALSE when we fail to create an
+                                 * input-selector, so that we only post a
+                                 * warning once */
+
+  GstElement *audio_sink;       /* configured audio sink, or NULL      */
+  GstElement *video_sink;       /* configured video sink, or NULL      */
+  GstElement *subpic_sink;      /* configured subpicture sink, or NULL */
+  GstElement *text_sink;        /* configured text sink, or NULL       */
 };
 
 struct _GstPlayBinClass
@@ -351,6 +397,11 @@
   void (*audio_changed) (GstPlayBin * playbin);
   void (*text_changed) (GstPlayBin * playbin);
 
+  /* notify app that the tags of audio/video/text streams changed */
+  void (*video_tags_changed) (GstPlayBin * playbin, gint stream);
+  void (*audio_tags_changed) (GstPlayBin * playbin, gint stream);
+  void (*text_tags_changed) (GstPlayBin * playbin, gint stream);
+
   /* get audio/video/text tags for a stream */
   GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream);
   GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
@@ -358,6 +409,11 @@
 
   /* get the last video frame and convert it to the given caps */
   GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
+
+  /* get audio/video/text pad for a stream */
+  GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream);
+  GstPad *(*get_audio_pad) (GstPlayBin * playbin, gint stream);
+  GstPad *(*get_text_pad) (GstPlayBin * playbin, gint stream);
 };
 
 /* props */
@@ -376,11 +432,15 @@
 #define DEFAULT_AUDIO_SINK        NULL
 #define DEFAULT_VIDEO_SINK        NULL
 #define DEFAULT_VIS_PLUGIN        NULL
+#define DEFAULT_TEXT_SINK         NULL
+#define DEFAULT_SUBPIC_SINK       NULL
 #define DEFAULT_VOLUME            1.0
 #define DEFAULT_MUTE              FALSE
 #define DEFAULT_FRAME             NULL
 #define DEFAULT_FONT_DESC         NULL
 #define DEFAULT_CONNECTION_SPEED  0
+#define DEFAULT_BUFFER_DURATION   -1
+#define DEFAULT_BUFFER_SIZE       -1
 
 enum
 {
@@ -399,23 +459,35 @@
   PROP_AUDIO_SINK,
   PROP_VIDEO_SINK,
   PROP_VIS_PLUGIN,
+  PROP_TEXT_SINK,
+  PROP_SUBPIC_SINK,
   PROP_VOLUME,
   PROP_MUTE,
   PROP_FRAME,
   PROP_FONT_DESC,
-  PROP_CONNECTION_SPEED
+  PROP_CONNECTION_SPEED,
+  PROP_BUFFER_SIZE,
+  PROP_BUFFER_DURATION,
+  PROP_LAST
 };
 
 /* signals */
 enum
 {
   SIGNAL_ABOUT_TO_FINISH,
+  SIGNAL_CONVERT_FRAME,
   SIGNAL_VIDEO_CHANGED,
   SIGNAL_AUDIO_CHANGED,
   SIGNAL_TEXT_CHANGED,
+  SIGNAL_VIDEO_TAGS_CHANGED,
+  SIGNAL_AUDIO_TAGS_CHANGED,
+  SIGNAL_TEXT_TAGS_CHANGED,
   SIGNAL_GET_VIDEO_TAGS,
   SIGNAL_GET_AUDIO_TAGS,
   SIGNAL_GET_TEXT_TAGS,
+  SIGNAL_GET_VIDEO_PAD,
+  SIGNAL_GET_AUDIO_PAD,
+  SIGNAL_GET_TEXT_PAD,
   LAST_SIGNAL
 };
 
@@ -443,7 +515,11 @@
 static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
     GstCaps * caps);
 
-static gboolean setup_next_source (GstPlayBin * playbin);
+static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream);
+static GstPad *gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream);
+static GstPad *gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream);
+
+static gboolean setup_next_source (GstPlayBin * playbin, GstState target);
 
 static GstElementClass *parent_class;
 
@@ -532,49 +608,50 @@
   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_finalize);
 
   /**
-   * GstPlayBin:uri
+   * GstPlayBin2:uri
    *
    * Set the next URI that playbin will play. This property can be set from the
    * about-to-finish signal to queue the next media file.
    */
   g_object_class_install_property (gobject_klass, PROP_URI,
       g_param_spec_string ("uri", "URI", "URI of the media to play",
-          NULL, G_PARAM_READWRITE));
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstPlayBin:suburi
+   * GstPlayBin2:suburi
    *
    * Set the next subtitle URI that playbin will play. This property can be
    * set from the about-to-finish signal to queue the next subtitle media file.
    */
   g_object_class_install_property (gobject_klass, PROP_SUBURI,
       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
-          NULL, G_PARAM_READWRITE));
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, PROP_SOURCE,
       g_param_spec_object ("source", "Source", "Source element",
-          GST_TYPE_ELEMENT, G_PARAM_READABLE));
-
+          GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstPlayBin:flags
+   * GstPlayBin2:flags
    *
    * Control the behaviour of playbin.
    */
   g_object_class_install_property (gobject_klass, PROP_FLAGS,
       g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
-          GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS, G_PARAM_READWRITE));
+          GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstPlayBin:n-video
+   * GstPlayBin2:n-video
    *
    * Get the total number of available video streams. 
    */
   g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
       g_param_spec_int ("n-video", "Number Video",
-          "Total number of video streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
+          "Total number of video streams", 0, G_MAXINT, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlayBin:current-video
+   * GstPlayBin2:current-video
    *
    * Get or set the currently playing video stream. By default the first video
    * stream with data is played.
@@ -582,17 +659,18 @@
   g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
       g_param_spec_int ("current-video", "Current Video",
           "Currently playing video stream (-1 = auto)",
-          -1, G_MAXINT, -1, G_PARAM_READWRITE));
+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlayBin:n-audio
+   * GstPlayBin2:n-audio
    *
    * Get the total number of available audio streams. 
    */
   g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
       g_param_spec_int ("n-audio", "Number Audio",
-          "Total number of audio streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
+          "Total number of audio streams", 0, G_MAXINT, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlayBin:current-audio
+   * GstPlayBin2:current-audio
    *
    * Get or set the currently playing audio stream. By default the first audio
    * stream with data is played.
@@ -600,17 +678,18 @@
   g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
       g_param_spec_int ("current-audio", "Current audio",
           "Currently playing audio stream (-1 = auto)",
-          -1, G_MAXINT, -1, G_PARAM_READWRITE));
+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlayBin:n-text
+   * GstPlayBin2:n-text
    *
    * Get the total number of available subtitle streams. 
    */
   g_object_class_install_property (gobject_klass, PROP_N_TEXT,
       g_param_spec_int ("n-text", "Number Text",
-          "Total number of text streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
+          "Total number of text streams", 0, G_MAXINT, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlayBin:current-text
+   * GstPlayBin2:current-text:
    *
    * Get or set the currently playing subtitle stream. By default the first
    * subtitle stream with data is played.
@@ -618,39 +697,49 @@
   g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
       g_param_spec_int ("current-text", "Current Text",
           "Currently playing text stream (-1 = auto)",
-          -1, G_MAXINT, -1, G_PARAM_READWRITE));
+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
           "be checked for an encoding to use. If that is not set either, "
-          "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
+          "ISO-8859-15 will be assumed.", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
       g_param_spec_object ("video-sink", "Video Sink",
           "the video output element to use (NULL = default sink)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK,
       g_param_spec_object ("audio-sink", "Audio Sink",
           "the audio output element to use (NULL = default sink)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN,
       g_param_spec_object ("vis-plugin", "Vis plugin",
-          "the visualization element to use (NULL = none)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+          "the visualization element to use (NULL = default)",
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_klass, PROP_TEXT_SINK,
+      g_param_spec_object ("text-sink", "Text plugin",
+          "the text output element to use (NULL = default textoverlay)",
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_klass, PROP_SUBPIC_SINK,
+      g_param_spec_object ("subpic-sink", "Subpicture plugin",
+          "the subpicture output element to use (NULL = default dvdspu)",
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, PROP_VOLUME,
-      g_param_spec_double ("volume", "Volume", "The audio volume",
-          0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE));
+      g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%",
+          0.0, VOLUME_MAX_DOUBLE, 1.0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, PROP_MUTE,
       g_param_spec_boolean ("mute", "Mute",
           "Mute the audio channel without changing the volume", FALSE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstPlayBin::frame
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2:frame:
+   * @playbin: a #GstPlayBin2
    *
    * Get the currently rendered or prerolled frame in the sink.
    * The #GstCaps on the buffer will describe the format of the buffer.
@@ -658,23 +747,37 @@
   g_object_class_install_property (gobject_klass, PROP_FRAME,
       gst_param_spec_mini_object ("frame", "Frame",
           "The last frame (NULL = no video available)",
-          GST_TYPE_BUFFER, G_PARAM_READABLE));
+          GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
       g_param_spec_string ("subtitle-font-desc",
           "Subtitle font description",
           "Pango font description of font "
-          "to be used for subtitle rendering", NULL, G_PARAM_WRITABLE));
+          "to be used for subtitle rendering", NULL,
+          G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
       g_param_spec_uint ("connection-speed", "Connection Speed",
           "Network connection speed in kbps (0 = unknown)",
-          0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
+          0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE,
+      g_param_spec_int ("buffer-size", "Buffer size (bytes)",
+          "Buffer size when buffering network streams",
+          -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_klass, PROP_BUFFER_DURATION,
+      g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
+          "Buffer duration when buffering network streams",
+          -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   /**
-   * GstPlayBin::about-to-finish:
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::about-to-finish
+   * @playbin: a #GstPlayBin2
    *
    * This signal is emitted when the current uri is about to finish. You can
-   * set the next-uri and next-suburi to make sure that playback continues.
+   * set the uri and suburi to make sure that playback continues.
    */
   gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
@@ -683,10 +786,10 @@
       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
 
   /**
-   * GstPlayBin::video-changed
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::video-changed
+   * @playbin: a #GstPlayBin2
    *
-   * This signal is emited whenever the number or order of the video
+   * This signal is emitted whenever the number or order of the video
    * streams has changed. The application will most likely want to select
    * a new video stream.
    */
@@ -696,10 +799,10 @@
       G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   /**
-   * GstPlayBin::audio-changed
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::audio-changed
+   * @playbin: a #GstPlayBin2
    *
-   * This signal is emited whenever the number or order of the audio
+   * This signal is emitted whenever the number or order of the audio
    * streams has changed. The application will most likely want to select
    * a new audio stream.
    */
@@ -709,10 +812,10 @@
       G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   /**
-   * GstPlayBin::text-changed
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::text-changed
+   * @playbin: a #GstPlayBin2
    *
-   * This signal is emited whenever the number or order of the text
+   * This signal is emitted whenever the number or order of the text
    * streams has changed. The application will most likely want to select
    * a new text stream.
    */
@@ -723,8 +826,56 @@
       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
 
   /**
-   * GstPlayBin::get-video-tags
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::video-tags-changed
+   * @playbin: a #GstPlayBin2
+   * @stream: stream index with changed tags
+   *
+   * This signal is emitted whenever the tags of a video stream have changed.
+   * The application will most likely want to get the new tags.
+   *
+   * Since: 0.10.24
+   */
+  gst_play_bin_signals[SIGNAL_VIDEO_TAGS_CHANGED] =
+      g_signal_new ("video-tags-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstPlayBinClass, video_tags_changed), NULL, NULL,
+      gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
+  /**
+   * GstPlayBin2::audio-tags-changed
+   * @playbin: a #GstPlayBin2
+   * @stream: stream index with changed tags
+   *
+   * This signal is emitted whenever the tags of an audio stream have changed.
+   * The application will most likely want to get the new tags.
+   *
+   * Since: 0.10.24
+   */
+  gst_play_bin_signals[SIGNAL_AUDIO_TAGS_CHANGED] =
+      g_signal_new ("audio-tags-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstPlayBinClass, audio_tags_changed), NULL, NULL,
+      gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
+  /**
+   * GstPlayBin2::text-tags-changed
+   * @playbin: a #GstPlayBin2
+   * @stream: stream index with changed tags
+   *
+   * This signal is emitted whenever the tags of a text stream have changed.
+   * The application will most likely want to get the new tags.
+   *
+   * Since: 0.10.24
+   */
+  gst_play_bin_signals[SIGNAL_TEXT_TAGS_CHANGED] =
+      g_signal_new ("text-tags-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstPlayBinClass, text_tags_changed), NULL, NULL,
+      gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
+  /**
+   * GstPlayBin2::get-video-tags
+   * @playbin: a #GstPlayBin2
    * @stream: a video stream number
    *
    * Action signal to retrieve the tags of a specific video stream number.
@@ -739,8 +890,8 @@
       G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   /**
-   * GstPlayBin::get-audio-tags
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::get-audio-tags
+   * @playbin: a #GstPlayBin2
    * @stream: an audio stream number
    *
    * Action signal to retrieve the tags of a specific audio stream number.
@@ -755,8 +906,8 @@
       G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   /**
-   * GstPlayBin::get-text-tags
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::get-text-tags
+   * @playbin: a #GstPlayBin2
    * @stream: a text stream number
    *
    * Action signal to retrieve the tags of a specific text stream number.
@@ -771,8 +922,8 @@
       G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   /**
-   * GstPlayBin::convert-frame
-   * @playbin: a #GstPlayBin
+   * GstPlayBin2::convert-frame
+   * @playbin: a #GstPlayBin2
    * @caps: the target format of the frame
    *
    * Action signal to retrieve the currently playing video frame in the format
@@ -785,18 +936,74 @@
    * %NULL is returned when no current buffer can be retrieved or when the
    * conversion failed.
    */
-  gst_play_bin_signals[SIGNAL_GET_TEXT_TAGS] =
+  gst_play_bin_signals[SIGNAL_CONVERT_FRAME] =
       g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
       G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
       gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
 
+  /**
+   * GstPlayBin2::get-video-pad
+   * @playbin: a #GstPlayBin2
+   * @stream: a video stream number
+   *
+   * Action signal to retrieve the stream-selector sinkpad for a specific 
+   * video stream.
+   * This pad can be used for notifications of caps changes, stream-specific
+   * queries, etc.
+   *
+   * Returns: a #GstPad, or NULL when the stream number does not exist.
+   */
+  gst_play_bin_signals[SIGNAL_GET_VIDEO_PAD] =
+      g_signal_new ("get-video-pad", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+      G_STRUCT_OFFSET (GstPlayBinClass, get_video_pad), NULL, NULL,
+      gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
+  /**
+   * GstPlayBin2::get-audio-pad
+   * @playbin: a #GstPlayBin2
+   * @stream: an audio stream number
+   *
+   * Action signal to retrieve the stream-selector sinkpad for a specific 
+   * audio stream.
+   * This pad can be used for notifications of caps changes, stream-specific
+   * queries, etc.
+   *
+   * Returns: a #GstPad, or NULL when the stream number does not exist.
+   */
+  gst_play_bin_signals[SIGNAL_GET_AUDIO_PAD] =
+      g_signal_new ("get-audio-pad", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+      G_STRUCT_OFFSET (GstPlayBinClass, get_audio_pad), NULL, NULL,
+      gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
+  /**
+   * GstPlayBin2::get-text-pad
+   * @playbin: a #GstPlayBin2
+   * @stream: a text stream number
+   *
+   * Action signal to retrieve the stream-selector sinkpad for a specific 
+   * text stream.
+   * This pad can be used for notifications of caps changes, stream-specific
+   * queries, etc.
+   *
+   * Returns: a #GstPad, or NULL when the stream number does not exist.
+   */
+  gst_play_bin_signals[SIGNAL_GET_TEXT_PAD] =
+      g_signal_new ("get-text-pad", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+      G_STRUCT_OFFSET (GstPlayBinClass, get_text_pad), NULL, NULL,
+      gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
+
   klass->get_video_tags = gst_play_bin_get_video_tags;
   klass->get_audio_tags = gst_play_bin_get_audio_tags;
   klass->get_text_tags = gst_play_bin_get_text_tags;
 
   klass->convert_frame = gst_play_bin_convert_frame;
 
+  klass->get_video_pad = gst_play_bin_get_video_pad;
+  klass->get_audio_pad = gst_play_bin_get_audio_pad;
+  klass->get_text_pad = gst_play_bin_get_text_pad;
+
   gst_element_class_set_details (gstelement_klass, &gst_play_bin_details);
 
   gstelement_klass->change_state =
@@ -813,23 +1020,50 @@
   group->video_channels = g_ptr_array_new ();
   group->audio_channels = g_ptr_array_new ();
   group->text_channels = g_ptr_array_new ();
-  /* init selectors */
+  group->subp_channels = g_ptr_array_new ();
+  group->lock = g_mutex_new ();
+  /* init selectors. The selector is found by finding the first prefix that
+   * matches the media. */
   group->playbin = playbin;
-  group->selector[0].media = "audio/x-raw-";
+  /* If you add any items to these lists, check that media_list[] is defined
+   * above to be large enough to hold MAX(items)+1, so as to accomodate a
+   * NULL terminator (set when the memory is zeroed on allocation) */
+  group->selector[0].media_list[0] = "audio/x-raw-";
   group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
   group->selector[0].channels = group->audio_channels;
-  group->selector[1].media = "audio/";
+  group->selector[1].media_list[0] = "audio/";
   group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
   group->selector[1].channels = group->audio_channels;
-  group->selector[2].media = "video/x-raw-";
+  group->selector[2].media_list[0] = "video/x-raw-";
   group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
   group->selector[2].channels = group->video_channels;
-  group->selector[3].media = "video/";
-  group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
-  group->selector[3].channels = group->video_channels;
-  group->selector[4].media = "text/";
-  group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
-  group->selector[4].channels = group->text_channels;
+  group->selector[3].media_list[0] = "video/x-dvd-subpicture";
+  group->selector[3].media_list[1] = "subpicture/x-pgs";
+  group->selector[3].type = GST_PLAY_SINK_TYPE_SUBPIC;
+  group->selector[3].channels = group->subp_channels;
+  group->selector[4].media_list[0] = "video/";
+  group->selector[4].type = GST_PLAY_SINK_TYPE_VIDEO;
+  group->selector[4].channels = group->video_channels;
+  group->selector[5].media_list[0] = "text/";
+  group->selector[5].type = GST_PLAY_SINK_TYPE_TEXT;
+  group->selector[5].channels = group->text_channels;
+}
+
+static void
+free_group (GstPlayBin * playbin, GstSourceGroup * group)
+{
+  g_free (group->uri);
+  g_ptr_array_free (group->video_channels, TRUE);
+  g_ptr_array_free (group->audio_channels, TRUE);
+  g_ptr_array_free (group->text_channels, TRUE);
+  g_ptr_array_free (group->subp_channels, TRUE);
+  g_mutex_free (group->lock);
+  if (group->audio_sink)
+    gst_object_unref (group->audio_sink);
+  group->audio_sink = NULL;
+  if (group->video_sink)
+    gst_object_unref (group->video_sink);
+  group->video_sink = NULL;
 }
 
 static void
@@ -837,6 +1071,12 @@
 {
   GstFactoryListType type;
 
+  playbin->lock = g_mutex_new ();
+  playbin->dyn_lock = g_mutex_new ();
+
+  /* assume we can create a selector */
+  playbin->have_selector = TRUE;
+
   /* init groups */
   playbin->curr_group = &playbin->groups[0];
   playbin->next_group = &playbin->groups[1];
@@ -853,9 +1093,14 @@
   gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
   gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
 
+  playbin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
+
   playbin->current_video = DEFAULT_CURRENT_VIDEO;
   playbin->current_audio = DEFAULT_CURRENT_AUDIO;
   playbin->current_text = DEFAULT_CURRENT_TEXT;
+
+  playbin->buffer_duration = DEFAULT_BUFFER_DURATION;
+  playbin->buffer_size = DEFAULT_BUFFER_SIZE;
 }
 
 static void
@@ -865,7 +1110,24 @@
 
   playbin = GST_PLAY_BIN (object);
 
+  free_group (playbin, &playbin->groups[0]);
+  free_group (playbin, &playbin->groups[1]);
+
+  if (playbin->source)
+    gst_object_unref (playbin->source);
+  if (playbin->video_sink)
+    gst_object_unref (playbin->video_sink);
+  if (playbin->audio_sink)
+    gst_object_unref (playbin->audio_sink);
+  if (playbin->text_sink)
+    gst_object_unref (playbin->text_sink);
+  if (playbin->subpic_sink)
+    gst_object_unref (playbin->subpic_sink);
+
   g_value_array_free (playbin->elements);
+  g_free (playbin->encoding);
+  g_mutex_free (playbin->lock);
+  g_mutex_free (playbin->dyn_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -880,17 +1142,18 @@
     return;
   }
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = playbin->next_group;
 
-  /* if we have no previous uri, or the new uri is different from the
-   * old one, replug */
+  GST_SOURCE_GROUP_LOCK (group);
+  /* store the uri in the next group we will play */
   g_free (group->uri);
   group->uri = g_strdup (uri);
   group->valid = TRUE;
-
-  GST_DEBUG ("setting new uri to %s", uri);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_SOURCE_GROUP_UNLOCK (group);
+
+  GST_DEBUG ("set new uri to %s", uri);
+  GST_PLAY_BIN_UNLOCK (playbin);
 }
 
 static void
@@ -898,24 +1161,38 @@
 {
   GstSourceGroup *group;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = playbin->next_group;
 
-  if ((!suburi && !group->suburi) ||
-      (suburi && group->suburi && !strcmp (group->suburi, suburi)))
-    goto done;
-
+  GST_SOURCE_GROUP_LOCK (group);
   g_free (group->suburi);
   group->suburi = g_strdup (suburi);
+  GST_SOURCE_GROUP_UNLOCK (group);
 
   GST_DEBUG ("setting new .sub uri to %s", suburi);
 
-done:
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
+}
+
+static void
+gst_play_bin_set_flags (GstPlayBin * playbin, GstPlayFlags flags)
+{
+  gst_play_sink_set_flags (playbin->playsink, flags);
+  gst_play_sink_reconfigure (playbin->playsink);
+}
+
+static GstPlayFlags
+gst_play_bin_get_flags (GstPlayBin * playbin)
+{
+  GstPlayFlags flags;
+
+  flags = gst_play_sink_get_flags (playbin->playsink);
+
+  return flags;
 }
 
 /* get the currently playing group or if nothing is playing, the next
- * group. Must be called with the LOCK. */
+ * group. Must be called with the PLAY_BIN_LOCK. */
 static GstSourceGroup *
 get_group (GstPlayBin * playbin)
 {
@@ -927,13 +1204,65 @@
   return result;
 }
 
+static GstPad *
+gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream)
+{
+  GstPad *sinkpad = NULL;
+  GstSourceGroup *group;
+
+  GST_PLAY_BIN_LOCK (playbin);
+  group = get_group (playbin);
+  if (stream < group->video_channels->len) {
+    sinkpad = g_ptr_array_index (group->video_channels, stream);
+    gst_object_ref (sinkpad);
+  }
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  return sinkpad;
+}
+
+static GstPad *
+gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream)
+{
+  GstPad *sinkpad = NULL;
+  GstSourceGroup *group;
+
+  GST_PLAY_BIN_LOCK (playbin);
+  group = get_group (playbin);
+  if (stream < group->audio_channels->len) {
+    sinkpad = g_ptr_array_index (group->audio_channels, stream);
+    gst_object_ref (sinkpad);
+  }
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  return sinkpad;
+}
+
+static GstPad *
+gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream)
+{
+  GstPad *sinkpad = NULL;
+  GstSourceGroup *group;
+
+  GST_PLAY_BIN_LOCK (playbin);
+  group = get_group (playbin);
+  if (stream < group->text_channels->len) {
+    sinkpad = g_ptr_array_index (group->text_channels, stream);
+    gst_object_ref (sinkpad);
+  }
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  return sinkpad;
+}
+
+
 static GstTagList *
 get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream)
 {
   GstTagList *result;
   GstPad *sinkpad;
 
-  if (!channels || channels->len < stream)
+  if (!channels || stream >= channels->len)
     return NULL;
 
   sinkpad = g_ptr_array_index (channels, stream);
@@ -948,10 +1277,10 @@
   GstTagList *result;
   GstSourceGroup *group;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = get_group (playbin);
   result = get_tags (playbin, group->video_channels, stream);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   return result;
 }
@@ -962,10 +1291,10 @@
   GstTagList *result;
   GstSourceGroup *group;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = get_group (playbin);
   result = get_tags (playbin, group->audio_channels, stream);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   return result;
 }
@@ -976,10 +1305,10 @@
   GstTagList *result;
   GstSourceGroup *group;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = get_group (playbin);
   result = get_tags (playbin, group->text_channels, stream);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   return result;
 }
@@ -1000,6 +1329,36 @@
   return result;
 }
 
+/* Returns current stream number, or -1 if none has been selected yet */
+static int
+get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
+{
+  /* Internal API cleanup would make this easier... */
+  int i;
+  GstPad *pad, *current;
+  GstObject *selector = NULL;
+  int ret = -1;
+
+  for (i = 0; i < channels->len; i++) {
+    pad = g_ptr_array_index (channels, i);
+    if ((selector = gst_pad_get_parent (pad))) {
+      g_object_get (selector, "active-pad", &current, NULL);
+      gst_object_unref (selector);
+
+      if (pad == current) {
+        gst_object_unref (current);
+        ret = i;
+        break;
+      }
+
+      if (current)
+        gst_object_unref (current);
+    }
+  }
+
+  return ret;
+}
+
 static gboolean
 gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
 {
@@ -1007,12 +1366,12 @@
   GPtrArray *channels;
   GstPad *sinkpad;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = get_group (playbin);
   if (!(channels = group->video_channels))
     goto no_channels;
 
-  if (stream == -1 || channels->len < stream) {
+  if (stream == -1 || channels->len <= stream) {
     sinkpad = NULL;
   } else {
     /* take channel from selected stream */
@@ -1021,7 +1380,7 @@
 
   if (sinkpad)
     gst_object_ref (sinkpad);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   if (sinkpad) {
     GstObject *selector;
@@ -1037,7 +1396,7 @@
 
 no_channels:
   {
-    GST_OBJECT_UNLOCK (playbin);
+    GST_PLAY_BIN_UNLOCK (playbin);
     return FALSE;
   }
 }
@@ -1049,12 +1408,12 @@
   GPtrArray *channels;
   GstPad *sinkpad;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = get_group (playbin);
   if (!(channels = group->audio_channels))
     goto no_channels;
 
-  if (stream == -1 || channels->len < stream) {
+  if (stream == -1 || channels->len <= stream) {
     sinkpad = NULL;
   } else {
     /* take channel from selected stream */
@@ -1063,7 +1422,7 @@
 
   if (sinkpad)
     gst_object_ref (sinkpad);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   if (sinkpad) {
     GstObject *selector;
@@ -1079,7 +1438,7 @@
 
 no_channels:
   {
-    GST_OBJECT_UNLOCK (playbin);
+    GST_PLAY_BIN_UNLOCK (playbin);
     return FALSE;
   }
 }
@@ -1091,12 +1450,12 @@
   GPtrArray *channels;
   GstPad *sinkpad;
 
-  GST_OBJECT_LOCK (playbin);
+  GST_PLAY_BIN_LOCK (playbin);
   group = get_group (playbin);
   if (!(channels = group->text_channels))
     goto no_channels;
 
-  if (stream == -1 || channels->len < stream) {
+  if (stream == -1 || channels->len <= stream) {
     sinkpad = NULL;
   } else {
     /* take channel from selected stream */
@@ -1105,7 +1464,7 @@
 
   if (sinkpad)
     gst_object_ref (sinkpad);
-  GST_OBJECT_UNLOCK (playbin);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   if (sinkpad) {
     GstObject *selector;
@@ -1121,12 +1480,56 @@
 
 no_channels:
   {
-    GST_OBJECT_UNLOCK (playbin);
+    GST_PLAY_BIN_UNLOCK (playbin);
     return FALSE;
   }
 }
 
 static void
+gst_play_bin_set_encoding (GstPlayBin * playbin, const gchar * encoding)
+{
+  GstElement *elem;
+
+  GST_PLAY_BIN_LOCK (playbin);
+  g_free (playbin->encoding);
+  playbin->encoding = g_strdup (encoding);
+
+  /* set subtitles on all current and next decodebins. */
+  if ((elem = playbin->groups[0].uridecodebin))
+    g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
+  if ((elem = playbin->groups[0].suburidecodebin))
+    g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
+  if ((elem = playbin->groups[1].uridecodebin))
+    g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
+  if ((elem = playbin->groups[1].suburidecodebin))
+    g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
+  GST_PLAY_BIN_UNLOCK (playbin);
+}
+
+static void
+gst_play_bin_set_sink (GstPlayBin * playbin, GstElement ** elem,
+    const gchar * dbg, GstElement * sink)
+{
+  GST_INFO_OBJECT (playbin, "Setting %s sink to %" GST_PTR_FORMAT, dbg, sink);
+
+  GST_PLAY_BIN_LOCK (playbin);
+  if (*elem != sink) {
+    GstElement *old;
+
+    old = *elem;
+    if (sink) {
+      gst_object_ref (sink);
+      gst_object_sink (sink);
+    }
+    *elem = sink;
+    if (old)
+      gst_object_unref (old);
+  }
+  GST_LOG_OBJECT (playbin, "%s sink now %" GST_PTR_FORMAT, dbg, *elem);
+  GST_PLAY_BIN_UNLOCK (playbin);
+}
+
+static void
 gst_play_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -1142,7 +1545,7 @@
       gst_play_bin_set_suburi (playbin, g_value_get_string (value));
       break;
     case PROP_FLAGS:
-      gst_play_sink_set_flags (playbin->playsink, g_value_get_flags (value));
+      gst_play_bin_set_flags (playbin, g_value_get_flags (value));
       break;
     case PROP_CURRENT_VIDEO:
       gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value));
@@ -1154,15 +1557,28 @@
       gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value));
       break;
     case PROP_SUBTITLE_ENCODING:
+      gst_play_bin_set_encoding (playbin, g_value_get_string (value));
       break;
     case PROP_VIDEO_SINK:
+      gst_play_bin_set_sink (playbin, &playbin->video_sink, "video",
+          g_value_get_object (value));
       break;
     case PROP_AUDIO_SINK:
+      gst_play_bin_set_sink (playbin, &playbin->audio_sink, "audio",
+          g_value_get_object (value));
       break;
     case PROP_VIS_PLUGIN:
       gst_play_sink_set_vis_plugin (playbin->playsink,
           g_value_get_object (value));
       break;
+    case PROP_TEXT_SINK:
+      gst_play_bin_set_sink (playbin, &playbin->text_sink, "text",
+          g_value_get_object (value));
+      break;
+    case PROP_SUBPIC_SINK:
+      gst_play_bin_set_sink (playbin, &playbin->subpic_sink, "subpicture",
+          g_value_get_object (value));
+      break;
     case PROP_VOLUME:
       gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
       break;
@@ -1170,11 +1586,19 @@
       gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value));
       break;
     case PROP_FONT_DESC:
+      gst_play_sink_set_font_desc (playbin->playsink,
+          g_value_get_string (value));
       break;
     case PROP_CONNECTION_SPEED:
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       playbin->connection_speed = g_value_get_uint (value) * 1000;
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
+      break;
+    case PROP_BUFFER_SIZE:
+      playbin->buffer_size = g_value_get_int (value);
+      break;
+    case PROP_BUFFER_DURATION:
+      playbin->buffer_duration = g_value_get_int64 (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1182,6 +1606,24 @@
   }
 }
 
+static GstElement *
+gst_play_bin_get_current_sink (GstPlayBin * playbin, GstElement ** elem,
+    const gchar * dbg, GstPlaySinkType type)
+{
+  GstElement *sink;
+
+  sink = gst_play_sink_get_sink (playbin->playsink, type);
+
+  GST_LOG_OBJECT (playbin, "play_sink_get_sink() returned %s sink %"
+      GST_PTR_FORMAT ", the originally set %s sink is %" GST_PTR_FORMAT,
+      dbg, sink, dbg, *elem);
+
+  if (sink == NULL)
+    sink = *elem;
+
+  return sink;
+}
+
 static void
 gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
@@ -1195,85 +1637,111 @@
     {
       GstSourceGroup *group;
 
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       group = get_group (playbin);
       g_value_set_string (value, group->uri);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     }
     case PROP_SUBURI:
     {
       GstSourceGroup *group;
 
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       group = get_group (playbin);
       g_value_set_string (value, group->suburi);
+      GST_PLAY_BIN_UNLOCK (playbin);
+      break;
+    }
+    case PROP_SOURCE:
+    {
+      GST_OBJECT_LOCK (playbin);
+      g_value_set_object (value, playbin->source);
       GST_OBJECT_UNLOCK (playbin);
       break;
     }
-    case PROP_SOURCE:
-      break;
     case PROP_FLAGS:
-      g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink));
+      g_value_set_flags (value, gst_play_bin_get_flags (playbin));
       break;
     case PROP_N_VIDEO:
     {
       GstSourceGroup *group;
       gint n_video;
 
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       group = get_group (playbin);
       n_video = (group->video_channels ? group->video_channels->len : 0);
       g_value_set_int (value, n_video);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     }
     case PROP_CURRENT_VIDEO:
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       g_value_set_int (value, playbin->current_video);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     case PROP_N_AUDIO:
     {
       GstSourceGroup *group;
       gint n_audio;
 
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       group = get_group (playbin);
       n_audio = (group->audio_channels ? group->audio_channels->len : 0);
       g_value_set_int (value, n_audio);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     }
     case PROP_CURRENT_AUDIO:
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       g_value_set_int (value, playbin->current_audio);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     case PROP_N_TEXT:
     {
       GstSourceGroup *group;
       gint n_text;
 
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       group = get_group (playbin);
       n_text = (group->text_channels ? group->text_channels->len : 0);
       g_value_set_int (value, n_text);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     }
     case PROP_CURRENT_TEXT:
-      GST_OBJECT_LOCK (playbin);
+      GST_PLAY_BIN_LOCK (playbin);
       g_value_set_int (value, playbin->current_text);
-      GST_OBJECT_UNLOCK (playbin);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     case PROP_SUBTITLE_ENCODING:
+      GST_PLAY_BIN_LOCK (playbin);
+      g_value_set_string (value, playbin->encoding);
+      GST_PLAY_BIN_UNLOCK (playbin);
       break;
     case PROP_VIDEO_SINK:
+      g_value_set_object (value,
+          gst_play_bin_get_current_sink (playbin, &playbin->video_sink,
+              "video", GST_PLAY_SINK_TYPE_VIDEO));
       break;
     case PROP_AUDIO_SINK:
+      g_value_set_object (value,
+          gst_play_bin_get_current_sink (playbin, &playbin->audio_sink,
+              "audio", GST_PLAY_SINK_TYPE_AUDIO));
       break;
     case PROP_VIS_PLUGIN:
+      g_value_set_object (value,
+          gst_play_sink_get_vis_plugin (playbin->playsink));
+      break;
+    case PROP_TEXT_SINK:
+      g_value_set_object (value,
+          gst_play_bin_get_current_sink (playbin, &playbin->text_sink,
+              "text", GST_PLAY_SINK_TYPE_TEXT));
+      break;
+    case PROP_SUBPIC_SINK:
+      g_value_set_object (value,
+          gst_play_bin_get_current_sink (playbin, &playbin->subpic_sink,
+              "subpicture", GST_PLAY_SINK_TYPE_SUBPIC));
       break;
     case PROP_VOLUME:
       g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink));
@@ -1285,10 +1753,22 @@
       gst_value_take_buffer (value, gst_play_bin_convert_frame (playbin, NULL));
       break;
     case PROP_FONT_DESC:
+      g_value_take_string (value,
+          gst_play_sink_get_font_desc (playbin->playsink));
       break;
     case PROP_CONNECTION_SPEED:
+      GST_PLAY_BIN_LOCK (playbin);
+      g_value_set_uint (value, playbin->connection_speed / 1000);
+      GST_PLAY_BIN_UNLOCK (playbin);
+      break;
+    case PROP_BUFFER_SIZE:
       GST_OBJECT_LOCK (playbin);
-      g_value_set_uint (value, playbin->connection_speed / 1000);
+      g_value_set_int (value, playbin->buffer_size);
+      GST_OBJECT_UNLOCK (playbin);
+      break;
+    case PROP_BUFFER_DURATION:
+      GST_OBJECT_LOCK (playbin);
+      g_value_set_int64 (value, playbin->buffer_duration);
       GST_OBJECT_UNLOCK (playbin);
       break;
     default:
@@ -1300,7 +1780,7 @@
 /* mime types we are not handling on purpose right now, don't post a
  * missing-plugin message for these */
 static const gchar *blacklisted_mimes[] = {
-  "video/x-dvd-subpicture", NULL
+  "video/x-dvd-subpicture", "subpicture/x-pgs", NULL
 };
 
 static void
@@ -1324,8 +1804,118 @@
   GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
 }
 
+static void
+selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
+    GstPlayBin * playbin)
+{
+  gchar *property;
+  GstSourceGroup *group;
+  GstSourceSelect *select = NULL;
+  int i;
+
+  GST_PLAY_BIN_LOCK (playbin);
+  group = get_group (playbin);
+
+  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
+    if (selector == G_OBJECT (group->selector[i].selector)) {
+      select = &group->selector[i];
+    }
+  }
+
+  /* We got a pad-change after our group got switched out; no need to notify */
+  if (!select) {
+    GST_PLAY_BIN_UNLOCK (playbin);
+    return;
+  }
+
+  switch (select->type) {
+    case GST_PLAY_SINK_TYPE_VIDEO:
+    case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+      property = "current-video";
+      playbin->current_video = get_current_stream_number (playbin,
+          group->video_channels);
+      break;
+    case GST_PLAY_SINK_TYPE_AUDIO:
+    case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+      property = "current-audio";
+      playbin->current_audio = get_current_stream_number (playbin,
+          group->audio_channels);
+      break;
+    case GST_PLAY_SINK_TYPE_TEXT:
+      property = "current-text";
+      playbin->current_text = get_current_stream_number (playbin,
+          group->text_channels);
+      break;
+    default:
+      property = NULL;
+  }
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  if (property)
+    g_object_notify (G_OBJECT (playbin), property);
+}
+
+static void
+selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
+{
+  /* no nothing */
+  GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked);
+}
+
+/* helper function to lookup stuff in lists */
+static gboolean
+array_has_value (const gchar * values[], const gchar * value)
+{
+  gint i;
+
+  for (i = 0; values[i]; i++) {
+    if (g_str_has_prefix (value, values[i]))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+typedef struct
+{
+  GstPlayBin *playbin;
+  gint stream_id;
+  GstPlaySinkType type;
+} NotifyTagsData;
+
+static void
+notify_tags_cb (GObject * object, GParamSpec * pspec, gpointer user_data)
+{
+  NotifyTagsData *ntdata = (NotifyTagsData *) user_data;
+  gint signal;
+
+  GST_DEBUG_OBJECT (ntdata->playbin, "Tags on pad %" GST_PTR_FORMAT
+      " with stream id %d and type %d have changed",
+      object, ntdata->stream_id, ntdata->type);
+
+  switch (ntdata->type) {
+    case GST_PLAY_SINK_TYPE_VIDEO:
+    case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+      signal = SIGNAL_VIDEO_TAGS_CHANGED;
+      break;
+    case GST_PLAY_SINK_TYPE_AUDIO:
+    case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+      signal = SIGNAL_AUDIO_TAGS_CHANGED;
+      break;
+    case GST_PLAY_SINK_TYPE_TEXT:
+      signal = SIGNAL_TEXT_TAGS_CHANGED;
+      break;
+    default:
+      signal = -1;
+      break;
+  }
+
+  if (signal >= 0)
+    g_signal_emit (G_OBJECT (ntdata->playbin), gst_play_bin_signals[signal], 0,
+        ntdata->stream_id);
+}
+
 /* this function is called when a new pad is added to decodebin. We check the
- * type of the pad and add it to the selecter element of the group. 
+ * type of the pad and add it to the selector element of the group. 
  */
 static void
 pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
@@ -1338,6 +1928,7 @@
   GstPadLinkReturn res;
   GstSourceSelect *select = NULL;
   gint i;
+  gboolean changed = FALSE;
 
   playbin = group->playbin;
 
@@ -1351,7 +1942,7 @@
 
   /* major type of the pad, this determines the selector to use */
   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
-    if (g_str_has_prefix (name, group->selector[i].media)) {
+    if (array_has_value (group->selector[i].media_list, name)) {
       select = &group->selector[i];
       break;
     }
@@ -1361,43 +1952,127 @@
   if (select == NULL)
     goto unknown_type;
 
-  if (select->selector == NULL) {
+  GST_SOURCE_GROUP_LOCK (group);
+  if (select->selector == NULL && playbin->have_selector) {
     /* no selector, create one */
     GST_DEBUG_OBJECT (playbin, "creating new selector");
-    select->selector = g_object_new (GST_TYPE_STREAM_SELECTOR, NULL);
-    if (select->selector == NULL)
-      goto no_selector;
-
-    GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
-    gst_bin_add (GST_BIN_CAST (playbin), select->selector);
-    gst_element_set_state (select->selector, GST_STATE_PAUSED);
-
-    /* save source pad */
-    select->srcpad = gst_element_get_pad (select->selector, "src");
+    select->selector = g_object_new (GST_TYPE_INPUT_SELECTOR, NULL);
+    /* the above can't fail, but we keep the error handling around for when
+     * the selector plugin has moved to -base or -good and we stop using an
+     * internal copy of input-selector */
+    if (select->selector == NULL) {
+      /* post the missing selector message only once */
+      playbin->have_selector = FALSE;
+      gst_element_post_message (GST_ELEMENT_CAST (playbin),
+          gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
+              "input-selector"));
+      GST_ELEMENT_WARNING (playbin, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "input-selector"), (NULL));
+    } else {
+      g_signal_connect (select->selector, "notify::active-pad",
+          G_CALLBACK (selector_active_pad_changed), playbin);
+
+      GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
+      gst_bin_add (GST_BIN_CAST (playbin), select->selector);
+      gst_element_set_state (select->selector, GST_STATE_PAUSED);
+    }
+  }
+
+  if (select->srcpad == NULL) {
+    if (select->selector) {
+      /* save source pad of the selector */
+      select->srcpad = gst_element_get_static_pad (select->selector, "src");
+    } else {
+      /* no selector, use the pad as the source pad then */
+      select->srcpad = gst_object_ref (pad);
+    }
+    /* block the selector srcpad. It's possible that multiple decodebins start
+     * pushing data into the selectors before we have a chance to collect all
+     * streams and connect the sinks, resulting in not-linked errors. After we
+     * configured the sinks we will unblock them all. */
+    gst_pad_set_blocked_async (select->srcpad, TRUE, selector_blocked, NULL);
   }
 
   /* get sinkpad for the new stream */
-  if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
-    GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
-        GST_DEBUG_PAD_NAME (sinkpad));
-
-    /* store the selector for the pad */
-    g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
-
-    /* store the pad in the array */
-    GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad);
-    g_ptr_array_add (select->channels, sinkpad);
-
-    res = gst_pad_link (pad, sinkpad);
-    if (GST_PAD_LINK_FAILED (res))
-      goto link_failed;
-
-    /* store selector pad so we can release it */
-    g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
+  if (select->selector) {
+    if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
+      gulong notify_tags_handler = 0;
+      NotifyTagsData *ntdata;
+
+      GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
+          GST_DEBUG_PAD_NAME (sinkpad));
+
+      /* store the selector for the pad */
+      g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
+
+      /* connect to the notify::tags signal for our
+       * own *-tags-changed signals
+       */
+      ntdata = g_new0 (NotifyTagsData, 1);
+      ntdata->playbin = playbin;
+      ntdata->stream_id = select->channels->len;
+      ntdata->type = select->type;
+
+      notify_tags_handler =
+          g_signal_connect_data (G_OBJECT (sinkpad), "notify::tags",
+          G_CALLBACK (notify_tags_cb), ntdata, (GClosureNotify) g_free,
+          (GConnectFlags) 0);
+      g_object_set_data (G_OBJECT (sinkpad), "playbin2.notify_tags_handler",
+          (gpointer) notify_tags_handler);
+
+      /* store the pad in the array */
+      GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad);
+      g_ptr_array_add (select->channels, sinkpad);
+
+      res = gst_pad_link (pad, sinkpad);
+      if (GST_PAD_LINK_FAILED (res))
+        goto link_failed;
+
+      /* store selector pad so we can release it */
+      g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
+
+      changed = TRUE;
+      GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
+          GST_DEBUG_PAD_NAME (pad), select->selector);
+    }
+  } else {
+    /* no selector, don't configure anything, we'll link the new pad directly to
+     * the sink. */
+    changed = FALSE;
+    sinkpad = NULL;
   }
-  GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
-      GST_DEBUG_PAD_NAME (pad), select->selector);
-
+  GST_SOURCE_GROUP_UNLOCK (group);
+
+  if (changed) {
+    int signal;
+    switch (select->type) {
+      case GST_PLAY_SINK_TYPE_VIDEO:
+      case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+        /* we want to return NOT_LINKED for unselected pads but only for audio
+         * and video pads because text pads might come from an external file. */
+        g_object_set (sinkpad, "always-ok", FALSE, NULL);
+        signal = SIGNAL_VIDEO_CHANGED;
+        break;
+      case GST_PLAY_SINK_TYPE_AUDIO:
+      case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+        g_object_set (sinkpad, "always-ok", FALSE, NULL);
+        signal = SIGNAL_AUDIO_CHANGED;
+        break;
+      case GST_PLAY_SINK_TYPE_TEXT:
+        signal = SIGNAL_TEXT_CHANGED;
+        break;
+      case GST_PLAY_SINK_TYPE_SUBPIC:
+      default:
+        signal = -1;
+    }
+
+    if (signal >= 0)
+      g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[signal], 0, NULL);
+  }
+
+done:
+  gst_caps_unref (caps);
   return;
 
   /* ERRORS */
@@ -1405,24 +2080,19 @@
   {
     GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",
         name, GST_DEBUG_PAD_NAME (pad));
-    return;
-  }
-no_selector:
-  {
-    GST_ERROR_OBJECT (playbin, "could not create selector for pad %s:%s",
-        GST_DEBUG_PAD_NAME (pad));
-    return;
+    goto done;
   }
 link_failed:
   {
     GST_ERROR_OBJECT (playbin,
         "failed to link pad %s:%s to selector, reason %d",
         GST_DEBUG_PAD_NAME (pad), res);
-    return;
+    GST_SOURCE_GROUP_UNLOCK (group);
+    goto done;
   }
 }
 
-/* called when a pad is removed form the uridecodebin. We unlink the pad from
+/* called when a pad is removed from the uridecodebin. We unlink the pad from
  * the selector. This will make the selector select a new pad. */
 static void
 pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
@@ -1437,11 +2107,21 @@
   GST_DEBUG_OBJECT (playbin,
       "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
 
+  GST_SOURCE_GROUP_LOCK (group);
   /* get the selector sinkpad */
   if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
     goto not_linked;
 
   if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) {
+    gulong notify_tags_handler;
+
+    notify_tags_handler =
+        (gulong) g_object_get_data (G_OBJECT (peer),
+        "playbin2.notify_tags_handler");
+    if (notify_tags_handler != 0)
+      g_signal_handler_disconnect (G_OBJECT (peer), notify_tags_handler);
+    g_object_set_data (G_OBJECT (peer), "playbin2.notify_tags_handler", NULL);
+
     /* remove the pad from the array */
     g_ptr_array_remove (select->channels, peer);
     GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer);
@@ -1453,14 +2133,18 @@
   /* get selector, this can be NULL when the element is removing the pads
    * because it's being disposed. */
   selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer));
-  if (!selector)
+  if (!selector) {
+    gst_object_unref (peer);
     goto no_selector;
+  }
 
   /* release the pad to the selector, this will make the selector choose a new
    * pad. */
   gst_element_release_request_pad (selector, peer);
+  gst_object_unref (peer);
 
   gst_object_unref (selector);
+  GST_SOURCE_GROUP_UNLOCK (group);
 
   return;
 
@@ -1468,11 +2152,13 @@
 not_linked:
   {
     GST_DEBUG_OBJECT (playbin, "pad not linked");
+    GST_SOURCE_GROUP_UNLOCK (group);
     return;
   }
 no_selector:
   {
     GST_DEBUG_OBJECT (playbin, "selector not found");
+    GST_SOURCE_GROUP_UNLOCK (group);
     return;
   }
 }
@@ -1492,46 +2178,137 @@
   GstPlayBin *playbin;
   GstPadLinkReturn res;
   gint i;
+  gboolean configure;
 
   playbin = group->playbin;
 
   GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
 
+  GST_PLAY_BIN_SHUTDOWN_LOCK (playbin, shutdown);
+
+  GST_SOURCE_GROUP_LOCK (group);
   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
     GstSourceSelect *select = &group->selector[i];
 
-    if (select->selector) {
+    /* check if the specific media type was detected and thus has a selector
+     * created for it. If there is the media type, get a sinkpad from the sink
+     * and link it. We only do this if we have not yet requested the sinkpad
+     * before. */
+    if (select->srcpad && select->sinkpad == NULL) {
+      GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
       select->sinkpad =
           gst_play_sink_request_pad (playbin->playsink, select->type);
       res = gst_pad_link (select->srcpad, select->sinkpad);
-      GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", select->media,
-          res);
+      GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
+          select->media_list[0], res);
+      if (res != GST_PAD_LINK_OK) {
+        GST_ELEMENT_ERROR (playbin, CORE, PAD,
+            ("Internal playbin error."),
+            ("Failed to link selector to sink. Error %d", res));
+      }
     }
   }
-  /* configure the modes now */
-  gst_play_sink_reconfigure (playbin->playsink);
-}
-
-/* send an EOS event to all of the selectors */
-static void
-perform_eos (GstPlayBin * playbin, GstSourceGroup * group)
-{
-  GstEvent *event;
-  gint i;
-
-  GST_DEBUG_OBJECT (playbin, "doing EOS in group %p", group);
-
-  event = gst_event_new_eos ();
-  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
-    GstSourceSelect *select = &group->selector[i];
-
-    if (select->selector) {
-      GST_DEBUG_OBJECT (playbin, "send EOS in selector %s", select->media);
-      gst_event_ref (event);
-      gst_pad_push_event (select->srcpad, event);
+  GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending,
+      group->pending - 1);
+
+  if (group->pending > 0)
+    group->pending--;
+
+  if (group->pending == 0) {
+    /* we are the last group to complete, we will configure the output and then
+     * signal the other waiters. */
+    GST_LOG_OBJECT (playbin, "last group complete");
+    configure = TRUE;
+  } else {
+    GST_LOG_OBJECT (playbin, "have more pending groups");
+    configure = FALSE;
+  }
+  GST_SOURCE_GROUP_UNLOCK (group);
+
+  if (configure) {
+    /* if we have custom sinks, configure them now */
+    GST_SOURCE_GROUP_LOCK (group);
+    if (group->audio_sink) {
+      GST_INFO_OBJECT (playbin, "setting custom audio sink %" GST_PTR_FORMAT,
+          group->audio_sink);
+      gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO,
+          group->audio_sink);
+    } else {
+      GST_INFO_OBJECT (playbin, "setting default audio sink %" GST_PTR_FORMAT,
+          playbin->audio_sink);
+      gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO,
+          playbin->audio_sink);
+    }
+    if (group->video_sink) {
+      GST_INFO_OBJECT (playbin, "setting custom video sink %" GST_PTR_FORMAT,
+          group->video_sink);
+      gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO,
+          group->video_sink);
+    } else {
+      GST_INFO_OBJECT (playbin, "setting default video sink %" GST_PTR_FORMAT,
+          playbin->video_sink);
+      gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO,
+          playbin->video_sink);
     }
+    gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_TEXT,
+        playbin->text_sink);
+    gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_SUBPIC,
+        playbin->subpic_sink);
+    GST_SOURCE_GROUP_UNLOCK (group);
+
+    GST_LOG_OBJECT (playbin, "reconfigure sink");
+    /* we configure the modes if we were the last decodebin to complete. */
+    gst_play_sink_reconfigure (playbin->playsink);
+
+    /* signal the other decodebins that they can continue now. */
+    GST_SOURCE_GROUP_LOCK (group);
+    /* unblock all selectors */
+    for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
+      GstSourceSelect *select = &group->selector[i];
+
+      if (select->srcpad) {
+        GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
+            select->srcpad);
+        gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
+            NULL);
+      }
+    }
+    GST_SOURCE_GROUP_UNLOCK (group);
   }
-  gst_event_unref (event);
+
+  GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin);
+
+  return;
+
+shutdown:
+  {
+    GST_DEBUG ("ignoring, we are shutting down");
+    /* Request a flushing pad from playsink that we then link to the selector.
+     * Then we unblock the selectors so that they stop with a WRONG_STATE
+     * instead of a NOT_LINKED error.
+     */
+    GST_SOURCE_GROUP_LOCK (group);
+    for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
+      GstSourceSelect *select = &group->selector[i];
+
+      if (select->srcpad) {
+        if (select->sinkpad == NULL) {
+          GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad");
+          select->sinkpad =
+              gst_play_sink_request_pad (playbin->playsink,
+              GST_PLAY_SINK_TYPE_FLUSHING);
+          res = gst_pad_link (select->srcpad, select->sinkpad);
+          GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res);
+        }
+        GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
+            select->srcpad);
+        gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
+            NULL);
+      }
+    }
+    GST_SOURCE_GROUP_UNLOCK (group);
+    return;
+  }
 }
 
 static void
@@ -1543,21 +2320,13 @@
 
   GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group);
 
-  /* mark use as sending out the about-to-finish signal. When the app sets a URI
-   * when this signal is emited, we're marking it as next-uri */
-  playbin->about_to_finish = TRUE;
-
   /* after this call, we should have a next group to activate or we EOS */
   g_signal_emit (G_OBJECT (playbin),
       gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
 
-  playbin->about_to_finish = FALSE;
-
-  /* now activate the next group. If the app did not set a next-uri, this will
+  /* now activate the next group. If the app did not set a uri, this will
    * fail and we can do EOS */
-  if (!setup_next_source (playbin)) {
-    perform_eos (playbin, group);
-  }
+  setup_next_source (playbin, GST_STATE_PAUSED);
 }
 
 /* Called when we must provide a list of factories to plug to @pad with @caps.
@@ -1587,8 +2356,8 @@
 
 /* We are asked to select an element. See if the next element to check
  * is a sink. If this is the case, we see if the sink works by setting it to
- * READY. If the sink works, we return -2 to make decodebin expose the raw pad
- * so that we can setup the mixers. */
+ * READY. If the sink works, we return SELECT_EXPOSE to make decodebin
+ * expose the raw pad so that we can setup the mixers. */
 static GstAutoplugSelectResult
 autoplug_select_cb (GstElement * decodebin, GstPad * pad,
     GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
@@ -1596,6 +2365,8 @@
   GstPlayBin *playbin;
   GstElement *element;
   const gchar *klass;
+  GstPlaySinkType type;
+  GstElement **sinkp;
 
   playbin = group->playbin;
 
@@ -1612,6 +2383,44 @@
   /* it's a sink, see if an instance of it actually works */
   GST_DEBUG_OBJECT (playbin, "we found a sink");
 
+  klass = gst_element_factory_get_klass (factory);
+
+  /* figure out the klass */
+  if (strstr (klass, "Audio")) {
+    GST_DEBUG_OBJECT (playbin, "we found an audio sink");
+    type = GST_PLAY_SINK_TYPE_AUDIO;
+    sinkp = &group->audio_sink;
+  } else if (strstr (klass, "Video")) {
+    GST_DEBUG_OBJECT (playbin, "we found a video sink");
+    type = GST_PLAY_SINK_TYPE_VIDEO;
+    sinkp = &group->video_sink;
+  } else {
+    /* unknown klass, skip this element */
+    GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
+    return GST_AUTOPLUG_SELECT_SKIP;
+  }
+
+  /* if we are asked to do visualisations and it's an audio sink, skip the
+   * element. We can only do visualisations with raw sinks */
+  if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_VIS) {
+    if (type == GST_PLAY_SINK_TYPE_AUDIO) {
+      GST_DEBUG_OBJECT (playbin, "skip audio sink because of vis");
+      return GST_AUTOPLUG_SELECT_SKIP;
+    }
+  }
+
+  /* now see if we already have a sink element */
+  GST_SOURCE_GROUP_LOCK (group);
+  if (*sinkp) {
+    GST_DEBUG_OBJECT (playbin, "we already have a pending sink, expose pad");
+    /* for now, just assume that we can link the pad to this same sink. FIXME,
+     * check that we can link this new pad to this sink as well. */
+    GST_SOURCE_GROUP_UNLOCK (group);
+    return GST_AUTOPLUG_SELECT_EXPOSE;
+  }
+  GST_DEBUG_OBJECT (playbin, "we have no pending sink, try to create one");
+  GST_SOURCE_GROUP_UNLOCK (group);
+
   if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
     GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
         gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
@@ -1629,19 +2438,24 @@
     return GST_AUTOPLUG_SELECT_SKIP;
   }
 
-  /* at this point, we have the sink working, configure it in playsink */
-  klass = gst_element_factory_get_klass (factory);
-
-  /* get klass to figure out if it's audio or video */
-  if (strstr (klass, "Audio")) {
-    GST_DEBUG_OBJECT (playbin, "configure audio sink");
-    gst_play_sink_set_audio_sink (playbin->playsink, element);
-  } else if (strstr (klass, "Video")) {
-    GST_DEBUG_OBJECT (playbin, "configure video sink");
-    gst_play_sink_set_video_sink (playbin->playsink, element);
+  /* remember the sink in the group now, the element is floating, we take
+   * ownership now */
+  GST_SOURCE_GROUP_LOCK (group);
+  if (*sinkp == NULL) {
+    /* store the sink in the group, we will configure it later when we
+     * reconfigure the sink */
+    GST_DEBUG_OBJECT (playbin, "remember sink");
+    gst_object_ref (element);
+    gst_object_sink (element);
+    *sinkp = element;
   } else {
-    GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
+    /* some other thread configured a sink while we were testing the sink, set
+     * the sink back to NULL and assume we can use the other sink */
+    GST_DEBUG_OBJECT (playbin, "another sink was found, expose pad");
+    gst_element_set_state (element, GST_STATE_NULL);
+    gst_object_unref (element);
   }
+  GST_SOURCE_GROUP_UNLOCK (group);
 
   /* tell decodebin to expose the pad because we are going to use this
    * sink */
@@ -1650,67 +2464,202 @@
   return GST_AUTOPLUG_SELECT_EXPOSE;
 }
 
+static void
+notify_source_cb (GstElement * uridecodebin, GParamSpec * pspec,
+    GstSourceGroup * group)
+{
+  GstPlayBin *playbin;
+  GstElement *source;
+
+  playbin = group->playbin;
+
+  g_object_get (group->uridecodebin, "source", &source, NULL);
+
+  GST_OBJECT_LOCK (playbin);
+  if (playbin->source)
+    gst_object_unref (playbin->source);
+  playbin->source = source;
+  GST_OBJECT_UNLOCK (playbin);
+
+  g_object_notify (G_OBJECT (playbin), "source");
+}
+
+/* must be called with the group lock */
 static gboolean
-activate_group (GstPlayBin * playbin, GstSourceGroup * group)
+group_set_locked_state_unlocked (GstPlayBin * playbin, GstSourceGroup * group,
+    gboolean locked)
+{
+  GST_DEBUG_OBJECT (playbin, "locked_state %d on group %p", locked, group);
+
+  if (group->uridecodebin)
+    gst_element_set_locked_state (group->uridecodebin, locked);
+  if (group->suburidecodebin)
+    gst_element_set_locked_state (group->suburidecodebin, locked);
+
+  return TRUE;
+}
+
+#define REMOVE_SIGNAL(obj,id)            \
+if (id) {                                \
+  g_signal_handler_disconnect (obj, id); \
+  id = 0;                                \
+}
+
+/* must be called with PLAY_BIN_LOCK */
+static gboolean
+activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target)
 {
   GstElement *uridecodebin;
+  GstElement *suburidecodebin = NULL;
 
   g_return_val_if_fail (group->valid, FALSE);
   g_return_val_if_fail (!group->active, FALSE);
 
+  GST_DEBUG_OBJECT (playbin, "activating group %p", group);
+
+  GST_SOURCE_GROUP_LOCK (group);
   if (group->uridecodebin) {
+    GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
+    REMOVE_SIGNAL (group->uridecodebin, group->pad_added_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->pad_removed_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->no_more_pads_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->drained_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id);
+    REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id);
     gst_element_set_state (group->uridecodebin, GST_STATE_NULL);
-    gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin);
-    group->uridecodebin = NULL;
+    uridecodebin = group->uridecodebin;
+  } else {
+    GST_DEBUG_OBJECT (playbin, "making new uridecodebin");
+    uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
+    if (!uridecodebin)
+      goto no_decodebin;
+    gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
+    group->uridecodebin = uridecodebin;
   }
 
-  uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
-  if (!uridecodebin)
-    goto no_decodebin;
-
   /* configure connection speed */
-  g_object_set (uridecodebin, "connection-speed", playbin->connection_speed,
-      NULL);
+  g_object_set (uridecodebin, "connection-speed",
+      playbin->connection_speed / 1000, NULL);
+  if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_DOWNLOAD)
+    g_object_set (uridecodebin, "download", TRUE, NULL);
+  else
+    g_object_set (uridecodebin, "download", FALSE, NULL);
+  /* configure subtitle encoding */
+  g_object_set (uridecodebin, "subtitle-encoding", playbin->encoding, NULL);
   /* configure uri */
   g_object_set (uridecodebin, "uri", group->uri, NULL);
+  g_object_set (uridecodebin, "buffer-duration", playbin->buffer_duration,
+      NULL);
+  g_object_set (uridecodebin, "buffer-size", playbin->buffer_size, NULL);
 
   /* connect pads and other things */
-  g_signal_connect (uridecodebin, "pad-added", G_CALLBACK (pad_added_cb),
-      group);
-  g_signal_connect (uridecodebin, "pad-removed", G_CALLBACK (pad_removed_cb),
-      group);
-  g_signal_connect (uridecodebin, "no-more-pads", G_CALLBACK (no_more_pads_cb),
-      group);
+  group->pad_added_id = g_signal_connect (uridecodebin, "pad-added",
+      G_CALLBACK (pad_added_cb), group);
+  group->pad_removed_id = g_signal_connect (uridecodebin, "pad-removed",
+      G_CALLBACK (pad_removed_cb), group);
+  group->no_more_pads_id = g_signal_connect (uridecodebin, "no-more-pads",
+      G_CALLBACK (no_more_pads_cb), group);
+  group->notify_source_id = g_signal_connect (uridecodebin, "notify::source",
+      G_CALLBACK (notify_source_cb), group);
+  /* we have 1 pending no-more-pads */
+  group->pending = 1;
+
   /* is called when the uridecodebin is out of data and we can switch to the
    * next uri */
-  g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb), group);
+  group->drained_id =
+      g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb),
+      group);
 
   /* will be called when a new media type is found. We return a list of decoders
    * including sinks for decodebin to try */
-  g_signal_connect (uridecodebin, "autoplug-factories",
+  group->autoplug_factories_id =
+      g_signal_connect (uridecodebin, "autoplug-factories",
       G_CALLBACK (autoplug_factories_cb), group);
-
-  g_signal_connect (uridecodebin, "autoplug-select",
+  group->autoplug_select_id = g_signal_connect (uridecodebin, "autoplug-select",
       G_CALLBACK (autoplug_select_cb), group);
 
-  /*  */
-  gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
-  group->uridecodebin = uridecodebin;
-
-  gst_element_set_state (uridecodebin, GST_STATE_PAUSED);
-
+  if (group->suburi) {
+    /* subtitles */
+    if (group->suburidecodebin) {
+      GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin");
+      REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
+      REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
+      REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
+      gst_element_set_state (group->suburidecodebin, GST_STATE_NULL);
+      suburidecodebin = group->suburidecodebin;
+    } else {
+      GST_DEBUG_OBJECT (playbin, "making new suburidecodebin");
+      suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
+      if (!suburidecodebin)
+        goto no_decodebin;
+
+      gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
+      group->suburidecodebin = suburidecodebin;
+    }
+
+    /* configure connection speed */
+    g_object_set (suburidecodebin, "connection-speed",
+        playbin->connection_speed, NULL);
+    /* configure subtitle encoding */
+    g_object_set (suburidecodebin, "subtitle-encoding", playbin->encoding,
+        NULL);
+    /* configure uri */
+    g_object_set (suburidecodebin, "uri", group->suburi, NULL);
+
+    /* connect pads and other things */
+    group->sub_pad_added_id = g_signal_connect (suburidecodebin, "pad-added",
+        G_CALLBACK (pad_added_cb), group);
+    group->sub_pad_removed_id = g_signal_connect (suburidecodebin,
+        "pad-removed", G_CALLBACK (pad_removed_cb), group);
+    group->sub_no_more_pads_id = g_signal_connect (suburidecodebin,
+        "no-more-pads", G_CALLBACK (no_more_pads_cb), group);
+
+    /* we have 2 pending no-more-pads */
+    group->pending = 2;
+  }
+
+  /* release the group lock before setting the state of the decodebins, they
+   * might fire signals in this thread that we need to handle with the
+   * group_lock taken. */
+  GST_SOURCE_GROUP_UNLOCK (group);
+
+  if (suburidecodebin) {
+    if (gst_element_set_state (suburidecodebin,
+            target) == GST_STATE_CHANGE_FAILURE)
+      goto suburidecodebin_failure;
+  }
+  if (gst_element_set_state (uridecodebin, target) == GST_STATE_CHANGE_FAILURE)
+    goto uridecodebin_failure;
+
+  GST_SOURCE_GROUP_LOCK (group);
+  /* alow state changes of the playbin2 affect the group elements now */
+  group_set_locked_state_unlocked (playbin, group, FALSE);
   group->active = TRUE;
+  GST_SOURCE_GROUP_UNLOCK (group);
 
   return TRUE;
 
   /* ERRORS */
 no_decodebin:
   {
+    GST_SOURCE_GROUP_UNLOCK (group);
+    return FALSE;
+  }
+suburidecodebin_failure:
+  {
+    GST_DEBUG_OBJECT (playbin, "failed state change of subtitle uridecodebin");
+    return FALSE;
+  }
+uridecodebin_failure:
+  {
+    GST_DEBUG_OBJECT (playbin, "failed state change of uridecodebin");
     return FALSE;
   }
 }
 
-/* unlink a group of uridecodebins from the sink */
+/* unlink a group of uridecodebins from the sink.
+ * must be called with PLAY_BIN_LOCK */
 static gboolean
 deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
 {
@@ -1721,27 +2670,46 @@
 
   GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
 
+  GST_SOURCE_GROUP_LOCK (group);
+  group->active = FALSE;
   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
     GstSourceSelect *select = &group->selector[i];
 
-    if (!select->selector)
-      continue;
-
-    GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
-    gst_pad_unlink (select->srcpad, select->sinkpad);
-
-    /* release back */
-    gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
-    select->sinkpad = NULL;
-
-    gst_object_unref (select->srcpad);
-    select->srcpad = NULL;
-
-    gst_element_set_state (select->selector, GST_STATE_NULL);
-    gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
-    select->selector = NULL;
+    GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media_list[0]);
+
+    if (select->srcpad) {
+      if (select->sinkpad) {
+        GST_LOG_OBJECT (playbin, "unlinking from sink");
+        gst_pad_unlink (select->srcpad, select->sinkpad);
+
+        /* release back */
+        GST_LOG_OBJECT (playbin, "release sink pad");
+        gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
+        select->sinkpad = NULL;
+      }
+      gst_object_unref (select->srcpad);
+      select->srcpad = NULL;
+    }
+
+    if (select->selector) {
+      gst_element_set_state (select->selector, GST_STATE_NULL);
+      gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
+      select->selector = NULL;
+    }
   }
-  group->active = FALSE;
+  /* delete any custom sinks we might have */
+  if (group->audio_sink)
+    gst_object_unref (group->audio_sink);
+  group->audio_sink = NULL;
+  if (group->video_sink)
+    gst_object_unref (group->video_sink);
+  group->video_sink = NULL;
+  /* we still have the decodebins added to the playbin2 but we can't remove them
+   * yet or change their state because this function might be called from the
+   * streaming threads, instead block the state so that state changes on the
+   * playbin2 don't affect us anymore */
+  group_set_locked_state_unlocked (playbin, group, TRUE);
+  GST_SOURCE_GROUP_UNLOCK (group);
 
   return TRUE;
 }
@@ -1750,13 +2718,14 @@
  * configured. It swaps out the current_group and activates the valid 
  * next_group. */
 static gboolean
-setup_next_source (GstPlayBin * playbin)
+setup_next_source (GstPlayBin * playbin, GstState target)
 {
   GstSourceGroup *new_group, *old_group;
 
   GST_DEBUG_OBJECT (playbin, "setup sources");
 
   /* see if there is a next group */
+  GST_PLAY_BIN_LOCK (playbin);
   new_group = playbin->next_group;
   if (!new_group || !new_group->valid)
     goto no_next_group;
@@ -1770,12 +2739,13 @@
   }
 
   /* activate the new group */
-  if (!activate_group (playbin, new_group))
+  if (!activate_group (playbin, new_group, target))
     goto activate_failed;
 
   /* swap old and new */
   playbin->curr_group = new_group;
   playbin->next_group = old_group;
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   return TRUE;
 
@@ -1783,17 +2753,19 @@
 no_next_group:
   {
     GST_DEBUG_OBJECT (playbin, "no next group");
+    GST_PLAY_BIN_UNLOCK (playbin);
     return FALSE;
   }
 activate_failed:
   {
     GST_DEBUG_OBJECT (playbin, "activate failed");
+    GST_PLAY_BIN_UNLOCK (playbin);
     return FALSE;
   }
 }
 
 /* The group that is currently playing is copied again to the
- * next_group.
+ * next_group so that it will start playing the next time.
  */
 static gboolean
 save_current_group (GstPlayBin * playbin)
@@ -1803,6 +2775,7 @@
   GST_DEBUG_OBJECT (playbin, "save current group");
 
   /* see if there is a current group */
+  GST_PLAY_BIN_LOCK (playbin);
   curr_group = playbin->curr_group;
   if (curr_group && curr_group->valid) {
     /* unlink our pads with the sink */
@@ -1811,6 +2784,27 @@
   /* swap old and new */
   playbin->curr_group = playbin->next_group;
   playbin->next_group = curr_group;
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  return TRUE;
+}
+
+/* clear the locked state from all groups. This function is called before a
+ * state change to NULL is performed on them. */
+static gboolean
+groups_set_locked_state (GstPlayBin * playbin, gboolean locked)
+{
+  GST_DEBUG_OBJECT (playbin, "setting locked state to %d on all groups",
+      locked);
+
+  GST_PLAY_BIN_LOCK (playbin);
+  GST_SOURCE_GROUP_LOCK (playbin->curr_group);
+  group_set_locked_state_unlocked (playbin, playbin->curr_group, locked);
+  GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
+  GST_SOURCE_GROUP_LOCK (playbin->next_group);
+  group_set_locked_state_unlocked (playbin, playbin->next_group, locked);
+  GST_SOURCE_GROUP_UNLOCK (playbin->next_group);
+  GST_PLAY_BIN_UNLOCK (playbin);
 
   return TRUE;
 }
@@ -1825,16 +2819,48 @@
 
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      if (!setup_next_source (playbin))
+      GST_LOG_OBJECT (playbin, "clearing shutdown flag");
+      g_atomic_int_set (&playbin->shutdown, 0);
+      if (!setup_next_source (playbin, GST_STATE_READY))
         goto source_failed;
       break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      /* FIXME unlock our waiting groups */
+      GST_LOG_OBJECT (playbin, "setting shutdown flag");
+      g_atomic_int_set (&playbin->shutdown, 1);
+
+      /* wait for all callbacks to end by taking the lock.
+       * No dynamic (critical) new callbacks will
+       * be able to happen as we set the shutdown flag. */
+      GST_PLAY_BIN_DYN_LOCK (playbin);
+      GST_LOG_OBJECT (playbin, "dynamic lock taken, we can continue shutdown");
+      GST_PLAY_BIN_DYN_UNLOCK (playbin);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      /* unlock so that all groups go to NULL */
+      groups_set_locked_state (playbin, FALSE);
+      break;
     default:
       break;
   }
 
   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-  if (ret == GST_STATE_CHANGE_FAILURE)
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
+      GstSourceGroup *curr_group;
+
+      curr_group = playbin->curr_group;
+      if (curr_group && curr_group->valid) {
+        /* unlink our pads with the sink */
+        deactivate_group (playbin, curr_group);
+      }
+
+      /* Swap current and next group back */
+      playbin->curr_group = playbin->next_group;
+      playbin->next_group = curr_group;
+    }
     return ret;
+  }
 
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
@@ -1845,6 +2871,11 @@
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       save_current_group (playbin);
       break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      /* make sure the groups don't perform a state change anymore until we
+       * enable them again */
+      groups_set_locked_state (playbin, TRUE);
+      break;
     default:
       break;
   }
@@ -1867,6 +2898,9 @@
 {
   GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin");
 
+  g_type_class_ref (gst_input_selector_get_type ());
+  g_type_class_ref (gst_selector_pad_get_type ());
+
   return gst_element_register (plugin, "playbin2", GST_RANK_NONE,
       GST_TYPE_PLAY_BIN);
 }
--- a/gst_plugins_base/gst/playback/gstplaysink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplaysink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,32 +29,33 @@
 
 #include "gstplaysink.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
 GST_DEBUG_CATEGORY_STATIC (gst_play_sink_debug);
 #define GST_CAT_DEFAULT gst_play_sink_debug
 
 #define VOLUME_MAX_DOUBLE 10.0
 
+#define GST_PLAY_CHAIN(c) ((GstPlayChain *)(c))
+
 /* holds the common data fields for the audio and video pipelines. We keep them
  * in a structure to more easily have all the info available. */
 typedef struct
 {
   GstPlaySink *playsink;
-  GstPad *sinkpad;
   GstElement *bin;
   gboolean added;
   gboolean activated;
+  gboolean raw;
 } GstPlayChain;
 
 typedef struct
 {
   GstPlayChain chain;
+  GstPad *sinkpad;
   GstElement *queue;
   GstElement *conv;
   GstElement *resample;
   GstElement *volume;           /* element with the volume property */
+  gboolean sink_volume;         /* if the volume was provided by the sink */
   GstElement *mute;             /* element with the mute property */
   GstElement *sink;
 } GstPlayAudioChain;
@@ -62,6 +63,7 @@
 typedef struct
 {
   GstPlayChain chain;
+  GstPad *sinkpad;
   GstElement *queue;
   GstElement *conv;
   GstElement *scale;
@@ -72,6 +74,7 @@
 typedef struct
 {
   GstPlayChain chain;
+  GstPad *sinkpad;
   GstElement *queue;
   GstElement *conv;
   GstElement *resample;
@@ -83,6 +86,33 @@
                                  * chain */
 } GstPlayVisChain;
 
+typedef struct
+{
+  GstPlayChain chain;
+  GstPad *sinkpad;
+  GstElement *conv;
+  GstElement *overlay;
+  GstPad *videosinkpad;
+  GstPad *textsinkpad;
+  GstPad *srcpad;               /* outgoing srcpad, used to connect to the next
+                                 * chain */
+  GstElement *sink;             /* custom sink to receive subtitle buffers */
+} GstPlayTextChain;
+
+typedef struct
+{
+  GstPlayChain chain;
+  GstPad *sinkpad;
+  GstElement *queue;
+  GstElement *conv;
+  GstElement *overlay;
+  GstPad *videosinkpad;
+  GstPad *subpsinkpad;
+  GstPad *srcpad;               /* outgoing srcpad, used to connect to the next
+                                 * chain */
+  GstElement *sink;             /* custom sink to receive subpicture buffers */
+} GstPlaySubpChain;
+
 #define GST_PLAY_SINK_GET_LOCK(playsink) (((GstPlaySink *)playsink)->lock)
 #define GST_PLAY_SINK_LOCK(playsink)     g_mutex_lock (GST_PLAY_SINK_GET_LOCK (playsink))
 #define GST_PLAY_SINK_UNLOCK(playsink)   g_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink))
@@ -93,35 +123,47 @@
 
   GMutex *lock;
 
+  gboolean async_pending;
+  gboolean need_async_start;
+
   GstPlayFlags flags;
 
-  GstPlayChain *audiochain;
-  GstPlayChain *videochain;
-  GstPlayChain *vischain;
+  /* chains */
+  GstPlayAudioChain *audiochain;
+  GstPlayVideoChain *videochain;
+  GstPlayVisChain *vischain;
+  GstPlayTextChain *textchain;
+  GstPlaySubpChain *subpchain;
 
+  /* audio */
   GstPad *audio_pad;
   gboolean audio_pad_raw;
+  /* audio tee */
   GstElement *audio_tee;
   GstPad *audio_tee_sink;
   GstPad *audio_tee_asrc;
   GstPad *audio_tee_vissrc;
-
+  /* video */
   GstPad *video_pad;
   gboolean video_pad_raw;
-
+  /* text */
   GstPad *text_pad;
+  /* subpictures */
+  GstPad *subp_pad;
 
   /* properties */
   GstElement *audio_sink;
   GstElement *video_sink;
   GstElement *visualisation;
+  GstElement *text_sink;
+  GstElement *subp_sink;
   gfloat volume;
   gboolean mute;
   gchar *font_desc;             /* font description */
   guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
-
-  /* internal elements */
-  GstElement *textoverlay_element;
+  gint count;
+  gboolean volume_changed;      /* volume/mute changed while no audiochain */
+  gboolean mute_changed;        /* ... has been reated yet */
 };
 
 struct _GstPlaySinkClass
@@ -134,12 +176,6 @@
 enum
 {
   PROP_0,
-  PROP_AUDIO_SINK,
-  PROP_VIDEO_SINK,
-  PROP_VIS_PLUGIN,
-  PROP_VOLUME,
-  PROP_FRAME,
-  PROP_FONT_DESC,
   PROP_LAST
 };
 
@@ -154,17 +190,12 @@
 static void gst_play_sink_dispose (GObject * object);
 static void gst_play_sink_finalize (GObject * object);
 
-static void gst_play_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * spec);
-static void gst_play_sink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * spec);
-
 static gboolean gst_play_sink_send_event (GstElement * element,
     GstEvent * event);
 static GstStateChangeReturn gst_play_sink_change_state (GstElement * element,
     GstStateChange transition);
 
-static GstElementClass *parent_class;
+static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message);
 
 /* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
 
@@ -173,36 +204,8 @@
     "Generic/Bin/Player",
     "Autoplug and play media from an uri",
     "Wim Taymans <wim.taymans@gmail.com>");
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_play_sink_get_type (void)
-{
-  static GType gst_play_sink_type = 0;
-
-  if (!gst_play_sink_type) {
-    static const GTypeInfo gst_play_sink_info = {
-      sizeof (GstPlaySinkClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_play_sink_class_init,
-      NULL,
-      NULL,
-      sizeof (GstPlaySink),
-      0,
-      (GInstanceInitFunc) gst_play_sink_init,
-      NULL
-    };
-
-    gst_play_sink_type = g_type_register_static (GST_TYPE_BIN,
-        "GstPlaySink", &gst_play_sink_info, 0);
-  }
-
-  return gst_play_sink_type;
-}
+G_DEFINE_TYPE (GstPlaySink, gst_play_sink, GST_TYPE_BIN);
 
 static void
 gst_play_sink_class_init (GstPlaySinkClass * klass)
@@ -215,45 +218,18 @@
   gstelement_klass = (GstElementClass *) klass;
   gstbin_klass = (GstBinClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_klass->set_property = gst_play_sink_set_property;
-  gobject_klass->get_property = gst_play_sink_get_property;
-
   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_sink_dispose);
   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_sink_finalize);
 
-  g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
-      g_param_spec_object ("video-sink", "Video Sink",
-          "the video output element to use (NULL = default sink)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK,
-      g_param_spec_object ("audio-sink", "Audio Sink",
-          "the audio output element to use (NULL = default sink)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN,
-      g_param_spec_object ("vis-plugin", "Vis plugin",
-          "the visualization element to use (NULL = none)",
-          GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_klass, PROP_VOLUME,
-      g_param_spec_double ("volume", "volume", "volume",
-          0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_klass, PROP_FRAME,
-      gst_param_spec_mini_object ("frame", "Frame",
-          "The last video frame (NULL = no video available)",
-          GST_TYPE_BUFFER, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
-      g_param_spec_string ("subtitle-font-desc",
-          "Subtitle font description",
-          "Pango font description of font "
-          "to be used for subtitle rendering", NULL, G_PARAM_WRITABLE));
-
   gst_element_class_set_details (gstelement_klass, &gst_play_sink_details);
 
   gstelement_klass->change_state =
       GST_DEBUG_FUNCPTR (gst_play_sink_change_state);
   gstelement_klass->send_event = GST_DEBUG_FUNCPTR (gst_play_sink_send_event);
 
+  gstbin_klass->handle_message =
+      GST_DEBUG_FUNCPTR (gst_play_sink_handle_message);
+
   GST_DEBUG_CATEGORY_INIT (gst_play_sink_debug, "playsink", 0, "play bin");
 }
 
@@ -264,12 +240,24 @@
   playsink->video_sink = NULL;
   playsink->audio_sink = NULL;
   playsink->visualisation = NULL;
-  playsink->textoverlay_element = NULL;
+  playsink->text_sink = NULL;
   playsink->volume = 1.0;
   playsink->font_desc = NULL;
   playsink->flags = GST_PLAY_FLAG_SOFT_VOLUME;
 
   playsink->lock = g_mutex_new ();
+  playsink->need_async_start = TRUE;
+  GST_OBJECT_FLAG_SET (playsink, GST_ELEMENT_IS_SINK);
+}
+
+static void
+free_chain (GstPlayChain * chain)
+{
+  if (chain) {
+    if (chain->bin)
+      gst_object_unref (chain->bin);
+    g_free (chain);
+  }
 }
 
 static void
@@ -294,14 +282,44 @@
     gst_object_unref (playsink->visualisation);
     playsink->visualisation = NULL;
   }
-  if (playsink->textoverlay_element != NULL) {
-    gst_object_unref (playsink->textoverlay_element);
-    playsink->textoverlay_element = NULL;
+  if (playsink->text_sink != NULL) {
+    gst_element_set_state (playsink->text_sink, GST_STATE_NULL);
+    gst_object_unref (playsink->text_sink);
+    playsink->text_sink = NULL;
   }
+
+  free_chain ((GstPlayChain *) playsink->videochain);
+  playsink->videochain = NULL;
+  free_chain ((GstPlayChain *) playsink->audiochain);
+  playsink->audiochain = NULL;
+  free_chain ((GstPlayChain *) playsink->vischain);
+  playsink->vischain = NULL;
+  free_chain ((GstPlayChain *) playsink->textchain);
+  playsink->textchain = NULL;
+
+  if (playsink->audio_tee_sink) {
+    gst_object_unref (playsink->audio_tee_sink);
+    playsink->audio_tee_sink = NULL;
+  }
+
+  if (playsink->audio_tee_vissrc) {
+    gst_element_release_request_pad (playsink->audio_tee,
+        playsink->audio_tee_vissrc);
+    gst_object_unref (playsink->audio_tee_vissrc);
+    playsink->audio_tee_vissrc = NULL;
+  }
+
+  if (playsink->audio_tee_asrc) {
+    gst_element_release_request_pad (playsink->audio_tee,
+        playsink->audio_tee_asrc);
+    gst_object_unref (playsink->audio_tee_asrc);
+    playsink->audio_tee_asrc = NULL;
+  }
+
   g_free (playsink->font_desc);
   playsink->font_desc = NULL;
 
-  G_OBJECT_CLASS (parent_class)->dispose (object);
+  G_OBJECT_CLASS (gst_play_sink_parent_class)->dispose (object);
 }
 
 static void
@@ -313,45 +331,108 @@
 
   g_mutex_free (playsink->lock);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gst_play_sink_parent_class)->finalize (object);
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
-gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink)
+gst_play_sink_set_sink (GstPlaySink * playsink, GstPlaySinkType type,
+    GstElement * sink)
 {
-  GST_OBJECT_LOCK (playsink);
-  if (playsink->video_sink)
-    gst_object_unref (playsink->video_sink);
+  GstElement **elem = NULL, *old = NULL;
+
+  GST_LOG ("Setting sink %" GST_PTR_FORMAT " as sink type %d", sink, type);
 
-  if (sink) {
-    gst_object_ref (sink);
-    gst_object_sink (sink);
+  GST_PLAY_SINK_LOCK (playsink);
+  switch (type) {
+    case GST_PLAY_SINK_TYPE_AUDIO:
+    case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+      elem = &playsink->audio_sink;
+      break;
+    case GST_PLAY_SINK_TYPE_VIDEO:
+    case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+      elem = &playsink->video_sink;
+      break;
+    case GST_PLAY_SINK_TYPE_TEXT:
+      elem = &playsink->text_sink;
+      break;
+    case GST_PLAY_SINK_TYPE_SUBPIC:
+      elem = &playsink->subp_sink;
+      break;
+    default:
+      break;
   }
-  playsink->video_sink = sink;
-  GST_OBJECT_UNLOCK (playsink);
+  if (elem) {
+    old = *elem;
+    if (sink)
+      gst_object_ref (sink);
+    *elem = sink;
+  }
+  GST_PLAY_SINK_UNLOCK (playsink);
+
+  if (old)
+    gst_object_unref (old);
 }
+
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
-void
-gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink)
+GstElement *
+gst_play_sink_get_sink (GstPlaySink * playsink, GstPlaySinkType type)
 {
-  GST_OBJECT_LOCK (playsink);
-  if (playsink->audio_sink)
-    gst_object_unref (playsink->audio_sink);
+  GstElement *result = NULL;
+  GstElement *elem = NULL, *chainp = NULL;
 
-  if (sink) {
-    gst_object_ref (sink);
-    gst_object_sink (sink);
+  GST_PLAY_SINK_LOCK (playsink);
+  switch (type) {
+    case GST_PLAY_SINK_TYPE_AUDIO:
+    {
+      GstPlayAudioChain *chain;
+      if ((chain = (GstPlayAudioChain *) playsink->audiochain))
+        chainp = chain->sink;
+      elem = playsink->audio_sink;
+      break;
+    }
+    case GST_PLAY_SINK_TYPE_VIDEO:
+    {
+      GstPlayVideoChain *chain;
+      if ((chain = (GstPlayVideoChain *) playsink->videochain))
+        chainp = chain->sink;
+      elem = playsink->video_sink;
+      break;
+    }
+    case GST_PLAY_SINK_TYPE_TEXT:
+    {
+      GstPlayTextChain *chain;
+      if ((chain = (GstPlayTextChain *) playsink->textchain))
+        chainp = chain->sink;
+      elem = playsink->text_sink;
+      break;
+    }
+    case GST_PLAY_SINK_TYPE_SUBPIC:
+    {
+      GstPlaySubpChain *chain;
+      if ((chain = (GstPlaySubpChain *) playsink->subpchain))
+        chainp = chain->sink;
+      elem = playsink->subp_sink;
+      break;
+    }
+    default:
+      break;
   }
-  playsink->audio_sink = sink;
-  GST_OBJECT_UNLOCK (playsink);
+  if (chainp) {
+    /* we have an active chain with a sink, get the sink */
+    result = gst_object_ref (chainp);
+  }
+  /* nothing found, return last configured sink */
+  if (result == NULL && elem)
+    result = gst_object_ref (elem);
+  GST_PLAY_SINK_UNLOCK (playsink);
+
+  return result;
 }
 
 static void
@@ -390,13 +471,13 @@
   gst_bin_remove (GST_BIN_CAST (chain->chain.bin), chain->vis);
 
   /* add new plugin and set state to playing */
-  chain->vis = gst_object_ref (playsink->visualisation);
+  chain->vis = playsink->visualisation;
   gst_bin_add (GST_BIN_CAST (chain->chain.bin), chain->vis);
   gst_element_set_state (chain->vis, GST_STATE_PLAYING);
 
   /* get pads */
-  chain->vissinkpad = gst_element_get_pad (chain->vis, "sink");
-  chain->vissrcpad = gst_element_get_pad (chain->vis, "src");
+  chain->vissinkpad = gst_element_get_static_pad (chain->vis, "sink");
+  chain->vissrcpad = gst_element_get_static_pad (chain->vis, "src");
 
   /* link pads */
   gst_pad_link (chain->blockpad, chain->vissinkpad);
@@ -419,11 +500,22 @@
 {
   GstPlayVisChain *chain;
 
+  /* setting NULL means creating the default vis plugin */
+  if (vis == NULL)
+    vis = gst_element_factory_make ("goom", "vis");
+
+  /* simply return if we don't have a vis plugin here */
+  if (vis == NULL)
+    return;
+
   GST_PLAY_SINK_LOCK (playsink);
   /* first store the new vis */
   if (playsink->visualisation)
     gst_object_unref (playsink->visualisation);
-  playsink->visualisation = gst_object_ref (vis);
+  /* take ownership */
+  gst_object_ref (vis);
+  gst_object_sink (vis);
+  playsink->visualisation = vis;
 
   /* now try to change the plugin in the running vis chain, if we have no chain,
    * we don't bother, any future vis chain will be created with the new vis
@@ -433,7 +525,10 @@
 
   /* block the pad, the next time the callback is called we can change the
    * visualisation. It's possible that this never happens or that the pad was
-   * already blocked. */
+   * already blocked. If the callback never happens, we don't have new data so
+   * we don't need the new vis plugin. If the pad was already blocked, the
+   * function returns FALSE but the previous pad block will do the right thing
+   * anyway. */
   GST_DEBUG_OBJECT (playsink, "blocking vis pad");
   gst_pad_set_blocked_async (chain->blockpad, TRUE, gst_play_sink_vis_blocked,
       playsink);
@@ -447,6 +542,30 @@
 #endif
 
 
+GstElement *
+gst_play_sink_get_vis_plugin (GstPlaySink * playsink)
+{
+  GstElement *result = NULL;
+  GstPlayVisChain *chain;
+
+  GST_PLAY_SINK_LOCK (playsink);
+  if ((chain = (GstPlayVisChain *) playsink->vischain)) {
+    /* we have an active chain, get the sink */
+    if (chain->vis)
+      result = gst_object_ref (chain->vis);
+  }
+  /* nothing found, return last configured sink */
+  if (result == NULL && playsink->visualisation)
+    result = gst_object_ref (playsink->visualisation);
+  GST_PLAY_SINK_UNLOCK (playsink);
+
+  return result;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
 void
 gst_play_sink_set_volume (GstPlaySink * playsink, gdouble volume)
 {
@@ -456,7 +575,15 @@
   playsink->volume = volume;
   chain = (GstPlayAudioChain *) playsink->audiochain;
   if (chain && chain->volume) {
-    g_object_set (chain->volume, "volume", volume, NULL);
+    GST_LOG_OBJECT (playsink, "elements: volume=%" GST_PTR_FORMAT ", mute=%"
+        GST_PTR_FORMAT "; new volume=%.03f, mute=%d", chain->volume,
+        chain->mute, volume, playsink->mute);
+    /* if there is a mute element or we are not muted, set the volume */
+    if (chain->mute || !playsink->mute)
+      g_object_set (chain->volume, "volume", volume, NULL);
+  } else {
+    GST_LOG_OBJECT (playsink, "no volume element");
+    playsink->volume_changed = TRUE;
   }
   GST_PLAY_SINK_UNLOCK (playsink);
 }
@@ -473,11 +600,12 @@
 
   GST_PLAY_SINK_LOCK (playsink);
   chain = (GstPlayAudioChain *) playsink->audiochain;
+  result = playsink->volume;
   if (chain && chain->volume) {
-    g_object_get (chain->volume, "volume", &result, NULL);
-    playsink->volume = result;
-  } else {
-    result = playsink->volume;
+    if (chain->mute || !playsink->mute) {
+      g_object_get (chain->volume, "volume", &result, NULL);
+      playsink->volume = result;
+    }
   }
   GST_PLAY_SINK_UNLOCK (playsink);
 
@@ -496,8 +624,18 @@
   GST_PLAY_SINK_LOCK (playsink);
   playsink->mute = mute;
   chain = (GstPlayAudioChain *) playsink->audiochain;
-  if (chain && chain->mute) {
-    g_object_set (chain->mute, "mute", mute, NULL);
+  if (chain) {
+    if (chain->mute) {
+      g_object_set (chain->mute, "mute", mute, NULL);
+    } else if (chain->volume) {
+      if (mute)
+        g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL);
+      else
+        g_object_set (chain->volume, "volume", (gdouble) playsink->volume,
+            NULL);
+    }
+  } else {
+    playsink->mute_changed = TRUE;
   }
   GST_PLAY_SINK_UNLOCK (playsink);
 }
@@ -526,80 +664,6 @@
 }
 
 static void
-gst_play_sink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstPlaySink *playsink;
-
-  playsink = GST_PLAY_SINK (object);
-
-  switch (prop_id) {
-    case PROP_VIDEO_SINK:
-      gst_play_sink_set_video_sink (playsink, g_value_get_object (value));
-      break;
-    case PROP_AUDIO_SINK:
-      gst_play_sink_set_audio_sink (playsink, g_value_get_object (value));
-      break;
-    case PROP_VIS_PLUGIN:
-      gst_play_sink_set_vis_plugin (playsink, g_value_get_object (value));
-      break;
-    case PROP_VOLUME:
-      gst_play_sink_set_volume (playsink, g_value_get_double (value));
-      break;
-    case PROP_FONT_DESC:
-      GST_OBJECT_LOCK (playsink);
-      g_free (playsink->font_desc);
-      playsink->font_desc = g_strdup (g_value_get_string (value));
-      if (playsink->textoverlay_element) {
-        g_object_set (G_OBJECT (playsink->textoverlay_element),
-            "font-desc", g_value_get_string (value), NULL);
-      }
-      GST_OBJECT_UNLOCK (playsink);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_play_sink_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
-{
-  GstPlaySink *playsink;
-
-  playsink = GST_PLAY_SINK (object);
-
-  switch (prop_id) {
-    case PROP_VIDEO_SINK:
-      GST_OBJECT_LOCK (playsink);
-      g_value_set_object (value, playsink->video_sink);
-      GST_OBJECT_UNLOCK (playsink);
-      break;
-    case PROP_AUDIO_SINK:
-      GST_OBJECT_LOCK (playsink);
-      g_value_set_object (value, playsink->audio_sink);
-      GST_OBJECT_UNLOCK (playsink);
-      break;
-    case PROP_VIS_PLUGIN:
-      GST_OBJECT_LOCK (playsink);
-      g_value_set_object (value, playsink->visualisation);
-      GST_OBJECT_UNLOCK (playsink);
-      break;
-    case PROP_VOLUME:
-      g_value_set_double (value, gst_play_sink_get_volume (playsink));
-      break;
-    case PROP_FRAME:
-    {
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
 post_missing_element_message (GstPlaySink * playsink, const gchar * name)
 {
   GstMessage *msg;
@@ -608,15 +672,6 @@
   gst_element_post_message (GST_ELEMENT_CAST (playsink), msg);
 }
 
-static void
-free_chain (GstPlayChain * chain)
-{
-  if (chain->bin)
-    gst_object_unref (chain->bin);
-  gst_object_unref (chain->playsink);
-  g_free (chain);
-}
-
 static gboolean
 add_chain (GstPlayChain * chain, gboolean add)
 {
@@ -636,11 +691,17 @@
 static gboolean
 activate_chain (GstPlayChain * chain, gboolean activate)
 {
+  GstState state;
+
   if (chain->activated == activate)
     return TRUE;
 
+  GST_OBJECT_LOCK (chain->playsink);
+  state = GST_STATE_TARGET (chain->playsink);
+  GST_OBJECT_UNLOCK (chain->playsink);
+
   if (activate)
-    gst_element_set_state (chain->bin, GST_STATE_PAUSED);
+    gst_element_set_state (chain->bin, state);
   else
     gst_element_set_state (chain->bin, GST_STATE_NULL);
 
@@ -687,6 +748,106 @@
   return result;
 }
 
+static gint
+find_property_sink (GstElement * element, const gchar * name)
+{
+  gint res;
+  gboolean is_sink;
+
+  GST_OBJECT_LOCK (element);
+  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
+  GST_OBJECT_UNLOCK (element);
+
+  if (is_sink &&
+      g_object_class_find_property (G_OBJECT_GET_CLASS (element), name)) {
+    res = 0;
+    GST_DEBUG_OBJECT (element, "found %s property on sink", name);
+  } else {
+    GST_DEBUG_OBJECT (element, "did not find %s property", name);
+    res = 1;
+    gst_object_unref (element);
+  }
+  return res;
+}
+
+/* find a sink in the hierarchy with a property named @name. This function does
+ * not increase the refcount of the returned object and thus remains valid as
+ * long as the bin is valid. */
+static GstElement *
+gst_play_sink_find_property_sinks (GstPlaySink * playsink, GstElement * obj,
+    const gchar * name)
+{
+  GstElement *result = NULL;
+  GstIterator *it;
+
+  if (g_object_class_find_property (G_OBJECT_GET_CLASS (obj), name)) {
+    result = obj;
+  } else if (GST_IS_BIN (obj)) {
+    it = gst_bin_iterate_recurse (GST_BIN_CAST (obj));
+    result = gst_iterator_find_custom (it,
+        (GCompareFunc) find_property_sink, (gpointer) name);
+    gst_iterator_free (it);
+    /* we don't need the extra ref */
+    if (result)
+      gst_object_unref (result);
+  }
+  return result;
+}
+
+static void
+do_async_start (GstPlaySink * playsink)
+{
+  GstMessage *message;
+
+  if (!playsink->need_async_start)
+    return;
+
+  playsink->async_pending = TRUE;
+
+  GST_INFO_OBJECT (playsink, "Sending async_start message");
+  message = gst_message_new_async_start (GST_OBJECT_CAST (playsink), FALSE);
+  GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (GST_BIN_CAST
+      (playsink), message);
+}
+
+static void
+do_async_done (GstPlaySink * playsink)
+{
+  GstMessage *message;
+
+  if (playsink->async_pending) {
+    GST_INFO_OBJECT (playsink, "Sending async_done message");
+    message = gst_message_new_async_done (GST_OBJECT_CAST (playsink));
+    GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (GST_BIN_CAST
+        (playsink), message);
+
+    playsink->async_pending = FALSE;
+  }
+
+  playsink->need_async_start = FALSE;
+}
+
+/* try to change the state of an element. This function returns the element when
+ * the state change could be performed. When this function returns NULL an error
+ * occured and the element is unreffed if @unref is TRUE. */
+static GstElement *
+try_element (GstPlaySink * playsink, GstElement * element, gboolean unref)
+{
+  GstStateChangeReturn ret;
+
+  if (element) {
+    ret = gst_element_set_state (element, GST_STATE_READY);
+    if (ret == GST_STATE_CHANGE_FAILURE) {
+      GST_DEBUG_OBJECT (playsink, "failed state change..");
+      gst_element_set_state (element, GST_STATE_NULL);
+      if (unref)
+        gst_object_unref (element);
+      element = NULL;
+    }
+  }
+  return element;
+}
+
 /* make the element (bin) that contains the elements needed to perform
  * video display. 
  *
@@ -700,37 +861,51 @@
  *  +------------------------------------------------------------+
  *           
  */
-static GstPlayChain *
-gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
+static GstPlayVideoChain *
+gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async,
+    gboolean queue)
 {
   GstPlayVideoChain *chain;
   GstBin *bin;
   GstPad *pad;
+  GstElement *head, *prev, *elem;
 
   chain = g_new0 (GstPlayVideoChain, 1);
-  chain->chain.playsink = gst_object_ref (playsink);
+  chain->chain.playsink = playsink;
+  chain->chain.raw = raw;
+
+  GST_DEBUG_OBJECT (playsink, "making video chain %p", chain);
 
   if (playsink->video_sink) {
-    chain->sink = playsink->video_sink;
-  } else {
-    chain->sink = gst_element_factory_make ("autovideosink", "videosink");
-    if (chain->sink == NULL) {
-      chain->sink = gst_element_factory_make ("xvimagesink", "videosink");
-    }
-    if (chain->sink == NULL)
-      goto no_sinks;
+    GST_DEBUG_OBJECT (playsink, "trying configured videosink");
+    chain->sink = try_element (playsink, playsink->video_sink, FALSE);
+  }
+  if (chain->sink == NULL) {
+    GST_DEBUG_OBJECT (playsink, "trying autovideosink");
+    elem = gst_element_factory_make ("autovideosink", "videosink");
+    chain->sink = try_element (playsink, elem, TRUE);
   }
+  /* FIXME: if DEFAULT_VIDEOSINK != "autovideosink" try this now */
+  if (chain->sink == NULL) {
+    GST_DEBUG_OBJECT (playsink, "trying xvimagesink");
+    elem = gst_element_factory_make ("xvimagesink", "videosink");
+    chain->sink = try_element (playsink, elem, TRUE);
+  }
+  if (chain->sink == NULL)
+    goto no_sinks;
 
   /* if we can disable async behaviour of the sink, we can avoid adding a
-   * queue for the audio chain. We can't use the deep property here because the
-   * sink might change it's internal sink element later. */
-  if (g_object_class_find_property (G_OBJECT_GET_CLASS (chain->sink), "async")) {
-    GST_DEBUG_OBJECT (playsink, "setting async property to %d on video sink",
-        async);
-    g_object_set (chain->sink, "async", async, NULL);
+   * queue for the audio chain. */
+  elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "async");
+  if (elem) {
+    GST_DEBUG_OBJECT (playsink, "setting async property to %d on element %s",
+        async, GST_ELEMENT_NAME (elem));
+    g_object_set (elem, "async", async, NULL);
     chain->async = async;
-  } else
+  } else {
+    GST_DEBUG_OBJECT (playsink, "no async property on the sink");
     chain->async = TRUE;
+  }
 
   /* create a bin to hold objects, as we create them we add them to this bin so
    * that when something goes wrong we only need to unref the bin */
@@ -740,74 +915,86 @@
   gst_object_sink (bin);
   gst_bin_add (bin, chain->sink);
 
-  if (raw) {
-    chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
-    if (chain->conv == NULL)
-      goto no_colorspace;
-    gst_bin_add (bin, chain->conv);
-
-    chain->scale = gst_element_factory_make ("videoscale", "vscale");
-    if (chain->scale == NULL)
-      goto no_videoscale;
-    gst_bin_add (bin, chain->scale);
+  if (queue) {
+    /* decouple decoder from sink, this improves playback quite a lot since the
+     * decoder can continue while the sink blocks for synchronisation. We don't
+     * need a lot of buffers as this consumes a lot of memory and we don't want
+     * too little because else we would be context switching too quickly. */
+    chain->queue = gst_element_factory_make ("queue", "vqueue");
+    g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3,
+        "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
+    gst_bin_add (bin, chain->queue);
+    head = prev = chain->queue;
+  } else {
+    head = chain->sink;
+    prev = NULL;
   }
 
-  /* decouple decoder from sink, this improves playback quite a lot since the
-   * decoder can continue while the sink blocks for synchronisation. We don't
-   * need a lot of buffers as this consumes a lot of memory and we don't want
-   * too little because else we would be context switching too quickly. */
-  chain->queue = gst_element_factory_make ("queue", "vqueue");
-  g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3,
-      "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
-  gst_bin_add (bin, chain->queue);
+  if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) {
+    GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace");
+    chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
+    if (chain->conv == NULL) {
+      post_missing_element_message (playsink, "ffmpegcolorspace");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "ffmpegcolorspace"), ("video rendering might fail"));
+    } else {
+      gst_bin_add (bin, chain->conv);
+      if (prev) {
+        if (!gst_element_link_pads (prev, "src", chain->conv, "sink"))
+          goto link_failed;
+      } else {
+        head = chain->conv;
+      }
+      prev = chain->conv;
+    }
 
-  if (raw) {
-    gst_element_link_pads (chain->queue, "src", chain->conv, "sink");
-    gst_element_link_pads (chain->conv, "src", chain->scale, "sink");
-    /* be more careful with the pad from the custom sink element, it might not
-     * be named 'sink' */
-    if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL))
-      goto link_failed;
-
-    pad = gst_element_get_pad (chain->queue, "sink");
-  } else {
-    if (!gst_element_link_pads (chain->queue, "src", chain->sink, NULL))
-      goto link_failed;
-    pad = gst_element_get_pad (chain->queue, "sink");
+    GST_DEBUG_OBJECT (playsink, "creating videoscale");
+    chain->scale = gst_element_factory_make ("videoscale", "vscale");
+    if (chain->scale == NULL) {
+      post_missing_element_message (playsink, "videoscale");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "videoscale"), ("possibly a liboil version mismatch?"));
+    } else {
+      gst_bin_add (bin, chain->scale);
+      if (prev) {
+        if (!gst_element_link_pads (prev, "src", chain->scale, "sink"))
+          goto link_failed;
+      } else {
+        head = chain->scale;
+      }
+      prev = chain->scale;
+    }
   }
 
-  chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
+  if (prev) {
+    GST_DEBUG_OBJECT (playsink, "linking to sink");
+    if (!gst_element_link_pads (prev, "src", chain->sink, NULL))
+      goto link_failed;
+  }
+
+  pad = gst_element_get_static_pad (head, "sink");
+  chain->sinkpad = gst_ghost_pad_new ("sink", pad);
   gst_object_unref (pad);
-  gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
 
-  return (GstPlayChain *) chain;
+  gst_element_add_pad (chain->chain.bin, chain->sinkpad);
+
+  return chain;
 
   /* ERRORS */
 no_sinks:
   {
-    post_missing_element_message (playsink, "autovideosink");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Both autovideosink and xvimagesink elements are missing.")),
-        (NULL));
-    free_chain ((GstPlayChain *) chain);
-    return NULL;
-  }
-no_colorspace:
-  {
-    post_missing_element_message (playsink, "ffmpegcolorspace");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Missing element '%s' - check your GStreamer installation."),
-            "ffmpegcolorspace"), (NULL));
-    free_chain ((GstPlayChain *) chain);
-    return NULL;
-  }
-
-no_videoscale:
-  {
-    post_missing_element_message (playsink, "videoscale");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Missing element '%s' - check your GStreamer installation."),
-            "videoscale"), ("possibly a liboil version mismatch?"));
+    if (!elem) {
+      post_missing_element_message (playsink, "autovideosink");
+      GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
+          (_("Both autovideosink and xvimagesink elements are missing.")),
+          (NULL));
+    } else {
+      GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE,
+          (_("Both autovideosink and xvimagesink elements are not working.")),
+          (NULL));
+    }
     free_chain ((GstPlayChain *) chain);
     return NULL;
   }
@@ -820,87 +1007,330 @@
   }
 }
 
-#if 0
+static gboolean
+setup_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async,
+    gboolean queue)
+{
+  GstElement *elem;
+  GstPlayVideoChain *chain;
+  GstStateChangeReturn ret;
+
+  chain = playsink->videochain;
+
+  /* if the chain was active we don't do anything */
+  if (GST_PLAY_CHAIN (chain)->activated == TRUE)
+    return TRUE;
+
+  if (chain->chain.raw != raw)
+    return FALSE;
+
+  /* try to set the sink element to READY again */
+  ret = gst_element_set_state (chain->sink, GST_STATE_READY);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return FALSE;
+
+  /* if we can disable async behaviour of the sink, we can avoid adding a
+   * queue for the audio chain. */
+  elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "async");
+  if (elem) {
+    GST_DEBUG_OBJECT (playsink, "setting async property to %d on element %s",
+        async, GST_ELEMENT_NAME (elem));
+    g_object_set (elem, "async", async, NULL);
+    chain->async = async;
+  } else {
+    GST_DEBUG_OBJECT (playsink, "no async property on the sink");
+    chain->async = TRUE;
+  }
+  return TRUE;
+}
+
 /* make an element for playback of video with subtitles embedded.
  *
- *  +--------------------------------------------------+
- *  | tbin                  +-------------+            |
- *  |          +-----+      | textoverlay |   +------+ |
- *  |          | csp | +--video_sink      |   | vbin | |
- * video_sink-sink  src+ +-text_sink     src-sink    | |
- *  |          +-----+   |  +-------------+   +------+ |
- * text_sink-------------+                             |
- *  +--------------------------------------------------+
- *
- *  If there is no subtitle renderer this function will simply return the
- *  videosink without the text_sink pad.
+ *  +----------------------------------------------+
+ *  | tbin                  +-------------+        |
+ *  |          +-----+      | textoverlay |        |
+ *  |          | csp | +--video_sink      |        |
+ * sink-------sink  src+ +-text_sink     src--+    |
+ *  |          +-----+   |  +-------------+   +-- src   
+ * text_sink-------------+                         |
+ *  +----------------------------------------------+
  */
-static GstElement *
-gen_text_element (GstPlaySink * playsink)
+static GstPlayTextChain *
+gen_text_chain (GstPlaySink * playsink)
 {
-  GstElement *element, *csp, *overlay, *vbin;
-  GstPad *pad;
+  GstPlayTextChain *chain;
+  GstBin *bin;
+  GstElement *elem;
+  GstPad *videosinkpad, *textsinkpad, *srcpad;
+
+  chain = g_new0 (GstPlayTextChain, 1);
+  chain->chain.playsink = playsink;
+
+  GST_DEBUG_OBJECT (playsink, "making text chain %p", chain);
+
+  chain->chain.bin = gst_bin_new ("tbin");
+  bin = GST_BIN_CAST (chain->chain.bin);
+  gst_object_ref (bin);
+  gst_object_sink (bin);
+
+  videosinkpad = textsinkpad = srcpad = NULL;
+
+  /* first try to hook the text pad to the custom sink */
+  if (playsink->text_sink) {
+    GST_DEBUG_OBJECT (playsink, "trying configured textsink");
+    chain->sink = try_element (playsink, playsink->text_sink, FALSE);
+    if (chain->sink) {
+      elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "async");
+      if (elem) {
+        /* make sure the sparse subtitles don't participate in the preroll */
+        g_object_set (elem, "async", FALSE, NULL);
+        /* we have a custom sink, this will be our textsinkpad */
+        textsinkpad = gst_element_get_static_pad (chain->sink, "sink");
+        if (textsinkpad) {
+          /* we're all fine now and we can add the sink to the chain */
+          GST_DEBUG_OBJECT (playsink, "adding custom text sink");
+          gst_bin_add (bin, chain->sink);
+        } else {
+          GST_WARNING_OBJECT (playsink,
+              "can't find a sink pad on custom text sink");
+          gst_object_unref (chain->sink);
+          chain->sink = NULL;
+        }
+        /* try to set sync to true but it's no biggie when we can't */
+        if ((elem =
+                gst_play_sink_find_property_sinks (playsink, chain->sink,
+                    "sync")))
+          g_object_set (elem, "sync", TRUE, NULL);
+      } else {
+        GST_WARNING_OBJECT (playsink,
+            "can't find async property in custom text sink");
+      }
+    }
+    if (textsinkpad == NULL) {
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Custom text sink element is not usable.")),
+          ("fallback to default textoverlay"));
+    }
+  }
 
-  /* Create the video rendering bin, error is posted when this fails. */
-  vbin = gen_video_element (playsink);
-  if (!vbin)
-    return NULL;
+  if (textsinkpad == NULL) {
+    if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) {
+      /* no custom sink, try to setup the colorspace and textoverlay elements */
+      chain->conv = gst_element_factory_make ("ffmpegcolorspace", "tconv");
+      if (chain->conv == NULL) {
+        /* not really needed, it might work without colorspace */
+        post_missing_element_message (playsink, "ffmpegcolorspace");
+        GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+            (_("Missing element '%s' - check your GStreamer installation."),
+                "ffmpegcolorspace"), ("subtitle rendering might fail"));
+      } else {
+        gst_bin_add (bin, chain->conv);
+        videosinkpad = gst_element_get_static_pad (chain->conv, "sink");
+      }
+    }
 
-  /* Text overlay */
-  overlay = gst_element_factory_make ("textoverlay", "overlay");
+    chain->overlay = gst_element_factory_make ("textoverlay", "overlay");
+    if (chain->overlay == NULL) {
+      post_missing_element_message (playsink, "textoverlay");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "textoverlay"), ("subtitle rendering disabled"));
+    } else {
+      gst_bin_add (bin, chain->overlay);
+
+      /* Set some parameters */
+      g_object_set (G_OBJECT (chain->overlay),
+          "halign", "center", "valign", "bottom", NULL);
+      if (playsink->font_desc) {
+        g_object_set (G_OBJECT (chain->overlay), "font-desc",
+            playsink->font_desc, NULL);
+      }
+      g_object_set (G_OBJECT (chain->overlay), "wait-text", FALSE, NULL);
 
-  /* If no overlay return the video bin without subtitle support. */
-  if (!overlay)
-    goto no_overlay;
+      textsinkpad = gst_element_get_static_pad (chain->overlay, "text_sink");
+
+      srcpad = gst_element_get_static_pad (chain->overlay, "src");
+
+      if (videosinkpad) {
+        /* if we had a videosinkpad, we had a converter and we can link it, we
+         * know that this will work */
+        gst_element_link_pads (chain->conv, "src", chain->overlay,
+            "video_sink");
+      } else {
+        /* no videopad, expose our own video pad then */
+        videosinkpad =
+            gst_element_get_static_pad (chain->overlay, "video_sink");
+      }
+    }
+  }
 
-  /* Create our bin */
-  element = gst_bin_new ("textbin");
-
-  /* Set some parameters */
-  g_object_set (G_OBJECT (overlay),
-      "halign", "center", "valign", "bottom", NULL);
-  if (playsink->font_desc) {
-    g_object_set (G_OBJECT (overlay), "font-desc", playsink->font_desc, NULL);
+  if (videosinkpad == NULL) {
+    /* if we still don't have a videosink, we don't have a converter nor an
+     * overlay. the only thing we can do is insert an identity and ghost the src
+     * and sink pads. */
+    chain->conv = gst_element_factory_make ("identity", "tidentity");
+    g_object_set (chain->conv, "signal-handoffs", FALSE, NULL);
+    g_object_set (chain->conv, "silent", TRUE, NULL);
+    gst_bin_add (bin, chain->conv);
+    srcpad = gst_element_get_static_pad (chain->conv, "src");
+    videosinkpad = gst_element_get_static_pad (chain->conv, "sink");
+  } else {
+    /* we have a videosink but maybe not a srcpad because there was no
+     * overlay */
+    if (srcpad == NULL) {
+      /* ghost the source pad of the converter then */
+      srcpad = gst_element_get_static_pad (chain->conv, "src");
+    }
   }
 
-  /* Take a ref */
-  playsink->textoverlay_element = GST_ELEMENT_CAST (gst_object_ref (overlay));
+  /* expose the ghostpads */
+  if (videosinkpad) {
+    chain->videosinkpad = gst_ghost_pad_new ("sink", videosinkpad);
+    gst_object_unref (videosinkpad);
+    gst_element_add_pad (chain->chain.bin, chain->videosinkpad);
+  }
+  if (textsinkpad) {
+    chain->textsinkpad = gst_ghost_pad_new ("text_sink", textsinkpad);
+    gst_object_unref (textsinkpad);
+    gst_element_add_pad (chain->chain.bin, chain->textsinkpad);
+  }
+  if (srcpad) {
+    chain->srcpad = gst_ghost_pad_new ("src", srcpad);
+    gst_object_unref (srcpad);
+    gst_element_add_pad (chain->chain.bin, chain->srcpad);
+  }
 
-  /* we know this will succeed, as the video bin already created one before */
-  csp = gst_element_factory_make ("ffmpegcolorspace", "subtitlecsp");
-
-  /* Add our elements */
-  gst_bin_add_many (GST_BIN_CAST (element), csp, overlay, vbin, NULL);
+  return chain;
+}
 
-  /* Link */
-  gst_element_link_pads (csp, "src", overlay, "video_sink");
-  gst_element_link_pads (overlay, "src", vbin, "sink");
+/* make an element for playback of video with subpictures embedded.
+ *
+ *  +--------------------------------------------------------+
+ *  | pbin                            +-------------+        |
+ *  |       +-------+    +-----+      |   dvdspu    |        |
+ *  |       | queue |    | csp | +---video          |        |
+ * sink----sink    src--sink  src+ +-subpicture    src--+    |
+ *  |       +-------+    +-----+   |  +-------------+   +-- src   
+ * subpicture----------------------+                         |
+ *  +--------------------------------------------------------+
+ */
+static GstPlaySubpChain *
+gen_subp_chain (GstPlaySink * playsink)
+{
+  GstPlaySubpChain *chain;
+  GstBin *bin;
+  GstElement *elem, *head;
+  GstPad *videosinkpad, *subpsinkpad, *srcpad;
 
-  /* Add ghost pads on the subtitle bin */
-  pad = gst_element_get_pad (overlay, "text_sink");
-  gst_element_add_pad (element, gst_ghost_pad_new ("text_sink", pad));
-  gst_object_unref (pad);
+  chain = g_new0 (GstPlaySubpChain, 1);
+  chain->chain.playsink = playsink;
+
+  GST_DEBUG_OBJECT (playsink, "making subpicture chain %p", chain);
+
+  chain->chain.bin = gst_bin_new ("pbin");
+  bin = GST_BIN_CAST (chain->chain.bin);
+  gst_object_ref (bin);
+  gst_object_sink (bin);
+
+  videosinkpad = subpsinkpad = srcpad = NULL;
 
-  pad = gst_element_get_pad (csp, "sink");
-  gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
-  gst_object_unref (pad);
+  /* first try to hook the text pad to the custom sink */
+  if (playsink->subp_sink) {
+    GST_DEBUG_OBJECT (playsink, "trying configured subpsink");
+    chain->sink = try_element (playsink, playsink->text_sink, FALSE);
+    if (chain->sink) {
+      elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "async");
+      if (elem) {
+        /* make sure the sparse subtitles don't participate in the preroll */
+        g_object_set (elem, "async", FALSE, NULL);
+        /* we have a custom sink, this will be our subpsinkpad */
+        subpsinkpad = gst_element_get_static_pad (chain->sink, "sink");
+        if (subpsinkpad) {
+          /* we're all fine now and we can add the sink to the chain */
+          GST_DEBUG_OBJECT (playsink, "adding custom text sink");
+          gst_bin_add (bin, chain->sink);
+        } else {
+          GST_WARNING_OBJECT (playsink,
+              "can't find a sink pad on custom text sink");
+          gst_object_unref (chain->sink);
+          chain->sink = NULL;
+        }
+        /* try to set sync to true but it's no biggie when we can't */
+        if ((elem =
+                gst_play_sink_find_property_sinks (playsink, chain->sink,
+                    "sync")))
+          g_object_set (elem, "sync", TRUE, NULL);
+      } else {
+        GST_WARNING_OBJECT (playsink,
+            "can't find async property in custom text sink");
+      }
+    }
+    if (subpsinkpad == NULL) {
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Custom text sink element is not usable.")),
+          ("fallback to default dvdspu overlay"));
+    }
+  }
 
-  /* Set state to READY */
-  gst_element_set_state (element, GST_STATE_READY);
+  /* make a little queue */
+  chain->queue = gst_element_factory_make ("queue", "vqueue");
+  g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3,
+      "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
+  gst_bin_add (bin, chain->queue);
+  head = chain->queue;
 
-  return element;
+  /* video goes into the queue */
+  videosinkpad = gst_element_get_static_pad (chain->queue, "sink");
 
-  /* ERRORS */
-no_overlay:
-  {
-    post_missing_element_message (playsink, "textoverlay");
-    GST_WARNING_OBJECT (playsink,
-        "No overlay (pango) element, subtitles disabled");
-    return vbin;
+  if (subpsinkpad == NULL) {
+    if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) {
+      /* no custom sink, try to setup the colorspace and textoverlay elements */
+      chain->conv = gst_element_factory_make ("ffmpegcolorspace", "tconv");
+      if (chain->conv == NULL) {
+        /* not really needed, it might work without colorspace */
+        post_missing_element_message (playsink, "ffmpegcolorspace");
+        GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+            (_("Missing element '%s' - check your GStreamer installation."),
+                "ffmpegcolorspace"), ("subpicture rendering might fail"));
+      } else {
+        gst_bin_add (bin, chain->conv);
+        gst_element_link_pads (head, "src", chain->conv, "sink");
+        head = chain->conv;
+      }
+    }
+
+    chain->overlay = gst_element_factory_make ("dvdspu", "spuoverlay");
+    if (chain->overlay == NULL) {
+      post_missing_element_message (playsink, "dvdspu");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "dvdspu"), ("subpicture rendering disabled"));
+    } else {
+      gst_bin_add (bin, chain->overlay);
+      /* Set some parameters */
+      subpsinkpad = gst_element_get_static_pad (chain->overlay, "subpicture");
+      /* link to the next element */
+      gst_element_link_pads (head, "src", chain->overlay, "video");
+      head = chain->overlay;
+    }
   }
+  srcpad = gst_element_get_static_pad (head, "src");
+  chain->srcpad = gst_ghost_pad_new ("src", srcpad);
+  gst_object_unref (srcpad);
+  gst_element_add_pad (chain->chain.bin, chain->srcpad);
+
+  /* expose the ghostpads */
+  chain->videosinkpad = gst_ghost_pad_new ("sink", videosinkpad);
+  gst_object_unref (videosinkpad);
+  gst_element_add_pad (chain->chain.bin, chain->videosinkpad);
+
+  if (subpsinkpad) {
+    chain->subpsinkpad = gst_ghost_pad_new ("subpicture", subpsinkpad);
+    gst_object_unref (subpsinkpad);
+    gst_element_add_pad (chain->chain.bin, chain->subpsinkpad);
+  }
+  return chain;
 }
-#endif
-
 
 /* make the chain that contains the elements needed to perform
  * audio playback. 
@@ -917,27 +1347,40 @@
  * sink-+                                                         |
  *  +-------------------------------------------------------------+
  */
-static GstPlayChain *
+static GstPlayAudioChain *
 gen_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue)
 {
   GstPlayAudioChain *chain;
   GstBin *bin;
-  gboolean res;
+  gboolean have_volume;
   GstPad *pad;
+  GstElement *head, *prev, *elem;
 
   chain = g_new0 (GstPlayAudioChain, 1);
-  chain->chain.playsink = gst_object_ref (playsink);
+  chain->chain.playsink = playsink;
+  chain->chain.raw = raw;
+
+  GST_DEBUG_OBJECT (playsink, "making audio chain %p", chain);
 
   if (playsink->audio_sink) {
-    chain->sink = playsink->audio_sink;
-  } else {
-    chain->sink = gst_element_factory_make ("autoaudiosink", "audiosink");
-    if (chain->sink == NULL) {
-      chain->sink = gst_element_factory_make ("alsasink", "audiosink");
-    }
-    if (chain->sink == NULL)
-      goto no_sinks;
+    GST_DEBUG_OBJECT (playsink, "trying configured audiosink %" GST_PTR_FORMAT,
+        playsink->audio_sink);
+    chain->sink = try_element (playsink, playsink->audio_sink, FALSE);
+  }
+  if (chain->sink == NULL) {
+    GST_DEBUG_OBJECT (playsink, "trying autoaudiosink");
+    elem = gst_element_factory_make ("autoaudiosink", "audiosink");
+    chain->sink = try_element (playsink, elem, TRUE);
   }
+  /* FIXME: if DEFAULT_AUDIOSINK != "autoaudiosink" try this now */
+  if (chain->sink == NULL) {
+    GST_DEBUG_OBJECT (playsink, "trying alsasink");
+    elem = gst_element_factory_make ("alsasink", "audiosink");
+    chain->sink = try_element (playsink, elem, TRUE);
+  }
+  if (chain->sink == NULL)
+    goto no_sinks;
+
   chain->chain.bin = gst_bin_new ("abin");
   bin = GST_BIN_CAST (chain->chain.bin);
   gst_object_ref (bin);
@@ -950,97 +1393,151 @@
     GST_DEBUG_OBJECT (playsink, "adding audio queue");
     chain->queue = gst_element_factory_make ("queue", "aqueue");
     gst_bin_add (bin, chain->queue);
+    prev = head = chain->queue;
+  } else {
+    head = chain->sink;
+    prev = NULL;
+  }
+
+  /* check if the sink, or something within the sink, has the volume property.
+   * If it does we don't need to add a volume element.  */
+  elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "volume");
+  if (elem) {
+    chain->volume = elem;
+
+    GST_DEBUG_OBJECT (playsink, "the sink has a volume property");
+    have_volume = TRUE;
+    chain->sink_volume = TRUE;
+    /* if the sink also has a mute property we can use this as well. We'll only
+     * use the mute property if there is a volume property. We can simulate the
+     * mute with the volume otherwise. */
+    chain->mute =
+        gst_play_sink_find_property_sinks (playsink, chain->sink, "mute");
+    if (chain->mute) {
+      GST_DEBUG_OBJECT (playsink, "the sink has a mute property");
+    }
+    /* use the sink to control the volume and mute */
+    if (playsink->volume_changed) {
+      g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
+    }
+    if (playsink->mute_changed) {
+      if (chain->mute) {
+        g_object_set (chain->mute, "mute", playsink->mute, NULL);
+      } else {
+        if (playsink->mute)
+          g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL);
+      }
+    }
+  } else {
+    /* no volume, we need to add a volume element when we can */
+    GST_DEBUG_OBJECT (playsink, "the sink has no volume property");
+    have_volume = FALSE;
+    chain->sink_volume = FALSE;
   }
 
-  if (raw) {
+  if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_AUDIO)) {
+    GST_DEBUG_OBJECT (playsink, "creating audioconvert");
     chain->conv = gst_element_factory_make ("audioconvert", "aconv");
-    if (chain->conv == NULL)
-      goto no_audioconvert;
-    gst_bin_add (bin, chain->conv);
-
-    chain->resample = gst_element_factory_make ("audioresample", "aresample");
-    if (chain->resample == NULL)
-      goto no_audioresample;
-    gst_bin_add (bin, chain->resample);
-
-    res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
-
-    /* FIXME check if the sink has the volume property */
-
-    if (playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) {
-      chain->volume = gst_element_factory_make ("volume", "volume");
-      if (chain->volume == NULL)
-        goto no_volume;
-
-      /* volume also has the mute property */
-      chain->mute = gst_object_ref (chain->volume);
+    if (chain->conv == NULL) {
+      post_missing_element_message (playsink, "audioconvert");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "audioconvert"), ("possibly a liboil version mismatch?"));
+    } else {
+      gst_bin_add (bin, chain->conv);
+      if (prev) {
+        if (!gst_element_link_pads (prev, "src", chain->conv, "sink"))
+          goto link_failed;
+      } else {
+        head = chain->conv;
+      }
+      prev = chain->conv;
+    }
 
-      /* configure with the latest volume */
-      g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
-      gst_bin_add (bin, chain->volume);
-
-      res &=
-          gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
-      res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
+    GST_DEBUG_OBJECT (playsink, "creating audioresample");
+    chain->resample = gst_element_factory_make ("audioresample", "aresample");
+    if (chain->resample == NULL) {
+      post_missing_element_message (playsink, "audioresample");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "audioresample"), ("possibly a liboil version mismatch?"));
     } else {
-      res &= gst_element_link_pads (chain->resample, "src", chain->sink, NULL);
+      gst_bin_add (bin, chain->resample);
+      if (prev) {
+        if (!gst_element_link_pads (prev, "src", chain->resample, "sink"))
+          goto link_failed;
+      } else {
+        head = chain->resample;
+      }
+      prev = chain->resample;
     }
-    if (!res)
-      goto link_failed;
 
-    if (queue) {
-      res = gst_element_link_pads (chain->queue, "src", chain->conv, "sink");
-      pad = gst_element_get_pad (chain->queue, "sink");
-    } else {
-      pad = gst_element_get_pad (chain->conv, "sink");
-    }
-  } else {
-    if (queue) {
-      res = gst_element_link_pads (chain->queue, "src", chain->sink, "sink");
-      pad = gst_element_get_pad (chain->queue, "sink");
-    } else {
-      pad = gst_element_get_pad (chain->sink, "sink");
+    if (!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) {
+      GST_DEBUG_OBJECT (playsink, "creating volume");
+      chain->volume = gst_element_factory_make ("volume", "volume");
+      if (chain->volume == NULL) {
+        post_missing_element_message (playsink, "volume");
+        GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+            (_("Missing element '%s' - check your GStreamer installation."),
+                "volume"), ("possibly a liboil version mismatch?"));
+      } else {
+        have_volume = TRUE;
+
+        /* volume also has the mute property */
+        chain->mute = chain->volume;
+
+        /* configure with the latest volume and mute */
+        g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume,
+            NULL);
+        g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL);
+        gst_bin_add (bin, chain->volume);
+
+        if (prev) {
+          if (!gst_element_link_pads (prev, "src", chain->volume, "sink"))
+            goto link_failed;
+        } else {
+          head = chain->volume;
+        }
+        prev = chain->volume;
+      }
     }
   }
-  chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
+
+  if (prev) {
+    /* we only have to link to the previous element if we have something in
+     * front of the sink */
+    GST_DEBUG_OBJECT (playsink, "linking to sink");
+    if (!gst_element_link_pads (prev, "src", chain->sink, NULL))
+      goto link_failed;
+  }
+
+  /* post a warning if we have no way to configure the volume */
+  if (!have_volume) {
+    GST_ELEMENT_WARNING (playsink, STREAM, NOT_IMPLEMENTED,
+        (_("No volume control found")), ("Volume/mute is not available"));
+  }
+
+  /* and ghost the sinkpad of the headmost element */
+  GST_DEBUG_OBJECT (playsink, "ghosting sink pad");
+  pad = gst_element_get_static_pad (head, "sink");
+  chain->sinkpad = gst_ghost_pad_new ("sink", pad);
   gst_object_unref (pad);
-  gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
+  gst_element_add_pad (chain->chain.bin, chain->sinkpad);
 
-  return (GstPlayChain *) chain;
+  return chain;
 
   /* ERRORS */
 no_sinks:
   {
-    post_missing_element_message (playsink, "autoaudiosink");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Both autoaudiosink and alsasink elements are missing.")), (NULL));
-    free_chain ((GstPlayChain *) chain);
-    return NULL;
-  }
-no_audioconvert:
-  {
-    post_missing_element_message (playsink, "audioconvert");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Missing element '%s' - check your GStreamer installation."),
-            "audioconvert"), ("possibly a liboil version mismatch?"));
-    free_chain ((GstPlayChain *) chain);
-    return NULL;
-  }
-no_audioresample:
-  {
-    post_missing_element_message (playsink, "audioresample");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Missing element '%s' - check your GStreamer installation."),
-            "audioresample"), ("possibly a liboil version mismatch?"));
-    free_chain ((GstPlayChain *) chain);
-    return NULL;
-  }
-no_volume:
-  {
-    post_missing_element_message (playsink, "volume");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Missing element '%s' - check your GStreamer installation."),
-            "volume"), ("possibly a liboil version mismatch?"));
+    if (!elem) {
+      post_missing_element_message (playsink, "autoaudiosink");
+      GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
+          (_("Both autoaudiosink and alsasink elements are missing.")), (NULL));
+    } else {
+      GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE,
+          (_("Both autoaudiosink and alsasink elements are not working.")),
+          (NULL));
+    }
     free_chain ((GstPlayChain *) chain);
     return NULL;
   }
@@ -1053,6 +1550,70 @@
   }
 }
 
+static gboolean
+setup_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue)
+{
+  GstElement *elem;
+  GstPlayAudioChain *chain;
+  GstStateChangeReturn ret;
+
+  chain = playsink->audiochain;
+
+  /* if the chain was active we don't do anything */
+  if (GST_PLAY_CHAIN (chain)->activated == TRUE)
+    return TRUE;
+
+  if (chain->chain.raw != raw)
+    return FALSE;
+
+  /* try to set the sink element to READY again */
+  ret = gst_element_set_state (chain->sink, GST_STATE_READY);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return FALSE;
+
+  /* check if the sink, or something within the sink, has the volume property.
+   * If it does we don't need to add a volume element.  */
+  elem = gst_play_sink_find_property_sinks (playsink, chain->sink, "volume");
+  if (elem) {
+    chain->volume = elem;
+
+    if (playsink->volume_changed) {
+      GST_DEBUG_OBJECT (playsink, "the sink has a volume property, setting %f",
+          playsink->volume);
+      /* use the sink to control the volume */
+      g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
+    }
+    /* if the sink also has a mute property we can use this as well. We'll only
+     * use the mute property if there is a volume property. We can simulate the
+     * mute with the volume otherwise. */
+    chain->mute =
+        gst_play_sink_find_property_sinks (playsink, chain->sink, "mute");
+    if (chain->mute) {
+      GST_DEBUG_OBJECT (playsink, "the sink has a mute property");
+    }
+  } else {
+    /* no volume, we need to add a volume element when we can */
+    GST_DEBUG_OBJECT (playsink, "the sink has no volume property");
+    if (!raw) {
+      GST_LOG_OBJECT (playsink, "non-raw format, can't do soft volume control");
+      chain->volume = NULL;
+      chain->mute = NULL;
+    } else {
+      /* both last and current chain are raw audio, there should be a volume
+       * element already, unless the sink changed from one with a volume
+       * property to one that hasn't got a volume property, in which case we
+       * re-generate the chain */
+      if (chain->volume == NULL) {
+        GST_DEBUG_OBJECT (playsink, "no existing volume element to re-use");
+        return FALSE;
+      }
+
+      GST_DEBUG_OBJECT (playsink, "reusing existing volume element");
+    }
+  }
+  return TRUE;
+}
+
 /*
  *  +-------------------------------------------------------------------+
  *  | visbin                                                            |
@@ -1064,16 +1625,19 @@
  *  +-------------------------------------------------------------------+
  *           
  */
-static GstPlayChain *
+static GstPlayVisChain *
 gen_vis_chain (GstPlaySink * playsink)
 {
   GstPlayVisChain *chain;
   GstBin *bin;
   gboolean res;
   GstPad *pad;
+  GstElement *elem;
 
   chain = g_new0 (GstPlayVisChain, 1);
-  chain->chain.playsink = gst_object_ref (playsink);
+  chain->chain.playsink = playsink;
+
+  GST_DEBUG_OBJECT (playsink, "making vis chain %p", chain);
 
   chain->chain.bin = gst_bin_new ("visbin");
   bin = GST_BIN_CAST (chain->chain.bin);
@@ -1097,15 +1661,20 @@
 
   /* this pad will be used for blocking the dataflow and switching the vis
    * plugin */
-  chain->blockpad = gst_element_get_pad (chain->resample, "src");
+  chain->blockpad = gst_element_get_static_pad (chain->resample, "src");
 
   if (playsink->visualisation) {
-    chain->vis = gst_object_ref (playsink->visualisation);
-  } else {
-    chain->vis = gst_element_factory_make ("goom", "vis");
-    if (!chain->vis)
-      goto no_goom;
+    GST_DEBUG_OBJECT (playsink, "trying configure vis");
+    chain->vis = try_element (playsink, playsink->visualisation, FALSE);
   }
+  if (chain->vis == NULL) {
+    GST_DEBUG_OBJECT (playsink, "trying goom");
+    elem = gst_element_factory_make ("goom", "vis");
+    chain->vis = try_element (playsink, elem, TRUE);
+  }
+  if (chain->vis == NULL)
+    goto no_goom;
+
   gst_bin_add (bin, chain->vis);
 
   res = gst_element_link_pads (chain->queue, "src", chain->conv, "sink");
@@ -1114,18 +1683,18 @@
   if (!res)
     goto link_failed;
 
-  chain->vissinkpad = gst_element_get_pad (chain->vis, "sink");
-  chain->vissrcpad = gst_element_get_pad (chain->vis, "src");
+  chain->vissinkpad = gst_element_get_static_pad (chain->vis, "sink");
+  chain->vissrcpad = gst_element_get_static_pad (chain->vis, "src");
 
-  pad = gst_element_get_pad (chain->queue, "sink");
-  chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
+  pad = gst_element_get_static_pad (chain->queue, "sink");
+  chain->sinkpad = gst_ghost_pad_new ("sink", pad);
   gst_object_unref (pad);
-  gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
+  gst_element_add_pad (chain->chain.bin, chain->sinkpad);
 
   chain->srcpad = gst_ghost_pad_new ("src", chain->vissrcpad);
   gst_element_add_pad (chain->chain.bin, chain->srcpad);
 
-  return (GstPlayChain *) chain;
+  return chain;
 
   /* ERRORS */
 no_audioconvert:
@@ -1164,33 +1733,9 @@
   }
 }
 
-#if 0
-static gboolean
-activate_vis (GstPlaySink * playsink, gboolean activate)
-{
-  /* need to have an audio chain */
-  if (!playsink->audiochain || !playsink->vischain)
-    return FALSE;
-
-  if (playsink->vischain->activated == activate)
-    return TRUE;
-
-  if (activate) {
-    /* activation: Add the vis chain to the sink bin . Take a new srcpad from
-     * the tee of the audio chain and link it to the sinkpad of the vis chain.
-     */
-
-  } else {
-    /* deactivation: release the srcpad from the tee of the audio chain. Set the
-     * vis chain to NULL and remove it from the sink bin */
-
-  }
-  return TRUE;
-}
-#endif
-
 /* this function is called when all the request pads are requested and when we
- * have to construct the final pipeline.
+ * have to construct the final pipeline. Based on the flags we construct the
+ * final output pipelines.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1200,12 +1745,12 @@
 gst_play_sink_reconfigure (GstPlaySink * playsink)
 {
   GstPlayFlags flags;
-  gboolean need_audio, need_video, need_vis;
+  gboolean need_audio, need_video, need_vis, need_text, need_subp;
 
   GST_DEBUG_OBJECT (playsink, "reconfiguring");
 
   /* assume we need nothing */
-  need_audio = need_video = need_vis = FALSE;
+  need_audio = need_video = need_vis = need_text = need_subp = FALSE;
 
   GST_PLAY_SINK_LOCK (playsink);
   GST_OBJECT_LOCK (playsink);
@@ -1214,7 +1759,22 @@
   GST_OBJECT_UNLOCK (playsink);
 
   /* figure out which components we need */
-  if (flags & GST_PLAY_FLAG_VIDEO && playsink->video_pad) {
+  if (flags & GST_PLAY_FLAG_TEXT && (playsink->text_pad || playsink->subp_pad)) {
+    /* we have a text_pad and we need text rendering, in this case we need a
+     * video_pad to combine the video with the text */
+    if (!playsink->video_pad)
+      goto subs_but_no_video;
+
+    /* we have subtitles and we are requested to show it, we also need to show
+     * video in this case. */
+    need_video = TRUE;
+    need_text = (playsink->text_pad != NULL);
+    need_subp = (playsink->subp_pad != NULL);
+
+    /* we can't handle both of them yet */
+    if (need_text && need_subp)
+      goto subs_and_text;
+  } else if (flags & GST_PLAY_FLAG_VIDEO && playsink->video_pad) {
     /* we have video and we are requested to show it */
     need_video = TRUE;
   }
@@ -1222,71 +1782,233 @@
     if (flags & GST_PLAY_FLAG_AUDIO) {
       need_audio = TRUE;
     }
-    if (flags & GST_PLAY_FLAG_VIS && !need_video) {
-      /* also add video when we add visualisation */
-      need_video = TRUE;
-      need_vis = TRUE;
+    if (playsink->audio_pad_raw) {
+      /* only can do vis with raw uncompressed audio */
+      if (flags & GST_PLAY_FLAG_VIS && !need_video) {
+        /* also add video when we add visualisation */
+        need_video = TRUE;
+        need_vis = TRUE;
+      }
     }
   }
 
+  /* set up video pipeline */
   if (need_video) {
+    gboolean raw, async, queue;
+
+    /* we need a raw sink when we do vis or when we have a raw pad */
+    raw = need_vis ? TRUE : playsink->video_pad_raw;
+    /* we try to set the sink async=FALSE when we need vis, this way we can
+     * avoid a queue in the audio chain. */
+    async = !need_vis;
+    /* put a little queue in front of the video but only if we are not doing
+     * subpictures because then we will add the queue in front of the subpicture
+     * mixer to minimize latency. */
+    queue = (need_subp == FALSE);
+
     GST_DEBUG_OBJECT (playsink, "adding video, raw %d",
         playsink->video_pad_raw);
-    if (!playsink->videochain) {
-      gboolean raw, async;
 
-      /* we need a raw sink when we do vis or when we have a raw pad */
-      raw = need_vis ? TRUE : playsink->video_pad_raw;
-      /* we try to set the sink async=FALSE when we need vis, this way we can
-       * avoid a queue in the audio chain. */
-      async = !need_vis;
+    if (playsink->videochain) {
+      /* try to reactivate the chain */
+      if (!setup_video_chain (playsink, raw, async, queue)) {
+        add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
+        activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
+        free_chain ((GstPlayChain *) playsink->videochain);
+        playsink->videochain = NULL;
+      }
+    }
 
-      playsink->videochain = gen_video_chain (playsink, raw, async);
+    if (!playsink->videochain) {
+      playsink->videochain = gen_video_chain (playsink, raw, async, queue);
+    }
+    if (playsink->videochain) {
+      GST_DEBUG_OBJECT (playsink, "adding video chain");
+      add_chain (GST_PLAY_CHAIN (playsink->videochain), TRUE);
+      activate_chain (GST_PLAY_CHAIN (playsink->videochain), TRUE);
+      /* if we are not part of vis or subtitles, set the ghostpad target */
+      if (!need_vis && !need_text && playsink->text_pad == NULL) {
+        GST_DEBUG_OBJECT (playsink, "ghosting video sinkpad");
+        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad),
+            playsink->videochain->sinkpad);
+      }
     }
-    add_chain (playsink->videochain, TRUE);
-    activate_chain (playsink->videochain, TRUE);
-    if (!need_vis)
-      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad),
-          playsink->videochain->sinkpad);
   } else {
+    GST_DEBUG_OBJECT (playsink, "no video needed");
     if (playsink->videochain) {
-      add_chain (playsink->videochain, FALSE);
-      activate_chain (playsink->videochain, FALSE);
+      GST_DEBUG_OBJECT (playsink, "removing video chain");
+      if (playsink->vischain) {
+        GstPad *srcpad;
+
+        GST_DEBUG_OBJECT (playsink, "unlinking vis chain");
+
+        /* also had visualisation, release the tee srcpad before we then 
+         * unlink the video from it */
+        if (playsink->audio_tee_vissrc) {
+          gst_element_release_request_pad (playsink->audio_tee,
+              playsink->audio_tee_vissrc);
+          gst_object_unref (playsink->audio_tee_vissrc);
+          playsink->audio_tee_vissrc = NULL;
+        }
+        srcpad =
+            gst_element_get_static_pad (playsink->vischain->chain.bin, "src");
+        gst_pad_unlink (srcpad, playsink->videochain->sinkpad);
+      }
+      add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
+      activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
     }
     if (playsink->video_pad)
       gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL);
   }
 
-  if (need_audio) {
-    GST_DEBUG_OBJECT (playsink, "adding audio");
-    if (!playsink->audiochain) {
-      gboolean raw, queue;
+  if (need_text) {
+    GST_DEBUG_OBJECT (playsink, "adding text");
+    if (!playsink->textchain) {
+      GST_DEBUG_OBJECT (playsink, "creating text chain");
+      playsink->textchain = gen_text_chain (playsink);
+    }
+    if (playsink->textchain) {
+      GST_DEBUG_OBJECT (playsink, "adding text chain");
+      add_chain (GST_PLAY_CHAIN (playsink->textchain), TRUE);
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->text_pad),
+          playsink->textchain->textsinkpad);
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad),
+          playsink->textchain->videosinkpad);
+      gst_pad_link (playsink->textchain->srcpad, playsink->videochain->sinkpad);
+      activate_chain (GST_PLAY_CHAIN (playsink->textchain), TRUE);
+      if (playsink->textchain->overlay)
+        g_object_set (playsink->textchain->overlay, "silent", FALSE, NULL);
+    }
+  } else {
+    GST_DEBUG_OBJECT (playsink, "no text needed");
+    /* we have no subtitles/text or we are requested to not show them */
+    if (playsink->textchain) {
+      if (playsink->text_pad == NULL) {
+        /* no text pad, remove the chain entirely */
+        GST_DEBUG_OBJECT (playsink, "removing text chain");
+        add_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE);
+        activate_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE);
+      } else {
+        /* we have a chain and a textpad, turn the subtitles off */
+        GST_DEBUG_OBJECT (playsink, "turning off the text");
+        if (playsink->textchain->overlay)
+          g_object_set (playsink->textchain->overlay, "silent", TRUE, NULL);
+      }
+    }
+    if (!need_video && playsink->video_pad)
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL);
+    if (playsink->text_pad)
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->text_pad), NULL);
+  }
 
-      /* get a raw sink if we are asked for a raw pad */
-      raw = playsink->audio_pad_raw;
-      if (need_vis) {
-        /* If we are dealing with visualisations, we need to add a queue to
-         * decouple the audio from the video part. We only have to do this when
-         * the video part is async=true */
-        queue = ((GstPlayVideoChain *) playsink->videochain)->async;
-        GST_DEBUG_OBJECT (playsink, "need audio queue for vis: %d", queue);
+  if (need_subp && playsink->videochain) {
+    GST_DEBUG_OBJECT (playsink, "adding subpicture");
+    if (!playsink->subpchain) {
+      GST_DEBUG_OBJECT (playsink, "creating subpicture chain");
+      playsink->subpchain = gen_subp_chain (playsink);
+    }
+    if (playsink->subpchain) {
+      GST_DEBUG_OBJECT (playsink, "adding subp chain");
+      add_chain (GST_PLAY_CHAIN (playsink->subpchain), TRUE);
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->subp_pad),
+          playsink->subpchain->subpsinkpad);
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad),
+          playsink->subpchain->videosinkpad);
+      gst_pad_link (playsink->subpchain->srcpad, playsink->videochain->sinkpad);
+      activate_chain (GST_PLAY_CHAIN (playsink->subpchain), TRUE);
+    }
+  } else {
+    GST_DEBUG_OBJECT (playsink, "no subpicture needed");
+    /* we have no subpicture or we are requested to not show them */
+    if (playsink->subpchain) {
+      if (playsink->subp_pad == NULL) {
+        /* no subpicture pad, remove the chain entirely */
+        GST_DEBUG_OBJECT (playsink, "removing subp chain");
+        add_chain (GST_PLAY_CHAIN (playsink->subpchain), FALSE);
+        activate_chain (GST_PLAY_CHAIN (playsink->subpchain), FALSE);
       } else {
-        /* no vis, we can avoid a queue */
-        GST_DEBUG_OBJECT (playsink, "don't need audio queue");
-        queue = FALSE;
+        /* we have a chain and a subpicture pad, turn the subtitles off */
+        GST_DEBUG_OBJECT (playsink, "turning off the subp");
       }
+    }
+    if (!need_video && playsink->video_pad)
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL);
+    if (playsink->subp_pad)
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->subp_pad), NULL);
+  }
 
+  if (need_audio) {
+    gboolean raw, queue;
+
+    GST_DEBUG_OBJECT (playsink, "adding audio");
+
+    /* get a raw sink if we are asked for a raw pad */
+    raw = playsink->audio_pad_raw;
+    if (need_vis && playsink->videochain) {
+      /* If we are dealing with visualisations, we need to add a queue to
+       * decouple the audio from the video part. We only have to do this when
+       * the video part is async=true */
+      queue = ((GstPlayVideoChain *) playsink->videochain)->async;
+      GST_DEBUG_OBJECT (playsink, "need audio queue for vis: %d", queue);
+    } else {
+      /* no vis, we can avoid a queue */
+      GST_DEBUG_OBJECT (playsink, "don't need audio queue");
+      queue = FALSE;
+    }
+
+    if (playsink->audiochain) {
+      /* try to reactivate the chain */
+      if (!setup_audio_chain (playsink, raw, queue)) {
+        GST_DEBUG_OBJECT (playsink, "removing current audio chain");
+        if (playsink->audio_tee_asrc) {
+          gst_element_release_request_pad (playsink->audio_tee,
+              playsink->audio_tee_asrc);
+          gst_object_unref (playsink->audio_tee_asrc);
+          playsink->audio_tee_asrc = NULL;
+        }
+        add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
+        activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
+        playsink->audiochain->volume = NULL;
+        playsink->audiochain->mute = NULL;
+        free_chain ((GstPlayChain *) playsink->audiochain);
+        playsink->audiochain = NULL;
+        playsink->volume_changed = playsink->mute_changed = FALSE;
+      }
+    }
+
+    if (!playsink->audiochain) {
+      GST_DEBUG_OBJECT (playsink, "creating new audio chain");
       playsink->audiochain = gen_audio_chain (playsink, raw, queue);
     }
-    add_chain (playsink->audiochain, TRUE);
-    gst_pad_link (playsink->audio_tee_asrc, playsink->audiochain->sinkpad);
-    activate_chain (playsink->audiochain, TRUE);
+
+    if (playsink->audiochain) {
+      GST_DEBUG_OBJECT (playsink, "adding audio chain");
+      if (playsink->audio_tee_asrc == NULL) {
+        playsink->audio_tee_asrc =
+            gst_element_get_request_pad (playsink->audio_tee, "src%d");
+      }
+      add_chain (GST_PLAY_CHAIN (playsink->audiochain), TRUE);
+      activate_chain (GST_PLAY_CHAIN (playsink->audiochain), TRUE);
+      gst_pad_link (playsink->audio_tee_asrc, playsink->audiochain->sinkpad);
+    }
   } else {
+    GST_DEBUG_OBJECT (playsink, "no audio needed");
     /* we have no audio or we are requested to not play audio */
     if (playsink->audiochain) {
-      gst_pad_unlink (playsink->audio_tee_asrc, playsink->audiochain->sinkpad);
-      add_chain (playsink->audiochain, FALSE);
-      activate_chain (playsink->audiochain, FALSE);
+      GST_DEBUG_OBJECT (playsink, "removing audio chain");
+      /* release the audio pad */
+      if (playsink->audio_tee_asrc) {
+        gst_element_release_request_pad (playsink->audio_tee,
+            playsink->audio_tee_asrc);
+        gst_object_unref (playsink->audio_tee_asrc);
+        playsink->audio_tee_asrc = NULL;
+      }
+      if (playsink->audiochain->sink_volume) {
+        playsink->audiochain->volume = NULL;
+        playsink->audiochain->mute = NULL;
+      }
+      add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
+      activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
     }
   }
 
@@ -1298,28 +2020,72 @@
 
     GST_DEBUG_OBJECT (playsink, "adding visualisation");
 
-    srcpad =
-        gst_element_get_pad (GST_ELEMENT_CAST (playsink->vischain->bin), "src");
-    add_chain (playsink->vischain, TRUE);
-    gst_pad_link (playsink->audio_tee_vissrc, playsink->vischain->sinkpad);
-    gst_pad_link (srcpad, playsink->videochain->sinkpad);
-    gst_object_unref (srcpad);
-    activate_chain (playsink->vischain, TRUE);
+    if (playsink->vischain) {
+      GST_DEBUG_OBJECT (playsink, "setting up vis chain");
+      srcpad =
+          gst_element_get_static_pad (playsink->vischain->chain.bin, "src");
+      add_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
+      activate_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
+      if (playsink->audio_tee_vissrc == NULL) {
+        playsink->audio_tee_vissrc =
+            gst_element_get_request_pad (playsink->audio_tee, "src%d");
+      }
+      gst_pad_link (playsink->audio_tee_vissrc, playsink->vischain->sinkpad);
+      gst_pad_link (srcpad, playsink->videochain->sinkpad);
+      gst_object_unref (srcpad);
+    }
   } else {
+    GST_DEBUG_OBJECT (playsink, "no vis needed");
     if (playsink->vischain) {
-      add_chain (playsink->vischain, FALSE);
-      activate_chain (playsink->vischain, FALSE);
+      if (playsink->audio_tee_vissrc) {
+        gst_element_release_request_pad (playsink->audio_tee,
+            playsink->audio_tee_vissrc);
+        gst_object_unref (playsink->audio_tee_vissrc);
+        playsink->audio_tee_vissrc = NULL;
+      }
+      GST_DEBUG_OBJECT (playsink, "removing vis chain");
+      add_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE);
+      activate_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE);
     }
   }
+  do_async_done (playsink);
   GST_PLAY_SINK_UNLOCK (playsink);
 
   return TRUE;
+
+  /* ERRORS */
+subs_but_no_video:
+  {
+    GST_ELEMENT_ERROR (playsink, STREAM, FORMAT,
+        (_("Can't play a text file without video.")),
+        ("Have text pad but no video pad"));
+    GST_PLAY_SINK_UNLOCK (playsink);
+    return FALSE;
+  }
+subs_and_text:
+  {
+    GST_ELEMENT_ERROR (playsink, STREAM, FORMAT,
+        (_("Can't play a text subtitles and subpictures.")),
+        ("Have text pad and subpicture pad"));
+    GST_PLAY_SINK_UNLOCK (playsink);
+    return FALSE;
+  }
 }
+
+/**
+ * gst_play_sink_set_flags:
+ * @playsink: a #GstPlaySink
+ * @flags: #GstPlayFlags
+ *
+ * Configure @flags on @playsink. The flags control the behaviour of @playsink
+ * when constructing the sink pipelins.
+ *
+ * Returns: TRUE if the flags could be configured.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 gboolean
 gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags)
 {
@@ -1331,11 +2097,20 @@
 
   return TRUE;
 }
+
+/**
+ * gst_play_sink_get_flags:
+ * @playsink: a #GstPlaySink
+ *
+ * Get the flags of @playsink. That flags control the behaviour of the sink when
+ * it constructs the sink pipelines.
+ *
+ * Returns: the currently configured #GstPlayFlags.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 GstPlayFlags
 gst_play_sink_get_flags (GstPlaySink * playsink)
 {
@@ -1354,6 +2129,59 @@
 #endif
 
 
+void
+gst_play_sink_set_font_desc (GstPlaySink * playsink, const gchar * desc)
+{
+  GstPlayTextChain *chain;
+
+  GST_PLAY_SINK_LOCK (playsink);
+  chain = (GstPlayTextChain *) playsink->textchain;
+  g_free (playsink->font_desc);
+  playsink->font_desc = g_strdup (desc);
+  if (chain && chain->overlay) {
+    g_object_set (chain->overlay, "font-desc", desc, NULL);
+  }
+  GST_PLAY_SINK_UNLOCK (playsink);
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gchar *
+gst_play_sink_get_font_desc (GstPlaySink * playsink)
+{
+  gchar *result = NULL;
+  GstPlayTextChain *chain;
+
+  GST_PLAY_SINK_LOCK (playsink);
+  chain = (GstPlayTextChain *) playsink->textchain;
+  if (chain && chain->overlay) {
+    g_object_get (chain->overlay, "font-desc", &result, NULL);
+    playsink->font_desc = g_strdup (result);
+  } else {
+    result = g_strdup (playsink->font_desc);
+  }
+  GST_PLAY_SINK_UNLOCK (playsink);
+
+  return result;
+}
+
+/**
+ * gst_play_sink_get_last_frame:
+ * @playsink: a #GstPlaySink
+ *
+ * Get the last displayed frame from @playsink. This frame is in the native
+ * format of the sink element, the caps on the result buffer contain the format
+ * of the frame data.
+ *
+ * Returns: a #GstBuffer with the frame data or %NULL when no video frame is
+ * available.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
 GstBuffer *
 gst_play_sink_get_last_frame (GstPlaySink * playsink)
 {
@@ -1385,17 +2213,29 @@
 
   return result;
 }
+
+/**
+ * gst_play_sink_request_pad
+ * @playsink: a #GstPlaySink
+ * @type: a #GstPlaySinkType
+ *
+ * Create or return a pad of @type.
+ *
+ * Returns: a #GstPad of @type or %NULL when the pad could not be created.
+ */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 GstPad *
 gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
 {
   GstPad *res = NULL;
   gboolean created = FALSE;
   gboolean raw = FALSE;
+  gboolean activate = TRUE;
+
+  GST_DEBUG_OBJECT (playsink, "request pad type %d", type);
 
   GST_PLAY_SINK_LOCK (playsink);
   switch (type) {
@@ -1403,20 +2243,19 @@
       raw = TRUE;
     case GST_PLAY_SINK_TYPE_AUDIO:
       if (!playsink->audio_tee) {
+        GST_LOG_OBJECT (playsink, "creating tee");
         /* create tee when needed. This element will feed the audio sink chain
          * and the vis chain. */
         playsink->audio_tee = gst_element_factory_make ("tee", "audiotee");
         playsink->audio_tee_sink =
-            gst_element_get_pad (playsink->audio_tee, "sink");
-        /* get two request pads */
-        playsink->audio_tee_vissrc =
-            gst_element_get_request_pad (playsink->audio_tee, "src%d");
-        playsink->audio_tee_asrc =
-            gst_element_get_request_pad (playsink->audio_tee, "src%d");
+            gst_element_get_static_pad (playsink->audio_tee, "sink");
         gst_bin_add (GST_BIN_CAST (playsink), playsink->audio_tee);
         gst_element_set_state (playsink->audio_tee, GST_STATE_PAUSED);
+      } else {
+        gst_element_set_state (playsink->audio_tee, GST_STATE_PAUSED);
       }
       if (!playsink->audio_pad) {
+        GST_LOG_OBJECT (playsink, "ghosting tee sinkpad");
         playsink->audio_pad =
             gst_ghost_pad_new ("audio_sink", playsink->audio_tee_sink);
         created = TRUE;
@@ -1428,6 +2267,7 @@
       raw = TRUE;
     case GST_PLAY_SINK_TYPE_VIDEO:
       if (!playsink->video_pad) {
+        GST_LOG_OBJECT (playsink, "ghosting videosink");
         playsink->video_pad =
             gst_ghost_pad_new_no_target ("video_sink", GST_PAD_SINK);
         created = TRUE;
@@ -1436,6 +2276,7 @@
       res = playsink->video_pad;
       break;
     case GST_PLAY_SINK_TYPE_TEXT:
+      GST_LOG_OBJECT (playsink, "ghosting text");
       if (!playsink->text_pad) {
         playsink->text_pad =
             gst_ghost_pad_new_no_target ("text_sink", GST_PAD_SINK);
@@ -1443,6 +2284,28 @@
       }
       res = playsink->text_pad;
       break;
+    case GST_PLAY_SINK_TYPE_FLUSHING:
+    {
+      gchar *padname;
+
+      /* we need a unique padname for the flushing pad. */
+      padname = g_strdup_printf ("flushing_%d", playsink->count);
+      res = gst_ghost_pad_new_no_target (padname, GST_PAD_SINK);
+      g_free (padname);
+      playsink->count++;
+      activate = FALSE;
+      created = TRUE;
+      break;
+    }
+    case GST_PLAY_SINK_TYPE_SUBPIC:
+      GST_LOG_OBJECT (playsink, "ghosting subpicture pad");
+      if (!playsink->subp_pad) {
+        playsink->subp_pad =
+            gst_ghost_pad_new_no_target ("subp_sink", GST_PAD_SINK);
+        created = TRUE;
+      }
+      res = playsink->subp_pad;
+      break;
     default:
       res = NULL;
       break;
@@ -1450,8 +2313,12 @@
   GST_PLAY_SINK_UNLOCK (playsink);
 
   if (created && res) {
+    /* we have to add the pad when it's active or we get an error when the
+     * element is 'running' */
     gst_pad_set_active (res, TRUE);
     gst_element_add_pad (GST_ELEMENT_CAST (playsink), res);
+    if (!activate)
+      gst_pad_set_active (res, activate);
   }
 
   return res;
@@ -1465,6 +2332,9 @@
 gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad)
 {
   GstPad **res = NULL;
+  gboolean untarget = TRUE;
+
+  GST_DEBUG_OBJECT (playsink, "release pad %" GST_PTR_FORMAT, pad);
 
   GST_PLAY_SINK_LOCK (playsink);
   if (pad == playsink->video_pad) {
@@ -1473,16 +2343,73 @@
     res = &playsink->audio_pad;
   } else if (pad == playsink->text_pad) {
     res = &playsink->text_pad;
+  } else if (pad == playsink->subp_pad) {
+    res = &playsink->subp_pad;
+  } else {
+    /* try to release the given pad anyway, these could be the FLUSHING pads. */
+    res = &pad;
+    untarget = FALSE;
   }
   GST_PLAY_SINK_UNLOCK (playsink);
 
   if (*res) {
+    GST_DEBUG_OBJECT (playsink, "deactivate pad %" GST_PTR_FORMAT, *res);
     gst_pad_set_active (*res, FALSE);
+    if (untarget) {
+      GST_DEBUG_OBJECT (playsink, "untargeting pad %" GST_PTR_FORMAT, *res);
+      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (*res), NULL);
+    }
+    GST_DEBUG_OBJECT (playsink, "remove pad %" GST_PTR_FORMAT, *res);
     gst_element_remove_pad (GST_ELEMENT_CAST (playsink), *res);
     *res = NULL;
   }
 }
 
+static void
+gst_play_sink_handle_message (GstBin * bin, GstMessage * message)
+{
+  GstPlaySink *playsink;
+
+  playsink = GST_PLAY_SINK_CAST (bin);
+
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_STEP_DONE:
+    {
+      GstFormat format;
+      guint64 amount;
+      gdouble rate;
+      gboolean flush, intermediate, res, eos;
+      guint64 duration;
+
+      GST_INFO_OBJECT (playsink, "Handling step-done message");
+      gst_message_parse_step_done (message, &format, &amount, &rate, &flush,
+          &intermediate, &duration, &eos);
+
+      if (format == GST_FORMAT_BUFFERS) {
+        /* for the buffer format, we align the other streams */
+        if (playsink->audiochain) {
+          GstEvent *event;
+
+          event =
+              gst_event_new_step (GST_FORMAT_TIME, duration, rate, flush,
+              intermediate);
+
+          if (!(res =
+                  gst_element_send_event (playsink->audiochain->chain.bin,
+                      event))) {
+            GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink");
+          }
+        }
+      }
+      GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message);
+      break;
+    }
+    default:
+      GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message);
+      break;
+  }
+}
+
 /* Send an event to our sinks until one of them works; don't then send to the
  * remaining sinks (unlike GstBin)
  */
@@ -1491,22 +2418,22 @@
 {
   gboolean res = TRUE;
 
+  if (playsink->videochain) {
+    gst_event_ref (event);
+    if ((res = gst_element_send_event (playsink->videochain->chain.bin, event))) {
+      GST_DEBUG_OBJECT (playsink, "Sent event succesfully to video sink");
+      goto done;
+    }
+    GST_DEBUG_OBJECT (playsink, "Event failed when sent to video sink");
+  }
   if (playsink->audiochain) {
     gst_event_ref (event);
-    if ((res = gst_element_send_event (playsink->audiochain->bin, event))) {
+    if ((res = gst_element_send_event (playsink->audiochain->chain.bin, event))) {
       GST_DEBUG_OBJECT (playsink, "Sent event succesfully to audio sink");
       goto done;
     }
     GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink");
   }
-  if (playsink->videochain) {
-    gst_event_ref (event);
-    if ((res = gst_element_send_event (playsink->videochain->bin, event))) {
-      GST_DEBUG_OBJECT (playsink, "Sent event succesfully to video sink");
-      goto done;
-    }
-    GST_DEBUG_OBJECT (playsink, "Event failed when sent to video sink");
-  }
 done:
   gst_event_unref (event);
   return res;
@@ -1520,14 +2447,40 @@
 {
   gboolean res = FALSE;
   GstEventType event_type = GST_EVENT_TYPE (event);
+  GstPlaySink *playsink;
+
+  playsink = GST_PLAY_SINK_CAST (element);
 
   switch (event_type) {
     case GST_EVENT_SEEK:
-      GST_DEBUG_OBJECT (element, "Sending seek event to a sink");
-      res = gst_play_sink_send_event_to_sink (GST_PLAY_SINK (element), event);
+      GST_DEBUG_OBJECT (element, "Sending event to a sink");
+      res = gst_play_sink_send_event_to_sink (playsink, event);
       break;
+    case GST_EVENT_STEP:
+    {
+      GstFormat format;
+      guint64 amount;
+      gdouble rate;
+      gboolean flush, intermediate;
+
+      gst_event_parse_step (event, &format, &amount, &rate, &flush,
+          &intermediate);
+
+      if (format == GST_FORMAT_BUFFERS) {
+        /* for buffers, we will try to step video frames, for other formats we
+         * send the step to all sinks */
+        res = gst_play_sink_send_event_to_sink (playsink, event);
+      } else {
+        res =
+            GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
+            event);
+      }
+      break;
+    }
     default:
-      res = parent_class->send_event (element, event);
+      res =
+          GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
+          event);
       break;
   }
   return res;
@@ -1537,41 +2490,102 @@
 gst_play_sink_change_state (GstElement * element, GstStateChange transition)
 {
   GstStateChangeReturn ret;
+  GstStateChangeReturn bret;
+
   GstPlaySink *playsink;
 
   playsink = GST_PLAY_SINK (element);
 
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+      /* we want to go async to PAUSED until we managed to configure and add the
+       * sinks */
+      do_async_start (playsink);
+      ret = GST_STATE_CHANGE_ASYNC;
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      if (playsink->audiochain && playsink->audiochain->sink_volume) {
+        /* remove our links to the mute and volume elements when they were
+         * provided by a sink */
+        playsink->audiochain->volume = NULL;
+        playsink->audiochain->mute = NULL;
+      }
+      ret = GST_STATE_CHANGE_SUCCESS;
       break;
     default:
+      /* all other state changes return SUCCESS by default, this value can be
+       * overridden by the result of the children */
+      ret = GST_STATE_CHANGE_SUCCESS;
       break;
   }
 
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
+  /* do the state change of the children */
+  bret =
+      GST_ELEMENT_CLASS (gst_play_sink_parent_class)->change_state (element,
+      transition);
+  /* now look at the result of our children and adjust the return value */
+  switch (bret) {
+    case GST_STATE_CHANGE_FAILURE:
+      /* failure, we stop */
+      goto activate_failed;
+    case GST_STATE_CHANGE_NO_PREROLL:
+      /* some child returned NO_PREROLL. This is strange but we never know. We
+       * commit our async state change (if any) and return the NO_PREROLL */
+      do_async_done (playsink);
+      ret = bret;
+      break;
+    case GST_STATE_CHANGE_ASYNC:
+      /* some child was async, return this */
+      ret = bret;
+      break;
+    default:
+      /* return our previously configured return value */
+      break;
+  }
 
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       /* FIXME Release audio device when we implement that */
+      playsink->need_async_start = TRUE;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+    case GST_STATE_CHANGE_READY_TO_NULL:
       /* remove sinks we added */
       if (playsink->videochain) {
-        activate_chain (playsink->videochain, FALSE);
-        add_chain (playsink->videochain, FALSE);
+        activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
+        add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
       }
       if (playsink->audiochain) {
-        activate_chain (playsink->audiochain, FALSE);
-        add_chain (playsink->audiochain, FALSE);
+        activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
+        add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE);
+      }
+      if (playsink->vischain) {
+        activate_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE);
+        add_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE);
       }
+      if (playsink->textchain) {
+        activate_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE);
+        add_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE);
+      }
+      if (playsink->subpchain) {
+        activate_chain (GST_PLAY_CHAIN (playsink->subpchain), FALSE);
+        add_chain (GST_PLAY_CHAIN (playsink->subpchain), FALSE);
+      }
+      do_async_done (playsink);
       break;
     default:
       break;
   }
+  return ret;
 
-  return ret;
+  /* ERRORS */
+activate_failed:
+  {
+    GST_DEBUG_OBJECT (element,
+        "element failed to change states -- activation problem?");
+    return GST_STATE_CHANGE_FAILURE;
+  }
 }
--- a/gst_plugins_base/gst/playback/gstplaysink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstplaysink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -36,6 +36,8 @@
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAY_SINK))
 #define GST_IS_PLAY_SINK_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK))
+#define GST_PLAY_SINK_CAST(obj) \
+  ((GstPlaySink*)(obj))
 
 /**
  * GstPlaySinkType:
@@ -44,7 +46,9 @@
  * @GST_PLAY_SINK_TYPE_VIDEO: a non-raw video pad
  * @GST_PLAY_SINK_TYPE_VIDEO_RAW: a raw video pad
  * @GST_PLAY_SINK_TYPE_TEXT: a raw text pad
+ * @GST_PLAY_SINK_TYPE_SUBPIC: a subpicture pad
  * @GST_PLAY_SINK_TYPE_LAST: the last type
+ * @GST_PLAY_SINK_TYPE_FLUSHING: a flushing pad, used when shutting down
  *
  * Types of pads that can be requested from the sinks.
  */
@@ -54,7 +58,11 @@
   GST_PLAY_SINK_TYPE_VIDEO     = 2,
   GST_PLAY_SINK_TYPE_VIDEO_RAW = 3,
   GST_PLAY_SINK_TYPE_TEXT      = 4,
-  GST_PLAY_SINK_TYPE_LAST      = 5
+  GST_PLAY_SINK_TYPE_SUBPIC    = 5,
+  GST_PLAY_SINK_TYPE_LAST      = 6,
+
+  /* this is a dummy pad */
+  GST_PLAY_SINK_TYPE_FLUSHING  = 7
 } GstPlaySinkType;
 
 typedef struct _GstPlaySink GstPlaySink;
@@ -80,18 +88,23 @@
 IMPORT_C
 #endif
 
+void             gst_play_sink_set_sink       (GstPlaySink * playsink, GstPlaySinkType type, GstElement * sink);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+GstElement *     gst_play_sink_get_sink       (GstPlaySink * playsink, GstPlaySinkType type);
 
-void             gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-void             gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink);
+
+void             gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-void             gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis);
+GstElement *     gst_play_sink_get_vis_plugin (GstPlaySink * playsink);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -130,6 +143,17 @@
 #endif
 
 
+void             gst_play_sink_set_font_desc  (GstPlaySink *playsink, const gchar * desc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gchar *          gst_play_sink_get_font_desc  (GstPlaySink *playsink);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 GstBuffer *      gst_play_sink_get_last_frame (GstPlaySink * playsink);
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gst_plugins_base/gst/playback/gstqueue2.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstqueue2.c	Fri Apr 16 15:15:52 2010 +0300
@@ -27,8 +27,8 @@
  * @short_description: Asynchronous data queue.
  *
  * Data is queued until one of the limits specified by the
- * #GstQueue:max-size-buffers, #GstQueue:max-size-bytes and/or
- * #GstQueue:max-size-time properties has been reached. Any attempt to push
+ * #GstQueue2:max-size-buffers, #GstQueue2:max-size-bytes and/or
+ * #GstQueue2:max-size-time properties has been reached. Any attempt to push
  * more buffers into the queue will block the pushing thread until more space
  * becomes available.
  *
@@ -36,16 +36,22 @@
  * processing on sink and source pad.
  *
  * You can query how many buffers are queued by reading the
- * #GstQueue:current-level-buffers property.
+ * #GstQueue2:current-level-buffers property.
  *
  * The default queue size limits are 100 buffers, 2MB of data, or
  * two seconds worth of data, whichever is reached first.
  *
- * If you set temp-location, the element will buffer data on the file
- * specified by it. By using this, it will buffer the entire 
- * stream data on the file independently of the queue size limits, they
- * will only be used for buffering statistics.
+ * If you set temp-tmpl to a value such as /tmp/gstreamer-XXXXXX, the element
+ * will allocate a random free filename and buffer data in the file.
+ * By using this, it will buffer the entire stream data on the file independently
+ * of the queue size limits, they will only be used for buffering statistics.
  *
+ * Since 0.10.24, setting the temp-location property with a filename is deprecated
+ * because it's impossible to securely open a temporary file in this way. The
+ * property will still be used to notify the application of the allocated
+ * filename, though.
+ *
+ * Last reviewed on 2009-07-10 (0.10.24)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -57,9 +63,16 @@
 #include <gst/gst.h>
 #include <gst/gst-i18n-plugin.h>
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
+#ifdef G_OS_WIN32
+#include <io.h>                 /* lseek, open, close, read */
+#undef lseek
+#define lseek _lseeki64
+#undef off_t
+#define off_t guint64
+#else
+#include <unistd.h>
 #endif
+
 static const GstElementDetails gst_queue_details = GST_ELEMENT_DETAILS ("Queue",
     "Generic",
     "Simple data queue",
@@ -96,7 +109,7 @@
 
 /* other defines */
 #define DEFAULT_BUFFER_SIZE 4096
-#define QUEUE_IS_USING_TEMP_FILE(queue) (queue->temp_location != NULL)
+#define QUEUE_IS_USING_TEMP_FILE(queue) ((queue)->temp_location_set || (queue)->temp_template != NULL)
 
 enum
 {
@@ -111,6 +124,7 @@
   PROP_USE_RATE_ESTIMATE,
   PROP_LOW_PERCENT,
   PROP_HIGH_PERCENT,
+  PROP_TEMP_TEMPLATE,
   PROP_TEMP_LOCATION
 };
 
@@ -199,10 +213,13 @@
   GCond *item_del;              /* signals space now available for writing */
 
   /* temp location stuff */
+  gchar *temp_template;
+  gboolean temp_location_set;
   gchar *temp_location;
   FILE *temp_file;
   guint64 writing_pos;
   guint64 reading_pos;
+  guint64 max_reading_pos;
   /* we need this to send the first new segment event of the stream
    * because we can't save it on the file */
   gboolean segment_event_received;
@@ -228,7 +245,7 @@
                       queue->cur_level.time, \
                       queue->max_level.time, \
                       (guint64) (QUEUE_IS_USING_TEMP_FILE(queue) ? \
-                        queue->writing_pos - queue->reading_pos : \
+                        queue->writing_pos - queue->max_reading_pos : \
                         queue->queue->length))
 
 #define GST_QUEUE_MUTEX_LOCK(q) G_STMT_START {                          \
@@ -367,50 +384,60 @@
   g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
       g_param_spec_uint ("current-level-bytes", "Current level (kB)",
           "Current amount of data in the queue (bytes)",
-          0, G_MAXUINT, 0, G_PARAM_READABLE));
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BUFFERS,
       g_param_spec_uint ("current-level-buffers", "Current level (buffers)",
           "Current number of buffers in the queue",
-          0, G_MAXUINT, 0, G_PARAM_READABLE));
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME,
       g_param_spec_uint64 ("current-level-time", "Current level (ns)",
           "Current amount of data in the queue (in ns)",
-          0, G_MAXUINT64, 0, G_PARAM_READABLE));
+          0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES,
       g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
           "Max. amount of data in the queue (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, G_PARAM_READWRITE));
+          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS,
       g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
-          "Max. number of buffers in the queue (0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS, G_PARAM_READWRITE));
+          "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
+          DEFAULT_MAX_SIZE_BUFFERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME,
       g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
-          "Max. amount of data in the queue (in ns, 0=disable)",
-          0, G_MAXUINT64, DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE));
+          "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
+          DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_USE_BUFFERING,
       g_param_spec_boolean ("use-buffering", "Use buffering",
           "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds",
-          DEFAULT_USE_BUFFERING, G_PARAM_READWRITE));
+          DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_USE_RATE_ESTIMATE,
       g_param_spec_boolean ("use-rate-estimate", "Use Rate Estimate",
           "Estimate the bitrate of the stream to calculate time level",
-          DEFAULT_USE_RATE_ESTIMATE, G_PARAM_READWRITE));
+          DEFAULT_USE_RATE_ESTIMATE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_LOW_PERCENT,
       g_param_spec_int ("low-percent", "Low percent",
-          "Low threshold for buffering to start",
-          0, 100, DEFAULT_LOW_PERCENT, G_PARAM_READWRITE));
+          "Low threshold for buffering to start", 0, 100, DEFAULT_LOW_PERCENT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT,
       g_param_spec_int ("high-percent", "High percent",
-          "High threshold for buffering to finish",
-          0, 100, DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE));
+          "High threshold for buffering to finish", 0, 100,
+          DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TEMP_TEMPLATE,
+      g_param_spec_string ("temp-template", "Temporary File Template",
+          "File template to store temporary files in, should contain directory "
+          "and XXXXXX. (NULL == disabled)",
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION,
       g_param_spec_string ("temp-location", "Temporary File Location",
-          "Location of a temporary file to store data in",
-          NULL, G_PARAM_READWRITE));
+          "Location to store temporary files in (Deprecated: Only read this "
+          "property, use temp-tmpl to configure the name template)",
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&srctemplate));
@@ -487,8 +514,9 @@
   queue->queue = g_queue_new ();
 
   /* tempfile related */
+  queue->temp_template = NULL;
   queue->temp_location = NULL;
-  queue->temp_file = NULL;
+  queue->temp_location_set = FALSE;
 
   GST_DEBUG_OBJECT (queue,
       "initialized queue's not_empty & not_full conditions");
@@ -516,8 +544,8 @@
   g_timer_destroy (queue->out_timer);
 
   /* temp_file path cleanup  */
-  if (queue->temp_location != NULL)
-    g_free (queue->temp_location);
+  g_free (queue->temp_template);
+  g_free (queue->temp_location);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -689,15 +717,27 @@
     }
   }
   if (post) {
+    GstMessage *message;
+    GstBufferingMode mode;
+
     /* scale to high percent so that it becomes the 100% mark */
     percent = percent * 100 / queue->high_percent;
     /* clip */
     if (percent > 100)
       percent = 100;
 
+    if (QUEUE_IS_USING_TEMP_FILE (queue))
+      mode = GST_BUFFERING_DOWNLOAD;
+    else
+      mode = GST_BUFFERING_STREAM;
+
     GST_DEBUG_OBJECT (queue, "buffering %d percent", percent);
-    gst_element_post_message (GST_ELEMENT_CAST (queue),
-        gst_message_new_buffering (GST_OBJECT_CAST (queue), percent));
+    message = gst_message_new_buffering (GST_OBJECT_CAST (queue), percent);
+    gst_message_set_buffering_stats (message, mode,
+        queue->byte_in_rate, queue->byte_out_rate, -1);
+
+    gst_element_post_message (GST_ELEMENT_CAST (queue), message);
+
   } else {
     GST_DEBUG_OBJECT (queue, "filled %d percent", percent);
   }
@@ -800,6 +840,10 @@
     queue->last_out_elapsed = elapsed;
     queue->bytes_out = 0;
   }
+  if (queue->byte_in_rate > 0.0) {
+    queue->cur_level.rate_time =
+        queue->cur_level.bytes / queue->byte_in_rate * GST_SECOND;
+  }
   GST_DEBUG_OBJECT (queue, "rates: out %f, time %" GST_TIME_FORMAT,
       queue->byte_out_rate, GST_TIME_ARGS (queue->cur_level.rate_time));
 }
@@ -811,7 +855,13 @@
   guint8 *data;
   int ret;
 
+#ifdef HAVE_FSEEKO
+  fseeko (queue->temp_file, (off_t) queue->writing_pos, SEEK_SET);
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
+  lseek (fileno (queue->temp_file), (off_t) queue->writing_pos, SEEK_SET);
+#else
   fseek (queue->temp_file, queue->writing_pos, SEEK_SET);
+#endif
 
   data = GST_BUFFER_DATA (buffer);
   size = GST_BUFFER_SIZE (buffer);
@@ -822,6 +872,11 @@
     GST_ERROR_OBJECT (queue, "fwrite returned error");
   }
   queue->writing_pos += size;
+
+  if (queue->writing_pos > queue->max_reading_pos)
+    queue->cur_level.bytes = queue->writing_pos - queue->max_reading_pos;
+  else
+    queue->cur_level.bytes = 0;
 }
 
 /* see if there is enough data in the file to read a full buffer */
@@ -856,7 +911,7 @@
 #ifdef HAVE_FSEEKO
   if (fseeko (queue->temp_file, (off_t) offset, SEEK_SET) != 0)
     goto seek_failed;
-#elif defined (G_OS_UNIX)
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
   if (lseek (fileno (queue->temp_file), (off_t) offset,
           SEEK_SET) == (off_t) - 1)
     goto seek_failed;
@@ -889,6 +944,12 @@
   *buffer = buf;
 
   queue->reading_pos = offset + length;
+  queue->max_reading_pos = MAX (queue->max_reading_pos, queue->reading_pos);
+
+  if (queue->writing_pos > queue->max_reading_pos)
+    queue->cur_level.bytes = queue->writing_pos - queue->max_reading_pos;
+  else
+    queue->cur_level.bytes = 0;
 
   return GST_FLOW_OK;
 
@@ -951,33 +1012,74 @@
 static gboolean
 gst_queue_open_temp_location_file (GstQueue * queue)
 {
-  /* nothing to do */
-  if (queue->temp_location == NULL)
-    goto no_filename;
+  gint fd = -1;
+  gchar *name = NULL;
+
+  GST_DEBUG_OBJECT (queue, "opening temp file %s", queue->temp_template);
+
+  /* we have two cases:
+   * - temp_location was set to something !NULL (Deprecated). in this case we
+   *   open the specified filename.
+   * - temp_template was set, allocate a filename and open that filename
+   */
+  if (!queue->temp_location_set) {
+    /* nothing to do */
+    if (queue->temp_template == NULL)
+      goto no_directory;
 
-  /* open the file for update/writing */
-  queue->temp_file = g_fopen (queue->temp_location, "wb+");
-  /* error creating file */
-  if (queue->temp_file == NULL)
-    goto open_failed;
+    /* make copy of the template, we don't want to change this */
+    name = g_strdup (queue->temp_template);
+    fd = g_mkstemp (name);
+    if (fd == -1)
+      goto mkstemp_failed;
+
+    /* open the file for update/writing */
+    queue->temp_file = fdopen (fd, "wb+");
+    /* error creating file */
+    if (queue->temp_file == NULL)
+      goto open_failed;
+
+    g_free (queue->temp_location);
+    queue->temp_location = name;
+
+    g_object_notify (G_OBJECT (queue), "temp-location");
+  } else {
+    /* open the file for update/writing, this is deprecated but we still need to
+     * support it for API/ABI compatibility */
+    queue->temp_file = g_fopen (queue->temp_location, "wb+");
+    /* error creating file */
+    if (queue->temp_file == NULL)
+      goto open_failed;
+  }
 
   queue->writing_pos = 0;
   queue->reading_pos = 0;
+  queue->max_reading_pos = 0;
 
   return TRUE;
 
   /* ERRORS */
-no_filename:
+no_directory:
   {
     GST_ELEMENT_ERROR (queue, RESOURCE, NOT_FOUND,
-        (_("No file name specified.")), (NULL));
+        (_("No Temp directory specified.")), (NULL));
+    return FALSE;
+  }
+mkstemp_failed:
+  {
+    GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ,
+        (_("Could not create temp file \"%s\"."), queue->temp_template),
+        GST_ERROR_SYSTEM);
+    g_free (name);
     return FALSE;
   }
 open_failed:
   {
     GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ,
-        (_("Could not open file \"%s\" for reading."), queue->temp_location),
-        GST_ERROR_SYSTEM);
+        (_("Could not open file \"%s\" for reading."), name), GST_ERROR_SYSTEM);
+    g_free (name);
+    if (fd != -1)
+      close (fd);
     return FALSE;
   }
 }
@@ -989,6 +1091,8 @@
   if (queue->temp_file == NULL)
     return;
 
+  GST_DEBUG_OBJECT (queue, "closing temp file");
+
   /* we don't remove the file so that the application can use it as a cache
    * later on */
   fflush (queue->temp_file);
@@ -998,11 +1102,25 @@
 }
 
 static void
+gst_queue_flush_temp_file (GstQueue * queue)
+{
+  if (queue->temp_file == NULL)
+    return;
+
+  GST_DEBUG_OBJECT (queue, "flushing temp file");
+
+  queue->temp_file = g_freopen (queue->temp_location, "wb+", queue->temp_file);
+
+  queue->writing_pos = 0;
+  queue->reading_pos = 0;
+  queue->max_reading_pos = 0;
+}
+
+static void
 gst_queue_locked_flush (GstQueue * queue)
 {
   if (QUEUE_IS_USING_TEMP_FILE (queue)) {
-    gst_queue_close_temp_location_file (queue);
-    gst_queue_open_temp_location_file (queue);
+    gst_queue_flush_temp_file (queue);
   } else {
     while (!g_queue_is_empty (queue->queue)) {
       GstMiniObject *data = g_queue_pop_head (queue->queue);
@@ -1039,6 +1157,7 @@
     queue->cur_level.buffers++;
     queue->cur_level.bytes += size;
     queue->bytes_in += size;
+
     /* apply new buffer to segment stats */
     apply_buffer (queue, buffer, &queue->sink_segment);
     /* update the byterate stats */
@@ -1068,7 +1187,10 @@
             goto unexpected_event;
 
           queue->segment_event_received = TRUE;
+          if (queue->starting_segment != NULL)
+            gst_event_unref (queue->starting_segment);
           queue->starting_segment = event;
+          item = NULL;
         }
         /* a new segment allows us to accept more buffers if we got UNEXPECTED
          * from downstream */
@@ -1092,6 +1214,9 @@
 
     if (!QUEUE_IS_USING_TEMP_FILE (queue))
       g_queue_push_tail (queue->queue, item);
+    else
+      gst_mini_object_unref (GST_MINI_OBJECT_CAST (item));
+
     GST_QUEUE_SIGNAL_ADD (queue);
   }
 
@@ -1266,7 +1391,7 @@
     return FALSE;
 
   if (QUEUE_IS_USING_TEMP_FILE (queue)) {
-    return queue->writing_pos == queue->reading_pos;
+    return queue->writing_pos == queue->max_reading_pos;
   } else {
     if (queue->queue->length == 0)
       return TRUE;
@@ -1288,6 +1413,10 @@
   if (QUEUE_IS_USING_TEMP_FILE (queue))
     return FALSE;
 
+  /* we are never filled when we have no buffers at all */
+  if (queue->cur_level.buffers == 0)
+    return FALSE;
+
 #define CHECK_FILLED(format) ((queue->max_level.format) > 0 && \
 		(queue->cur_level.format) >= (queue->max_level.format))
 
@@ -1548,8 +1677,14 @@
       event, GST_EVENT_TYPE_NAME (event));
 #endif
 
-  /* just forward upstream */
-  res = gst_pad_push_event (queue->sinkpad, event);
+  if (!QUEUE_IS_USING_TEMP_FILE (queue)) {
+    /* just forward upstream */
+    res = gst_pad_push_event (queue->sinkpad, event);
+  } else {
+    /* when using a temp file, we unblock the pending read */
+    res = TRUE;
+    gst_event_unref (event);
+  }
 
   return res;
 }
@@ -1605,15 +1740,7 @@
     }
     case GST_QUERY_DURATION:
     {
-      GST_DEBUG_OBJECT (queue, "waiting for preroll in duration query");
-
-      GST_QUEUE_MUTEX_LOCK (queue);
-      /* we have to wait until the upstream element is at least paused, which
-       * happened when we received a first item. */
-      while (gst_queue_is_empty (queue)) {
-        GST_QUEUE_WAIT_ADD_CHECK (queue, flushing);
-      }
-      GST_QUEUE_MUTEX_UNLOCK (queue);
+      GST_DEBUG_OBJECT (queue, "doing peer query");
 
       if (!gst_queue_peer_query (queue, queue->sinkpad, query))
         goto peer_failed;
@@ -1621,6 +1748,59 @@
       GST_DEBUG_OBJECT (queue, "peer query success");
       break;
     }
+    case GST_QUERY_BUFFERING:
+    {
+      GstFormat format;
+
+      GST_DEBUG_OBJECT (queue, "query buffering");
+
+      if (!QUEUE_IS_USING_TEMP_FILE (queue)) {
+        /* no temp file, just forward to the peer */
+        if (!gst_queue_peer_query (queue, queue->sinkpad, query))
+          goto peer_failed;
+        GST_DEBUG_OBJECT (queue, "buffering forwarded to peer");
+      } else {
+        gint64 start, stop;
+
+        gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL);
+
+        switch (format) {
+          case GST_FORMAT_PERCENT:
+          {
+            gint64 duration;
+            GstFormat peer_fmt;
+
+            peer_fmt = GST_FORMAT_BYTES;
+
+            if (!gst_pad_query_peer_duration (queue->sinkpad, &peer_fmt,
+                    &duration))
+              goto peer_failed;
+
+            GST_DEBUG_OBJECT (queue, "duration %" G_GINT64_FORMAT ", writing %"
+                G_GINT64_FORMAT, duration, queue->writing_pos);
+
+            start = 0;
+            /* get our available data relative to the duration */
+            if (duration != -1)
+              stop = GST_FORMAT_PERCENT_MAX * queue->writing_pos / duration;
+            else
+              stop = -1;
+            break;
+          }
+          case GST_FORMAT_BYTES:
+            start = 0;
+            stop = queue->writing_pos;
+            break;
+          default:
+            start = -1;
+            stop = -1;
+            break;
+        }
+        gst_query_set_buffering_percent (query, queue->is_buffering, 100);
+        gst_query_set_buffering_range (query, format, start, stop, -1);
+      }
+      break;
+    }
     default:
       /* peer handled other queries */
       if (!gst_queue_peer_query (queue, queue->sinkpad, query))
@@ -1636,12 +1816,6 @@
     GST_DEBUG_OBJECT (queue, "failed peer query");
     return FALSE;
   }
-flushing:
-  {
-    GST_DEBUG_OBJECT (queue, "flushing while waiting for query");
-    GST_QUEUE_MUTEX_UNLOCK (queue);
-    return FALSE;
-  }
 }
 
 static GstFlowReturn
@@ -1681,8 +1855,10 @@
   gboolean ret;
 
   queue = GST_QUEUE (gst_pad_get_parent (pad));
+
   /* we can operate in pull mode when we are using a tempfile */
   ret = QUEUE_IS_USING_TEMP_FILE (queue);
+
   gst_object_unref (GST_OBJECT (queue));
 
   return ret;
@@ -1856,8 +2032,8 @@
 #define QUEUE_THRESHOLD_CHANGE(q)\
   g_cond_signal (queue->item_add);
 
-static gboolean
-gst_queue_set_temp_location (GstQueue * queue, const gchar * location)
+static void
+gst_queue_set_temp_template (GstQueue * queue, const gchar * template)
 {
   GstState state;
 
@@ -1869,19 +2045,16 @@
   GST_OBJECT_UNLOCK (queue);
 
   /* set new location */
-  g_free (queue->temp_location);
-  queue->temp_location = g_strdup (location);
+  g_free (queue->temp_template);
+  queue->temp_template = g_strdup (template);
 
-  g_object_notify (G_OBJECT (queue), "temp-location");
-
-  return TRUE;
+  return;
 
 /* ERROR */
 wrong_state:
   {
-    GST_DEBUG_OBJECT (queue, "setting temp-location in wrong state");
+    GST_WARNING_OBJECT (queue, "setting temp-template property in wrong state");
     GST_OBJECT_UNLOCK (queue);
-    return FALSE;
   }
 }
 
@@ -1923,8 +2096,15 @@
     case PROP_HIGH_PERCENT:
       queue->high_percent = g_value_get_int (value);
       break;
+    case PROP_TEMP_TEMPLATE:
+      gst_queue_set_temp_template (queue, g_value_get_string (value));
+      break;
     case PROP_TEMP_LOCATION:
-      gst_queue_set_temp_location (queue, g_value_dup_string (value));
+      g_free (queue->temp_location);
+      queue->temp_location = g_value_dup_string (value);
+      /* you can set the property back to NULL to make it use the temp-tmpl
+       * property. */
+      queue->temp_location_set = queue->temp_location != NULL;
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1973,6 +2153,9 @@
     case PROP_HIGH_PERCENT:
       g_value_set_int (value, queue->high_percent);
       break;
+    case PROP_TEMP_TEMPLATE:
+      g_value_set_string (value, queue->temp_template);
+      break;
     case PROP_TEMP_LOCATION:
       g_value_set_string (value, queue->temp_location);
       break;
@@ -1995,6 +2178,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
   return gst_element_register (plugin, "queue2", GST_RANK_NONE, GST_TYPE_QUEUE);
--- a/gst_plugins_base/gst/playback/gstscreenshot.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gstscreenshot.c	Fri Apr 16 15:15:52 2010 +0300
@@ -181,6 +181,7 @@
         g_return_val_if_reached (NULL);
       }
     }
+    gst_message_unref (msg);
   } else {
     g_warning ("Could not take screenshot: %s", "timeout during conversion");
     result = NULL;
--- a/gst_plugins_base/gst/playback/gststreaminfo.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gststreaminfo.c	Fri Apr 16 15:15:52 2010 +0300
@@ -132,27 +132,29 @@
   g_object_class_install_property (gobject_klass, ARG_PAD,
       g_param_spec_object ("object", "object",
           "Source Pad or object of the stream", GST_TYPE_OBJECT,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_TYPE,
       g_param_spec_enum ("type", "Type", "Type of the stream",
-          GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN, G_PARAM_READABLE));
+          GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_DECODER,
       g_param_spec_string ("decoder", "Decoder",
-          "The decoder used to decode the stream", NULL, G_PARAM_READABLE));
+          "The decoder used to decode the stream", NULL,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_MUTE,
       g_param_spec_boolean ("mute", "Mute", "Mute or unmute this stream", FALSE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_CAPS,
       g_param_spec_boxed ("caps", "Capabilities",
           "Capabilities (or type) of this stream", GST_TYPE_CAPS,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_LANG_CODE,
       g_param_spec_string ("language-code", "Language code",
-          "Language code for this stream, conforming to ISO-639-1",
-          NULL, G_PARAM_READABLE));
+          "Language code for this stream, conforming to ISO-639-1", NULL,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_klass, ARG_CODEC,
-      g_param_spec_string ("codec", "Codec",
-          "Codec used to encode the stream", NULL, G_PARAM_READABLE));
+      g_param_spec_string ("codec", "Codec", "Codec used to encode the stream",
+          NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   gst_stream_info_signals[SIGNAL_MUTED] =
       g_signal_new ("muted", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
--- a/gst_plugins_base/gst/playback/gststreamselector.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gststreamselector.c	Fri Apr 16 15:15:52 2010 +0300
@@ -28,10 +28,6 @@
 
 #include "gststreamselector.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (stream_selector_debug);
 #define GST_CAT_DEFAULT stream_selector_debug
 
@@ -147,7 +143,7 @@
     };
 
     selector_pad_type =
-        g_type_register_static (GST_TYPE_PAD, "GstSelectorPad",
+        g_type_register_static (GST_TYPE_PAD, "GstPlaybinSelectorPad",
         &selector_pad_info, 0);
   }
   return selector_pad_type;
@@ -169,11 +165,12 @@
   g_object_class_install_property (gobject_class, PROP_PAD_TAGS,
       g_param_spec_boxed ("tags", "Tags",
           "The currently active tags on the pad", GST_TYPE_TAG_LIST,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE,
       g_param_spec_boolean ("active", "Active",
-          "If the pad is currently active", FALSE, G_PARAM_READABLE));
+          "If the pad is currently active", FALSE,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -257,12 +254,14 @@
   gboolean forward = TRUE;
   GstStreamSelector *sel;
   GstSelectorPad *selpad;
+  GstPad *active_sinkpad;
 
   sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad));
   selpad = GST_SELECTOR_PAD_CAST (pad);
 
   /* only forward if we are dealing with the active sinkpad */
-  forward = gst_stream_selector_is_active_sinkpad (sel, pad);
+  active_sinkpad = gst_stream_selector_activate_sinkpad (sel, pad);
+  forward = (active_sinkpad == pad);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_STOP:
@@ -519,10 +518,12 @@
 
   g_object_class_install_property (gobject_class, PROP_N_PADS,
       g_param_spec_uint ("n-pads", "Number of Pads",
-          "The number of sink pads", 0, G_MAXUINT, 0, G_PARAM_READABLE));
+          "The number of sink pads", 0, G_MAXUINT, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
       g_param_spec_object ("active-pad", "Active Pad",
-          "The currently active sink pad", GST_TYPE_PAD, G_PARAM_READWRITE));
+          "The currently active sink pad", GST_TYPE_PAD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->request_new_pad = gst_stream_selector_request_new_pad;
   gstelement_class->release_pad = gst_stream_selector_release_pad;
--- a/gst_plugins_base/gst/playback/gsturidecodebin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/gsturidecodebin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,7 +19,6 @@
 
 /**
  * SECTION:element-uridecodebin
- * @short_description: decoder for an uri
  *
  * Decodes data from a URI into raw media.
  */
@@ -33,12 +32,10 @@
 #include <gst/gst.h>
 #include <gst/gst-i18n-plugin.h>
 
+#include "gstfactorylists.h"
 #include "gstplay-marshal.h"
 #include "gstplay-enum.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
 #define GST_TYPE_URI_DECODE_BIN \
   (gst_uri_decode_bin_get_type())
 #define GST_URI_DECODE_BIN(obj) \
@@ -49,23 +46,43 @@
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_URI_DECODE_BIN))
 #define GST_IS_URI_DECODE_BIN_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_URI_DECODE_BIN))
+#define GST_URI_DECODE_BIN_CAST(obj) ((GstURIDecodeBin *) (obj))
 
 typedef struct _GstURIDecodeBin GstURIDecodeBin;
 typedef struct _GstURIDecodeBinClass GstURIDecodeBinClass;
 
+#define GST_URI_DECODE_BIN_GET_LOCK(dec) (((GstURIDecodeBin*)(dec))->lock)
+#define GST_URI_DECODE_BIN_LOCK(dec) (g_mutex_lock(GST_URI_DECODE_BIN_GET_LOCK(dec)))
+#define GST_URI_DECODE_BIN_UNLOCK(dec) (g_mutex_unlock(GST_URI_DECODE_BIN_GET_LOCK(dec)))
+
+/**
+ * GstURIDecodeBin
+ *
+ * uridecodebin element struct
+ */
 struct _GstURIDecodeBin
 {
   GstBin parent_instance;
 
+  GMutex *lock;                 /* lock for constructing */
+
+  GValueArray *factories;       /* factories we can use for selecting elements */
+
   gchar *uri;
   guint connection_speed;
   GstCaps *caps;
   gchar *encoding;
 
   gboolean is_stream;
+  gboolean need_queue;
+  guint64 buffer_duration;      /* When streaming, buffer duration (ns) */
+  guint buffer_size;            /* When streaming, buffer size (bytes) */
+  gboolean download;
+
   GstElement *source;
-  GstElement *queue;
-  GSList *decoders;
+  GstElement *typefind;
+  guint have_type_id;           /* have-type signal id from typefind */
+  GSList *decodebins;
   GSList *srcpads;
   gint numpads;
 
@@ -73,6 +90,8 @@
   guint src_np_sig_id;          /* new-pad signal id */
   guint src_nmp_sig_id;         /* no-more-pads signal id */
   gint pending;
+
+  gboolean async_pending;       /* async-start has been emited */
 };
 
 struct _GstURIDecodeBinClass
@@ -123,17 +142,25 @@
 
 /* properties */
 #define DEFAULT_PROP_URI	    NULL
+#define DEFAULT_PROP_SOURCE	    NULL
 #define DEFAULT_CONNECTION_SPEED    0
 #define DEFAULT_CAPS                NULL
 #define DEFAULT_SUBTITLE_ENCODING   NULL
+#define DEFAULT_BUFFER_DURATION     -1
+#define DEFAULT_BUFFER_SIZE         -1
+#define DEFAULT_DOWNLOAD            FALSE
 
 enum
 {
   PROP_0,
   PROP_URI,
+  PROP_SOURCE,
   PROP_CONNECTION_SPEED,
   PROP_CAPS,
   PROP_SUBTITLE_ENCODING,
+  PROP_BUFFER_SIZE,
+  PROP_BUFFER_DURATION,
+  PROP_DOWNLOAD,
   PROP_LAST
 };
 
@@ -212,6 +239,25 @@
   return TRUE;
 }
 
+static GValueArray *
+gst_uri_decode_bin_autoplug_factories (GstElement * element, GstPad * pad,
+    GstCaps * caps)
+{
+  GValueArray *result;
+
+  GST_DEBUG_OBJECT (element, "finding factories");
+
+  /* return all compatible factories for caps */
+  result =
+      gst_factory_list_filter (GST_URI_DECODE_BIN_CAST (element)->factories,
+      caps);
+
+  GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result);
+
+  return result;
+}
+
+
 static void
 gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
 {
@@ -229,28 +275,52 @@
 
   g_object_class_install_property (gobject_class, PROP_URI,
       g_param_spec_string ("uri", "URI", "URI to decode",
-          DEFAULT_PROP_URI, G_PARAM_READWRITE));
+          DEFAULT_PROP_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_SOURCE,
+      g_param_spec_object ("source", "Source", "Source object used",
+          GST_TYPE_ELEMENT, G_PARAM_READABLE));
 
   g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
       g_param_spec_uint ("connection-speed", "Connection Speed",
           "Network connection speed in kbps (0 = unknown)",
-          0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
+          0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_CAPS,
       g_param_spec_boxed ("caps", "Caps",
           "The caps on which to stop decoding. (NULL = default)",
-          GST_TYPE_CAPS, G_PARAM_READWRITE));
+          GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_SUBTITLE_ENCODING,
       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
           "be checked for an encoding to use. If that is not set either, "
-          "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
+          "ISO-8859-15 will be assumed.", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
+      g_param_spec_int ("buffer-size", "Buffer size (bytes)",
+          "Buffer size when buffering network streams",
+          -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_BUFFER_DURATION,
+      g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
+          "Buffer duration when buffering network streams",
+          -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_DOWNLOAD,
+      g_param_spec_boolean ("download", "Download",
+          "Attempt download buffering when buffering network streams",
+          DEFAULT_DOWNLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstURIDecodeBin::unknown-type:
-   * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type.
+   * @bin: The uridecodebin
+   * @pad: the new pad containing caps that cannot be resolved to a 'final'
+   * stream type.
    * @caps: the #GstCaps of the pad that cannot be resolved.
    *
    * This signal is emitted when a pad for which there is no further possible
@@ -259,11 +329,12 @@
   gst_uri_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, unknown_type),
-      NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
+      NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
    * GstURIDecodeBin::autoplug-continue:
+   * @bin: The uridecodebin
    * @pad: The #GstPad.
    * @caps: The #GstCaps found.
    *
@@ -279,16 +350,23 @@
       g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
           autoplug_continue), _gst_boolean_accumulator, NULL,
-      gst_play_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD,
+      gst_play_marshal_BOOLEAN__OBJECT_BOXED, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD,
       GST_TYPE_CAPS);
 
   /**
    * GstURIDecodeBin::autoplug-factories:
+   * @bin: The decodebin
    * @pad: The #GstPad.
    * @caps: The #GstCaps found.
    *
    * This function is emited when an array of possible factories for @caps on
-   * @pad is needed. Decodebin2 will by default return 
+   * @pad is needed. Uridecodebin will by default return an array with all
+   * compatible factories, sorted by rank.
+   *
+   * If this function returns NULL, @pad will be exposed as a final caps.
+   *
+   * If this function returns an empty array, the pad will be considered as
+   * having an unhandled type media type.
    *
    * Returns: a #GValueArray* with a list of factories to try. The factories are
    * by default tried in the returned order or based on the index returned by
@@ -298,29 +376,40 @@
       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
           autoplug_factories), _gst_array_accumulator, NULL,
-      gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
+      gst_play_marshal_BOXED__OBJECT_BOXED, G_TYPE_VALUE_ARRAY, 2,
       GST_TYPE_PAD, GST_TYPE_CAPS);
 
   /**
    * GstURIDecodeBin::autoplug-select:
    * @pad: The #GstPad.
    * @caps: The #GstCaps.
-   * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by
-   * rank (higher ranks come first).
+   * @factory: A #GstElementFactory to use
    *
    * This signal is emitted once uridecodebin has found all the possible
-   * #GstElementFactory that can be used to handle the given @caps.
+   * #GstElementFactory that can be used to handle the given @caps. For each of
+   * those factories, this signal is emited.
+   *
+   * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum
+   * value indicating what decodebin2 should do next.
+   *
+   * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from
+   * @factory.
    *
-   * Returns: A #gint indicating what factory index from the @factories array
-   * that you wish uridecodebin to use for trying to decode the given @caps.
-   * -1 to stop selection of a factory. The default handler always
-   * returns the first possible factory.
+   * A value of #GST_AUTOPLUG_SELECT_EXPOSE will expose @pad without plugging
+   * any element to it.
+   *
+   * A value of #GST_AUTOPLUG_SELECT_SKIP will skip @factory and move to the
+   * next factory.
+   *
+   * Returns: a #GST_TYPE_AUTOPLUG_SELECT_RESULT that indicates the required
+   * operation. The default handler will always return
+   * #GST_AUTOPLUG_SELECT_TRY.
    */
   gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
           autoplug_select), _gst_select_accumulator, NULL,
-      gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
+      gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT,
       GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
       GST_TYPE_ELEMENT_FACTORY);
 
@@ -343,15 +432,26 @@
 
   klass->autoplug_continue =
       GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_continue);
+  klass->autoplug_factories =
+      GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_factories);
 }
 
 static void
 gst_uri_decode_bin_init (GstURIDecodeBin * dec, GstURIDecodeBinClass * klass)
 {
+  /* first filter out the interesting element factories */
+  dec->factories = gst_factory_list_get_elements (GST_FACTORY_LIST_DECODER);
+
+  dec->lock = g_mutex_new ();
+
   dec->uri = g_strdup (DEFAULT_PROP_URI);
   dec->connection_speed = DEFAULT_CONNECTION_SPEED;
   dec->caps = DEFAULT_CAPS;
   dec->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
+
+  dec->buffer_duration = DEFAULT_BUFFER_DURATION;
+  dec->buffer_size = DEFAULT_BUFFER_SIZE;
+  dec->download = DEFAULT_DOWNLOAD;
 }
 
 static void
@@ -359,13 +459,40 @@
 {
   GstURIDecodeBin *dec = GST_URI_DECODE_BIN (obj);
 
+  g_mutex_free (dec->lock);
   g_free (dec->uri);
   g_free (dec->encoding);
+  if (dec->factories)
+    g_value_array_free (dec->factories);
+  if (dec->caps)
+    gst_caps_unref (dec->caps);
 
   G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
 static void
+gst_uri_decode_bin_set_encoding (GstURIDecodeBin * dec, const gchar * encoding)
+{
+  GSList *walk;
+
+  GST_URI_DECODE_BIN_LOCK (dec);
+
+  /* set property first */
+  GST_OBJECT_LOCK (dec);
+  g_free (dec->encoding);
+  dec->encoding = g_strdup (encoding);
+  GST_OBJECT_UNLOCK (dec);
+
+  /* set the property on all decodebins now */
+  for (walk = dec->decodebins; walk; walk = g_slist_next (walk)) {
+    GObject *decodebin = G_OBJECT (walk->data);
+
+    g_object_set (decodebin, "subtitle-encoding", encoding, NULL);
+  }
+  GST_URI_DECODE_BIN_UNLOCK (dec);
+}
+
+static void
 gst_uri_decode_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -391,10 +518,16 @@
       GST_OBJECT_UNLOCK (dec);
       break;
     case PROP_SUBTITLE_ENCODING:
-      GST_OBJECT_LOCK (dec);
-      g_free (dec->encoding);
-      dec->encoding = g_value_dup_string (value);
-      GST_OBJECT_UNLOCK (dec);
+      gst_uri_decode_bin_set_encoding (dec, g_value_get_string (value));
+      break;
+    case PROP_BUFFER_SIZE:
+      dec->buffer_size = g_value_get_int (value);
+      break;
+    case PROP_BUFFER_DURATION:
+      dec->buffer_duration = g_value_get_int64 (value);
+      break;
+    case PROP_DOWNLOAD:
+      dec->download = g_value_get_boolean (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -414,6 +547,11 @@
       g_value_set_string (value, dec->uri);
       GST_OBJECT_UNLOCK (dec);
       break;
+    case PROP_SOURCE:
+      GST_OBJECT_LOCK (dec);
+      g_value_set_object (value, dec->source);
+      GST_OBJECT_UNLOCK (dec);
+      break;
     case PROP_CONNECTION_SPEED:
       GST_OBJECT_LOCK (dec);
       g_value_set_uint (value, dec->connection_speed / 1000);
@@ -429,12 +567,50 @@
       g_value_set_string (value, dec->encoding);
       GST_OBJECT_UNLOCK (dec);
       break;
+    case PROP_BUFFER_SIZE:
+      GST_OBJECT_LOCK (dec);
+      g_value_set_int (value, dec->buffer_size);
+      GST_OBJECT_UNLOCK (dec);
+      break;
+    case PROP_BUFFER_DURATION:
+      GST_OBJECT_LOCK (dec);
+      g_value_set_int64 (value, dec->buffer_duration);
+      GST_OBJECT_UNLOCK (dec);
+      break;
+    case PROP_DOWNLOAD:
+      g_value_set_boolean (value, dec->download);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
 
+static void
+do_async_start (GstURIDecodeBin * dbin)
+{
+  GstMessage *message;
+
+  dbin->async_pending = TRUE;
+
+  message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE);
+  parent_class->handle_message (GST_BIN_CAST (dbin), message);
+}
+
+static void
+do_async_done (GstURIDecodeBin * dbin)
+{
+  GstMessage *message;
+
+  if (dbin->async_pending) {
+    GST_DEBUG_OBJECT (dbin, "posting ASYNC_DONE");
+    message = gst_message_new_async_done (GST_OBJECT_CAST (dbin));
+    parent_class->handle_message (GST_BIN_CAST (dbin), message);
+
+    dbin->async_pending = FALSE;
+  }
+}
+
 #define DEFAULT_QUEUE_SIZE          (3 * GST_SECOND)
 #define DEFAULT_QUEUE_MIN_THRESHOLD ((DEFAULT_QUEUE_SIZE * 30) / 100)
 #define DEFAULT_QUEUE_THRESHOLD     ((DEFAULT_QUEUE_SIZE * 95) / 100)
@@ -474,7 +650,7 @@
   /* setup phase */
   GST_DEBUG_OBJECT (element, "no more pads, %d pending", decoder->pending);
 
-  GST_OBJECT_LOCK (decoder);
+  GST_URI_DECODE_BIN_LOCK (decoder);
   final = (decoder->pending == 0);
 
   /* nothing pending, we can exit */
@@ -490,7 +666,7 @@
   final = (decoder->pending == 0);
 
 done:
-  GST_OBJECT_UNLOCK (decoder);
+  GST_URI_DECODE_BIN_UNLOCK (decoder);
 
   if (final)
     gst_element_no_more_pads (GST_ELEMENT_CAST (decoder));
@@ -531,10 +707,10 @@
   GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>. Last: %d",
       GST_PAD_NAME (pad), last);
 
-  GST_OBJECT_LOCK (decoder);
+  GST_URI_DECODE_BIN_LOCK (decoder);
   padname = g_strdup_printf ("src%d", decoder->numpads);
   decoder->numpads++;
-  GST_OBJECT_UNLOCK (decoder);
+  GST_URI_DECODE_BIN_UNLOCK (decoder);
 
   newpad = gst_ghost_pad_new (padname, pad);
   g_free (padname);
@@ -554,6 +730,10 @@
   GST_DEBUG_OBJECT (element, "pad removed name: <%s:%s>",
       GST_DEBUG_PAD_NAME (pad));
 
+  /* we only care about srcpads */
+  if (!GST_PAD_IS_SRC (pad))
+    return;
+
   if (!(ghost = g_object_get_data (G_OBJECT (pad), "uridecodebin.ghostpad")))
     goto no_ghost;
 
@@ -587,12 +767,27 @@
   return FALSE;
 }
 
+static gboolean
+array_has_uri_value (const gchar * values[], const gchar * value)
+{
+  gint i;
+
+  for (i = 0; values[i]; i++) {
+    if (!g_ascii_strncasecmp (value, values[i], strlen (values[i])))
+      return TRUE;
+  }
+  return FALSE;
+}
+
 /* list of URIs that we consider to be streams and that need buffering.
  * We have no mechanism yet to figure this out with a query. */
 static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
-  "mmsu://", "mmst://", NULL
+  "mmsu://", "mmst://", "fd://", NULL
 };
 
+/* list of URIs that need a queue because they are pretty bursty */
+static const gchar *queue_uris[] = { "cdda://", NULL };
+
 /* blacklisted URIs, we know they will always fail. */
 static const gchar *blacklisted_uris[] = { NULL };
 
@@ -604,15 +799,23 @@
 };
 #endif
 
-/* mime types we consider raw media */
-static const gchar *raw_mimes[] = {
-  "audio/x-raw", "video/x-raw", NULL
+/* media types we consider raw media */
+static const gchar *raw_media[] = {
+  "audio/x-raw", "video/x-raw", "text/plain", "text/x-pango-markup",
+  "video/x-dvd-subpicture", "subpicture/x-", NULL
 };
 
-#define IS_STREAM_URI(uri)          (array_has_value (stream_uris, uri))
-#define IS_BLACKLISTED_URI(uri)     (array_has_value (blacklisted_uris, uri))
+/* media types we can download */
+static const gchar *download_media[] = {
+  "video/quicktime", "video/x-flv", NULL
+};
+
+#define IS_STREAM_URI(uri)          (array_has_uri_value (stream_uris, uri))
+#define IS_QUEUE_URI(uri)           (array_has_uri_value (queue_uris, uri))
+#define IS_BLACKLISTED_URI(uri)     (array_has_uri_value (blacklisted_uris, uri))
 #define IS_NO_MEDIA_MIME(mime)      (array_has_value (no_media_mimes, mime))
-#define IS_RAW_MIME(mime)           (array_has_value (raw_mimes, mime))
+#define IS_RAW_MEDIA(media)         (array_has_value (raw_media, media))
+#define IS_DOWNLOAD_MEDIA(media)    (array_has_value (download_media, media))
 
 /*
  * Generate and configure a source element.
@@ -625,6 +828,8 @@
   if (!decoder->uri)
     goto no_uri;
 
+  GST_LOG_OBJECT (decoder, "finding source for %s", decoder->uri);
+
   if (!gst_uri_is_valid (decoder->uri))
     goto invalid_uri;
 
@@ -635,13 +840,20 @@
   if (!source)
     goto no_source;
 
+  GST_LOG_OBJECT (decoder, "found source type %s", G_OBJECT_TYPE_NAME (source));
+
   decoder->is_stream = IS_STREAM_URI (decoder->uri);
+  GST_LOG_OBJECT (decoder, "source is stream: %d", decoder->is_stream);
+
+  decoder->need_queue = IS_QUEUE_URI (decoder->uri);
+  GST_LOG_OBJECT (decoder, "source needs queue: %d", decoder->need_queue);
 
   /* make HTTP sources send extra headers so we get icecast
    * metadata in case the stream is an icecast stream */
   if (!strncmp (decoder->uri, "http://", 7) &&
       g_object_class_find_property (G_OBJECT_GET_CLASS (source),
           "iradio-mode")) {
+    GST_LOG_OBJECT (decoder, "configuring iradio-mode");
     g_object_set (source, "iradio-mode", TRUE, NULL);
   }
 
@@ -653,7 +865,13 @@
     g_object_set (source, "connection-speed",
         decoder->connection_speed / 1000, NULL);
   }
-
+  if (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
+          "subtitle-encoding")) {
+    GST_DEBUG_OBJECT (decoder,
+        "setting subtitle-encoding=%s to source element", decoder->encoding);
+    g_object_set (G_OBJECT (source), "subtitle-encoding", decoder->encoding,
+        NULL);
+  }
   return source;
 
   /* ERRORS */
@@ -714,6 +932,8 @@
   if (caps == NULL)
     return FALSE;
 
+  GST_DEBUG_OBJECT (pad, "have caps %" GST_PTR_FORMAT, caps);
+
   capssize = gst_caps_get_size (caps);
   /* no caps, skip and move to the next pad */
   if (capssize == 0 || gst_caps_is_empty (caps) || gst_caps_is_any (caps))
@@ -722,12 +942,14 @@
   /* count the number of raw formats in the caps */
   for (i = 0; i < capssize; ++i) {
     GstStructure *s;
-    const gchar *mime_type;
+    const gchar *media_type;
 
     s = gst_caps_get_structure (caps, i);
-    mime_type = gst_structure_get_name (s);
+    media_type = gst_structure_get_name (s);
 
-    if (IS_RAW_MIME (mime_type))
+    GST_DEBUG_OBJECT (pad, "check media-type %s", media_type);
+
+    if (IS_RAW_MEDIA (media_type))
       ++num_raw;
   }
 
@@ -745,6 +967,7 @@
  * @is_raw: are all pads raw data
  * @have_out: does the source have output
  * @is_dynamic: is this a dynamic source
+ * @use_queue: put a queue before raw output pads
  *
  * Check the source of @decoder and collect information about it.
  *
@@ -761,7 +984,7 @@
  */
 static gboolean
 analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw,
-    gboolean * have_out, gboolean * is_dynamic)
+    gboolean * have_out, gboolean * is_dynamic, gboolean use_queue)
 {
   GstIterator *pads_iter;
   gboolean done = FALSE;
@@ -794,12 +1017,35 @@
         *have_out = TRUE;
 
         /* if FALSE, this pad has no caps and we continue with the next pad. */
-        if (!has_all_raw_caps (pad, is_raw))
+        if (!has_all_raw_caps (pad, is_raw)) {
+          gst_object_unref (pad);
           break;
+        }
 
         /* caps on source pad are all raw, we can add the pad */
-        if (*is_raw)
-          new_decoded_pad_cb (decoder->source, pad, FALSE, decoder);
+        if (*is_raw) {
+          GstElement *outelem;
+
+          if (use_queue) {
+            GstPad *sinkpad;
+
+            /* insert a queue element right before the raw pad */
+            outelem = gst_element_factory_make ("queue2", "queue");
+            gst_bin_add (GST_BIN_CAST (decoder), outelem);
+
+            sinkpad = gst_element_get_static_pad (outelem, "sink");
+            gst_pad_link (pad, sinkpad);
+            gst_object_unref (sinkpad);
+            gst_object_unref (pad);
+
+            /* get the new raw srcpad */
+            pad = gst_element_get_static_pad (outelem, "src");
+          } else {
+            outelem = decoder->source;
+          }
+          new_decoded_pad_cb (outelem, pad, FALSE, decoder);
+        }
+        gst_object_unref (pad);
         break;
     }
   }
@@ -835,15 +1081,15 @@
 {
   GSList *walk;
 
-  for (walk = bin->decoders; walk; walk = g_slist_next (walk)) {
+  for (walk = bin->decodebins; walk; walk = g_slist_next (walk)) {
     GstElement *decoder = GST_ELEMENT_CAST (walk->data);
 
     GST_DEBUG_OBJECT (bin, "removing old decoder element");
     gst_element_set_state (decoder, GST_STATE_NULL);
     gst_bin_remove (GST_BIN_CAST (bin), decoder);
   }
-  g_slist_free (bin->decoders);
-  bin->decoders = NULL;
+  g_slist_free (bin->decodebins);
+  bin->decodebins = NULL;
 }
 
 static void
@@ -891,7 +1137,7 @@
 proxy_autoplug_factories_signal (GstElement * element, GstPad * pad,
     GstCaps * caps, GstURIDecodeBin * dec)
 {
-  GValueArray *result = NULL;
+  GValueArray *result;
 
   g_signal_emit (G_OBJECT (dec),
       gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps,
@@ -926,16 +1172,23 @@
       gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
 }
 
+/* make a decodebin and connect to all the signals */
 static GstElement *
-make_decoder (GstURIDecodeBin * decoder, gboolean use_queue)
+make_decoder (GstURIDecodeBin * decoder)
 {
-  GstElement *result, *decodebin;
+  GstElement *decodebin;
+
+  GST_LOG_OBJECT (decoder, "making new decodebin2");
 
   /* now create the decoder element */
   decodebin = gst_element_factory_make ("decodebin2", NULL);
   if (!decodebin)
     goto no_decodebin;
 
+  /* configure caps if we have any */
+  if (decoder->caps)
+    g_object_set (decodebin, "caps", decoder->caps, NULL);
+
   /* connect signals to proxy */
   g_signal_connect (G_OBJECT (decodebin), "unknown-type",
       G_CALLBACK (proxy_unknown_type_signal), decoder);
@@ -948,34 +1201,6 @@
   g_signal_connect (G_OBJECT (decodebin), "drained",
       G_CALLBACK (proxy_drained_signal), decoder);
 
-  if (use_queue) {
-    GstElement *queue;
-    GstPad *gpad, *pad;
-
-    queue = gst_element_factory_make ("queue2", NULL);
-    if (!queue)
-      goto no_queue2;
-
-    /* configure the queue as a buffering element */
-    g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
-
-    result = gst_bin_new ("source-bin");
-
-    gst_bin_add (GST_BIN_CAST (result), queue);
-    gst_bin_add (GST_BIN_CAST (result), decodebin);
-
-    gst_element_link (queue, decodebin);
-
-    pad = gst_element_get_pad (queue, "sink");
-    gpad = gst_ghost_pad_new (GST_PAD_NAME (pad), pad);
-    gst_object_unref (pad);
-
-    gst_pad_set_active (gpad, TRUE);
-    gst_element_add_pad (GST_ELEMENT_CAST (result), gpad);
-  } else {
-    result = decodebin;
-  }
-
   /* set up callbacks to create the links between decoded data
    * and video/audio/subtitle rendering/output. */
   g_signal_connect (G_OBJECT (decodebin),
@@ -987,13 +1212,16 @@
   g_signal_connect (G_OBJECT (decodebin),
       "unknown-type", G_CALLBACK (unknown_type_cb), decoder);
   g_object_set_data (G_OBJECT (decodebin), "pending", "1");
+  g_object_set (G_OBJECT (decodebin), "subtitle-encoding", decoder->encoding,
+      NULL);
   decoder->pending++;
-
-  gst_bin_add (GST_BIN_CAST (decoder), result);
+  GST_LOG_OBJECT (decoder, "have %d pending dynamic objects", decoder->pending);
 
-  decoder->decoders = g_slist_prepend (decoder->decoders, result);
+  gst_bin_add (GST_BIN_CAST (decoder), decodebin);
 
-  return result;
+  decoder->decodebins = g_slist_prepend (decoder->decodebins, decodebin);
+
+  return decodebin;
 
   /* ERRORS */
 no_decodebin:
@@ -1002,11 +1230,151 @@
         (_("Could not create \"decodebin2\" element.")), (NULL));
     return NULL;
   }
+}
+
+static void
+type_found (GstElement * typefind, guint probability,
+    GstCaps * caps, GstURIDecodeBin * decoder)
+{
+  GstElement *dec_elem, *queue;
+  GstStructure *s;
+  const gchar *media_type;
+
+  GST_DEBUG_OBJECT (decoder, "typefind found caps %" GST_PTR_FORMAT, caps);
+
+  dec_elem = make_decoder (decoder);
+  if (!dec_elem)
+    goto no_decodebin;
+
+  queue = gst_element_factory_make ("queue2", NULL);
+  if (!queue)
+    goto no_queue2;
+
+  g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
+
+  s = gst_caps_get_structure (caps, 0);
+  media_type = gst_structure_get_name (s);
+
+  GST_DEBUG_OBJECT (decoder, "check media-type %s, %d", media_type,
+      decoder->download);
+
+  if (IS_DOWNLOAD_MEDIA (media_type) && decoder->download) {
+    gchar *temp_template, *filename;
+    const gchar *tmp_dir, *prgname;
+
+    tmp_dir = g_get_tmp_dir ();
+    prgname = g_get_prgname ();
+    if (prgname == NULL)
+      prgname = "GStreamer";
+
+    filename = g_strdup_printf ("%s-XXXXXX", prgname);
+
+    /* build our filename */
+    temp_template = g_build_filename (tmp_dir, filename, NULL);
+
+    GST_DEBUG_OBJECT (decoder, "enable download buffering in %s (%s, %s, %s)",
+        temp_template, tmp_dir, prgname, filename);
+
+    /* configure progressive download for selected media types */
+    g_object_set (G_OBJECT (queue), "temp-template", temp_template, NULL);
+
+    g_free (filename);
+    g_free (temp_template);
+  }
+
+  /* Disable max-size-buffers */
+  g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL);
+
+  /* If buffer size or duration are set, set them on the queue2 element */
+  if (decoder->buffer_size != -1)
+    g_object_set (G_OBJECT (queue), "max-size-bytes",
+        decoder->buffer_size, NULL);
+  if (decoder->buffer_duration != -1)
+    g_object_set (G_OBJECT (queue), "max-size-time",
+        decoder->buffer_duration, NULL);
+
+  gst_bin_add (GST_BIN_CAST (decoder), queue);
+
+  if (!gst_element_link_pads (typefind, "src", queue, "sink"))
+    goto could_not_link;
+
+  /* to force caps on the decodebin element and avoid reparsing stuff by
+   * typefind. It also avoids a deadlock in the way typefind activates pads in
+   * the state change */
+  g_object_set (G_OBJECT (dec_elem), "sink-caps", caps, NULL);
+
+  if (!gst_element_link_pads (queue, "src", dec_elem, "sink"))
+    goto could_not_link;
+
+  gst_element_set_state (dec_elem, GST_STATE_PLAYING);
+  gst_element_set_state (queue, GST_STATE_PLAYING);
+
+  do_async_done (decoder);
+
+  return;
+
+  /* ERRORS */
+no_decodebin:
+  {
+    /* error was posted */
+    return;
+  }
+could_not_link:
+  {
+    GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
+        (NULL), ("Can't link typefind to decodebin2 element"));
+    return;
+  }
 no_queue2:
   {
     GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,
         (_("Could not create \"queue2\" element.")), (NULL));
-    return NULL;
+    return;
+  }
+}
+
+/* setup a streaming source. This will first plug a typefind element to the
+ * source. After we find the type, we decide to plug a queue2 and continue to
+ * plug a decodebin2 starting from the found caps */
+static gboolean
+setup_streaming (GstURIDecodeBin * decoder)
+{
+  GstElement *typefind;
+
+  /* now create the decoder element */
+  typefind = gst_element_factory_make ("typefind", NULL);
+  if (!typefind)
+    goto no_typefind;
+
+  gst_bin_add (GST_BIN_CAST (decoder), typefind);
+
+  if (!gst_element_link (decoder->source, typefind))
+    goto could_not_link;
+
+  decoder->typefind = typefind;
+
+  /* connect a signal to find out when the typefind element found
+   * a type */
+  decoder->have_type_id =
+      g_signal_connect (G_OBJECT (decoder->typefind), "have-type",
+      G_CALLBACK (type_found), decoder);
+
+  do_async_start (decoder);
+
+  return TRUE;
+
+  /* ERRORS */
+no_typefind:
+  {
+    GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,
+        (_("Could not create \"typefind\" element.")), (NULL));
+    return FALSE;
+  }
+could_not_link:
+  {
+    GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
+        (NULL), ("Can't link source to typefind element"));
+    return FALSE;
   }
 }
 
@@ -1039,18 +1407,20 @@
   GstElement *decoder;
   gboolean is_raw;
 
+  GST_URI_DECODE_BIN_LOCK (bin);
   GST_DEBUG_OBJECT (bin, "Found new pad %s.%s in source element %s",
       GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
 
   /* if this is a pad with all raw caps, we can expose it */
   if (has_all_raw_caps (pad, &is_raw) && is_raw) {
     /* it's all raw, create output pads. */
+    GST_URI_DECODE_BIN_UNLOCK (bin);
     new_decoded_pad_cb (element, pad, FALSE, bin);
     return;
   }
 
   /* not raw, create decoder */
-  decoder = make_decoder (bin, FALSE);
+  decoder = make_decoder (bin);
   if (!decoder)
     goto no_decodebin;
 
@@ -1061,6 +1431,7 @@
   GST_DEBUG_OBJECT (bin, "linked decoder to new pad");
 
   gst_element_set_state (decoder, GST_STATE_PLAYING);
+  GST_URI_DECODE_BIN_UNLOCK (bin);
 
   return;
 
@@ -1068,12 +1439,14 @@
 no_decodebin:
   {
     /* error was posted */
+    GST_URI_DECODE_BIN_UNLOCK (bin);
     return;
   }
 could_not_link:
   {
     GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION,
         (NULL), ("Can't link source to decoder element"));
+    GST_URI_DECODE_BIN_UNLOCK (bin);
     return;
   }
 }
@@ -1091,6 +1464,8 @@
   /* delete old src */
   remove_source (decoder);
 
+  decoder->pending = 0;
+
   /* create and configure an element that can handle the uri */
   if (!(decoder->source = gen_source_element (decoder)))
     goto no_source;
@@ -1099,6 +1474,9 @@
    * handled by the application right after. */
   gst_bin_add (GST_BIN_CAST (decoder), decoder->source);
 
+  /* notify of the new source used */
+  g_object_notify (G_OBJECT (decoder), "source");
+
   /* remove the old decoders now, if any */
   remove_decoders (decoder);
 
@@ -1106,14 +1484,15 @@
    * if so, we can create streams for the pads and be done with it.
    * Also check that is has source pads, if not, we assume it will
    * do everything itself.  */
-  if (!analyse_source (decoder, &is_raw, &have_out, &is_dynamic))
+  if (!analyse_source (decoder, &is_raw, &have_out, &is_dynamic,
+          decoder->need_queue))
     goto invalid_source;
 
   if (is_raw) {
     GST_DEBUG_OBJECT (decoder, "Source provides all raw data");
     /* source provides raw data, we added the pads and we can now signal a
      * no_more pads because we are done. */
-    /* FIXME, actually do this... */
+    gst_element_no_more_pads (GST_ELEMENT_CAST (decoder));
     return TRUE;
   }
   if (!have_out && !is_dynamic) {
@@ -1135,17 +1514,24 @@
     g_object_set_data (G_OBJECT (decoder->source), "pending", "1");
     decoder->pending++;
   } else {
-    GstElement *dec_elem;
-
-    GST_DEBUG_OBJECT (decoder, "Pluggin decodebin to source");
+    if (decoder->is_stream) {
+      GST_DEBUG_OBJECT (decoder, "Setting up streaming");
+      /* do the stream things here */
+      if (!setup_streaming (decoder))
+        goto streaming_failed;
+    } else {
+      GstElement *dec_elem;
 
-    /* no dynamic source, we can link now */
-    dec_elem = make_decoder (decoder, decoder->is_stream);
-    if (!dec_elem)
-      goto no_decoder;
+      /* no streaming source, we can link now */
+      GST_DEBUG_OBJECT (decoder, "Plugging decodebin to source");
 
-    if (!gst_element_link (decoder->source, dec_elem))
-      goto could_not_link;
+      dec_elem = make_decoder (decoder);
+      if (!dec_elem)
+        goto no_decoder;
+
+      if (!gst_element_link (decoder->source, dec_elem))
+        goto could_not_link;
+    }
   }
   return TRUE;
 
@@ -1166,6 +1552,11 @@
     /* message was posted */
     return FALSE;
   }
+streaming_failed:
+  {
+    /* message was posted */
+    return FALSE;
+  }
 could_not_link:
   {
     GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
@@ -1319,6 +1710,7 @@
   gst_object_unref (item);
   return TRUE;
 }
+
 static void
 decoder_query_duration_done (GstURIDecodeBin * dec, QueryFold * fold)
 {
@@ -1350,6 +1742,7 @@
   gst_object_unref (item);
   return TRUE;
 }
+
 static void
 decoder_query_position_done (GstURIDecodeBin * dec, QueryFold * fold)
 {
@@ -1392,6 +1785,7 @@
   gst_object_unref (item);
   return TRUE;
 }
+
 static void
 decoder_query_latency_done (GstURIDecodeBin * dec, QueryFold * fold)
 {
@@ -1423,6 +1817,7 @@
 
   return TRUE;
 }
+
 static void
 decoder_query_seeking_done (GstURIDecodeBin * dec, QueryFold * fold)
 {
@@ -1571,6 +1966,13 @@
       remove_decoders (decoder);
       remove_pads (decoder);
       remove_source (decoder);
+      do_async_done (decoder);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      GST_DEBUG ("ready to null");
+      remove_decoders (decoder);
+      remove_pads (decoder);
+      remove_source (decoder);
       break;
     default:
       break;
@@ -1601,6 +2003,7 @@
   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       LOCALEDIR);
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
   return gst_element_register (plugin, "uridecodebin", GST_RANK_NONE,
--- a/gst_plugins_base/gst/playback/test.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/test.c	Fri Apr 16 15:15:52 2010 +0300
@@ -42,7 +42,7 @@
   gst_bin_add (GST_BIN (element), sink);
   gst_element_link_pads (conv, "src", sink, "sink");
 
-  pad = gst_element_get_pad (conv, "sink");
+  pad = gst_element_get_static_pad (conv, "sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
   gst_object_unref (pad);
 
@@ -65,7 +65,7 @@
   gst_bin_add (GST_BIN (element), sink);
   gst_element_link_pads (conv, "src", sink, "sink");
 
-  pad = gst_element_get_pad (conv, "sink");
+  pad = gst_element_get_static_pad (conv, "sink");
   gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
   gst_object_unref (pad);
 
@@ -112,7 +112,7 @@
       goto state_error;
 
     /* get the ghostpad of the sink bin */
-    sinkpad = gst_element_get_pad (sink, "sink");
+    sinkpad = gst_element_get_static_pad (sink, "sink");
 
     /* link'n'play */
     lret = gst_pad_link (pad, sinkpad);
--- a/gst_plugins_base/gst/playback/test4.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/test4.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,8 +16,15 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>             /* exit() */
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 #include <gst/gst.h>
 
--- a/gst_plugins_base/gst/playback/test5.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/test5.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,8 +16,15 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>             /* exit */
+#endif
 #include <gst/gst.h>
 
 static GMainLoop *loop;
--- a/gst_plugins_base/gst/playback/test6.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/test6.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,8 +16,15 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>             /* exit */
+#endif
 #include <gst/gst.h>
 
 static void
@@ -30,7 +37,7 @@
   fakesink = gst_element_factory_make ("fakesink", NULL);
   gst_bin_add (GST_BIN (pipeline), fakesink);
 
-  sinkpad = gst_element_get_pad (fakesink, "sink");
+  sinkpad = gst_element_get_static_pad (fakesink, "sink");
   if (GST_PAD_LINK_FAILED (gst_pad_link (new_pad, sinkpad))) {
     g_warning ("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME (new_pad),
         GST_DEBUG_PAD_NAME (sinkpad));
--- a/gst_plugins_base/gst/playback/test7.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/playback/test7.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,7 +16,12 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#include <stdlib.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>             /* exit() */
+#endif
 #include <gst/gst.h>
 
 #define UPDATE_INTERVAL 500
--- a/gst_plugins_base/gst/subparse/gstssaparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/subparse/gstssaparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -53,7 +53,6 @@
 static gboolean gst_ssa_parse_sink_event (GstPad * pad, GstEvent * event);
 static GstFlowReturn gst_ssa_parse_chain (GstPad * sinkpad, GstBuffer * buf);
 
-
 static void
 gst_ssa_parse_base_init (gpointer klass)
 {
@@ -108,6 +107,7 @@
 
   parse->ini = NULL;
   parse->framed = FALSE;
+  parse->send_tags = FALSE;
 }
 
 static void
@@ -153,6 +153,7 @@
   }
 
   parse->framed = TRUE;
+  parse->send_tags = TRUE;
 
   priv = (GstBuffer *) gst_value_get_mini_object (val);
   g_return_val_if_fail (priv != NULL, FALSE);
@@ -305,11 +306,20 @@
   if (G_UNLIKELY (!parse->framed))
     goto not_framed;
 
+  if (G_UNLIKELY (parse->send_tags)) {
+    GstTagList *tags;
+
+    tags = gst_tag_list_new ();
+    gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_SUBTITLE_CODEC,
+        "SubStation Alpha", NULL);
+    gst_element_found_tags_for_pad (GST_ELEMENT (parse), parse->srcpad, tags);
+    parse->send_tags = FALSE;
+  }
+
   /* make double-sure it's 0-terminated and all */
   txt = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
-
   if (txt == NULL)
-    return GST_FLOW_UNEXPECTED;
+    goto empty_text;
 
   ts = GST_BUFFER_TIMESTAMP (buf);
   ret = gst_ssa_parse_push_line (parse, txt, ts, GST_BUFFER_DURATION (buf));
@@ -321,6 +331,7 @@
     ret = GST_FLOW_OK;
   }
 
+  gst_buffer_unref (buf);
   g_free (txt);
 
   return ret;
@@ -330,8 +341,16 @@
   {
     GST_ELEMENT_ERROR (parse, STREAM, FORMAT, (NULL),
         ("Only SSA subtitles embedded in containers are supported"));
+    gst_buffer_unref (buf);
     return GST_FLOW_NOT_NEGOTIATED;
   }
+empty_text:
+  {
+    GST_ELEMENT_WARNING (parse, STREAM, FORMAT, (NULL),
+        ("Received empty subtitle"));
+    gst_buffer_unref (buf);
+    return GST_FLOW_OK;
+  }
 }
 
 static GstStateChangeReturn
--- a/gst_plugins_base/gst/subparse/gstssaparse.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/subparse/gstssaparse.h	Fri Apr 16 15:15:52 2010 +0300
@@ -40,6 +40,7 @@
   GstPad         *srcpad;
 
   gboolean        framed;
+  gboolean        send_tags;
 
   gchar          *ini;
 };
--- a/gst_plugins_base/gst/subparse/gstsubparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/subparse/gstsubparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <glib.h>
 #include <regex.h>
 
 #include "gstsubparse.h"
@@ -34,9 +35,6 @@
 #include "tmplayerparse.h"
 #include "mpl2parse.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
 GST_DEBUG_CATEGORY (sub_parse_debug);
 
 #define DEFAULT_ENCODING   NULL
@@ -149,11 +147,24 @@
     g_free (subparse->encoding);
     subparse->encoding = NULL;
   }
+
+  if (subparse->detected_encoding) {
+    g_free (subparse->detected_encoding);
+    subparse->detected_encoding = NULL;
+  }
+
+  if (subparse->adapter) {
+    gst_object_unref (subparse->adapter);
+    subparse->adapter = NULL;
+  }
+
   if (subparse->textbuf) {
     g_string_free (subparse->textbuf, TRUE);
     subparse->textbuf = NULL;
   }
+#ifndef GST_DISABLE_XML
   sami_context_deinit (&subparse->state);
+#endif
 
   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
 }
@@ -174,10 +185,11 @@
 
   g_object_class_install_property (object_class, PROP_ENCODING,
       g_param_spec_string ("subtitle-encoding", "subtitle charset encoding",
-          "Encoding to assume if input subtitles are not in UTF-8 encoding. "
-          "If not set, the GST_SUBTITLE_ENCODING environment variable will "
-          "be checked for an encoding to use. If that is not set either, "
-          "ISO-8859-15 will be assumed.", DEFAULT_ENCODING, G_PARAM_READWRITE));
+          "Encoding to assume if input subtitles are not in UTF-8 or any other "
+          "Unicode encoding. If not set, the GST_SUBTITLE_ENCODING environment "
+          "variable will be checked for an encoding to use. If that is not set "
+          "either, ISO-8859-15 will be assumed.", DEFAULT_ENCODING,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -201,6 +213,8 @@
   gst_segment_init (&subparse->segment, GST_FORMAT_TIME);
   subparse->need_segment = TRUE;
   subparse->encoding = g_strdup (DEFAULT_ENCODING);
+  subparse->detected_encoding = NULL;
+  subparse->adapter = gst_adapter_new ();
 }
 
 /*
@@ -308,21 +322,113 @@
 }
 
 static gchar *
-convert_encoding (GstSubParse * self, const gchar * str, gsize len)
+gst_sub_parse_get_format_description (GstSubParseFormat format)
+{
+  switch (format) {
+    case GST_SUB_PARSE_FORMAT_MDVDSUB:
+      return "MicroDVD";
+    case GST_SUB_PARSE_FORMAT_SUBRIP:
+      return "SubRip";
+    case GST_SUB_PARSE_FORMAT_MPSUB:
+      return "MPSub";
+    case GST_SUB_PARSE_FORMAT_SAMI:
+      return "SAMI";
+    case GST_SUB_PARSE_FORMAT_TMPLAYER:
+      return "TMPlayer";
+    case GST_SUB_PARSE_FORMAT_MPL2:
+      return "MPL2";
+    case GST_SUB_PARSE_FORMAT_SUBVIEWER:
+      return "SubViewer";
+    default:
+    case GST_SUB_PARSE_FORMAT_UNKNOWN:
+      break;
+  }
+  return NULL;
+}
+
+static gchar *
+gst_convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding,
+    gsize * consumed, GError ** err)
+{
+  gchar *ret = NULL;
+
+  *consumed = 0;
+  ret =
+      g_convert_with_fallback (str, len, "UTF-8", encoding, "*", consumed, NULL,
+      err);
+  if (ret == NULL)
+    return ret;
+
+  /* + 3 to skip UTF-8 BOM if it was added */
+  len = strlen (ret);
+  if (len >= 3 && (guint8) ret[0] == 0xEF && (guint8) ret[1] == 0xBB
+      && (guint8) ret[2] == 0xBF)
+    g_memmove (ret, ret + 3, len + 1 - 3);
+
+  return ret;
+}
+
+static gchar *
+detect_encoding (const gchar * str, gsize len)
+{
+  if (len >= 3 && (guint8) str[0] == 0xEF && (guint8) str[1] == 0xBB
+      && (guint8) str[2] == 0xBF)
+    return g_strdup ("UTF-8");
+
+  if (len >= 2 && (guint8) str[0] == 0xFE && (guint8) str[1] == 0xFF)
+    return g_strdup ("UTF-16BE");
+
+  if (len >= 2 && (guint8) str[0] == 0xFF && (guint8) str[1] == 0xFE)
+    return g_strdup ("UTF-16LE");
+
+  if (len >= 4 && (guint8) str[0] == 0x00 && (guint8) str[1] == 0x00
+      && (guint8) str[2] == 0xFE && (guint8) str[3] == 0xFF)
+    return g_strdup ("UTF-32BE");
+
+  if (len >= 4 && (guint8) str[0] == 0xFF && (guint8) str[1] == 0xFE
+      && (guint8) str[2] == 0x00 && (guint8) str[3] == 0x00)
+    return g_strdup ("UTF-32LE");
+
+  return NULL;
+}
+
+static gchar *
+convert_encoding (GstSubParse * self, const gchar * str, gsize len,
+    gsize * consumed)
 {
   const gchar *encoding;
   GError *err = NULL;
-  gchar *ret;
+  gchar *ret = NULL;
+
+  *consumed = 0;
+
+  /* First try any detected encoding */
+  if (self->detected_encoding) {
+    ret =
+        gst_convert_to_utf8 (str, len, self->detected_encoding, consumed, &err);
 
+    if (!err)
+      return ret;
+
+    GST_WARNING_OBJECT (self, "could not convert string from '%s' to UTF-8: %s",
+        self->detected_encoding, err->message);
+    g_free (self->detected_encoding);
+    self->detected_encoding = NULL;
+    g_error_free (err);
+  }
+
+  /* Otherwise check if it's UTF8 */
   if (self->valid_utf8) {
     if (g_utf8_validate (str, len, NULL)) {
       GST_LOG_OBJECT (self, "valid UTF-8, no conversion needed");
+      *consumed = len;
       return g_strndup (str, len);
     }
     GST_INFO_OBJECT (self, "invalid UTF-8!");
     self->valid_utf8 = FALSE;
   }
 
+  /* Else try fallback */
   encoding = self->encoding;
   if (encoding == NULL || *encoding == '\0') {
     encoding = g_getenv ("GST_SUBTITLE_ENCODING");
@@ -335,8 +441,7 @@
     }
   }
 
-  ret = g_convert_with_fallback (str, len, "UTF-8", encoding, "*", NULL,
-      NULL, &err);
+  ret = gst_convert_to_utf8 (str, len, encoding, consumed, &err);
 
   if (err) {
     GST_WARNING_OBJECT (self, "could not convert string from '%s' to UTF-8: %s",
@@ -344,8 +449,7 @@
     g_error_free (err);
 
     /* invalid input encoding, fall back to ISO-8859-15 (always succeeds) */
-    ret = g_convert_with_fallback (str, len, "UTF-8", "ISO-8859-15", "*",
-        NULL, NULL, NULL);
+    ret = gst_convert_to_utf8 (str, len, "ISO-8859-15", consumed, NULL);
   }
 
   GST_LOG_OBJECT (self,
@@ -377,7 +481,7 @@
   }
 
   line_len = line_end - self->textbuf->str;
-  line = convert_encoding (self, self->textbuf->str, line_len);
+  line = g_strndup (self->textbuf->str, line_len);
   self->textbuf = g_string_erase (self->textbuf, 0,
       line_len + (have_r ? 2 : 1));
   return line;
@@ -655,11 +759,59 @@
   }
 }
 
+static gboolean
+parse_subrip_time (const gchar * ts_string, GstClockTime * t)
+{
+  gchar s[128] = { '\0', };
+  gchar *end, *p;
+  guint hour, min, sec, msec, len;
+
+  while (*ts_string == ' ')
+    ++ts_string;
+
+  g_strlcpy (s, ts_string, sizeof (s));
+  if ((end = strstr (s, "-->")))
+    *end = '\0';
+  g_strchomp (s);
+
+  /* ms may be in these formats:
+   * hh:mm:ss,500 = 500ms
+   * hh:mm:ss,  5 =   5ms
+   * hh:mm:ss, 5  =  50ms
+   * hh:mm:ss, 50 =  50ms
+   * hh:mm:ss,5   = 500ms
+   * and sscanf() doesn't differentiate between '  5' and '5' so munge
+   * the white spaces within the timestamp to '0' (I'm sure there's a
+   * way to make sscanf() do this for us, but how?)
+   */
+  g_strdelimit (s, " ", '0');
+
+  /* make sure we have exactly three digits after he comma */
+  p = strchr (s, ',');
+  g_assert (p != NULL);
+  ++p;
+  len = strlen (p);
+  if (len > 3) {
+    p[3] = '\0';
+  } else
+    while (len < 3) {
+      g_strlcat (&p[len], "0", 2);
+      ++len;
+    }
+
+  GST_LOG ("parsing timestamp '%s'", s);
+  if (sscanf (s, "%u:%u:%u,%u", &hour, &min, &sec, &msec) != 4) {
+    GST_WARNING ("failed to parse subrip timestamp string '%s'", s);
+    return FALSE;
+  }
+
+  *t = ((hour * 3600) + (min * 60) + sec) * GST_SECOND + msec * GST_MSECOND;
+  return TRUE;
+}
+
 static gchar *
 parse_subrip (ParserState * state, const gchar * line)
 {
-  guint h1, m1, s1, ms1;
-  guint h2, m2, s2, ms2;
   int subnum;
   gchar *ret;
 
@@ -670,21 +822,24 @@
         state->state = 1;
       return NULL;
     case 1:
+    {
+      GstClockTime ts_start, ts_end;
+      gchar *end_time;
+
       /* looking for start_time --> end_time */
-      if (sscanf (line, "%u:%u:%u,%u --> %u:%u:%u,%u",
-              &h1, &m1, &s1, &ms1, &h2, &m2, &s2, &ms2) == 8) {
+      if ((end_time = strstr (line, " --> ")) &&
+          parse_subrip_time (line, &ts_start) &&
+          parse_subrip_time (end_time + strlen (" --> "), &ts_end) &&
+          state->start_time <= ts_end) {
         state->state = 2;
-        state->start_time =
-            (((guint64) h1) * 3600 + m1 * 60 + s1) * GST_SECOND +
-            ms1 * GST_MSECOND;
-        state->duration =
-            (((guint64) h2) * 3600 + m2 * 60 + s2) * GST_SECOND +
-            ms2 * GST_MSECOND - state->start_time;
+        state->start_time = ts_start;
+        state->duration = ts_end - ts_start;
       } else {
-        GST_DEBUG ("error parsing subrip time line");
+        GST_DEBUG ("error parsing subrip time line '%s'", line);
         state->state = 0;
       }
       return NULL;
+    }
     case 2:
     {
       /* No need to parse that text if it's out of segment */
@@ -876,6 +1031,7 @@
 
   state->start_time = 0;
   state->duration = 0;
+  state->max_duration = 0;      /* no limit */
   state->state = 0;
   state->segment = NULL;
 }
@@ -887,9 +1043,49 @@
     g_string_free (state->buf, TRUE);
     state->buf = NULL;
   }
+#ifndef GST_DISABLE_XML
   if (state->user_data) {
     sami_context_reset (state);
   }
+#endif
+}
+
+/* regex type enum */
+typedef enum
+{
+  GST_SUB_PARSE_REGEX_UNKNOWN = 0,
+  GST_SUB_PARSE_REGEX_MDVDSUB = 1,
+  GST_SUB_PARSE_REGEX_SUBRIP = 2,
+} GstSubParseRegex;
+
+static gpointer
+gst_sub_parse_data_format_autodetect_regex_once (GstSubParseRegex regtype)
+{
+  gpointer result = NULL;
+  GError *gerr = NULL;
+  switch (regtype) {
+    case GST_SUB_PARSE_REGEX_MDVDSUB:
+      result =
+          (gpointer) g_regex_new ("^\\{[0-9]+\\}\\{[0-9]+\\}", 0, 0, &gerr);
+      if (result == NULL) {
+        g_warning ("Compilation of mdvd regex failed: %s", gerr->message);
+        g_error_free (gerr);
+      }
+      break;
+    case GST_SUB_PARSE_REGEX_SUBRIP:
+      result = (gpointer) g_regex_new ("^([ 0-9]){0,3}[0-9]\\s*(\x0d)?\x0a"
+          "[ 0-9][0-9]:[ 0-9][0-9]:[ 0-9][0-9],[ 0-9]{0,2}[0-9]"
+          " +--> +([ 0-9])?[0-9]:[ 0-9][0-9]:[ 0-9][0-9],[ 0-9]{0,2}[0-9]",
+          0, 0, &gerr);
+      if (result == NULL) {
+        g_warning ("Compilation of subrip regex failed: %s", gerr->message);
+        g_error_free (gerr);
+      }
+      break;
+    default:
+      GST_WARNING ("Trying to allocate regex of unknown type %u", regtype);
+  }
+  return result;
 }
 
 /*
@@ -901,33 +1097,29 @@
 static GstSubParseFormat
 gst_sub_parse_data_format_autodetect (gchar * match_str)
 {
-  static gboolean need_init_regexps = TRUE;
-  static regex_t mdvd_rx;
-  static regex_t subrip_rx;
   guint n1, n2, n3;
 
-  /* initialize the regexps used the first time around */
-  if (need_init_regexps) {
-    int err;
-    char errstr[128];
+  static GOnce mdvd_rx_once = G_ONCE_INIT;
+  static GOnce subrip_rx_once = G_ONCE_INIT;
+
+  GRegex *mdvd_grx;
+  GRegex *subrip_grx;
 
-    need_init_regexps = FALSE;
-    if ((err = regcomp (&mdvd_rx, "^\\{[0-9]+\\}\\{[0-9]+\\}",
-                REG_EXTENDED | REG_NEWLINE | REG_NOSUB) != 0) ||
-        (err = regcomp (&subrip_rx, "^[0-9]([0-9]){0,3}(\x0d)?\x0a"
-                "[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9]{3}"
-                " --> [0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9]{3}",
-                REG_EXTENDED | REG_NEWLINE | REG_NOSUB)) != 0) {
-      regerror (err, &subrip_rx, errstr, 127);
-      GST_WARNING ("Compilation of subrip regex failed: %s", errstr);
-    }
-  }
+  g_once (&mdvd_rx_once,
+      (GThreadFunc) gst_sub_parse_data_format_autodetect_regex_once,
+      (gpointer) GST_SUB_PARSE_REGEX_MDVDSUB);
+  g_once (&subrip_rx_once,
+      (GThreadFunc) gst_sub_parse_data_format_autodetect_regex_once,
+      (gpointer) GST_SUB_PARSE_REGEX_SUBRIP);
 
-  if (regexec (&mdvd_rx, match_str, 0, NULL, 0) == 0) {
+  mdvd_grx = (GRegex *) mdvd_rx_once.retval;
+  subrip_grx = (GRegex *) subrip_rx_once.retval;
+
+  if (g_regex_match (mdvd_grx, match_str, 0, NULL) == TRUE) {
     GST_LOG ("MicroDVD (frame based) format detected");
     return GST_SUB_PARSE_FORMAT_MDVDSUB;
   }
-  if (regexec (&subrip_rx, match_str, 0, NULL, 0) == 0) {
+  if (g_regex_match (subrip_grx, match_str, 0, NULL) == TRUE) {
     GST_LOG ("SubRip (time based) format detected");
     return GST_SUB_PARSE_FORMAT_SUBRIP;
   }
@@ -936,11 +1128,13 @@
     GST_LOG ("MPSub (time based) format detected");
     return GST_SUB_PARSE_FORMAT_MPSUB;
   }
+#ifndef GST_DISABLE_XML
   if (strstr (match_str, "<SAMI>") != NULL ||
       strstr (match_str, "<sami>") != NULL) {
     GST_LOG ("SAMI (time based) format detected");
     return GST_SUB_PARSE_FORMAT_SAMI;
   }
+#endif
   /* we're boldly assuming the first subtitle appears within the first hour */
   if (sscanf (match_str, "0:%02u:%02u:", &n1, &n2) == 2 ||
       sscanf (match_str, "0:%02u:%02u=", &n1, &n2) == 2 ||
@@ -969,7 +1163,7 @@
   gchar *data;
   GstSubParseFormat format;
 
-  if (strlen (self->textbuf->str) < 35) {
+  if (strlen (self->textbuf->str) < 30) {
     GST_DEBUG ("File too small to be a subtitles file");
     return NULL;
   }
@@ -979,6 +1173,7 @@
   g_free (data);
 
   self->parser_type = format;
+  self->subtitle_codec = gst_sub_parse_get_format_description (format);
   parser_state_init (&self->state);
 
   switch (format) {
@@ -991,12 +1186,15 @@
     case GST_SUB_PARSE_FORMAT_MPSUB:
       self->parse_line = parse_mpsub;
       return gst_caps_new_simple ("text/plain", NULL);
+#ifndef GST_DISABLE_XML
     case GST_SUB_PARSE_FORMAT_SAMI:
       self->parse_line = parse_sami;
       sami_context_init (&self->state);
       return gst_caps_new_simple ("text/x-pango-markup", NULL);
+#endif
     case GST_SUB_PARSE_FORMAT_TMPLAYER:
       self->parse_line = parse_tmplayer;
+      self->state.max_duration = 5 * GST_SECOND;
       return gst_caps_new_simple ("text/plain", NULL);
     case GST_SUB_PARSE_FORMAT_MPL2:
       self->parse_line = parse_mpl2;
@@ -1016,19 +1214,48 @@
 static void
 feed_textbuf (GstSubParse * self, GstBuffer * buf)
 {
-  if (GST_BUFFER_OFFSET (buf) != self->offset) {
+  gboolean discont;
+  gsize consumed;
+  gchar *input = NULL;
+
+  discont = GST_BUFFER_IS_DISCONT (buf);
+
+  if (GST_BUFFER_OFFSET_IS_VALID (buf) &&
+      GST_BUFFER_OFFSET (buf) != self->offset) {
+    self->offset = GST_BUFFER_OFFSET (buf);
+    discont = TRUE;
+  }
+
+  if (discont) {
+    GST_INFO ("discontinuity");
     /* flush the parser state */
     parser_state_init (&self->state);
     g_string_truncate (self->textbuf, 0);
+    gst_adapter_clear (self->adapter);
+#ifndef GST_DISABLE_XML
     sami_context_reset (&self->state);
+#endif
+    /* we could set a flag to make sure that the next buffer we push out also
+     * has the DISCONT flag set, but there's no point really given that it's
+     * subtitles which are discontinuous by nature. */
   }
 
-  self->textbuf = g_string_append_len (self->textbuf,
-      (gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
   self->offset = GST_BUFFER_OFFSET (buf) + GST_BUFFER_SIZE (buf);
   self->next_offset = self->offset;
 
-  gst_buffer_unref (buf);
+  gst_adapter_push (self->adapter, buf);
+
+  input =
+      convert_encoding (self, (const gchar *) gst_adapter_peek (self->adapter,
+          gst_adapter_available (self->adapter)),
+      (gsize) gst_adapter_available (self->adapter), &consumed);
+
+  if (input && consumed > 0) {
+    self->textbuf = g_string_append (self->textbuf, input);
+    gst_adapter_flush (self->adapter, consumed);
+  }
+
+  g_free (input);
 }
 
 static GstFlowReturn
@@ -1038,6 +1265,13 @@
   GstCaps *caps = NULL;
   gchar *line, *subtitle;
 
+  if (self->first_buffer) {
+    self->detected_encoding =
+        detect_encoding ((gchar *) GST_BUFFER_DATA (buf),
+        GST_BUFFER_SIZE (buf));
+    self->first_buffer = FALSE;
+  }
+
   feed_textbuf (self, buf);
 
   /* make sure we know the format */
@@ -1050,14 +1284,26 @@
       return GST_FLOW_UNEXPECTED;
     }
     gst_caps_unref (caps);
+
+    /* push tags */
+    if (self->subtitle_codec != NULL) {
+      GstTagList *tags;
+
+      tags = gst_tag_list_new ();
+      gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_SUBTITLE_CODEC,
+          self->subtitle_codec, NULL);
+      gst_element_found_tags_for_pad (GST_ELEMENT (self), self->srcpad, tags);
+    }
   }
 
-  while ((line = get_next_line (self)) && !self->flushing) {
+  while (!self->flushing && (line = get_next_line (self))) {
+    guint offset = 0;
+
     /* Set segment on our parser state machine */
     self->state.segment = &self->segment;
     /* Now parse the line, out of segment lines will just return NULL */
-    GST_LOG_OBJECT (self, "Parsing line '%s'", line);
-    subtitle = self->parse_line (&self->state, line);
+    GST_LOG_OBJECT (self, "Parsing line '%s'", line + offset);
+    subtitle = self->parse_line (&self->state, line + offset);
     g_free (line);
 
     if (subtitle) {
@@ -1075,6 +1321,16 @@
         GST_BUFFER_TIMESTAMP (buf) = self->state.start_time;
         GST_BUFFER_DURATION (buf) = self->state.duration;
 
+        /* in some cases (e.g. tmplayer) we can only determine the duration
+         * of a text chunk from the timestamp of the next text chunk; in those
+         * cases, we probably want to limit the duration to something
+         * reasonable, so we don't end up showing some text for e.g. 40 seconds
+         * just because nothing else is being said during that time */
+        if (self->state.max_duration > 0 && GST_BUFFER_DURATION_IS_VALID (buf)) {
+          if (GST_BUFFER_DURATION (buf) > self->state.max_duration)
+            GST_BUFFER_DURATION (buf) = self->state.max_duration;
+        }
+
         gst_segment_set_last_stop (&self->segment, GST_FORMAT_TIME,
             self->state.start_time);
 
@@ -1085,6 +1341,10 @@
         ret = gst_pad_push (self->srcpad, buf);
       }
 
+      /* move this forward (the tmplayer parser needs this) */
+      if (self->state.duration != GST_CLOCK_TIME_NONE)
+        self->state.start_time += self->state.duration;
+
       g_free (subtitle);
       subtitle = NULL;
 
@@ -1108,10 +1368,9 @@
 
   /* Push newsegment if needed */
   if (self->need_segment) {
-#ifndef __SYMBIAN32__
     GST_LOG_OBJECT (self, "pushing newsegment event with %" GST_SEGMENT_FORMAT,
         &self->segment);
-#endif
+
     gst_pad_push_event (self->srcpad, gst_event_new_new_segment (FALSE,
             self->segment.rate, self->segment.format,
             self->segment.last_stop, self->segment.stop, self->segment.time));
@@ -1136,13 +1395,15 @@
       /* Make sure the last subrip chunk is pushed out even
        * if the file does not have an empty line at the end */
       if (self->parser_type == GST_SUB_PARSE_FORMAT_SUBRIP ||
+          self->parser_type == GST_SUB_PARSE_FORMAT_TMPLAYER ||
           self->parser_type == GST_SUB_PARSE_FORMAT_MPL2) {
-        GstBuffer *buf = gst_buffer_new_and_alloc (1 + 1);
+        GstBuffer *buf = gst_buffer_new_and_alloc (2 + 1);
 
         GST_DEBUG ("EOS. Pushing remaining text (if any)");
         GST_BUFFER_DATA (buf)[0] = '\n';
-        GST_BUFFER_DATA (buf)[1] = '\0';        /* play it safe */
-        GST_BUFFER_SIZE (buf) = 1;
+        GST_BUFFER_DATA (buf)[1] = '\n';
+        GST_BUFFER_DATA (buf)[2] = '\0';        /* play it safe */
+        GST_BUFFER_SIZE (buf) = 2;
         GST_BUFFER_OFFSET (buf) = self->offset;
         gst_sub_parse_chain (pad, buf);
       }
@@ -1217,7 +1478,11 @@
       self->next_offset = 0;
       self->parser_type = GST_SUB_PARSE_FORMAT_UNKNOWN;
       self->valid_utf8 = TRUE;
+      self->first_buffer = TRUE;
+      g_free (self->detected_encoding);
+      self->detected_encoding = NULL;
       g_string_truncate (self->textbuf, 0);
+      gst_adapter_clear (self->adapter);
       break;
     default:
       break;
@@ -1247,15 +1512,19 @@
  * also, give different  subtitle formats really different types */
 static GstStaticCaps mpl2_caps =
 GST_STATIC_CAPS ("application/x-subtitle-mpl2");
+#define SUB_CAPS (gst_static_caps_get (&sub_caps))
+
 static GstStaticCaps tmp_caps =
 GST_STATIC_CAPS ("application/x-subtitle-tmplayer");
-static GstStaticCaps smi_caps = GST_STATIC_CAPS ("application/x-subtitle-sami");
+#define TMP_CAPS (gst_static_caps_get (&tmp_caps))
+
 static GstStaticCaps sub_caps = GST_STATIC_CAPS ("application/x-subtitle");
+#define MPL2_CAPS (gst_static_caps_get (&mpl2_caps))
 
-#define SUB_CAPS (gst_static_caps_get (&sub_caps))
+#ifndef GST_DISABLE_XML
+static GstStaticCaps smi_caps = GST_STATIC_CAPS ("application/x-subtitle-sami");
 #define SAMI_CAPS (gst_static_caps_get (&smi_caps))
-#define TMP_CAPS (gst_static_caps_get (&tmp_caps))
-#define MPL2_CAPS (gst_static_caps_get (&mpl2_caps))
+#endif
 
 static void
 gst_subparse_type_find (GstTypeFind * tf, gpointer private)
@@ -1264,12 +1533,62 @@
   const guint8 *data;
   GstCaps *caps;
   gchar *str;
+  gchar *encoding = NULL;
+  const gchar *end;
 
-  if (!(data = gst_type_find_peek (tf, 0, 36)))
+  if (!(data = gst_type_find_peek (tf, 0, 129)))
     return;
 
   /* make sure string passed to _autodetect() is NUL-terminated */
-  str = g_strndup ((gchar *) data, 35);
+  str = g_malloc0 (129);
+  memcpy (str, data, 128);
+
+  if ((encoding = detect_encoding (str, 128)) != NULL) {
+    gchar *converted_str;
+    GError *err = NULL;
+    gsize tmp;
+
+    converted_str = gst_convert_to_utf8 (str, 128, encoding, &tmp, &err);
+    if (converted_str == NULL) {
+      GST_DEBUG ("Encoding '%s' detected but conversion failed: %s", encoding,
+          err->message);
+      g_error_free (err);
+      g_free (encoding);
+    } else {
+      g_free (str);
+      str = converted_str;
+      g_free (encoding);
+    }
+  }
+
+  /* Check if at least the first 120 chars are valid UTF8,
+   * otherwise convert as always */
+  if (!g_utf8_validate (str, 128, &end) && (end - str) < 120) {
+    gchar *converted_str;
+    GError *err = NULL;
+    gsize tmp;
+    const gchar *enc;
+
+    enc = g_getenv ("GST_SUBTITLE_ENCODING");
+    if (enc == NULL || *enc == '\0') {
+      /* if local encoding is UTF-8 and no encoding specified
+       * via the environment variable, assume ISO-8859-15 */
+      if (g_get_charset (&enc)) {
+        enc = "ISO-8859-15";
+      }
+    }
+    converted_str = gst_convert_to_utf8 (str, 128, enc, &tmp, &err);
+    if (converted_str == NULL) {
+      GST_DEBUG ("Charset conversion failed: %s", err->message);
+      g_error_free (err);
+      g_free (str);
+      return;
+    } else {
+      g_free (str);
+      str = converted_str;
+    }
+  }
+
   format = gst_sub_parse_data_format_autodetect (str);
   g_free (str);
 
@@ -1286,10 +1605,12 @@
       GST_DEBUG ("MPSub format detected");
       caps = SUB_CAPS;
       break;
+#ifndef GST_DISABLE_XML
     case GST_SUB_PARSE_FORMAT_SAMI:
       GST_DEBUG ("SAMI (time-based) format detected");
       caps = SAMI_CAPS;
       break;
+#endif
     case GST_SUB_PARSE_FORMAT_TMPLAYER:
       GST_DEBUG ("TMPlayer (time based) format detected");
       caps = TMP_CAPS;
--- a/gst_plugins_base/gst/subparse/gstsubparse.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/subparse/gstsubparse.h	Fri Apr 16 15:15:52 2010 +0300
@@ -22,6 +22,7 @@
 #define __GST_SUBPARSE_H__
 
 #include <gst/gst.h>
+#include <gst/base/gstadapter.h>
 
 GST_DEBUG_CATEGORY_EXTERN (sub_parse_debug);
 #define GST_CAT_DEFAULT sub_parse_debug
@@ -60,6 +61,7 @@
   GString *buf;
   guint64  start_time;
   guint64  duration;
+  guint64  max_duration; /* to clamp duration, 0 = no limit (used by tmplayer parser) */
   GstSegment *segment;
   gpointer user_data;
   gdouble  fps;          /* used by microdvd parser */
@@ -72,10 +74,14 @@
 
   GstPad *sinkpad,*srcpad;
 
+  /* contains the input in the input encoding */
+  GstAdapter *adapter;
+  /* contains the UTF-8 decoded input */
   GString *textbuf;
 
   GstSubParseFormat parser_type;
   gboolean parser_detected;
+  const gchar *subtitle_codec;
 
   Parser parse_line;
   ParserState state;
@@ -91,7 +97,10 @@
   
   gboolean flushing;
   gboolean valid_utf8;
+  gchar   *detected_encoding;
   gchar   *encoding;
+
+  gboolean first_buffer;
 };
 
 struct _GstSubParseClass {
--- a/gst_plugins_base/gst/subparse/samiparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/subparse/samiparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -47,8 +47,8 @@
                                  * and _context_pop_state(). */
   htmlParserCtxtPtr htmlctxt;   /* html parser context */
   gboolean has_result;          /* set when ready to push out result */
-  gboolean in_title;            /* flag to avoid appending the title content
-                                 * to buf */
+  gboolean in_sync;             /* flag to avoid appending anything except the
+                                 * content of the sync elements to buf */
   guint64 time1;                /* previous start attribute in sync tag */
   guint64 time2;                /* current start attribute in sync tag  */
 };
@@ -62,6 +62,7 @@
 static void
 sami_context_push_state (GstSamiContext * sctx, char state)
 {
+  GST_LOG ("state %c", state);
   g_string_append_c (sctx->state, state);
 }
 
@@ -72,6 +73,7 @@
   GString *context_state = sctx->state;
   int i;
 
+  GST_LOG ("state %c", state);
   for (i = context_state->len - 1; i >= 0; i--) {
     switch (context_state->str[i]) {
       case ITALIC_TAG:         /* <i> */
@@ -131,10 +133,13 @@
       if (!value)
         continue;
       if (!xmlStrncmp ((const xmlChar *) "start", key, 5)) {
-        sctx->time1 = sctx->time2;
+        /* Only set a new start time if we don't have text pending */
+        if (sctx->resultbuf->len == 0)
+          sctx->time1 = sctx->time2;
+
         sctx->time2 = atoi ((const char *) value) * GST_MSECOND;
-        sctx->has_result = TRUE;
         g_string_append (sctx->resultbuf, sctx->buf->str);
+        sctx->has_result = (sctx->resultbuf->len != 0) ? TRUE : FALSE;
         g_string_truncate (sctx->buf, 0);
       }
     }
@@ -210,10 +215,11 @@
 {
   GstSamiContext *sctx = (GstSamiContext *) ctx;
 
-  if (!xmlStrncmp ((const xmlChar *) "title", name, 5)) {
-    sctx->in_title = TRUE;
-  } else if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) {
+  GST_LOG ("name:%s", name);
+
+  if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) {
     handle_start_sync (sctx, atts);
+    sctx->in_sync = TRUE;
   } else if (!xmlStrncmp ((const xmlChar *) "font", name, 4)) {
     handle_start_font (sctx, atts);
   } else if (!xmlStrncmp ((const xmlChar *) "ruby", name, 4)) {
@@ -239,8 +245,24 @@
 {
   GstSamiContext *sctx = (GstSamiContext *) ctx;
 
-  if (!xmlStrncmp ((const xmlChar *) "title", name, 5)) {
-    sctx->in_title = FALSE;
+  GST_LOG ("name:%s", name);
+
+  if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) {
+    sctx->in_sync = FALSE;
+  } else if ((!xmlStrncmp ((const xmlChar *) "body", name, 4)) ||
+      (!xmlStrncmp ((const xmlChar *) "sami", name, 4))) {
+    /* We will usually have one buffer left when the body is closed
+     * as we need the next sync to actually send it */
+    if (sctx->buf->len != 0) {
+      /* Only set a new start time if we don't have text pending */
+      if (sctx->resultbuf->len == 0)
+        sctx->time1 = sctx->time2;
+
+      sctx->time2 = GST_CLOCK_TIME_NONE;
+      g_string_append (sctx->resultbuf, sctx->buf->str);
+      sctx->has_result = (sctx->resultbuf->len != 0) ? TRUE : FALSE;
+      g_string_truncate (sctx->buf, 0);
+    }
   } else if (!xmlStrncmp ((const xmlChar *) "font", name, 4)) {
     sami_context_pop_state (sctx, SPAN_TAG);
   } else if (!xmlStrncmp ((const xmlChar *) "ruby", name, 4)) {
@@ -255,12 +277,29 @@
 {
   GstSamiContext *sctx = (GstSamiContext *) ctx;
   gchar *escaped;
+  gchar *tmp;
+  gint i;
 
-  /* skip title */
-  if (sctx->in_title)
+  /* Skip everything except content of the sync elements */
+  if (!sctx->in_sync)
     return;
 
   escaped = g_markup_escape_text ((const gchar *) ch, len);
+  g_strstrip (escaped);
+
+  /* Remove double spaces forom the string as those are
+   * usually added by newlines and indention */
+  tmp = escaped;
+  for (i = 0; i <= strlen (escaped); i++) {
+    escaped[i] = *tmp;
+    if (*tmp != ' ') {
+      tmp++;
+      continue;
+    }
+    while (*tmp == ' ')
+      tmp++;
+  }
+
   if (has_tag (sctx->state, RT_TAG)) {
     g_string_append_c (sctx->rubybuf, ' ');
     g_string_append (sctx->rubybuf, escaped);
@@ -373,7 +412,7 @@
     g_string_truncate (context->resultbuf, 0);
     g_string_truncate (context->state, 0);
     context->has_result = FALSE;
-    context->in_title = FALSE;
+    context->in_sync = FALSE;
     context->time1 = 0;
     context->time2 = 0;
   }
--- a/gst_plugins_base/gst/subparse/tmplayerparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/subparse/tmplayerparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,5 @@
 /* GStreamer tmplayer format subtitle parser
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2006-2008 Tim-Philipp Müller <tim centricular net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -55,9 +55,30 @@
  * 00:00:53,1=
  * 00:00:54,1=a lush and fertile planet.
  * 00:00:56,1=
+ *
+ * --------------------------------------------------------------------------
+ *
+ * And another variety (which is 'time-base 0:00:00:' but without empty lines):
+ *
+ * 00:00:01:This is the Earth at a time|when the dinosaurs roamed...
+ * 00:00:03:a lush and fertile planet.
+ * 00:00:06:More text here
+ * 00:00:12:Yet another line
+ *
  */
 
 static gchar *
+tmplayer_process_buffer (ParserState * state)
+{
+  gchar *ret;
+
+  ret = g_strndup (state->buf->str, state->buf->len);
+  g_strdelimit (ret, "|", '\n');
+  g_string_truncate (state->buf, 0);
+  return ret;
+}
+
+static gchar *
 tmplayer_parse_line (ParserState * state, const gchar * line, guint line_num)
 {
   GstClockTime ts = GST_CLOCK_TIME_NONE;
@@ -78,19 +99,34 @@
     GST_LOG ("single line format %u %u %u %u %c", h, m, s, l, divc);
     ts = GST_SECOND * ((((h * 60) + m) * 60) + s);
     text_start = strchr (line + 6, divc);
+  } else if (line[0] == '\0' && state->buf->len > 0 &&
+      GST_CLOCK_TIME_IS_VALID (state->start_time)) {
+    /* if we get an empty line (could be the end of the file, but doesn't have
+     * to be), just push whatever is still in the buffer without a duration */
+    GST_LOG ("empty line, and there's still text in the buffer");
+    ret = tmplayer_process_buffer (state);
+    state->duration = GST_CLOCK_TIME_NONE;
+    return ret;
   } else {
     GST_WARNING ("failed to parse line: '%s'", line);
     return NULL;
   }
 
+  /* if this is a line without text, or the first line in a multiline file,
+   * process and return the data in the buffer, which is the previous line(s) */
   if (text_start == NULL || text_start[1] == '\0' ||
       (l == 1 && state->buf->len > 0)) {
+
     if (GST_CLOCK_TIME_IS_VALID (state->start_time) &&
         state->start_time < ts && line_num > 0) {
-      ret = g_strndup (state->buf->str, state->buf->len);
-      g_strdelimit (ret, "|", '\n');
-      g_string_truncate (state->buf, 0);
+      ret = tmplayer_process_buffer (state);
       state->duration = ts - state->start_time;
+      /* ..and append current line's text (if there is any) for the next round.
+       * We don't have to store ts as pending_start_time, since we deduce the
+       * durations from the start times anyway, so as long as the parser just
+       * forwards state->start_time by duration after it pushes the line we
+       * are about to return it will all be good. */
+      g_string_append (state->buf, text_start + 1);
     } else if (line_num > 0) {
       GST_WARNING ("end of subtitle unit but no valid start time?!");
     }
@@ -101,6 +137,7 @@
     state->start_time = ts;
   }
 
+  GST_LOG ("returning: '%s'", GST_STR_NULL (ret));
   return ret;
 }
 #ifdef __SYMBIAN32__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/tcp/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,53 @@
+This part of the documentation is for the new tcp elements:
+- tcpclientsrc
+- tcpclientsink
+- tcpserversrc
+- tcpserversink
+                                                                                
+TESTS
+-----
+Use these tests to test functionality of the various tcp plugins
+
+* server: nc -l -p 3000
+  client: nc localhost 3000
+  everything you type in the server is shown on the client
+  everything you type in the client is shown on the server
+
+* server: nc -l -p 3000
+  client: gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2
+  everything you type in the server is shown on the client
+
+* server: nc -l -p 3000
+  client: gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000
+  everything you type in the client is shown on the server
+
+* server: gst-launch tcpserversrc protocol=none port=3000 ! fdsink fd=2
+  client: gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000
+
+* server: gst-launch fdsrc fd=1 ! tcpserversink protocol=none port=3000
+  client: gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2
+  -> Received first buffer without caps set
+
+TODO
+----
+- implement DNS resolution
+
+multifdsink
+-----------
+- operation:
+  - client fd gets added when "add" signal gets emitted on multifdsink
+  - signal handler creates a GstTCPClient structure, adds it to ->clients,
+    and adds the fd to ->fd_hash, then emits client-added
+  - client 
+
+  - when a buffer comes in:
+    - the _render vmethod puts the buffer on the global queue
+    - and increases bytes_to_serve
+    - (currently it sets streamheaders, but since this is treated globally
+       this is wrong - clients can be at different positions in the stream)
+
+  - when a client issues a write (ie requests data):
+    - when using GDP, if no caps sent yet, send caps first, then set caps_sent
+    - if streamheader buffers, and we haven't sent yet to this client,
+      send current streamheader buffers, then set streamheader_sent
+    - send out buffers
--- a/gst_plugins_base/gst/tcp/gstmultifdsink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gstmultifdsink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,43 +21,36 @@
 
 /**
  * SECTION:element-multifdsink
- * @short_description: Send data to multiple file descriptors
  * @see_also: tcpserversink
  *
- * <refsect2>
- * <para>
  * This plugin writes incoming data to a set of file descriptors. The
- * file descriptors can be added to multifdsink by emitting the "add" signal. 
- * For each descriptor added, the "client-added" signal will be called.
- * </para>
- * <para>
- * As of version 0.10.8, a client can also be added with the "add-full" signal
+ * file descriptors can be added to multifdsink by emitting the #GstMultiFdSink::add signal. 
+ * For each descriptor added, the #GstMultiFdSink::client-added signal will be called.
+ *
+ * As of version 0.10.8, a client can also be added with the #GstMultiFdSink::add-full signal
  * that allows for more control over what and how much data a client 
  * initially receives.
- * </para>
- * <para>
- * Clients can be removed from multifdsink by emitting the "remove" signal. For
- * each descriptor removed, the "client-removed" signal will be called. The
- * "client-removed" signal can also be fired when multifdsink decides that a
+ *
+ * Clients can be removed from multifdsink by emitting the #GstMultiFdSink::remove signal. For
+ * each descriptor removed, the #GstMultiFdSink::client-removed signal will be called. The
+ * #GstMultiFdSink::client-removed signal can also be fired when multifdsink decides that a
  * client is not active anymore or, depending on the value of the
- * "recover-policy" property, if the client is reading too slowly.
+ * #GstMultiFdSink:recover-policy property, if the client is reading too slowly.
  * In all cases, multifdsink will never close a file descriptor itself.
  * The user of multifdsink is responsible for closing all file descriptors.
- * This can for example be done in response to the "client-fd-removed" signal.
+ * This can for example be done in response to the #GstMultiFdSink::client-fd-removed signal.
  * Note that multifdsink still has a reference to the file descriptor when the
- * "client-removed" signal is emitted, so that "get-stats" can be performed on
+ * #GstMultiFdSink::client-removed signal is emitted, so that "get-stats" can be performed on
  * the descriptor; it is therefore not safe to close the file descriptor in
- * the "client-removed" signal handler, and you should use the 
- * "client-fd-removed" signal to safely close the fd.
- * </para>
- * <para>
+ * the #GstMultiFdSink::client-removed signal handler, and you should use the 
+ * #GstMultiFdSink::client-fd-removed signal to safely close the fd.
+ *
  * Multifdsink internally keeps a queue of the incoming buffers and uses a
  * separate thread to send the buffers to the clients. This ensures that no
  * client write can block the pipeline and that clients can read with different
  * speeds.
- * </para>
- * <para>
- * When adding a client to multifdsink, the "sync-method" property will define
+ *
+ * When adding a client to multifdsink, the #GstMultiFdSink:sync-method property will define
  * which buffer in the queued buffers will be sent first to the client. Clients 
  * can be sent the most recent buffer (which might not be decodable by the 
  * client if it is not a keyframe), the next keyframe received in 
@@ -65,48 +58,42 @@
  * last received keyframe (which will cause a simple burst-on-connect). 
  * Multifdsink will always keep at least one keyframe in its internal buffers
  * when the sync-mode is set to latest-keyframe.
- * </para>
- * <para>
- * As of version 0.10.8, there are additional values for the sync-method 
+ *
+ * As of version 0.10.8, there are additional values for the #GstMultiFdSink:sync-method 
  * property to allow finer control over burst-on-connect behaviour. By selecting
  * the 'burst' method a minimum burst size can be chosen, 'burst-keyframe'
  * additionally requires that the burst begin with a keyframe, and 
  * 'burst-with-keyframe' attempts to burst beginning with a keyframe, but will
  * prefer a minimum burst size even if it requires not starting with a keyframe.
- * </para>
- * <para>
+ *
  * Multifdsink can be instructed to keep at least a minimum amount of data
  * expressed in time or byte units in its internal queues with the the 
- * "time-min" and "bytes-min" properties respectively. These properties are
- * useful if the application adds clients with the "add-full" signal to
- * make sure that a burst connect can actually be honored. 
- * </para>
- * <para>
+ * #GstMultiFdSink:time-min and #GstMultiFdSink:bytes-min properties respectively.
+ * These properties are useful if the application adds clients with the 
+ * #GstMultiFdSink::add-full signal to make sure that a burst connect can
+ * actually be honored. 
+ *
  * When streaming data, clients are allowed to read at a different rate than
  * the rate at which multifdsink receives data. If the client is reading too
  * fast, no data will be send to the client until multifdsink receives more
  * data. If the client, however, reads too slowly, data for that client will be 
  * queued up in multifdsink. Two properties control the amount of data 
- * (buffers) that is queued in multifdsink: "buffers-max" and 
- * "buffers-soft-max". A client that falls behind by "buffers-max" is removed 
- * from multifdsink forcibly.
- * </para>
- * <para>
- * A client with a lag of at least "buffers-soft-max" enters the recovery
- * procedure which is controlled with the "recover-policy" property. A recover
- * policy of NONE will do nothing, RESYNC_LATEST will send the most recently
+ * (buffers) that is queued in multifdsink: #GstMultiFdSink:buffers-max and 
+ * #GstMultiFdSink:buffers-soft-max. A client that falls behind by
+ * #GstMultiFdSink:buffers-max is removed from multifdsink forcibly.
+ *
+ * A client with a lag of at least #GstMultiFdSink:buffers-soft-max enters the recovery
+ * procedure which is controlled with the #GstMultiFdSink:recover-policy property.
+ * A recover policy of NONE will do nothing, RESYNC_LATEST will send the most recently
  * received buffer as the next buffer for the client, RESYNC_SOFT_LIMIT
  * positions the client to the soft limit in the buffer queue and
  * RESYNC_KEYFRAME positions the client at the most recent keyframe in the
  * buffer queue.
- * </para>
- * <para>
+ *
  * multifdsink will by default synchronize on the clock before serving the 
  * buffers to the clients. This behaviour can be disabled by setting the sync 
  * property to FALSE. Multifdsink will by default not do QoS and will never
  * drop late buffers.
- * </para>
- * </refsect2>
  *
  * Last reviewed on 2006-09-12 (0.10.10)
  */
@@ -117,11 +104,18 @@
 #include <gst/gst-i18n-plugin.h>
 
 #include <sys/ioctl.h>
+
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <netinet/in.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #ifdef HAVE_FIONREAD_IN_SYS_FILIO
 #include <sys/filio.h>
@@ -176,16 +170,21 @@
 #define DEFAULT_TIME_MIN                -1
 #define DEFAULT_BYTES_MIN               -1
 #define DEFAULT_BUFFERS_MIN             -1
-#define DEFAULT_UNIT_TYPE               GST_UNIT_TYPE_BUFFERS
+#define DEFAULT_UNIT_TYPE               GST_TCP_UNIT_TYPE_BUFFERS
 #define DEFAULT_UNITS_MAX               -1
 #define DEFAULT_UNITS_SOFT_MAX          -1
 #define DEFAULT_RECOVER_POLICY          GST_RECOVER_POLICY_NONE
 #define DEFAULT_TIMEOUT                 0
 #define DEFAULT_SYNC_METHOD             GST_SYNC_METHOD_LATEST
 
-#define DEFAULT_BURST_UNIT              GST_UNIT_TYPE_UNDEFINED
+#define DEFAULT_BURST_UNIT              GST_TCP_UNIT_TYPE_UNDEFINED
 #define DEFAULT_BURST_VALUE             0
 
+#define DEFAULT_QOS_DSCP                -1
+#define DEFAULT_HANDLE_READ             TRUE
+
+#define DEFAULT_RESEND_STREAMHEADER      TRUE
+
 enum
 {
   PROP_0,
@@ -214,6 +213,16 @@
 
   PROP_BURST_UNIT,
   PROP_BURST_VALUE,
+
+  PROP_QOS_DSCP,
+
+  PROP_HANDLE_READ,
+
+  PROP_RESEND_STREAMHEADER,
+
+  PROP_NUM_FDS,
+
+  PROP_LAST
 };
 
 /* For backward compat, we can't really select the poll mode anymore with
@@ -229,6 +238,7 @@
     {2, "EPoll", "epoll"},
     {0, NULL, NULL},
   };
+
   if (!fdset_mode_type) {
     fdset_mode_type = g_enum_register_static ("GstFDSetMode", fdset_mode);
   }
@@ -294,10 +304,10 @@
 {
   static GType unit_type_type = 0;
   static const GEnumValue unit_type[] = {
-    {GST_UNIT_TYPE_UNDEFINED, "Undefined", "undefined"},
-    {GST_UNIT_TYPE_BUFFERS, "Buffers", "buffers"},
-    {GST_UNIT_TYPE_BYTES, "Bytes", "bytes"},
-    {GST_UNIT_TYPE_TIME, "Time", "time"},
+    {GST_TCP_UNIT_TYPE_UNDEFINED, "Undefined", "undefined"},
+    {GST_TCP_UNIT_TYPE_BUFFERS, "Buffers", "buffers"},
+    {GST_TCP_UNIT_TYPE_BYTES, "Bytes", "bytes"},
+    {GST_TCP_UNIT_TYPE_TIME, "Time", "time"},
     {0, NULL, NULL},
   };
 
@@ -378,7 +388,8 @@
 
   g_object_class_install_property (gobject_class, PROP_PROTOCOL,
       g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in",
-          GST_TYPE_TCP_PROTOCOL, DEFAULT_PROTOCOL, G_PARAM_READWRITE));
+          GST_TYPE_TCP_PROTOCOL, DEFAULT_PROTOCOL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstMultiFdSink::mode
@@ -391,88 +402,132 @@
   g_object_class_install_property (gobject_class, PROP_MODE,
       g_param_spec_enum ("mode", "Mode",
           "The mode for selecting activity on the fds (deprecated)",
-          GST_TYPE_FDSET_MODE, DEFAULT_MODE, G_PARAM_READWRITE));
+          GST_TYPE_FDSET_MODE, DEFAULT_MODE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BUFFERS_MAX,
       g_param_spec_int ("buffers-max", "Buffers max",
           "max number of buffers to queue for a client (-1 = no limit)", -1,
-          G_MAXINT, DEFAULT_BUFFERS_MAX, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-      PROP_BUFFERS_SOFT_MAX, g_param_spec_int ("buffers-soft-max",
-          "Buffers soft max",
+          G_MAXINT, DEFAULT_BUFFERS_MAX,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_BUFFERS_SOFT_MAX,
+      g_param_spec_int ("buffers-soft-max", "Buffers soft max",
           "Recover client when going over this limit (-1 = no limit)", -1,
-          G_MAXINT, DEFAULT_BUFFERS_SOFT_MAX, G_PARAM_READWRITE));
+          G_MAXINT, DEFAULT_BUFFERS_SOFT_MAX,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BYTES_MIN,
       g_param_spec_int ("bytes-min", "Bytes min",
           "min number of bytes to queue (-1 = as little as possible)", -1,
-          G_MAXINT, DEFAULT_BYTES_MIN, G_PARAM_READWRITE));
+          G_MAXINT, DEFAULT_BYTES_MIN,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_TIME_MIN,
       g_param_spec_int64 ("time-min", "Time min",
           "min number of time to queue (-1 = as little as possible)", -1,
-          G_MAXINT64, DEFAULT_TIME_MIN, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_TIME_MIN,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_BUFFERS_MIN,
       g_param_spec_int ("buffers-min", "Buffers min",
           "min number of buffers to queue (-1 = as few as possible)", -1,
-          G_MAXINT, DEFAULT_BUFFERS_MIN, G_PARAM_READWRITE));
+          G_MAXINT, DEFAULT_BUFFERS_MIN,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_UNIT_TYPE,
       g_param_spec_enum ("unit-type", "Units type",
           "The unit to measure the max/soft-max/queued properties",
-          GST_TYPE_UNIT_TYPE, DEFAULT_UNIT_TYPE, G_PARAM_READWRITE));
+          GST_TYPE_UNIT_TYPE, DEFAULT_UNIT_TYPE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_UNITS_MAX,
       g_param_spec_int64 ("units-max", "Units max",
           "max number of units to queue (-1 = no limit)", -1, G_MAXINT64,
-          DEFAULT_UNITS_MAX, G_PARAM_READWRITE));
+          DEFAULT_UNITS_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_UNITS_SOFT_MAX,
       g_param_spec_int64 ("units-soft-max", "Units soft max",
           "Recover client when going over this limit (-1 = no limit)", -1,
-          G_MAXINT64, DEFAULT_UNITS_SOFT_MAX, G_PARAM_READWRITE));
+          G_MAXINT64, DEFAULT_UNITS_SOFT_MAX,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BUFFERS_QUEUED,
       g_param_spec_uint ("buffers-queued", "Buffers queued",
           "Number of buffers currently queued", 0, G_MAXUINT, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 #if NOT_IMPLEMENTED
   g_object_class_install_property (gobject_class, PROP_BYTES_QUEUED,
       g_param_spec_uint ("bytes-queued", "Bytes queued",
           "Number of bytes currently queued", 0, G_MAXUINT, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_TIME_QUEUED,
       g_param_spec_uint64 ("time-queued", "Time queued",
           "Number of time currently queued", 0, G_MAXUINT64, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 #endif
 
   g_object_class_install_property (gobject_class, PROP_RECOVER_POLICY,
       g_param_spec_enum ("recover-policy", "Recover Policy",
           "How to recover when client reaches the soft max",
-          GST_TYPE_RECOVER_POLICY, DEFAULT_RECOVER_POLICY, G_PARAM_READWRITE));
+          GST_TYPE_RECOVER_POLICY, DEFAULT_RECOVER_POLICY,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
       g_param_spec_uint64 ("timeout", "Timeout",
           "Maximum inactivity timeout in nanoseconds for a client (0 = no limit)",
-          0, G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE));
+          0, G_MAXUINT64, DEFAULT_TIMEOUT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SYNC_METHOD,
       g_param_spec_enum ("sync-method", "Sync Method",
-          "How to sync new clients to the stream",
-          GST_TYPE_SYNC_METHOD, DEFAULT_SYNC_METHOD, G_PARAM_READWRITE));
+          "How to sync new clients to the stream", GST_TYPE_SYNC_METHOD,
+          DEFAULT_SYNC_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_BYTES_TO_SERVE,
       g_param_spec_uint64 ("bytes-to-serve", "Bytes to serve",
           "Number of bytes received to serve to clients", 0, G_MAXUINT64, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_BYTES_SERVED,
       g_param_spec_uint64 ("bytes-served", "Bytes served",
           "Total number of bytes send to all clients", 0, G_MAXUINT64, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BURST_UNIT,
       g_param_spec_enum ("burst-unit", "Burst unit",
           "The format of the burst units (when sync-method is burst[[-with]-keyframe])",
-          GST_TYPE_UNIT_TYPE, DEFAULT_BURST_UNIT, G_PARAM_READWRITE));
+          GST_TYPE_UNIT_TYPE, DEFAULT_BURST_UNIT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_BURST_VALUE,
       g_param_spec_uint64 ("burst-value", "Burst value",
-          "The amount of burst expressed in burst-unit",
-          0, G_MAXUINT64, DEFAULT_BURST_VALUE, G_PARAM_READWRITE));
+          "The amount of burst expressed in burst-unit", 0, G_MAXUINT64,
+          DEFAULT_BURST_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_QOS_DSCP,
+      g_param_spec_int ("qos-dscp", "QoS diff srv code point",
+          "Quality of Service, differentiated services code point (-1 default)",
+          -1, 63, DEFAULT_QOS_DSCP,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstMultiFdSink::handle-read
+   *
+   * Handle read requests from clients and discard the data.
+   *
+   * Since: 0.10.23
+   */
+  g_object_class_install_property (gobject_class, PROP_HANDLE_READ,
+      g_param_spec_boolean ("handle-read", "Handle Read",
+          "Handle client reads and discard the data",
+          DEFAULT_HANDLE_READ, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstMultiFdSink::resend-streamheader
+   *
+   * Resend the streamheaders to existing clients when they change.
+   *
+   * Since: 0.10.23
+   */
+  g_object_class_install_property (gobject_class, PROP_RESEND_STREAMHEADER,
+      g_param_spec_boolean ("resend-streamheader", "Resend streamheader",
+          "Resend the streamheader if it changes in the caps",
+          DEFAULT_RESEND_STREAMHEADER,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_NUM_FDS,
+      g_param_spec_uint ("num-fds", "Number of fds",
+          "The current number of client file descriptors.",
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstMultiFdSink::add:
@@ -490,7 +545,7 @@
    * GstMultiFdSink::add-full:
    * @gstmultifdsink: the multifdsink element to emit this signal on
    * @fd:             the file descriptor to add to multifdsink
-   * @keyframe:       start bursting from a keyframe
+   * @sync:           the sync method to use
    * @unit_type_min:  the unit-type of @value_min
    * @value_min:      the minimum amount of data to burst expressed in
    *                  @unit_type_min units.
@@ -505,8 +560,8 @@
       g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass,
           add_full), NULL, NULL,
-      gst_tcp_marshal_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6,
-      G_TYPE_INT, G_TYPE_BOOLEAN, GST_TYPE_UNIT_TYPE, G_TYPE_UINT64,
+      gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6,
+      G_TYPE_INT, GST_TYPE_SYNC_METHOD, GST_TYPE_UNIT_TYPE, G_TYPE_UINT64,
       GST_TYPE_UNIT_TYPE, G_TYPE_UINT64);
   /**
    * GstMultiFdSink::remove:
@@ -521,7 +576,7 @@
           remove), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1,
       G_TYPE_INT);
   /**
-   * GstMultiFdSink::remove_flush:
+   * GstMultiFdSink::remove-flush:
    * @gstmultifdsink: the multifdsink element to emit this signal on
    * @fd:             the file descriptor to remove from multifdsink
    *
@@ -662,6 +717,11 @@
   this->def_burst_unit = DEFAULT_BURST_UNIT;
   this->def_burst_value = DEFAULT_BURST_VALUE;
 
+  this->qos_dscp = DEFAULT_QOS_DSCP;
+  this->handle_read = DEFAULT_HANDLE_READ;
+
+  this->resend_streamheader = DEFAULT_RESEND_STREAMHEADER;
+
   this->header_flags = 0;
 }
 
@@ -679,6 +739,84 @@
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gint
+setup_dscp_client (GstMultiFdSink * sink, GstTCPClient * client)
+{
+  gint tos;
+  gint ret;
+  union gst_sockaddr
+  {
+    struct sockaddr sa;
+    struct sockaddr_in6 sa_in6;
+    struct sockaddr_storage sa_stor;
+  } sa;
+  socklen_t slen = sizeof (sa);
+  gint af;
+
+  /* don't touch */
+  if (sink->qos_dscp < 0)
+    return 0;
+
+  if ((ret = getsockname (client->fd.fd, &sa.sa, &slen)) < 0) {
+    GST_DEBUG_OBJECT (sink, "could not get sockname: %s", g_strerror (errno));
+    return ret;
+  }
+
+  af = sa.sa.sa_family;
+
+  /* if this is an IPv4-mapped address then do IPv4 QoS */
+  if (af == AF_INET6) {
+
+    GST_DEBUG_OBJECT (sink, "check IP6 socket");
+    if (IN6_IS_ADDR_V4MAPPED (&(sa.sa_in6.sin6_addr))) {
+      GST_DEBUG_OBJECT (sink, "mapped to IPV4");
+      af = AF_INET;
+    }
+  }
+
+  /* extract and shift 6 bits of the DSCP */
+  tos = (sink->qos_dscp & 0x3f) << 2;
+
+  switch (af) {
+    case AF_INET:
+      ret = setsockopt (client->fd.fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos));
+      break;
+    case AF_INET6:
+#ifdef IPV6_TCLASS
+      ret =
+          setsockopt (client->fd.fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,
+          sizeof (tos));
+      break;
+#endif
+    default:
+      ret = 0;
+      GST_ERROR_OBJECT (sink, "unsupported AF");
+      break;
+  }
+  if (ret)
+    GST_DEBUG_OBJECT (sink, "could not set DSCP: %s", g_strerror (errno));
+
+  return ret;
+}
+
+
+static void
+setup_dscp (GstMultiFdSink * sink)
+{
+  GList *clients, *next;
+
+  CLIENTS_LOCK (sink);
+  for (clients = sink->clients; clients; clients = next) {
+    GstTCPClient *client;
+
+    client = (GstTCPClient *) clients->data;
+    next = g_list_next (clients);
+
+    setup_dscp_client (sink, client);
+  }
+  CLIENTS_UNLOCK (sink);
+}
+
 /* "add-full" signal implementation */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -686,8 +824,8 @@
 
 void
 gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd,
-    GstSyncMethod sync_method, GstUnitType min_unit, guint64 min_value,
-    GstUnitType max_unit, guint64 max_value)
+    GstSyncMethod sync_method, GstTCPUnitType min_unit, guint64 min_value,
+    GstTCPUnitType max_unit, guint64 max_value)
 {
   GstTCPClient *client;
   GList *clink;
@@ -745,21 +883,23 @@
   sink->clients_cookie++;
 
   /* set the socket to non blocking */
-//temporary commented for multifdsink issue  
-  //res = fcntl (fd, F_SETFL, O_NONBLOCK);  //Arun
-  
+//  temporary  fix for multifdsink
+  //res = fcntl (fd, F_SETFL, O_NONBLOCK);
   /* we always read from a client */
   gst_poll_add_fd (sink->fdset, &client->fd);
 
   /* we don't try to read from write only fds */
-  flags = fcntl (fd, F_GETFL, 0);
-  if ((flags & O_ACCMODE) != O_WRONLY) {
-    gst_poll_fd_ctl_read (sink->fdset, &client->fd, TRUE);
+  if (sink->handle_read) {
+    flags = fcntl (fd, F_GETFL, 0);
+    if ((flags & O_ACCMODE) != O_WRONLY) {
+      gst_poll_fd_ctl_read (sink->fdset, &client->fd, TRUE);
+    }
   }
   /* figure out the mode, can't use send() for non sockets */
   res = fstat (fd, &statbuf);
   if (S_ISSOCK (statbuf.st_mode)) {
     client->is_socket = TRUE;
+    setup_dscp_client (sink, client);
   }
 
   gst_poll_restart (sink->fdset);
@@ -1279,14 +1419,21 @@
           send_streamheader = TRUE;
         } else {
           /* both old and new caps have streamheader set */
-          sh1 = gst_structure_get_value (s, "streamheader");
-          s = gst_caps_get_structure (caps, 0);
-          sh2 = gst_structure_get_value (s, "streamheader");
-          if (gst_value_compare (sh1, sh2) != GST_VALUE_EQUAL) {
+          if (!sink->resend_streamheader) {
             GST_DEBUG_OBJECT (sink,
-                "[fd %5d] new streamheader different from old, sending",
+                "[fd %5d] asked to not resend the streamheader, not sending",
                 client->fd.fd);
-            send_streamheader = TRUE;
+            send_streamheader = FALSE;
+          } else {
+            sh1 = gst_structure_get_value (s, "streamheader");
+            s = gst_caps_get_structure (caps, 0);
+            sh2 = gst_structure_get_value (s, "streamheader");
+            if (gst_value_compare (sh1, sh2) != GST_VALUE_EQUAL) {
+              GST_DEBUG_OBJECT (sink,
+                  "[fd %5d] new streamheader different from old, sending",
+                  client->fd.fd);
+              send_streamheader = TRUE;
+            }
           }
         }
       }
@@ -1414,9 +1561,9 @@
 get_buffers_max (GstMultiFdSink * sink, gint64 max)
 {
   switch (sink->unit_type) {
-    case GST_UNIT_TYPE_BUFFERS:
+    case GST_TCP_UNIT_TYPE_BUFFERS:
       return max;
-    case GST_UNIT_TYPE_TIME:
+    case GST_TCP_UNIT_TYPE_TIME:
     {
       GstBuffer *buf;
       int i;
@@ -1440,7 +1587,7 @@
       }
       return len + 1;
     }
-    case GST_UNIT_TYPE_BYTES:
+    case GST_TCP_UNIT_TYPE_BYTES:
     {
       GstBuffer *buf;
       int i;
@@ -1583,23 +1730,23 @@
  * Returns: FALSE if the unit is unknown or undefined. TRUE otherwise.
  */
 static gboolean
-assign_value (GstUnitType unit, guint64 value, gint * bytes, gint * buffers,
+assign_value (GstTCPUnitType unit, guint64 value, gint * bytes, gint * buffers,
     GstClockTime * time)
 {
   gboolean res = TRUE;
 
   /* set only the limit of the given format to the given value */
   switch (unit) {
-    case GST_UNIT_TYPE_BUFFERS:
+    case GST_TCP_UNIT_TYPE_BUFFERS:
       *buffers = (gint) value;
       break;
-    case GST_UNIT_TYPE_TIME:
+    case GST_TCP_UNIT_TYPE_TIME:
       *time = value;
       break;
-    case GST_UNIT_TYPE_BYTES:
+    case GST_TCP_UNIT_TYPE_BYTES:
       *bytes = (gint) value;
       break;
-    case GST_UNIT_TYPE_UNDEFINED:
+    case GST_TCP_UNIT_TYPE_UNDEFINED:
     default:
       res = FALSE;
       break;
@@ -1616,8 +1763,9 @@
  * function returns FALSE.
  */
 static gboolean
-count_burst_unit (GstMultiFdSink * sink, gint * min_idx, GstUnitType min_unit,
-    guint64 min_value, gint * max_idx, GstUnitType max_unit, guint64 max_value)
+count_burst_unit (GstMultiFdSink * sink, gint * min_idx,
+    GstTCPUnitType min_unit, guint64 min_value, gint * max_idx,
+    GstTCPUnitType max_unit, guint64 max_value)
 {
   gint bytes_min = -1, buffers_min = -1;
   gint bytes_max = -1, buffers_max = -1;
@@ -2238,11 +2386,12 @@
     GstBuffer *buf;
 
     /* no point in searching beyond the soft-max if any. */
-    if (soft_max_buffers) {
+    if (soft_max_buffers > 0) {
       limit = MIN (limit, soft_max_buffers);
     }
-    GST_LOG_OBJECT (sink, "extending queue to include sync point, now at %d",
-        max_buffer_usage);
+    GST_LOG_OBJECT (sink,
+        "extending queue to include sync point, now at %d, limit is %d",
+        max_buffer_usage, limit);
     for (i = 0; i < limit; i++) {
       buf = g_array_index (sink->bufqueue, GstBuffer *, i);
       if (is_sync_frame (sink, buf)) {
@@ -2342,6 +2491,7 @@
                 fd, g_strerror (errno), errno);
             if (errno == EBADF) {
               client->status = GST_CLIENT_STATUS_ERROR;
+              /* releases the CLIENTS lock */
               gst_multi_fd_sink_remove_client_link (sink, clients);
             }
           }
@@ -2587,6 +2737,16 @@
     case PROP_BURST_VALUE:
       multifdsink->def_burst_value = g_value_get_uint64 (value);
       break;
+    case PROP_QOS_DSCP:
+      multifdsink->qos_dscp = g_value_get_int (value);
+      setup_dscp (multifdsink);
+      break;
+    case PROP_HANDLE_READ:
+      multifdsink->handle_read = g_value_get_boolean (value);
+      break;
+    case PROP_RESEND_STREAMHEADER:
+      multifdsink->resend_streamheader = g_value_get_boolean (value);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -2663,6 +2823,18 @@
     case PROP_BURST_VALUE:
       g_value_set_uint64 (value, multifdsink->def_burst_value);
       break;
+    case PROP_QOS_DSCP:
+      g_value_set_int (value, multifdsink->qos_dscp);
+      break;
+    case PROP_HANDLE_READ:
+      g_value_set_boolean (value, multifdsink->handle_read);
+      break;
+    case PROP_RESEND_STREAMHEADER:
+      g_value_set_boolean (value, multifdsink->resend_streamheader);
+      break;
+    case PROP_NUM_FDS:
+      g_value_set_uint (value, g_hash_table_size (multifdsink->fd_hash));
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--- a/gst_plugins_base/gst/tcp/gstmultifdsink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gstmultifdsink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -96,21 +96,21 @@
 } GstSyncMethod;
 
 /**
- * GstUnitType:
- * @GST_UNIT_TYPE_UNDEFINED: undefined
- * @GST_UNIT_TYPE_BUFFERS  : buffers
- * @GST_UNIT_TYPE_TIME     : timeunits (in nanoseconds)
- * @GST_UNIT_TYPE_BYTES    : bytes
+ * GstTCPUnitType:
+ * @GST_TCP_UNIT_TYPE_UNDEFINED: undefined
+ * @GST_TCP_UNIT_TYPE_BUFFERS  : buffers
+ * @GST_TCP_UNIT_TYPE_TIME     : timeunits (in nanoseconds)
+ * @GST_TCP_UNIT_TYPE_BYTES    : bytes
  *
  * The units used to specify limits.
  */
 typedef enum
 {
-  GST_UNIT_TYPE_UNDEFINED,
-  GST_UNIT_TYPE_BUFFERS,
-  GST_UNIT_TYPE_TIME,
-  GST_UNIT_TYPE_BYTES
-} GstUnitType;
+  GST_TCP_UNIT_TYPE_UNDEFINED,
+  GST_TCP_UNIT_TYPE_BUFFERS,
+  GST_TCP_UNIT_TYPE_TIME,
+  GST_TCP_UNIT_TYPE_BYTES
+} GstTCPUnitType;
 
 /**
  * GstClientStatus:
@@ -162,9 +162,9 @@
 
   /* method to sync client when connecting */
   GstSyncMethod sync_method;
-  GstUnitType   burst_min_unit;
+  GstTCPUnitType   burst_min_unit;
   guint64       burst_min_value;
-  GstUnitType   burst_max_unit;
+  GstTCPUnitType   burst_max_unit;
   guint64       burst_max_value;
 
   GstCaps *caps;                /* caps of last queued buffer */
@@ -208,6 +208,8 @@
 
   GstTCPProtocol protocol;
   guint mtu;
+  gint qos_dscp;
+  gboolean handle_read;
 
   GArray *bufqueue;     /* global queue of buffers */
 
@@ -216,14 +218,14 @@
 
   /* these values are used to check if a client is reading fast
    * enough and to control receovery */
-  GstUnitType unit_type;/* the type of the units */
+  GstTCPUnitType unit_type;/* the type of the units */
   gint64 units_max;       /* max units to queue for a client */
   gint64 units_soft_max;  /* max units a client can lag before recovery starts */
   GstRecoverPolicy recover_policy;
   GstClockTime timeout; /* max amount of nanoseconds to remain idle */
 
   GstSyncMethod def_sync_method;    /* what method to use for connecting clients */
-  GstUnitType   def_burst_unit;
+  GstTCPUnitType   def_burst_unit;
   guint64       def_burst_value;
 
   /* these values are used to control the amount of data
@@ -233,6 +235,8 @@
   gint64 time_min;	/* min time to queue */
   gint   buffers_min;   /* min number of buffers to queue */
 
+  gboolean resend_streamheader; /* resend streamheader if it changes */
+
   /* stats */
   gint buffers_queued;  /* number of queued buffers */
   gint bytes_queued;    /* number of queued bytes */
@@ -247,8 +251,8 @@
   /* element methods */
   void          (*add)          (GstMultiFdSink *sink, int fd);
   void          (*add_full)     (GstMultiFdSink *sink, int fd, GstSyncMethod sync,
-		                 GstUnitType format, guint64 value, 
-				 GstUnitType max_unit, guint64 max_value);
+		                 GstTCPUnitType format, guint64 value, 
+				 GstTCPUnitType max_unit, guint64 max_value);
   void          (*remove)       (GstMultiFdSink *sink, int fd);
   void          (*remove_flush) (GstMultiFdSink *sink, int fd);
   void          (*clear)        (GstMultiFdSink *sink);
@@ -282,8 +286,8 @@
 #endif
 
 void          gst_multi_fd_sink_add_full     (GstMultiFdSink *sink, int fd, GstSyncMethod sync, 
-                                              GstUnitType min_unit, guint64 min_value,
-                                              GstUnitType max_unit, guint64 max_value);
+                                              GstTCPUnitType min_unit, guint64 min_value,
+                                              GstTCPUnitType max_unit, guint64 max_value);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gst_plugins_base/gst/tcp/gsttcp-enumtypes.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcp-enumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,16 +13,17 @@
 GType
 gst_tcp_protocol_get_type (void)
 {
-  static GType etype = 0;
-  if (etype == 0) {
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
     static const GEnumValue values[] = {
       { GST_TCP_PROTOCOL_NONE, "GST_TCP_PROTOCOL_NONE", "none" },
       { GST_TCP_PROTOCOL_GDP, "GST_TCP_PROTOCOL_GDP", "gdp" },
       { 0, NULL, NULL }
     };
-    etype = g_enum_register_static ("GstTCPProtocol", values);
+    GType g_define_type_id = g_enum_register_static ("GstTCPProtocol", values);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
   }
-  return etype;
+  return g_define_type_id__volatile;
 }
 
 /* Generated data ends here */
--- a/gst_plugins_base/gst/tcp/gsttcp-marshal.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcp-marshal.c	Fri Apr 16 15:15:52 2010 +0300
@@ -132,28 +132,28 @@
             data2);
 }
 
-/* VOID:INT,BOOLEAN,INT,UINT64,INT,UINT64 (gsttcp-marshal.list:4) */
+/* VOID:INT,ENUM,INT,UINT64,INT,UINT64 (gsttcp-marshal.list:4) */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 void
-gst_tcp_marshal_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64 (GClosure     *closure,
-                                                         GValue       *return_value G_GNUC_UNUSED,
-                                                         guint         n_param_values,
-                                                         const GValue *param_values,
-                                                         gpointer      invocation_hint G_GNUC_UNUSED,
-                                                         gpointer      marshal_data)
+gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64 (GClosure     *closure,
+                                                      GValue       *return_value G_GNUC_UNUSED,
+                                                      guint         n_param_values,
+                                                      const GValue *param_values,
+                                                      gpointer      invocation_hint G_GNUC_UNUSED,
+                                                      gpointer      marshal_data)
 {
-  typedef void (*GMarshalFunc_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64) (gpointer     data1,
-                                                                        gint         arg_1,
-                                                                        gboolean     arg_2,
-                                                                        gint         arg_3,
-                                                                        guint64      arg_4,
-                                                                        gint         arg_5,
-                                                                        guint64      arg_6,
-                                                                        gpointer     data2);
-  register GMarshalFunc_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64 callback;
+  typedef void (*GMarshalFunc_VOID__INT_ENUM_INT_UINT64_INT_UINT64) (gpointer     data1,
+                                                                     gint         arg_1,
+                                                                     gint         arg_2,
+                                                                     gint         arg_3,
+                                                                     guint64      arg_4,
+                                                                     gint         arg_5,
+                                                                     guint64      arg_6,
+                                                                     gpointer     data2);
+  register GMarshalFunc_VOID__INT_ENUM_INT_UINT64_INT_UINT64 callback;
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
 
@@ -169,11 +169,11 @@
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_VOID__INT_ENUM_INT_UINT64_INT_UINT64) (marshal_data ? marshal_data : cc->callback);
 
   callback (data1,
             g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_boolean (param_values + 2),
+            g_marshal_value_peek_enum (param_values + 2),
             g_marshal_value_peek_int (param_values + 3),
             g_marshal_value_peek_uint64 (param_values + 4),
             g_marshal_value_peek_int (param_values + 5),
--- a/gst_plugins_base/gst/tcp/gsttcp-marshal.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcp-marshal.h	Fri Apr 16 15:15:52 2010 +0300
@@ -33,17 +33,17 @@
                                              gpointer      invocation_hint,
                                              gpointer      marshal_data);
 
-/* VOID:INT,BOOLEAN,INT,UINT64,INT,UINT64 (gsttcp-marshal.list:4) */
+/* VOID:INT,ENUM,INT,UINT64,INT,UINT64 (gsttcp-marshal.list:4) */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-extern void gst_tcp_marshal_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64 (GClosure     *closure,
-                                                                     GValue       *return_value,
-                                                                     guint         n_param_values,
-                                                                     const GValue *param_values,
-                                                                     gpointer      invocation_hint,
-                                                                     gpointer      marshal_data);
+extern void gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64 (GClosure     *closure,
+                                                                  GValue       *return_value,
+                                                                  guint         n_param_values,
+                                                                  const GValue *param_values,
+                                                                  gpointer      invocation_hint,
+                                                                  gpointer      marshal_data);
 
 /* BOXED:INT (gsttcp-marshal.list:5) */
 #ifdef __SYMBIAN32__
--- a/gst_plugins_base/gst/tcp/gsttcp-marshal.list	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcp-marshal.list	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,5 @@
 VOID:STRING,UINT
 VOID:INT
 VOID:INT,BOXED
-VOID:INT,BOOLEAN,INT,UINT64,INT,UINT64
+VOID:INT,ENUM,INT,UINT64,INT,UINT64
 BOXED:INT
--- a/gst_plugins_base/gst/tcp/gsttcp.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcp.c	Fri Apr 16 15:15:52 2010 +0300
@@ -37,11 +37,7 @@
 #endif
 
 #include "gsttcp.h"
-#ifdef __SYMBIAN32__
-#include "gst/gst-i18n-plugin.h"
-#else
 #include <gst/gst-i18n-plugin.h>
-#endif
 
 GST_DEBUG_CATEGORY_EXTERN (tcp_debug);
 #define GST_CAT_DEFAULT tcp_debug
@@ -126,15 +122,13 @@
         count - bytes_written, MSG_NOSIGNAL);
 
     if (wrote <= 0) {
+      GST_WARNING ("error while writing");
       return bytes_written;
     }
     bytes_written += wrote;
   }
 
-  if (bytes_written < 0)
-    GST_WARNING ("error while writing");
-  else
-    GST_LOG ("wrote %" G_GSIZE_FORMAT " bytes succesfully", bytes_written);
+  GST_LOG ("wrote %" G_GSIZE_FORMAT " bytes succesfully", bytes_written);
   return bytes_written;
 }
 
--- a/gst_plugins_base/gst/tcp/gsttcp.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcp.h	Fri Apr 16 15:15:52 2010 +0300
@@ -34,6 +34,20 @@
 
 G_BEGIN_DECLS
 
+/**
+ * GstTCPProtocol:
+ * @GST_TCP_PROTOCOL_NONE: Raw data transmission
+ * @GST_TCP_PROTOCOL_GDP: #GstBuffers are wrapped and sent/received using the
+ *      GDP protocol.
+ *
+ * This enum is provided by the tcp/multifd elements to configure the format of
+ * data transmission/reception.
+ *
+ * The GDP protocol wraps data buffers in a header that also carries format
+ * information and timestamps. The None value indicates the data is
+ * sent/received as-is. In that case, format information and timestamping
+ * must be transmitted separately, or implicit in the bytestream itself.
+ */
 typedef enum
 {
   GST_TCP_PROTOCOL_NONE,
--- a/gst_plugins_base/gst/tcp/gsttcpclientsink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcpclientsink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,14 +18,25 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:element-tcpclientsink
+ * @see_also: #tcpclientsrc
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * # server:
+ * nc -l -p 3000
+ * # client:
+ * gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000
+ * ]| everything you type in the client is shown on the server
+ * </refsect2>
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include "gst/gst-i18n-plugin.h"
-#else
 #include <gst/gst-i18n-plugin.h>
-#endif
 #include <gst/dataprotocol/dataprotocol.h>
 #include "gsttcp.h"
 #include "gsttcpclientsink.h"
@@ -146,13 +157,15 @@
 
   g_object_class_install_property (gobject_class, ARG_HOST,
       g_param_spec_string ("host", "Host", "The host/IP to send the packets to",
-          TCP_DEFAULT_HOST, G_PARAM_READWRITE));
+          TCP_DEFAULT_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_PORT,
       g_param_spec_int ("port", "Port", "The port to send the packets to",
-          0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, G_PARAM_READWRITE));
+          0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_PROTOCOL,
       g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in",
-          GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE, G_PARAM_READWRITE));
+          GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state = gst_tcp_client_sink_change_state;
 
--- a/gst_plugins_base/gst/tcp/gsttcpclientsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcpclientsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,16 +18,26 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:element-tcpclientsrc
+ * @see_also: #tcpclientsink
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * # server:
+ * nc -l -p 3000
+ * # client:
+ * gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2
+ * ]| everything you type in the server is shown on the client
+ * </refsect2>
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include "gst/gst-i18n-plugin.h"
-#else
 #include <gst/gst-i18n-plugin.h>
-#endif
 #include "gsttcp.h"
 #include "gsttcpclientsrc.h"
 #include <string.h>             /* memset */
@@ -112,13 +122,15 @@
   g_object_class_install_property (gobject_class, PROP_HOST,
       g_param_spec_string ("host", "Host",
           "The host IP address to receive packets from", TCP_DEFAULT_HOST,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PORT,
       g_param_spec_int ("port", "Port", "The port to receive packets from", 0,
-          TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, G_PARAM_READWRITE));
+          TCP_HIGHEST_PORT, TCP_DEFAULT_PORT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PROTOCOL,
       g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in",
-          GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE, G_PARAM_READWRITE));
+          GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstbasesrc_class->get_caps = gst_tcp_client_src_getcaps;
   gstbasesrc_class->start = gst_tcp_client_src_start;
@@ -140,8 +152,6 @@
   this->protocol = GST_TCP_PROTOCOL_NONE;
   this->caps = NULL;
 
-  gst_base_src_set_live (GST_BASE_SRC (this), TRUE);
-
   GST_OBJECT_FLAG_UNSET (this, GST_TCP_CLIENT_SRC_OPEN);
 }
 
@@ -336,23 +346,12 @@
   GST_DEBUG_OBJECT (src, "connecting to server");
   ret = connect (src->sock_fd.fd, (struct sockaddr *) &src->server_sin,
       sizeof (src->server_sin));
+  if (ret)
+    goto connect_failed;
 
-  if (ret) {
-    gst_tcp_client_src_stop (GST_BASE_SRC (src));
-    switch (errno) {
-      case ECONNREFUSED:
-        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
-            (_("Connection to %s:%d refused."), src->host, src->port), (NULL));
-        return FALSE;
-        break;
-      default:
-        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
-            ("connect to %s:%d failed: %s", src->host, src->port,
-                g_strerror (errno)));
-        return FALSE;
-        break;
-    }
-  }
+  /* add the socket to the poll */
+  gst_poll_add_fd (src->fdset, &src->sock_fd);
+  gst_poll_fd_ctl_read (src->fdset, &src->sock_fd, TRUE);
 
   return TRUE;
 
@@ -372,6 +371,22 @@
     gst_tcp_client_src_stop (GST_BASE_SRC (src));
     return FALSE;
   }
+connect_failed:
+  {
+    gst_tcp_client_src_stop (GST_BASE_SRC (src));
+    switch (errno) {
+      case ECONNREFUSED:
+        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
+            (_("Connection to %s:%d refused."), src->host, src->port), (NULL));
+        break;
+      default:
+        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
+            ("connect to %s:%d failed: %s", src->host, src->port,
+                g_strerror (errno)));
+        break;
+    }
+    return FALSE;
+  }
 }
 
 /* close the socket and associated resources
--- a/gst_plugins_base/gst/tcp/gsttcpserversink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcpserversink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,20 +19,24 @@
  */
 
 /**
- * SECTION:tcpserversink
- * @short_description: a sink that acts as a TCP server and sends data to
- *  multiple clients
+ * SECTION:element-tcpserversink
  * @see_also: #multifdsink
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * # server:
+ * gst-launch fdsrc fd=1 ! tcpserversink protocol=none port=3000
+ * # client:
+ * gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2
+ * ]| 
+ * </refsect2>
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include "gst/gst-i18n-plugin.h"
-#else
 #include <gst/gst-i18n-plugin.h>
-#endif
 #include <string.h>             /* memset */
 
 #include <sys/ioctl.h>
@@ -105,10 +109,11 @@
 
   g_object_class_install_property (gobject_class, ARG_HOST,
       g_param_spec_string ("host", "host", "The host/IP to send the packets to",
-          TCP_DEFAULT_HOST, G_PARAM_READWRITE));
+          TCP_DEFAULT_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_PORT,
       g_param_spec_int ("port", "port", "The port to send the packets to",
-          0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, G_PARAM_READWRITE));
+          0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstmultifdsink_class->init = gst_tcp_server_sink_init_send;
   gstmultifdsink_class->wait = gst_tcp_server_sink_handle_wait;
@@ -158,12 +163,8 @@
   client_sock_fd =
       accept (sink->server_sock.fd, (struct sockaddr *) &client_address,
       &client_address_len);
-  if (client_sock_fd == -1) {
-    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
-        ("Could not accept client on server socket %d: %s (%d)",
-            sink->server_sock.fd, g_strerror (errno), errno));
-    return FALSE;
-  }
+  if (client_sock_fd == -1)
+    goto accept_failed;
 
   gst_multi_fd_sink_add (GST_MULTI_FD_SINK (sink), client_sock_fd);
 
@@ -171,6 +172,15 @@
       inet_ntoa (client_address.sin_addr), client_sock_fd);
 
   return TRUE;
+
+  /* ERRORS */
+accept_failed:
+  {
+    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
+        ("Could not accept client on server socket %d: %s (%d)",
+            sink->server_sock.fd, g_strerror (errno), errno));
+    return FALSE;
+  }
 }
 
 static void
@@ -194,13 +204,18 @@
 
   if (gst_poll_fd_can_read (set, &this->server_sock)) {
     /* handle new client connection on server socket */
-    if (!gst_tcp_server_sink_handle_server_read (this)) {
-      GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
-          ("client connection failed: %s", g_strerror (errno)));
-      return FALSE;
-    }
+    if (!gst_tcp_server_sink_handle_server_read (this))
+      goto connection_failed;
   }
   return TRUE;
+
+  /* ERRORS */
+connection_failed:
+  {
+    GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
+        ("client connection failed: %s", g_strerror (errno)));
+    return FALSE;
+  }
 }
 
 static void
@@ -263,31 +278,23 @@
   GstTCPServerSink *this = GST_TCP_SERVER_SINK (parent);
 
   /* create sending server socket */
-  if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
-    GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM);
-    return FALSE;
-  }
+  if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
+    goto no_socket;
+
   GST_DEBUG_OBJECT (this, "opened sending server socket with fd %d",
       this->server_sock.fd);
 
   /* make address reusable */
   ret = 1;
   if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_REUSEADDR,
-          (void *) &ret, sizeof (ret)) < 0) {
-    gst_tcp_socket_close (&this->server_sock);
-    GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
-        ("Could not setsockopt: %s", g_strerror (errno)));
-    return FALSE;
-  }
+          (void *) &ret, sizeof (ret)) < 0)
+    goto reuse_failed;
+
   /* keep connection alive; avoids SIGPIPE during write */
   ret = 1;
   if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_KEEPALIVE,
-          (void *) &ret, sizeof (ret)) < 0) {
-    gst_tcp_socket_close (&this->server_sock);
-    GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
-        ("Could not setsockopt: %s", g_strerror (errno)));
-    return FALSE;
-  }
+          (void *) &ret, sizeof (ret)) < 0)
+    goto keepalive_failed;
 
   /* name the socket */
   memset (&this->server_sin, 0, sizeof (this->server_sin));
@@ -299,30 +306,17 @@
   GST_DEBUG_OBJECT (this, "binding server socket to address");
   ret = bind (this->server_sock.fd, (struct sockaddr *) &this->server_sin,
       sizeof (this->server_sin));
-
-  if (ret) {
-    gst_tcp_socket_close (&this->server_sock);
-    switch (errno) {
-      default:
-        GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
-            ("bind on port %d failed: %s", this->server_port,
-                g_strerror (errno)));
-        return FALSE;
-        break;
-    }
-  }
+  if (ret)
+    goto bind_failed;
 
   /* set the server socket to nonblocking */
   fcntl (this->server_sock.fd, F_SETFL, O_NONBLOCK);
 
   GST_DEBUG_OBJECT (this, "listening on server socket %d with queue of %d",
       this->server_sock.fd, TCP_BACKLOG);
-  if (listen (this->server_sock.fd, TCP_BACKLOG) == -1) {
-    gst_tcp_socket_close (&this->server_sock);
-    GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
-        ("Could not listen on server socket: %s", g_strerror (errno)));
-    return FALSE;
-  }
+  if (listen (this->server_sock.fd, TCP_BACKLOG) == -1)
+    goto listen_failed;
+
   GST_DEBUG_OBJECT (this,
       "listened on server socket %d, returning from connection setup",
       this->server_sock.fd);
@@ -331,6 +325,46 @@
   gst_poll_fd_ctl_read (parent->fdset, &this->server_sock, TRUE);
 
   return TRUE;
+
+  /* ERRORS */
+no_socket:
+  {
+    GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM);
+    return FALSE;
+  }
+reuse_failed:
+  {
+    gst_tcp_socket_close (&this->server_sock);
+    GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
+        ("Could not setsockopt: %s", g_strerror (errno)));
+    return FALSE;
+  }
+keepalive_failed:
+  {
+    gst_tcp_socket_close (&this->server_sock);
+    GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
+        ("Could not setsockopt: %s", g_strerror (errno)));
+    return FALSE;
+  }
+listen_failed:
+  {
+    gst_tcp_socket_close (&this->server_sock);
+    GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
+        ("Could not listen on server socket: %s", g_strerror (errno)));
+    return FALSE;
+  }
+bind_failed:
+  {
+    gst_tcp_socket_close (&this->server_sock);
+    switch (errno) {
+      default:
+        GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
+            ("bind on port %d failed: %s", this->server_port,
+                g_strerror (errno)));
+        break;
+    }
+    return FALSE;
+  }
 }
 
 static gboolean
--- a/gst_plugins_base/gst/tcp/gsttcpserversrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/tcp/gsttcpserversrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,16 +18,26 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:element-tcpserversrc
+ * @see_also: #tcpserversink
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * # server:
+ * gst-launch tcpserversrc protocol=none port=3000 ! fdsink fd=2
+ * # client:
+ * gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000
+ * ]| 
+ * </refsect2>
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include "gst/gst-i18n-plugin.h"
-#else
 #include <gst/gst-i18n-plugin.h>
-#endif
 #include "gsttcp.h"
 #include "gsttcpserversrc.h"
 #include <string.h>             /* memset */
@@ -110,13 +120,15 @@
 
   g_object_class_install_property (gobject_class, PROP_HOST,
       g_param_spec_string ("host", "Host", "The hostname to listen as",
-          TCP_DEFAULT_LISTEN_HOST, G_PARAM_READWRITE));
+          TCP_DEFAULT_LISTEN_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PORT,
       g_param_spec_int ("port", "Port", "The port to listen to",
-          0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, G_PARAM_READWRITE));
+          0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PROTOCOL,
       g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in",
-          GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE, G_PARAM_READWRITE));
+          GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstbasesrc_class->start = gst_tcp_server_src_start;
   gstbasesrc_class->stop = gst_tcp_server_src_stop;
--- a/gst_plugins_base/gst/typefind/gsttypefindfunctions.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/typefind/gsttypefindfunctions.c	Fri Apr 16 15:15:52 2010 +0300
@@ -23,11 +23,7 @@
 #include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
-
-#include <glib/gstrfuncs.h>
+#include <glib.h>
 
 #include <gst/gsttypefind.h>
 #include <gst/gstelement.h>
@@ -38,13 +34,71 @@
 #include <string.h>
 #include <ctype.h>
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (type_find_debug);
 #define GST_CAT_DEFAULT type_find_debug
 
+/* DataScanCtx: helper for typefind functions that scan through data
+ * step-by-step, to avoid doing a peek at each and every offset */
+
+#define DATA_SCAN_CTX_CHUNK_SIZE 4096
+
+typedef struct
+{
+  guint64 offset;
+  const guint8 *data;
+  gint size;
+} DataScanCtx;
+
+static inline void
+data_scan_ctx_advance (GstTypeFind * tf, DataScanCtx * c, guint bytes_to_skip)
+{
+  c->offset += bytes_to_skip;
+  if (G_LIKELY (c->size > bytes_to_skip)) {
+    c->size -= bytes_to_skip;
+    c->data += bytes_to_skip;
+  } else {
+    c->data += c->size;
+    c->size = 0;
+  }
+}
+
+static inline gboolean
+data_scan_ctx_ensure_data (GstTypeFind * tf, DataScanCtx * c, gint min_len)
+{
+  const guint8 *data;
+  guint64 len;
+  guint chunk_len = MAX (DATA_SCAN_CTX_CHUNK_SIZE, min_len);
+
+  if (G_LIKELY (c->size >= min_len))
+    return TRUE;
+
+  data = gst_type_find_peek (tf, c->offset, chunk_len);
+  if (G_LIKELY (data != NULL)) {
+    c->data = data;
+    c->size = chunk_len;
+    return TRUE;
+  }
+
+  /* if there's less than our chunk size, try to get as much as we can, but
+   * always at least min_len bytes (we might be typefinding the first buffer
+   * of the stream and not have as much data available as we'd like) */
+  len = gst_type_find_get_length (tf);
+  if (len > 0) {
+    len = CLAMP (len - c->offset, min_len, chunk_len);
+  } else {
+    len = min_len;
+  }
+
+  data = gst_type_find_peek (tf, c->offset, len);
+  if (data != NULL) {
+    c->data = data;
+    c->size = len;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
 /*** text/plain ***/
 static gboolean xml_check_first_element (GstTypeFind * tf,
     const gchar * element, guint elen, gboolean strict);
@@ -64,7 +118,8 @@
   guint min_size = 16;          /* minimum size  */
   guint size = 32 * 1024;       /* starting size */
   guint probability = 95;       /* starting probability */
-  guint step = 10;              /* how much we reduce probability in each iteration */
+  guint step = 10;              /* how much we reduce probability in each
+                                 * iteration */
 
   while (probability > step && size > min_size) {
     data = gst_type_find_peek (tf, offset, size);
@@ -359,6 +414,34 @@
     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MID_CAPS);
 }
 
+/*** audio/mobile-xmf ***/
+
+static GstStaticCaps mxmf_caps = GST_STATIC_CAPS ("audio/mobile-xmf");
+
+#define MXMF_CAPS gst_static_caps_get(&mxmf_caps)
+static void
+mxmf_type_find (GstTypeFind * tf, gpointer unused)
+{
+  guint8 *data = NULL;
+
+  /* Search FileId "XMF_" 4 bytes */
+  data = gst_type_find_peek (tf, 0, 4);
+  if (data && data[0] == 'X' && data[1] == 'M' && data[2] == 'F'
+      && data[3] == '_') {
+    /* Search Format version "2.00" 4 bytes */
+    data = gst_type_find_peek (tf, 4, 4);
+    if (data && data[0] == '2' && data[1] == '.' && data[2] == '0'
+        && data[3] == '0') {
+      /* Search TypeId 2     1 byte */
+      data = gst_type_find_peek (tf, 11, 1);
+      if (data && data[0] == 2) {
+        gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXMF_CAPS);
+      }
+    }
+  }
+}
+
+
 /*** video/x-fli ***/
 
 static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli");
@@ -469,18 +552,79 @@
 static void
 flac_type_find (GstTypeFind * tf, gpointer unused)
 {
-  guint8 *data;
-
-  data = gst_type_find_peek (tf, 0, 5);
-  if (G_LIKELY (data)) {
-    /* standard flac */
-    if (memcmp (data, "fLaC", 4) == 0) {
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
+  DataScanCtx c = { 0, NULL, 0 };
+
+  if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
+    return;
+
+  /* standard flac (also old/broken flac-in-ogg with an initial 4-byte marker
+   * packet and without the usual packet framing) */
+  if (memcmp (c.data, "fLaC", 4) == 0) {
+    gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
+    return;
+  }
+
+  if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
+    return;
+
+  /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */
+  if (memcmp (c.data, "\177FLAC\001", 6) == 0) {
+    gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
+    return;
+  }
+
+  /* flac without headers (subset format) */
+  /* 64K should be enough */
+  while (c.offset < (64 * 1024)) {
+    if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
+      break;
+
+    /* look for frame header,
+     * http://flac.sourceforge.net/format.html#frame_header
+     */
+    if (c.data[0] == 0xff && (c.data[1] >> 2) == 0x3e) {
+      /* bit 15 in the header must be 0 */
+      if (((c.data[1] >> 1) & 0x01) == 0x01)
+        goto advance;
+
+      /* blocksize must be != 0x00 */
+      if ((c.data[2] >> 4) == 0x00)
+        goto advance;
+
+      /* samplerate must be != 0x0f */
+      if ((c.data[2] & 0x0f) == 0x0f)
+        goto advance;
+      /* also 0 is invalid, as it means get the info from the header and we
+       * don't have headers if we are here */
+      if ((c.data[2] & 0x0f) == 0x00)
+        goto advance;
+
+      /* channel assignment must be < 11 */
+      if ((c.data[3] >> 4) >= 11)
+        goto advance;
+
+      /* sample size must be != 0x07 and != 0x05 */
+      if (((c.data[3] >> 1) & 0x07) == 0x07)
+        goto advance;
+      if (((c.data[3] >> 1) & 0x07) == 0x05)
+        goto advance;
+      /* also 0 is invalid, as it means get the info from the header and we
+       * don't have headers if we are here */
+      if (((c.data[3] >> 1) & 0x07) == 0x00)
+        goto advance;
+
+      /* next bit must be 0 */
+      if ((c.data[3] & 0x01) == 0x01)
+        goto advance;
+
+      /* FIXME: shouldn't we include the crc check ? */
+
+      GST_DEBUG ("Found flac without headers at %d", (gint) c.offset);
+      gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, FLAC_CAPS);
+      return;
     }
-    /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */
-    else if (memcmp (data, "\177FLAC\001", 6) == 0) {
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
-    }
+  advance:
+    data_scan_ctx_advance (tf, &c, 1);
   }
 }
 
@@ -493,68 +637,58 @@
 static void
 aac_type_find (GstTypeFind * tf, gpointer unused)
 {
-  guint8 *data = gst_type_find_peek (tf, 0, AAC_AMOUNT);
-  gint snc;
-
-  /* detect adts header or adif header.
-   * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
-   * the other hand, is 14 bits only, so we require one valid frame with
-   * again a valid syncpoint on the next one (28 bits) for certainty. We
-   * require 4 kB, which is quite a lot, since frames are generally 200-400
-   * bytes.
-   */
-  if (data) {
-    gint n;
-
-    for (n = 0; n < AAC_AMOUNT - 3; n++) {
-      snc = GST_READ_UINT16_BE (&data[n]);
+  DataScanCtx c = { 0, NULL, 0 };
+
+  while (c.offset < AAC_AMOUNT) {
+    guint snc, len;
+
+    /* detect adts header or adif header.
+     * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
+     * the other hand, is 14 bits only, so we require one valid frame with
+     * again a valid syncpoint on the next one (28 bits) for certainty. We
+     * require 4 kB, which is quite a lot, since frames are generally 200-400
+     * bytes.
+     */
+    if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
+      break;
+
+    snc = GST_READ_UINT16_BE (c.data);
+    if (G_UNLIKELY ((snc & 0xfff6) == 0xfff0)) {
+      /* ADTS header - find frame length */
+      GST_DEBUG ("Found one ADTS syncpoint at offset 0x%" G_GINT64_MODIFIER
+          "x, tracing next...", c.offset);
+      len = ((c.data[3] & 0x03) << 11) |
+          (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
+
+      if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
+        GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
+        goto next;
+      }
+
+      snc = GST_READ_UINT16_BE (c.data + len);
       if ((snc & 0xfff6) == 0xfff0) {
-        /* ADTS header - find frame length */
-        gint len;
-
-        GST_DEBUG ("Found one ADTS syncpoint at offset 0x%x, tracing next...",
-            n);
-        if (AAC_AMOUNT - n < 5) {
-          GST_DEBUG ("Not enough data to parse ADTS header");
-          break;
-        }
-        len = ((data[n + 3] & 0x03) << 11) |
-            (data[n + 4] << 3) | ((data[n + 5] & 0xe0) >> 5);
-        if (n + len + 2 >= AAC_AMOUNT) {
-          GST_DEBUG ("Next frame is not within reach");
-          break;
-        } else if (len == 0) {
-          continue;
-        }
-
-        snc = GST_READ_UINT16_BE (&data[n + len]);
-        if ((snc & 0xfff6) == 0xfff0) {
-          gint mpegversion = (data[n + 1] & 0x08) ? 2 : 4;
-          GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
-              "framed", G_TYPE_BOOLEAN, FALSE,
-              "mpegversion", G_TYPE_INT, mpegversion,
-              NULL);
-
-          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
-          gst_caps_unref (caps);
-
-          GST_DEBUG ("Found ADTS-%d syncpoint at offset 0x%x (framelen %u)",
-              mpegversion, n, len);
-          break;
-        }
-
-        GST_DEBUG ("No next frame found... (should be at 0x%x)", n + len);
-      } else if (!memcmp (&data[n], "ADIF", 4)) {
-        /* ADIF header */
-        GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
+        gint mpegversion;
+
+        mpegversion = (c.data[1] & 0x08) ? 2 : 4;
+        GST_DEBUG ("Found second ADTS-%d syncpoint at offset 0x%"
+            G_GINT64_MODIFIER "x, framelen %u", mpegversion, c.offset, len);
+        gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
             "framed", G_TYPE_BOOLEAN, FALSE,
-            "mpegversion", G_TYPE_INT, 4,
-            NULL);
-
-        gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
-        gst_caps_unref (caps);
+            "mpegversion", G_TYPE_INT, mpegversion, NULL);
+        break;
       }
+
+      GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
+    } else if (!memcmp (c.data, "ADIF", 4)) {
+      /* ADIF header */
+      gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
+          "framed", G_TYPE_BOOLEAN, FALSE, "mpegversion", G_TYPE_INT, 4, NULL);
+      break;
     }
+
+  next:
+
+    data_scan_ctx_advance (tf, &c, 1);
   }
 }
 
@@ -801,6 +935,10 @@
         offset += length;
       }
       g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
+      if (head_data == NULL &&
+          gst_type_find_peek (tf, offset + start_off - 1, 1) == NULL)
+        /* Incomplete last frame - don't count it. */
+        found--;
       if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
           (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
         /* we can make a valid guess */
@@ -898,35 +1036,41 @@
 
 suggest:
   {
-    GstCaps *caps;
-
-    g_assert (layer > 0);
-
-    caps = gst_caps_make_writable (MP3_CAPS);
-    gst_structure_set (gst_caps_get_structure (caps, 0), "layer",
-        G_TYPE_INT, layer, NULL);
-    gst_type_find_suggest (tf, prob, caps);
-    gst_caps_unref (caps);
-    return;
+    g_return_if_fail (layer >= 1 && layer <= 3);
+
+    gst_type_find_suggest_simple (tf, prob, "audio/mpeg",
+        "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL);
   }
 }
 
 /*** audio/x-musepack ***/
 
-static GstStaticCaps musepack_caps = GST_STATIC_CAPS ("audio/x-musepack");
+static GstStaticCaps musepack_caps =
+GST_STATIC_CAPS ("audio/x-musepack, streamversion= (int) { 7, 8 }");
 
 #define MUSEPACK_CAPS (gst_static_caps_get(&musepack_caps))
 static void
 musepack_type_find (GstTypeFind * tf, gpointer unused)
 {
   guint8 *data = gst_type_find_peek (tf, 0, 4);
+  GstTypeFindProbability prop = GST_TYPE_FIND_MINIMUM;
+  gint streamversion = -1;
 
   if (data && memcmp (data, "MP+", 3) == 0) {
+    streamversion = 7;
     if ((data[3] & 0x7f) == 7) {
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MUSEPACK_CAPS);
+      prop = GST_TYPE_FIND_MAXIMUM;
     } else {
-      gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, MUSEPACK_CAPS);
+      prop = GST_TYPE_FIND_LIKELY + 10;
     }
+  } else if (data && memcmp (data, "MPCK", 4) == 0) {
+    streamversion = 8;
+    prop = GST_TYPE_FIND_MAXIMUM;
+  }
+
+  if (streamversion != -1) {
+    gst_type_find_suggest_simple (tf, prop, "audio/x-musepack",
+        "streamversion", G_TYPE_INT, streamversion, NULL);
   }
 }
 
@@ -1027,6 +1171,15 @@
   }
 }
 
+/*** gsm ***/
+
+/* can only be detected by using the extension, in which case we use the default
+ * GSM properties */
+static GstStaticCaps gsm_caps =
+GST_STATIC_CAPS ("audio/x-gsm, rate=8000, channels=1");
+
+#define GSM_CAPS (gst_static_caps_get(&gsm_caps))
+
 /*** wavpack ***/
 
 static GstStaticCaps wavpack_caps =
@@ -1136,10 +1289,7 @@
     }
     if (*x == '\n' &&
         !g_ascii_strncasecmp ("content-type:", (gchar *) x + 1, 13)) {
-      GstCaps *caps = gst_caps_copy (MULTIPART_CAPS);
-
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, caps);
-      gst_caps_unref (caps);
+      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MULTIPART_CAPS);
       return;
     }
   }
@@ -1150,9 +1300,9 @@
     "systemstream = (boolean) true, mpegversion = (int) [ 1, 2 ]");
 
 #define MPEG_SYS_CAPS gst_static_caps_get(&mpeg_sys_caps)
-#define IS_MPEG_HEADER(data)            ((((guint8 *)(data))[0] == 0x00) &&  \
+#define IS_MPEG_HEADER(data) (G_UNLIKELY((((guint8 *)(data))[0] == 0x00) &&  \
                                          (((guint8 *)(data))[1] == 0x00) &&  \
-                                         (((guint8 *)(data))[2] == 0x01))
+                                         (((guint8 *)(data))[2] == 0x01)))
 
 #define IS_MPEG_PACK_CODE(b) ((b) == 0xBA)
 #define IS_MPEG_SYS_CODE(b) ((b) == 0xBB)
@@ -1171,7 +1321,7 @@
 #define MPEG2_MAX_SYS_HEADERS 5
 
 static gboolean
-mpeg_sys_is_valid_pack (GstTypeFind * tf, guint8 * data, guint len,
+mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len,
     guint * pack_size)
 {
   /* Check the pack header @ offset for validity, assuming that the 4 byte header
@@ -1387,7 +1537,6 @@
   return;
 suggest:
   {
-    GstCaps *caps = gst_caps_copy (MPEG_SYS_CAPS);
     guint prob;
 
     prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers));
@@ -1400,10 +1549,9 @@
     GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n",
         mpegversion, pack_headers, pes_headers, prob);
 
-    gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
-        G_TYPE_INT, mpegversion, NULL);
-    gst_type_find_suggest (tf, prob, caps);
-    gst_caps_unref (caps);
+    gst_type_find_suggest_simple (tf, prob, "video/mpeg",
+        "systemstream", G_TYPE_BOOLEAN, TRUE,
+        "mpegversion", G_TYPE_INT, mpegversion, NULL);
   }
 };
 
@@ -1481,18 +1629,15 @@
         found = mpeg_ts_probe_headers (tf, skipped, pack_sizes[p]);
         if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) {
           gint probability;
-          GstCaps *caps = gst_caps_copy (MPEGTS_CAPS);
-
-          gst_structure_set (gst_caps_get_structure (caps, 0), "packetsize",
-              G_TYPE_INT, pack_sizes[p], NULL);
 
           /* found at least 4 headers. 10 headers = MAXIMUM probability. 
            * Arbitrarily, I assigned 10% probability for each header we
            * found, 40% -> 100% */
           probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
 
-          gst_type_find_suggest (tf, probability, caps);
-          gst_caps_unref (caps);
+          gst_type_find_suggest_simple (tf, probability, "video/mpegts",
+              "systemstream", G_TYPE_BOOLEAN, TRUE,
+              "packetsize", G_TYPE_INT, pack_sizes[p], NULL);
           return;
         }
       }
@@ -1535,10 +1680,8 @@
         seen_vos = TRUE;
       } else if (sc >= 0x20 && sc <= 0x2F) {    /* video_object_layer_start_code */
         if (seen_vos) {
-          GstCaps *caps = gst_caps_copy (MPEG4_VIDEO_CAPS);
-
-          gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps);
-          gst_caps_unref (caps);
+          gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN,
+              MPEG4_VIDEO_CAPS);
           return;
         } else
           return;
@@ -1560,11 +1703,11 @@
 static void
 h264_video_type_find (GstTypeFind * tf, gpointer unused)
 {
+  DataScanCtx c = { 0, NULL, 0 };
+
   /* Stream consists of: a series of sync codes (00 00 00 01) followed 
    * by NALs
    */
-  guint8 *data = NULL;
-  int offset = 0;
   int stat_slice = 0;
   int stat_dpa = 0;
   int stat_dpb = 0;
@@ -1574,15 +1717,17 @@
   int stat_pps = 0;
   int nut, ref;
 
-  while (offset < H264_MAX_PROBE_LENGTH) {
-    data = gst_type_find_peek (tf, offset, 4);
-    if (data && IS_MPEG_HEADER (data)) {
-      nut = data[3] & 0x9f;     /* forbiden_zero_bit | nal_unit_type */
-      ref = data[3] & 0x60;     /* nal_ref_idc */
+  while (c.offset < H264_MAX_PROBE_LENGTH) {
+    if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
+      break;
+
+    if (IS_MPEG_HEADER (c.data)) {
+      nut = c.data[3] & 0x9f;   /* forbiden_zero_bit | nal_unit_type */
+      ref = c.data[3] & 0x60;   /* nal_ref_idc */
 
       /* if forbiden bit is different to 0 won't be h264 */
       if (nut > 0x1f)
-        goto done;
+        break;
 
       /* collect statistics about the NAL types */
       if (nut == 1)
@@ -1600,23 +1745,16 @@
       else if ((nut == 8) && (ref != 0))
         stat_pps++;
 
-      offset += 4;
+      if ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
+          stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
+        gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS);
+        return;
+      }
+
+      data_scan_ctx_advance (tf, &c, 4);
     }
-    offset += 1;
-
-    if ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
-        stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
-      GstCaps *caps = gst_caps_copy (H264_VIDEO_CAPS);
-
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps);
-      gst_caps_unref (caps);
-
-      goto done;
-    }
+    data_scan_ctx_advance (tf, &c, 1);
   }
-
-done:
-  return;
 }
 
 /*** video/mpeg video stream ***/
@@ -1624,23 +1762,6 @@
 static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, "
     "systemstream = (boolean) false");
 #define MPEG_VIDEO_CAPS gst_static_caps_get(&mpeg_video_caps)
-static void
-mpeg_video_type_find (GstTypeFind * tf, gpointer unused)
-{
-  static const guint8 sequence_header[] = { 0x00, 0x00, 0x01, 0xb3 };
-  guint8 *data = NULL;
-
-  data = gst_type_find_peek (tf, 0, 8);
-
-  if (data && memcmp (data, sequence_header, 4) == 0) {
-    GstCaps *caps = gst_caps_copy (MPEG_VIDEO_CAPS);
-
-    gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
-        G_TYPE_INT, 1, NULL);
-    gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, caps);
-    gst_caps_unref (caps);
-  }
-}
 
 /*
  * Idea is the same as MPEG system stream typefinding: We check each
@@ -1653,85 +1774,97 @@
 
 #define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6
 #define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024)      /* 100 kB */
-#define GST_MPEGVID_TYPEFIND_SYNC_SIZE 2048
 
 static void
 mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
 {
-  gint size = 0, found = 0;
-  guint64 skipped = 0;
-  guint8 *data = NULL;
-
-  while (1) {
-    if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) {
-      GstCaps *caps = gst_caps_copy (MPEG_VIDEO_CAPS);
-
-      gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
-          G_TYPE_INT, 1, NULL);
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 2, caps);
-      gst_caps_unref (caps);
+  DataScanCtx c = { 0, NULL, 0 };
+  gboolean seen_seq_at_0 = FALSE;
+  gboolean seen_seq = FALSE;
+  gboolean seen_gop = FALSE;
+  guint64 last_pic_offset = 0;
+  guint num_pic_headers = 0;
+  gint found = 0;
+
+  while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) {
+    if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
+      break;
+
+    if (!data_scan_ctx_ensure_data (tf, &c, 5))
+      break;
+
+    if (!IS_MPEG_HEADER (c.data))
+      goto next;
+
+    /* a pack header indicates that this isn't an elementary stream */
+    if (c.data[3] == 0xBA && mpeg_sys_is_valid_pack (tf, c.data, c.size, NULL))
       return;
+
+    /* do we have a sequence header? */
+    if (c.data[3] == 0xB3) {
+      seen_seq_at_0 = seen_seq_at_0 || (c.offset == 0);
+      seen_seq = TRUE;
+      data_scan_ctx_advance (tf, &c, 4 + 8);
+      continue;
     }
 
-    if (skipped > GST_MPEGVID_TYPEFIND_TRY_SYNC)
-      break;
-
-    if (size < 5) {
-      data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE);
-      if (!data)
-        break;
-      size = GST_MPEGVID_TYPEFIND_SYNC_SIZE;
+    /* or a GOP header */
+    if (c.data[3] == 0xB8) {
+      seen_gop = TRUE;
+      data_scan_ctx_advance (tf, &c, 8);
+      continue;
+    }
+
+    /* but what we'd really like to see is a picture header */
+    if (c.data[3] == 0x00) {
+      ++num_pic_headers;
+      last_pic_offset = c.offset;
+      data_scan_ctx_advance (tf, &c, 8);
+      continue;
     }
 
-    if (IS_MPEG_HEADER (data)) {
-      /* An MPEG PACK header indicates that this isn't an elementary stream */
-      if (IS_MPEG_PACK_CODE (data[3])) {
-        if (mpeg_sys_is_valid_pack (tf, data, size, NULL))
-          break;
-      }
-
-      /* are we a sequence (0xB3) or GOP (0xB8) header? */
-      if (data[3] == 0xB3 || data[3] == 0xB8) {
-        size -= 8;
-        data += 8;
-        skipped += 8;
-        if (data[3] == 0xB3)
-          continue;
-        else if (size < 4) {
-          data =
-              gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE);
-          size = GST_MPEGVID_TYPEFIND_SYNC_SIZE;
-          if (!data)
-            break;
-        }
-        /* else, we should now see an image */
-      }
+    /* ... each followed by a slice header with slice_vertical_pos=1 that's
+     * not too far away from the previously seen picture header. */
+    if (c.data[3] == 0x01 && num_pic_headers > found &&
+        (c.offset - last_pic_offset) >= 4 &&
+        (c.offset - last_pic_offset) <= 64) {
+      data_scan_ctx_advance (tf, &c, 4);
+      found += 1;
+      continue;
     }
 
-    /* image header (and, when found, slice header) */
-    if (IS_MPEG_HEADER (data) && data[4] == 0x0) {
-      size -= 8;
-      data += 8;
-      skipped += 8;
-      if (size < 5) {
-        data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE);
-        size = GST_MPEGVID_TYPEFIND_SYNC_SIZE;
-        if (!data)
-          break;
-      }
-      if ((IS_MPEG_HEADER (data) && data[3] == 0x1) ||
-          (IS_MPEG_HEADER (data + 1) && data[4] == 0x1)) {
-        size -= 4;
-        data += 4;
-        skipped += 4;
-        found += 1;
-        continue;
-      }
-    }
-
-    size--;
-    data++;
-    skipped++;
+  next:
+
+    data_scan_ctx_advance (tf, &c, 1);
+  }
+
+  if (found > 0 || seen_seq) {
+    GstTypeFindProbability probability = 0;
+
+    GST_LOG ("Found %d pictures, seq:%d, gop:%d", found, seen_seq, seen_gop);
+
+    if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq && seen_gop)
+      probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1;
+    else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq)
+      probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9;
+    else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
+      probability = GST_TYPE_FIND_LIKELY;
+    else if (seen_seq_at_0 && seen_gop && found > 2)
+      probability = GST_TYPE_FIND_LIKELY - 10;
+    else if (seen_seq && seen_gop && found > 2)
+      probability = GST_TYPE_FIND_LIKELY - 20;
+    else if (seen_seq_at_0 && found > 0)
+      probability = GST_TYPE_FIND_POSSIBLE;
+    else if (seen_seq && found > 0)
+      probability = GST_TYPE_FIND_POSSIBLE - 5;
+    else if (found > 0)
+      probability = GST_TYPE_FIND_POSSIBLE - 10;
+    else if (seen_seq)
+      probability = GST_TYPE_FIND_POSSIBLE - 20;
+
+    gst_type_find_suggest_simple (tf, probability, "video/mpeg",
+        "systemstream", G_TYPE_BOOLEAN, FALSE,
+        "mpegversion", G_TYPE_INT, 1, NULL);
   }
 }
 
@@ -1876,6 +2009,38 @@
 
 }
 
+/*** video/mj2 and image/jp2 ***/
+static GstStaticCaps mj2_caps = GST_STATIC_CAPS ("video/mj2");
+
+#define MJ2_CAPS gst_static_caps_get(&mj2_caps)
+
+static GstStaticCaps jp2_caps = GST_STATIC_CAPS ("image/jp2");
+
+#define JP2_CAPS gst_static_caps_get(&jp2_caps)
+
+static void
+jp2_type_find (GstTypeFind * tf, gpointer unused)
+{
+  guint8 *data;
+
+  data = gst_type_find_peek (tf, 0, 24);
+  if (!data)
+    return;
+
+  /* jp2 signature */
+  if (memcmp (data, "\000\000\000\014jP  \015\012\207\012", 12) != 0)
+    return;
+
+  /* check ftyp box */
+  data += 12;
+  if (memcmp (data + 4, "ftyp", 4) == 0) {
+    if (memcmp (data + 8, "jp2 ", 4) == 0)
+      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JP2_CAPS);
+    else if (memcmp (data + 8, "mjp2", 4) == 0)
+      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MJ2_CAPS);
+  }
+}
+
 /*** video/quicktime ***/
 
 static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime");
@@ -1892,6 +2057,8 @@
   guint64 size;
 
   while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) {
+    guint64 new_offset;
+
     /* box/atom types that are in common with ISO base media file format */
     if (STRNCMP (&data[4], "moov", 4) == 0 ||
         STRNCMP (&data[4], "mdat", 4) == 0 ||
@@ -1929,7 +2096,10 @@
       if (size < 8)
         break;
     }
-    offset += size;
+    new_offset = offset + size;
+    if (new_offset <= offset)
+      break;
+    offset = new_offset;
   }
   if (tip > 0) {
     gst_type_find_suggest (tf, tip, QT_CAPS);
@@ -2157,16 +2327,58 @@
 static void
 bmp_type_find (GstTypeFind * tf, gpointer unused)
 {
-  guint8 *data = gst_type_find_peek (tf, 0, 18);
-
-  if (data && memcmp (data, "BM", 2) == 0) {
-    if ((data[14] == 0x0C ||
-            data[14] == 0x28 ||
-            data[14] == 0xF0) &&
-        data[15] == 0 && data[16] == 0 && data[17] == 0) {
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, BMP_CAPS);
-    }
+  DataScanCtx c = { 0, NULL, 0 };
+  guint32 struct_size, w, h, planes, bpp;
+
+  if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 54)))
+    return;
+
+  if (c.data[0] != 'B' || c.data[1] != 'M')
+    return;
+
+  /* skip marker + size */
+  data_scan_ctx_advance (tf, &c, 2 + 4);
+
+  /* reserved, must be 0 */
+  if (c.data[0] != 0 || c.data[1] != 0 || c.data[2] != 0 || c.data[3] != 0)
+    return;
+
+  data_scan_ctx_advance (tf, &c, 2 + 2);
+
+  /* offset to start of image data in bytes (check for sanity) */
+  GST_LOG ("offset=%u", GST_READ_UINT32_LE (c.data));
+  if (GST_READ_UINT32_LE (c.data) > (10 * 1024 * 1024))
+    return;
+
+  struct_size = GST_READ_UINT32_LE (c.data + 4);
+  GST_LOG ("struct_size=%u", struct_size);
+
+  data_scan_ctx_advance (tf, &c, 4 + 4);
+
+  if (struct_size == 0x0C) {
+    w = GST_READ_UINT16_LE (c.data);
+    h = GST_READ_UINT16_LE (c.data + 2);
+    planes = GST_READ_UINT16_LE (c.data + 2 + 2);
+    bpp = GST_READ_UINT16_LE (c.data + 2 + 2 + 2);
+  } else if (struct_size == 40 || struct_size == 64 || struct_size == 108
+      || struct_size == 124 || struct_size == 0xF0) {
+    w = GST_READ_UINT32_LE (c.data);
+    h = GST_READ_UINT32_LE (c.data + 4);
+    planes = GST_READ_UINT16_LE (c.data + 4 + 4);
+    bpp = GST_READ_UINT16_LE (c.data + 4 + 4 + 2);
+  } else {
+    return;
   }
+
+  /* image sizes sanity check */
+  GST_LOG ("w=%u, h=%u, planes=%u, bpp=%u", w, h, planes, bpp);
+  if (w == 0 || w > 0xfffff || h == 0 || h > 0xfffff || planes != 1 ||
+      (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32))
+    return;
+
+  gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "image/bmp",
+      "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, "bpp", G_TYPE_INT, bpp,
+      NULL);
 }
 
 /*** image/tiff ***/
@@ -2298,6 +2510,52 @@
     }
 }
 
+/*** application/mxf ***/
+static GstStaticCaps mxf_caps = GST_STATIC_CAPS ("application/mxf");
+
+#define MXF_MAX_PROBE_LENGTH (1024 * 64)
+#define MXF_CAPS (gst_static_caps_get(&mxf_caps))
+
+/*
+ * MXF files start with a header partition pack key of 16 bytes which is defined
+ * at SMPTE-377M 6.1. Before this there can be up to 64K of run-in which _must_
+ * not contain the partition pack key.
+ */
+static void
+mxf_type_find (GstTypeFind * tf, gpointer ununsed)
+{
+  static const guint8 partition_pack_key[] =
+      { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+    0x01
+  };
+  DataScanCtx c = { 0, NULL, 0 };
+
+  while (c.offset <= MXF_MAX_PROBE_LENGTH) {
+    if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 16)))
+      break;
+
+    if (memcmp (c.data, partition_pack_key, 13) == 0) {
+      /* Header partition pack? */
+      if (c.data[13] != 0x02)
+        goto advance;
+
+      /* Partition status */
+      if (c.data[14] >= 0x05)
+        goto advance;
+
+      /* Reserved, must be 0x00 */
+      if (c.data[15] != 0x00)
+        goto advance;
+
+      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXF_CAPS);
+      return;
+    }
+
+  advance:
+    data_scan_ctx_advance (tf, &c, 1);
+  }
+}
+
 /*** video/x-dv ***/
 
 static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, "
@@ -2311,21 +2569,18 @@
   data = gst_type_find_peek (tf, 0, 5);
 
   /* check for DIF  and DV flag */
-  if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00) &&
-      ((data[4] & 0x01) == 0)) {
-    gchar *format;
-    GstCaps *caps = gst_caps_copy (DV_CAPS);
+  if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00)) {
+    const gchar *format;
 
     if (data[3] & 0x80) {
       format = "PAL";
     } else {
       format = "NTSC";
     }
-    gst_structure_set (gst_caps_get_structure (caps, 0), "format",
-        G_TYPE_STRING, format, NULL);
-
-    gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, caps);
-    gst_caps_unref (caps);
+
+    gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "video/x-dv",
+        "systemstream", G_TYPE_BOOLEAN, TRUE,
+        "format", G_TYPE_STRING, format, NULL);
   }
 }
 
@@ -2333,8 +2588,10 @@
 /*** application/ogg and application/x-annodex ***/
 static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg");
 static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex");
-
-#define OGGANX_CAPS (gst_static_caps_get(&annodex_caps))
+static GstStaticCaps ogg_annodex_caps =
+    GST_STATIC_CAPS ("application/ogg;application/x-annodex");
+
+#define OGGANX_CAPS (gst_static_caps_get(&ogg_annodex_caps))
 
 static void
 ogganx_type_find (GstTypeFind * tf, gpointer private)
@@ -2346,7 +2603,8 @@
     /* Check for an annodex fishbone header */
     data = gst_type_find_peek (tf, 28, 8);
     if (data && memcmp (data, "fishead\0", 8) == 0)
-      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGGANX_CAPS);
+      gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
+          gst_static_caps_get (&annodex_caps));
 
     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
         gst_static_caps_get (&ogg_caps));
@@ -2418,6 +2676,35 @@
   }
 }
 
+/*** kate ***/
+static void
+kate_type_find (GstTypeFind * tf, gpointer private)
+{
+  guint8 *data = gst_type_find_peek (tf, 0, 64);
+  gchar category[16] = { 0, };
+
+  if (G_UNLIKELY (data == NULL))
+    return;
+
+  /* see: http://wiki.xiph.org/index.php/OggKate#Format_specification */
+  if (G_LIKELY (memcmp (data, "\200kate\0\0\0", 8) != 0))
+    return;
+
+  /* make sure we always have a NUL-terminated string */
+  memcpy (category, data + 48, 15);
+  GST_LOG ("kate category: %s", category);
+  /* canonical categories for subtitles: subtitles, spu-subtitles, SUB, K-SPU */
+  if (strcmp (category, "subtitles") == 0 || strcmp (category, "SUB") == 0 ||
+      strcmp (category, "spu-subtitles") == 0 ||
+      strcmp (category, "K-SPU") == 0) {
+    gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM,
+        "subtitle/x-kate", NULL);
+  } else {
+    gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM,
+        "application/x-kate", NULL);
+  }
+}
+
 /*** application/x-ogm-video or audio***/
 
 static GstStaticCaps ogmvideo_caps =
@@ -2501,6 +2788,26 @@
   }
 }
 
+/*** audio/x-celt ***/
+
+static GstStaticCaps celt_caps = GST_STATIC_CAPS ("audio/x-celt");
+
+#define CELT_CAPS (gst_static_caps_get(&celt_caps))
+static void
+celt_type_find (GstTypeFind * tf, gpointer private)
+{
+  guint8 *data = gst_type_find_peek (tf, 0, 8);
+
+  if (data) {
+    /* 8 byte string "CELT   " */
+    if (memcmp (data, "CELT    ", 8) != 0)
+      return;
+
+    /* TODO: Check other values of the CELT header */
+    gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CELT_CAPS);
+  }
+}
+
 /*** application/x-ogg-skeleton ***/
 static GstStaticCaps ogg_skeleton_caps =
 GST_STATIC_CAPS ("application/x-ogg-skeleton, parsed=(boolean)FALSE");
@@ -2718,11 +3025,7 @@
   if (data && data[0] == 0x24 && data[1] == 0x48 &&
       GST_READ_UINT16_LE (data + 2) > 2 + 2 + 4 + 2 + 2 + 16 &&
       memcmp (data + 2 + 2 + 4 + 2 + 2, asf_marker, 16) == 0) {
-    GstCaps *caps = gst_caps_copy (MMSH_CAPS);
-
-    gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
-    gst_caps_unref (caps);
-    return;
+    gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MMSH_CAPS);
   }
 }
 
@@ -2903,13 +3206,16 @@
   };
   static gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL };
   static gchar *ac3_exts[] = { "ac3", NULL };
-  static gchar *musepack_exts[] = { "mpc", NULL };
+  static gchar *gsm_exts[] = { "gsm", NULL };
+  static gchar *musepack_exts[] = { "mpc", "mpp", "mp+", NULL };
   static gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL };
   static gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL };
   static gchar *mpeg_ts_exts[] = { "ts", NULL };
   static gchar *ogg_exts[] = { "anx", "ogg", "ogm", NULL };
   static gchar *qt_exts[] = { "mov", NULL };
   static gchar *qtif_exts[] = { "qif", "qtif", "qti", NULL };
+  static gchar *mj2_exts[] = { "mj2", NULL };
+  static gchar *jp2_exts[] = { "jp2", NULL };
   static gchar *rm_exts[] = { "ra", "ram", "rm", "rmvb", NULL };
   static gchar *swf_exts[] = { "swf", "swfl", NULL };
   static gchar *utf8_exts[] = { "txt", NULL };
@@ -2968,7 +3274,13 @@
   static gchar *vivo_exts[] = { "viv", NULL };
   static gchar *nsf_exts[] = { "nsf", NULL };
   static gchar *mid_exts[] = { "mid", "midi", NULL };
+  static gchar *mxmf_exts[] = { "mxmf", NULL };
   static gchar *imelody_exts[] = { "imy", "ime", "imelody", NULL };
+  static gchar *pdf_exts[] = { "pdf", NULL };
+  static gchar *mxf_exts[] = { "mxf", NULL };
+  static gchar *msword_exts[] = { "doc", NULL };
+  static gchar *dsstore_exts[] = { "DS_Store", NULL };
+  static gchar *psd_exts[] = { "psd", NULL };
 
   GST_DEBUG_CATEGORY_INIT (type_find_debug, "typefindfunctions",
       GST_DEBUG_FG_GREEN | GST_DEBUG_BG_RED, "generic type find functions");
@@ -2999,6 +3311,8 @@
 #endif
   TYPE_FIND_REGISTER (plugin, "audio/midi", GST_RANK_PRIMARY, mid_type_find,
       mid_exts, MID_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "audio/mobile-xmf", GST_RANK_PRIMARY,
+      mxmf_type_find, mxmf_exts, MXMF_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "video/x-fli", GST_RANK_MARGINAL, flx_type_find,
       flx_exts, FLX_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/x-id3v2", GST_RANK_PRIMARY + 103,
@@ -3015,23 +3329,23 @@
       mp3_exts, MP3_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find,
       ac3_exts, AC3_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "audio/x-gsm", GST_RANK_PRIMARY, NULL,
+      gsm_exts, GSM_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
       mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
       mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
       ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL);
-  TYPE_FIND_REGISTER (plugin, "video/mpeg,elementary", GST_RANK_SECONDARY,
-      mpeg_video_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL, NULL);
-  TYPE_FIND_REGISTER (plugin, "video/mpeg-stream", GST_RANK_MARGINAL,
+  TYPE_FIND_REGISTER (plugin, "video/mpeg-elementary", GST_RANK_MARGINAL,
       mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL,
       NULL);
   TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY,
       mpeg4_video_type_find, m4v_exts, MPEG_VIDEO_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "video/x-h264", GST_RANK_PRIMARY,
       h264_video_type_find, h264_exts, MPEG_VIDEO_CAPS, NULL, NULL);
-  TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY,
-      nuv_type_find, nuv_exts, NUV_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY, nuv_type_find,
+      nuv_exts, NUV_CAPS, NULL, NULL);
 
   /* ISO formats */
   TYPE_FIND_REGISTER (plugin, "audio/x-m4a", GST_RANK_PRIMARY, m4a_type_find,
@@ -3042,6 +3356,10 @@
       qt_type_find, qt_exts, QT_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "image/x-quicktime", GST_RANK_SECONDARY,
       qtif_type_find, qtif_exts, QTIF_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "image/jp2", GST_RANK_PRIMARY,
+      jp2_type_find, jp2_exts, JP2_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "video/mj2", GST_RANK_PRIMARY,
+      jp2_type_find, mj2_exts, MJ2_CAPS, NULL, NULL);
 
   TYPE_FIND_REGISTER (plugin, "text/html", GST_RANK_SECONDARY, html_type_find,
       html_exts, HTML_CAPS, NULL, NULL);
@@ -3097,6 +3415,8 @@
       tiff_exts, TIFF_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY,
       matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "application/mxf", GST_RANK_PRIMARY,
+      mxf_type_find, mxf_exts, MXF_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mve", GST_RANK_SECONDARY,
       mve_exts, "Interplay MVE File\032\000\032\000\000\001\063\021", 26,
       GST_TYPE_FIND_MAXIMUM);
@@ -3129,6 +3449,8 @@
       zip_exts, "PK\003\004", 4, GST_TYPE_FIND_LIKELY);
   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-compress",
       GST_RANK_SECONDARY, compress_exts, "\037\235", 2, GST_TYPE_FIND_LIKELY);
+  TYPE_FIND_REGISTER (plugin, "subtitle/x-kate", GST_RANK_MARGINAL,
+      kate_type_find, NULL, NULL, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "audio/x-flac", GST_RANK_PRIMARY,
       flac_type_find, flac_exts, FLAC_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "audio/x-vorbis", GST_RANK_PRIMARY,
@@ -3143,6 +3465,8 @@
       ogmtext_type_find, NULL, OGMTEXT_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "audio/x-speex", GST_RANK_PRIMARY,
       speex_type_find, NULL, SPEEX_CAPS, NULL, NULL);
+  TYPE_FIND_REGISTER (plugin, "audio/x-celt", GST_RANK_PRIMARY,
+      celt_type_find, NULL, CELT_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/x-ogg-skeleton", GST_RANK_PRIMARY,
       oggskel_type_find, NULL, OGG_SKELETON_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "text/x-cmml", GST_RANK_PRIMARY, cmml_type_find,
@@ -3176,6 +3500,18 @@
       vivo_type_find, vivo_exts, VIVO_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nsf",
       GST_RANK_SECONDARY, nsf_exts, "NESM\x1a", 5, GST_TYPE_FIND_MAXIMUM);
+  TYPE_FIND_REGISTER_START_WITH (plugin, "application/pdf",
+      GST_RANK_SECONDARY, pdf_exts, "%PDF-", 5, GST_TYPE_FIND_LIKELY);
+  TYPE_FIND_REGISTER_START_WITH (plugin, "application/msword",
+      GST_RANK_SECONDARY, msword_exts, "\320\317\021\340\241\261\032\341", 8,
+      GST_TYPE_FIND_LIKELY);
+  /* Mac OS X .DS_Store files tend to be taken for video/mpeg */
+  TYPE_FIND_REGISTER_START_WITH (plugin, "application/octet-stream",
+      GST_RANK_SECONDARY, dsstore_exts, "\000\000\000\001Bud1", 8,
+      GST_TYPE_FIND_LIKELY);
+  TYPE_FIND_REGISTER_START_WITH (plugin, "image/vnd.adobe.photoshop",
+      GST_RANK_SECONDARY, psd_exts, "8BPS\000\001\000\000\000\000", 10,
+      GST_TYPE_FIND_LIKELY);
   return TRUE;
 }
 
--- a/gst_plugins_base/gst/videorate/gstvideorate.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videorate/gstvideorate.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,61 +19,50 @@
 
 /**
  * SECTION:element-videorate
- * @short_description: retimestamps and drops/duplicates video frames to
- *  match the source pad's framerate and create a perfect stream
  *
- * <refsect2>
- * <para>
  * This element takes an incoming stream of timestamped video frames.
  * It will produce a perfect stream that matches the source pad's framerate.
  *
  * The correction is performed by dropping and duplicating frames, no fancy
  * algorithm is used to interpolate frames (yet).
- * </para>
- * <para>
+ *
  * By default the element will simply negotiate the same framerate on its
  * source and sink pad.
- * </para>
- * <para>
+ *
  * This operation is useful to link to elements that require a perfect stream.
  * Typical examples are formats that do not store timestamps for video frames,
  * but only store a framerate, like Ogg and AVI.
- * </para>
- * <para>
+ *
  * A conversion to a specific framerate can be forced by using filtered caps on
  * the source pad.
- * </para>
- * <para>
- * The properties "in", "out", "duplicate" and "drop" can be read to obtain
- * information about number of input frames, output frames, dropped frames
- * (i.e. the number of unused input frames) and duplicated frames (i.e. the
- *  number of times an input frame was duplicated, beside being used normally).
+ *
+ * The properties #GstVideoRate:in, #GstVideoRate:out, #GstVideoRate:duplicate
+ * and #GstVideoRate:drop can be read to obtain information about number of
+ * input frames, output frames, dropped frames (i.e. the number of unused input
+ * frames) and duplicated frames (i.e. the number of times an input frame was
+ * duplicated, beside being used normally).
  *
  * An input stream that needs no adjustments will thus never have dropped or
  * duplicated frames.
  *
- * When the "silent" property is set to FALSE, a GObject property notification
- * will be emitted whenever one of the "duplicate" or "drop" values changes.
+ * When the #GstVideoRate:silent property is set to FALSE, a GObject property
+ * notification will be emitted whenever one of the #GstVideoRate:duplicate or
+ * #GstVideoRate:drop values changes.
  * This can potentially cause performance degradation.
  * Note that property notification will happen from the streaming thread, so
  * applications should be prepared for this.
- * </para>
+ *
+ * <refsect2>
  * <title>Example pipelines</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videorate ! video/x-raw-yuv,framerate=15/1 ! xvimagesink
- * </programlisting>
- * Decode an Ogg/Theora file and adjust the framerate to 15 fps before playing.
+ * ]| Decode an Ogg/Theora file and adjust the framerate to 15 fps before playing.
  * To create the test Ogg/Theora file refer to the documentation of theoraenc.
- * </para>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v v4lsrc ! videorate ! video/x-raw-yuv,framerate=25/2 ! theoraenc ! oggmux ! filesink location=v4l.ogg
- * </programlisting>
- * Capture video from a V4L device, and adjust the stream to 12.5 fps before
+ * ]| Capture video from a V4L device, and adjust the stream to 12.5 fps before
  * encoding to Ogg/Theora.
- * </para>
-  * </refsect2>
+ * </refsect2>
  *
  * Last reviewed on 2006-09-02 (0.10.11)
  */
@@ -120,14 +109,14 @@
     GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb")
+    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb; image/jpeg; image/png")
     );
 
 static GstStaticPadTemplate gst_video_rate_sink_template =
     GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb")
+    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb; image/jpeg; image/png")
     );
 
 static void gst_video_rate_swap_prev (GstVideoRate * videorate,
@@ -160,6 +149,7 @@
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&gst_video_rate_src_template));
 }
+
 static void
 gst_video_rate_class_init (GstVideoRateClass * klass)
 {
@@ -173,24 +163,26 @@
 
   g_object_class_install_property (object_class, ARG_IN,
       g_param_spec_uint64 ("in", "In",
-          "Number of input frames", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+          "Number of input frames", 0, G_MAXUINT64, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_OUT,
-      g_param_spec_uint64 ("out", "Out",
-          "Number of output frames", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+      g_param_spec_uint64 ("out", "Out", "Number of output frames", 0,
+          G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_DUP,
       g_param_spec_uint64 ("duplicate", "Duplicate",
-          "Number of duplicated frames", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+          "Number of duplicated frames", 0, G_MAXUINT64, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_DROP,
-      g_param_spec_uint64 ("drop", "Drop",
-          "Number of dropped frames", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+      g_param_spec_uint64 ("drop", "Drop", "Number of dropped frames", 0,
+          G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_SILENT,
       g_param_spec_boolean ("silent", "silent",
-          "Don't emit notify for dropped and duplicated frames",
-          DEFAULT_SILENT, G_PARAM_READWRITE));
+          "Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, ARG_NEW_PREF,
-      g_param_spec_double ("new_pref", "New Pref",
-          "Value indicating how much to prefer new frames (unused)",
-          0.0, 1.0, DEFAULT_NEW_PREF, G_PARAM_READWRITE));
+      g_param_spec_double ("new-pref", "New Pref",
+          "Value indicating how much to prefer new frames (unused)", 0.0, 1.0,
+          DEFAULT_NEW_PREF, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   element_class->change_state = gst_video_rate_change_state;
 }
@@ -276,6 +268,7 @@
     videorate->from_rate_denominator = rate_denominator;
     otherpad = videorate->srcpad;
   }
+
   /* now try to find something for the peer */
   opeer = gst_pad_get_peer (otherpad);
   if (opeer) {
@@ -362,9 +355,12 @@
 
   videorate->in = 0;
   videorate->out = 0;
+  videorate->segment_out = 0;
   videorate->drop = 0;
   videorate->dup = 0;
   videorate->next_ts = GST_CLOCK_TIME_NONE;
+  videorate->last_ts = GST_CLOCK_TIME_NONE;
+  videorate->discont = TRUE;
   gst_video_rate_swap_prev (videorate, NULL, 0);
 
   gst_segment_init (&videorate->segment, GST_FORMAT_TIME);
@@ -417,14 +413,21 @@
   GST_BUFFER_OFFSET (outbuf) = videorate->out;
   GST_BUFFER_OFFSET_END (outbuf) = videorate->out + 1;
 
+  if (videorate->discont) {
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+    videorate->discont = FALSE;
+  } else
+    GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DISCONT);
+
   /* this is the timestamp we put on the buffer */
   push_ts = videorate->next_ts;
 
   videorate->out++;
+  videorate->segment_out++;
   if (videorate->to_rate_numerator) {
     /* interpolate next expected timestamp in the segment */
     videorate->next_ts = videorate->segment.accum + videorate->segment.start +
-        gst_util_uint64_scale (videorate->out,
+        gst_util_uint64_scale (videorate->segment_out,
         videorate->to_rate_denominator * GST_SECOND,
         videorate->to_rate_numerator);
     GST_BUFFER_DURATION (outbuf) = videorate->next_ts - push_ts;
@@ -462,6 +465,7 @@
   videorate->prev_ts = time;
 }
 
+#define MAGIC_LIMIT  25
 static gboolean
 gst_video_rate_event (GstPad * pad, GstEvent * event)
 {
@@ -486,6 +490,38 @@
 
       GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT");
 
+      /* close up the previous segment, if appropriate */
+      if (!update && videorate->prevbuf) {
+        gint count = 0;
+        GstFlowReturn res;
+
+        res = GST_FLOW_OK;
+        /* fill up to the end of current segment,
+         * or only send out the stored buffer if there is no specific stop.
+         * regardless, prevent going loopy in strange cases */
+        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
+            ((GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) &&
+                    videorate->next_ts - videorate->segment.accum
+                    < videorate->segment.stop)
+                || count < 1)) {
+          gst_video_rate_flush_prev (videorate);
+          count++;
+        }
+        if (count > 1) {
+          videorate->dup += count - 1;
+          if (!videorate->silent)
+            g_object_notify (G_OBJECT (videorate), "duplicate");
+        } else if (count == 0) {
+          videorate->drop++;
+          if (!videorate->silent)
+            g_object_notify (G_OBJECT (videorate), "drop");
+        }
+        /* clean up for the new one; _chain will resume from the new start */
+        videorate->segment_out = 0;
+        gst_video_rate_swap_prev (videorate, NULL, 0);
+        videorate->next_ts = GST_CLOCK_TIME_NONE;
+      }
+
       /* We just want to update the accumulated stream_time  */
       gst_segment_set_newsegment_full (&videorate->segment, update, rate, arate,
           format, start, stop, time);
@@ -550,11 +586,17 @@
               GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
               GST_TIME_ARGS (min), GST_TIME_ARGS (max));
 
-          /* add latency. We don't really know since we hold on to the frames
-           * until we get a next frame, which can be anything. We assume
-           * however that this will take from_rate time. */
-          latency = gst_util_uint64_scale (GST_SECOND,
-              videorate->from_rate_denominator, videorate->from_rate_numerator);
+          if (videorate->from_rate_numerator != 0) {
+            /* add latency. We don't really know since we hold on to the frames
+             * until we get a next frame, which can be anything. We assume
+             * however that this will take from_rate time. */
+            latency = gst_util_uint64_scale (GST_SECOND,
+                videorate->from_rate_denominator,
+                videorate->from_rate_numerator);
+          } else {
+            /* no input framerate, we don't know */
+            latency = 0;
+          }
 
           GST_DEBUG_OBJECT (videorate, "Our latency: %"
               GST_TIME_FORMAT, GST_TIME_ARGS (latency));
@@ -587,7 +629,7 @@
 {
   GstVideoRate *videorate;
   GstFlowReturn res = GST_FLOW_OK;
-  GstClockTime intime, in_ts;
+  GstClockTime intime, in_ts, in_dur;
 
   videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad));
 
@@ -597,9 +639,19 @@
     goto not_negotiated;
 
   in_ts = GST_BUFFER_TIMESTAMP (buffer);
+  in_dur = GST_BUFFER_DURATION (buffer);
 
-  if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE))
-    goto invalid_buffer;
+  if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE)) {
+    in_ts = videorate->last_ts;
+    if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE))
+      goto invalid_buffer;
+  }
+
+  /* get the time of the next expected buffer timestamp, we use this when the
+   * next buffer has -1 as a timestamp */
+  videorate->last_ts = in_ts;
+  if (in_dur != GST_CLOCK_TIME_NONE)
+    videorate->last_ts += in_dur;
 
   GST_DEBUG_OBJECT (videorate, "got buffer with timestamp %" GST_TIME_FORMAT,
       GST_TIME_ARGS (in_ts));
@@ -615,7 +667,7 @@
     if (!GST_CLOCK_TIME_IS_VALID (videorate->next_ts)) {
       /* new buffer, we expect to output a buffer that matches the first
        * timestamp in the segment */
-      videorate->next_ts = videorate->segment.start;
+      videorate->next_ts = videorate->segment.start + videorate->segment.accum;
     }
   } else {
     GstClockTime prevtime;
@@ -664,7 +716,7 @@
           GST_TIME_ARGS (videorate->next_ts));
 
       /* output first one when its the best */
-      if (diff1 < diff2) {
+      if (diff1 <= diff2) {
         count++;
 
         /* on error the _flush function posted a warning already */
@@ -673,7 +725,8 @@
           goto done;
         }
       }
-      /* continue while the first one was the best */
+      /* continue while the first one was the best, if they were equal avoid
+       * going into an infinite loop */
     }
     while (diff1 < diff2);
 
@@ -784,6 +837,10 @@
   videorate = GST_VIDEO_RATE (element);
 
   switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      videorate->discont = TRUE;
+      videorate->last_ts = -1;
+      break;
     default:
       break;
   }
--- a/gst_plugins_base/gst/videorate/gstvideorate.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videorate/gstvideorate.h	Fri Apr 16 15:15:52 2010 +0300
@@ -55,6 +55,9 @@
   guint64 next_ts;              /* Timestamp of next buffer to output */
   GstBuffer *prevbuf;
   guint64 prev_ts;              /* Previous buffer timestamp */
+  guint64 segment_out;          /* in-segment counting */
+  gboolean discont;
+  guint64 last_ts;              /* Timestamp of last input buffer */
 
   /* segment handling */
   GstSegment segment;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/videoscale/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,5 @@
+- test different strides using
+gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=328,height=240 ! xvimagesink 
+gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=324,height=240 ! xvimagesink 
+gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=322,height=240 ! xvimagesink 
+gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=321,height=240 ! xvimagesink 
--- a/gst_plugins_base/gst/videoscale/gstvideoscale.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/gstvideoscale.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,35 +22,27 @@
  * SECTION:element-videoscale
  * @see_also: videorate, ffmpegcolorspace
  *
- * <refsect2>
- * <para>
  * This element resizes video frames. By default the element will try to
  * negotiate to the same size on the source and sinkpad so that no scaling
  * is needed. It is therefore safe to insert this element in a pipeline to
  * get more robust behaviour without any cost if no scaling is needed.
- * </para>
- * <para>
+ *
  * This element supports a wide range of color spaces including various YUV and
  * RGB formats and is therefore generally able to operate anywhere in a
  * pipeline.
- * </para>
+ *
+ * <refsect2>
  * <title>Example pipelines</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! ffmpegcolorspace ! videoscale ! ximagesink
- * </programlisting>
- * Decode an Ogg/Theora and display the video using ximagesink. Since
+ * ]| Decode an Ogg/Theora and display the video using ximagesink. Since
  * ximagesink cannot perform scaling, the video scaling will be performed by
  * videoscale when you resize the video window.
  * To create the test Ogg/Theora file refer to the documentation of theoraenc.
- * </para>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoscale ! video/x-raw-yuv, width=50 ! xvimagesink
- * </programlisting>
- * Decode an Ogg/Theora and display the video using xvimagesink with a width of
- * 50.
- * </para>
+ * ]| Decode an Ogg/Theora and display the video using xvimagesink with a width
+ * of 50.
  * </refsect2>
  *
  * Last reviewed on 2006-03-02 (0.10.4)
@@ -63,15 +55,16 @@
 #include <string.h>
 
 #include <gst/video/video.h>
-#include <gst/liboil.h>
+#include <liboil/liboil.h>
 
+#ifdef __SYMBIAN32__
+#include <liboil/globals.h>
+#endif
 
 #include "gstvideoscale.h"
 #include "vs_image.h"
 #include "vs_4tap.h"
 
-#include <glib_global.h>
-
 
 /* debug variable definition */
 GST_DEBUG_CATEGORY (video_scale_debug);
@@ -83,7 +76,7 @@
     "Resizes video",
     "Wim Taymans <wim.taymans@chello.be>");
 
-#define DEFAULT_PROP_METHOD	GST_VIDEO_SCALE_NEAREST
+#define DEFAULT_PROP_METHOD	GST_VIDEO_SCALE_BILINEAR
 
 enum
 {
@@ -92,10 +85,6 @@
       /* FILL ME */
 };
 
-/* can't handle width/height of 1 yet, since we divide a lot by (n-1) */
-#undef GST_VIDEO_SIZE_RANGE
-#define GST_VIDEO_SIZE_RANGE "(int) [ 2, MAX ]"
-
 static GstStaticCaps gst_video_scale_format_caps[] = {
   GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB),
@@ -107,6 +96,7 @@
   GST_STATIC_CAPS (GST_VIDEO_CAPS_ABGR),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_BGR),
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("v308")),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2")),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YVYU")),
@@ -115,7 +105,18 @@
   GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")),
   GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB_16),
-  GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB_15)
+  GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB_15),
+  GST_STATIC_CAPS ("video/x-raw-gray, "
+      "bpp = 8, "
+      "depth = 8, "
+      "width = " GST_VIDEO_SIZE_RANGE ", "
+      "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE),
+  GST_STATIC_CAPS ("video/x-raw-gray, "
+      "bpp = 16, "
+      "depth = 16, "
+      "endianness = BYTE_ORDER, "
+      "width = " GST_VIDEO_SIZE_RANGE ", "
+      "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE)
 };
 
 enum
@@ -130,6 +131,7 @@
   GST_VIDEO_SCALE_ABGR,
   GST_VIDEO_SCALE_RGB,
   GST_VIDEO_SCALE_BGR,
+  GST_VIDEO_SCALE_v308,
   GST_VIDEO_SCALE_AYUV,
   GST_VIDEO_SCALE_YUY2,
   GST_VIDEO_SCALE_YVYU,
@@ -138,7 +140,9 @@
   GST_VIDEO_SCALE_I420,
   GST_VIDEO_SCALE_YV12,
   GST_VIDEO_SCALE_RGB565,
-  GST_VIDEO_SCALE_RGB555
+  GST_VIDEO_SCALE_RGB555,
+  GST_VIDEO_SCALE_GRAY8,
+  GST_VIDEO_SCALE_GRAY16
 };
 
 #define GST_TYPE_VIDEO_SCALE_METHOD (gst_video_scale_method_get_type())
@@ -146,6 +150,7 @@
 gst_video_scale_method_get_type (void)
 {
   static GType video_scale_method_type = 0;
+
   static const GEnumValue video_scale_methods[] = {
     {GST_VIDEO_SCALE_NEAREST, "Nearest Neighbour", "nearest-neighbour"},
     {GST_VIDEO_SCALE_BILINEAR, "Bilinear", "bilinear"},
@@ -194,9 +199,13 @@
 
 
 static void gst_video_scale_base_init (gpointer g_class);
+
 static void gst_video_scale_class_init (GstVideoScaleClass * klass);
+
 static void gst_video_scale_init (GstVideoScale * videoscale);
+
 static void gst_video_scale_finalize (GstVideoScale * videoscale);
+
 static gboolean gst_video_scale_src_event (GstBaseTransform * trans,
     GstEvent * event);
 
@@ -277,7 +286,8 @@
 
   g_object_class_install_property (gobject_class, PROP_METHOD,
       g_param_spec_enum ("method", "method", "method",
-          GST_TYPE_VIDEO_SCALE_METHOD, DEFAULT_PROP_METHOD, G_PARAM_READWRITE));
+          GST_TYPE_VIDEO_SCALE_METHOD, DEFAULT_PROP_METHOD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   trans_class->transform_caps =
       GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps);
@@ -367,54 +377,28 @@
 
   structure = gst_caps_get_structure (caps, 0);
 
-  /* check compatibility of format and method before we copy the input caps */
-  if (method == GST_VIDEO_SCALE_4TAP) {
-    guint32 fourcc;
-
-    if (!gst_structure_has_name (structure, "video/x-raw-yuv"))
-      goto method_not_implemented_for_format;
-    if (!gst_structure_get_fourcc (structure, "format", &fourcc))
-      goto method_not_implemented_for_format;
-    if (fourcc != GST_MAKE_FOURCC ('I', '4', '2', '0') &&
-        fourcc != GST_MAKE_FOURCC ('Y', 'V', '1', '2'))
-      goto method_not_implemented_for_format;
-  }
-
   ret = gst_caps_copy (caps);
-  structure = gst_caps_get_structure (ret, 0);
+  structure = gst_structure_copy (gst_caps_get_structure (ret, 0));
 
   gst_structure_set (structure,
       "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
       "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
 
+  gst_caps_merge_structure (ret, gst_structure_copy (structure));
+
   /* if pixel aspect ratio, make a range of it */
   if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) {
-    GstCaps *copy;
-    GstStructure *cstruct;
-
-    /* copy input PAR first, this is the prefered PAR */
-    gst_structure_set_value (structure, "pixel-aspect-ratio", par);
-
-    /* then make a copy with a fraction range as a second choice */
-    copy = gst_caps_copy (ret);
-    cstruct = gst_caps_get_structure (copy, 0);
-    gst_structure_set (cstruct,
+    gst_structure_set (structure,
         "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
 
-    /* and append */
-    gst_caps_append (ret, copy);
+    gst_caps_merge_structure (ret, structure);
+  } else {
+    gst_structure_free (structure);
   }
 
   GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret);
 
   return ret;
-
-method_not_implemented_for_format:
-  {
-    GST_DEBUG_OBJECT (trans, "method %d not implemented for format %"
-        GST_PTR_FORMAT ", returning empty caps", method, caps);
-    return gst_caps_new_empty ();
-  }
 }
 
 static int
@@ -461,6 +445,7 @@
       break;
     case GST_VIDEO_SCALE_RGB:
     case GST_VIDEO_SCALE_BGR:
+    case GST_VIDEO_SCALE_v308:
       img->stride = GST_ROUND_UP_4 (img->width * 3);
       *size = img->stride * img->height;
       break;
@@ -471,9 +456,14 @@
       *size = img->stride * img->height;
       break;
     case GST_VIDEO_SCALE_Y:
+    case GST_VIDEO_SCALE_GRAY8:
       img->stride = GST_ROUND_UP_4 (img->width);
       *size = img->stride * img->height;
       break;
+    case GST_VIDEO_SCALE_GRAY16:
+      img->stride = GST_ROUND_UP_4 (img->width * 2);
+      *size = img->stride * img->height;
+      break;
     case GST_VIDEO_SCALE_I420:
     case GST_VIDEO_SCALE_YV12:
     {
@@ -610,7 +600,9 @@
   /* we have both PAR but they might not be fixated */
   if (from_par && to_par) {
     gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
+
     gint count = 0, w = 0, h = 0;
+
     guint num, den;
 
     /* from_par should be fixed */
@@ -761,8 +753,12 @@
   gst_video_scale_prepare_image (videoscale->format, out, dest, &dest_u,
       &dest_v);
 
+  if (src->height < 4 && method == GST_VIDEO_SCALE_4TAP)
+    method = GST_VIDEO_SCALE_BILINEAR;
+
   switch (method) {
     case GST_VIDEO_SCALE_NEAREST:
+      GST_LOG_OBJECT (videoscale, "doing nearest scaling");
       switch (videoscale->format) {
         case GST_VIDEO_SCALE_RGBx:
         case GST_VIDEO_SCALE_xRGB:
@@ -777,6 +773,7 @@
           break;
         case GST_VIDEO_SCALE_RGB:
         case GST_VIDEO_SCALE_BGR:
+        case GST_VIDEO_SCALE_v308:
           vs_image_scale_nearest_RGB (dest, src, videoscale->tmp_buf);
           break;
         case GST_VIDEO_SCALE_YUY2:
@@ -787,8 +784,12 @@
           vs_image_scale_nearest_UYVY (dest, src, videoscale->tmp_buf);
           break;
         case GST_VIDEO_SCALE_Y:
+        case GST_VIDEO_SCALE_GRAY8:
           vs_image_scale_nearest_Y (dest, src, videoscale->tmp_buf);
           break;
+        case GST_VIDEO_SCALE_GRAY16:
+          vs_image_scale_nearest_Y16 (dest, src, videoscale->tmp_buf);
+          break;
         case GST_VIDEO_SCALE_I420:
         case GST_VIDEO_SCALE_YV12:
           vs_image_scale_nearest_Y (dest, src, videoscale->tmp_buf);
@@ -806,6 +807,7 @@
       }
       break;
     case GST_VIDEO_SCALE_BILINEAR:
+      GST_LOG_OBJECT (videoscale, "doing bilinear scaling");
       switch (videoscale->format) {
         case GST_VIDEO_SCALE_RGBx:
         case GST_VIDEO_SCALE_xRGB:
@@ -820,6 +822,7 @@
           break;
         case GST_VIDEO_SCALE_RGB:
         case GST_VIDEO_SCALE_BGR:
+        case GST_VIDEO_SCALE_v308:
           vs_image_scale_linear_RGB (dest, src, videoscale->tmp_buf);
           break;
         case GST_VIDEO_SCALE_YUY2:
@@ -830,8 +833,12 @@
           vs_image_scale_linear_UYVY (dest, src, videoscale->tmp_buf);
           break;
         case GST_VIDEO_SCALE_Y:
+        case GST_VIDEO_SCALE_GRAY8:
           vs_image_scale_linear_Y (dest, src, videoscale->tmp_buf);
           break;
+        case GST_VIDEO_SCALE_GRAY16:
+          vs_image_scale_linear_Y16 (dest, src, videoscale->tmp_buf);
+          break;
         case GST_VIDEO_SCALE_I420:
         case GST_VIDEO_SCALE_YV12:
           vs_image_scale_linear_Y (dest, src, videoscale->tmp_buf);
@@ -849,16 +856,51 @@
       }
       break;
     case GST_VIDEO_SCALE_4TAP:
+      GST_LOG_OBJECT (videoscale, "doing 4tap scaling");
       switch (videoscale->format) {
+        case GST_VIDEO_SCALE_RGBx:
+        case GST_VIDEO_SCALE_xRGB:
+        case GST_VIDEO_SCALE_BGRx:
+        case GST_VIDEO_SCALE_xBGR:
+        case GST_VIDEO_SCALE_RGBA:
+        case GST_VIDEO_SCALE_ARGB:
+        case GST_VIDEO_SCALE_BGRA:
+        case GST_VIDEO_SCALE_ABGR:
+        case GST_VIDEO_SCALE_AYUV:
+          vs_image_scale_4tap_RGBA (dest, src, videoscale->tmp_buf);
+          break;
+        case GST_VIDEO_SCALE_RGB:
+        case GST_VIDEO_SCALE_BGR:
+        case GST_VIDEO_SCALE_v308:
+          vs_image_scale_4tap_RGB (dest, src, videoscale->tmp_buf);
+          break;
+        case GST_VIDEO_SCALE_YUY2:
+        case GST_VIDEO_SCALE_YVYU:
+          vs_image_scale_4tap_YUYV (dest, src, videoscale->tmp_buf);
+          break;
+        case GST_VIDEO_SCALE_UYVY:
+          vs_image_scale_4tap_UYVY (dest, src, videoscale->tmp_buf);
+          break;
+        case GST_VIDEO_SCALE_Y:
+        case GST_VIDEO_SCALE_GRAY8:
+          vs_image_scale_4tap_Y (dest, src, videoscale->tmp_buf);
+          break;
+        case GST_VIDEO_SCALE_GRAY16:
+          vs_image_scale_4tap_Y16 (dest, src, videoscale->tmp_buf);
+          break;
         case GST_VIDEO_SCALE_I420:
         case GST_VIDEO_SCALE_YV12:
           vs_image_scale_4tap_Y (dest, src, videoscale->tmp_buf);
           vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf);
           vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
           break;
+        case GST_VIDEO_SCALE_RGB565:
+          vs_image_scale_4tap_RGB565 (dest, src, videoscale->tmp_buf);
+          break;
+        case GST_VIDEO_SCALE_RGB555:
+          vs_image_scale_4tap_RGB555 (dest, src, videoscale->tmp_buf);
+          break;
         default:
-          /* FIXME: update gst_video_scale_transform_caps once RGB and/or
-           * other YUV formats work too */
           goto unsupported;
       }
       break;
@@ -929,9 +971,8 @@
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-	#ifndef __SYMBIAN32__
   oil_init ();
-  #endif
+
   if (!gst_element_register (plugin, "videoscale", GST_RANK_NONE,
           GST_TYPE_VIDEO_SCALE))
     return FALSE;
--- a/gst_plugins_base/gst/videoscale/gstvideoscale.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/gstvideoscale.h	Fri Apr 16 15:15:52 2010 +0300
@@ -86,6 +86,10 @@
 struct _GstVideoScaleClass {
   GstBaseTransformClass parent_class;
 };
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GType gst_video_scale_get_type(void);
 
--- a/gst_plugins_base/gst/videoscale/vs_4tap.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/vs_4tap.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,7 @@
 /*
  * Image Scaling Functions (4 tap)
  * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * Copyright (c) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,12 +31,12 @@
 
 #include "vs_4tap.h"
 
-#include <gst/liboil.h>
+#include <liboil/liboil.h>
+#ifdef __SYMBIAN32__
+#include <liboil/globals.h>
+#endif
 #include <math.h>
 
-
-
-
 #define SHIFT 10
 
 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
@@ -182,8 +183,15 @@
   int xacc;
   int k;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   k = 0;
   for (i = 0; i < 4; i++) {
@@ -219,3 +227,1213 @@
     yacc += y_increment;
   }
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_resample_4tap_Y16 (uint8_t * dest, uint8_t * src,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y;
+  uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
+
+  acc = *xacc;
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = (acc & 0xff00) >> 8;
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * s[MAX (j - 1, 0)];
+      y += vs_4tap_taps[x][1] * s[j];
+      y += vs_4tap_taps[x][2] * s[j + 1];
+      y += vs_4tap_taps[x][3] * s[j + 2];
+    } else {
+      y = vs_4tap_taps[x][0] * s[CLAMP (j - 1, 0, src_width - 1)];
+      y += vs_4tap_taps[x][1] * s[CLAMP (j, 0, src_width - 1)];
+      y += vs_4tap_taps[x][2] * s[CLAMP (j + 1, 0, src_width - 1)];
+      y += vs_4tap_taps[x][3] * s[CLAMP (j + 2, 0, src_width - 1)];
+    }
+    y += (1 << (SHIFT - 1));
+    d[i] = CLAMP (y >> SHIFT, 0, 65535);
+    acc += increment;
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_merge_4tap_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+    uint8_t * src3, uint8_t * src4, int n, int acc)
+{
+  int i;
+  int y;
+  int a, b, c, d;
+  uint16_t *de = (uint16_t *) dest, *s1 = (uint16_t *) src1;
+  uint16_t *s2 = (uint16_t *) src2, *s3 = (uint16_t *) src3;
+  uint16_t *s4 = (uint16_t *) src4;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+  for (i = 0; i < n; i++) {
+    y = a * s1[i];
+    y += b * s2[i];
+    y += c * s3[i];
+    y += d * s4[i];
+    y += (1 << (SHIFT - 1));
+    de[i] = CLAMP (y >> SHIFT, 0, 65535);
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_Y16 (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_Y16 (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_Y16 (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_resample_4tap_RGBA (uint8_t * dest, uint8_t * src,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y;
+  int off;
+
+  acc = *xacc;
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = (acc & 0xffff) >> 8;
+
+    for (off = 0; off < 4; off++) {
+      if (j - 1 >= 0 && j + 2 < src_width) {
+        y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 4 + off, 0)];
+        y += vs_4tap_taps[x][1] * src[j * 4 + off];
+        y += vs_4tap_taps[x][2] * src[(j + 1) * 4 + off];
+        y += vs_4tap_taps[x][3] * src[(j + 2) * 4 + off];
+      } else {
+        y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 4 + off, 0,
+                4 * (src_width - 1) + off)];
+        y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + off, 0,
+                4 * (src_width - 1) + off)];
+        y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 4 + off, 0,
+                4 * (src_width - 1) + off)];
+        y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 4 + off, 0,
+                4 * (src_width - 1) + off)];
+      }
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
+    }
+    acc += increment;
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_merge_4tap_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+    uint8_t * src3, uint8_t * src4, int n, int acc)
+{
+  int i;
+  int y;
+  int off;
+  int a, b, c, d;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+  for (i = 0; i < n; i++) {
+    for (off = 0; off < 4; off++) {
+      y = a * src1[i * 4 + off];
+      y += b * src2[i * 4 + off];
+      y += c * src3[i * 4 + off];
+      y += d * src4[i * 4 + off];
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
+    }
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_RGBA (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_RGBA (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_RGBA (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_RGBA (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_resample_4tap_RGB (uint8_t * dest, uint8_t * src,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y;
+  int off;
+
+  acc = *xacc;
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = (acc & 0xffff) >> 8;
+
+    for (off = 0; off < 3; off++) {
+      if (j - 1 >= 0 && j + 2 < src_width) {
+        y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 3 + off, 0)];
+        y += vs_4tap_taps[x][1] * src[j * 3 + off];
+        y += vs_4tap_taps[x][2] * src[(j + 1) * 3 + off];
+        y += vs_4tap_taps[x][3] * src[(j + 2) * 3 + off];
+      } else {
+        y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 3 + off, 0,
+                3 * (src_width - 1) + off)];
+        y += vs_4tap_taps[x][1] * src[CLAMP (j * 3 + off, 0,
+                3 * (src_width - 1) + off)];
+        y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 3 + off, 0,
+                3 * (src_width - 1) + off)];
+        y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 3 + off, 0,
+                3 * (src_width - 1) + off)];
+      }
+      y += (1 << (SHIFT - 1));
+      dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255);
+    }
+    acc += increment;
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_merge_4tap_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+    uint8_t * src3, uint8_t * src4, int n, int acc)
+{
+  int i;
+  int y;
+  int off;
+  int a, b, c, d;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+  for (i = 0; i < n; i++) {
+    for (off = 0; off < 3; off++) {
+      y = a * src1[i * 3 + off];
+      y += b * src2[i * 3 + off];
+      y += c * src3[i * 3 + off];
+      y += d * src4[i * 3 + off];
+      y += (1 << (SHIFT - 1));
+      dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255);
+    }
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_RGB (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_RGB (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_RGB (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_RGB (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_resample_4tap_YUYV (uint8_t * dest, uint8_t * src,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y;
+  int quads = (n + 1) / 2;
+  int last_y = 2 * (src_width - 1);
+  int last_u =
+      MAX ((2 * (src_width - 1) % 4 ==
+          0) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1);
+  int last_v =
+      MAX ((2 * (src_width - 1) % 4 ==
+          2) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1);
+
+  acc = *xacc;
+  for (i = 0; i < quads; i++) {
+    j = acc >> 16;
+    x = (acc & 0xffff) >> 8;
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)];
+      y += vs_4tap_taps[x][1] * src[j * 2 + 0];
+      y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2];
+      y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4];
+    } else {
+      y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)];
+      y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)];
+      y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)];
+      y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)];
+    }
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
+
+    j = acc >> 17;
+    x = (acc & 0x1ffff) >> 9;
+
+    if (2 * (j - 1) >= 0 && 2 * (j + 4) < src_width) {
+      y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 1 - 4, 1)];
+      y += vs_4tap_taps[x][1] * src[j * 4 + 1];
+      y += vs_4tap_taps[x][2] * src[j * 4 + 1 + 4];
+      y += vs_4tap_taps[x][3] * src[j * 4 + 1 + 8];
+    } else {
+      y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 1 - 4, 1, last_u)];
+      y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 1, 1, last_u)];
+      y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 1 + 4, 1, last_u)];
+      y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 1 + 8, 1, last_u)];
+    }
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
+
+    if (2 * i + 1 < n) {
+      if (2 * (j - 1) >= 0 && 2 * (j + 4) < src_width) {
+        y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 3 - 4, 3)];
+        y += vs_4tap_taps[x][1] * src[j * 4 + 3];
+        y += vs_4tap_taps[x][2] * src[j * 4 + 3 + 4];
+        y += vs_4tap_taps[x][3] * src[j * 4 + 3 + 8];
+      } else {
+        y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 3 - 4, 3, last_v)];
+        y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 3, 3, last_v)];
+        y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 3 + 4, 3, last_v)];
+        y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 3 + 8, 3, last_v)];
+      }
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
+    }
+
+    acc += increment;
+    j = acc >> 16;
+    x = (acc & 0xffff) >> 8;
+
+    if (2 * i + 1 < n) {
+      if (j - 1 >= 0 && j + 2 < src_width) {
+        y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)];
+        y += vs_4tap_taps[x][1] * src[j * 2 + 0];
+        y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2];
+        y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4];
+      } else {
+        y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)];
+        y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)];
+        y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)];
+        y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)];
+      }
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
+      acc += increment;
+    }
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_merge_4tap_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+    uint8_t * src3, uint8_t * src4, int n, int acc)
+{
+  int i;
+  int y;
+  int a, b, c, d;
+  int quads = (n + 1) / 2;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+  for (i = 0; i < quads; i++) {
+    y = a * src1[i * 4 + 0];
+    y += b * src2[i * 4 + 0];
+    y += c * src3[i * 4 + 0];
+    y += d * src4[i * 4 + 0];
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
+
+    y = a * src1[i * 4 + 1];
+    y += b * src2[i * 4 + 1];
+    y += c * src3[i * 4 + 1];
+    y += d * src4[i * 4 + 1];
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
+
+    if (2 * i + 1 < n) {
+      y = a * src1[i * 4 + 2];
+      y += b * src2[i * 4 + 2];
+      y += c * src3[i * 4 + 2];
+      y += d * src4[i * 4 + 2];
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
+
+      y = a * src1[i * 4 + 3];
+      y += b * src2[i * 4 + 3];
+      y += c * src3[i * 4 + 3];
+      y += d * src4[i * 4 + 3];
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
+    }
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_YUYV (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_YUYV (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_YUYV (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_YUYV (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_resample_4tap_UYVY (uint8_t * dest, uint8_t * src,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y;
+  int quads = (n + 1) / 2;
+  int last_y = 2 * (src_width - 1) + 1;
+  int last_u =
+      MAX ((2 * (src_width - 1) % 4 ==
+          0) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0);
+  int last_v =
+      MAX ((2 * (src_width - 1) % 4 ==
+          2) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0);
+
+  acc = *xacc;
+  for (i = 0; i < quads; i++) {
+    j = acc >> 16;
+    x = (acc & 0xffff) >> 8;
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 1)];
+      y += vs_4tap_taps[x][1] * src[j * 2 + 1];
+      y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2];
+      y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4];
+    } else {
+      y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)];
+      y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)];
+      y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)];
+      y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)];
+    }
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
+
+    j = acc >> 17;
+    x = (acc & 0x1ffff) >> 9;
+
+    if (2 * (j - 2) >= 0 && 2 * (j + 4) < src_width) {
+      y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 0 - 4, 0)];
+      y += vs_4tap_taps[x][1] * src[j * 4 + 0];
+      y += vs_4tap_taps[x][2] * src[j * 4 + 0 + 4];
+      y += vs_4tap_taps[x][3] * src[j * 4 + 0 + 8];
+    } else {
+      y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 0 - 4, 0, last_u)];
+      y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 0, 0, last_u)];
+      y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 0 + 4, 0, last_u)];
+      y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 0 + 8, 0, last_u)];
+    }
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
+
+    if (2 * i + 1 < n) {
+      if (2 * (j - 1) >= 0 && 2 * (j + 4) < src_width) {
+        y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 2 - 4, 2)];
+        y += vs_4tap_taps[x][1] * src[j * 4 + 2];
+        y += vs_4tap_taps[x][2] * src[j * 4 + 2 + 4];
+        y += vs_4tap_taps[x][3] * src[j * 4 + 2 + 8];
+      } else {
+        y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 2 - 4, 2, last_v)];
+        y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 2, 2, last_v)];
+        y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 2 + 4, 2, last_v)];
+        y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 2 + 8, 2, last_v)];
+      }
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
+    }
+
+    acc += increment;
+    j = acc >> 16;
+    x = (acc & 0xffff) >> 8;
+
+    if (2 * i + 1 < n) {
+      if (j - 1 >= 0 && j + 2 < src_width) {
+        y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 0)];
+        y += vs_4tap_taps[x][1] * src[j * 2 + 1];
+        y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2];
+        y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4];
+      } else {
+        y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)];
+        y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)];
+        y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)];
+        y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)];
+      }
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
+      acc += increment;
+    }
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_merge_4tap_UYVY (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+    uint8_t * src3, uint8_t * src4, int n, int acc)
+{
+  int i;
+  int y;
+  int a, b, c, d;
+  int quads = (n + 1) / 2;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+  for (i = 0; i < quads; i++) {
+    y = a * src1[i * 4 + 0];
+    y += b * src2[i * 4 + 0];
+    y += c * src3[i * 4 + 0];
+    y += d * src4[i * 4 + 0];
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
+
+    y = a * src1[i * 4 + 1];
+    y += b * src2[i * 4 + 1];
+    y += c * src3[i * 4 + 1];
+    y += d * src4[i * 4 + 1];
+    y += (1 << (SHIFT - 1));
+    dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
+
+    if (2 * i + 1 < n) {
+      y = a * src1[i * 4 + 2];
+      y += b * src2[i * 4 + 2];
+      y += c * src3[i * 4 + 2];
+      y += d * src4[i * 4 + 2];
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
+
+      y = a * src1[i * 4 + 3];
+      y += b * src2[i * 4 + 3];
+      y += c * src3[i * 4 + 3];
+      y += d * src4[i * 4 + 3];
+      y += (1 << (SHIFT - 1));
+      dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
+    }
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_UYVY (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_UYVY (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_UYVY (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_UYVY (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
+
+/* note that src and dest are uint16_t, and thus endian dependent */
+
+#define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13)
+#define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9)
+#define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
+
+#define RGB565(r,g,b) \
+  ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f))
+
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_resample_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y, y_r, y_b, y_g;
+  uint16_t *dest = (uint16_t *) dest_u8;
+  uint16_t *src = (uint16_t *) src_u8;
+
+  acc = *xacc;
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff >> 8;
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * RGB565_R (src[MAX ((j - 1), 0)]);
+      y += vs_4tap_taps[x][1] * RGB565_R (src[j]);
+      y += vs_4tap_taps[x][2] * RGB565_R (src[(j + 1)]);
+      y += vs_4tap_taps[x][3] * RGB565_R (src[(j + 2)]);
+    } else {
+      y = vs_4tap_taps[x][0] * RGB565_R (src[CLAMP ((j - 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][1] * RGB565_R (src[CLAMP (j, 0, src_width - 1)]);
+      y += vs_4tap_taps[x][2] * RGB565_R (src[CLAMP ((j + 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][3] * RGB565_R (src[CLAMP ((j + 2), 0,
+                  src_width - 1)]);
+    }
+    y += (1 << (SHIFT - 1));
+    y_r = CLAMP (y >> SHIFT, 0, 255);
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * RGB565_G (src[MAX ((j - 1), 0)]);
+      y += vs_4tap_taps[x][1] * RGB565_G (src[j]);
+      y += vs_4tap_taps[x][2] * RGB565_G (src[(j + 1)]);
+      y += vs_4tap_taps[x][3] * RGB565_G (src[(j + 2)]);
+    } else {
+      y = vs_4tap_taps[x][0] * RGB565_G (src[CLAMP ((j - 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][1] * RGB565_G (src[CLAMP (j, 0, src_width - 1)]);
+      y += vs_4tap_taps[x][2] * RGB565_G (src[CLAMP ((j + 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][3] * RGB565_G (src[CLAMP ((j + 2), 0,
+                  src_width - 1)]);
+    }
+    y += (1 << (SHIFT - 1));
+    y_g = CLAMP (y >> SHIFT, 0, 255);
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * RGB565_B (src[MAX ((j - 1), 0)]);
+      y += vs_4tap_taps[x][1] * RGB565_B (src[j]);
+      y += vs_4tap_taps[x][2] * RGB565_B (src[(j + 1)]);
+      y += vs_4tap_taps[x][3] * RGB565_B (src[(j + 2)]);
+    } else {
+      y = vs_4tap_taps[x][0] * RGB565_B (src[CLAMP ((j - 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][1] * RGB565_B (src[CLAMP (j, 0, src_width - 1)]);
+      y += vs_4tap_taps[x][2] * RGB565_B (src[CLAMP ((j + 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][3] * RGB565_B (src[CLAMP ((j + 2), 0,
+                  src_width - 1)]);
+    }
+    y += (1 << (SHIFT - 1));
+    y_b = CLAMP (y >> SHIFT, 0, 255);
+
+    dest[i] = RGB565 (y_r, y_b, y_g);
+    acc += increment;
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_merge_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8,
+    uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc)
+{
+  int i;
+  int y, y_r, y_b, y_g;
+  int a, b, c, d;
+  uint16_t *dest = (uint16_t *) dest_u8;
+  uint16_t *src1 = (uint16_t *) src1_u8;
+  uint16_t *src2 = (uint16_t *) src2_u8;
+  uint16_t *src3 = (uint16_t *) src3_u8;
+  uint16_t *src4 = (uint16_t *) src4_u8;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+
+  for (i = 0; i < n; i++) {
+    y = a * RGB565_R (src1[i]);
+    y += b * RGB565_R (src2[i]);
+    y += c * RGB565_R (src3[i]);
+    y += d * RGB565_R (src4[i]);
+    y += (1 << (SHIFT - 1));
+    y_r = CLAMP (y >> SHIFT, 0, 255);
+
+    y = a * RGB565_G (src1[i]);
+    y += b * RGB565_G (src2[i]);
+    y += c * RGB565_G (src3[i]);
+    y += d * RGB565_G (src4[i]);
+    y += (1 << (SHIFT - 1));
+    y_g = CLAMP (y >> SHIFT, 0, 255);
+
+    y = a * RGB565_B (src1[i]);
+    y += b * RGB565_B (src2[i]);
+    y += c * RGB565_B (src3[i]);
+    y += d * RGB565_B (src4[i]);
+    y += (1 << (SHIFT - 1));
+    y_b = CLAMP (y >> SHIFT, 0, 255);
+
+    dest[i] = RGB565 (y_r, y_b, y_g);
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_RGB565 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_RGB565 (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_RGB565 (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_RGB565 (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
+
+/* note that src and dest are uint16_t, and thus endian dependent */
+
+#define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13)
+#define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9)
+#define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
+
+#define RGB555(r,g,b) \
+  ((((r)<<7)&0x7c00) | (((g)<<2)&0x03e0) | (((b)>>3)&0x001f))
+
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_resample_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
+    int n, int src_width, int *xacc, int increment)
+{
+  int i;
+  int j;
+  int acc;
+  int x;
+  int y, y_r, y_b, y_g;
+  uint16_t *dest = (uint16_t *) dest_u8;
+  uint16_t *src = (uint16_t *) src_u8;
+
+  acc = *xacc;
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff >> 8;
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * RGB555_R (src[MAX ((j - 1), 0)]);
+      y += vs_4tap_taps[x][1] * RGB555_R (src[j]);
+      y += vs_4tap_taps[x][2] * RGB555_R (src[(j + 1)]);
+      y += vs_4tap_taps[x][3] * RGB555_R (src[(j + 2)]);
+    } else {
+      y = vs_4tap_taps[x][0] * RGB555_R (src[CLAMP ((j - 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][1] * RGB555_R (src[CLAMP (j, 0, src_width - 1)]);
+      y += vs_4tap_taps[x][2] * RGB555_R (src[CLAMP ((j + 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][3] * RGB555_R (src[CLAMP ((j + 2), 0,
+                  src_width - 1)]);
+    }
+    y += (1 << (SHIFT - 1));
+    y_r = CLAMP (y >> SHIFT, 0, 255);
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * RGB555_G (src[MAX ((j - 1), 0)]);
+      y += vs_4tap_taps[x][1] * RGB555_G (src[j]);
+      y += vs_4tap_taps[x][2] * RGB555_G (src[(j + 1)]);
+      y += vs_4tap_taps[x][3] * RGB555_G (src[(j + 2)]);
+    } else {
+      y = vs_4tap_taps[x][0] * RGB555_G (src[CLAMP ((j - 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][1] * RGB555_G (src[CLAMP (j, 0, src_width - 1)]);
+      y += vs_4tap_taps[x][2] * RGB555_G (src[CLAMP ((j + 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][3] * RGB555_G (src[CLAMP ((j + 2), 0,
+                  src_width - 1)]);
+    }
+    y += (1 << (SHIFT - 1));
+    y_g = CLAMP (y >> SHIFT, 0, 255);
+
+    if (j - 1 >= 0 && j + 2 < src_width) {
+      y = vs_4tap_taps[x][0] * RGB555_B (src[MAX ((j - 1), 0)]);
+      y += vs_4tap_taps[x][1] * RGB555_B (src[j]);
+      y += vs_4tap_taps[x][2] * RGB555_B (src[(j + 1)]);
+      y += vs_4tap_taps[x][3] * RGB555_B (src[(j + 2)]);
+    } else {
+      y = vs_4tap_taps[x][0] * RGB555_B (src[CLAMP ((j - 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][1] * RGB555_B (src[CLAMP (j, 0, src_width - 1)]);
+      y += vs_4tap_taps[x][2] * RGB555_B (src[CLAMP ((j + 1), 0,
+                  src_width - 1)]);
+      y += vs_4tap_taps[x][3] * RGB555_B (src[CLAMP ((j + 2), 0,
+                  src_width - 1)]);
+    }
+    y += (1 << (SHIFT - 1));
+    y_b = CLAMP (y >> SHIFT, 0, 255);
+
+    dest[i] = RGB555 (y_r, y_b, y_g);
+    acc += increment;
+  }
+  *xacc = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_scanline_merge_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8,
+    uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc)
+{
+  int i;
+  int y, y_r, y_b, y_g;
+  int a, b, c, d;
+  uint16_t *dest = (uint16_t *) dest_u8;
+  uint16_t *src1 = (uint16_t *) src1_u8;
+  uint16_t *src2 = (uint16_t *) src2_u8;
+  uint16_t *src3 = (uint16_t *) src3_u8;
+  uint16_t *src4 = (uint16_t *) src4_u8;
+
+  acc = (acc >> 8) & 0xff;
+  a = vs_4tap_taps[acc][0];
+  b = vs_4tap_taps[acc][1];
+  c = vs_4tap_taps[acc][2];
+  d = vs_4tap_taps[acc][3];
+
+  for (i = 0; i < n; i++) {
+    y = a * RGB555_R (src1[i]);
+    y += b * RGB555_R (src2[i]);
+    y += c * RGB555_R (src3[i]);
+    y += d * RGB555_R (src4[i]);
+    y += (1 << (SHIFT - 1));
+    y_r = CLAMP (y >> SHIFT, 0, 255);
+
+    y = a * RGB555_G (src1[i]);
+    y += b * RGB555_G (src2[i]);
+    y += c * RGB555_G (src3[i]);
+    y += d * RGB555_G (src4[i]);
+    y += (1 << (SHIFT - 1));
+    y_g = CLAMP (y >> SHIFT, 0, 255);
+
+    y = a * RGB555_B (src1[i]);
+    y += b * RGB555_B (src2[i]);
+    y += c * RGB555_B (src3[i]);
+    y += d * RGB555_B (src4[i]);
+    y += (1 << (SHIFT - 1));
+    y_b = CLAMP (y >> SHIFT, 0, 255);
+
+    dest[i] = RGB555 (y_r, y_b, y_g);
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int yacc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int xacc;
+  int k;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  k = 0;
+  for (i = 0; i < 4; i++) {
+    xacc = 0;
+    vs_scanline_resample_4tap_RGB555 (tmpbuf + i * dest->stride,
+        src->pixels + i * src->stride, dest->width, src->width,
+        &xacc, x_increment);
+  }
+
+  yacc = 0;
+  for (i = 0; i < dest->height; i++) {
+    uint8_t *t0, *t1, *t2, *t3;
+
+    j = yacc >> 16;
+
+    while (j > k) {
+      k++;
+      if (k + 3 < src->height) {
+        xacc = 0;
+        vs_scanline_resample_4tap_RGB555 (tmpbuf + ((k + 3) & 3) * dest->stride,
+            src->pixels + (k + 3) * src->stride,
+            dest->width, src->width, &xacc, x_increment);
+      }
+    }
+
+    t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
+    t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
+    t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
+    t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
+    vs_scanline_merge_4tap_RGB555 (dest->pixels + i * dest->stride,
+        t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+    yacc += y_increment;
+  }
+}
--- a/gst_plugins_base/gst/videoscale/vs_4tap.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/vs_4tap.h	Fri Apr 16 15:15:52 2010 +0300
@@ -30,15 +30,161 @@
 
 #include "vs_image.h"
 
-#include <gst/liboil.h>
+#include <liboil/liboil.h>
 
 void vs_4tap_init (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_resample_4tap_Y (uint8_t *dest, uint8_t *src,
     int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_4tap_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2,
     uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src,
     uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void vs_scanline_resample_4tap_RGBA (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_4tap_RGBA (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_RGBA (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void vs_scanline_resample_4tap_RGB (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_4tap_RGB (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_RGB (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void vs_scanline_resample_4tap_YUYV (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_4tap_YUYV (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_YUYV (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void vs_scanline_resample_4tap_UYVY (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_4tap_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_UYVY (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void vs_scanline_resample_4tap_RGB565 (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_4tap_RGB565 (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_RGB565 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void vs_scanline_resample_4tap_RGB555 (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_4tap_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_4tap_Y16 (uint8_t *dest, uint8_t *src,
+    int n, int src_width, int *xacc, int increment);
+	
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+	
+void vs_scanline_merge_4tap_Y16 (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+    uint8_t *src3, uint8_t *src4, int n, int acc);
+	
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf);
 
 #endif
 
--- a/gst_plugins_base/gst/videoscale/vs_image.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/vs_image.c	Fri Apr 16 15:15:52 2010 +0300
@@ -49,8 +49,16 @@
   int x;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
 
   acc = 0;
   for (i = 0; i < dest->height; i++) {
@@ -59,7 +67,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_RGBA (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -86,8 +95,15 @@
   int dest_size;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = dest->width * 4;
 
@@ -97,8 +113,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_RGBA (tmp1, src->pixels, dest->width, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_RGBA (tmp1, src->pixels, src->width, dest->width,
+      &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -112,7 +128,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGBA (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -121,8 +137,8 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_RGBA (tmp2,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_RGBA (dest->pixels + i * dest->stride,
@@ -131,8 +147,8 @@
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_RGBA (tmp1,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_RGBA (dest->pixels + i * dest->stride,
@@ -140,11 +156,11 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGBA (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_RGBA (tmp2,
-            src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+            src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
             x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_RGBA (dest->pixels + i * dest->stride,
@@ -173,8 +189,15 @@
   int x;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   acc = 0;
   for (i = 0; i < dest->height; i++) {
@@ -183,7 +206,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_RGB (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -210,8 +234,15 @@
   int dest_size;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = dest->width * 3;
 
@@ -221,8 +252,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_RGB (tmp1, src->pixels, dest->width, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_RGB (tmp1, src->pixels, src->width, dest->width,
+      &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -236,7 +267,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -245,8 +276,8 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_RGB (tmp2,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
@@ -255,8 +286,8 @@
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_RGB (tmp1,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
@@ -264,11 +295,11 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_RGB (tmp2,
-            src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+            src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
             x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
@@ -297,12 +328,17 @@
   int j;
   int x;
   int xacc;
-  int n_quads;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
-  n_quads = ROUND_UP_2 (dest->width) / 2;
   acc = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -310,7 +346,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_YUYV (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, n_quads, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -335,14 +372,19 @@
   int j;
   int x;
   int dest_size;
-  int n_quads;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = ROUND_UP_4 (dest->width * 2);
-  n_quads = ROUND_UP_2 (dest->width) / 2;
 
   tmp1 = tmpbuf;
   tmp2 = tmpbuf + dest_size;
@@ -350,8 +392,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_YUYV (tmp1, src->pixels, n_quads, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_YUYV (tmp1, src->pixels, src->width, dest->width,
+      &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -365,7 +407,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
-            n_quads, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -374,31 +416,34 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_YUYV (tmp2,
-              src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
-            tmp1, tmp2, n_quads, x);
+            tmp1, tmp2, dest->width, x);
       } else if (j == y2) {
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_YUYV (tmp1,
-              src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
-            tmp2, tmp1, n_quads, x);
+            tmp2, tmp1, dest->width, x);
       } else {
         xacc = 0;
         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
-            n_quads, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_YUYV (tmp2,
-            src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+            src->pixels + (j + 1) * src->stride, src->width, dest->width,
+            &xacc, x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
-            tmp1, tmp2, n_quads, x);
+            tmp1, tmp2, dest->width, x);
       }
     }
 
@@ -423,12 +468,17 @@
   int j;
   int x;
   int xacc;
-  int n_quads;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
-  n_quads = (dest->width + 1) / 2;
   acc = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -436,7 +486,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_UYVY (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, n_quads, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -461,14 +512,19 @@
   int j;
   int x;
   int dest_size;
-  int n_quads;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = ROUND_UP_4 (dest->width * 2);
-  n_quads = ROUND_UP_2 (dest->width) / 2;
 
   tmp1 = tmpbuf;
   tmp2 = tmpbuf + dest_size;
@@ -476,8 +532,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_UYVY (tmp1, src->pixels, n_quads, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_UYVY (tmp1, src->pixels, src->width, dest->width,
+      &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -491,7 +547,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
-            n_quads, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -500,31 +556,34 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_UYVY (tmp2,
-              src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
-            tmp1, tmp2, n_quads, x);
+            tmp1, tmp2, dest->width, x);
       } else if (j == y2) {
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_UYVY (tmp1,
-              src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
-            tmp2, tmp1, n_quads, x);
+            tmp2, tmp1, dest->width, x);
       } else {
         xacc = 0;
         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
-            n_quads, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_UYVY (tmp2,
-            src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+            src->pixels + (j + 1) * src->stride, src->width, dest->width,
+            &xacc, x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
-            tmp1, tmp2, n_quads, x);
+            tmp1, tmp2, dest->width, x);
       }
     }
 
@@ -550,8 +609,15 @@
   int x;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   acc = 0;
   for (i = 0; i < dest->height; i++) {
@@ -560,7 +626,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_Y (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -587,8 +654,15 @@
   int dest_size;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = dest->width;
 
@@ -598,8 +672,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_Y (tmp1, src->pixels, dest->width, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_Y (tmp1, src->pixels, src->width, dest->width,
+      &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -613,7 +687,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_Y (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -622,8 +696,8 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_Y (tmp2,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_Y (dest->pixels + i * dest->stride,
@@ -632,8 +706,8 @@
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_Y (tmp1,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_Y (dest->pixels + i * dest->stride,
@@ -641,11 +715,11 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_Y (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_Y (tmp2,
-            src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+            src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
             x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_Y (dest->pixels + i * dest->stride,
@@ -656,6 +730,142 @@
     acc += y_increment;
   }
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_image_scale_nearest_Y16 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int acc;
+  int y_increment;
+  int x_increment;
+  int i;
+  int j;
+  int x;
+  int xacc;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  acc = 0;
+  for (i = 0; i < dest->height; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff;
+
+    xacc = 0;
+    vs_scanline_resample_nearest_Y16 (dest->pixels + i * dest->stride,
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
+
+    acc += y_increment;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_image_scale_linear_Y16 (const VSImage * dest, const VSImage * src,
+    uint8_t * tmpbuf)
+{
+  int acc;
+  int y_increment;
+  int x_increment;
+  uint8_t *tmp1;
+  uint8_t *tmp2;
+  int y1;
+  int y2;
+  int i;
+  int j;
+  int x;
+  int dest_size;
+  int xacc;
+
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+  dest_size = 2 * dest->width;
+
+  tmp1 = tmpbuf;
+  tmp2 = tmpbuf + dest_size;
+
+  acc = 0;
+  xacc = 0;
+  y2 = -1;
+  vs_scanline_resample_linear_Y16 (tmp1, src->pixels, src->width, dest->width,
+      &xacc, x_increment);
+  y1 = 0;
+  for (i = 0; i < dest->height; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff;
+
+    if (x == 0) {
+      if (j == y1) {
+        memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+      } else if (j == y2) {
+        memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+      } else {
+        xacc = 0;
+        vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
+            src->width, dest->width, &xacc, x_increment);
+        y1 = j;
+        memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+      }
+    } else {
+      if (j == y1) {
+        if (j + 1 != y2) {
+          xacc = 0;
+          vs_scanline_resample_linear_Y16 (tmp2,
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
+          y2 = j + 1;
+        }
+        vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
+            tmp1, tmp2, dest->width, x);
+      } else if (j == y2) {
+        if (j + 1 != y1) {
+          xacc = 0;
+          vs_scanline_resample_linear_Y16 (tmp1,
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
+          y1 = j + 1;
+        }
+        vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
+            tmp2, tmp1, dest->width, x);
+      } else {
+        xacc = 0;
+        vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
+            src->width, dest->width, &xacc, x_increment);
+        y1 = j;
+        xacc = 0;
+        vs_scanline_resample_linear_Y16 (tmp2,
+            src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
+            x_increment);
+        y2 = (j + 1);
+        vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
+            tmp1, tmp2, dest->width, x);
+      }
+    }
+
+    acc += y_increment;
+  }
+}
 
 /* RGB565 */
 #ifdef __SYMBIAN32__
@@ -675,8 +885,15 @@
   int x;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   acc = 0;
   for (i = 0; i < dest->height; i++) {
@@ -685,7 +902,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_RGB565 (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -712,8 +930,15 @@
   int dest_size;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = dest->width * 2;
 
@@ -723,8 +948,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, dest->width, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, src->width,
+      dest->width, &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -738,7 +963,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -747,8 +972,8 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_RGB565 (tmp2,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
@@ -757,8 +982,8 @@
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_RGB565 (tmp1,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
@@ -766,11 +991,11 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_RGB565 (tmp2,
-            src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+            src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
             x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
@@ -800,8 +1025,15 @@
   int x;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   acc = 0;
   for (i = 0; i < dest->height; i++) {
@@ -810,7 +1042,8 @@
 
     xacc = 0;
     vs_scanline_resample_nearest_RGB555 (dest->pixels + i * dest->stride,
-        src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+        src->pixels + j * src->stride, src->width, dest->width, &xacc,
+        x_increment);
 
     acc += y_increment;
   }
@@ -837,8 +1070,15 @@
   int dest_size;
   int xacc;
 
-  y_increment = ((src->height - 1) << 16) / (dest->height - 1);
-  x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+  if (dest->height == 1)
+    y_increment = 0;
+  else
+    y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+
+  if (dest->width == 1)
+    x_increment = 0;
+  else
+    x_increment = ((src->width - 1) << 16) / (dest->width - 1);
 
   dest_size = dest->width * 2;
 
@@ -848,8 +1088,8 @@
   acc = 0;
   xacc = 0;
   y2 = -1;
-  vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, dest->width, &xacc,
-      x_increment);
+  vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, src->width,
+      dest->width, &xacc, x_increment);
   y1 = 0;
   for (i = 0; i < dest->height; i++) {
     j = acc >> 16;
@@ -863,7 +1103,7 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
       }
@@ -872,8 +1112,8 @@
         if (j + 1 != y2) {
           xacc = 0;
           vs_scanline_resample_linear_RGB555 (tmp2,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y2 = j + 1;
         }
         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
@@ -882,8 +1122,8 @@
         if (j + 1 != y1) {
           xacc = 0;
           vs_scanline_resample_linear_RGB555 (tmp1,
-              src->pixels + (j + 1) * src->stride, dest->width, &xacc,
-              x_increment);
+              src->pixels + (j + 1) * src->stride, src->width, dest->width,
+              &xacc, x_increment);
           y1 = j + 1;
         }
         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
@@ -891,11 +1131,11 @@
       } else {
         xacc = 0;
         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
-            dest->width, &xacc, x_increment);
+            src->width, dest->width, &xacc, x_increment);
         y1 = j;
         xacc = 0;
         vs_scanline_resample_linear_RGB555 (tmp2,
-            src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+            src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
             x_increment);
         y2 = (j + 1);
         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
--- a/gst_plugins_base/gst/videoscale/vs_image.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/vs_image.h	Fri Apr 16 15:15:52 2010 +0300
@@ -27,9 +27,8 @@
 
 #ifndef __VS_IMAGE_H__
 #define __VS_IMAGE_H__
-//#include <liboil/liboil-stdint.h>
 
-typedef unsigned char uint8_t;
+#include <liboil/liboil-stdint.h>
 
 typedef struct _VSImage VSImage;
 
@@ -39,41 +38,102 @@
   int height;
   int stride;
 };
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_RGBA (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_RGBA (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_RGB (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_RGB (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_YUYV (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_YUYV (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_UYVY (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_UYVY (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_Y (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_RGB565 (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_RGB565 (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_image_scale_nearest_RGB555 (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_image_scale_linear_RGB555 (const VSImage *dest, const VSImage *src,
     uint8_t *tmpbuf);
 
+void vs_image_scale_nearest_Y16 (const VSImage *dest, const VSImage *src,
+    uint8_t *tmpbuf);
+void vs_image_scale_linear_Y16 (const VSImage *dest, const VSImage *src,
+    uint8_t *tmpbuf);
+
 #endif
 
--- a/gst_plugins_base/gst/videoscale/vs_scanline.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/vs_scanline.c	Fri Apr 16 15:15:52 2010 +0300
@@ -26,10 +26,15 @@
  */
 
 #include "vs_scanline.h"
-#include <gst/liboil.h>
+
+#include <liboil/liboil.h>
 
 /* greyscale, i.e., single componenet */
 #ifdef __SYMBIAN32__
+#include <liboil/globals.h>
+#endif
+#include <glib.h>
+#ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
@@ -49,8 +54,8 @@
 
 
 void
-vs_scanline_resample_nearest_Y (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_Y (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
@@ -60,7 +65,7 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i] = (x < 32768) ? src[j] : src[j + 1];
+    dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
 
     acc += increment;
   }
@@ -71,19 +76,28 @@
 EXPORT_C
 #endif
 
-
 void
-vs_scanline_resample_linear_Y (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_Y (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
-  uint32_t vals[2];
+  int acc = *accumulator;
+  int i;
+  int j;
+  int x;
 
-  vals[0] = *accumulator;
-  vals[1] = increment;
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff;
 
-  oil_resample_linear_u8 (dest, src, n, vals);
+    if (j + 1 < src_width)
+      dest[i] = (src[j] * (65536 - x) + src[j + 1] * x) >> 16;
+    else
+      dest[i] = src[j];
 
-  *accumulator = vals[0];
+    acc += increment;
+  }
+
+  *accumulator = acc;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -98,7 +112,91 @@
 
   oil_merge_linear_u8 (dest, src1, src2, &value, n);
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
+void
+vs_scanline_downsample_Y16 (uint8_t * dest, uint8_t * src, int n)
+{
+  int i;
+  uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
+
+  for (i = 0; i < n; i++) {
+    d[i] = (s[i * 2] + s[i * 2 + 1]) / 2;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_resample_nearest_Y16 (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
+{
+  int acc = *accumulator;
+  int i;
+  int j;
+  int x;
+  uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
+
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff;
+    d[i] = (x < 32768 || j + 1 >= src_width) ? s[j] : s[j + 1];
+
+    acc += increment;
+  }
+
+  *accumulator = acc;
+}
+
+#include <glib.h>
+
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_resample_linear_Y16 (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
+{
+  int acc = *accumulator;
+  int i;
+  int j;
+  int x;
+  uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
+
+  for (i = 0; i < n; i++) {
+    j = acc >> 16;
+    x = acc & 0xffff;
+
+    if (j + 1 < src_width)
+      d[i] = (s[j] * (65536 - x) + s[j + 1] * x) >> 16;
+    else
+      d[i] = s[j];
+
+    acc += increment;
+  }
+
+  *accumulator = acc;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+vs_scanline_merge_linear_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+    int n, int x)
+{
+  int i;
+  uint16_t *d = (uint16_t *) dest, *s1 = (uint16_t *) src1, *s2 =
+      (uint16_t *) src2;
+
+  for (i = 0; i < n; i++) {
+    d[i] = (s1[i] * (65536 - x) + s2[i] * x) >> 16;
+  }
+}
 
 /* RGBA */
 #ifdef __SYMBIAN32__
@@ -124,8 +222,8 @@
 
 
 void
-vs_scanline_resample_nearest_RGBA (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_RGBA (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
@@ -135,31 +233,61 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 0] = (x < 32768) ? src[j * 4 + 0] : src[j * 4 + 4];
-    dest[i * 4 + 1] = (x < 32768) ? src[j * 4 + 1] : src[j * 4 + 5];
-    dest[i * 4 + 2] = (x < 32768) ? src[j * 4 + 2] : src[j * 4 + 6];
-    dest[i * 4 + 3] = (x < 32768) ? src[j * 4 + 3] : src[j * 4 + 7];
+
+    if (j + 1 < src_width) {
+      dest[i * 4 + 0] = (x < 32768) ? src[j * 4 + 0] : src[j * 4 + 4];
+      dest[i * 4 + 1] = (x < 32768) ? src[j * 4 + 1] : src[j * 4 + 5];
+      dest[i * 4 + 2] = (x < 32768) ? src[j * 4 + 2] : src[j * 4 + 6];
+      dest[i * 4 + 3] = (x < 32768) ? src[j * 4 + 3] : src[j * 4 + 7];
+    } else {
+      dest[i * 4 + 0] = src[j * 4 + 0];
+      dest[i * 4 + 1] = src[j * 4 + 1];
+      dest[i * 4 + 2] = src[j * 4 + 2];
+      dest[i * 4 + 3] = src[j * 4 + 3];
+    }
 
     acc += increment;
   }
 
   *accumulator = acc;
 }
+
+#include <stdio.h>
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
-
 void
-vs_scanline_resample_linear_RGBA (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_RGBA (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   uint32_t vals[2];
 
   vals[0] = *accumulator;
   vals[1] = increment;
 
-  oil_resample_linear_argb ((uint32_t *) dest, (uint32_t *) src, n, vals);
+  if (src_width % 2 == 0) {
+    oil_resample_linear_argb ((uint32_t *) dest, (uint32_t *) src, n, vals);
+  } else if (src_width > 1) {
+    if (n > 1)
+      oil_resample_linear_argb ((uint32_t *) dest, (uint32_t *) src, n - 1,
+          vals);
+    dest[4 * (n - 1) + 0] = src[(vals[0] >> 16) + 0];
+    dest[4 * (n - 1) + 1] = src[(vals[0] >> 16) + 1];
+    dest[4 * (n - 1) + 2] = src[(vals[0] >> 16) + 2];
+    dest[4 * (n - 1) + 3] = src[(vals[0] >> 16) + 3];
+    vals[0] += increment;
+  } else {
+    int i;
+
+    for (i = 0; i < n; i++) {
+      dest[4 * i + 0] = src[0];
+      dest[4 * i + 1] = src[1];
+      dest[4 * i + 2] = src[2];
+      dest[4 * i + 3] = src[3];
+      vals[0] += increment;
+    }
+  }
 
   *accumulator = vals[0];
 }
@@ -202,8 +330,8 @@
 
 
 void
-vs_scanline_resample_nearest_RGB (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_RGB (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
@@ -213,9 +341,12 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 3 + 0] = (x < 32768) ? src[j * 3 + 0] : src[j * 3 + 3];
-    dest[i * 3 + 1] = (x < 32768) ? src[j * 3 + 1] : src[j * 3 + 4];
-    dest[i * 3 + 2] = (x < 32768) ? src[j * 3 + 2] : src[j * 3 + 5];
+    dest[i * 3 + 0] = (x < 32768
+        || j + 1 >= src_width) ? src[j * 3 + 0] : src[j * 3 + 3];
+    dest[i * 3 + 1] = (x < 32768
+        || j + 1 >= src_width) ? src[j * 3 + 1] : src[j * 3 + 4];
+    dest[i * 3 + 2] = (x < 32768
+        || j + 1 >= src_width) ? src[j * 3 + 2] : src[j * 3 + 5];
 
     acc += increment;
   }
@@ -228,8 +359,8 @@
 
 
 void
-vs_scanline_resample_linear_RGB (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_RGB (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
@@ -239,9 +370,19 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 3 + 0] = (src[j * 3 + 0] * (65536 - x) + src[j * 3 + 3] * x) >> 16;
-    dest[i * 3 + 1] = (src[j * 3 + 1] * (65536 - x) + src[j * 3 + 4] * x) >> 16;
-    dest[i * 3 + 2] = (src[j * 3 + 2] * (65536 - x) + src[j * 3 + 5] * x) >> 16;
+
+    if (j + 1 < src_width) {
+      dest[i * 3 + 0] =
+          (src[j * 3 + 0] * (65536 - x) + src[j * 3 + 3] * x) >> 16;
+      dest[i * 3 + 1] =
+          (src[j * 3 + 1] * (65536 - x) + src[j * 3 + 4] * x) >> 16;
+      dest[i * 3 + 2] =
+          (src[j * 3 + 2] * (65536 - x) + src[j * 3 + 5] * x) >> 16;
+    } else {
+      dest[i * 3 + 0] = src[j * 3 + 0];
+      dest[i * 3 + 1] = src[j * 3 + 1];
+      dest[i * 3 + 2] = src[j * 3 + 2];
+    }
 
     acc += increment;
   }
@@ -265,7 +406,7 @@
 
 /* YUYV */
 
-/* n is the number of bi-pixels */
+/* n is the number of pixels */
 /* increment is per Y pixel */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -290,30 +431,40 @@
 
 
 void
-vs_scanline_resample_nearest_YUYV (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_YUYV (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
   int j;
   int x;
+  int quads = (n + 1) / 2;
 
-  for (i = 0; i < n; i++) {
+  for (i = 0; i < quads; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 0] = (x < 32768) ? src[j * 2 + 0] : src[j * 2 + 2];
+    dest[i * 4 + 0] = (x < 32768
+        || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
 
     j = acc >> 17;
     x = acc & 0x1ffff;
-    dest[i * 4 + 1] = (x < 65536) ? src[j * 4 + 1] : src[j * 4 + 5];
-    dest[i * 4 + 3] = (x < 65536) ? src[j * 4 + 3] : src[j * 4 + 7];
+    dest[i * 4 + 1] = (x < 65536
+        || 2 * (j + 2) >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5];
+
+    if (2 * i + 1 < n && 2 * (j + 1) < src_width)
+      dest[i * 4 + 3] = (x < 65536
+          || 2 * (j + 3) >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7];
 
     acc += increment;
 
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 2] = (x < 32768) ? src[j * 2 + 0] : src[j * 2 + 2];
-    acc += increment;
+
+    if (2 * i + 1 < n && j < src_width) {
+      dest[i * 4 + 2] = (x < 32768
+          || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
+      acc += increment;
+    }
   }
 
   *accumulator = acc;
@@ -324,34 +475,58 @@
 
 
 void
-vs_scanline_resample_linear_YUYV (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_YUYV (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
   int j;
   int x;
+  int quads = (n + 1) / 2;
 
-  for (i = 0; i < n; i++) {
+  for (i = 0; i < quads; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 0] = (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
+
+    if (j + 1 < src_width)
+      dest[i * 4 + 0] =
+          (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
+    else
+      dest[i * 4 + 0] = src[j * 2 + 0];
 
     j = acc >> 17;
     x = acc & 0x1ffff;
-    dest[i * 4 + 1] =
-        (src[j * 4 + 1] * (131072 - x) + src[j * 4 + 5] * x) >> 17;
-    dest[i * 4 + 3] =
-        (src[j * 4 + 3] * (131072 - x) + src[j * 4 + 7] * x) >> 17;
+
+    if (2 * (j + 2) < src_width)
+      dest[i * 4 + 1] =
+          (src[j * 4 + 1] * (131072 - x) + src[j * 4 + 5] * x) >> 17;
+    else
+      dest[i * 4 + 1] = src[j * 4 + 1];
+
+    if (2 * i + 1 < n && 2 * (j + 1) < src_width) {
+      if (2 * (j + 3) < src_width)
+        dest[i * 4 + 3] =
+            (src[j * 4 + 3] * (131072 - x) + src[j * 4 + 7] * x) >> 17;
+      else
+        dest[i * 4 + 3] = src[j * 4 + 3];
+    }
 
     acc += increment;
 
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 2] = (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
-    acc += increment;
+
+    if (2 * i + 1 < n && j < src_width) {
+      if (j + 1 < src_width)
+        dest[i * 4 + 2] =
+            (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
+      else
+        dest[i * 4 + 2] = src[j * 2 + 0];
+      acc += increment;
+    }
   }
 
+
   *accumulator = acc;
 }
 #ifdef __SYMBIAN32__
@@ -364,16 +539,20 @@
     int n, int x)
 {
   int i;
+  int quads = (n + 1) / 2;
 
-  for (i = 0; i < n; i++) {
+  for (i = 0; i < quads; i++) {
     dest[i * 4 + 0] =
         (src1[i * 4 + 0] * (65536 - x) + src2[i * 4 + 0] * x) >> 16;
     dest[i * 4 + 1] =
         (src1[i * 4 + 1] * (65536 - x) + src2[i * 4 + 1] * x) >> 16;
-    dest[i * 4 + 2] =
-        (src1[i * 4 + 2] * (65536 - x) + src2[i * 4 + 2] * x) >> 16;
-    dest[i * 4 + 3] =
-        (src1[i * 4 + 3] * (65536 - x) + src2[i * 4 + 3] * x) >> 16;
+
+    if (2 * i + 1 < n) {
+      dest[i * 4 + 2] =
+          (src1[i * 4 + 2] * (65536 - x) + src2[i * 4 + 2] * x) >> 16;
+      dest[i * 4 + 3] =
+          (src1[i * 4 + 3] * (65536 - x) + src2[i * 4 + 3] * x) >> 16;
+    }
   }
 }
 
@@ -405,30 +584,42 @@
 
 
 void
-vs_scanline_resample_nearest_UYVY (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_UYVY (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
   int j;
   int x;
+  int quads = (n + 1) / 2;
 
-  for (i = 0; i < n; i++) {
+  for (i = 0; i < quads; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 1] = (x < 32768) ? src[j * 2 + 1] : src[j * 2 + 3];
+
+    dest[i * 4 + 1] = (x < 32768
+        || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
 
     j = acc >> 17;
     x = acc & 0x1ffff;
-    dest[i * 4 + 0] = (x < 65536) ? src[j * 4 + 0] : src[j * 4 + 4];
-    dest[i * 4 + 2] = (x < 65536) ? src[j * 4 + 2] : src[j * 4 + 6];
+
+    dest[i * 4 + 0] = (x < 65536
+        || 2 * (j + 2) >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4];
+
+    if (2 * i + 1 < n && 2 * (j + 1) < src_width)
+      dest[i * 4 + 2] = (x < 65536
+          || 2 * (j + 3) >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6];
 
     acc += increment;
 
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 3] = (x < 32768) ? src[j * 2 + 1] : src[j * 2 + 3];
-    acc += increment;
+
+    if (2 * i + 1 < n && j < src_width) {
+      dest[i * 4 + 3] = (x < 32768
+          || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
+      acc += increment;
+    }
   }
 
   *accumulator = acc;
@@ -439,32 +630,54 @@
 
 
 void
-vs_scanline_resample_linear_UYVY (uint8_t * dest, uint8_t * src, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_UYVY (uint8_t * dest, uint8_t * src, int src_width,
+    int n, int *accumulator, int increment)
 {
   int acc = *accumulator;
   int i;
   int j;
   int x;
+  int quads = (n + 1) / 2;
 
-  for (i = 0; i < n; i++) {
+  for (i = 0; i < quads; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 1] = (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
+
+    if (j + 1 < src_width)
+      dest[i * 4 + 1] =
+          (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
+    else
+      dest[i * 4 + 1] = src[j * 2 + 1];
 
     j = acc >> 17;
     x = acc & 0x1ffff;
-    dest[i * 4 + 0] =
-        (src[j * 4 + 0] * (131072 - x) + src[j * 4 + 4] * x) >> 17;
-    dest[i * 4 + 2] =
-        (src[j * 4 + 2] * (131072 - x) + src[j * 4 + 6] * x) >> 17;
+    if (2 * (j + 2) < src_width)
+      dest[i * 4 + 0] =
+          (src[j * 4 + 0] * (131072 - x) + src[j * 4 + 4] * x) >> 17;
+    else
+      dest[i * 4 + 0] = src[j * 4 + 0];
+
+    if (i * 2 + 1 < n && 2 * (j + 1) < src_width) {
+      if (2 * (j + 3) < src_width)
+        dest[i * 4 + 2] =
+            (src[j * 4 + 2] * (131072 - x) + src[j * 4 + 6] * x) >> 17;
+      else
+        dest[i * 4 + 2] = src[j * 4 + 2];
+    }
 
     acc += increment;
 
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i * 4 + 3] = (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
-    acc += increment;
+
+    if (2 * i + 1 < n && j < src_width) {
+      if (j + 1 < src_width)
+        dest[i * 4 + 3] =
+            (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
+      else
+        dest[i * 4 + 3] = src[j * 2 + 1];
+      acc += increment;
+    }
   }
 
   *accumulator = acc;
@@ -475,13 +688,25 @@
 
 
 void
-vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1, uint8_t * src2,
-    int n, int x)
+vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1,
+    uint8_t * src2, int n, int x)
 {
-  uint32_t value = x >> 8;
+  int i;
+  int quads = (n + 1) / 2;
 
-  oil_merge_linear_argb ((uint32_t *) dest, (uint32_t *) src1,
-      (uint32_t *) src2, &value, n);
+  for (i = 0; i < quads; i++) {
+    dest[i * 4 + 0] =
+        (src1[i * 4 + 0] * (65536 - x) + src2[i * 4 + 0] * x) >> 16;
+    dest[i * 4 + 1] =
+        (src1[i * 4 + 1] * (65536 - x) + src2[i * 4 + 1] * x) >> 16;
+
+    if (2 * i + 1 < n) {
+      dest[i * 4 + 2] =
+          (src1[i * 4 + 2] * (65536 - x) + src2[i * 4 + 2] * x) >> 16;
+      dest[i * 4 + 3] =
+          (src1[i * 4 + 3] * (65536 - x) + src2[i * 4 + 3] * x) >> 16;
+    }
+  }
 }
 
 
@@ -519,8 +744,8 @@
 
 
 void
-vs_scanline_resample_nearest_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
+    int src_width, int n, int *accumulator, int increment)
 {
   uint16_t *dest = (uint16_t *) dest_u8;
   uint16_t *src = (uint16_t *) src_u8;
@@ -532,7 +757,7 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i] = (x < 32768) ? src[j] : src[j + 1];
+    dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
 
     acc += increment;
   }
@@ -545,8 +770,8 @@
 
 
 void
-vs_scanline_resample_linear_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
+    int src_width, int n, int *accumulator, int increment)
 {
   uint16_t *dest = (uint16_t *) dest_u8;
   uint16_t *src = (uint16_t *) src_u8;
@@ -558,10 +783,16 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i] = RGB565 (
-        (RGB565_R (src[j]) * (65536 - x) + RGB565_R (src[j + 1]) * x) >> 16,
-        (RGB565_G (src[j]) * (65536 - x) + RGB565_G (src[j + 1]) * x) >> 16,
-        (RGB565_B (src[j]) * (65536 - x) + RGB565_B (src[j + 1]) * x) >> 16);
+
+    if (j + 1 < src_width) {
+      dest[i] = RGB565 (
+          (RGB565_R (src[j]) * (65536 - x) + RGB565_R (src[j + 1]) * x) >> 16,
+          (RGB565_G (src[j]) * (65536 - x) + RGB565_G (src[j + 1]) * x) >> 16,
+          (RGB565_B (src[j]) * (65536 - x) + RGB565_B (src[j + 1]) * x) >> 16);
+    } else {
+      dest[i] = RGB565 (RGB565_R (src[j]),
+          RGB565_G (src[j]), RGB565_B (src[j]));
+    }
 
     acc += increment;
   }
@@ -625,8 +856,8 @@
 
 
 void
-vs_scanline_resample_nearest_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_nearest_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
+    int src_width, int n, int *accumulator, int increment)
 {
   uint16_t *dest = (uint16_t *) dest_u8;
   uint16_t *src = (uint16_t *) src_u8;
@@ -638,7 +869,7 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i] = (x < 32768) ? src[j] : src[j + 1];
+    dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
 
     acc += increment;
   }
@@ -651,8 +882,8 @@
 
 
 void
-vs_scanline_resample_linear_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n,
-    int *accumulator, int increment)
+vs_scanline_resample_linear_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
+    int src_width, int n, int *accumulator, int increment)
 {
   uint16_t *dest = (uint16_t *) dest_u8;
   uint16_t *src = (uint16_t *) src_u8;
@@ -664,10 +895,16 @@
   for (i = 0; i < n; i++) {
     j = acc >> 16;
     x = acc & 0xffff;
-    dest[i] = RGB555 (
-        (RGB555_R (src[j]) * (65536 - x) + RGB555_R (src[j + 1]) * x) >> 16,
-        (RGB555_G (src[j]) * (65536 - x) + RGB555_G (src[j + 1]) * x) >> 16,
-        (RGB555_B (src[j]) * (65536 - x) + RGB555_B (src[j + 1]) * x) >> 16);
+
+    if (j + 1 < src_width) {
+      dest[i] = RGB555 (
+          (RGB555_R (src[j]) * (65536 - x) + RGB555_R (src[j + 1]) * x) >> 16,
+          (RGB555_G (src[j]) * (65536 - x) + RGB555_G (src[j + 1]) * x) >> 16,
+          (RGB555_B (src[j]) * (65536 - x) + RGB555_B (src[j + 1]) * x) >> 16);
+    } else {
+      dest[i] = RGB555 (RGB555_R (src[j]),
+          RGB555_G (src[j]), RGB555_B (src[j]));
+    }
 
     acc += increment;
   }
--- a/gst_plugins_base/gst/videoscale/vs_scanline.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videoscale/vs_scanline.h	Fri Apr 16 15:15:52 2010 +0300
@@ -38,42 +38,173 @@
 #endif
 
 void vs_scanline_downsample_Y (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_Y (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_Y (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_Y (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_Y (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_scanline_downsample_RGBA (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_RGBA (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_RGBA (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_RGBA (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_RGBA (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_RGBA (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_scanline_downsample_RGB (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_RGB (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_RGB (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_RGB (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_RGB (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_RGB (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_scanline_downsample_YUYV (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_YUYV (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_YUYV (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_YUYV (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_YUYV (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_YUYV (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_scanline_downsample_UYVY (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_UYVY (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_UYVY (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_UYVY (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_UYVY (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_scanline_downsample_RGB565 (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_RGB565 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_RGB565 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_RGB565 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 void vs_scanline_downsample_RGB555 (uint8_t *dest, uint8_t *src, int n);
-void vs_scanline_resample_nearest_RGB555 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
-void vs_scanline_resample_linear_RGB555 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_RGB555 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_RGB555 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void vs_scanline_merge_linear_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_downsample_Y16 (uint8_t *dest, uint8_t *src, int n);
+
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_nearest_Y16 (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment);
+
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_resample_linear_Y16 (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void vs_scanline_merge_linear_Y16 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
 
 #ifdef __SYMBIAN32__
 G_END_DECLS
 #endif
+
 #endif
 
--- a/gst_plugins_base/gst/videotestsrc/gstvideotestsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videotestsrc/gstvideotestsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,19 +21,15 @@
 /**
  * SECTION:element-videotestsrc
  *
- * <refsect2>
- * <para>
  * The videotestsrc element is used to produce test video data in a wide variaty
  * of formats. The video test data produced can be controlled with the "pattern"
  * property.
- * </para>
+ *
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v videotestsrc pattern=snow ! ximagesink
- * </programlisting>
- * Shows random noise in an X window.
- * </para>
+ * ]| Shows random noise in an X window.
  * </refsect2>
  */
 
@@ -45,28 +41,48 @@
 
 #include <string.h>
 #include <stdlib.h>
-#include <gst/liboil.h>
+#include <liboil/liboil.h>
 
-#define USE_PEER_BUFFERALLOC
+#ifdef __SYMBIAN32__
+#include <liboil/globals.h>
+#endif
 
 GST_DEBUG_CATEGORY_STATIC (video_test_src_debug);
 #define GST_CAT_DEFAULT video_test_src_debug
 
-
 static const GstElementDetails video_test_src_details =
 GST_ELEMENT_DETAILS ("Video test source",
     "Source/Video",
     "Creates a test video stream",
     "David A. Schleef <ds@schleef.org>");
 
+#define DEFAULT_PATTERN            GST_VIDEO_TEST_SRC_SMPTE
+#define DEFAULT_TIMESTAMP_OFFSET   0
+#define DEFAULT_IS_LIVE            FALSE
+#define DEFAULT_PEER_ALLOC         TRUE
+#define DEFAULT_COLOR_SPEC         GST_VIDEO_TEST_SRC_BT601
 
 enum
 {
   PROP_0,
   PROP_PATTERN,
   PROP_TIMESTAMP_OFFSET,
-  PROP_IS_LIVE
-      /* FILL ME */
+  PROP_IS_LIVE,
+  PROP_PEER_ALLOC,
+  PROP_COLOR_SPEC,
+  PROP_K0,
+  PROP_KX,
+  PROP_KY,
+  PROP_KT,
+  PROP_KXT,
+  PROP_KYT,
+  PROP_KXY,
+  PROP_KX2,
+  PROP_KY2,
+  PROP_KT2,
+  PROP_XOFFSET,
+  PROP_YOFFSET,
+  PROP_LAST
 };
 
 
@@ -115,6 +131,8 @@
     {GST_VIDEO_TEST_SRC_CHECKERS8, "Checkers 8px", "checkers-8"},
     {GST_VIDEO_TEST_SRC_CIRCULAR, "Circular", "circular"},
     {GST_VIDEO_TEST_SRC_BLINK, "Blink", "blink"},
+    {GST_VIDEO_TEST_SRC_SMPTE75, "SMPTE 75% color bars", "smpte75"},
+    {GST_VIDEO_TEST_SRC_ZONE_PLATE, "Zone plate", "zone-plate"},
     {0, NULL, NULL}
   };
 
@@ -125,6 +143,24 @@
   return video_test_src_pattern_type;
 }
 
+#define GST_TYPE_VIDEO_TEST_SRC_COLOR_SPEC (gst_video_test_src_color_spec_get_type ())
+static GType
+gst_video_test_src_color_spec_get_type (void)
+{
+  static GType video_test_src_color_spec_type = 0;
+  static const GEnumValue color_spec_types[] = {
+    {GST_VIDEO_TEST_SRC_BT601, "ITU-R Rec. BT.601", "bt601"},
+    {GST_VIDEO_TEST_SRC_BT709, "ITU-R Rec. BT.709", "bt709"},
+    {0, NULL, NULL}
+  };
+
+  if (!video_test_src_color_spec_type) {
+    video_test_src_color_spec_type =
+        g_enum_register_static ("GstVideoTestSrcColorSpec", color_spec_types);
+  }
+  return video_test_src_color_spec_type;
+}
+
 static void
 gst_video_test_src_base_init (gpointer g_class)
 {
@@ -154,15 +190,79 @@
   g_object_class_install_property (gobject_class, PROP_PATTERN,
       g_param_spec_enum ("pattern", "Pattern",
           "Type of test pattern to generate", GST_TYPE_VIDEO_TEST_SRC_PATTERN,
-          GST_VIDEO_TEST_SRC_SMPTE, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-      PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
-          "Timestamp offset",
+          DEFAULT_PATTERN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_TIMESTAMP_OFFSET,
+      g_param_spec_int64 ("timestamp-offset", "Timestamp offset",
           "An offset added to timestamps set on buffers (in ns)", G_MININT64,
-          G_MAXINT64, 0, G_PARAM_READWRITE));
+          G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_IS_LIVE,
       g_param_spec_boolean ("is-live", "Is Live",
-          "Whether to act as a live source", FALSE, G_PARAM_READWRITE));
+          "Whether to act as a live source", DEFAULT_IS_LIVE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_PEER_ALLOC,
+      g_param_spec_boolean ("peer-alloc", "Peer Alloc",
+          "Ask the peer to allocate an output buffer", DEFAULT_PEER_ALLOC,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_COLOR_SPEC,
+      g_param_spec_enum ("colorspec", "Color Specification",
+          "Generate video in the given color specification",
+          GST_TYPE_VIDEO_TEST_SRC_COLOR_SPEC,
+          DEFAULT_COLOR_SPEC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_K0,
+      g_param_spec_int ("k0", "Zoneplate zero order phase",
+          "Zoneplate zero order phase, for generating plain fields or phase offsets",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KX,
+      g_param_spec_int ("kx", "Zoneplate 1st order x phase",
+          "Zoneplate 1st order x phase, for generating constant horizontal frequencies",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KY,
+      g_param_spec_int ("ky", "Zoneplate 1st order y phase",
+          "Zoneplate 1st order y phase, for generating contant vertical frequencies",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KT,
+      g_param_spec_int ("kt", "Zoneplate 1st order t phase",
+          "Zoneplate 1st order t phase, for generating phase rotation as a function of time",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KXT,
+      g_param_spec_int ("kxt", "Zoneplate x*t product phase",
+          "Zoneplate x*t product phase, normalised to kxy/256 cycles per vertical pixel at width/2 from origin",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KYT,
+      g_param_spec_int ("kyt", "Zoneplate y*t product phase",
+          "Zoneplate y*t product phase", G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KXY,
+      g_param_spec_int ("kxy", "Zoneplate x*y product phase",
+          "Zoneplate x*t product phase", G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KX2,
+      g_param_spec_int ("kx2", "Zoneplate 2nd order x phase",
+          "Zoneplate 2nd order x phase, normalised to kx2/256 cycles per horizontal pixel at width/2 from origin",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KY2,
+      g_param_spec_int ("ky2", "Zoneplate 2nd order y phase",
+          "Zoneplate 2nd order y phase, normailsed to ky2/256 cycles per vertical pixel at height/2 from origin",
+          G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_KT2,
+      g_param_spec_int ("kt2", "Zoneplate 2nd order t phase",
+          "Zoneplate 2nd order t phase, t*t/256 cycles per picture", G_MININT32,
+          G_MAXINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_XOFFSET,
+      g_param_spec_int ("xoffset", "Zoneplate 2nd order products x offset",
+          "Zoneplate 2nd order products x offset", G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_YOFFSET,
+      g_param_spec_int ("yoffset", "Zoneplate 2nd order products y offset",
+          "Zoneplate 2nd order products y offset", G_MININT32, G_MAXINT32, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstbasesrc_class->get_caps = gst_video_test_src_getcaps;
   gstbasesrc_class->set_caps = gst_video_test_src_setcaps;
@@ -182,13 +282,14 @@
 
   gst_pad_set_fixatecaps_function (pad, gst_video_test_src_src_fixate);
 
-  gst_video_test_src_set_pattern (src, GST_VIDEO_TEST_SRC_SMPTE);
+  gst_video_test_src_set_pattern (src, DEFAULT_PATTERN);
 
-  src->timestamp_offset = 0;
+  src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
 
   /* we operate in time */
   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
-  gst_base_src_set_live (GST_BASE_SRC (src), FALSE);
+  gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
+  src->peer_alloc = DEFAULT_PEER_ALLOC;
 }
 
 static void
@@ -251,6 +352,12 @@
     case GST_VIDEO_TEST_SRC_BLINK:
       videotestsrc->make_image = gst_video_test_src_black;
       break;
+    case GST_VIDEO_TEST_SRC_SMPTE75:
+      videotestsrc->make_image = gst_video_test_src_smpte75;
+      break;
+    case GST_VIDEO_TEST_SRC_ZONE_PLATE:
+      videotestsrc->make_image = gst_video_test_src_zoneplate;
+      break;
     default:
       g_assert_not_reached ();
   }
@@ -272,6 +379,48 @@
     case PROP_IS_LIVE:
       gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
       break;
+    case PROP_PEER_ALLOC:
+      src->peer_alloc = g_value_get_boolean (value);
+      break;
+    case PROP_COLOR_SPEC:
+      src->color_spec = g_value_get_enum (value);
+      break;
+    case PROP_K0:
+      src->k0 = g_value_get_int (value);
+      break;
+    case PROP_KX:
+      src->kx = g_value_get_int (value);
+      break;
+    case PROP_KY:
+      src->ky = g_value_get_int (value);
+      break;
+    case PROP_KT:
+      src->kt = g_value_get_int (value);
+      break;
+    case PROP_KXT:
+      src->kxt = g_value_get_int (value);
+      break;
+    case PROP_KYT:
+      src->kyt = g_value_get_int (value);
+      break;
+    case PROP_KXY:
+      src->kxy = g_value_get_int (value);
+      break;
+    case PROP_KX2:
+      src->kx2 = g_value_get_int (value);
+      break;
+    case PROP_KY2:
+      src->ky2 = g_value_get_int (value);
+      break;
+    case PROP_KT2:
+      src->kt2 = g_value_get_int (value);
+      break;
+    case PROP_XOFFSET:
+      src->xoffset = g_value_get_int (value);
+      break;
+    case PROP_YOFFSET:
+      src->yoffset = g_value_get_int (value);
+      break;
     default:
       break;
   }
@@ -293,6 +442,48 @@
     case PROP_IS_LIVE:
       g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
       break;
+    case PROP_PEER_ALLOC:
+      g_value_set_boolean (value, src->peer_alloc);
+      break;
+    case PROP_COLOR_SPEC:
+      g_value_set_enum (value, src->color_spec);
+      break;
+    case PROP_K0:
+      g_value_set_int (value, src->k0);
+      break;
+    case PROP_KX:
+      g_value_set_int (value, src->kx);
+      break;
+    case PROP_KY:
+      g_value_set_int (value, src->ky);
+      break;
+    case PROP_KT:
+      g_value_set_int (value, src->kt);
+      break;
+    case PROP_KXT:
+      g_value_set_int (value, src->kxt);
+      break;
+    case PROP_KYT:
+      g_value_set_int (value, src->kyt);
+      break;
+    case PROP_KXY:
+      g_value_set_int (value, src->kxy);
+      break;
+    case PROP_KX2:
+      g_value_set_int (value, src->kx2);
+      break;
+    case PROP_KY2:
+      g_value_set_int (value, src->ky2);
+      break;
+    case PROP_KT2:
+      g_value_set_int (value, src->kt2);
+      break;
+    case PROP_XOFFSET:
+      g_value_set_int (value, src->xoffset);
+      break;
+    case PROP_YOFFSET:
+      g_value_set_int (value, src->yoffset);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -301,9 +492,12 @@
 
 /* threadsafe because this gets called as the plugin is loaded */
 static GstCaps *
-gst_video_test_src_getcaps (GstBaseSrc * unused)
+gst_video_test_src_getcaps (GstBaseSrc * bsrc)
 {
   static GstCaps *capslist = NULL;
+  GstVideoTestSrc *videotestsrc;
+
+  videotestsrc = GST_VIDEO_TEST_SRC (bsrc);
 
   if (!capslist) {
     GstCaps *caps;
@@ -535,8 +729,8 @@
 gst_video_test_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
 {
   GstVideoTestSrc *src;
-  gulong newsize;
-  GstBuffer *outbuf;
+  gulong newsize, size;
+  GstBuffer *outbuf = NULL;
   GstFlowReturn res;
   GstClockTime next_time;
 
@@ -557,17 +751,31 @@
       "creating buffer of %lu bytes with %dx%d image for frame %d", newsize,
       src->width, src->height, (gint) src->n_frames);
 
-#ifdef USE_PEER_BUFFERALLOC
-  res =
-      gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (psrc),
-      GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)),
-      &outbuf);
-  if (res != GST_FLOW_OK)
-    goto no_buffer;
-#else
-  outbuf = gst_buffer_new_and_alloc (newsize);
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)));
-#endif
+  if (src->peer_alloc) {
+    res =
+        gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (psrc),
+        GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)),
+        &outbuf);
+    if (res != GST_FLOW_OK)
+      goto no_buffer;
+
+    /* the buffer could have renegotiated, we need to discard any buffers of the
+     * wrong size. */
+    size = GST_BUFFER_SIZE (outbuf);
+    newsize = gst_video_test_src_get_size (src, src->width, src->height);
+
+    if (size != newsize) {
+      gst_buffer_unref (outbuf);
+      outbuf = NULL;
+    }
+  }
+
+  if (outbuf == NULL) {
+    outbuf = gst_buffer_new_and_alloc (newsize);
+    gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)));
+  }
+
+  memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf));
 
   if (src->pattern_type == GST_VIDEO_TEST_SRC_BLINK) {
     if (src->n_frames & 0x1) {
@@ -635,7 +843,7 @@
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  //oil_init ();
+  oil_init ();
 
   GST_DEBUG_CATEGORY_INIT (video_test_src_debug, "videotestsrc", 0,
       "Video Test Source");
--- a/gst_plugins_base/gst/videotestsrc/gstvideotestsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videotestsrc/gstvideotestsrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -52,6 +52,8 @@
  * @GST_VIDEO_TEST_SRC_CHECKERS8: Checkers pattern (8px)
  * @GST_VIDEO_TEST_SRC_CIRCULAR: Circular pattern
  * @GST_VIDEO_TEST_SRC_BLINK: Alternate between black and white
+ * @GST_VIDEO_TEST_SRC_SMPTE75: SMPTE test pattern (75% color bars)
+ * @GST_VIDEO_TEST_SRC_ZONE_PLATE: Zone plate
  *
  * The test pattern to produce.
  */
@@ -68,9 +70,23 @@
   GST_VIDEO_TEST_SRC_CHECKERS4,
   GST_VIDEO_TEST_SRC_CHECKERS8,
   GST_VIDEO_TEST_SRC_CIRCULAR,
-  GST_VIDEO_TEST_SRC_BLINK
+  GST_VIDEO_TEST_SRC_BLINK,
+  GST_VIDEO_TEST_SRC_SMPTE75,
+  GST_VIDEO_TEST_SRC_ZONE_PLATE
 } GstVideoTestSrcPattern;
 
+/**
+ * GstVideoTestSrcColorSpec:
+ * @GST_VIDEO_TEST_SRC_BT601: ITU-R Rec. BT.601
+ * @GST_VIDEO_TEST_SRC_BT709: ITU-R Rec. BT.601
+ *
+ * The color specification to use.
+ */
+typedef enum {
+  GST_VIDEO_TEST_SRC_BT601,
+  GST_VIDEO_TEST_SRC_BT709
+} GstVideoTestSrcColorSpec;
+
 typedef struct _GstVideoTestSrc GstVideoTestSrc;
 typedef struct _GstVideoTestSrcClass GstVideoTestSrcClass;
 
@@ -87,6 +103,9 @@
   /* type of output */
   GstVideoTestSrcPattern pattern_type;
 
+  /* Color spec of output */
+  GstVideoTestSrcColorSpec color_spec;
+
   /* video state */
   char *format_name;
   gint width;
@@ -100,13 +119,32 @@
   gint64 timestamp_offset;              /* base offset */
   GstClockTime running_time;            /* total running time */
   gint64 n_frames;                      /* total frames sent */
+  gboolean peer_alloc;
 
+  /* zoneplate */
+  gint k0;
+  gint kx;
+  gint ky;
+  gint kt;
+  gint kxt;
+  gint kyt;
+  gint kxy;
+  gint kx2;
+  gint ky2;
+  gint kt2;
+  gint xoffset;
+  gint yoffset;
+  
   void (*make_image) (GstVideoTestSrc *v, unsigned char *dest, int w, int h);
 };
 
 struct _GstVideoTestSrcClass {
   GstPushSrcClass parent_class;
 };
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GType gst_video_test_src_get_type (void);
 
--- a/gst_plugins_base/gst/videotestsrc/videotestsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videotestsrc/videotestsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,8 +25,11 @@
 
 #include "gstvideotestsrc.h"
 #include "videotestsrc.h"
-#include <gst/liboil.h>
+#include <liboil/liboil.h>
 
+#ifdef __SYMBIAN32__
+#include <liboil/globals.h>
+#endif
 
 #include <string.h>
 #include <stdlib.h>
@@ -209,49 +212,125 @@
   COLOR_DARK_GREY
 };
 
-static const struct vts_color_struct vts_colors[] = {
-  /* 100% white */
-  {255, 128, 128, 255, 255, 255, 255},
-  /* yellow */
-  {226, 0, 155, 255, 255, 0, 255},
-  /* cyan */
-  {179, 170, 0, 0, 255, 255, 255},
-  /* green */
-  {150, 46, 21, 0, 255, 0, 255},
-  /* magenta */
-  {105, 212, 235, 255, 0, 255, 255},
-  /* red */
-  {76, 85, 255, 255, 0, 0, 255},
-  /* blue */
-  {29, 255, 107, 0, 0, 255, 255},
-  /* black */
-  {16, 128, 128, 0, 0, 0, 255},
-  /* -I */
-  {16, 198, 21, 0, 0, 128, 255},
-  /* +Q */
-  {16, 235, 198, 0, 128, 255, 255},
-  /* superblack */
-  {0, 128, 128, 0, 0, 0, 255},
-  /* 5% grey */
-  {32, 128, 128, 32, 32, 32, 255},
+static const struct vts_color_struct_rgb vts_colors_rgb[] = {
+  {255, 255, 255},
+  {255, 255, 0},
+  {0, 255, 255},
+  {0, 255, 0},
+  {255, 0, 255},
+  {255, 0, 0},
+  {0, 0, 255},
+  {0, 0, 0},
+  {0, 0, 128},                  /* -I ? */
+  {0, 128, 255},                /* +Q ? */
+  {0, 0, 0},
+  {19, 19, 19},
+};
+
+static const struct vts_color_struct_rgb vts_colors_rgb_75[] = {
+  {191, 191, 191},
+  {191, 191, 0},
+  {0, 191, 191},
+  {0, 191, 0},
+  {191, 0, 191},
+  {191, 0, 0},
+  {0, 0, 191},
+  {0, 0, 0},
+  {0, 0, 128},                  /* -I ? */
+  {0, 128, 255},                /* +Q ? */
+  {0, 0, 0},
+  {19, 19, 19},
+};
+
+static const struct vts_color_struct_yuv vts_colors_bt709_ycbcr_100[] = {
+  {235, 128, 128},
+  {219, 16, 138},
+  {188, 154, 16},
+  {173, 42, 26},
+  {78, 214, 230},
+  {63, 102, 240},
+  {32, 240, 118},
+  {16, 128, 128},
+  {16, 198, 21},                /* -I ? */
+  {16, 235, 198},               /* +Q ? */
+  {0, 128, 128},
+  {32, 128, 128},
+};
+
+static const struct vts_color_struct_yuv vts_colors_bt709_ycbcr_75[] = {
+  {180, 128, 128},
+  {168, 44, 136},
+  {145, 147, 44},
+  {133, 63, 52},
+  {63, 193, 204},
+  {51, 109, 212},
+  {28, 212, 120},
+  {16, 128, 128},
+  {16, 198, 21},                /* -I ? */
+  {16, 235, 198},               /* +Q ? */
+  {0, 128, 128},
+  {32, 128, 128},
 };
 
+static const struct vts_color_struct_yuv vts_colors_bt601_ycbcr_100[] = {
+  {235, 128, 128},
+  {210, 16, 146},
+  {170, 166, 16},
+  {145, 54, 34},
+  {106, 202, 222},
+  {81, 90, 240},
+  {41, 240, 110},
+  {16, 128, 128},
+  {16, 198, 21},                /* -I ? */
+  {16, 235, 198},               /* +Q ? */
+  {-0, 128, 128},
+  {32, 128, 128},
+};
 
-#if 0
+static const struct vts_color_struct_yuv vts_colors_bt601_ycbcr_75[] = {
+  {180, 128, 128},
+  {162, 44, 142},
+  {131, 156, 44},
+  {112, 72, 58},
+  {84, 184, 198},
+  {65, 100, 212},
+  {35, 212, 114},
+  {16, 128, 128},
+  {16, 198, 21},                /* -I ? */
+  {16, 235, 198},               /* +Q ? */
+  {-0, 128, 128},
+  {32, 128, 128},
+};
 
-/*                        wht  yel  cya  grn  mag  red  blu  blk   -I    Q, superblack, dark grey */
-static int y_colors[] = { 255, 226, 179, 150, 105, 76, 29, 16, 16, 16, 0, 32 };
-static int u_colors[] =
-    { 128, 0, 170, 46, 212, 85, 255, 128, 198, 235, 128, 128 };
-static int v_colors[] =
-    { 128, 155, 0, 21, 235, 255, 107, 128, 21, 198, 128, 128 };
+static const struct vts_color_struct_gray vts_colors_gray_100[] = {
+  {235 << 8},
+  {210 << 8},
+  {170 << 8},
+  {145 << 8},
+  {106 << 8},
+  {81 << 8},
+  {41 << 8},
+  {16 << 8},
+  {16 << 8},
+  {16 << 8},
+  {-0 << 8},
+  {32 << 8},
+};
 
-/*                        wht  yel  cya  grn  mag  red  blu  blk   -I    Q  superblack, dark grey */
-static int r_colors[] = { 255, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 32 };
-static int g_colors[] = { 255, 255, 255, 255, 0, 0, 0, 0, 0, 128, 0, 32 };
-static int b_colors[] = { 255, 0, 255, 0, 255, 0, 255, 0, 128, 255, 0, 32 };
-#endif
-
+static const struct vts_color_struct_gray vts_colors_gray_75[] = {
+  {180 << 8},
+  {162 << 8},
+  {131 << 8},
+  {112 << 8},
+  {84 << 8},
+  {65 << 8},
+  {35 << 8},
+  {16 << 8},
+  {16 << 8},
+  {16 << 8},
+  {-0 << 8},
+  {32 << 8},
+};
 
 static void paint_setup_I420 (paintinfo * p, unsigned char *dest);
 static void paint_setup_YV12 (paintinfo * p, unsigned char *dest);
@@ -261,8 +340,15 @@
 static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest);
 static void paint_setup_Y41B (paintinfo * p, unsigned char *dest);
 static void paint_setup_Y42B (paintinfo * p, unsigned char *dest);
+static void paint_setup_Y444 (paintinfo * p, unsigned char *dest);
 static void paint_setup_Y800 (paintinfo * p, unsigned char *dest);
 static void paint_setup_AYUV (paintinfo * p, unsigned char *dest);
+static void paint_setup_v308 (paintinfo * p, unsigned char *dest);
+static void paint_setup_NV12 (paintinfo * p, unsigned char *dest);
+static void paint_setup_NV21 (paintinfo * p, unsigned char *dest);
+static void paint_setup_v410 (paintinfo * p, unsigned char *dest);
+static void paint_setup_v216 (paintinfo * p, unsigned char *dest);
+static void paint_setup_v210 (paintinfo * p, unsigned char *dest);
 
 #if 0
 static void paint_setup_IMC1 (paintinfo * p, unsigned char *dest);
@@ -288,12 +374,18 @@
 static void paint_setup_bayer (paintinfo * p, unsigned char *dest);
 
 static void paint_hline_I420 (paintinfo * p, int x, int y, int w);
+static void paint_hline_NV12_NV21 (paintinfo * p, int x, int y, int w);
 static void paint_hline_YUY2 (paintinfo * p, int x, int y, int w);
 static void paint_hline_IYU2 (paintinfo * p, int x, int y, int w);
 static void paint_hline_Y41B (paintinfo * p, int x, int y, int w);
 static void paint_hline_Y42B (paintinfo * p, int x, int y, int w);
+static void paint_hline_Y444 (paintinfo * p, int x, int y, int w);
 static void paint_hline_Y800 (paintinfo * p, int x, int y, int w);
+static void paint_hline_v308 (paintinfo * p, int x, int y, int w);
 static void paint_hline_AYUV (paintinfo * p, int x, int y, int w);
+static void paint_hline_v410 (paintinfo * p, int x, int y, int w);
+static void paint_hline_v216 (paintinfo * p, int x, int y, int w);
+static void paint_hline_v210 (paintinfo * p, int x, int y, int w);
 
 #if 0
 static void paint_hline_IMC1 (paintinfo * p, int x, int y, int w);
@@ -306,6 +398,11 @@
 
 static void paint_hline_bayer (paintinfo * p, int x, int y, int w);
 
+static void paint_setup_GRAY8 (paintinfo * p, unsigned char *dest);
+static void paint_setup_GRAY16 (paintinfo * p, unsigned char *dest);
+static void paint_hline_GRAY8 (paintinfo * p, int x, int y, int w);
+static void paint_hline_GRAY16 (paintinfo * p, int x, int y, int w);
+
 struct fourcc_list_struct fourcc_list[] = {
 /* packed */
   {VTS_YUV, "YUY2", "YUY2", 16, paint_setup_YUY2, paint_hline_YUY2},
@@ -313,7 +410,11 @@
   {VTS_YUV, "Y422", "Y422", 16, paint_setup_UYVY, paint_hline_YUY2},
   {VTS_YUV, "UYNV", "UYNV", 16, paint_setup_UYVY, paint_hline_YUY2},    /* FIXME: UYNV? */
   {VTS_YUV, "YVYU", "YVYU", 16, paint_setup_YVYU, paint_hline_YUY2},
+  {VTS_YUV, "v308", "v308", 24, paint_setup_v308, paint_hline_v308},
   {VTS_YUV, "AYUV", "AYUV", 32, paint_setup_AYUV, paint_hline_AYUV},
+  {VTS_YUV, "v410", "v410", 32, paint_setup_v410, paint_hline_v410},
+  {VTS_YUV, "v210", "v210", 21, paint_setup_v210, paint_hline_v210},
+  {VTS_YUV, "v216", "v216", 32, paint_setup_v216, paint_hline_v216},
 
   /* interlaced */
   /*{ VTS_YUV,  "IUYV", "IUY2", 16, paint_setup_YVYU, paint_hline_YUY2 }, */
@@ -345,7 +446,9 @@
   /* I420 */
   {VTS_YUV, "I420", "I420", 12, paint_setup_I420, paint_hline_I420},
   /* NV12 */
+  {VTS_YUV, "NV12", "NV12", 12, paint_setup_NV12, paint_hline_NV12_NV21},
   /* NV21 */
+  {VTS_YUV, "NV21", "NV21", 12, paint_setup_NV21, paint_hline_NV12_NV21},
 #if 0
   /* IMC1 */
   {VTS_YUV, "IMC1", "IMC1", 16, paint_setup_IMC1, paint_hline_IMC1},
@@ -361,9 +464,15 @@
   {VTS_YUV, "Y41B", "Y41B", 12, paint_setup_Y41B, paint_hline_Y41B},
   /* Y42B */
   {VTS_YUV, "Y42B", "Y42B", 16, paint_setup_Y42B, paint_hline_Y42B},
+  /* Y444 */
+  {VTS_YUV, "Y444", "Y444", 24, paint_setup_Y444, paint_hline_Y444},
   /* Y800 grayscale */
   {VTS_YUV, "Y800", "Y800", 8, paint_setup_Y800, paint_hline_Y800},
 
+  /* Not exactly YUV but it's the same as above */
+  {VTS_GRAY, "GRAY8", "GRAY8", 8, paint_setup_GRAY8, paint_hline_GRAY8},
+  {VTS_GRAY, "GRAY16", "GRAY16", 16, paint_setup_GRAY16, paint_hline_GRAY16},
+
   {VTS_RGB, "RGB ", "xRGB8888", 32, paint_setup_xRGB8888, paint_hline_str4, 24,
       0x00ff0000, 0x0000ff00, 0x000000ff},
   {VTS_RGB, "RGB ", "xBGR8888", 32, paint_setup_xBGR8888, paint_hline_str4, 24,
@@ -392,6 +501,7 @@
 
   {VTS_BAYER, "BAY8", "Bayer", 8, paint_setup_bayer, paint_hline_bayer}
 };
+
 int n_fourccs = G_N_ELEMENTS (fourcc_list);
 
 struct fourcc_list_struct *
@@ -403,7 +513,24 @@
 
   g_return_val_if_fail (structure, NULL);
 
-  if (strcmp (media_type, "video/x-raw-yuv") == 0) {
+  if (strcmp (media_type, "video/x-raw-gray") == 0) {
+    gint bpp, depth, endianness = 0;
+
+    ret = gst_structure_get_int (structure, "bpp", &bpp) &&
+        gst_structure_get_int (structure, "depth", &depth);
+    if (!ret || bpp != depth || (depth != 8 && depth != 16))
+      return NULL;
+
+    ret = gst_structure_get_int (structure, "endianness", &endianness);
+    if ((!ret || endianness != G_BYTE_ORDER) && bpp == 16)
+      return NULL;
+
+    for (i = 0; i < n_fourccs; i++) {
+      if (fourcc_list[i].type == VTS_GRAY && fourcc_list[i].bitspp == bpp) {
+        return fourcc_list + i;
+      }
+    }
+  } else if (strcmp (media_type, "video/x-raw-yuv") == 0) {
     char *s;
     int fourcc;
     guint32 format;
@@ -539,6 +666,14 @@
             format->alpha_mask, NULL);
       }
       break;
+    case VTS_GRAY:
+      structure = gst_structure_new ("video/x-raw-gray",
+          "bpp", G_TYPE_INT, format->bitspp, "depth", G_TYPE_INT,
+          format->bitspp, NULL);
+      if (format->bitspp == 16)
+        gst_structure_set (structure, "endianness", G_TYPE_INT, G_BYTE_ORDER,
+            NULL);
+      break;
     case VTS_YUV:
       structure = gst_structure_new ("video/x-raw-yuv",
           "format", GST_TYPE_FOURCC, fourcc, NULL);
@@ -584,6 +719,13 @@
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -601,7 +743,9 @@
     int x1 = i * w / 7;
     int x2 = (i + 1) * w / 7;
 
-    p->color = vts_colors + i;
+    p->yuv_color = p->yuv_colors + i;
+    p->rgb_color = p->rgb_colors + i;
+    p->gray_color = p->gray_colors + i;
     for (j = 0; j < y1; j++) {
       p->paint_hline (p, x1, j, (x2 - x1));
     }
@@ -618,7 +762,9 @@
     } else {
       k = 6 - i;
     }
-    p->color = vts_colors + k;
+    p->yuv_color = p->yuv_colors + k;
+    p->rgb_color = p->rgb_colors + k;
+    p->gray_color = p->gray_colors + k;
     for (j = y1; j < y2; j++) {
       p->paint_hline (p, x1, j, (x2 - x1));
     }
@@ -637,7 +783,9 @@
     } else
       k = 9;
 
-    p->color = vts_colors + k;
+    p->yuv_color = p->yuv_colors + k;
+    p->rgb_color = p->rgb_colors + k;
+    p->gray_color = p->gray_colors + k;
     for (j = y2; j < h; j++) {
       p->paint_hline (p, x1, j, (x2 - x1));
     }
@@ -656,7 +804,9 @@
     } else
       k = COLOR_DARK_GREY;
 
-    p->color = vts_colors + k;
+    p->yuv_color = p->yuv_colors + k;
+    p->rgb_color = p->rgb_colors + k;
+    p->gray_color = p->gray_colors + k;
     for (j = y2; j < h; j++) {
       p->paint_hline (p, x1, j, (x2 - x1));
     }
@@ -664,18 +814,26 @@
 
   {
     int x1 = w * 3 / 4;
-    struct vts_color_struct color;
+    struct vts_color_struct_rgb rgb_color;
+    struct vts_color_struct_yuv yuv_color;
+    struct vts_color_struct_gray gray_color;
 
-    color = vts_colors[COLOR_BLACK];
-    p->color = &color;
+    rgb_color = p->rgb_colors[COLOR_BLACK];
+    yuv_color = p->yuv_colors[COLOR_BLACK];
+    gray_color = p->gray_colors[COLOR_BLACK];
+    p->rgb_color = &rgb_color;
+    p->yuv_color = &yuv_color;
+    p->gray_color = &gray_color;
 
     for (i = x1; i < w; i++) {
       for (j = y2; j < h; j++) {
         /* FIXME not strictly correct */
-        color.Y = random_char ();
-        color.R = color.Y;
-        color.G = color.Y;
-        color.B = color.Y;
+        int y = random_char ();
+        yuv_color.Y = y;
+        rgb_color.R = y;
+        rgb_color.G = y;
+        rgb_color.B = y;
+        gray_color.G = (y << 8) | random_char ();
         p->paint_hline (p, i, j, 1);
       }
     }
@@ -684,6 +842,46 @@
 }
 
 void
+gst_video_test_src_smpte75 (GstVideoTestSrc * v, unsigned char *dest, int w,
+    int h)
+{
+  int i;
+  int j;
+  paintinfo pi = { NULL, };
+  paintinfo *p = &pi;
+  struct fourcc_list_struct *fourcc;
+
+  p->rgb_colors = vts_colors_rgb_75;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_75;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_75;
+  }
+  p->gray_colors = vts_colors_gray_75;
+  p->width = w;
+  p->height = h;
+  fourcc = v->fourcc;
+  if (fourcc == NULL)
+    return;
+
+  fourcc->paint_setup (p, dest);
+  p->paint_hline = fourcc->paint_hline;
+
+  /* color bars */
+  for (i = 0; i < 7; i++) {
+    int x1 = i * w / 7;
+    int x2 = (i + 1) * w / 7;
+
+    p->yuv_color = p->yuv_colors + i;
+    p->rgb_color = p->rgb_colors + i;
+    p->gray_color = p->gray_colors + i;
+    for (j = 0; j < h; j++) {
+      p->paint_hline (p, x1, j, (x2 - x1));
+    }
+  }
+}
+
+void
 gst_video_test_src_snow (GstVideoTestSrc * v, unsigned char *dest, int w, int h)
 {
   int i;
@@ -691,8 +889,17 @@
   paintinfo pi = { NULL, };
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
-  struct vts_color_struct color;
+  struct vts_color_struct_rgb rgb_color;
+  struct vts_color_struct_yuv yuv_color;
+  struct vts_color_struct_gray gray_color;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -702,16 +909,22 @@
   fourcc->paint_setup (p, dest);
   p->paint_hline = fourcc->paint_hline;
 
-  color = vts_colors[COLOR_BLACK];
-  p->color = &color;
+  rgb_color = p->rgb_colors[COLOR_BLACK];
+  yuv_color = p->yuv_colors[COLOR_BLACK];
+  gray_color = p->gray_colors[COLOR_BLACK];
+  p->rgb_color = &rgb_color;
+  p->yuv_color = &yuv_color;
+  p->gray_color = &gray_color;
 
   for (i = 0; i < w; i++) {
     for (j = 0; j < h; j++) {
       /* FIXME not strictly correct */
-      color.Y = random_char ();
-      color.R = color.Y;
-      color.G = color.Y;
-      color.B = color.Y;
+      int y = random_char ();
+      yuv_color.Y = y;
+      rgb_color.R = y;
+      rgb_color.G = y;
+      rgb_color.B = y;
+      gray_color.G = (y << 8) | random_char ();
       p->paint_hline (p, i, j, 1);
     }
   }
@@ -719,13 +932,20 @@
 
 static void
 gst_video_test_src_unicolor (GstVideoTestSrc * v, unsigned char *dest, int w,
-    int h, const struct vts_color_struct *color)
+    int h, int color_index)
 {
   int i;
   paintinfo pi = { NULL, };
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -735,7 +955,9 @@
   fourcc->paint_setup (p, dest);
   p->paint_hline = fourcc->paint_hline;
 
-  p->color = color;
+  p->rgb_color = p->rgb_colors + color_index;
+  p->yuv_color = p->yuv_colors + color_index;
+  p->gray_color = p->gray_colors + color_index;
 
   for (i = 0; i < h; i++) {
     p->paint_hline (p, 0, i, w);
@@ -745,31 +967,31 @@
 void
 gst_video_test_src_black (GstVideoTestSrc * v, guchar * dest, int w, int h)
 {
-  gst_video_test_src_unicolor (v, dest, w, h, vts_colors + COLOR_BLACK);
+  gst_video_test_src_unicolor (v, dest, w, h, COLOR_BLACK);
 }
 
 void
 gst_video_test_src_white (GstVideoTestSrc * v, guchar * dest, int w, int h)
 {
-  gst_video_test_src_unicolor (v, dest, w, h, vts_colors + COLOR_WHITE);
+  gst_video_test_src_unicolor (v, dest, w, h, COLOR_WHITE);
 }
 
 void
 gst_video_test_src_red (GstVideoTestSrc * v, guchar * dest, int w, int h)
 {
-  gst_video_test_src_unicolor (v, dest, w, h, vts_colors + COLOR_RED);
+  gst_video_test_src_unicolor (v, dest, w, h, COLOR_RED);
 }
 
 void
 gst_video_test_src_green (GstVideoTestSrc * v, guchar * dest, int w, int h)
 {
-  gst_video_test_src_unicolor (v, dest, w, h, vts_colors + COLOR_GREEN);
+  gst_video_test_src_unicolor (v, dest, w, h, COLOR_GREEN);
 }
 
 void
 gst_video_test_src_blue (GstVideoTestSrc * v, guchar * dest, int w, int h)
 {
-  gst_video_test_src_unicolor (v, dest, w, h, vts_colors + COLOR_BLUE);
+  gst_video_test_src_unicolor (v, dest, w, h, COLOR_BLUE);
 }
 
 void
@@ -780,6 +1002,13 @@
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -790,10 +1019,14 @@
   p->paint_hline = fourcc->paint_hline;
 
   for (y = 0; y < h; y++) {
-    p->color = vts_colors + COLOR_GREEN;
+    p->rgb_color = p->rgb_colors + COLOR_GREEN;
+    p->yuv_color = p->yuv_colors + COLOR_GREEN;
+    p->gray_color = p->gray_colors + COLOR_GREEN;
     p->paint_hline (p, 0, y, w);
     for (x = (y % 2); x < w; x += 2) {
-      p->color = vts_colors + COLOR_RED;
+      p->rgb_color = p->rgb_colors + COLOR_RED;
+      p->yuv_color = p->yuv_colors + COLOR_RED;
+      p->gray_color = p->gray_colors + COLOR_RED;
       p->paint_hline (p, x, y, 1);
     }
   }
@@ -807,6 +1040,13 @@
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -816,7 +1056,9 @@
   fourcc->paint_setup (p, dest);
   p->paint_hline = fourcc->paint_hline;
 
-  p->color = vts_colors + COLOR_GREEN;
+  p->rgb_color = p->rgb_colors + COLOR_GREEN;
+  p->yuv_color = p->yuv_colors + COLOR_GREEN;
+  p->gray_color = p->gray_colors + COLOR_GREEN;
   for (y = 0; y < h; y++) {
     p->paint_hline (p, 0, y, w);
   }
@@ -825,7 +1067,9 @@
     for (x = ((y % 4) == 0) ? 0 : 2; x < w; x += 4) {
       guint len = (x < (w - 1)) ? 2 : (w - x);
 
-      p->color = vts_colors + COLOR_RED;
+      p->rgb_color = p->rgb_colors + COLOR_RED;
+      p->yuv_color = p->yuv_colors + COLOR_RED;
+      p->gray_color = p->gray_colors + COLOR_RED;
       p->paint_hline (p, x, y + 0, len);
       if (G_LIKELY ((y + 1) < h)) {
         p->paint_hline (p, x, y + 1, len);
@@ -842,6 +1086,13 @@
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -851,7 +1102,9 @@
   fourcc->paint_setup (p, dest);
   p->paint_hline = fourcc->paint_hline;
 
-  p->color = vts_colors + COLOR_GREEN;
+  p->rgb_color = p->rgb_colors + COLOR_GREEN;
+  p->yuv_color = p->yuv_colors + COLOR_GREEN;
+  p->gray_color = p->gray_colors + COLOR_GREEN;
   for (y = 0; y < h; y++) {
     p->paint_hline (p, 0, y, w);
   }
@@ -860,7 +1113,9 @@
     for (x = ((y % 8) == 0) ? 0 : 4; x < w; x += 8) {
       guint len = (x < (w - 3)) ? 4 : (w - x);
 
-      p->color = vts_colors + COLOR_RED;
+      p->rgb_color = p->rgb_colors + COLOR_RED;
+      p->yuv_color = p->yuv_colors + COLOR_RED;
+      p->gray_color = p->gray_colors + COLOR_RED;
       p->paint_hline (p, x, y + 0, len);
       if (G_LIKELY ((y + 1) < h)) {
         p->paint_hline (p, x, y + 1, len);
@@ -883,6 +1138,13 @@
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -892,40 +1154,183 @@
   fourcc->paint_setup (p, dest);
   p->paint_hline = fourcc->paint_hline;
 
-  p->color = vts_colors + COLOR_GREEN;
+  p->rgb_color = p->rgb_colors + COLOR_GREEN;
+  p->yuv_color = p->yuv_colors + COLOR_GREEN;
+  p->gray_color = p->gray_colors + COLOR_GREEN;
   for (y = 0; y < h; y++) {
-    p->paint_hline (p, 0, y, w);
+    for (x = 0; x < w; x += 8) {
+      int len = MIN (8, w - x);
+
+      if ((x ^ y) & (1 << 4)) {
+        p->rgb_color = p->rgb_colors + COLOR_GREEN;
+        p->yuv_color = p->yuv_colors + COLOR_GREEN;
+        p->gray_color = p->gray_colors + COLOR_GREEN;
+      } else {
+        p->rgb_color = p->rgb_colors + COLOR_RED;
+        p->yuv_color = p->yuv_colors + COLOR_RED;
+        p->gray_color = p->gray_colors + COLOR_RED;
+      }
+      p->paint_hline (p, x, y, len);
+    }
+  }
+}
+
+void
+gst_video_test_src_zoneplate (GstVideoTestSrc * v, unsigned char *dest,
+    int w, int h)
+{
+  int i;
+  int j;
+  paintinfo pi = { NULL, };
+  paintinfo *p = &pi;
+  struct fourcc_list_struct *fourcc;
+  struct vts_color_struct_rgb rgb_color;
+  struct vts_color_struct_yuv yuv_color;
+  struct vts_color_struct_gray gray_color;
+  static uint8_t sine_array[256];
+  static int sine_array_inited = FALSE;
+
+  static int t = 0;             /* time - increment phase vs time by 1 for each generated frame */
+  /* this may not fit with the correct gstreamer notion of time, so maybe FIXME? */
+
+  int xreset = -(w / 2) - v->xoffset;   /* starting values for x^2 and y^2, centering the ellipse */
+  int yreset = -(h / 2) - v->yoffset;
+
+  int x, y;
+  int accum_kx;
+  int accum_kxt;
+  int accum_ky;
+  int accum_kyt;
+  int accum_kxy;
+  int kt;
+  int kt2;
+  int ky2;
+  int delta_kxt = v->kxt * t;
+  int delta_kxy;
+  int scale_kxy = 0xffff / (w / 2);
+  int scale_kx2 = 0xffff / w;
+
+  if (!sine_array_inited) {
+    int black = 16;
+    int white = 235;
+    int range = white - black;
+    for (i = 0; i < 256; i++) {
+      sine_array[i] =
+          floor (range * (0.5 + 0.5 * sin (i * 2 * M_PI / 256)) + 0.5 + black);
+    }
+    sine_array_inited = TRUE;
   }
 
-  for (y = 0; y < h; y += 8) {
-    for (x = ((GST_ROUND_UP_8 (y) % 16) == 0) ? 0 : 8; x < w; x += 16) {
-      guint len = (x < (w - 7)) ? 8 : (w - x);
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
+  p->width = w;
+  p->height = h;
+  fourcc = v->fourcc;
+  if (fourcc == NULL)
+    return;
+
+  fourcc->paint_setup (p, dest);
+  p->paint_hline = fourcc->paint_hline;
+
+  rgb_color = p->rgb_colors[COLOR_BLACK];
+  yuv_color = p->yuv_colors[COLOR_BLACK];
+  gray_color = p->gray_colors[COLOR_BLACK];
+  p->rgb_color = &rgb_color;
+  p->yuv_color = &yuv_color;
+  p->gray_color = &gray_color;
 
-      p->color = vts_colors + COLOR_RED;
-      p->paint_hline (p, x, y + 0, len);
-      if (G_LIKELY ((y + 1) < h)) {
-        p->paint_hline (p, x, y + 1, len);
-        if (G_LIKELY ((y + 2) < h)) {
-          p->paint_hline (p, x, y + 2, len);
-          if (G_LIKELY ((y + 3) < h)) {
-            p->paint_hline (p, x, y + 3, len);
-            if (G_LIKELY ((y + 4) < h)) {
-              p->paint_hline (p, x, y + 4, len);
-              if (G_LIKELY ((y + 5) < h)) {
-                p->paint_hline (p, x, y + 5, len);
-                if (G_LIKELY ((y + 6) < h)) {
-                  p->paint_hline (p, x, y + 6, len);
-                  if (G_LIKELY ((y + 7) < h)) {
-                    p->paint_hline (p, x, y + 7, len);
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
+  /* Zoneplate equation:
+   *
+   * phase = k0 + kx*x + ky*y + kt*t
+   *       + kxt*x*t + kyt*y*t + kxy*x*y
+   *       + kx2*x*x + ky2*y*y + Kt2*t*t
+   */
+
+#if 0
+  for (j = 0, y = yreset; j < h; j++, y++) {
+    for (i = 0, x = xreset; i < w; i++, x++) {
+
+      //zero order
+      int phase = v->k0;
+
+      //first order
+      phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t);
+
+      //cross term
+      //phase = phase + (v->kxt * i * t) + (v->kyt * j * t);
+      //phase = phase + (v->kxy * x * y) / (w/2);
+
+      /*second order */
+      /*normalise x/y terms to rate of change of phase at the picture edge */
+      phase =
+          phase + ((v->kx2 * x * x) / w) + ((v->ky2 * y * y) / h) +
+          ((v->kt2 * t * t) >> 1);
+
+      color.Y = sine_array[phase & 0xff];
+
+      color.R = color.Y;
+      color.G = color.Y;
+      color.B = color.Y;
+      p->paint_hline (p, i, j, 1);
     }
   }
+#endif
+
+  /* optimised version, with original code shown in comments */
+  accum_ky = 0;
+  accum_kyt = 0;
+  kt = v->kt * t;
+  kt2 = v->kt2 * t * t;
+  for (j = 0, y = yreset; j < h; j++, y++) {
+    accum_kx = 0;
+    accum_kxt = 0;
+    accum_ky += v->ky;
+    accum_kyt += v->kyt * t;
+    delta_kxy = v->kxy * y * scale_kxy;
+    accum_kxy = delta_kxy * xreset;
+    ky2 = (v->ky2 * y * y) / h;
+    for (i = 0, x = xreset; i < w; i++, x++) {
+
+      //zero order
+      int phase = v->k0;
+
+      //first order
+      accum_kx += v->kx;
+      //phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t);
+      phase = phase + accum_kx + accum_ky + kt;
+
+      //cross term
+      accum_kxt += delta_kxt;
+      accum_kxy += delta_kxy;
+      //phase = phase + (v->kxt * i * t) + (v->kyt * j * t);
+      phase = phase + accum_kxt + accum_kyt;
+
+      //phase = phase + (v->kxy * x * y) / (w/2);
+      //phase = phase + accum_kxy / (w/2) ;
+      phase = phase + (accum_kxy >> 16);
+
+      /*second order */
+      /*normalise x/y terms to rate of change of phase at the picture edge */
+      //phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1);
+      phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1);
+
+      yuv_color.Y = sine_array[phase & 0xff];
+
+      rgb_color.R = yuv_color.Y;
+      rgb_color.G = yuv_color.Y;
+      rgb_color.B = yuv_color.Y;
+
+      gray_color.G = yuv_color.Y << 8;
+      p->paint_hline (p, i, j, 1);
+    }
+  }
+
+  t++;
 }
 
 #undef SCALE_AMPLITUDE
@@ -938,7 +1343,9 @@
   paintinfo pi = { NULL, };
   paintinfo *p = &pi;
   struct fourcc_list_struct *fourcc;
-  struct vts_color_struct color;
+  struct vts_color_struct_rgb rgb_color;
+  struct vts_color_struct_yuv yuv_color;
+  struct vts_color_struct_gray gray_color;
   static uint8_t sine_array[256];
   static int sine_array_inited = FALSE;
   double freq[8];
@@ -956,6 +1363,13 @@
     sine_array_inited = TRUE;
   }
 
+  p->rgb_colors = vts_colors_rgb;
+  if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) {
+    p->yuv_colors = vts_colors_bt601_ycbcr_100;
+  } else {
+    p->yuv_colors = vts_colors_bt709_ycbcr_100;
+  }
+  p->gray_colors = vts_colors_gray_100;
   p->width = w;
   p->height = h;
   fourcc = v->fourcc;
@@ -965,8 +1379,12 @@
   fourcc->paint_setup (p, dest);
   p->paint_hline = fourcc->paint_hline;
 
-  color = vts_colors[COLOR_BLACK];
-  p->color = &color;
+  rgb_color = p->rgb_colors[COLOR_BLACK];
+  yuv_color = p->yuv_colors[COLOR_BLACK];
+  gray_color = p->gray_colors[COLOR_BLACK];
+  p->rgb_color = &rgb_color;
+  p->yuv_color = &yuv_color;
+  p->gray_color = &gray_color;
 
   for (i = 1; i < 8; i++) {
     freq[i] = 200 * pow (2.0, -(i - 1) / 4.0);
@@ -990,7 +1408,8 @@
               h)) / (2 * w);
       seg = floor (dist * 16);
       if (seg == 0 || seg >= 8) {
-        color.Y = 255;
+        yuv_color.Y = 255;
+        gray_color.G = 65535;
       } else {
 #ifdef SCALE_AMPLITUDE
         double a;
@@ -1000,14 +1419,16 @@
         a = ampl[seg];
         if (a < 0)
           a = 0;
-        color.Y = 128 + a * (sine_array[d & 0xff] - 128);
+        yuv_color.Y = 128 + a * (sine_array[d & 0xff] - 128);
+        gray_color.G = 128 + a * (sine_array[d & 0xff] - 128);
 #else
-        color.Y = sine_array[d & 0xff];
+        yuv_color.Y = sine_array[d & 0xff];
+        gray_color.G = sine_array[d & 0xff];
 #endif
       }
-      color.R = color.Y;
-      color.G = color.Y;
-      color.B = color.Y;
+      rgb_color.R = yuv_color.Y;
+      rgb_color.G = yuv_color.Y;
+      rgb_color.B = yuv_color.Y;
       p->paint_hline (p, i, j, 1);
     }
   }
@@ -1026,6 +1447,30 @@
 }
 
 static void
+paint_setup_NV12 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest;
+  p->ystride = GST_ROUND_UP_4 (p->width);
+  p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
+  p->vp = p->up + 1;
+  p->ustride = p->ystride;
+  p->vstride = p->ystride;
+  p->endptr = p->up + (p->ystride * GST_ROUND_UP_2 (p->height)) / 2;
+}
+
+static void
+paint_setup_NV21 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest;
+  p->ystride = GST_ROUND_UP_4 (p->width);
+  p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height);
+  p->up = p->vp + 1;
+  p->ustride = p->ystride;
+  p->vstride = p->ystride;
+  p->endptr = p->vp + (p->ystride * GST_ROUND_UP_2 (p->height)) / 2;
+}
+
+static void
 paint_hline_I420 (paintinfo * p, int x, int y, int w)
 {
   int x1 = x / 2;
@@ -1033,9 +1478,25 @@
   int offset = y * p->ystride;
   int offset1 = (y / 2) * p->ustride;
 
-  oil_splat_u8_ns (p->yp + offset + x, &p->color->Y, w);
-  oil_splat_u8_ns (p->up + offset1 + x1, &p->color->U, x2 - x1);
-  oil_splat_u8_ns (p->vp + offset1 + x1, &p->color->V, x2 - x1);
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  oil_splat_u8_ns (p->up + offset1 + x1, &p->yuv_color->U, x2 - x1);
+  oil_splat_u8_ns (p->vp + offset1 + x1, &p->yuv_color->V, x2 - x1);
+}
+
+static void
+paint_hline_NV12_NV21 (paintinfo * p, int x, int y, int w)
+{
+  int x1 = x / 2;
+  int x2 = (x + w) / 2;
+  int offset = y * p->ystride;
+  int offsetuv = (y / 2) * p->ustride + (x & ~0x01);
+  int uvlength = x2 - x1 + 1;
+
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  if (uvlength) {
+    oil_splat_u8 (p->up + offsetuv, 2, &p->yuv_color->U, uvlength);
+    oil_splat_u8 (p->vp + offsetuv, 2, &p->yuv_color->V, uvlength);
+  }
 }
 
 static void
@@ -1051,6 +1512,16 @@
 }
 
 static void
+paint_setup_v308 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest;
+  p->up = dest + 1;
+  p->vp = dest + 2;
+  p->ystride = GST_ROUND_UP_4 (p->width * 3);
+  p->endptr = dest + p->ystride * p->height;
+}
+
+static void
 paint_setup_AYUV (paintinfo * p, unsigned char *dest)
 {
   p->ap = dest;
@@ -1062,6 +1533,38 @@
 }
 
 static void
+paint_setup_v410 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest + 0;
+  p->up = dest + 0;
+  p->vp = dest + 0;
+  p->ystride = p->width * 4;
+  p->endptr = dest + p->ystride * p->height;
+}
+
+static void
+paint_setup_v216 (paintinfo * p, unsigned char *dest)
+{
+  p->ap = dest;
+  p->yp = dest + 2;
+  p->up = dest + 0;
+  p->vp = dest + 4;
+  p->ystride = p->width * 4;
+  p->endptr = dest + p->ystride * p->height;
+}
+
+static void
+paint_setup_v210 (paintinfo * p, unsigned char *dest)
+{
+  p->ap = dest;
+  p->yp = dest + 0;
+  p->up = dest + 0;
+  p->vp = dest + 0;
+  p->ystride = ((p->width + 47) / 48) * 128;    /* no, really. */
+  p->endptr = dest + p->ystride * p->height;
+}
+
+static void
 paint_setup_YUY2 (paintinfo * p, unsigned char *dest)
 {
   p->yp = dest;
@@ -1092,15 +1595,96 @@
 }
 
 static void
-paint_hline_AYUV (paintinfo * p, int x, int y, int w)
+paint_hline_v308 (paintinfo * p, int x, int y, int w)
 {
   int offset;
 
+  offset = (y * p->ystride) + (x * 3);
+  oil_splat_u8 (p->yp + offset, 3, &p->yuv_color->Y, w);
+  oil_splat_u8 (p->up + offset, 3, &p->yuv_color->U, w);
+  oil_splat_u8 (p->vp + offset, 3, &p->yuv_color->V, w);
+}
+
+static void
+paint_hline_AYUV (paintinfo * p, int x, int y, int w)
+{
+  int offset;
+  guint8 alpha = 255;
+
   offset = (y * p->ystride) + (x * 4);
-  oil_splat_u8 (p->yp + offset, 4, &p->color->Y, w);
-  oil_splat_u8 (p->up + offset, 4, &p->color->U, w);
-  oil_splat_u8 (p->vp + offset, 4, &p->color->V, w);
-  oil_splat_u8 (p->ap + offset, 4, &p->color->A, w);
+  oil_splat_u8 (p->yp + offset, 4, &p->yuv_color->Y, w);
+  oil_splat_u8 (p->up + offset, 4, &p->yuv_color->U, w);
+  oil_splat_u8 (p->vp + offset, 4, &p->yuv_color->V, w);
+  oil_splat_u8 (p->ap + offset, 4, &alpha, w);
+}
+
+#define TO_16(x) (((x)<<8) | (x))
+#define TO_10(x) (((x)<<2) | ((x)>>6))
+
+static void
+paint_hline_v216 (paintinfo * p, int x, int y, int w)
+{
+  int x1 = x / 2;
+  int x2 = (x + w) / 2;
+  uint16_t Y, U, V;
+  int i;
+  int offset;
+
+  offset = y * p->ystride;
+  Y = TO_16 (p->yuv_color->Y);
+  U = TO_16 (p->yuv_color->U);
+  V = TO_16 (p->yuv_color->V);
+  for (i = x; i < x + w; i++) {
+    GST_WRITE_UINT16_LE (p->yp + offset + i * 4, Y);
+  }
+  for (i = x1; i < x2; i++) {
+    GST_WRITE_UINT16_LE (p->up + offset + i * 8, U);
+    GST_WRITE_UINT16_LE (p->vp + offset + i * 8, V);
+  }
+}
+
+static void
+paint_hline_v410 (paintinfo * p, int x, int y, int w)
+{
+  uint32_t a;
+  uint8_t *data;
+  int i;
+
+  a = (TO_10 (p->yuv_color->U) << 22) |
+      (TO_10 (p->yuv_color->Y) << 12) | (TO_10 (p->yuv_color->V) << 2);
+
+  data = p->yp + y * p->ystride + x * 4;
+  for (i = 0; i < w; i++) {
+    GST_WRITE_UINT32_LE (data, a);
+  }
+}
+
+static void
+paint_hline_v210 (paintinfo * p, int x, int y, int w)
+{
+  uint32_t a0, a1, a2, a3;
+  uint8_t *data;
+  int i;
+
+  /* FIXME this is kinda gross.  it only handles x values in
+     multiples of 6 */
+
+  a0 = TO_10 (p->yuv_color->U) | (TO_10 (p->yuv_color->Y) << 10)
+      | (TO_10 (p->yuv_color->V) << 20);
+  a1 = TO_10 (p->yuv_color->Y) | (TO_10 (p->yuv_color->U) << 10)
+      | (TO_10 (p->yuv_color->Y) << 20);
+  a2 = TO_10 (p->yuv_color->V) | (TO_10 (p->yuv_color->Y) << 10)
+      | (TO_10 (p->yuv_color->U) << 20);
+  a3 = TO_10 (p->yuv_color->Y) | (TO_10 (p->yuv_color->V) << 10)
+      | (TO_10 (p->yuv_color->Y) << 20);
+
+  data = p->yp + y * p->ystride;
+  for (i = x / 6; i < (x + w) / 6; i++) {
+    GST_WRITE_UINT32_LE (data + i * 16 + 0, a0);
+    GST_WRITE_UINT32_LE (data + i * 16 + 4, a1);
+    GST_WRITE_UINT32_LE (data + i * 16 + 8, a2);
+    GST_WRITE_UINT32_LE (data + i * 16 + 12, a3);
+  }
 }
 
 static void
@@ -1111,9 +1695,9 @@
   int offset;
 
   offset = y * p->ystride;
-  oil_splat_u8 (p->yp + offset + x * 2, 2, &p->color->Y, w);
-  oil_splat_u8 (p->up + offset + x1 * 4, 4, &p->color->U, x2 - x1);
-  oil_splat_u8 (p->vp + offset + x1 * 4, 4, &p->color->V, x2 - x1);
+  oil_splat_u8 (p->yp + offset + x * 2, 2, &p->yuv_color->Y, w);
+  oil_splat_u8 (p->up + offset + x1 * 4, 4, &p->yuv_color->U, x2 - x1);
+  oil_splat_u8 (p->vp + offset + x1 * 4, 4, &p->yuv_color->V, x2 - x1);
 }
 
 static void
@@ -1133,9 +1717,9 @@
   int offset;
 
   offset = y * p->ystride;
-  oil_splat_u8 (p->yp + offset + x * 3, 3, &p->color->Y, w);
-  oil_splat_u8 (p->up + offset + x * 3, 3, &p->color->U, w);
-  oil_splat_u8 (p->vp + offset + x * 3, 3, &p->color->V, w);
+  oil_splat_u8 (p->yp + offset + x * 3, 3, &p->yuv_color->Y, w);
+  oil_splat_u8 (p->up + offset + x * 3, 3, &p->yuv_color->U, w);
+  oil_splat_u8 (p->vp + offset + x * 3, 3, &p->yuv_color->V, w);
 }
 
 static void
@@ -1158,9 +1742,9 @@
   int offset = y * p->ystride;
   int offset1 = y * p->ustride;
 
-  oil_splat_u8_ns (p->yp + offset + x, &p->color->Y, w);
-  oil_splat_u8_ns (p->up + offset1 + x1, &p->color->U, x2 - x1);
-  oil_splat_u8_ns (p->vp + offset1 + x1, &p->color->V, x2 - x1);
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  oil_splat_u8_ns (p->up + offset1 + x1, &p->yuv_color->U, x2 - x1);
+  oil_splat_u8_ns (p->vp + offset1 + x1, &p->yuv_color->V, x2 - x1);
 }
 
 static void
@@ -1183,9 +1767,29 @@
   int offset = y * p->ystride;
   int offset1 = y * p->ustride;
 
-  oil_splat_u8_ns (p->yp + offset + x, &p->color->Y, w);
-  oil_splat_u8_ns (p->up + offset1 + x1, &p->color->U, x2 - x1);
-  oil_splat_u8_ns (p->vp + offset1 + x1, &p->color->V, x2 - x1);
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  oil_splat_u8_ns (p->up + offset1 + x1, &p->yuv_color->U, x2 - x1);
+  oil_splat_u8_ns (p->vp + offset1 + x1, &p->yuv_color->V, x2 - x1);
+}
+
+static void
+paint_setup_Y444 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest;
+  p->ystride = GST_ROUND_UP_4 (p->width);
+  p->up = p->yp + p->ystride * p->height;
+  p->vp = p->up + p->ystride * p->height;
+  p->endptr = p->vp + p->ystride * p->height;
+}
+
+static void
+paint_hline_Y444 (paintinfo * p, int x, int y, int w)
+{
+  int offset = y * p->ystride;
+
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  oil_splat_u8_ns (p->up + offset + x, &p->yuv_color->U, w);
+  oil_splat_u8_ns (p->vp + offset + x, &p->yuv_color->V, w);
 }
 
 static void
@@ -1202,7 +1806,7 @@
 {
   int offset = y * p->ystride;
 
-  oil_splat_u8_ns (p->yp + offset + x, &p->color->Y, w);
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
 }
 
 #if 0
@@ -1246,9 +1850,9 @@
   int offset = y * p->width;
   int offset1 = (y / 2) * p->width;
 
-  oil_splat_u8_ns (p->yp + offset + x, &p->color->Y, w);
-  oil_splat_u8_ns (p->up + offset1 + x1, &p->color->U, x2 - x1);
-  oil_splat_u8_ns (p->vp + offset1 + x1, &p->color->V, x2 - x1);
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  oil_splat_u8_ns (p->up + offset1 + x1, &p->yuv_color->U, x2 - x1);
+  oil_splat_u8_ns (p->vp + offset1 + x1, &p->yuv_color->V, x2 - x1);
 }
 #endif
 
@@ -1289,9 +1893,9 @@
   int offset = y * p->ystride;
   int offset1 = (y / 4) * p->ustride;
 
-  oil_splat_u8_ns (p->yp + offset + x, &p->color->Y, w);
-  oil_splat_u8_ns (p->up + offset1 + x1, &p->color->U, x2 - x1);
-  oil_splat_u8_ns (p->vp + offset1 + x1, &p->color->V, x2 - x1);
+  oil_splat_u8_ns (p->yp + offset + x, &p->yuv_color->Y, w);
+  oil_splat_u8_ns (p->up + offset1 + x1, &p->yuv_color->U, x2 - x1);
+  oil_splat_u8_ns (p->vp + offset1 + x1, &p->yuv_color->V, x2 - x1);
 }
 
 static void
@@ -1386,13 +1990,14 @@
 paint_hline_str4 (paintinfo * p, int x, int y, int w)
 {
   int offset = y * p->ystride;
+  guint8 alpha = 255;
 
-  oil_splat_u8 (p->yp + offset + x * 4, 4, &p->color->R, w);
-  oil_splat_u8 (p->up + offset + x * 4, 4, &p->color->G, w);
-  oil_splat_u8 (p->vp + offset + x * 4, 4, &p->color->B, w);
+  oil_splat_u8 (p->yp + offset + x * 4, 4, &p->rgb_color->R, w);
+  oil_splat_u8 (p->up + offset + x * 4, 4, &p->rgb_color->G, w);
+  oil_splat_u8 (p->vp + offset + x * 4, 4, &p->rgb_color->B, w);
 
   if (p->ap != NULL) {
-    oil_splat_u8 (p->ap + offset + (x * 4), 4, &p->color->A, w);
+    oil_splat_u8 (p->ap + offset + (x * 4), 4, &alpha, w);
   }
 }
 
@@ -1401,9 +2006,9 @@
 {
   int offset = y * p->ystride;
 
-  oil_splat_u8 (p->yp + offset + x * 3, 3, &p->color->R, w);
-  oil_splat_u8 (p->up + offset + x * 3, 3, &p->color->G, w);
-  oil_splat_u8 (p->vp + offset + x * 3, 3, &p->color->B, w);
+  oil_splat_u8 (p->yp + offset + x * 3, 3, &p->rgb_color->R, w);
+  oil_splat_u8 (p->up + offset + x * 3, 3, &p->rgb_color->G, w);
+  oil_splat_u8 (p->vp + offset + x * 3, 3, &p->rgb_color->B, w);
 }
 
 static void
@@ -1420,8 +2025,8 @@
   int offset = y * p->ystride;
   uint8_t a, b;
 
-  a = (p->color->R & 0xf8) | (p->color->G >> 5);
-  b = ((p->color->G << 3) & 0xe0) | (p->color->B >> 3);
+  a = (p->rgb_color->R & 0xf8) | (p->rgb_color->G >> 5);
+  b = ((p->rgb_color->G << 3) & 0xe0) | (p->rgb_color->B >> 3);
 
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
   oil_splat_u8 (p->yp + offset + x * 2 + 0, 2, &b, w);
@@ -1446,8 +2051,8 @@
   int offset = y * p->ystride;
   uint8_t a, b;
 
-  a = ((p->color->R >> 1) & 0x7c) | (p->color->G >> 6);
-  b = ((p->color->G << 2) & 0xe0) | (p->color->B >> 3);
+  a = ((p->rgb_color->R >> 1) & 0x7c) | (p->rgb_color->G >> 6);
+  b = ((p->rgb_color->G << 2) & 0xe0) | (p->rgb_color->B >> 3);
 
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
   oil_splat_u8 (p->yp + offset + x * 2 + 0, 2, &b, w);
@@ -1477,18 +2082,51 @@
   if (y & 1) {
     for (i = x; i < x + w; i++) {
       if (i & 1) {
-        dest[i] = p->color->G;
+        dest[i] = p->rgb_color->G;
       } else {
-        dest[i] = p->color->B;
+        dest[i] = p->rgb_color->B;
       }
     }
   } else {
     for (i = x; i < x + w; i++) {
       if (i & 1) {
-        dest[i] = p->color->R;
+        dest[i] = p->rgb_color->R;
       } else {
-        dest[i] = p->color->G;
+        dest[i] = p->rgb_color->G;
       }
     }
   }
 }
+
+static void
+paint_setup_GRAY8 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest;
+  p->ystride = GST_ROUND_UP_4 (p->width);
+  p->endptr = dest + p->ystride * p->height;
+}
+
+static void
+paint_hline_GRAY8 (paintinfo * p, int x, int y, int w)
+{
+  int offset = y * p->ystride;
+  guint8 color = p->gray_color->G >> 8;
+
+  oil_splat_u8_ns (p->yp + offset + x, &color, w);
+}
+
+static void
+paint_setup_GRAY16 (paintinfo * p, unsigned char *dest)
+{
+  p->yp = dest;
+  p->ystride = GST_ROUND_UP_4 (p->width * 2);
+  p->endptr = dest + p->ystride * p->height;
+}
+
+static void
+paint_hline_GRAY16 (paintinfo * p, int x, int y, int w)
+{
+  int offset = y * p->ystride;
+
+  oil_splat_u16_ns ((guint16 *) (p->yp + offset + 2 * x), &p->gray_color->G, w);
+}
--- a/gst_plugins_base/gst/videotestsrc/videotestsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/videotestsrc/videotestsrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -25,13 +25,18 @@
 enum {
   VTS_YUV,
   VTS_RGB,
+  VTS_GRAY,
   VTS_BAYER
 };
 
-struct vts_color_struct {
-        guint8 Y, U, V;
-        guint8 R, G, B;
-	guint8 A;
+struct vts_color_struct_yuv {
+  guint8 Y, U, V;
+};
+struct vts_color_struct_rgb {
+  guint8 R, G, B;
+};
+struct vts_color_struct_gray {
+  guint16 G;
 };
 
 typedef struct paintinfo_struct paintinfo;
@@ -47,7 +52,13 @@
   int vstride;
   int width;
   int height;
-  const struct vts_color_struct *color;
+  const struct vts_color_struct_rgb *rgb_colors;
+  const struct vts_color_struct_yuv *yuv_colors;
+  const struct vts_color_struct_gray *gray_colors;
+  const struct vts_color_struct_rgb *rgb_color;
+  const struct vts_color_struct_yuv *yuv_color;
+  const struct vts_color_struct_gray *gray_color;
+  //const struct vts_color_struct *color;
   void (*paint_hline) (paintinfo * p, int x, int y, int w);
 };
 
@@ -77,6 +88,8 @@
 int     gst_video_test_src_get_size     (GstVideoTestSrc * v, int w, int h);
 void    gst_video_test_src_smpte        (GstVideoTestSrc * v,
                                          unsigned char *dest, int w, int h);
+void    gst_video_test_src_smpte75      (GstVideoTestSrc * v,
+                                         unsigned char *dest, int w, int h);
 void    gst_video_test_src_snow         (GstVideoTestSrc * v,
                                          unsigned char *dest, int w, int h);
 void    gst_video_test_src_black        (GstVideoTestSrc * v,
@@ -99,7 +112,8 @@
                                          unsigned char *dest, int w, int h);
 void    gst_video_test_src_circular     (GstVideoTestSrc * v,
                                          unsigned char *dest, int w, int h);
-
+void    gst_video_test_src_zoneplate    (GstVideoTestSrc * v,
+		                         unsigned char *dest, int w, int h);
 extern struct fourcc_list_struct fourcc_list[];
 extern int n_fourccs;
 
--- a/gst_plugins_base/gst/volume/gstvolume.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/volume/gstvolume.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,19 +24,15 @@
 /**
  * SECTION:element-volume
  *
+ * The volume element changes the volume of the audio data.
+ *
  * <refsect2>
- * <para>
- * The volume element changes the volume of the audio data.
- * </para>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v -m audiotestsrc ! volume volume=0.5 ! level ! fakesink silent=TRUE
- * </programlisting>
- * This pipeline shows that the level of audiotestsrc has been halved
+ * ]| This pipeline shows that the level of audiotestsrc has been halved
  * (peak values are around -6 dB and RMS around -9 dB) compared to
  * the same pipeline without the volume element.
- * </para>
  * </refsect2>
  */
 
@@ -52,9 +48,10 @@
 #include <gst/controller/gstcontroller.h>
 #include <gst/audio/audio.h>
 #include <gst/audio/gstaudiofilter.h>
-
-#include <gst/liboil.h>
-
+#include <liboil/liboil.h>
+#ifdef __SYMBIAN32__
+#include <liboil/globals.h>
+#endif
 #include "gstvolume.h"
 
 /* some defines for audio processing */
@@ -85,11 +82,6 @@
 #define GST_CAT_DEFAULT gst_volume_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
-static const GstElementDetails volume_details = GST_ELEMENT_DETAILS ("Volume",
-    "Filter/Effect/Audio",
-    "Set volume on audio/raw streams",
-    "Andy Wingo <wingo@pobox.com>");
-
 /* Filter signals and args */
 enum
 {
@@ -97,10 +89,12 @@
   LAST_SIGNAL
 };
 
+#define DEFAULT_PROP_MUTE       FALSE
+#define DEFAULT_PROP_VOLUME     1.0
+
 enum
 {
   PROP_0,
-  PROP_SILENT,
   PROP_MUTE,
   PROP_VOLUME
 };
@@ -168,9 +162,9 @@
     const GValue * value, GParamSpec * pspec);
 static void volume_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static void volume_update_volume (const GValue * value, gpointer data);
-static void volume_update_mute (const GValue * value, gpointer data);
 
+static void volume_before_transform (GstBaseTransform * base,
+    GstBuffer * buffer);
 static GstFlowReturn volume_transform_ip (GstBaseTransform * base,
     GstBuffer * outbuf);
 static gboolean volume_setup (GstAudioFilter * filter,
@@ -213,36 +207,36 @@
       switch (GST_AUDIO_FILTER (this)->format.width) {
         case 32:
           /* only clamp if the gain is greater than 1.0
-           * FIXME: real_vol_i can change while processing the buffer!
+           * FIXME: current_vol_i can change while processing the buffer!
            */
-          if (this->real_vol_i32 > VOLUME_UNITY_INT32)
+          if (this->current_vol_i32 > VOLUME_UNITY_INT32)
             this->process = volume_process_int32_clamp;
           else
             this->process = volume_process_int32;
           break;
         case 24:
           /* only clamp if the gain is greater than 1.0
-           * FIXME: real_vol_i can change while processing the buffer!
+           * FIXME: current_vol_i can change while processing the buffer!
            */
-          if (this->real_vol_i24 > VOLUME_UNITY_INT24)
+          if (this->current_vol_i24 > VOLUME_UNITY_INT24)
             this->process = volume_process_int24_clamp;
           else
             this->process = volume_process_int24;
           break;
         case 16:
           /* only clamp if the gain is greater than 1.0
-           * FIXME: real_vol_i can change while processing the buffer!
+           * FIXME: current_vol_i can change while processing the buffer!
            */
-          if (this->real_vol_i16 > VOLUME_UNITY_INT16)
+          if (this->current_vol_i16 > VOLUME_UNITY_INT16)
             this->process = volume_process_int16_clamp;
           else
             this->process = volume_process_int16;
           break;
         case 8:
           /* only clamp if the gain is greater than 1.0
-           * FIXME: real_vol_i can change while processing the buffer!
+           * FIXME: current_vol_i can change while processing the buffer!
            */
-          if (this->real_vol_i16 > VOLUME_UNITY_INT8)
+          if (this->current_vol_i16 > VOLUME_UNITY_INT8)
             this->process = volume_process_int8_clamp;
           else
             this->process = volume_process_int8;
@@ -266,27 +260,43 @@
   return (this->process != NULL);
 }
 
-static void
-volume_update_real_volume (GstVolume * this)
+static gboolean
+volume_update_volume (GstVolume * this, gfloat volume, gboolean mute)
 {
-  gboolean passthrough = FALSE;
+  gboolean passthrough;
+  gboolean res;
+
+  GST_DEBUG_OBJECT (this, "configure mute %d, volume %f", mute, volume);
 
-  if (this->mute) {
-    this->real_vol_f = 0.0;
-    this->real_vol_i8 = this->real_vol_i16 = this->real_vol_i24 =
-        this->real_vol_i32 = 0;
+  if (mute) {
+    this->current_mute = TRUE;
+    this->current_volume = 0.0;
+
+    this->current_vol_i8 = 0;
+    this->current_vol_i16 = 0;
+    this->current_vol_i24 = 0;
+    this->current_vol_i32 = 0;
+
+    passthrough = FALSE;
   } else {
-    this->real_vol_f = this->volume_f;
-    this->real_vol_i8 = this->volume_i8;
-    this->real_vol_i16 = this->volume_i16;
-    this->real_vol_i24 = this->volume_i24;
-    this->real_vol_i32 = this->volume_i32;
-    passthrough = (this->volume_i16 == VOLUME_UNITY_INT16);
+    this->current_mute = FALSE;
+    this->current_volume = volume;
+
+    this->current_vol_i8 = volume * VOLUME_UNITY_INT8;
+    this->current_vol_i16 = volume * VOLUME_UNITY_INT16;
+    this->current_vol_i24 = volume * VOLUME_UNITY_INT24;
+    this->current_vol_i32 = volume * VOLUME_UNITY_INT32;
+
+    passthrough = (this->current_vol_i16 == VOLUME_UNITY_INT16);
   }
-  if (this->real_vol_f != 0.0)
-    this->silent_buffer = FALSE;
-  volume_choose_func (this);
+
+  GST_DEBUG_OBJECT (this, "set passthrough %d", passthrough);
+
   gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (this), passthrough);
+
+  res = this->negotiated = volume_choose_func (this);
+
+  return res;
 }
 
 /* Mixer interface */
@@ -294,7 +304,7 @@
 static gboolean
 gst_volume_interface_supported (GstImplementsInterface * iface, GType type)
 {
-  g_assert (type == GST_TYPE_MIXER);
+  g_return_val_if_fail (type == GST_TYPE_MIXER, FALSE);
   return TRUE;
 }
 
@@ -323,13 +333,9 @@
   g_return_if_fail (this != NULL);
   g_return_if_fail (GST_IS_VOLUME (this));
 
-  this->volume_f = (gfloat) volumes[0] / VOLUME_STEPS;
-  this->volume_i32 = this->volume_f * VOLUME_UNITY_INT32;
-  this->volume_i24 = this->volume_f * VOLUME_UNITY_INT24;
-  this->volume_i16 = this->volume_f * VOLUME_UNITY_INT16;
-  this->volume_i8 = this->volume_f * VOLUME_UNITY_INT8;
-
-  volume_update_real_volume (this);
+  GST_OBJECT_LOCK (this);
+  this->volume = (gfloat) volumes[0] / VOLUME_STEPS;
+  GST_OBJECT_UNLOCK (this);
 }
 
 static void
@@ -340,7 +346,9 @@
   g_return_if_fail (this != NULL);
   g_return_if_fail (GST_IS_VOLUME (this));
 
-  volumes[0] = (gint) this->volume_f * VOLUME_STEPS;
+  GST_OBJECT_LOCK (this);
+  volumes[0] = (gint) this->volume * VOLUME_STEPS;
+  GST_OBJECT_UNLOCK (this);
 }
 
 static void
@@ -351,9 +359,9 @@
   g_return_if_fail (this != NULL);
   g_return_if_fail (GST_IS_VOLUME (this));
 
+  GST_OBJECT_LOCK (this);
   this->mute = mute;
-
-  volume_update_real_volume (this);
+  GST_OBJECT_UNLOCK (this);
 }
 
 static void
@@ -392,7 +400,9 @@
   GstAudioFilterClass *filter_class = GST_AUDIO_FILTER_CLASS (g_class);
   GstCaps *caps;
 
-  gst_element_class_set_details (element_class, &volume_details);
+  gst_element_class_set_details_simple (element_class, "Volume",
+      "Filter/Effect/Audio",
+      "Set volume on audio/raw streams", "Andy Wingo <wingo@pobox.com>");
 
   caps = gst_caps_from_string (ALLOWED_CAPS);
   gst_audio_filter_class_add_pad_templates (filter_class, caps);
@@ -416,15 +426,15 @@
 
   g_object_class_install_property (gobject_class, PROP_MUTE,
       g_param_spec_boolean ("mute", "Mute", "mute channel",
-          FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+          DEFAULT_PROP_MUTE,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_VOLUME,
-      g_param_spec_double ("volume", "Volume", "volume factor",
-          0.0, VOLUME_MAX_DOUBLE, 1.0,
-          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+      g_param_spec_double ("volume", "Volume", "volume factor, 1.0=100%",
+          0.0, VOLUME_MAX_DOUBLE, DEFAULT_PROP_VOLUME,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
-  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "volume", 0, "Volume gain");
-
+  trans_class->before_transform = GST_DEBUG_FUNCPTR (volume_before_transform);
   trans_class->transform_ip = GST_DEBUG_FUNCPTR (volume_transform_ip);
   filter_class->setup = GST_DEBUG_FUNCPTR (volume_setup);
 }
@@ -434,13 +444,11 @@
 {
   GstMixerTrack *track = NULL;
 
-  this->mute = FALSE;
-  this->volume_i8 = this->real_vol_i8 = VOLUME_UNITY_INT8;
-  this->volume_i16 = this->real_vol_i16 = VOLUME_UNITY_INT16;
-  this->volume_i24 = this->real_vol_i24 = VOLUME_UNITY_INT24;
-  this->volume_i32 = this->real_vol_i32 = VOLUME_UNITY_INT32;
-  this->volume_f = this->real_vol_f = 1.0;
+  this->mute = DEFAULT_PROP_MUTE;;
+  this->volume = DEFAULT_PROP_VOLUME;
+
   this->tracklist = NULL;
+  this->negotiated = FALSE;
 
   track = g_object_new (GST_TYPE_MIXER_TRACK, NULL);
 
@@ -456,20 +464,15 @@
   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (this), TRUE);
 }
 
-/* NOTE: although it might be tempting to have volume_process_mute() which uses
- *       memset(bytes, 0, nbytes) for the vol=0 case, this has the downside that
- *       unmuting would only take place after processing a buffer.
- */
-
 static void
 volume_process_double (GstVolume * this, gpointer bytes, guint n_bytes)
 {
   gdouble *data = (gdouble *) bytes;
-  guint i, num_samples = n_bytes / sizeof (gdouble);
+  guint num_samples = n_bytes / sizeof (gdouble);
 
-  for (i = 0; i < num_samples; i++) {
-    *data++ *= this->real_vol_f;
-  }
+  gdouble vol = this->current_volume;
+
+  oil_scalarmultiply_f64_ns (data, data, &vol, num_samples);
 }
 
 static void
@@ -478,16 +481,17 @@
   gfloat *data = (gfloat *) bytes;
   guint num_samples = n_bytes / sizeof (gfloat);
 
-  /*
-     guint i;
-     for (i = 0; i < num_samples; i++) {
-     *data++ *= this->real_vol_f;
-     }
+#if 0
+  guint i;
+
+  for (i = 0; i < num_samples; i++) {
+    *data++ *= this->real_vol_f;
+  }
+  /* time "gst-launch 2>/dev/null audiotestsrc wave=7 num-buffers=10000 ! audio/x-raw-float !
+   * volume volume=1.5 ! fakesink" goes from 0m0.850s -> 0m0.717s with liboil
    */
-  /* time gst-launch 2>/dev/null audiotestsrc wave=7 num-buffers=10000 ! audio/x-raw-float ! volume volume=1.5 ! fakesink
-   * goes from 0m0.850s -> 0m0.717s with liboil
-   */
-  oil_scalarmultiply_f32_ns (data, data, &this->real_vol_f, num_samples);
+#endif
+  oil_scalarmultiply_f32_ns (data, data, &this->current_volume, num_samples);
 }
 
 static void
@@ -501,7 +505,9 @@
   for (i = 0; i < num_samples; i++) {
     /* we use bitshifting instead of dividing by UNITY_INT for speed */
     val = (gint64) * data;
-    val = (((gint64) this->real_vol_i32 * val) >> VOLUME_UNITY_INT32_BIT_SHIFT);
+    val =
+        (((gint64) this->current_vol_i32 *
+            val) >> VOLUME_UNITY_INT32_BIT_SHIFT);
     *data++ = (gint32) val;
   }
 }
@@ -518,17 +524,31 @@
   for (i = 0; i < num_samples; i++) {
     /* we use bitshifting instead of dividing by UNITY_INT for speed */
     val = (gint64) * data;
-    val = (((gint64) this->real_vol_i32 * val) >> VOLUME_UNITY_INT32_BIT_SHIFT);
+    val =
+        (((gint64) this->current_vol_i32 *
+            val) >> VOLUME_UNITY_INT32_BIT_SHIFT);
     *data++ = (gint32) CLAMP (val, VOLUME_MIN_INT32, VOLUME_MAX_INT32);
   }
 }
 
 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
 #define get_unaligned_i24(_x) ( (((guint8*)_x)[0]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[2]) << 16) )
-#define write_unaligned_u24(_x,samp) do { *(_x)++ = samp & 0xFF; *(_x)++ = (samp >> 8) & 0xFF; *(_x)++ = (samp >> 16) & 0xFF; } while (0)
+
+#define write_unaligned_u24(_x,samp) \
+G_STMT_START { \
+  *(_x)++ = samp & 0xFF; \
+  *(_x)++ = (samp >> 8) & 0xFF; \
+  *(_x)++ = (samp >> 16) & 0xFF; \
+} G_STMT_END
+
 #else /* BIG ENDIAN */
 #define get_unaligned_i24(_x) ( (((guint8*)_x)[2]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[0]) << 16) )
-#define write_unaligned_u24(_x,samp) do { *(_x)++ = (samp >> 16) & 0xFF; *(_x)++ = (samp >> 8) & 0xFF; *(_x)++ = samp & 0xFF; } while (0)
+#define write_unaligned_u24(_x,samp) \
+G_STMT_START { \
+  *(_x)++ = (samp >> 16) & 0xFF; \
+  *(_x)++ = (samp >> 8) & 0xFF; \
+  *(_x)++ = samp & 0xFF; \
+} G_STMT_END
 #endif
 
 static void
@@ -544,7 +564,9 @@
     samp = get_unaligned_i24 (data);
 
     val = (gint32) samp;
-    val = (((gint64) this->real_vol_i24 * val) >> VOLUME_UNITY_INT24_BIT_SHIFT);
+    val =
+        (((gint64) this->current_vol_i24 *
+            val) >> VOLUME_UNITY_INT24_BIT_SHIFT);
     samp = (guint32) val;
 
     /* write the value back into the stream */
@@ -565,7 +587,9 @@
     samp = get_unaligned_i24 (data);
 
     val = (gint32) samp;
-    val = (((gint64) this->real_vol_i24 * val) >> VOLUME_UNITY_INT24_BIT_SHIFT);
+    val =
+        (((gint64) this->current_vol_i24 *
+            val) >> VOLUME_UNITY_INT24_BIT_SHIFT);
     samp = (guint32) CLAMP (val, VOLUME_MIN_INT24, VOLUME_MAX_INT24);
 
     /* write the value back into the stream */
@@ -587,7 +611,8 @@
     /* we use bitshifting instead of dividing by UNITY_INT for speed */
     val = (gint) * data;
     *data++ =
-        (gint16) ((this->real_vol_i16 * val) >> VOLUME_UNITY_INT16_BIT_SHIFT);
+        (gint16) ((this->current_vol_i16 *
+            val) >> VOLUME_UNITY_INT16_BIT_SHIFT);
   }
 #else
   /* FIXME: need oil_scalarmultiply_s16_ns ?
@@ -598,7 +623,7 @@
    * time gst-launch 2>/dev/null audiotestsrc wave=7 num-buffers=100 ! volume volume=1.5 ! fakesink
    */
   oil_scalarmult_s16 (data, 0, data, 0,
-      ((gint16 *) (void *) (&this->real_vol_i)), num_samples);
+      ((gint16 *) (void *) (&this->current_vol_i)), num_samples);
 #endif
 }
 
@@ -618,7 +643,7 @@
     /* we use bitshifting instead of dividing by UNITY_INT for speed */
     val = (gint) * data;
     *data++ =
-        (gint16) CLAMP ((this->real_vol_i16 *
+        (gint16) CLAMP ((this->current_vol_i16 *
             val) >> VOLUME_UNITY_INT16_BIT_SHIFT, VOLUME_MIN_INT16,
         VOLUME_MAX_INT16);
   }
@@ -636,7 +661,7 @@
     /* we use bitshifting instead of dividing by UNITY_INT for speed */
     val = (gint) * data;
     *data++ =
-        (gint8) ((this->real_vol_i8 * val) >> VOLUME_UNITY_INT8_BIT_SHIFT);
+        (gint8) ((this->current_vol_i8 * val) >> VOLUME_UNITY_INT8_BIT_SHIFT);
   }
 }
 
@@ -653,7 +678,7 @@
     /* we use bitshifting instead of dividing by UNITY_INT for speed */
     val = (gint) * data;
     *data++ =
-        (gint8) CLAMP ((this->real_vol_i8 *
+        (gint8) CLAMP ((this->current_vol_i8 *
             val) >> VOLUME_UNITY_INT8_BIT_SHIFT, VOLUME_MIN_INT8,
         VOLUME_MAX_INT8);
   }
@@ -665,14 +690,57 @@
 static gboolean
 volume_setup (GstAudioFilter * filter, GstRingBufferSpec * format)
 {
+  gboolean res;
   GstVolume *this = GST_VOLUME (filter);
+  gfloat volume;
+  gboolean mute;
 
-  if (volume_choose_func (this)) {
-    return TRUE;
-  } else {
+  GST_OBJECT_LOCK (this);
+  volume = this->volume;
+  mute = this->mute;
+  GST_OBJECT_UNLOCK (this);
+
+  res = volume_update_volume (this, volume, mute);
+  if (!res) {
     GST_ELEMENT_ERROR (this, CORE, NEGOTIATION,
         ("Invalid incoming format"), (NULL));
-    return FALSE;
+  }
+  this->negotiated = res;
+
+  return res;
+}
+
+static void
+volume_before_transform (GstBaseTransform * base, GstBuffer * buffer)
+{
+  GstClockTime timestamp;
+  GstVolume *this = GST_VOLUME (base);
+  gfloat volume;
+  gboolean mute;
+
+  /* FIXME: if controllers are bound, subdivide GST_BUFFER_SIZE into small
+   * chunks for smooth fades, what is small? 1/10th sec.
+   */
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  timestamp =
+      gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
+
+  GST_DEBUG_OBJECT (base, "sync to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (timestamp));
+
+  if (GST_CLOCK_TIME_IS_VALID (timestamp))
+    gst_object_sync_values (G_OBJECT (this), timestamp);
+
+  /* get latest values */
+  GST_OBJECT_LOCK (this);
+  volume = this->volume;
+  mute = this->mute;
+  GST_OBJECT_UNLOCK (this);
+
+  if ((volume != this->current_volume) || (mute != this->current_mute)) {
+    /* the volume or mute was updated, update our internal state before
+     * we continue processing. */
+    volume_update_volume (this, volume, mute);
   }
 }
 
@@ -684,68 +752,36 @@
 volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
 {
   GstVolume *this = GST_VOLUME (base);
-  GstClockTime timestamp;
+  guint8 *data;
+  guint size;
 
-  /* FIXME: if controllers are bound, subdivide GST_BUFFER_SIZE into small
-   * chunks for smooth fades, what is small? 1/10th sec.
-   */
-  timestamp = GST_BUFFER_TIMESTAMP (outbuf);
-  timestamp =
-      gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
-
-  GST_DEBUG_OBJECT (base, "sync to %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (timestamp));
-
-  if (GST_CLOCK_TIME_IS_VALID (timestamp))
-    gst_object_sync_values (G_OBJECT (this), timestamp);
+  if (G_UNLIKELY (!this->negotiated))
+    goto not_negotiated;
 
   /* don't process data in passthrough-mode */
   if (gst_base_transform_is_passthrough (base) ||
       GST_BUFFER_FLAG_IS_SET (outbuf, GST_BUFFER_FLAG_GAP))
     return GST_FLOW_OK;
 
-  if (this->real_vol_f == 0.0)
-    this->silent_buffer = TRUE;
+  data = GST_BUFFER_DATA (outbuf);
+  size = GST_BUFFER_SIZE (outbuf);
 
-  this->process (this, GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
-
-  if (this->silent_buffer)
+  if (this->current_volume == 0.0) {
+    memset (data, 0, size);
     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
-  this->silent_buffer = FALSE;
+  } else if (this->current_volume != 1.0) {
+    this->process (this, data, size);
+  }
 
   return GST_FLOW_OK;
-}
 
-static void
-volume_update_mute (const GValue * value, gpointer data)
-{
-  GstVolume *this = (GstVolume *) data;
-
-  g_return_if_fail (GST_IS_VOLUME (this));
-
-  if (G_VALUE_HOLDS_BOOLEAN (value)) {
-    this->mute = g_value_get_boolean (value);
-  } else if (G_VALUE_HOLDS_INT (value)) {
-    this->mute = (g_value_get_int (value) == 1);
+  /* ERRORS */
+not_negotiated:
+  {
+    GST_ELEMENT_ERROR (this, CORE, NEGOTIATION,
+        ("No format was negotiated"), (NULL));
+    return GST_FLOW_NOT_NEGOTIATED;
   }
-
-  volume_update_real_volume (this);
-}
-
-static void
-volume_update_volume (const GValue * value, gpointer data)
-{
-  GstVolume *this = (GstVolume *) data;
-
-  g_return_if_fail (GST_IS_VOLUME (this));
-
-  this->volume_f = g_value_get_double (value);
-  this->volume_i8 = this->volume_f * VOLUME_UNITY_INT8;
-  this->volume_i16 = this->volume_f * VOLUME_UNITY_INT16;
-  this->volume_i24 = this->volume_f * VOLUME_UNITY_INT24;
-  this->volume_i32 = this->volume_f * VOLUME_UNITY_INT32;
-
-  volume_update_real_volume (this);
 }
 
 static void
@@ -756,10 +792,14 @@
 
   switch (prop_id) {
     case PROP_MUTE:
-      volume_update_mute (value, this);
+      GST_OBJECT_LOCK (this);
+      this->mute = g_value_get_boolean (value);
+      GST_OBJECT_UNLOCK (this);
       break;
     case PROP_VOLUME:
-      volume_update_volume (value, this);
+      GST_OBJECT_LOCK (this);
+      this->volume = g_value_get_double (value);
+      GST_OBJECT_UNLOCK (this);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -775,10 +815,14 @@
 
   switch (prop_id) {
     case PROP_MUTE:
+      GST_OBJECT_LOCK (this);
       g_value_set_boolean (value, this->mute);
+      GST_OBJECT_UNLOCK (this);
       break;
     case PROP_VOLUME:
-      g_value_set_double (value, this->volume_f);
+      GST_OBJECT_LOCK (this);
+      g_value_set_double (value, this->volume);
+      GST_OBJECT_UNLOCK (this);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -789,13 +833,17 @@
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-#ifndef __SYMBIAN32__
   oil_init ();
-#endif  
 
   /* initialize gst controller library */
   gst_controller_init (NULL, NULL);
 
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "volume", 0, "Volume gain");
+
+  /* ref class from a thread-safe context to work around missing bit of
+   * thread-safety in GObject */
+  g_type_class_ref (GST_TYPE_MIXER_TRACK);
+
   return gst_element_register (plugin, "volume", GST_RANK_NONE,
       GST_TYPE_VOLUME);
 }
--- a/gst_plugins_base/gst/volume/gstvolume.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst/volume/gstvolume.h	Fri Apr 16 15:15:52 2010 +0300
@@ -55,19 +55,27 @@
   void (*process)(GstVolume*, gpointer, guint);
 
   gboolean mute;
-  gint   volume_i32, real_vol_i32;
-  gint   volume_i24, real_vol_i24; /* the _i(nt) values get synchronized with the */
-  gint   volume_i16, real_vol_i16; /* the _i(nt) values get synchronized with the */
-  gint   volume_i8, real_vol_i8;   /* the _i(nt) values get synchronized with the */
-  gfloat volume_f, real_vol_f; /* _f(loat) values on each update */
+  gfloat volume;
+
+  gboolean current_mute;
+  gfloat current_volume;
+
+  gint   current_vol_i32;
+  gint   current_vol_i24; /* the _i(nt) values get synchronized with the */
+  gint   current_vol_i16; /* the _i(nt) values get synchronized with the */
+  gint   current_vol_i8;   /* the _i(nt) values get synchronized with the */
   
   GList *tracklist;
-  gboolean silent_buffer;       /* flag for silent buffers */
+  gboolean negotiated;
 };
 
 struct _GstVolumeClass {
   GstAudioFilterClass parent_class;
 };
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GType gst_volume_get_type (void);
 
--- a/gst_plugins_base/sys/v4l/gstv4l.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * gstv4l.c: plugin for v4l elements
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst/gst-i18n-plugin.h"
-
-#include <gst/gst.h>
-
-#include "gstv4lelement.h"
-#include "gstv4lsrc.h"
-/* #include "gstv4ljpegsrc.h" */
-/* #include "gstv4lmjpegsrc.h" */
-/* #include "gstv4lmjpegsink.h" */
-
-GST_DEBUG_CATEGORY (v4l_debug); /* used in v4l_calls.c and v4lsrc_calls.c */
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  GST_DEBUG_CATEGORY_INIT (v4l_debug, "v4l", 0, "V4L API calls");
-
-  if (!gst_element_register (plugin, "v4lsrc", GST_RANK_NONE, GST_TYPE_V4LSRC))
-/*       !gst_element_register (plugin, "v4ljpegsrc", */
-/*           GST_RANK_NONE, GST_TYPE_V4LJPEGSRC) || */
-/*       !gst_element_register (plugin, "v4lmjpegsrc", */
-/*           GST_RANK_NONE, GST_TYPE_V4LMJPEGSRC) || */
-/*       !gst_element_register (plugin, "v4lmjpegsink", */
-/*           GST_RANK_NONE, GST_TYPE_V4LMJPEGSINK)) */
-    return FALSE;
-
-#ifdef ENABLE_NLS
-  setlocale (LC_ALL, "");
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif /* ENABLE_NLS */
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "video4linux",
-    "elements for Video 4 Linux",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/sys/v4l/gstv4lcolorbalance.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/* GStreamer
- *
- * gstv4lcolorbalance.c: color balance interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include "gstv4lcolorbalance.h"
-#include "gstv4lelement.h"
-
-static void
-gst_v4l_color_balance_channel_class_init (GstV4lColorBalanceChannelClass *
-    klass);
-static void gst_v4l_color_balance_channel_init (GstV4lColorBalanceChannel *
-    channel);
-
-static const GList *gst_v4l_color_balance_list_channels (GstColorBalance *
-    balance);
-static void gst_v4l_color_balance_set_value (GstColorBalance * balance,
-    GstColorBalanceChannel * channel, gint value);
-static gint gst_v4l_color_balance_get_value (GstColorBalance * balance,
-    GstColorBalanceChannel * channel);
-
-static GstColorBalanceChannelClass *parent_class = NULL;
-
-GType
-gst_v4l_color_balance_channel_get_type (void)
-{
-  static GType gst_v4l_color_balance_channel_type = 0;
-
-  if (!gst_v4l_color_balance_channel_type) {
-    static const GTypeInfo v4l_tuner_channel_info = {
-      sizeof (GstV4lColorBalanceChannelClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_v4l_color_balance_channel_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4lColorBalanceChannel),
-      0,
-      (GInstanceInitFunc) gst_v4l_color_balance_channel_init,
-      NULL
-    };
-
-    gst_v4l_color_balance_channel_type =
-        g_type_register_static (GST_TYPE_COLOR_BALANCE_CHANNEL,
-        "GstV4lColorBalanceChannel", &v4l_tuner_channel_info, 0);
-  }
-
-  return gst_v4l_color_balance_channel_type;
-}
-
-static void
-gst_v4l_color_balance_channel_class_init (GstV4lColorBalanceChannelClass *
-    klass)
-{
-  parent_class = g_type_class_peek_parent (klass);
-}
-
-static void
-gst_v4l_color_balance_channel_init (GstV4lColorBalanceChannel * channel)
-{
-  channel->index = 0;
-}
-
-void
-gst_v4l_color_balance_interface_init (GstColorBalanceClass * klass)
-{
-  GST_COLOR_BALANCE_TYPE (klass) = GST_COLOR_BALANCE_HARDWARE;
-
-  /* default virtual functions */
-  klass->list_channels = gst_v4l_color_balance_list_channels;
-  klass->set_value = gst_v4l_color_balance_set_value;
-  klass->get_value = gst_v4l_color_balance_get_value;
-}
-
-static G_GNUC_UNUSED gboolean
-gst_v4l_color_balance_contains_channel (GstV4lElement * v4lelement,
-    GstV4lColorBalanceChannel * v4lchannel)
-{
-  const GList *item;
-
-  for (item = v4lelement->colors; item != NULL; item = item->next)
-    if (item->data == v4lchannel)
-      return TRUE;
-
-  return FALSE;
-}
-
-static const GList *
-gst_v4l_color_balance_list_channels (GstColorBalance * balance)
-{
-  return GST_V4LELEMENT (balance)->colors;
-}
-
-static void
-gst_v4l_color_balance_set_value (GstColorBalance * balance,
-    GstColorBalanceChannel * channel, gint value)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (balance);
-  GstV4lColorBalanceChannel *v4lchannel =
-      GST_V4L_COLOR_BALANCE_CHANNEL (channel);
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
-  g_return_if_fail (gst_v4l_color_balance_contains_channel (v4lelement,
-          v4lchannel));
-
-  gst_v4l_set_picture (v4lelement, v4lchannel->index, value);
-}
-
-static gint
-gst_v4l_color_balance_get_value (GstColorBalance * balance,
-    GstColorBalanceChannel * channel)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (balance);
-  GstV4lColorBalanceChannel *v4lchannel =
-      GST_V4L_COLOR_BALANCE_CHANNEL (channel);
-  gint value;
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
-  g_return_val_if_fail (gst_v4l_color_balance_contains_channel (v4lelement,
-          v4lchannel), 0);
-
-  if (!gst_v4l_get_picture (v4lelement, v4lchannel->index, &value))
-    return 0;
-
-  return value;
-}
--- a/gst_plugins_base/sys/v4l/gstv4lcolorbalance.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* GStreamer
- *
- * gstv4lcolorbalance.h: color balance interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4L_COLOR_BALANCE_H__
-#define __GST_V4L_COLOR_BALANCE_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/colorbalance.h>
-#include "v4l_calls.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4L_COLOR_BALANCE_CHANNEL \
-  (gst_v4l_color_balance_channel_get_type ())
-#define GST_V4L_COLOR_BALANCE_CHANNEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, \
-                               GstV4lColorBalanceChannel))
-#define GST_V4L_COLOR_BALANCE_CHANNEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, \
-                            GstV4lColorBalanceChannelClass))
-#define GST_IS_V4L_COLOR_BALANCE_CHANNEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL))
-#define GST_IS_V4L_COLOR_BALANCE_CHANNEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL))
-
-typedef struct _GstV4lColorBalanceChannel {
-  GstColorBalanceChannel parent;
-
-  GstV4lPictureType index;
-} GstV4lColorBalanceChannel;
-
-typedef struct _GstV4lColorBalanceChannelClass {
-  GstColorBalanceChannelClass parent;
-} GstV4lColorBalanceChannelClass;
-
-GType   gst_v4l_color_balance_channel_get_type  (void);
-
-void    gst_v4l_color_balance_interface_init    (GstColorBalanceClass *klass);
-
-#endif /* __GST_V4L_COLOR_BALANCE_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lelement.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,470 +0,0 @@
-/* GStreamer
- *
- * gstv4lelement.c: base class for V4L elements
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <gst/interfaces/propertyprobe.h>
-
-#include "v4l_calls.h"
-#include "gstv4ltuner.h"
-#ifdef HAVE_XVIDEO
-#include "gstv4lxoverlay.h"
-#endif
-#include "gstv4lcolorbalance.h"
-
-
-enum
-{
-  PROP_0,
-  PROP_DEVICE,
-  PROP_DEVICE_NAME,
-  PROP_FLAGS
-};
-
-
-static void gst_v4lelement_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstV4lElement, gst_v4lelement, GstPushSrc,
-    GST_TYPE_PUSH_SRC, gst_v4lelement_init_interfaces);
-
-
-static void gst_v4lelement_dispose (GObject * object);
-static void gst_v4lelement_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4lelement_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-static gboolean gst_v4lelement_start (GstBaseSrc * src);
-static gboolean gst_v4lelement_stop (GstBaseSrc * src);
-
-
-static gboolean
-gst_v4l_iface_supported (GstImplementsInterface * iface, GType iface_type)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (iface);
-
-#ifdef HAVE_XVIDEO
-  g_assert (iface_type == GST_TYPE_TUNER ||
-      iface_type == GST_TYPE_X_OVERLAY || iface_type == GST_TYPE_COLOR_BALANCE);
-#else
-  g_assert (iface_type == GST_TYPE_TUNER ||
-      iface_type == GST_TYPE_COLOR_BALANCE);
-#endif
-
-  if (v4lelement->video_fd == -1)
-    return FALSE;
-
-#ifdef HAVE_XVIDEO
-  if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L_IS_OVERLAY (v4lelement))
-    return FALSE;
-#endif
-
-  return TRUE;
-}
-
-static void
-gst_v4l_interface_init (GstImplementsInterfaceClass * klass)
-{
-  /* default virtual functions */
-  klass->supported = gst_v4l_iface_supported;
-}
-
-static const GList *
-gst_v4l_probe_get_properties (GstPropertyProbe * probe)
-{
-  GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
-  static GList *list = NULL;
-
-  if (!list) {
-    list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
-  }
-
-  return list;
-}
-
-static gboolean
-gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check)
-{
-  static gboolean init = FALSE;
-  static GList *devices = NULL;
-
-  if (!init && !check) {
-    gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL };
-    gint base, n, fd;
-
-    while (devices) {
-      GList *item = devices;
-      gchar *device = item->data;
-
-      devices = g_list_remove (devices, item);
-      g_free (device);
-    }
-
-    /* detect /dev entries */
-    for (n = 0; n < 64; n++) {
-      for (base = 0; dev_base[base] != NULL; base++) {
-        struct stat s;
-        gchar *device = g_strdup_printf ("%s%d", dev_base[base], n);
-
-        /* does the /dev/ entry exist at all? */
-        if (stat (device, &s) == 0) {
-          /* yes: is a device attached? */
-          if ((fd = open (device, O_RDONLY)) > 0 || errno == EBUSY) {
-            if (fd > 0)
-              close (fd);
-
-            devices = g_list_append (devices, device);
-            break;
-          }
-        }
-        g_free (device);
-      }
-    }
-
-    init = TRUE;
-  }
-
-  klass->devices = devices;
-
-  return init;
-}
-
-static void
-gst_v4l_probe_probe_property (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      gst_v4l_class_probe_devices (klass, FALSE);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_v4l_probe_needs_probe (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
-  gboolean ret = FALSE;
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      ret = !gst_v4l_class_probe_devices (klass, TRUE);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-      break;
-  }
-
-  return ret;
-}
-
-static GValueArray *
-gst_v4l_class_list_devices (GstV4lElementClass * klass)
-{
-  GValueArray *array;
-  GValue value = { 0 };
-  GList *item;
-
-  if (!klass->devices)
-    return NULL;
-
-  array = g_value_array_new (g_list_length (klass->devices));
-  item = klass->devices;
-  g_value_init (&value, G_TYPE_STRING);
-  while (item) {
-    gchar *device = item->data;
-
-    g_value_set_string (&value, device);
-    g_value_array_append (array, &value);
-
-    item = item->next;
-  }
-  g_value_unset (&value);
-
-  return array;
-}
-
-static GValueArray *
-gst_v4l_probe_get_values (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
-  GValueArray *array = NULL;
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      array = gst_v4l_class_list_devices (klass);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-      break;
-  }
-
-  return array;
-}
-
-static void
-gst_v4l_property_probe_interface_init (GstPropertyProbeInterface * iface)
-{
-  iface->get_properties = gst_v4l_probe_get_properties;
-  iface->probe_property = gst_v4l_probe_probe_property;
-  iface->needs_probe = gst_v4l_probe_needs_probe;
-  iface->get_values = gst_v4l_probe_get_values;
-}
-
-#define GST_TYPE_V4L_DEVICE_FLAGS (gst_v4l_device_get_type ())
-static GType
-gst_v4l_device_get_type (void)
-{
-  static GType v4l_device_type = 0;
-
-  if (v4l_device_type == 0) {
-    static const GFlagsValue values[] = {
-      {VID_TYPE_CAPTURE, "CAPTURE", "Device can capture"},
-      {VID_TYPE_TUNER, "TUNER", "Device has a tuner"},
-      {VID_TYPE_OVERLAY, "OVERLAY", "Device can do overlay"},
-      {VID_TYPE_MPEG_DECODER, "MPEG_DECODER", "Device can decode MPEG"},
-      {VID_TYPE_MPEG_ENCODER, "MPEG_ENCODER", "Device can encode MPEG"},
-      {VID_TYPE_MJPEG_DECODER, "MJPEG_DECODER", "Device can decode MJPEG"},
-      {VID_TYPE_MJPEG_ENCODER, "MJPEG_ENCODER", "Device can encode MJPEG"},
-      {0x10000, "AUDIO", "Device handles audio"},
-      {0, NULL, NULL}
-    };
-
-    v4l_device_type = g_flags_register_static ("GstV4lDeviceTypeFlags", values);
-  }
-
-  return v4l_device_type;
-}
-
-static void
-gst_v4lelement_init_interfaces (GType type)
-{
-  static const GInterfaceInfo v4liface_info = {
-    (GInterfaceInitFunc) gst_v4l_interface_init,
-    NULL,
-    NULL,
-  };
-  static const GInterfaceInfo v4l_tuner_info = {
-    (GInterfaceInitFunc) gst_v4l_tuner_interface_init,
-    NULL,
-    NULL,
-  };
-#ifdef HAVE_XVIDEO
-  static const GInterfaceInfo v4l_xoverlay_info = {
-    (GInterfaceInitFunc) gst_v4l_xoverlay_interface_init,
-    NULL,
-    NULL,
-  };
-#endif
-  static const GInterfaceInfo v4l_colorbalance_info = {
-    (GInterfaceInitFunc) gst_v4l_color_balance_interface_init,
-    NULL,
-    NULL,
-  };
-  static const GInterfaceInfo v4l_propertyprobe_info = {
-    (GInterfaceInitFunc) gst_v4l_property_probe_interface_init,
-    NULL,
-    NULL,
-  };
-
-  g_type_add_interface_static (type,
-      GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info);
-  g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l_tuner_info);
-#ifdef HAVE_XVIDEO
-  g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l_xoverlay_info);
-#endif
-  g_type_add_interface_static (type,
-      GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info);
-  g_type_add_interface_static (type,
-      GST_TYPE_PROPERTY_PROBE, &v4l_propertyprobe_info);
-}
-
-
-static void
-gst_v4lelement_base_init (gpointer g_class)
-{
-  GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class);
-
-  klass->devices = NULL;
-}
-
-static void
-gst_v4lelement_class_init (GstV4lElementClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstBaseSrcClass *basesrc_class;
-
-  gobject_class = (GObjectClass *) klass;
-  basesrc_class = (GstBaseSrcClass *) klass;
-
-  gobject_class->set_property = gst_v4lelement_set_property;
-  gobject_class->get_property = gst_v4lelement_get_property;
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE,
-      g_param_spec_string ("device", "Device", "Device location",
-          NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME,
-      g_param_spec_string ("device_name", "Device name", "Name of the device",
-          NULL, G_PARAM_READABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS,
-      g_param_spec_flags ("flags", "Flags", "Device type flags",
-          GST_TYPE_V4L_DEVICE_FLAGS, 0, G_PARAM_READABLE));
-
-  basesrc_class->start = gst_v4lelement_start;
-  basesrc_class->stop = gst_v4lelement_stop;
-
-  gobject_class->dispose = gst_v4lelement_dispose;
-}
-
-
-static void
-gst_v4lelement_init (GstV4lElement * v4lelement, GstV4lElementClass * klass)
-{
-  /* some default values */
-  v4lelement->video_fd = -1;
-  v4lelement->buffer = NULL;
-  v4lelement->videodev = g_strdup ("/dev/video0");
-
-  v4lelement->norms = NULL;
-  v4lelement->channels = NULL;
-  v4lelement->colors = NULL;
-
-  v4lelement->xwindow_id = 0;
-}
-
-
-static void
-gst_v4lelement_dispose (GObject * object)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (object);
-
-  if (v4lelement->videodev) {
-    g_free (v4lelement->videodev);
-    v4lelement->videodev = NULL;
-  }
-
-  if (((GObjectClass *) parent_class)->dispose)
-    ((GObjectClass *) parent_class)->dispose (object);
-}
-
-
-static void
-gst_v4lelement_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      if (v4lelement->videodev)
-        g_free (v4lelement->videodev);
-      v4lelement->videodev = g_strdup (g_value_get_string (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-
-static void
-gst_v4lelement_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (object);
-
-  switch (prop_id) {
-    case PROP_DEVICE:
-      g_value_set_string (value, v4lelement->videodev);
-      break;
-    case PROP_DEVICE_NAME:{
-      gchar *new = NULL;
-
-      if (GST_V4L_IS_OPEN (v4lelement)) {
-        new = v4lelement->vcap.name;
-      } else if (gst_v4l_open (v4lelement)) {
-        new = v4lelement->vcap.name;
-        gst_v4l_close (v4lelement);
-      }
-      g_value_set_string (value, new);
-      break;
-    }
-    case PROP_FLAGS:{
-      guint flags = 0;
-
-      if (GST_V4L_IS_OPEN (v4lelement)) {
-        flags |= v4lelement->vcap.type & 0x3C0B;
-        if (v4lelement->vcap.audios)
-          flags |= 0x10000;
-      }
-      g_value_set_flags (value, flags);
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_v4lelement_start (GstBaseSrc * src)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (src);
-
-  if (!gst_v4l_open (v4lelement))
-    return FALSE;
-
-#ifdef HAVE_XVIDEO
-  gst_v4l_xoverlay_start (v4lelement);
-#endif
-
-  return TRUE;
-}
-
-static gboolean
-gst_v4lelement_stop (GstBaseSrc * src)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (src);
-
-#ifdef HAVE_XVIDEO
-  gst_v4l_xoverlay_stop (v4lelement);
-#endif
-
-  if (!gst_v4l_close (v4lelement))
-    return FALSE;
-
-  return TRUE;
-}
--- a/gst_plugins_base/sys/v4l/gstv4lelement.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/* GStreamer
- *
- * gstv4lelement.h: base class for V4L elements
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4LELEMENT_H__
-#define __GST_V4LELEMENT_H__
-
-/* Because of some really cool feature in video4linux1, also known as
- * 'not including sys/types.h and sys/time.h', we had to include it
- * ourselves. In all their intelligence, these people decided to fix
- * this in the next version (video4linux2) in such a cool way that it
- * breaks all compilations of old stuff...
- * The real problem is actually that linux/time.h doesn't use proper
- * macro checks before defining types like struct timeval. The proper
- * fix here is to either fuck the kernel header (which is what we do
- * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
- * upstream, which I'll consider doing later on. If you get compiler
- * errors here, check your linux/time.h && sys/time.h header setup.
- */
-#include <sys/types.h>
-#define _LINUX_TIME_H
-#include <linux/videodev.h>
-
-#include <gst/gst.h>
-#include <gst/base/gstpushsrc.h>
-
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4LELEMENT \
-  (gst_v4lelement_get_type())
-#define GST_V4LELEMENT(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LELEMENT,GstV4lElement))
-#define GST_V4LELEMENT_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LELEMENT,GstV4lElementClass))
-#define GST_IS_V4LELEMENT(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LELEMENT))
-#define GST_IS_V4LELEMENT_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LELEMENT))
-#define GST_V4LELEMENT_GET_CLASS(klass) \
-  (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_V4LELEMENT, GstV4lElementClass))
-
-typedef struct _GstV4lElement GstV4lElement;
-typedef struct _GstV4lElementClass GstV4lElementClass;
-typedef struct _GstV4lXv GstV4lXv;
-
-struct _GstV4lElement {
-  GstPushSrc element;
-
-  /* the video device */
-  char *videodev;
-
-  /* the video-device's file descriptor */
-  gint video_fd;
-
-  /* the video buffer (mmap()'ed) */
-  guint8 *buffer;
-
-  /* the video device's capabilities */
-  struct video_capability vcap;
-
-  /* the video device's window properties */
-  struct video_window vwin;
-
-  /* some more info about the current input's capabilities */
-  struct video_channel vchan;
-
-  /* lists... */
-  GList *colors;
-  GList *norms;
-  GList *channels;
-
-  /* X-overlay */
-  GstV4lXv *xv;
-  gulong xwindow_id;
-};
-
-struct _GstV4lElementClass {
-  GstPushSrcClass parent_class;
-
-  /* probed devices */
-  GList *devices;
-
-  /* actions */
-  gboolean (*get_attribute)   (GstElement  *element,
-                               const gchar *attr_name,
-                               int         *value);
-  gboolean (*set_attribute)   (GstElement  *element,
-                               const gchar *attr_name,
-                               const int    value);
-};
-
-GType gst_v4lelement_get_type(void);
-
-
-G_END_DECLS
-
-#endif /* __GST_V4LELEMENT_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4ljpegsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/* GStreamer
- *
- * gstv4ljpegsrc.h: V4L video source element for JPEG cameras
- *
- * Copyright (C) 2001-2005 Jan Schmidt <thaytan@mad.scientist.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_V4LJPEGSRC_H__
-#define __GST_V4LJPEGSRC_H__
-
-#include <gstv4lsrc.h>
-
-G_BEGIN_DECLS
-#define GST_TYPE_V4LJPEGSRC \
-  (gst_v4ljpegsrc_get_type())
-#define GST_V4LJPEGSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrc))
-#define GST_V4LJPEGSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrcClass))
-#define GST_IS_V4LJPEGSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LJPEGSRC))
-#define GST_IS_V4LJPEGSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LJPEGSRC))
-typedef struct _GstV4lJpegSrc GstV4lJpegSrc;
-typedef struct _GstV4lJpegSrcClass GstV4lJpegSrcClass;
-
-struct _GstV4lJpegSrc
-{
-  GstV4lSrc             v4lsrc;
-  GstPadGetFunction     getfn;
-  GstPadGetCapsFunction getcapsfn;
-};
-
-struct _GstV4lJpegSrcClass
-{
-  GstV4lSrcClass parent_class;
-};
-
-GType gst_v4ljpegsrc_get_type (void);
-
-G_END_DECLS
-#endif /* __GST_V4LJPEGSRC_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lmjpegsink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* GStreamer
- *
- * gstv4lmjpegsink.h: hardware MJPEG video sink element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4LMJPEGSINK_H__
-#define __GST_V4LMJPEGSINK_H__
-
-#include <gstv4lelement.h>
-#include <sys/time.h>
-#include <videodev_mjpeg.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_TYPE_V4LMJPEGSINK \
-  (gst_v4lmjpegsink_get_type())
-#define GST_V4LMJPEGSINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LMJPEGSINK,GstV4lMjpegSink))
-#define GST_V4LMJPEGSINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LMJPEGSINK,GstV4lMjpegSinkClass))
-#define GST_IS_V4LMJPEGSINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LMJPEGSINK))
-#define GST_IS_V4LMJPEGSINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LMJPEGSINK))
-
-typedef struct _GstV4lMjpegSink GstV4lMjpegSink;
-typedef struct _GstV4lMjpegSinkClass GstV4lMjpegSinkClass;
-
-struct _GstV4lMjpegSink {
-  GstV4lElement v4lelement;
-
-  /* the sink pas */
-  GstPad *sinkpad;
-
-  /* frame properties for common players */
-  gint frames_displayed;
-  guint64 frame_time;
-
-  /* system clock object */
-  GstClock *clock;
-
-  /* buffer/capture info */
-  struct mjpeg_sync bsync;
-  struct mjpeg_requestbuffers breq;
-
-  /* thread to keep track of synced frames */
-  gint8 *isqueued_queued_frames; /* 1 = queued, 0 = unqueued, -1 = error */
-  GThread *thread_queued_frames;
-  GMutex *mutex_queued_frames;
-  GCond **cond_queued_frames;
-  gint current_frame;
-
-  /* width/height/norm of the jpeg stream */
-  gint width;
-  gint height;
-  gint norm;
-
-  /* cache values */
-  gint x_offset;
-  gint y_offset;
-
-  gint numbufs;
-  gint bufsize; /* in KB */
-};
-
-struct _GstV4lMjpegSinkClass {
-  GstV4lElementClass parent_class;
-
-  /* signals */
-  void (*frame_displayed) (GstElement *element);
-};
-
-GType gst_v4lmjpegsink_get_type(void);
-
-
-G_END_DECLS
-
-#endif /* __GST_SDLVIDEOSINK_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lmjpegsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/* GStreamer
- *
- * gstv4lmjpegsrc.h: hardware MJPEG video source element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4LMJPEGSRC_H__
-#define __GST_V4LMJPEGSRC_H__
-
-#include <gstv4lelement.h>
-#include <sys/time.h>
-#include <videodev_mjpeg.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4LMJPEGSRC \
-  (gst_v4lmjpegsrc_get_type())
-#define GST_V4LMJPEGSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LMJPEGSRC,GstV4lMjpegSrc))
-#define GST_V4LMJPEGSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LMJPEGSRC,GstV4lMjpegSrcClass))
-#define GST_IS_V4LMJPEGSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LMJPEGSRC))
-#define GST_IS_V4LMJPEGSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LMJPEGSRC))
-
-typedef struct _GstV4lMjpegSrc GstV4lMjpegSrc;
-typedef struct _GstV4lMjpegSrcClass GstV4lMjpegSrcClass;
-
-struct _GstV4lMjpegSrc {
-  GstV4lElement v4lelement;
-
-  /* pads */
-  GstPad *srcpad;
-
-  /* buffer/capture info */
-  struct mjpeg_sync bsync;
-  struct mjpeg_requestbuffers breq;
-
-  /* num of queued frames and some GThread stuff
-   * to wait if there's not enough */
-  gint8 *frame_queue_state;
-  GMutex *mutex_queue_state;
-  GCond *cond_queue_state;
-  gint num_queued;
-  gint queue_frame;
-
-  /* True if we want to stop */
-  gboolean quit, is_capturing;
-
-  /* A/V sync... frame counter and internal cache */
-  gulong handled;
-  gint last_frame;
-  gint last_size;
-  gint need_writes;
-  gulong last_seq;
-
-  /* clock */
-  GstClock *clock;
-
-  /* time to substract from clock time to get back to timestamp */
-  GstClockTime substract_time;
-
-  /* how often are we going to use each frame? */
-  gint *use_num_times;
-
-  /* how are we going to push buffers? */
-  gboolean use_fixed_fps;
-
-  /* end size */
-  gint end_width, end_height;
-
-  /* caching values */
-#if 0
-  gint x_offset;
-  gint y_offset;
-  gint frame_width;
-  gint frame_height;
-#endif
-
-  gint quality;
-  gint numbufs;
-};
-
-struct _GstV4lMjpegSrcClass {
-  GstV4lElementClass parent_class;
-
-  void (*frame_capture) (GObject *object);
-  void (*frame_drop)    (GObject *object);
-  void (*frame_insert)  (GObject *object);
-  void (*frame_lost)    (GObject *object,
-                         gint     num_lost);
-};
-
-GType gst_v4lmjpegsrc_get_type(void);
-
-
-G_END_DECLS
-
-#endif /* __GST_V4LMJPEGSRC_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,732 +0,0 @@
-/* GStreamer
- *
- * gstv4lsrc.c: BT8x8/V4L source element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <sys/time.h>
-#include "v4lsrc_calls.h"
-#include <sys/ioctl.h>
-
-
-static const GstElementDetails gst_v4lsrc_details =
-GST_ELEMENT_DETAILS ("Video (video4linux/raw) Source",
-    "Source/Video",
-    "Reads raw frames from a video4linux device",
-    "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-
-GST_DEBUG_CATEGORY_STATIC (v4lsrc_debug);
-#define GST_CAT_DEFAULT v4lsrc_debug
-
-
-enum
-{
-  PROP_0,
-  PROP_AUTOPROBE,
-  PROP_AUTOPROBE_FPS,
-  PROP_COPY_MODE,
-  PROP_TIMESTAMP_OFFSET
-};
-
-
-GST_BOILERPLATE (GstV4lSrc, gst_v4lsrc, GstV4lElement, GST_TYPE_V4LELEMENT);
-
-
-/* basesrc methods */
-static gboolean gst_v4lsrc_start (GstBaseSrc * src);
-static gboolean gst_v4lsrc_stop (GstBaseSrc * src);
-static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps);
-static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
-static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
-static gboolean gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query);
-static void gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps);
-
-static void gst_v4lsrc_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4lsrc_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-
-static void
-gst_v4lsrc_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (gstelement_class, &gst_v4lsrc_details);
-
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
-          gst_caps_new_any ()));
-}
-
-static void
-gst_v4lsrc_class_init (GstV4lSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstBaseSrcClass *basesrc_class;
-  GstPushSrcClass *pushsrc_class;
-
-  gobject_class = (GObjectClass *) klass;
-  basesrc_class = (GstBaseSrcClass *) klass;
-  pushsrc_class = (GstPushSrcClass *) klass;
-
-  gobject_class->set_property = gst_v4lsrc_set_property;
-  gobject_class->get_property = gst_v4lsrc_get_property;
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE,
-      g_param_spec_boolean ("autoprobe", "Autoprobe",
-          "Whether the device should be probed for all possible features",
-          TRUE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE_FPS,
-      g_param_spec_boolean ("autoprobe-fps", "Autoprobe FPS",
-          "Whether the device should be probed for framerates",
-          TRUE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COPY_MODE,
-      g_param_spec_boolean ("copy-mode", "Copy mode",
-          "Whether to send out copies of buffers, or direct pointers to the mmap region",
-          TRUE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass),
-      PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
-          "Timestamp offset",
-          "A time offset subtracted from timestamps set on buffers (in ns)",
-          G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
-
-  GST_DEBUG_CATEGORY_INIT (v4lsrc_debug, "v4lsrc", 0, "V4L source element");
-
-  basesrc_class->get_caps = gst_v4lsrc_get_caps;
-  basesrc_class->set_caps = gst_v4lsrc_set_caps;
-  basesrc_class->start = gst_v4lsrc_start;
-  basesrc_class->stop = gst_v4lsrc_stop;
-  basesrc_class->fixate = gst_v4lsrc_fixate;
-  basesrc_class->query = gst_v4lsrc_query;
-
-  pushsrc_class->create = gst_v4lsrc_create;
-}
-
-static void
-gst_v4lsrc_init (GstV4lSrc * v4lsrc, GstV4lSrcClass * klass)
-{
-  v4lsrc->buffer_size = 0;
-
-  /* no colorspaces */
-  v4lsrc->colorspaces = NULL;
-
-  v4lsrc->is_capturing = FALSE;
-  v4lsrc->autoprobe = TRUE;
-  v4lsrc->autoprobe_fps = TRUE;
-  v4lsrc->copy_mode = TRUE;
-
-  v4lsrc->timestamp_offset = 0;
-
-  v4lsrc->fps_list = NULL;
-
-  gst_base_src_set_format (GST_BASE_SRC (v4lsrc), GST_FORMAT_TIME);
-  gst_base_src_set_live (GST_BASE_SRC (v4lsrc), TRUE);
-}
-
-static void
-gst_v4lsrc_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-  GstV4lSrc *v4lsrc = GST_V4LSRC (object);
-
-  switch (prop_id) {
-    case PROP_AUTOPROBE:
-      g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)));
-      v4lsrc->autoprobe = g_value_get_boolean (value);
-      break;
-    case PROP_AUTOPROBE_FPS:
-      g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)));
-      v4lsrc->autoprobe_fps = g_value_get_boolean (value);
-      break;
-    case PROP_COPY_MODE:
-      v4lsrc->copy_mode = g_value_get_boolean (value);
-      break;
-    case PROP_TIMESTAMP_OFFSET:
-      v4lsrc->timestamp_offset = g_value_get_int64 (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-
-static void
-gst_v4lsrc_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
-{
-  GstV4lSrc *v4lsrc = GST_V4LSRC (object);
-
-  switch (prop_id) {
-    case PROP_AUTOPROBE:
-      g_value_set_boolean (value, v4lsrc->autoprobe);
-      break;
-    case PROP_AUTOPROBE_FPS:
-      g_value_set_boolean (value, v4lsrc->autoprobe_fps);
-      break;
-    case PROP_COPY_MODE:
-      g_value_set_boolean (value, v4lsrc->copy_mode);
-      break;
-    case PROP_TIMESTAMP_OFFSET:
-      g_value_set_int64 (value, v4lsrc->timestamp_offset);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-/* this function is a bit of a last resort */
-static void
-gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps)
-{
-  GstStructure *structure;
-  int i;
-  int targetwidth, targetheight;
-  GstV4lSrc *v4lsrc = GST_V4LSRC (bsrc);
-  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
-  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
-  if (GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
-    GST_DEBUG_OBJECT (v4lsrc, "device reported w: %d-%d, h: %d-%d",
-        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight);
-    targetwidth = vcap->minwidth;
-    targetheight = vcap->minheight;
-    /* if we can get the current vwin settings, we use those to fixate */
-    if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc)))
-      GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities");
-    else {
-      targetwidth = vwin->width;
-      targetheight = vwin->height;
-    }
-  } else {
-    GST_DEBUG_OBJECT (v4lsrc, "device closed, guessing");
-    targetwidth = 320;
-    targetheight = 200;
-  }
-
-  GST_DEBUG_OBJECT (v4lsrc, "targetting %dx%d", targetwidth, targetheight);
-
-  for (i = 0; i < gst_caps_get_size (caps); ++i) {
-    const GValue *v;
-
-    structure = gst_caps_get_structure (caps, i);
-    gst_structure_fixate_field_nearest_int (structure, "width", targetwidth);
-    gst_structure_fixate_field_nearest_int (structure, "height", targetheight);
-    gst_structure_fixate_field_nearest_fraction (structure, "framerate", 15, 2);
-
-    v = gst_structure_get_value (structure, "format");
-    if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
-      guint32 fourcc;
-
-      g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
-
-      fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
-      gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
-    }
-  }
-}
-
-static gint all_palettes[] = {
-  VIDEO_PALETTE_YUV422,
-  VIDEO_PALETTE_YUV420P,
-  VIDEO_PALETTE_UYVY,
-  VIDEO_PALETTE_YUV411P,
-  VIDEO_PALETTE_YUV422P,
-  VIDEO_PALETTE_YUV410P,
-  VIDEO_PALETTE_YUV411,
-  VIDEO_PALETTE_RGB555,
-  VIDEO_PALETTE_RGB565,
-  VIDEO_PALETTE_RGB24,
-  VIDEO_PALETTE_RGB32,
-  -1
-};
-
-static GstCaps *
-gst_v4lsrc_palette_to_caps (int palette)
-{
-  guint32 fourcc;
-  GstCaps *caps;
-
-  switch (palette) {
-    case VIDEO_PALETTE_YUV422:
-    case VIDEO_PALETTE_YUYV:
-      fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
-      break;
-    case VIDEO_PALETTE_YUV420P:
-      fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
-      break;
-    case VIDEO_PALETTE_UYVY:
-      fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
-      break;
-    case VIDEO_PALETTE_YUV411P:
-      fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
-      break;
-    case VIDEO_PALETTE_YUV411:
-      fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P');
-      break;
-    case VIDEO_PALETTE_YUV422P:
-      fourcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
-      break;
-    case VIDEO_PALETTE_YUV410P:
-      fourcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
-      break;
-    case VIDEO_PALETTE_RGB555:
-    case VIDEO_PALETTE_RGB565:
-    case VIDEO_PALETTE_RGB24:
-    case VIDEO_PALETTE_RGB32:
-      fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
-      break;
-    default:
-      return NULL;
-  }
-
-  if (fourcc == GST_MAKE_FOURCC ('R', 'G', 'B', ' ')) {
-    switch (palette) {
-      case VIDEO_PALETTE_RGB555:
-        caps = gst_caps_from_string ("video/x-raw-rgb, "
-            "bpp = (int) 16, "
-            "depth = (int) 15, "
-            "endianness = (int) BYTE_ORDER, "
-            "red_mask = 0x7c00, " "green_mask = 0x03e0, " "blue_mask = 0x001f");
-        break;
-      case VIDEO_PALETTE_RGB565:
-        caps = gst_caps_from_string ("video/x-raw-rgb, "
-            "bpp = (int) 16, "
-            "depth = (int) 16, "
-            "endianness = (int) BYTE_ORDER, "
-            "red_mask = 0xf800, " "green_mask = 0x07f0, " "blue_mask = 0x001f");
-        break;
-      case VIDEO_PALETTE_RGB24:
-        caps = gst_caps_from_string ("video/x-raw-rgb, "
-            "bpp = (int) 24, "
-            "depth = (int) 24, "
-            "endianness = (int) BIG_ENDIAN, "
-            "red_mask = 0xFF0000, "
-            "green_mask = 0x00FF00, " "blue_mask = 0x0000FF");
-        break;
-      case VIDEO_PALETTE_RGB32:
-        caps = gst_caps_from_string ("video/x-raw-rgb, "
-            "bpp = (int) 32, "
-            "depth = (int) 24, "
-            "endianness = (int) BIG_ENDIAN, "
-            "red_mask = 0xFF000000, "
-            "green_mask = 0x00FF0000, " "blue_mask = 0x0000FF00");
-        break;
-      default:
-        g_assert_not_reached ();
-        return NULL;
-    }
-  } else {
-    caps = gst_caps_new_simple ("video/x-raw-yuv",
-        "format", GST_TYPE_FOURCC, fourcc, NULL);
-  }
-
-  return caps;
-}
-
-static GstCaps *
-gst_v4lsrc_get_any_caps (void)
-{
-  gint i;
-  GstCaps *caps = gst_caps_new_empty (), *one;
-
-  for (i = 0; all_palettes[i] != -1; i++) {
-    one = gst_v4lsrc_palette_to_caps (all_palettes[i]);
-    gst_caps_append (caps, one);
-  }
-
-  return caps;
-}
-
-static GstCaps *
-gst_v4lsrc_get_caps (GstBaseSrc * src)
-{
-  GstCaps *list;
-  GstV4lSrc *v4lsrc = GST_V4LSRC (src);
-  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
-  gint width = GST_V4LELEMENT (src)->vcap.minwidth;
-  gint height = GST_V4LELEMENT (src)->vcap.minheight;
-  gint i;
-  gint fps_n, fps_d;
-  GList *item;
-
-  if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
-    return gst_v4lsrc_get_any_caps ();
-  }
-
-  if (!v4lsrc->autoprobe) {
-    /* FIXME: query current caps and return those, with _any appended */
-    return gst_v4lsrc_get_any_caps ();
-  }
-
-  if (!v4lsrc->colorspaces) {
-    GST_DEBUG_OBJECT (v4lsrc, "Checking supported palettes");
-    for (i = 0; all_palettes[i] != -1; i++) {
-      /* try palette out */
-      if (!gst_v4lsrc_try_capture (v4lsrc, width, height, all_palettes[i]))
-        continue;
-      GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list",
-          all_palettes[i], gst_v4lsrc_palette_name (all_palettes[i]));
-      v4lsrc->colorspaces = g_list_append (v4lsrc->colorspaces,
-          GINT_TO_POINTER (all_palettes[i]));
-    }
-    GST_DEBUG_OBJECT (v4lsrc, "%d palette(s) supported",
-        g_list_length (v4lsrc->colorspaces));
-    if (v4lsrc->autoprobe_fps) {
-      GST_DEBUG_OBJECT (v4lsrc, "autoprobing framerates");
-      v4lsrc->fps_list = gst_v4lsrc_get_fps_list (v4lsrc);
-    }
-  }
-
-
-  if (!gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)) {
-    fps_n = 0;
-    fps_d = 1;
-  }
-
-  list = gst_caps_new_empty ();
-  for (item = v4lsrc->colorspaces; item != NULL; item = item->next) {
-    GstCaps *one;
-
-    one = gst_v4lsrc_palette_to_caps (GPOINTER_TO_INT (item->data));
-    if (!one) {
-      GST_WARNING_OBJECT (v4lsrc, "Palette %d gave no caps\n",
-          GPOINTER_TO_INT (item->data));
-      continue;
-    }
-
-    GST_DEBUG_OBJECT (v4lsrc,
-        "Device reports w: %d-%d, h: %d-%d, fps: %d/%d for palette %d",
-        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight,
-        fps_n, fps_d, GPOINTER_TO_INT (item->data));
-
-    if (vcap->minwidth < vcap->maxwidth) {
-      gst_caps_set_simple (one, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
-          vcap->maxwidth, NULL);
-    } else {
-      gst_caps_set_simple (one, "width", G_TYPE_INT, vcap->minwidth, NULL);
-    }
-    if (vcap->minheight < vcap->maxheight) {
-      gst_caps_set_simple (one, "height", GST_TYPE_INT_RANGE, vcap->minheight,
-          vcap->maxheight, NULL);
-    } else {
-      gst_caps_set_simple (one, "height", G_TYPE_INT, vcap->minheight, NULL);
-    }
-
-    if (v4lsrc->autoprobe_fps) {
-      GstStructure *structure = gst_caps_get_structure (one, 0);
-
-      if (v4lsrc->fps_list) {
-        gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
-      } else {
-        gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
-            fps_n, fps_d, NULL);
-      }
-    } else {
-      gst_caps_set_simple (one, "framerate", GST_TYPE_FRACTION_RANGE,
-          1, 1, 100, 1, NULL);
-    }
-
-    GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one);
-    gst_caps_append (list, one);
-  }
-
-  return list;
-}
-
-static gboolean
-gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
-{
-  GstV4lSrc *v4lsrc;
-  guint32 fourcc;
-  gint bpp, depth, w, h, palette = -1;
-  const GValue *new_fps;
-  gint cur_fps_n, cur_fps_d;
-  GstStructure *structure;
-  struct video_window *vwin;
-
-  v4lsrc = GST_V4LSRC (src);
-  vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
-  /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
-  if (!GST_V4L_IS_OPEN (v4lsrc))
-    return FALSE;
-
-  /* make sure we stop capturing and dealloc buffers */
-  if (GST_V4L_IS_ACTIVE (v4lsrc)) {
-    if (!gst_v4lsrc_capture_stop (v4lsrc))
-      return FALSE;
-    if (!gst_v4lsrc_capture_deinit (v4lsrc))
-      return FALSE;
-  }
-
-  /* it's fixed, one struct */
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0)
-    gst_structure_get_fourcc (structure, "format", &fourcc);
-  else
-    fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
-
-  gst_structure_get_int (structure, "width", &w);
-  gst_structure_get_int (structure, "height", &h);
-  new_fps = gst_structure_get_value (structure, "framerate");
-
-  /* set framerate if it's not already correct */
-  if (!gst_v4lsrc_get_fps (v4lsrc, &cur_fps_n, &cur_fps_d))
-    return FALSE;
-
-  if (new_fps) {
-    GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %d/%d fps", w, h,
-        gst_value_get_fraction_numerator (new_fps),
-        gst_value_get_fraction_denominator (new_fps));
-
-    if (gst_value_get_fraction_numerator (new_fps) != cur_fps_n ||
-        gst_value_get_fraction_denominator (new_fps) != cur_fps_d) {
-      int fps_index = (gst_value_get_fraction_numerator (new_fps) * 16) /
-          (gst_value_get_fraction_denominator (new_fps) * 15);
-
-      GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index);
-      /* set bits 16 to 21 to 0 */
-      vwin->flags &= (0x3F00 - 1);
-      /* set bits 16 to 21 to the index */
-      vwin->flags |= fps_index << 16;
-      if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
-        return FALSE;
-      }
-    }
-  }
-
-  switch (fourcc) {
-    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
-      palette = VIDEO_PALETTE_YUV420P;
-      v4lsrc->buffer_size = ((w + 1) & ~1) * ((h + 1) & ~1) * 1.5;
-      break;
-    case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
-      palette = VIDEO_PALETTE_YUV422;
-      v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
-      break;
-    case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
-      palette = VIDEO_PALETTE_UYVY;
-      v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
-      break;
-    case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
-      palette = VIDEO_PALETTE_YUV411P;
-      v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5;
-      break;
-    case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
-      palette = VIDEO_PALETTE_YUV411;
-      v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5;
-      break;
-    case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
-      palette = VIDEO_PALETTE_YUV410P;
-      v4lsrc->buffer_size = ((w + 3) & ~3) * ((h + 3) & ~3) * 1.125;
-      break;
-    case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
-      palette = VIDEO_PALETTE_YUV422P;
-      v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
-      break;
-    case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
-      gst_structure_get_int (structure, "depth", &depth);
-      switch (depth) {
-        case 15:
-          palette = VIDEO_PALETTE_RGB555;
-          v4lsrc->buffer_size = w * h * 2;
-          break;
-        case 16:
-          palette = VIDEO_PALETTE_RGB565;
-          v4lsrc->buffer_size = w * h * 2;
-          break;
-        case 24:
-          gst_structure_get_int (structure, "bpp", &bpp);
-          switch (bpp) {
-            case 24:
-              palette = VIDEO_PALETTE_RGB24;
-              v4lsrc->buffer_size = w * h * 3;
-              break;
-            case 32:
-              palette = VIDEO_PALETTE_RGB32;
-              v4lsrc->buffer_size = w * h * 4;
-              break;
-            default:
-              break;
-          }
-          break;
-        default:
-          break;
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (palette == -1) {
-    GST_WARNING_OBJECT (v4lsrc, "palette for fourcc %" GST_FOURCC_FORMAT
-        " is -1, refusing link", GST_FOURCC_ARGS (fourcc));
-    return FALSE;
-  }
-
-  GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d",
-      w, h, palette);
-  /* this only fills in v4lsrc->mmap values */
-  if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
-    GST_WARNING_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d",
-        w, h, palette);
-    return FALSE;
-  }
-
-  /* first try the negotiated settings using try_capture */
-  if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
-    GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for %dx%d", palette,
-        w, h);
-    return FALSE;
-  }
-
-  if (!gst_v4lsrc_capture_init (v4lsrc))
-    return FALSE;
-
-  if (!gst_v4lsrc_capture_start (v4lsrc))
-    return FALSE;
-
-  return TRUE;
-}
-
-static gboolean
-gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query)
-{
-  GstV4lSrc *v4lsrc;
-  gboolean res = FALSE;
-
-  v4lsrc = GST_V4LSRC (bsrc);
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_LATENCY:
-    {
-      GstClockTime min_latency, max_latency;
-      gint fps_n, fps_d;
-
-      /* device must be open */
-      if (!GST_V4L_IS_OPEN (v4lsrc))
-        goto done;
-
-      /* we must have a framerate */
-      if (!(res = gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)))
-        goto done;
-
-      /* min latency is the time to capture one frame */
-      min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
-
-      /* max latency is total duration of the frame buffer */
-      max_latency = v4lsrc->mbuf.frames * min_latency;
-
-      GST_DEBUG_OBJECT (bsrc,
-          "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
-
-      /* we are always live, the min latency is 1 frame and the max latency is
-       * the complete buffer of frames. */
-      gst_query_set_latency (query, TRUE, min_latency, max_latency);
-
-      res = TRUE;
-      break;
-    }
-    default:
-      res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
-      break;
-  }
-done:
-  return res;
-}
-
-/* start and stop are not symmetric -- start will open the device, but not start
-   capture. it's setcaps that will start capture, which is called via basesrc's
-   negotiate method. stop will both stop capture and close the device.
- */
-static gboolean
-gst_v4lsrc_start (GstBaseSrc * src)
-{
-  GstV4lSrc *v4lsrc = GST_V4LSRC (src);
-
-  if (!GST_BASE_SRC_CLASS (parent_class)->start (src))
-    return FALSE;
-
-  v4lsrc->offset = 0;
-
-  return TRUE;
-}
-
-static gboolean
-gst_v4lsrc_stop (GstBaseSrc * src)
-{
-  GstV4lSrc *v4lsrc = GST_V4LSRC (src);
-
-  if (GST_V4L_IS_ACTIVE (v4lsrc) && !gst_v4lsrc_capture_stop (v4lsrc))
-    return FALSE;
-
-  if (GST_V4LELEMENT (v4lsrc)->buffer != NULL) {
-    if (!gst_v4lsrc_capture_deinit (v4lsrc))
-      return FALSE;
-  }
-
-  if (!GST_BASE_SRC_CLASS (parent_class)->stop (src))
-    return FALSE;
-
-  g_list_free (v4lsrc->colorspaces);
-  v4lsrc->colorspaces = NULL;
-
-  if (v4lsrc->fps_list) {
-    g_value_unset (v4lsrc->fps_list);
-    g_free (v4lsrc->fps_list);
-    v4lsrc->fps_list = NULL;
-  }
-
-  return TRUE;
-}
-
-static GstFlowReturn
-gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** buf)
-{
-  GstV4lSrc *v4lsrc;
-  gint num;
-
-  v4lsrc = GST_V4LSRC (src);
-
-  /* grab a frame from the device */
-  if (!gst_v4lsrc_grab_frame (v4lsrc, &num))
-    return GST_FLOW_ERROR;
-
-  *buf = gst_v4lsrc_buffer_new (v4lsrc, num);
-
-  if (v4lsrc->copy_mode) {
-    GstBuffer *copy = gst_buffer_copy (*buf);
-
-    gst_buffer_unref (*buf);
-    *buf = copy;
-  }
-
-  return GST_FLOW_OK;
-}
--- a/gst_plugins_base/sys/v4l/gstv4lsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/* GStreamer
- *
- * gstv4lsrc.h: BT8x8/V4L video source element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4LSRC_H__
-#define __GST_V4LSRC_H__
-
-
-#include <gstv4lelement.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_TYPE_V4LSRC \
-  (gst_v4lsrc_get_type())
-#define GST_V4LSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LSRC,GstV4lSrc))
-#define GST_V4LSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LSRC,GstV4lSrcClass))
-#define GST_IS_V4LSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LSRC))
-#define GST_IS_V4LSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LSRC))
-
-
-typedef struct _GstV4lSrc GstV4lSrc;
-typedef struct _GstV4lSrcClass GstV4lSrcClass;
-
-
-enum
-{
-  QUEUE_STATE_ERROR = -1,
-  QUEUE_STATE_READY_FOR_QUEUE,  /* the frame is ready to be queued for capture */
-  QUEUE_STATE_QUEUED,           /* the frame is queued for capture */
-  QUEUE_STATE_SYNCED            /* the frame is captured */
-};
-
-
-struct _GstV4lSrc
-{
-  GstV4lElement v4lelement;
-
-  /* pads */
-  GstPad *srcpad;
-
-  /* capture/buffer info */
-  struct video_mmap mmap;
-  struct video_mbuf mbuf;
-  guint buffer_size;
-  GstClockTime timestamp_sync;
-
-  /* num of queued frames and some GThread stuff
-   * to wait if there's not enough */
-  gint8 *frame_queue_state;
-  GMutex *mutex_queue_state;
-  GCond *cond_queue_state;
-  gint num_queued;
-  gint sync_frame, queue_frame;
-  gboolean is_capturing;
-  GstClockTimeDiff timestamp_offset;
-
-  /* True if we want to stop */
-  gboolean quit;
-
-  gint offset;
-
-  /* list of supported colorspaces (as integers) */
-  GList *colorspaces;
-
-  gboolean autoprobe;           /* probe features on startup ? */
-  gboolean autoprobe_fps;       /* probe fps on startup ? */
-  gboolean copy_mode;
-
-  GValue *fps_list;             /* list of fps probed */
-};
-
-struct _GstV4lSrcClass
-{
-  GstV4lElementClass parent_class;
-};
-
-
-GType gst_v4lsrc_get_type (void);
-
-
-G_END_DECLS
-
-
-#endif /* __GST_V4LSRC_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4ltuner.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
-/* GStreamer
- *
- * gstv4ltuner.c: tuner interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-
-#include "gstv4ltuner.h"
-#include "gstv4lelement.h"
-#include "v4l_calls.h"
-
-static void gst_v4l_tuner_channel_class_init (GstV4lTunerChannelClass * klass);
-static void gst_v4l_tuner_channel_init (GstV4lTunerChannel * channel);
-
-static void gst_v4l_tuner_norm_class_init (GstV4lTunerNormClass * klass);
-static void gst_v4l_tuner_norm_init (GstV4lTunerNorm * norm);
-
-static const GList *gst_v4l_tuner_list_channels (GstTuner * tuner);
-static void gst_v4l_tuner_set_channel (GstTuner * tuner,
-    GstTunerChannel * channel);
-static GstTunerChannel *gst_v4l_tuner_get_channel (GstTuner * tuner);
-
-static const GList *gst_v4l_tuner_list_norms (GstTuner * tuner);
-static void gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm);
-static GstTunerNorm *gst_v4l_tuner_get_norm (GstTuner * tuner);
-
-static void gst_v4l_tuner_set_frequency (GstTuner * tuner,
-    GstTunerChannel * channel, gulong frequency);
-static gulong gst_v4l_tuner_get_frequency (GstTuner * tuner,
-    GstTunerChannel * channel);
-static gint gst_v4l_tuner_signal_strength (GstTuner * tuner,
-    GstTunerChannel * channel);
-
-static GstTunerNormClass *norm_parent_class = NULL;
-static GstTunerChannelClass *channel_parent_class = NULL;
-
-GType
-gst_v4l_tuner_channel_get_type (void)
-{
-  static GType gst_v4l_tuner_channel_type = 0;
-
-  if (!gst_v4l_tuner_channel_type) {
-    static const GTypeInfo v4l_tuner_channel_info = {
-      sizeof (GstV4lTunerChannelClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_v4l_tuner_channel_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4lTunerChannel),
-      0,
-      (GInstanceInitFunc) gst_v4l_tuner_channel_init,
-      NULL
-    };
-
-    gst_v4l_tuner_channel_type =
-        g_type_register_static (GST_TYPE_TUNER_CHANNEL,
-        "GstV4lTunerChannel", &v4l_tuner_channel_info, 0);
-  }
-
-  return gst_v4l_tuner_channel_type;
-}
-
-static void
-gst_v4l_tuner_channel_class_init (GstV4lTunerChannelClass * klass)
-{
-  channel_parent_class = g_type_class_peek_parent (klass);
-}
-
-static void
-gst_v4l_tuner_channel_init (GstV4lTunerChannel * channel)
-{
-  channel->index = 0;
-  channel->audio = 0;
-  channel->tuner = 0;
-}
-
-GType
-gst_v4l_tuner_norm_get_type (void)
-{
-  static GType gst_v4l_tuner_norm_type = 0;
-
-  if (!gst_v4l_tuner_norm_type) {
-    static const GTypeInfo v4l_tuner_norm_info = {
-      sizeof (GstV4lTunerNormClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_v4l_tuner_norm_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4lTunerNorm),
-      0,
-      (GInstanceInitFunc) gst_v4l_tuner_norm_init,
-      NULL
-    };
-
-    gst_v4l_tuner_norm_type =
-        g_type_register_static (GST_TYPE_TUNER_NORM,
-        "GstV4lTunerNorm", &v4l_tuner_norm_info, 0);
-  }
-
-  return gst_v4l_tuner_norm_type;
-}
-
-static void
-gst_v4l_tuner_norm_class_init (GstV4lTunerNormClass * klass)
-{
-  norm_parent_class = g_type_class_peek_parent (klass);
-}
-
-static void
-gst_v4l_tuner_norm_init (GstV4lTunerNorm * norm)
-{
-  norm->index = 0;
-}
-
-void
-gst_v4l_tuner_interface_init (GstTunerClass * klass)
-{
-  /* default virtual functions */
-  klass->list_channels = gst_v4l_tuner_list_channels;
-  klass->set_channel = gst_v4l_tuner_set_channel;
-  klass->get_channel = gst_v4l_tuner_get_channel;
-
-  klass->list_norms = gst_v4l_tuner_list_norms;
-  klass->set_norm = gst_v4l_tuner_set_norm;
-  klass->get_norm = gst_v4l_tuner_get_norm;
-
-  klass->set_frequency = gst_v4l_tuner_set_frequency;
-  klass->get_frequency = gst_v4l_tuner_get_frequency;
-  klass->signal_strength = gst_v4l_tuner_signal_strength;
-}
-
-static G_GNUC_UNUSED gboolean
-gst_v4l_tuner_contains_channel (GstV4lElement * v4lelement,
-    GstV4lTunerChannel * v4lchannel)
-{
-  const GList *item;
-
-  for (item = v4lelement->channels; item != NULL; item = item->next)
-    if (item->data == v4lchannel)
-      return TRUE;
-
-  return FALSE;
-}
-
-static const GList *
-gst_v4l_tuner_list_channels (GstTuner * tuner)
-{
-  return GST_V4LELEMENT (tuner)->channels;
-}
-
-static void
-gst_v4l_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
-  gint norm;
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
-  g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel));
-
-  gst_v4l_get_chan_norm (v4lelement, NULL, &norm);
-  gst_v4l_set_chan_norm (v4lelement, v4lchannel->index, norm);
-}
-
-static GstTunerChannel *
-gst_v4l_tuner_get_channel (GstTuner * tuner)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GList *item;
-  gint channel;
-
-  /* assert that we're opened */
-  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL);
-
-  gst_v4l_get_chan_norm (v4lelement, &channel, NULL);
-
-  for (item = v4lelement->channels; item != NULL; item = item->next) {
-    if (channel == GST_V4L_TUNER_CHANNEL (item->data)->index)
-      return GST_TUNER_CHANNEL (item->data);
-  }
-
-  return NULL;
-}
-
-static G_GNUC_UNUSED gboolean
-gst_v4l_tuner_contains_norm (GstV4lElement * v4lelement,
-    GstV4lTunerNorm * v4lnorm)
-{
-  const GList *item;
-
-  for (item = v4lelement->norms; item != NULL; item = item->next)
-    if (item->data == v4lnorm)
-      return TRUE;
-
-  return FALSE;
-}
-
-static const GList *
-gst_v4l_tuner_list_norms (GstTuner * tuner)
-{
-  return GST_V4LELEMENT (tuner)->norms;
-}
-
-static void
-gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GstV4lTunerNorm *v4lnorm = GST_V4L_TUNER_NORM (norm);
-  gint channel;
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
-  g_return_if_fail (gst_v4l_tuner_contains_norm (v4lelement, v4lnorm));
-
-  gst_v4l_get_chan_norm (v4lelement, &channel, NULL);
-  gst_v4l_set_chan_norm (v4lelement, channel, v4lnorm->index);
-}
-
-static GstTunerNorm *
-gst_v4l_tuner_get_norm (GstTuner * tuner)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GList *item;
-  gint norm;
-
-  /* assert that we're opened */
-  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL);
-
-  gst_v4l_get_chan_norm (v4lelement, NULL, &norm);
-
-  for (item = v4lelement->norms; item != NULL; item = item->next) {
-    if (norm == GST_V4L_TUNER_NORM (item->data)->index)
-      return GST_TUNER_NORM (item->data);
-  }
-
-  return NULL;
-}
-
-static void
-gst_v4l_tuner_set_frequency (GstTuner * tuner,
-    GstTunerChannel * channel, gulong frequency)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
-  gint chan;
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
-  g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
-          GST_TUNER_CHANNEL_FREQUENCY));
-  g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel));
-
-  gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
-  if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) {
-    gst_v4l_set_frequency (v4lelement, v4lchannel->tuner, frequency);
-  }
-}
-
-static gulong
-gst_v4l_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
-  gint chan;
-  gulong frequency = 0;
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
-  g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
-          GST_TUNER_CHANNEL_FREQUENCY), 0);
-  g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement,
-          v4lchannel), 0);
-
-  gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
-  if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) {
-    gst_v4l_get_frequency (v4lelement, v4lchannel->tuner, &frequency);
-  }
-
-  return frequency;
-}
-
-static gint
-gst_v4l_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
-  GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
-  gint chan;
-  guint signal = 0;
-
-  /* assert that we're opened and that we're using a known item */
-  g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
-  g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
-          GST_TUNER_CHANNEL_FREQUENCY), 0);
-  g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement,
-          v4lchannel), 0);
-
-  gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
-  if (chan == GST_V4L_TUNER_CHANNEL (channel)->index &&
-      GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
-    gst_v4l_get_signal (v4lelement, v4lchannel->tuner, &signal);
-  }
-
-  return (gint) signal;
-}
--- a/gst_plugins_base/sys/v4l/gstv4ltuner.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* GStreamer
- *
- * gstv4ltuner.h: tuner interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4L_TUNER_H__
-#define __GST_V4L_TUNER_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/tuner.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4L_TUNER_CHANNEL \
-  (gst_v4l_tuner_channel_get_type ())
-#define GST_V4L_TUNER_CHANNEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_TUNER_CHANNEL, \
-                               GstV4lTunerChannel))
-#define GST_V4L_TUNER_CHANNEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_TUNER_CHANNEL, \
-                            GstV4lTunerChannelClass))
-#define GST_IS_V4L_TUNER_CHANNEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_TUNER_CHANNEL))
-#define GST_IS_V4L_TUNER_CHANNEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_TUNER_CHANNEL))
-
-typedef struct _GstV4lTunerChannel {
-  GstTunerChannel parent;
-
-  gint            index;
-  gint            tuner;
-  gint            audio;
-} GstV4lTunerChannel;
-
-typedef struct _GstV4lTunerChannelClass {
-  GstTunerChannelClass parent;
-} GstV4lTunerChannelClass;
-
-#define GST_TYPE_V4L_TUNER_NORM \
-  (gst_v4l_tuner_norm_get_type ())
-#define GST_V4L_TUNER_NORM(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_TUNER_NORM, \
-                               GstV4lTunerNorm))
-#define GST_V4L_TUNER_NORM_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_TUNER_NORM, \
-                            GstV4lTunerNormClass))
-#define GST_IS_V4L_TUNER_NORM(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_TUNER_NORM))
-#define GST_IS_V4L_TUNER_NORM_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_TUNER_NORM))
-
-typedef struct _GstV4lTunerNorm {
-  GstTunerNorm parent;
-
-  gint         index;
-} GstV4lTunerNorm;
-
-typedef struct _GstV4lTunerNormClass {
-  GstTunerNormClass parent;
-} GstV4lTunerNormClass;
-
-GType   gst_v4l_tuner_channel_get_type  (void);
-GType   gst_v4l_tuner_norm_get_type     (void);
-
-void    gst_v4l_tuner_interface_init    (GstTunerClass *klass);
-
-#endif /* __GST_V4L_TUNER_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lxoverlay.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/* GStreamer
- *
- * gstv4lxoverlay.c: X-based overlay interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <sys/stat.h>
-
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-
-#include "gstv4lxoverlay.h"
-#include "gstv4lelement.h"
-#include "v4l_calls.h"
-
-GST_DEBUG_CATEGORY_STATIC (v4lxv_debug);
-#define GST_CAT_DEFAULT v4lxv_debug
-
-struct _GstV4lXv
-{
-  Display *dpy;
-  gint port, idle_id;
-  GMutex *mutex;
-};
-
-static void gst_v4l_xoverlay_set_xwindow_id (GstXOverlay * overlay,
-    XID xwindow_id);
-
-void
-gst_v4l_xoverlay_interface_init (GstXOverlayClass * klass)
-{
-  /* default virtual functions */
-  klass->set_xwindow_id = gst_v4l_xoverlay_set_xwindow_id;
-
-  GST_DEBUG_CATEGORY_INIT (v4lxv_debug, "v4lxv", 0,
-      "V4L XOverlay interface debugging");
-}
-
-static void
-gst_v4l_xoverlay_open (GstV4lElement * v4lelement)
-{
-  struct stat s;
-  GstV4lXv *v4lxv;
-  const gchar *name = g_getenv ("DISPLAY");
-  unsigned int ver, rel, req, ev, err, anum;
-  int i, id = 0, first_id = 0, min;
-  XvAdaptorInfo *ai;
-  Display *dpy;
-
-  /* we need a display, obviously */
-  if (!name || !(dpy = XOpenDisplay (name))) {
-    GST_WARNING ("No $DISPLAY set or failed to open - no overlay");
-    return;
-  }
-
-  /* First let's check that XVideo extension is available */
-  if (!XQueryExtension (dpy, "XVideo", &i, &i, &i)) {
-    GST_WARNING ("Xv extension not available - no overlay");
-    XCloseDisplay (dpy);
-    return;
-  }
-
-  /* find port that belongs to this device */
-  if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) {
-    GST_WARNING ("Xv extension not supported - no overlay");
-    XCloseDisplay (dpy);
-    return;
-  }
-  if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &anum, &ai) != Success) {
-    GST_WARNING ("Failed to query Xv adaptors");
-    XCloseDisplay (dpy);
-    return;
-  }
-  if (fstat (v4lelement->video_fd, &s) < 0) {
-    GST_ERROR ("Failed to stat() file descriptor: %s", g_strerror (errno));
-    XCloseDisplay (dpy);
-    return;
-  }
-  min = s.st_rdev & 0xff;
-  for (i = 0; i < anum; i++) {
-    if (!strcmp (ai[i].name, "video4linux")) {
-      if (first_id == 0)
-        first_id = ai[i].base_id;
-
-      /* hmm... */
-      if (first_id != 0 && ai[i].base_id == first_id + min)
-        id = ai[i].base_id;
-    }
-  }
-  XvFreeAdaptorInfo (ai);
-
-  if (id == 0) {
-    GST_WARNING ("Did not find XvPortID for device - no overlay");
-    XCloseDisplay (dpy);
-    return;
-  }
-
-  v4lxv = g_new0 (GstV4lXv, 1);
-  v4lxv->dpy = dpy;
-  v4lxv->port = id;
-  v4lxv->mutex = g_mutex_new ();
-  v4lxv->idle_id = 0;
-  v4lelement->xv = v4lxv;
-
-  if (v4lelement->xwindow_id) {
-    gst_v4l_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4lelement),
-        v4lelement->xwindow_id);
-  }
-}
-
-static void
-gst_v4l_xoverlay_close (GstV4lElement * v4lelement)
-{
-  GstV4lXv *v4lxv = v4lelement->xv;
-
-  if (!v4lelement->xv)
-    return;
-
-  if (v4lelement->xwindow_id) {
-    gst_v4l_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4lelement), 0);
-  }
-
-  XCloseDisplay (v4lxv->dpy);
-  g_mutex_free (v4lxv->mutex);
-  if (v4lxv->idle_id)
-    g_source_remove (v4lxv->idle_id);
-  g_free (v4lxv);
-  v4lelement->xv = NULL;
-}
-
-void
-gst_v4l_xoverlay_start (GstV4lElement * v4lelement)
-{
-  if (v4lelement->xwindow_id) {
-    gst_v4l_xoverlay_open (v4lelement);
-  }
-}
-
-void
-gst_v4l_xoverlay_stop (GstV4lElement * v4lelement)
-{
-  gst_v4l_xoverlay_close (v4lelement);
-}
-
-static gboolean
-idle_refresh (gpointer data)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (data);
-  GstV4lXv *v4lxv = v4lelement->xv;
-  XWindowAttributes attr;
-
-  if (v4lxv) {
-    g_mutex_lock (v4lxv->mutex);
-
-    XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
-    XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
-        DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
-        0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
-
-    v4lxv->idle_id = 0;
-    g_mutex_unlock (v4lxv->mutex);
-  }
-
-  /* once */
-  return FALSE;
-}
-
-static void
-gst_v4l_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
-  GstV4lElement *v4lelement = GST_V4LELEMENT (overlay);
-  GstV4lXv *v4lxv;
-  XWindowAttributes attr;
-  gboolean change = (v4lelement->xwindow_id != xwindow_id);
-
-  GST_LOG_OBJECT (v4lelement, "Changing port to %lx", xwindow_id);
-
-  if (!v4lelement->xv && GST_V4L_IS_OPEN (v4lelement))
-    gst_v4l_xoverlay_open (v4lelement);
-
-  v4lxv = v4lelement->xv;
-
-  if (v4lxv)
-    g_mutex_lock (v4lxv->mutex);
-
-  if (change) {
-    if (v4lelement->xwindow_id && v4lxv) {
-      GST_DEBUG_OBJECT (v4lelement,
-          "Disabling port %lx", v4lelement->xwindow_id);
-
-      XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 0);
-      XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 0);
-      XvStopVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id);
-    }
-
-    v4lelement->xwindow_id = xwindow_id;
-  }
-
-  if (!v4lxv || xwindow_id == 0) {
-    if (v4lxv)
-      g_mutex_unlock (v4lxv->mutex);
-    return;
-  }
-
-  if (change) {
-    GST_DEBUG_OBJECT (v4lelement, "Enabling port %lx", xwindow_id);
-
-    /* draw */
-    XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 1);
-    XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 1);
-  }
-
-  XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
-  XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
-      DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
-      0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
-
-  if (v4lxv->idle_id)
-    g_source_remove (v4lxv->idle_id);
-  v4lxv->idle_id = g_idle_add (idle_refresh, v4lelement);
-  g_mutex_unlock (v4lxv->mutex);
-}
--- a/gst_plugins_base/sys/v4l/gstv4lxoverlay.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/* GStreamer
- *
- * gstv4lxoverlay.h: tv mixer interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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_V4L_X_OVERLAY_H__
-#define __GST_V4L_X_OVERLAY_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/xoverlay.h>
-
-#include "gstv4lelement.h"
-
-G_BEGIN_DECLS
-
-void    gst_v4l_xoverlay_interface_init (GstXOverlayClass *klass);
-
-void    gst_v4l_xoverlay_start          (GstV4lElement * v4lelement);
-void    gst_v4l_xoverlay_stop           (GstV4lElement * v4lelement);
-
-G_END_DECLS
-
-#endif /* __GST_V4L_X_OVERLAY_H__ */
--- a/gst_plugins_base/sys/v4l/v4l_calls.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,723 +0,0 @@
-/* GStreamer
- *
- * v4l_calls.c: generic V4L calls
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <gst/gst.h>
-#include <gst/interfaces/tuner.h>
-#include <gst/interfaces/colorbalance.h>
-
-#include "v4l_calls.h"
-#include "gstv4ltuner.h"
-#include "gstv4lcolorbalance.h"
-
-#include "gstv4lsrc.h"
-/* #include "gstv4lmjpegsrc.h" */
-/* #include "gstv4lmjpegsink.h" */
-
-GST_DEBUG_CATEGORY_EXTERN (v4l_debug);
-#define GST_CAT_DEFAULT v4l_debug
-
-static const char *picture_name[] = {
-  "Hue",
-  "Brightness",
-  "Contrast",
-  "Saturation",
-  NULL
-};
-
-G_GNUC_UNUSED static const char *audio_name[] = {
-  "Volume",
-  "Mute",
-  "Mode",
-  NULL
-};
-
-static const char *norm_name[] = {
-  "PAL",
-  "NTSC",
-  "SECAM",
-  NULL
-};
-
-/******************************************************
- * gst_v4l_get_capabilities():
- *   get the device's capturing capabilities
- * sets v4lelement->vcap and v4lelement->vwin
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_capabilities (GstV4lElement * v4lelement)
-{
-  GST_DEBUG_OBJECT (v4lelement, "getting capabilities");
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  if (ioctl (v4lelement->video_fd, VIDIOCGCAP, &(v4lelement->vcap)) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("error getting capabilities %s of from device %s",
-            g_strerror (errno), v4lelement->videodev));
-    return FALSE;
-  }
-
-  if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(v4lelement->vwin)) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("error getting window properties %s of from device %s",
-            g_strerror (errno), v4lelement->videodev));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4l_set_window_properties():
- *   set the device's capturing parameters (vwin)
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_window_properties (GstV4lElement * v4lelement)
-{
-  struct video_window vwin;
-
-  GST_DEBUG_OBJECT (v4lelement, "setting window flags 0x%x to device %s",
-      v4lelement->vwin.flags, v4lelement->videodev);
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  if (ioctl (v4lelement->video_fd, VIDIOCSWIN, &(v4lelement->vwin)) < 0) {
-    GST_DEBUG_OBJECT (v4lelement,
-        "could not ioctl window properties 0x%x to device %s",
-        v4lelement->vwin.flags, v4lelement->videodev);
-    return FALSE;
-  }
-
-  /* get it again to make sure we have it correctly */
-  if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(vwin)) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("error getting window properties %s of from device %s",
-            g_strerror (errno), v4lelement->videodev));
-    return FALSE;
-  }
-  if (vwin.flags != v4lelement->vwin.flags) {
-    GST_DEBUG_OBJECT (v4lelement, "set 0x%x but got 0x%x back",
-        v4lelement->vwin.flags, vwin.flags);
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4l_open():
- *   open the video device (v4lelement->videodev)
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_open (GstV4lElement * v4lelement)
-{
-  int num;
-
-  GST_DEBUG_OBJECT (v4lelement, "opening device %s", v4lelement->videodev);
-  GST_V4L_CHECK_NOT_OPEN (v4lelement);
-  GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
-
-  /* be sure we have a device */
-  if (!v4lelement->videodev) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND,
-        (_("No device specified.")), (NULL));
-    return FALSE;
-  }
-
-  /* open the device */
-  v4lelement->video_fd = open (v4lelement->videodev, O_RDWR);
-  if (!GST_V4L_IS_OPEN (v4lelement)) {
-    if (errno == ENODEV || errno == ENOENT) {
-      GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND,
-          (_("Device \"%s\" does not exist."), v4lelement->videodev), (NULL));
-      return FALSE;
-    }
-    if (errno == EBUSY) {
-      GST_ELEMENT_ERROR (v4lelement, RESOURCE, BUSY,
-          (_("Device \"%s\" is already being used."), v4lelement->videodev),
-          (NULL));
-      return FALSE;
-    }
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, OPEN_READ_WRITE,
-        (_("Could not open device \"%s\" for reading and writing."),
-            v4lelement->videodev), GST_ERROR_SYSTEM);
-    return FALSE;
-  }
-
-  /* get capabilities */
-  if (!gst_v4l_get_capabilities (v4lelement)) {
-    close (v4lelement->video_fd);
-    v4lelement->video_fd = -1;
-    return FALSE;
-  }
-
-  /* device type check */
-  if ((GST_IS_V4LSRC (v4lelement) &&
-          !(v4lelement->vcap.type & VID_TYPE_CAPTURE))) {
-/*       (GST_IS_V4LMJPEGSRC (v4lelement) && */
-/*           !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) || */
-/*       (GST_IS_V4LMJPEGSINK (v4lelement) && */
-/*           !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) { */
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Device opened, but wrong type (0x%x)", v4lelement->vcap.type));
-    close (v4lelement->video_fd);
-    v4lelement->video_fd = -1;
-    return FALSE;
-  }
-
-  GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully",
-      v4lelement->vcap.name, v4lelement->videodev);
-
-  /* norms + inputs, for the tuner interface */
-  for (num = 0; norm_name[num] != NULL; num++) {
-    GstV4lTunerNorm *v4lnorm = g_object_new (GST_TYPE_V4L_TUNER_NORM,
-        NULL);
-    GstTunerNorm *norm = GST_TUNER_NORM (v4lnorm);
-
-    norm->label = g_strdup (norm_name[num]);
-    if (num == 1)
-      gst_value_set_fraction (&norm->framerate, 30000, 1001);
-    else
-      gst_value_set_fraction (&norm->framerate, 25, 1);
-
-    v4lnorm->index = num;
-    v4lelement->norms = g_list_append (v4lelement->norms, (gpointer) norm);
-  }
-  v4lelement->channels = gst_v4l_get_chan_names (v4lelement);
-
-  for (num = 0; picture_name[num] != NULL; num++) {
-    GstV4lColorBalanceChannel *v4lchannel =
-        g_object_new (GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, NULL);
-    GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (v4lchannel);
-
-    channel->label = g_strdup (picture_name[num]);
-    channel->min_value = 0;
-    channel->max_value = 65535;
-    v4lchannel->index = num;
-    v4lelement->colors = g_list_append (v4lelement->colors, channel);
-  }
-
-  GST_DEBUG_OBJECT (v4lelement, "Setting default norm/input");
-  gst_v4l_set_chan_norm (v4lelement, 0, 0);
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_close():
- *   close the video device (v4lelement->video_fd)
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_close (GstV4lElement * v4lelement)
-{
-  GST_DEBUG_OBJECT (v4lelement, "closing device");
-  GST_V4L_CHECK_OPEN (v4lelement);
-  GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
-
-  close (v4lelement->video_fd);
-  v4lelement->video_fd = -1;
-
-  g_list_foreach (v4lelement->channels, (GFunc) g_object_unref, NULL);
-  g_list_free (v4lelement->channels);
-  v4lelement->channels = NULL;
-
-  g_list_foreach (v4lelement->norms, (GFunc) g_object_unref, NULL);
-  g_list_free (v4lelement->norms);
-  v4lelement->norms = NULL;
-
-  g_list_foreach (v4lelement->colors, (GFunc) g_object_unref, NULL);
-  g_list_free (v4lelement->colors);
-  v4lelement->colors = NULL;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_num_chans()
- * return value: the number of video input channels
- ******************************************************/
-
-static gint
-gst_v4l_get_num_chans (GstV4lElement * v4lelement)
-{
-  GST_DEBUG_OBJECT (v4lelement, "getting number of channels");
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  return v4lelement->vcap.channels;
-}
-
-
-/******************************************************
- * gst_v4l_get_chan_names()
- * return value: a GList containing the channel names
- ******************************************************/
-
-GList *
-gst_v4l_get_chan_names (GstV4lElement * v4lelement)
-{
-  struct video_channel vchan;
-  GList *list = NULL;
-  gint i;
-
-  GST_DEBUG_OBJECT (v4lelement, "getting channel names");
-
-  if (!GST_V4L_IS_OPEN (v4lelement))
-    return NULL;
-
-  for (i = 0; i < gst_v4l_get_num_chans (v4lelement); i++) {
-    GstV4lTunerChannel *v4lchannel = g_object_new (GST_TYPE_V4L_TUNER_CHANNEL,
-        NULL);
-    GstTunerChannel *channel = GST_TUNER_CHANNEL (v4lchannel);
-
-    vchan.channel = i;
-    if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
-      return NULL;              /* memleak... */
-    channel->label = g_strdup (vchan.name);
-    channel->flags = GST_TUNER_CHANNEL_INPUT;
-    v4lchannel->index = i;
-    if (vchan.flags & VIDEO_VC_TUNER) {
-      struct video_tuner vtun;
-      gint n;
-
-      for (n = 0;; n++) {
-        if (n >= vchan.tuners) {
-          vtun.tuner = 0;       /* default */
-        } else {
-          vtun.tuner = n;
-          if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
-            continue;           /* no more tuners */
-          if (strcmp (vtun.name, vchan.name) != 0) {
-            continue;           /* not this one */
-          }
-        }
-        v4lchannel->tuner = n;
-        channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
-        channel->freq_multiplicator =
-            62.5 * ((vtun.flags & VIDEO_TUNER_LOW) ? 1 : 1000);
-        channel->min_frequency = vtun.rangelow;
-        channel->max_frequency = vtun.rangehigh;
-        channel->min_signal = 0;
-        channel->max_signal = 0xffff;
-        break;
-      }
-
-    }
-    if (vchan.flags & VIDEO_VC_AUDIO) {
-      struct video_audio vaud;
-      gint n;
-
-      for (n = 0; n < v4lelement->vcap.audios; n++) {
-        vaud.audio = n;
-        if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vaud) < 0)
-          continue;
-        if (!strcmp (vaud.name, vchan.name)) {
-          v4lchannel->audio = n;
-          channel->flags |= GST_TUNER_CHANNEL_AUDIO;
-          break;
-        }
-      }
-    }
-    list = g_list_append (list, (gpointer) channel);
-  }
-
-  return list;
-}
-
-
-/******************************************************
- * gst_v4l_get_chan_norm():
- *   get the currently active video-channel and it's
- *   norm (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_chan_norm (GstV4lElement * v4lelement, gint * channel, gint * norm)
-{
-  GST_DEBUG_OBJECT (v4lelement, "getting current channel and norm");
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  if (channel)
-    *channel = v4lelement->vchan.channel;
-  if (norm)
-    *norm = v4lelement->vchan.norm;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_chan_norm():
- *   set a new active channel and it's norm
- *   (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_chan_norm (GstV4lElement * v4lelement, gint channel, gint norm)
-{
-  GST_DEBUG_OBJECT (v4lelement, "setting channel = %d, norm = %d (%s)",
-      channel, norm, norm_name[norm]);
-  GST_V4L_CHECK_OPEN (v4lelement);
-  //GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
-
-  v4lelement->vchan.channel = channel;
-  v4lelement->vchan.norm = norm;
-
-  if (ioctl (v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error setting the channel/norm settings: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting the channel/norm settings: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_signal():
- *   get the current signal
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_signal (GstV4lElement * v4lelement, gint tunernum, guint * signal)
-{
-  struct video_tuner tuner;
-
-  GST_DEBUG_OBJECT (v4lelement, "getting tuner signal");
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  tuner.tuner = tunernum;
-  if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &tuner) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting tuner signal: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  *signal = tuner.signal;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_frequency():
- *   get the current frequency
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_frequency (GstV4lElement * v4lelement,
-    gint tunernum, gulong * frequency)
-{
-  struct video_tuner vtun;
-  GstTunerChannel *channel;
-
-  GST_DEBUG_OBJECT (v4lelement, "getting tuner frequency");
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  channel = gst_tuner_get_channel (GST_TUNER (v4lelement));
-
-  /* check that this is the current input */
-  vtun.tuner = tunernum;
-  if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
-    return FALSE;
-  if (strcmp (vtun.name, v4lelement->vchan.name))
-    return FALSE;
-
-  if (ioctl (v4lelement->video_fd, VIDIOCGFREQ, frequency) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting tuner frequency: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  *frequency = *frequency * channel->freq_multiplicator;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_frequency():
- *   set frequency
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_frequency (GstV4lElement * v4lelement,
-    gint tunernum, gulong frequency)
-{
-  struct video_tuner vtun;
-  GstTunerChannel *channel;
-
-  GST_DEBUG_OBJECT (v4lelement, "setting tuner frequency to %lu", frequency);
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  channel = gst_tuner_get_channel (GST_TUNER (v4lelement));
-
-  /* check that this is the current input */
-  vtun.tuner = tunernum;
-  if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
-    return FALSE;
-  if (strcmp (vtun.name, v4lelement->vchan.name))
-    return FALSE;
-
-  frequency = frequency / channel->freq_multiplicator;
-
-  if (ioctl (v4lelement->video_fd, VIDIOCSFREQ, &frequency) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error setting tuner frequency: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_picture():
- *   get a picture value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_picture (GstV4lElement * v4lelement,
-    GstV4lPictureType type, gint * value)
-{
-  struct video_picture vpic;
-
-  GST_DEBUG_OBJECT (v4lelement, "getting picture property type %d (%s)", type,
-      picture_name[type]);
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting picture parameters: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  switch (type) {
-    case V4L_PICTURE_HUE:
-      *value = vpic.hue;
-      break;
-    case V4L_PICTURE_BRIGHTNESS:
-      *value = vpic.brightness;
-      break;
-    case V4L_PICTURE_CONTRAST:
-      *value = vpic.contrast;
-      break;
-    case V4L_PICTURE_SATURATION:
-      *value = vpic.colour;
-      break;
-    default:
-      GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-          ("Error getting picture parameters: unknown type %d", type));
-      return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_picture():
- *   set a picture value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_picture (GstV4lElement * v4lelement,
-    GstV4lPictureType type, gint value)
-{
-  struct video_picture vpic;
-
-  GST_DEBUG_OBJECT (v4lelement, "setting picture type %d (%s) to value %d",
-      type, picture_name[type], value);
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting picture parameters: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  switch (type) {
-    case V4L_PICTURE_HUE:
-      vpic.hue = value;
-      break;
-    case V4L_PICTURE_BRIGHTNESS:
-      vpic.brightness = value;
-      break;
-    case V4L_PICTURE_CONTRAST:
-      vpic.contrast = value;
-      break;
-    case V4L_PICTURE_SATURATION:
-      vpic.colour = value;
-      break;
-    default:
-      GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-          ("Error setting picture parameters: unknown type %d", type));
-      return FALSE;
-  }
-
-  if (ioctl (v4lelement->video_fd, VIDIOCSPICT, &vpic) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error setting picture parameters: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_audio():
- *   get some audio value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_audio (GstV4lElement * v4lelement,
-    gint audionum, GstV4lAudioType type, gint * value)
-{
-  struct video_audio vau;
-
-  GST_DEBUG_OBJECT (v4lelement, "getting audio parameter type %d (%s)", type,
-      audio_name[type]);
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  vau.audio = audionum;
-  if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting audio parameters: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  switch (type) {
-    case V4L_AUDIO_MUTE:
-      *value = (vau.flags & VIDEO_AUDIO_MUTE);
-      break;
-    case V4L_AUDIO_VOLUME:
-      *value = vau.volume;
-      break;
-    case V4L_AUDIO_MODE:
-      *value = vau.mode;
-      break;
-    default:
-      GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-          ("Error getting audio parameters: unknown type %d", type));
-      return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_audio():
- *   set some audio value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_audio (GstV4lElement * v4lelement,
-    gint audionum, GstV4lAudioType type, gint value)
-{
-  struct video_audio vau;
-
-  GST_DEBUG_OBJECT (v4lelement,
-      "setting audio parameter type %d (%s) to value %d", type,
-      audio_name[type], value);
-  GST_V4L_CHECK_OPEN (v4lelement);
-
-  vau.audio = audionum;
-  if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error getting audio parameters: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  switch (type) {
-    case V4L_AUDIO_MUTE:
-      if (!(vau.flags & VIDEO_AUDIO_MUTABLE)) {
-        GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL),
-            ("Error setting audio mute: (un)setting mute is not supported"));
-        return FALSE;
-      }
-      if (value)
-        vau.flags |= VIDEO_AUDIO_MUTE;
-      else
-        vau.flags &= ~VIDEO_AUDIO_MUTE;
-      break;
-    case V4L_AUDIO_VOLUME:
-      if (!(vau.flags & VIDEO_AUDIO_VOLUME)) {
-        GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL),
-            ("Error setting audio volume: setting volume is not supported"));
-        return FALSE;
-      }
-      vau.volume = value;
-      break;
-    case V4L_AUDIO_MODE:
-      vau.mode = value;
-      break;
-    default:
-      GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-          ("Error setting audio parameters: unknown type %d", type));
-      return FALSE;
-  }
-
-  if (ioctl (v4lelement->video_fd, VIDIOCSAUDIO, &vau) < 0) {
-    GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
-        ("Error setting audio parameters: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  return TRUE;
-}
--- a/gst_plugins_base/sys/v4l/v4l_calls.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/* GStreamer
- *
- * v4l_calls.h: header for generic V4L calls
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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 __V4L_CALLS_H__
-#define __V4L_CALLS_H__
-
-#include "gstv4lelement.h"
-#include "gst/gst-i18n-plugin.h"
-
-
-G_BEGIN_DECLS
-
-
-/* simple check whether the device is open */
-#define GST_V4L_IS_OPEN(element) \
-  (GST_V4LELEMENT (element)->video_fd > 0)
-
-/* check whether the device is 'active' */
-#define GST_V4L_IS_ACTIVE(element) \
-  (GST_V4LELEMENT (element)->buffer != NULL)
-
-#define GST_V4L_IS_OVERLAY(element) \
-  (GST_V4LELEMENT (element)->vcap.type & VID_TYPE_OVERLAY)
-
-/* checks whether the current v4lelement has already been open()'ed or not */
-#define GST_V4L_CHECK_OPEN(element)                             \
-  if (!GST_V4L_IS_OPEN (element))                               \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,             \
-      (_("Device is not open.")), (NULL));                      \
-    return FALSE;                                               \
-  }
-
-/* checks whether the current v4lelement is close()'ed or whether it is still open */
-#define GST_V4L_CHECK_NOT_OPEN(element)                         \
-  if (GST_V4L_IS_OPEN (element))                                \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,             \
-      (_("Device is open.")), (NULL));                          \
-    return FALSE;                                               \
-  }
-
-/* checks whether the current v4lelement does video overlay */
-#define GST_V4L_CHECK_OVERLAY(element)                          \
-  if (!(element->vcap.type & VID_TYPE_OVERLAY))                 \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,             \
-      (NULL), ("Device cannot handle overlay"));                \
-    return FALSE;                                               \
-  }
-
-/* checks whether we're in capture mode or not */
-#define GST_V4L_CHECK_ACTIVE(element)                           \
-  if (!GST_V4L_IS_ACTIVE (element))                             \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS,             \
-      (NULL), ("Device is not in streaming mode"));             \
-    return FALSE;                                               \
-  }
-
-/* checks whether we're out of capture mode or not */
-#define GST_V4L_CHECK_NOT_ACTIVE(element)                       \
-  if (GST_V4L_IS_ACTIVE (element))                              \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS,             \
-      (NULL), ("Device is in streaming mode"));                 \
-    return FALSE;                                               \
-  }
-
-
-typedef enum {
-  V4L_PICTURE_HUE = 0,
-  V4L_PICTURE_BRIGHTNESS,
-  V4L_PICTURE_CONTRAST,
-  V4L_PICTURE_SATURATION,
-} GstV4lPictureType;
-
-typedef enum {
-  V4L_AUDIO_VOLUME = 0,
-  V4L_AUDIO_MUTE,
-  V4L_AUDIO_MODE, /* stereo, mono, ... (see videodev.h) */
-} GstV4lAudioType;
-
-
-/* open/close the device */
-gboolean gst_v4l_open           (GstV4lElement *v4lelement);
-gboolean gst_v4l_close          (GstV4lElement *v4lelement);
-
-/* norm control (norm = VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) */
-gboolean gst_v4l_get_chan_norm  (GstV4lElement *v4lelement,
-                                 gint          *channel,
-                                 gint          *norm);
-gboolean gst_v4l_set_chan_norm  (GstV4lElement *v4lelement,
-                                 gint           channel,
-                                 gint           norm);
-GList   *gst_v4l_get_chan_names (GstV4lElement *v4lelement);
-
-/* frequency control */
-gboolean gst_v4l_get_signal     (GstV4lElement *v4lelement,
-                                 gint           tunernum,
-                                 guint         *signal);
-gboolean gst_v4l_get_frequency  (GstV4lElement *v4lelement,
-                                 gint           tunernum,
-                                 gulong        *frequency);
-gboolean gst_v4l_set_frequency  (GstV4lElement *v4lelement,
-                                 gint           tunernum,
-                                 gulong         frequency);
-
-/* picture control */
-gboolean gst_v4l_get_picture    (GstV4lElement *v4lelement,
-                                 GstV4lPictureType type,
-                                 gint          *value);
-gboolean gst_v4l_set_picture    (GstV4lElement *v4lelement,
-                                 GstV4lPictureType type,
-                                 gint           value);
-
-/* audio control */
-gboolean gst_v4l_get_audio      (GstV4lElement *v4lelement,
-                                 gint           audionum,
-                                 GstV4lAudioType type,
-                                 gint          *value);
-gboolean gst_v4l_set_audio      (GstV4lElement *v4lelement,
-                                 gint           audionum,
-                                 GstV4lAudioType type,
-                                 gint           value);
-
-/* functions that v4lsrc needs */
-gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement);
-gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement);
-
-
-G_END_DECLS
-
-
-#endif /* __V4L_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/v4lmjpegsink_calls.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* GStreamer
- *
- * v4lmjpegsink_calls.c: functions for hardware MJPEG video sink
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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 __V4L_MJPEG_SINK_CALLS_H__
-#define __V4L_MJPEG_SINK_CALLS_H__
-
-#include "gstv4lmjpegsink.h"
-#include "v4l_calls.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-/* frame playback on device */
-gboolean gst_v4lmjpegsink_set_buffer      (GstV4lMjpegSink *v4lmjpegsink,
-                                           gint            numbufs,
-                                           gint            bufsize);
-gboolean gst_v4lmjpegsink_set_playback    (GstV4lMjpegSink *v4lmjpegsink,
-                                           gint            width,
-                                           gint            height,
-                                           gint            x_offset,
-                                           gint            y_offset,
-                                           gint            norm,
-                                           gint            interlacing);
-gboolean gst_v4lmjpegsink_playback_init   (GstV4lMjpegSink *v4lmjpegsink);
-gboolean gst_v4lmjpegsink_playback_start  (GstV4lMjpegSink *v4lmjpegsink);
-guint8 * gst_v4lmjpegsink_get_buffer      (GstV4lMjpegSink *v4lmjpegsink,
-                                           gint            num);
-gboolean gst_v4lmjpegsink_play_frame      (GstV4lMjpegSink *v4lmjpegsink,
-                                           gint            num);
-gboolean gst_v4lmjpegsink_wait_frame      (GstV4lMjpegSink *v4lmjpegsink,
-                                           gint            *num);
-gboolean gst_v4lmjpegsink_playback_stop   (GstV4lMjpegSink *v4lmjpegsink);
-gboolean gst_v4lmjpegsink_playback_deinit (GstV4lMjpegSink *v4lmjpegsink);
-
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __V4L_MJPEG_SINK_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/v4lmjpegsrc_calls.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* GStreamer
- *
- * v4lmjpegsrc_calls.h: functions for hardware MJPEG video source
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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 __V4L_MJPEG_SRC_CALLS_H__
-#define __V4L_MJPEG_SRC_CALLS_H__
-
-#include "gstv4lmjpegsrc.h"
-#include "v4l_calls.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-/* frame grabbing/capture */
-gboolean gst_v4lmjpegsrc_set_buffer     (GstV4lMjpegSrc *v4lmjpegsrc,
-                                         gint           numbufs,
-                                         gint           bufsize);
-gboolean gst_v4lmjpegsrc_set_capture    (GstV4lMjpegSrc *v4lmjpegsrc,
-                                         gint           decimation,
-                                         gint           quality);
-gboolean gst_v4lmjpegsrc_set_capture_m  (GstV4lMjpegSrc *v4lmjpegsrc,
-                                         gint           x_offset,
-                                         gint           y_offset,
-                                         gint           width,
-                                         gint           height,
-                                         gint           h_decimation,
-                                         gint           v_decimation,
-                                         gint           quality);
-gboolean gst_v4lmjpegsrc_capture_init   (GstV4lMjpegSrc *v4lmjpegsrc);
-gboolean gst_v4lmjpegsrc_capture_start  (GstV4lMjpegSrc *v4lmjpegsrc);
-gboolean gst_v4lmjpegsrc_grab_frame     (GstV4lMjpegSrc *v4lmjpegsrc,
-                                         gint           *num,
-                                         gint           *size);
-guint8 * gst_v4lmjpegsrc_get_buffer     (GstV4lMjpegSrc *v4lmjpegsrc,
-                                         gint           num);
-gboolean gst_v4lmjpegsrc_requeue_frame  (GstV4lMjpegSrc *v4lmjpegsrc,
-                                         gint           num);
-gboolean gst_v4lmjpegsrc_capture_stop   (GstV4lMjpegSrc *v4lmjpegsrc);
-gboolean gst_v4lmjpegsrc_capture_deinit (GstV4lMjpegSrc *v4lmjpegsrc);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __V4L_MJPEG_SRC_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/v4lsrc_calls.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,740 +0,0 @@
-/* GStreamer
- *
- * v4lsrc_calls.c: generic V4L source functions
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <errno.h>
-#include "v4lsrc_calls.h"
-#include <sys/time.h>
-
-/* number of buffers to be queued *at least* before syncing */
-#define MIN_BUFFERS_QUEUED 2
-
-/* On some systems MAP_FAILED seems to be missing */
-#ifndef MAP_FAILED
-#define MAP_FAILED ( (caddr_t) -1 )
-#endif
-
-GST_DEBUG_CATEGORY_EXTERN (v4l_debug);
-
-#define GST_CAT_DEFAULT v4l_debug
-
-#ifndef GST_DISABLE_GST_DEBUG
-/* palette names */
-static const char *v4l_palette_name[] = {
-  "",                           /* 0 */
-  "grayscale",                  /* VIDEO_PALETTE_GREY */
-  "Hi-420",                     /* VIDEO_PALETTE_HI420 */
-  "16-bit RGB (RGB-565)",       /* VIDEO_PALETTE_RB565 */
-  "24-bit RGB",                 /* VIDEO_PALETTE_RGB24 */
-  "32-bit RGB",                 /* VIDEO_PALETTE_RGB32 */
-  "15-bit RGB (RGB-555)",       /* VIDEO_PALETTE_RGB555 */
-  "YUV-4:2:2 (packed)",         /* VIDEO_PALETTE_YUV422 */
-  "YUYV",                       /* VIDEO_PALETTE_YUYV */
-  "UYVY",                       /* VIDEO_PALETTE_UYVY */
-  "YUV-4:2:0 (packed)",         /* VIDEO_PALETTE_YUV420 */
-  "YUV-4:1:1 (packed)",         /* VIDEO_PALETTE_YUV411 */
-  "Raw",                        /* VIDEO_PALETTE_RAW */
-  "YUV-4:2:2 (planar)",         /* VIDEO_PALETTE_YUV422P */
-  "YUV-4:1:1 (planar)",         /* VIDEO_PALETTE_YUV411P */
-  "YUV-4:2:0 (planar)/I420",    /* VIDEO_PALETTE_YUV420P */
-  "YUV-4:1:0 (planar)"          /* VIDEO_PALETTE_YUV410P */
-};
-#endif
-
-/******************************************************
- * gst_v4lsrc_queue_frame():
- *   queue a frame for capturing
- *   (ie. instruct the hardware to start capture)
- *   Requires queue_state lock to be held!
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-static gboolean
-gst_v4lsrc_queue_frame (GstV4lSrc * v4lsrc, gint num)
-{
-  GST_LOG_OBJECT (v4lsrc, "queueing frame %d", num);
-
-  if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_READY_FOR_QUEUE) {
-    return FALSE;
-  }
-
-  /* instruct the driver to prepare capture using buffer frame num */
-  v4lsrc->mmap.frame = num;
-  if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd,
-          VIDIOCMCAPTURE, &(v4lsrc->mmap)) < 0) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
-        ("Error queueing a buffer (%d): %s", num, g_strerror (errno)));
-    return FALSE;
-  }
-
-  v4lsrc->frame_queue_state[num] = QUEUE_STATE_QUEUED;
-  v4lsrc->num_queued++;
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4lsrc_hard_sync_frame(GstV4lSrc *v4lsrc,gint num)
- *   sync a frame and set the timestamp correctly
- *   Requires queue_state lock to be held
- *****************************************************/
-
-static gboolean
-gst_v4lsrc_sync_frame (GstV4lSrc * v4lsrc, gint num)
-{
-  GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d", num);
-
-  if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_QUEUED) {
-    return FALSE;
-  }
-
-  while (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &num) < 0) {
-    /* if the sync() got interrupted, we can retry */
-    if (errno != EINTR) {
-      v4lsrc->frame_queue_state[num] = QUEUE_STATE_ERROR;
-      GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM);
-      return FALSE;
-    }
-    GST_DEBUG_OBJECT (v4lsrc, "Sync got interrupted");
-  }
-  GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d done", num);
-
-  v4lsrc->frame_queue_state[num] = QUEUE_STATE_SYNCED;
-  v4lsrc->num_queued--;
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4lsrc_set_capture():
- *   set capture parameters, palette = VIDEO_PALETTE_*
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_set_capture (GstV4lSrc * v4lsrc,
-    gint width, gint height, gint palette)
-{
-  GST_DEBUG_OBJECT (v4lsrc,
-      "capture properties set to %dx%d, palette %d", width, height, palette);
-
-  v4lsrc->mmap.width = width;
-  v4lsrc->mmap.height = height;
-  v4lsrc->mmap.format = palette;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_init():
- *   initialize the capture system
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_init (GstV4lSrc * v4lsrc)
-{
-  GST_DEBUG_OBJECT (v4lsrc, "initting capture subsystem");
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  /* request the mmap buffer info:
-   * total size of mmap buffer, number of frames, offsets of frames */
-  if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF,
-          &(v4lsrc->mbuf)) < 0) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
-        ("Error getting buffer information: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  if (v4lsrc->mbuf.frames < MIN_BUFFERS_QUEUED) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
-        ("Not enough buffers. We got %d, we want at least %d",
-            v4lsrc->mbuf.frames, MIN_BUFFERS_QUEUED));
-    return FALSE;
-  }
-
-  GST_INFO_OBJECT (v4lsrc, "Got %d buffers (\'%s\') with total size %d KB",
-      v4lsrc->mbuf.frames, v4l_palette_name[v4lsrc->mmap.format],
-      v4lsrc->mbuf.size / (v4lsrc->mbuf.frames * 1024));
-
-  /* keep track of queued buffers */
-  v4lsrc->frame_queue_state = (gint8 *)
-      g_malloc (sizeof (gint8) * v4lsrc->mbuf.frames);
-
-  /* lock for the frame_state */
-  v4lsrc->mutex_queue_state = g_mutex_new ();
-  v4lsrc->cond_queue_state = g_cond_new ();
-
-  /* Map the buffers */
-  GST_V4LELEMENT (v4lsrc)->buffer = mmap (NULL, v4lsrc->mbuf.size,
-      PROT_READ | PROT_WRITE, MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0);
-  if (GST_V4LELEMENT (v4lsrc)->buffer == MAP_FAILED) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL),
-        ("Error mapping video buffers: %s", g_strerror (errno)));
-    GST_V4LELEMENT (v4lsrc)->buffer = NULL;
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_start():
- *   start streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_start (GstV4lSrc * v4lsrc)
-{
-  int n;
-
-  GST_DEBUG_OBJECT (v4lsrc, "starting capture");
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  g_mutex_lock (v4lsrc->mutex_queue_state);
-
-  v4lsrc->quit = FALSE;
-  v4lsrc->num_queued = 0;
-  v4lsrc->sync_frame = 0;
-  v4lsrc->queue_frame = 0;
-
-  /* set all buffers ready to queue, and queue captures to the device.
-   * This starts streaming capture */
-  for (n = 0; n < v4lsrc->mbuf.frames; n++) {
-    v4lsrc->frame_queue_state[n] = QUEUE_STATE_READY_FOR_QUEUE;
-    if (!gst_v4lsrc_queue_frame (v4lsrc, n)) {
-      g_mutex_unlock (v4lsrc->mutex_queue_state);
-      gst_v4lsrc_capture_stop (v4lsrc);
-      return FALSE;
-    }
-  }
-
-  v4lsrc->is_capturing = TRUE;
-  g_mutex_unlock (v4lsrc->mutex_queue_state);
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_grab_frame():
- *   capture one frame during streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_grab_frame (GstV4lSrc * v4lsrc, gint * num)
-{
-  GST_LOG_OBJECT (v4lsrc, "grabbing frame %d", *num);
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  g_mutex_lock (v4lsrc->mutex_queue_state);
-
-  /* do we have enough frames? */
-  while (v4lsrc->num_queued < MIN_BUFFERS_QUEUED ||
-      v4lsrc->frame_queue_state[v4lsrc->queue_frame] ==
-      QUEUE_STATE_READY_FOR_QUEUE) {
-    while (v4lsrc->frame_queue_state[v4lsrc->queue_frame] !=
-        QUEUE_STATE_READY_FOR_QUEUE && !v4lsrc->quit) {
-      GST_DEBUG_OBJECT (v4lsrc,
-          "Waiting for frames to become available (queued %d < minimum %d)",
-          v4lsrc->num_queued, MIN_BUFFERS_QUEUED);
-      g_cond_wait (v4lsrc->cond_queue_state, v4lsrc->mutex_queue_state);
-    }
-    if (v4lsrc->quit) {
-      g_mutex_unlock (v4lsrc->mutex_queue_state);
-      return FALSE;
-    }
-    if (!gst_v4lsrc_queue_frame (v4lsrc, v4lsrc->queue_frame)) {
-      g_mutex_unlock (v4lsrc->mutex_queue_state);
-      return FALSE;
-    }
-    v4lsrc->queue_frame = (v4lsrc->queue_frame + 1) % v4lsrc->mbuf.frames;
-  }
-
-  /* syncing on the buffer grabs it */
-  *num = v4lsrc->sync_frame;
-  if (!gst_v4lsrc_sync_frame (v4lsrc, *num)) {
-    g_mutex_unlock (v4lsrc->mutex_queue_state);
-    return FALSE;
-  }
-  v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames;
-
-  g_mutex_unlock (v4lsrc->mutex_queue_state);
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_get_buffer():
- *   get the address of the given frame number in the mmap'd buffer
- * return value: the buffer's address or NULL
- ******************************************************/
-
-guint8 *
-gst_v4lsrc_get_buffer (GstV4lSrc * v4lsrc, gint num)
-{
-  if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)) ||
-      !GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
-    return NULL;
-
-  if (num < 0 || num >= v4lsrc->mbuf.frames)
-    return NULL;
-
-  return GST_V4LELEMENT (v4lsrc)->buffer + v4lsrc->mbuf.offsets[num];
-}
-
-
-/******************************************************
- * gst_v4lsrc_requeue_frame():
- *   re-queue a frame after we're done with the buffer
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_requeue_frame (GstV4lSrc * v4lsrc, gint num)
-{
-  GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num);
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  /* mark frame as 'ready to requeue' */
-  g_mutex_lock (v4lsrc->mutex_queue_state);
-
-  if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_SYNCED) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, TOO_LAZY, (NULL),
-        ("Invalid state %d (expected %d), can't requeue",
-            v4lsrc->frame_queue_state[num], QUEUE_STATE_SYNCED));
-    return FALSE;
-  }
-
-  v4lsrc->frame_queue_state[num] = QUEUE_STATE_READY_FOR_QUEUE;
-
-  /* let an optional wait know */
-  g_cond_broadcast (v4lsrc->cond_queue_state);
-
-  g_mutex_unlock (v4lsrc->mutex_queue_state);
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_stop():
- *   stop streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_stop (GstV4lSrc * v4lsrc)
-{
-  GST_DEBUG_OBJECT (v4lsrc, "stopping capture");
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  g_mutex_lock (v4lsrc->mutex_queue_state);
-  v4lsrc->is_capturing = FALSE;
-
-  /* make an optional pending wait stop */
-  v4lsrc->quit = TRUE;
-  g_cond_broadcast (v4lsrc->cond_queue_state);
-
-  /* sync on remaining frames */
-  while (1) {
-    if (v4lsrc->frame_queue_state[v4lsrc->sync_frame] == QUEUE_STATE_QUEUED) {
-      gst_v4lsrc_sync_frame (v4lsrc, v4lsrc->sync_frame);
-      v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames;
-    } else {
-      break;
-    }
-  }
-
-  g_mutex_unlock (v4lsrc->mutex_queue_state);
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_deinit():
- *   deinitialize the capture system
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_deinit (GstV4lSrc * v4lsrc)
-{
-  GST_DEBUG_OBJECT (v4lsrc, "quitting capture subsystem");
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  /* free buffer tracker */
-  g_mutex_free (v4lsrc->mutex_queue_state);
-  v4lsrc->mutex_queue_state = NULL;
-  g_cond_free (v4lsrc->cond_queue_state);
-  v4lsrc->cond_queue_state = NULL;
-  g_free (v4lsrc->frame_queue_state);
-  v4lsrc->frame_queue_state = NULL;
-
-  /* unmap the buffer */
-  if (munmap (GST_V4LELEMENT (v4lsrc)->buffer, v4lsrc->mbuf.size) == -1) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, CLOSE, (NULL),
-        ("error munmap'ing capture buffer: %s", g_strerror (errno)));
-    return FALSE;
-  }
-  GST_V4LELEMENT (v4lsrc)->buffer = NULL;
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4lsrc_try_capture():
- *   try out a capture on the device
- *   This has to be done before initializing the
- *   actual capture system, to make sure we don't
- *   mess up anything. So we need to mini-mmap()
- *   a buffer here, queue and sync on one buffer,
- *   and unmap it.
- *   This is ugly, yes, I know - but it's a major
- *   design flaw of v4l1 that you don't know in
- *   advance which formats will be supported...
- *   This is better than "just assuming that it'll
- *   work"...
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_try_capture (GstV4lSrc * v4lsrc, gint width, gint height,
-    gint palette)
-{
-  /* so, we need a buffer and some more stuff */
-  int frame = 0;
-  guint8 *buffer;
-  struct video_mbuf vmbuf;
-  struct video_mmap vmmap;
-
-  GST_DEBUG_OBJECT (v4lsrc, "try out %dx%d, palette format %d (%s)",
-      width, height, palette, v4l_palette_name[palette]);
-  GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
-  GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
-  /* let's start by requesting a buffer and mmap()'ing it */
-  if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF, &vmbuf) < 0) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
-        ("Error getting buffer information: %s", g_strerror (errno)));
-    return FALSE;
-  }
-  /* Map the buffers */
-  buffer = mmap (NULL, vmbuf.size, PROT_READ | PROT_WRITE,
-      MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0);
-  if (buffer == MAP_FAILED) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL),
-        ("Error mapping our try-out buffer: %s", g_strerror (errno)));
-    return FALSE;
-  }
-
-  /* now that we have a buffer, let's try out our format */
-  vmmap.width = width;
-  vmmap.height = height;
-  vmmap.format = palette;
-  vmmap.frame = frame;
-  if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCMCAPTURE, &vmmap) < 0) {
-    if (errno != EINVAL)        /* our format failed! */
-      GST_ERROR_OBJECT (v4lsrc,
-          "Error queueing our try-out buffer: %s", g_strerror (errno));
-    munmap (buffer, vmbuf.size);
-    return FALSE;
-  }
-
-  if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &frame) < 0) {
-    GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM);
-    munmap (buffer, vmbuf.size);
-    return FALSE;
-  }
-
-  munmap (buffer, vmbuf.size);
-
-  /* if we got here, it worked! woohoo, the format is supported! */
-  return TRUE;
-}
-
-#ifndef GST_DISABLE_GST_DEBUG
-const char *
-gst_v4lsrc_palette_name (int i)
-{
-  return v4l_palette_name[i];
-}
-#endif
-
-gboolean
-gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc, gint * fps_n, gint * fps_d)
-{
-  gint norm;
-  gint fps_index;
-  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
-  /* check if we have vwin window properties giving a framerate,
-   * as is done for webcams
-   * See http://www.smcc.demon.nl/webcam/api.html
-   * which is used for the Philips and qce-ga drivers */
-  fps_index = (vwin->flags >> 16) & 0x3F;       /* 6 bit index for framerate */
-
-  /* webcams have a non-zero fps_index */
-  if (fps_index != 0) {
-    /* index of 16 corresponds to 15 fps */
-    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)",
-        fps_index * 15, 16, fps_index * 15.0 / 16);
-
-    if (fps_n)
-      *fps_n = fps_index * 15;
-    if (fps_d)
-      *fps_d = 16;
-
-    return TRUE;
-  }
-
-  /* removed fps estimation code here */
-
-  /* if that failed ... */
-
-  if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
-    return FALSE;
-
-  if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lsrc), NULL, &norm))
-    return FALSE;
-
-  if (norm == VIDEO_MODE_NTSC) {
-    if (fps_n)
-      *fps_n = 30000;
-    if (fps_d)
-      *fps_d = 1001;
-  } else {
-    if (fps_n)
-      *fps_n = 25;
-    if (fps_d)
-      *fps_d = 1;
-  }
-
-  return TRUE;
-}
-
-/* get a list of possible framerates
- * this is only done for webcams;
- * other devices return NULL here.
- * this function takes a LONG time to execute.
- */
-GValue *
-gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
-{
-  gint fps_index;
-  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-  GstV4lElement *v4lelement = GST_V4LELEMENT (v4lsrc);
-
-  /* check if we have vwin window properties giving a framerate,
-   * as is done for webcams
-   * See http://www.smcc.demon.nl/webcam/api.html
-   * which is used for the Philips and qce-ga drivers */
-  fps_index = (vwin->flags >> 16) & 0x3F;       /* 6 bit index for framerate */
-
-  /* webcams have a non-zero fps_index */
-  if (fps_index == 0) {
-    GST_DEBUG_OBJECT (v4lsrc, "fps_index is 0, no webcam");
-    return NULL;
-  }
-  GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index);
-
-  {
-    int i;
-    GValue *list = NULL;
-    GValue value = { 0 };
-
-    /* webcam detected, so try all framerates and return a list */
-
-    list = g_new0 (GValue, 1);
-    g_value_init (list, GST_TYPE_LIST);
-
-    /* index of 16 corresponds to 15 fps */
-    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)",
-        fps_index * 15, 16, fps_index * 15.0 / 16);
-    for (i = 0; i < 63; ++i) {
-      /* set bits 16 to 21 to 0 */
-      vwin->flags &= (0x3F00 - 1);
-      /* set bits 16 to 21 to the index */
-      vwin->flags |= i << 16;
-      if (gst_v4l_set_window_properties (v4lelement)) {
-        /* setting it succeeded.  FIXME: get it and check. */
-        g_value_init (&value, GST_TYPE_FRACTION);
-        gst_value_set_fraction (&value, i * 15, 16);
-        gst_value_list_append_value (list, &value);
-        g_value_unset (&value);
-      }
-    }
-    /* FIXME: set back the original fps_index */
-    vwin->flags &= (0x3F00 - 1);
-    vwin->flags |= fps_index << 16;
-    gst_v4l_set_window_properties (v4lelement);
-    return list;
-  }
-  return NULL;
-}
-
-#define GST_TYPE_V4LSRC_BUFFER (gst_v4lsrc_buffer_get_type())
-#define GST_IS_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4LSRC_BUFFER))
-#define GST_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4LSRC_BUFFER, GstV4lSrcBuffer))
-
-typedef struct _GstV4lSrcBuffer
-{
-  GstBuffer buffer;
-
-  GstV4lSrc *v4lsrc;
-
-  gint num;
-} GstV4lSrcBuffer;
-
-static void gst_v4lsrc_buffer_class_init (gpointer g_class,
-    gpointer class_data);
-static void gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class);
-static void gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer);
-
-static GstBufferClass *v4lbuffer_parent_class = NULL;
-
-static GType
-gst_v4lsrc_buffer_get_type (void)
-{
-  static GType _gst_v4lsrc_buffer_type;
-
-  if (G_UNLIKELY (_gst_v4lsrc_buffer_type == 0)) {
-    static const GTypeInfo v4lsrc_buffer_info = {
-      sizeof (GstBufferClass),
-      NULL,
-      NULL,
-      gst_v4lsrc_buffer_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4lSrcBuffer),
-      0,
-      gst_v4lsrc_buffer_init,
-      NULL
-    };
-    _gst_v4lsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
-        "GstV4lSrcBuffer", &v4lsrc_buffer_info, 0);
-  }
-  return _gst_v4lsrc_buffer_type;
-}
-
-static void
-gst_v4lsrc_buffer_class_init (gpointer g_class, gpointer class_data)
-{
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
-  v4lbuffer_parent_class = g_type_class_peek_parent (g_class);
-
-  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-      gst_v4lsrc_buffer_finalize;
-}
-
-static void
-gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class)
-{
-
-}
-
-static void
-gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer)
-{
-  GstV4lSrc *v4lsrc;
-  gint num;
-
-  v4lsrc = v4lsrc_buffer->v4lsrc;
-  num = v4lsrc_buffer->num;
-
-  GST_LOG_OBJECT (v4lsrc, "freeing buffer %p for frame %d", v4lsrc_buffer, num);
-
-  /* only requeue if we still have an mmap buffer */
-  if (GST_V4LELEMENT (v4lsrc)->buffer) {
-    GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num);
-    gst_v4lsrc_requeue_frame (v4lsrc, num);
-  }
-
-  gst_object_unref (v4lsrc);
-
-  GST_MINI_OBJECT_CLASS (v4lbuffer_parent_class)->
-      finalize (GST_MINI_OBJECT (v4lsrc_buffer));
-}
-
-/* Create a V4lSrc buffer from our mmap'd data area */
-GstBuffer *
-gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
-{
-  GstBuffer *buf;
-  gint fps_n, fps_d;
-  GstClockTime duration, timestamp, latency;
-
-  GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
-
-  g_return_val_if_fail (gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d), NULL);
-
-  buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4LSRC_BUFFER);
-
-  GST_V4LSRC_BUFFER (buf)->num = num;
-  GST_V4LSRC_BUFFER (buf)->v4lsrc = gst_object_ref (v4lsrc);
-
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
-  GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
-  GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
-  GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
-
-  duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
-  latency = duration;
-
-  timestamp = gst_clock_get_time (GST_ELEMENT_CAST (v4lsrc)->clock);
-  timestamp -= gst_element_get_base_time (GST_ELEMENT_CAST (v4lsrc));
-  if (timestamp > latency)
-    timestamp -= latency;
-  else
-    timestamp = 0;
-
-  GST_BUFFER_TIMESTAMP (buf) = timestamp;
-  GST_BUFFER_DURATION (buf) = duration;
-
-  /* the negotiate() method already set caps on the source pad */
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
-
-  return buf;
-}
--- a/gst_plugins_base/sys/v4l/v4lsrc_calls.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/* GStreamer
- *
- * v4lsrc_calls.h: functions for V4L video source
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * 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 __V4L_SRC_CALLS_H__
-#define __V4L_SRC_CALLS_H__
-
-#include "gstv4lsrc.h"
-#include "v4l_calls.h"
-
-
-G_BEGIN_DECLS
-
-
-/* frame grabbing/capture (palette = VIDEO_PALETTE_* - see videodev.h) */
-gboolean gst_v4lsrc_set_capture    (GstV4lSrc *v4lsrc, gint width, gint height, gint palette);
-gboolean gst_v4lsrc_capture_init   (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_capture_start  (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_grab_frame     (GstV4lSrc *v4lsrc, gint *num);
-guint8 * gst_v4lsrc_get_buffer     (GstV4lSrc *v4lsrc, gint  num);
-gboolean gst_v4lsrc_requeue_frame  (GstV4lSrc *v4lsrc, gint  num);
-gboolean gst_v4lsrc_capture_stop   (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_get_fps        (GstV4lSrc * v4lsrc, gint *fps_n, gint *fps_d);
-GValue * gst_v4lsrc_get_fps_list   (GstV4lSrc * v4lsrc);
-GstBuffer *gst_v4lsrc_buffer_new   (GstV4lSrc * v4lsrc, gint num);
-
-/* "the ugliest hack ever, now available at your local mirror" */
-gboolean gst_v4lsrc_try_capture    (GstV4lSrc *v4lsrc, gint width, gint height, gint palette);
-
-/* For debug purposes, share the palette names */
-#ifndef GST_DISABLE_GST_DEBUG
-const char *gst_v4lsrc_palette_name (int i);
-#endif
-
-
-G_END_DECLS
-
-
-#endif /* __V4L_SRC_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/videodev_mjpeg.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/* These are the MJPEG API extensions for the Video4Linux API,
-   first introduced by the Iomega Buz driver by Rainer Johanni 
-   <rainer@johanni.de>
-*/
-
-#ifndef __VIDEODEV_MJPEG_H__
-#define __VIDEODEV_MJPEG_H__
-
-/* This is identical with the mgavideo internal params struct, 
-   please tell me if you change this struct here ! <gz@lysator.liu.se) */
-struct mjpeg_params
-{
-
-   /* The following parameters can only be queried */
-
-   int major_version;            /* Major version number of driver */
-   int minor_version;            /* Minor version number of driver */
-
-   /* Main control parameters */
-
-   int input;                    /* Input channel: 0 = Composite, 1 = S-VHS */
-   int norm;                     /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
-   int decimation;               /* decimation of captured video,
-                                    enlargement of video played back.
-                                    Valid values are 1, 2, 4 or 0.
-                                    0 is a special value where the user
-                                    has full control over video scaling */
-
-   /* The following parameters only have to be set if decimation==0,
-      for other values of decimation they provide the data how the image is captured */
-
-   int HorDcm;                    /* Horizontal decimation: 1, 2 or 4 */
-   int VerDcm;                    /* Vertical decimation: 1 or 2 */
-   int TmpDcm;                    /* Temporal decimation: 1 or 2,
-                                     if TmpDcm==2 in capture every second frame is dropped,
-                                     in playback every frame is played twice */
-   int field_per_buff;            /* Number of fields per buffer: 1 or 2 */
-   int img_x;                     /* start of image in x direction */
-   int img_y;                     /* start of image in y direction */
-   int img_width;                 /* image width BEFORE decimation,
-                                     must be a multiple of HorDcm*16 */
-   int img_height;                /* image height BEFORE decimation,
-                                     must be a multiple of VerDcm*8 */
-
-   /* --- End of parameters for decimation==0 only --- */
-
-   /* JPEG control parameters */
-
-   int  quality;                  /* Measure for quality of compressed images.
-                                     Scales linearly with the size of the compressed images.
-                                     Must be beetween 0 and 100, 100 is a compression
-                                     ratio of 1:4 */
-
-   int  odd_even;                 /* Which field should come first ???
-                                     This is more aptly named "top_first",
-                                     i.e. (odd_even==1) --> top-field-first */
-
-   int  APPn;                     /* Number of APP segment to be written, must be 0..15 */
-   int  APP_len;                  /* Length of data in JPEG APPn segment */
-   char APP_data[60];             /* Data in the JPEG APPn segment. */
-
-   int  COM_len;                  /* Length of data in JPEG COM segment */
-   char COM_data[60];             /* Data in JPEG COM segment */
-
-   unsigned long jpeg_markers;    /* Which markers should go into the JPEG output.
-                                     Unless you exactly know what you do, leave them untouched.
-                                     Inluding less markers will make the resulting code
-                                     smaller, but there will be fewer applications
-                                     which can read it.
-                                     The presence of the APP and COM marker is
-                                     influenced by APP0_len and COM_len ONLY! */
-#define JPEG_MARKER_DHT (1<<3)    /* Define Huffman Tables */
-#define JPEG_MARKER_DQT (1<<4)    /* Define Quantization Tables */
-#define JPEG_MARKER_DRI (1<<5)    /* Define Restart Interval */
-#define JPEG_MARKER_COM (1<<6)    /* Comment segment */
-#define JPEG_MARKER_APP (1<<7)    /* App segment, driver will allways use APP0 */
-
-   int  VFIFO_FB;                 /* Flag for enabling Video Fifo Feedback.
-                                     If this flag is turned on and JPEG decompressing
-                                     is going to the screen, the decompress process
-                                     is stopped every time the Video Fifo is full.
-                                     This enables a smooth decompress to the screen
-                                     but the video output signal will get scrambled */
-
-   /* Misc */
-
-        char reserved[312];  /* Makes 512 bytes for this structure */
-};
-
-struct mjpeg_requestbuffers
-{
-   unsigned long count;      /* Number of buffers for MJPEG grabbing */
-   unsigned long size;       /* Size PER BUFFER in bytes */
-};
-
-struct mjpeg_sync
-{
-   unsigned long frame;      /* Frame (0 - n) for double buffer */
-   unsigned long length;     /* number of code bytes in buffer (capture only) */
-   unsigned long seq;        /* frame sequence number */
-   struct timeval timestamp; /* timestamp */
-};
-
-struct mjpeg_status
-{
-   int input;                /* Input channel, has to be set prior to BUZIOC_G_STATUS */
-   int signal;               /* Returned: 1 if valid video signal detected */
-   int norm;                 /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
-   int color;                /* Returned: 1 if color signal detected */
-};
-
-/*
-Private IOCTL to set up for displaying MJPEG
-*/
-#define MJPIOC_G_PARAMS       _IOR ('v', BASE_VIDIOCPRIVATE+0,  struct mjpeg_params)
-#define MJPIOC_S_PARAMS       _IOWR('v', BASE_VIDIOCPRIVATE+1,  struct mjpeg_params)
-#define MJPIOC_REQBUFS        _IOWR('v', BASE_VIDIOCPRIVATE+2,  struct mjpeg_requestbuffers)
-#define MJPIOC_QBUF_CAPT      _IOW ('v', BASE_VIDIOCPRIVATE+3,  int)
-#define MJPIOC_QBUF_PLAY      _IOW ('v', BASE_VIDIOCPRIVATE+4,  int)
-#define MJPIOC_SYNC           _IOR ('v', BASE_VIDIOCPRIVATE+5,  struct mjpeg_sync)
-#define MJPIOC_G_STATUS       _IOWR('v', BASE_VIDIOCPRIVATE+6,  struct mjpeg_status)
-
-#endif /* __VIDEODEV_MJPEG_H__ */
--- a/gst_plugins_base/sys/ximage/ximage.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* GStreamer
- * Copyright (C) <2003> Julien Moutte <julien@moutte.net>
- *
- * 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.
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ximagesink.h"
-
-GST_DEBUG_CATEGORY (gst_debug_ximagesink);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  if (!gst_element_register (plugin, "ximagesink",
-          GST_RANK_SECONDARY, GST_TYPE_XIMAGESINK))
-    return FALSE;
-
-  GST_DEBUG_CATEGORY_INIT (gst_debug_ximagesink, "ximagesink", 0,
-      "ximagesink element");
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "ximagesink",
-    "X11 video output element based on standard Xlib calls",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/sys/ximage/ximagesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2324 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
- *
- * 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.
- */
-
-/**
- * SECTION:element-ximagesink
- *
- * <refsect2>
- * <para>
- * XImageSink renders video frames to a drawable (XWindow) on a local or remote
- * display. This element can receive a Window ID from the application through
- * the XOverlay interface and will then render video frames in this drawable.
- * If no Window ID was provided by the application, the element will create its
- * own internal window and render into it.
- * </para>
- * <title>Scaling</title>
- * <para>
- * As standard XImage rendering to a drawable is not scaled, XImageSink will use
- * reverse caps negotiation to try to get scaled video frames for the drawable.
- * This is accomplished by asking the peer pad if it accepts some different caps
- * which in most cases implies that there is a scaling element in the pipeline,
- * or that an element generating the video frames can generate them with a 
- * different geometry. This mechanism is handled during buffer allocations, for
- * each allocation request the video sink will check the drawable geometry, look
- * at the
- * <link linkend="GstXImageSink--force-aspect-ratio">force-aspect-ratio</link>
- * property, calculate the geometry of desired video frames and then check that
- * the peer pad accept those new caps. If it does it will then allocate a buffer
- * in video memory with this new geometry and return it with the new caps.
- * </para>
- * <title>Events</title>
- * <para>
- * XImageSink creates a thread to handle events coming from the drawable. There
- * are several kind of events that can be grouped in 2 big categories: input 
- * events and window state related events. Input events will be translated to
- * navigation events and pushed upstream for other elements to react on them.
- * This includes events such as pointer moves, key press/release, clicks etc...
- * Other events are used to handle the drawable appearance even when the data
- * is not flowing (GST_STATE_PAUSED). That means that even when the element is
- * paused, it will receive expose events from the drawable and draw the latest
- * frame with correct borders/aspect-ratio.
- * </para>
- * <title>Pixel aspect ratio</title>
- * <para>
- * When changing state to GST_STATE_READY, XImageSink will open a connection to
- * the display specified in the
- * <link linkend="GstXImageSink--display">display</link> property or the default
- * display if nothing specified. Once this connection is open it will inspect 
- * the display configuration including the physical display geometry and 
- * then calculate the pixel aspect ratio. When caps negotiation will occur, the
- * video sink will set the calculated pixel aspect ratio on the caps to make 
- * sure that incoming video frames will have the correct pixel aspect ratio for
- * this display. Sometimes the calculated pixel aspect ratio can be wrong, it is
- * then possible to enforce a specific pixel aspect ratio using the
- * <link linkend="GstXImageSink--pixel-aspect-ratio">pixel-aspect-ratio</link>
- * property.
- * </para>
- * <title>Examples</title>
- * <para>
- * Here is a simple pipeline to test reverse negotiation :
- * <programlisting>
- * gst-launch -v videotestsrc ! queue ! ximagesink
- * </programlisting>
- * When the test video signal appears you can resize the window and see that
- * scaled buffers of the desired size are going to arrive with a short delay.
- * This illustrates how buffers of desired size are allocated along the way.
- * If you take away the queue, scaling will happen almost immediately.
- * </para>
- * <para>
- * Here is a simple pipeline to test navigation events :
- * <programlisting>
- * gst-launch -v videotestsrc ! navigationtest ! ffmpegcolorspace ! ximagesink
- * </programlisting>
- * While moving the mouse pointer over the test signal you will see a black box
- * following the mouse pointer. If you press the mouse button somewhere on the 
- * video and release it somewhere else a green box will appear where you pressed
- * the button and a red one where you released it. (The navigationtest element
- * is part of gst-plugins-good.)
- * </para>
- * <para>
- * Here is a simple pipeline to test pixel aspect ratio :
- * <programlisting>
- * gst-launch -v videotestsrc ! video/x-raw-rgb, pixel-aspect-ratio=(fraction)4/3 ! videoscale ! ximagesink
- * </programlisting>
- * This is faking a 4/3 pixel aspect ratio caps on video frames produced by
- * videotestsrc, in most cases the pixel aspect ratio of the display will be
- * 1/1. This means that videoscale will have to do the scaling to convert 
- * incoming frames to a size that will match the display pixel aspect ratio
- * (from 320x240 to 320x180 in this case). Note that you might have to escape 
- * some characters for your shell like '\(fraction\)'.
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Our interfaces */
-#include <gst/interfaces/navigation.h>
-#include <gst/interfaces/xoverlay.h>
-
-/* Object header */
-#include "ximagesink.h"
-
-/* Debugging category */
-#include <gst/gstinfo.h>
-
-GST_DEBUG_CATEGORY_EXTERN (gst_debug_ximagesink);
-#define GST_CAT_DEFAULT gst_debug_ximagesink
-
-typedef struct
-{
-  unsigned long flags;
-  unsigned long functions;
-  unsigned long decorations;
-  long input_mode;
-  unsigned long status;
-}
-MotifWmHints, MwmHints;
-
-#define MWM_HINTS_DECORATIONS   (1L << 1)
-
-static void gst_ximagesink_reset (GstXImageSink * ximagesink);
-static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
-    GstXImageBuffer * ximage);
-static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink,
-    GstXWindow * xwindow);
-static void gst_ximagesink_expose (GstXOverlay * overlay);
-
-/* ElementFactory information */
-static const GstElementDetails gst_ximagesink_details =
-GST_ELEMENT_DETAILS ("Video sink",
-    "Sink/Video",
-    "A standard X based videosink",
-    "Julien Moutte <julien@moutte.net>");
-
-static GstStaticPadTemplate gst_ximagesink_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-rgb, "
-        "framerate = (fraction) [ 0, MAX ], "
-        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
-    );
-
-enum
-{
-  PROP_0,
-  PROP_DISPLAY,
-  PROP_SYNCHRONOUS,
-  PROP_PIXEL_ASPECT_RATIO,
-  PROP_FORCE_ASPECT_RATIO,
-  PROP_HANDLE_EVENTS,
-  PROP_HANDLE_EXPOSE
-};
-
-static GstVideoSinkClass *parent_class = NULL;
-
-/* ============================================================= */
-/*                                                               */
-/*                       Private Methods                         */
-/*                                                               */
-/* ============================================================= */
-
-/* ximage buffers */
-
-static GstBufferClass *ximage_buffer_parent_class = NULL;
-
-#define GST_TYPE_XIMAGE_BUFFER (gst_ximage_buffer_get_type())
-
-#define GST_IS_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER))
-#define GST_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBuffer))
-#define GST_XIMAGE_BUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBufferClass))
-
-/* So some words about GstMiniObject, this is pretty messy...
-   GstMiniObject does not use the standard finalizing of GObjects, you are 
-   supposed to call gst_buffer_unref that's going to call gst_mini_objec_unref
-   which will handle its own refcount system and call gst_mini_object_free.
-   gst_mini_object_free will call the class finalize method which is not the 
-   one from GObject, after calling this finalize method it will free the object
-   instance for you if the refcount is still 0 so you should not chain up */
-static void
-gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
-{
-  GstXImageSink *ximagesink = NULL;
-  gboolean recycled = FALSE;
-  gboolean running;
-
-  g_return_if_fail (ximage != NULL);
-
-  ximagesink = ximage->ximagesink;
-  if (G_UNLIKELY (ximagesink == NULL)) {
-    GST_WARNING_OBJECT (ximagesink, "no sink found");
-    goto beach;
-  }
-
-  GST_OBJECT_LOCK (ximagesink);
-  running = ximagesink->running;
-  GST_OBJECT_UNLOCK (ximagesink);
-
-  if (running == FALSE) {
-    /* If the sink is shutting down, need to clear the image */
-    GST_DEBUG_OBJECT (ximagesink,
-        "destroy image %p because the sink is shutting down", ximage);
-    gst_ximagesink_ximage_destroy (ximagesink, ximage);
-  } else if ((ximage->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
-      (ximage->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
-    /* If our geometry changed we can't reuse that image. */
-    GST_DEBUG_OBJECT (ximagesink,
-        "destroy image %p as its size changed %dx%d vs current %dx%d",
-        ximage, ximage->width, ximage->height,
-        GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
-    gst_ximagesink_ximage_destroy (ximagesink, ximage);
-  } else {
-    /* In that case we can reuse the image and add it to our image pool. */
-    GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
-    /* need to increment the refcount again to recycle */
-    gst_buffer_ref (GST_BUFFER_CAST (ximage));
-    g_mutex_lock (ximagesink->pool_lock);
-    ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
-    g_mutex_unlock (ximagesink->pool_lock);
-    recycled = TRUE;
-  }
-
-  if (!recycled)
-    GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->
-        finalize (GST_MINI_OBJECT (ximage));
-
-beach:
-  return;
-}
-
-static void
-gst_ximage_buffer_free (GstXImageBuffer * ximage)
-{
-  /* make sure it is not recycled */
-  ximage->width = -1;
-  ximage->height = -1;
-  gst_buffer_unref (GST_BUFFER_CAST (ximage));
-}
-
-static void
-gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class)
-{
-#ifdef HAVE_XSHM
-  ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
-  ximage_buffer->SHMInfo.shmid = -1;
-#endif
-}
-
-static void
-gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data)
-{
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
-  ximage_buffer_parent_class = g_type_class_peek_parent (g_class);
-
-  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-      gst_ximage_buffer_finalize;
-}
-
-static GType
-gst_ximage_buffer_get_type (void)
-{
-  static GType _gst_ximage_buffer_type;
-
-  if (G_UNLIKELY (_gst_ximage_buffer_type == 0)) {
-    static const GTypeInfo ximage_buffer_info = {
-      sizeof (GstBufferClass),
-      NULL,
-      NULL,
-      gst_ximage_buffer_class_init,
-      NULL,
-      NULL,
-      sizeof (GstXImageBuffer),
-      0,
-      (GInstanceInitFunc) gst_ximage_buffer_init,
-      NULL
-    };
-    _gst_ximage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
-        "GstXImageBuffer", &ximage_buffer_info, 0);
-  }
-  return _gst_ximage_buffer_type;
-}
-
-/* X11 stuff */
-
-static gboolean error_caught = FALSE;
-
-static int
-gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent)
-{
-  char error_msg[1024];
-
-  XGetErrorText (display, xevent->error_code, error_msg, 1024);
-  GST_DEBUG ("ximagesink triggered an XError. error: %s", error_msg);
-  error_caught = TRUE;
-  return 0;
-}
-
-#ifdef HAVE_XSHM                /* Check that XShm calls actually work */
-
-static gboolean
-gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
-    GstXContext * xcontext)
-{
-  XImage *ximage;
-  XShmSegmentInfo SHMInfo;
-  size_t size;
-  int (*handler) (Display *, XErrorEvent *);
-  gboolean result = FALSE;
-  gboolean did_attach = FALSE;
-
-  g_return_val_if_fail (xcontext != NULL, FALSE);
-
-  /* Sync to ensure any older errors are already processed */
-  XSync (xcontext->disp, FALSE);
-
-  /* Set defaults so we don't free these later unnecessarily */
-  SHMInfo.shmaddr = ((void *) -1);
-  SHMInfo.shmid = -1;
-
-  /* Setting an error handler to catch failure */
-  error_caught = FALSE;
-  handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
-
-  /* Trying to create a 1x1 ximage */
-  GST_DEBUG ("XShmCreateImage of 1x1");
-
-  ximage = XShmCreateImage (xcontext->disp, xcontext->visual,
-      xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1);
-
-  /* Might cause an error, sync to ensure it is noticed */
-  XSync (xcontext->disp, FALSE);
-  if (!ximage || error_caught) {
-    GST_WARNING ("could not XShmCreateImage a 1x1 image");
-    goto beach;
-  }
-  size = ximage->height * ximage->bytes_per_line;
-
-  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
-  if (SHMInfo.shmid == -1) {
-    GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
-        size);
-    goto beach;
-  }
-
-  SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
-  if (SHMInfo.shmaddr == ((void *) -1)) {
-    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
-    /* Clean up shm seg */
-    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-    goto beach;
-  }
-
-  /* Delete the shared memory segment as soon as we manage to attach. 
-   * This way, it will be deleted as soon as we detach later, and not
-   * leaked if we crash. */
-  shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-
-  ximage->data = SHMInfo.shmaddr;
-  SHMInfo.readOnly = FALSE;
-
-  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
-    GST_WARNING ("Failed to XShmAttach");
-    goto beach;
-  }
-
-  /* Sync to ensure we see any errors we caused */
-  XSync (xcontext->disp, FALSE);
-
-  if (!error_caught) {
-    did_attach = TRUE;
-    /* store whether we succeeded in result */
-    result = TRUE;
-  }
-
-beach:
-  /* Sync to ensure we swallow any errors we caused and reset error_caught */
-  XSync (xcontext->disp, FALSE);
-  error_caught = FALSE;
-  XSetErrorHandler (handler);
-
-  if (did_attach) {
-    XShmDetach (xcontext->disp, &SHMInfo);
-    XSync (xcontext->disp, FALSE);
-  }
-  if (SHMInfo.shmaddr != ((void *) -1))
-    shmdt (SHMInfo.shmaddr);
-  if (ximage)
-    XDestroyImage (ximage);
-  return result;
-}
-#endif /* HAVE_XSHM */
-
-/* This function handles GstXImageBuffer creation depending on XShm availability */
-static GstXImageBuffer *
-gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
-{
-  GstXImageBuffer *ximage = NULL;
-  GstStructure *structure = NULL;
-  gboolean succeeded = FALSE;
-  int (*handler) (Display *, XErrorEvent *);
-
-  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
-  ximage = (GstXImageBuffer *) gst_mini_object_new (GST_TYPE_XIMAGE_BUFFER);
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (!gst_structure_get_int (structure, "width", &ximage->width) ||
-      !gst_structure_get_int (structure, "height", &ximage->height)) {
-    GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
-  }
-
-  GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", ximage,
-      ximage->width, ximage->height);
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  /* Setting an error handler to catch failure */
-  error_caught = FALSE;
-  handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
-  if (ximagesink->xcontext->use_xshm) {
-    ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
-        ximagesink->xcontext->visual,
-        ximagesink->xcontext->depth,
-        ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
-    if (!ximage->ximage || error_caught) {
-      g_mutex_unlock (ximagesink->x_lock);
-      /* Reset error handler */
-      error_caught = FALSE;
-      XSetErrorHandler (handler);
-      /* Push an error */
-      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              ximage->width, ximage->height),
-          ("could not XShmCreateImage a %dx%d image",
-              ximage->width, ximage->height));
-      goto beach;
-    }
-
-    /* we have to use the returned bytes_per_line for our shm size */
-    ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
-    GST_LOG_OBJECT (ximagesink,
-        "XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d",
-        ximage->size, ximage->width, ximage->ximage->bytes_per_line);
-
-    ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
-        IPC_CREAT | 0777);
-    if (ximage->SHMInfo.shmid == -1) {
-      g_mutex_unlock (ximagesink->x_lock);
-      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              ximage->width, ximage->height),
-          ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
-              ximage->size));
-      goto beach;
-    }
-
-    ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, NULL, 0);
-    if (ximage->SHMInfo.shmaddr == ((void *) -1)) {
-      g_mutex_unlock (ximagesink->x_lock);
-      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              ximage->width, ximage->height),
-          ("Failed to shmat: %s", g_strerror (errno)));
-      /* Clean up the shared memory segment */
-      shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
-      goto beach;
-    }
-
-    /* Now that we've attached, we can delete the shared memory segment.
-     * This way, it will be deleted as soon as we detach later, and not
-     * leaked if we crash. */
-    shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
-
-    ximage->ximage->data = ximage->SHMInfo.shmaddr;
-    ximage->SHMInfo.readOnly = FALSE;
-
-    if (XShmAttach (ximagesink->xcontext->disp, &ximage->SHMInfo) == 0) {
-      g_mutex_unlock (ximagesink->x_lock);
-      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              ximage->width, ximage->height), ("Failed to XShmAttach"));
-      goto beach;
-    }
-
-    XSync (ximagesink->xcontext->disp, FALSE);
-  } else
-#endif /* HAVE_XSHM */
-  {
-    guint allocsize;
-
-    ximage->ximage = XCreateImage (ximagesink->xcontext->disp,
-        ximagesink->xcontext->visual,
-        ximagesink->xcontext->depth,
-        ZPixmap, 0, NULL,
-        ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
-    if (!ximage->ximage || error_caught) {
-      g_mutex_unlock (ximagesink->x_lock);
-      /* Reset error handler */
-      error_caught = FALSE;
-      XSetErrorHandler (handler);
-      /* Push an error */
-      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              ximage->width, ximage->height),
-          ("could not XCreateImage a %dx%d image",
-              ximage->width, ximage->height));
-      goto beach;
-    }
-
-    /* upstream will assume that rowstrides are multiples of 4, but this
-     * doesn't always seem to be the case with XCreateImage() */
-    if ((ximage->ximage->bytes_per_line % 4) != 0) {
-      GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as "
-          "usually assumed");
-    }
-
-    /* we have to use the returned bytes_per_line for our image size */
-    ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
-
-    /* alloc a bit more for unexpected strides to avoid crashes upstream.
-     * FIXME: if we get an unrounded stride, the image will be displayed
-     * distorted, since all upstream elements assume a rounded stride */
-    allocsize =
-        GST_ROUND_UP_4 (ximage->ximage->bytes_per_line) *
-        ximage->ximage->height;
-    ximage->ximage->data = g_malloc (allocsize);
-    GST_LOG_OBJECT (ximagesink,
-        "non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, "
-        "stride %d", ximage->size, allocsize, ximage->width,
-        ximage->ximage->bytes_per_line);
-
-    XSync (ximagesink->xcontext->disp, FALSE);
-  }
-
-  /* Reset error handler */
-  error_caught = FALSE;
-  XSetErrorHandler (handler);
-
-  succeeded = TRUE;
-
-  GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
-  GST_BUFFER_SIZE (ximage) = ximage->size;
-
-  /* Keep a ref to our sink */
-  ximage->ximagesink = gst_object_ref (ximagesink);
-
-  g_mutex_unlock (ximagesink->x_lock);
-beach:
-  if (!succeeded) {
-    gst_ximage_buffer_free (ximage);
-    ximage = NULL;
-  }
-
-  return ximage;
-}
-
-/* This function destroys a GstXImageBuffer handling XShm availability */
-static void
-gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
-    GstXImageBuffer * ximage)
-{
-  g_return_if_fail (ximage != NULL);
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
-  /* Hold the object lock to ensure the XContext doesn't disappear */
-  GST_OBJECT_LOCK (ximagesink);
-
-  /* If the destroyed image is the current one we destroy our reference too */
-  if (ximagesink->cur_image == ximage) {
-    ximagesink->cur_image = NULL;
-  }
-
-  /* We might have some buffers destroyed after changing state to NULL */
-  if (!ximagesink->xcontext) {
-    GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
-#ifdef HAVE_XSHM
-    if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
-      shmdt (ximage->SHMInfo.shmaddr);
-    }
-#endif
-    goto beach;
-  }
-
-  g_mutex_lock (ximagesink->x_lock);
-
-#ifdef HAVE_XSHM
-  if (ximagesink->xcontext->use_xshm) {
-    if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
-      XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo);
-      XSync (ximagesink->xcontext->disp, 0);
-      shmdt (ximage->SHMInfo.shmaddr);
-    }
-    if (ximage->ximage)
-      XDestroyImage (ximage->ximage);
-
-  } else
-#endif /* HAVE_XSHM */
-  {
-    if (ximage->ximage) {
-      XDestroyImage (ximage->ximage);
-    }
-  }
-
-  XSync (ximagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-beach:
-  GST_OBJECT_UNLOCK (ximagesink);
-
-  if (ximage->ximagesink) {
-    /* Release the ref to our sink */
-    ximage->ximagesink = NULL;
-    gst_object_unref (ximagesink);
-  }
-
-  return;
-}
-
-/* We are called with the x_lock taken */
-static void
-gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink,
-    GstXWindow * xwindow, GstVideoRectangle rect)
-{
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-  g_return_if_fail (xwindow != NULL);
-
-  XSetForeground (ximagesink->xcontext->disp, xwindow->gc,
-      ximagesink->xcontext->black);
-
-  /* Left border */
-  if (rect.x > 0) {
-    XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        0, 0, rect.x, xwindow->height);
-  }
-
-  /* Right border */
-  if ((rect.x + rect.w) < xwindow->width) {
-    XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        rect.x + rect.w, 0, xwindow->width, xwindow->height);
-  }
-
-  /* Top border */
-  if (rect.y > 0) {
-    XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        0, 0, xwindow->width, rect.y);
-  }
-
-  /* Bottom border */
-  if ((rect.y + rect.h) < xwindow->height) {
-    XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        0, rect.y + rect.h, xwindow->width, xwindow->height);
-  }
-}
-
-/* This function puts a GstXImageBuffer on a GstXImageSink's window */
-static gboolean
-gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
-{
-  GstVideoRectangle src, dst, result;
-  gboolean draw_border = FALSE;
-
-  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
-
-  /* We take the flow_lock. If expose is in there we don't want to run
-     concurrently from the data flow thread */
-  g_mutex_lock (ximagesink->flow_lock);
-
-  if (G_UNLIKELY (ximagesink->xwindow == NULL)) {
-    g_mutex_unlock (ximagesink->flow_lock);
-    return FALSE;
-  }
-
-  /* Draw borders when displaying the first frame. After this
-     draw borders only on expose event. */
-  if (!ximagesink->cur_image) {
-    draw_border = TRUE;
-  }
-
-  /* Store a reference to the last image we put, lose the previous one */
-  if (ximage && ximagesink->cur_image != ximage) {
-    if (ximagesink->cur_image) {
-      GST_LOG_OBJECT (ximagesink, "unreffing %p", ximagesink->cur_image);
-      gst_buffer_unref (ximagesink->cur_image);
-    }
-    GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
-    ximagesink->cur_image =
-        GST_XIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER_CAST (ximage)));
-  }
-
-  /* Expose sends a NULL image, we take the latest frame */
-  if (!ximage) {
-    draw_border = TRUE;
-    if (ximagesink->cur_image) {
-      ximage = ximagesink->cur_image;
-    } else {
-      g_mutex_unlock (ximagesink->flow_lock);
-      return TRUE;
-    }
-  }
-
-  gst_ximagesink_xwindow_update_geometry (ximagesink, ximagesink->xwindow);
-
-  src.w = ximage->width;
-  src.h = ximage->height;
-  dst.w = ximagesink->xwindow->width;
-  dst.h = ximagesink->xwindow->height;
-
-  gst_video_sink_center_rect (src, dst, &result, FALSE);
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  if (draw_border) {
-    gst_ximagesink_xwindow_draw_borders (ximagesink, ximagesink->xwindow,
-        result);
-  }
-#ifdef HAVE_XSHM
-  if (ximagesink->xcontext->use_xshm) {
-    GST_LOG_OBJECT (ximagesink,
-        "XShmPutImage on %p, src: %d, %d - dest: %d, %d, dim: %dx%d, win %dx%d",
-        ximage, 0, 0, result.x, result.y, result.w, result.h,
-        ximagesink->xwindow->width, ximagesink->xwindow->height);
-    XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
-        ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
-        result.w, result.h, FALSE);
-  } else
-#endif /* HAVE_XSHM */
-  {
-    GST_LOG_OBJECT (ximagesink,
-        "XPutImage on %p, src: %d, %d - dest: %d, %d, dim: %dx%d, win %dx%d",
-        ximage, 0, 0, result.x, result.y, result.w, result.h,
-        ximagesink->xwindow->width, ximagesink->xwindow->height);
-    XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
-        ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
-        result.w, result.h);
-  }
-
-  XSync (ximagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  g_mutex_unlock (ximagesink->flow_lock);
-
-  return TRUE;
-}
-
-static gboolean
-gst_ximagesink_xwindow_decorate (GstXImageSink * ximagesink,
-    GstXWindow * window)
-{
-  Atom hints_atom = None;
-  MotifWmHints *hints;
-
-  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
-  g_return_val_if_fail (window != NULL, FALSE);
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS", 1);
-  if (hints_atom == None) {
-    g_mutex_unlock (ximagesink->x_lock);
-    return FALSE;
-  }
-
-  hints = g_malloc0 (sizeof (MotifWmHints));
-
-  hints->flags |= MWM_HINTS_DECORATIONS;
-  hints->decorations = 1 << 0;
-
-  XChangeProperty (ximagesink->xcontext->disp, window->win,
-      hints_atom, hints_atom, 32, PropModeReplace,
-      (guchar *) hints, sizeof (MotifWmHints) / sizeof (long));
-
-  XSync (ximagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  g_free (hints);
-
-  return TRUE;
-}
-
-/* This function handles a GstXWindow creation */
-static GstXWindow *
-gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
-{
-  GstXWindow *xwindow = NULL;
-  XGCValues values;
-
-  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
-  xwindow = g_new0 (GstXWindow, 1);
-
-  xwindow->width = width;
-  xwindow->height = height;
-  xwindow->internal = TRUE;
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp,
-      ximagesink->xcontext->root,
-      0, 0, xwindow->width, xwindow->height, 0, 0, ximagesink->xcontext->black);
-
-  /* We have to do that to prevent X from redrawing the background on 
-     ConfigureNotify. This takes away flickering of video when resizing. */
-  XSetWindowBackgroundPixmap (ximagesink->xcontext->disp, xwindow->win, None);
-
-  if (ximagesink->handle_events) {
-    Atom wm_delete;
-
-    XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
-        StructureNotifyMask | PointerMotionMask | KeyPressMask |
-        KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-
-    /* Tell the window manager we'd like delete client messages instead of
-     * being killed */
-    wm_delete = XInternAtom (ximagesink->xcontext->disp,
-        "WM_DELETE_WINDOW", False);
-    (void) XSetWMProtocols (ximagesink->xcontext->disp, xwindow->win,
-        &wm_delete, 1);
-  }
-
-  xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win,
-      0, &values);
-
-  XMapRaised (ximagesink->xcontext->disp, xwindow->win);
-
-  XSync (ximagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  gst_ximagesink_xwindow_decorate (ximagesink, xwindow);
-
-  gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (ximagesink), xwindow->win);
-
-  return xwindow;
-}
-
-/* This function destroys a GstXWindow */
-static void
-gst_ximagesink_xwindow_destroy (GstXImageSink * ximagesink,
-    GstXWindow * xwindow)
-{
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  /* If we did not create that window we just free the GC and let it live */
-  if (xwindow->internal)
-    XDestroyWindow (ximagesink->xcontext->disp, xwindow->win);
-  else
-    XSelectInput (ximagesink->xcontext->disp, xwindow->win, 0);
-
-  XFreeGC (ximagesink->xcontext->disp, xwindow->gc);
-
-  XSync (ximagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  g_free (xwindow);
-}
-
-static void
-gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink,
-    GstXWindow * xwindow)
-{
-  XWindowAttributes attr;
-
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
-  /* Update the window geometry */
-  g_mutex_lock (ximagesink->x_lock);
-
-  XGetWindowAttributes (ximagesink->xcontext->disp,
-      ximagesink->xwindow->win, &attr);
-
-  ximagesink->xwindow->width = attr.width;
-  ximagesink->xwindow->height = attr.height;
-
-  g_mutex_unlock (ximagesink->x_lock);
-}
-
-static void
-gst_ximagesink_xwindow_clear (GstXImageSink * ximagesink, GstXWindow * xwindow)
-{
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  XSetForeground (ximagesink->xcontext->disp, xwindow->gc,
-      ximagesink->xcontext->black);
-
-  XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
-      0, 0, xwindow->width, xwindow->height);
-
-  XSync (ximagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (ximagesink->x_lock);
-}
-
-/* This function handles XEvents that might be in the queue. It generates
-   GstEvent that will be sent upstream in the pipeline to handle interactivity
-   and navigation.*/
-static void
-gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
-{
-  XEvent e;
-  guint pointer_x = 0, pointer_y = 0;
-  gboolean pointer_moved = FALSE;
-  gboolean exposed = FALSE, configured = FALSE;
-
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
-  /* Then we get all pointer motion events, only the last position is
-     interesting. */
-  g_mutex_lock (ximagesink->flow_lock);
-  g_mutex_lock (ximagesink->x_lock);
-  while (XCheckWindowEvent (ximagesink->xcontext->disp,
-          ximagesink->xwindow->win, PointerMotionMask, &e)) {
-    g_mutex_unlock (ximagesink->x_lock);
-    g_mutex_unlock (ximagesink->flow_lock);
-
-    switch (e.type) {
-      case MotionNotify:
-        pointer_x = e.xmotion.x;
-        pointer_y = e.xmotion.y;
-        pointer_moved = TRUE;
-        break;
-      default:
-        break;
-    }
-    g_mutex_lock (ximagesink->flow_lock);
-    g_mutex_lock (ximagesink->x_lock);
-  }
-
-  if (pointer_moved) {
-    g_mutex_unlock (ximagesink->x_lock);
-    g_mutex_unlock (ximagesink->flow_lock);
-
-    GST_DEBUG ("ximagesink pointer moved over window at %d,%d",
-        pointer_x, pointer_y);
-    gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
-        "mouse-move", 0, pointer_x, pointer_y);
-
-    g_mutex_lock (ximagesink->flow_lock);
-    g_mutex_lock (ximagesink->x_lock);
-  }
-
-  /* We get all remaining events on our window to throw them upstream */
-  while (XCheckWindowEvent (ximagesink->xcontext->disp,
-          ximagesink->xwindow->win,
-          KeyPressMask | KeyReleaseMask |
-          ButtonPressMask | ButtonReleaseMask, &e)) {
-    KeySym keysym;
-
-    /* We lock only for the X function call */
-    g_mutex_unlock (ximagesink->x_lock);
-    g_mutex_unlock (ximagesink->flow_lock);
-
-    switch (e.type) {
-      case ButtonPress:
-        /* Mouse button pressed/released over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("ximagesink button %d pressed over window at %d,%d",
-            e.xbutton.button, e.xbutton.x, e.xbutton.x);
-        gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
-            "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        break;
-      case ButtonRelease:
-        GST_DEBUG ("ximagesink button %d release over window at %d,%d",
-            e.xbutton.button, e.xbutton.x, e.xbutton.x);
-        gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
-            "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        break;
-      case KeyPress:
-      case KeyRelease:
-        /* Key pressed/released over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("ximagesink key %d pressed over window at %d,%d",
-            e.xkey.keycode, e.xkey.x, e.xkey.x);
-        g_mutex_lock (ximagesink->x_lock);
-        keysym = XKeycodeToKeysym (ximagesink->xcontext->disp,
-            e.xkey.keycode, 0);
-        g_mutex_unlock (ximagesink->x_lock);
-        if (keysym != NoSymbol) {
-          char *key_str = NULL;
-
-          g_mutex_lock (ximagesink->x_lock);
-          key_str = XKeysymToString (keysym);
-          g_mutex_unlock (ximagesink->x_lock);
-          gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
-              e.type == KeyPress ? "key-press" : "key-release", key_str);
-
-        } else {
-          gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
-              e.type == KeyPress ? "key-press" : "key-release", "unknown");
-        }
-        break;
-      default:
-        GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)",
-            e.type);
-    }
-    g_mutex_lock (ximagesink->flow_lock);
-    g_mutex_lock (ximagesink->x_lock);
-  }
-
-  while (XCheckWindowEvent (ximagesink->xcontext->disp,
-          ximagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
-    switch (e.type) {
-      case Expose:
-        exposed = TRUE;
-        break;
-      case ConfigureNotify:
-        configured = TRUE;
-        break;
-      default:
-        break;
-    }
-  }
-
-  if (ximagesink->handle_expose && (exposed || configured)) {
-    g_mutex_unlock (ximagesink->x_lock);
-    g_mutex_unlock (ximagesink->flow_lock);
-
-    gst_ximagesink_expose (GST_X_OVERLAY (ximagesink));
-
-    g_mutex_lock (ximagesink->flow_lock);
-    g_mutex_lock (ximagesink->x_lock);
-  }
-
-  /* Handle Display events */
-  while (XPending (ximagesink->xcontext->disp)) {
-    XNextEvent (ximagesink->xcontext->disp, &e);
-
-    switch (e.type) {
-      case ClientMessage:{
-        Atom wm_delete;
-
-        wm_delete = XInternAtom (ximagesink->xcontext->disp,
-            "WM_DELETE_WINDOW", False);
-        if (wm_delete == (Atom) e.xclient.data.l[0]) {
-          /* Handle window deletion by posting an error on the bus */
-          GST_ELEMENT_ERROR (ximagesink, RESOURCE, NOT_FOUND,
-              ("Output window was closed"), (NULL));
-
-          g_mutex_unlock (ximagesink->x_lock);
-          gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
-          ximagesink->xwindow = NULL;
-          g_mutex_lock (ximagesink->x_lock);
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  g_mutex_unlock (ximagesink->x_lock);
-  g_mutex_unlock (ximagesink->flow_lock);
-}
-
-static gpointer
-gst_ximagesink_event_thread (GstXImageSink * ximagesink)
-{
-  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
-  GST_OBJECT_LOCK (ximagesink);
-  while (ximagesink->running) {
-    GST_OBJECT_UNLOCK (ximagesink);
-
-    if (ximagesink->xwindow) {
-      gst_ximagesink_handle_xevents (ximagesink);
-    }
-    g_usleep (100000);
-
-    GST_OBJECT_LOCK (ximagesink);
-  }
-  GST_OBJECT_UNLOCK (ximagesink);
-
-  return NULL;
-}
-
-/* This function calculates the pixel aspect ratio based on the properties
- * in the xcontext structure and stores it there. */
-static void
-gst_ximagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
-{
-  static const gint par[][2] = {
-    {1, 1},                     /* regular screen */
-    {16, 15},                   /* PAL TV */
-    {11, 10},                   /* 525 line Rec.601 video */
-    {54, 59},                   /* 625 line Rec.601 video */
-    {64, 45},                   /* 1280x1024 on 16:9 display */
-    {5, 3},                     /* 1280x1024 on 4:3 display */
-    {4, 3}                      /*  800x600 on 16:9 display */
-  };
-  gint i;
-  gint index;
-  gdouble ratio;
-  gdouble delta;
-
-#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
-
-  /* first calculate the "real" ratio based on the X values;
-   * which is the "physical" w/h divided by the w/h in pixels of the display */
-  ratio = (gdouble) (xcontext->widthmm * xcontext->height)
-      / (xcontext->heightmm * xcontext->width);
-
-  /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
-   * override here */
-  if (xcontext->width == 720 && xcontext->height == 576) {
-    ratio = 4.0 * 576 / (3.0 * 720);
-  }
-  GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
-
-  /* now find the one from par[][2] with the lowest delta to the real one */
-  delta = DELTA (0);
-  index = 0;
-
-  for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
-    gdouble this_delta = DELTA (i);
-
-    if (this_delta < delta) {
-      index = i;
-      delta = this_delta;
-    }
-  }
-
-  GST_DEBUG ("Decided on index %d (%d/%d)", index,
-      par[index][0], par[index][1]);
-
-  g_free (xcontext->par);
-  xcontext->par = g_new0 (GValue, 1);
-  g_value_init (xcontext->par, GST_TYPE_FRACTION);
-  gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
-  GST_DEBUG ("set xcontext PAR to %d/%d",
-      gst_value_get_fraction_numerator (xcontext->par),
-      gst_value_get_fraction_denominator (xcontext->par));
-}
-
-/* This function gets the X Display and global info about it. Everything is
-   stored in our object and will be cleaned when the object is disposed. Note
-   here that caps for supported format are generated without any window or
-   image creation */
-static GstXContext *
-gst_ximagesink_xcontext_get (GstXImageSink * ximagesink)
-{
-  GstXContext *xcontext = NULL;
-  XPixmapFormatValues *px_formats = NULL;
-  gint nb_formats = 0, i;
-
-  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
-  xcontext = g_new0 (GstXContext, 1);
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  xcontext->disp = XOpenDisplay (ximagesink->display_name);
-
-  if (!xcontext->disp) {
-    g_mutex_unlock (ximagesink->x_lock);
-    g_free (xcontext);
-    GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-        ("Could not initialise X output"), ("Could not open display"));
-    return NULL;
-  }
-
-  xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
-  xcontext->screen_num = DefaultScreen (xcontext->disp);
-  xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
-  xcontext->root = DefaultRootWindow (xcontext->disp);
-  xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
-  xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
-  xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
-
-  xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
-  xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
-  xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
-  xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
-
-  GST_DEBUG_OBJECT (ximagesink, "X reports %dx%d pixels and %d mm x %d mm",
-      xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
-
-  gst_ximagesink_calculate_pixel_aspect_ratio (xcontext);
-
-  /* We get supported pixmap formats at supported depth */
-  px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
-
-  if (!px_formats) {
-    XCloseDisplay (xcontext->disp);
-    g_mutex_unlock (ximagesink->x_lock);
-    g_free (xcontext->par);
-    g_free (xcontext);
-    return NULL;
-  }
-
-  /* We get bpp value corresponding to our running depth */
-  for (i = 0; i < nb_formats; i++) {
-    if (px_formats[i].depth == xcontext->depth)
-      xcontext->bpp = px_formats[i].bits_per_pixel;
-  }
-
-  XFree (px_formats);
-
-  xcontext->endianness =
-      (ImageByteOrder (xcontext->disp) ==
-      LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
-
-  /* Search for XShm extension support */
-#ifdef HAVE_XSHM
-  if (XShmQueryExtension (xcontext->disp) &&
-      gst_ximagesink_check_xshm_calls (ximagesink, xcontext)) {
-    xcontext->use_xshm = TRUE;
-    GST_DEBUG ("ximagesink is using XShm extension");
-  } else
-#endif
-  {
-    xcontext->use_xshm = FALSE;
-    GST_DEBUG ("ximagesink is not using XShm extension");
-  }
-
-  /* our caps system handles 24/32bpp RGB as big-endian. */
-  if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
-      xcontext->endianness == G_LITTLE_ENDIAN) {
-    xcontext->endianness = G_BIG_ENDIAN;
-    xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
-    xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
-    xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
-    if (xcontext->bpp == 24) {
-      xcontext->visual->red_mask >>= 8;
-      xcontext->visual->green_mask >>= 8;
-      xcontext->visual->blue_mask >>= 8;
-    }
-  }
-
-  /* update object's par with calculated one if not set yet */
-  if (!ximagesink->par) {
-    ximagesink->par = g_new0 (GValue, 1);
-    gst_value_init_and_copy (ximagesink->par, xcontext->par);
-    GST_DEBUG_OBJECT (ximagesink, "set calculated PAR on object's PAR");
-  }
-  xcontext->caps = gst_caps_new_simple ("video/x-raw-rgb",
-      "bpp", G_TYPE_INT, xcontext->bpp,
-      "depth", G_TYPE_INT, xcontext->depth,
-      "endianness", G_TYPE_INT, xcontext->endianness,
-      "red_mask", G_TYPE_INT, xcontext->visual->red_mask,
-      "green_mask", G_TYPE_INT, xcontext->visual->green_mask,
-      "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask,
-      "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-      "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-      "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-  if (ximagesink->par) {
-    int nom, den;
-
-    nom = gst_value_get_fraction_numerator (ximagesink->par);
-    den = gst_value_get_fraction_denominator (ximagesink->par);
-    gst_caps_set_simple (xcontext->caps, "pixel-aspect-ratio",
-        GST_TYPE_FRACTION, nom, den, NULL);
-  }
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  /* Setup our event listening thread */
-  GST_OBJECT_LOCK (ximagesink);
-  ximagesink->running = TRUE;
-  ximagesink->event_thread = g_thread_create (
-      (GThreadFunc) gst_ximagesink_event_thread, ximagesink, TRUE, NULL);
-  GST_OBJECT_UNLOCK (ximagesink);
-
-  return xcontext;
-}
-
-/* This function cleans the X context. Closing the Display and unrefing the
-   caps for supported formats. */
-static void
-gst_ximagesink_xcontext_clear (GstXImageSink * ximagesink)
-{
-  GstXContext *xcontext;
-
-  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
-  GST_OBJECT_LOCK (ximagesink);
-  if (ximagesink->xcontext == NULL) {
-    GST_OBJECT_UNLOCK (ximagesink);
-    return;
-  }
-
-  /* Take the xcontext reference and NULL it while we
-   * clean it up, so that any buffer-alloced buffers 
-   * arriving after this will be freed correctly */
-  xcontext = ximagesink->xcontext;
-  ximagesink->xcontext = NULL;
-
-  GST_OBJECT_UNLOCK (ximagesink);
-
-  gst_caps_unref (xcontext->caps);
-  g_free (xcontext->par);
-  g_free (ximagesink->par);
-  ximagesink->par = NULL;
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  XCloseDisplay (xcontext->disp);
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  g_free (xcontext);
-}
-
-static void
-gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
-{
-
-  g_mutex_lock (ximagesink->pool_lock);
-
-  while (ximagesink->buffer_pool) {
-    GstXImageBuffer *ximage = ximagesink->buffer_pool->data;
-
-    ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
-        ximagesink->buffer_pool);
-    gst_ximage_buffer_free (ximage);
-  }
-
-  g_mutex_unlock (ximagesink->pool_lock);
-}
-
-/* Element stuff */
-
-static GstCaps *
-gst_ximagesink_getcaps (GstBaseSink * bsink)
-{
-  GstXImageSink *ximagesink;
-  GstCaps *caps;
-  int i;
-
-  ximagesink = GST_XIMAGESINK (bsink);
-
-  if (ximagesink->xcontext)
-    return gst_caps_ref (ximagesink->xcontext->caps);
-
-  /* get a template copy and add the pixel aspect ratio */
-  caps =
-      gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK (ximagesink)->
-          sinkpad));
-  for (i = 0; i < gst_caps_get_size (caps); ++i) {
-    GstStructure *structure = gst_caps_get_structure (caps, i);
-
-    if (ximagesink->par) {
-      int nom, den;
-
-      nom = gst_value_get_fraction_numerator (ximagesink->par);
-      den = gst_value_get_fraction_denominator (ximagesink->par);
-      gst_structure_set (structure, "pixel-aspect-ratio",
-          GST_TYPE_FRACTION, nom, den, NULL);
-    }
-  }
-
-  return caps;
-}
-
-static gboolean
-gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
-{
-  GstXImageSink *ximagesink;
-  gboolean ret = TRUE;
-  GstStructure *structure;
-  GstCaps *intersection;
-  const GValue *par;
-  gint new_width, new_height;
-  const GValue *fps;
-
-  ximagesink = GST_XIMAGESINK (bsink);
-
-  if (!ximagesink->xcontext)
-    return FALSE;
-
-  GST_DEBUG_OBJECT (ximagesink,
-      "sinkconnect possible caps %" GST_PTR_FORMAT " with given caps %"
-      GST_PTR_FORMAT, ximagesink->xcontext->caps, caps);
-
-  /* We intersect those caps with our template to make sure they are correct */
-  intersection = gst_caps_intersect (ximagesink->xcontext->caps, caps);
-  GST_DEBUG_OBJECT (ximagesink, "intersection returned %" GST_PTR_FORMAT,
-      intersection);
-  if (gst_caps_is_empty (intersection)) {
-    gst_caps_unref (intersection);
-    return FALSE;
-  }
-
-  gst_caps_unref (intersection);
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  ret &= gst_structure_get_int (structure, "width", &new_width);
-  ret &= gst_structure_get_int (structure, "height", &new_height);
-  fps = gst_structure_get_value (structure, "framerate");
-  ret &= (fps != NULL);
-  if (!ret)
-    return FALSE;
-
-  /* if the caps contain pixel-aspect-ratio, they have to match ours,
-   * otherwise linking should fail */
-  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
-  if (par) {
-    if (ximagesink->par) {
-      if (gst_value_compare (par, ximagesink->par) != GST_VALUE_EQUAL) {
-        goto wrong_aspect;
-      }
-    } else if (ximagesink->xcontext->par) {
-      if (gst_value_compare (par, ximagesink->xcontext->par) != GST_VALUE_EQUAL) {
-        goto wrong_aspect;
-      }
-    }
-  }
-
-  GST_VIDEO_SINK_WIDTH (ximagesink) = new_width;
-  GST_VIDEO_SINK_HEIGHT (ximagesink) = new_height;
-  ximagesink->fps_n = gst_value_get_fraction_numerator (fps);
-  ximagesink->fps_d = gst_value_get_fraction_denominator (fps);
-
-  /* Notify application to set xwindow id now */
-  g_mutex_lock (ximagesink->flow_lock);
-  if (!ximagesink->xwindow) {
-    g_mutex_unlock (ximagesink->flow_lock);
-    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink));
-  } else {
-    g_mutex_unlock (ximagesink->flow_lock);
-  }
-
-  /* Creating our window and our image */
-  if (GST_VIDEO_SINK_WIDTH (ximagesink) <= 0 ||
-      GST_VIDEO_SINK_HEIGHT (ximagesink) <= 0) {
-    GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL),
-        ("Invalid image size."));
-    return FALSE;
-  }
-
-  g_mutex_lock (ximagesink->flow_lock);
-  if (!ximagesink->xwindow) {
-    ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink,
-        GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
-  }
-  g_mutex_unlock (ximagesink->flow_lock);
-
-  /* If our ximage has changed we destroy it, next chain iteration will create
-     a new one */
-  if ((ximagesink->ximage) &&
-      ((GST_VIDEO_SINK_WIDTH (ximagesink) != ximagesink->ximage->width) ||
-          (GST_VIDEO_SINK_HEIGHT (ximagesink) != ximagesink->ximage->height))) {
-    GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
-        ximagesink->ximage);
-    gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage));
-    ximagesink->ximage = NULL;
-  }
-
-  return TRUE;
-
-  /* ERRORS */
-wrong_aspect:
-  {
-    GST_INFO_OBJECT (ximagesink, "pixel aspect ratio does not match");
-    return FALSE;
-  }
-}
-
-static GstStateChangeReturn
-gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
-{
-  GstXImageSink *ximagesink;
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstXContext *xcontext = NULL;
-
-  ximagesink = GST_XIMAGESINK (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-
-      /* Initializing the XContext */
-      if (ximagesink->xcontext == NULL) {
-        xcontext = gst_ximagesink_xcontext_get (ximagesink);
-        if (xcontext == NULL) {
-          ret = GST_STATE_CHANGE_FAILURE;
-          goto beach;
-        }
-        GST_OBJECT_LOCK (ximagesink);
-        if (xcontext)
-          ximagesink->xcontext = xcontext;
-        GST_OBJECT_UNLOCK (ximagesink);
-      }
-
-      /* call XSynchronize with the current value of synchronous */
-      GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s",
-          ximagesink->synchronous ? "TRUE" : "FALSE");
-      g_mutex_lock (ximagesink->x_lock);
-      XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous);
-      g_mutex_unlock (ximagesink->x_lock);
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      g_mutex_lock (ximagesink->flow_lock);
-      if (ximagesink->xwindow)
-        gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
-      g_mutex_unlock (ximagesink->flow_lock);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      ximagesink->fps_n = 0;
-      ximagesink->fps_d = 1;
-      GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
-      GST_VIDEO_SINK_HEIGHT (ximagesink) = 0;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      gst_ximagesink_reset (ximagesink);
-      break;
-    default:
-      break;
-  }
-
-beach:
-  return ret;
-}
-
-static void
-gst_ximagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
-    GstClockTime * start, GstClockTime * end)
-{
-  GstXImageSink *ximagesink;
-
-  ximagesink = GST_XIMAGESINK (bsink);
-
-  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
-    *start = GST_BUFFER_TIMESTAMP (buf);
-    if (GST_BUFFER_DURATION_IS_VALID (buf)) {
-      *end = *start + GST_BUFFER_DURATION (buf);
-    } else {
-      if (ximagesink->fps_n > 0) {
-        *end = *start +
-            gst_util_uint64_scale_int (GST_SECOND, ximagesink->fps_d,
-            ximagesink->fps_n);
-      }
-    }
-  }
-}
-
-static GstFlowReturn
-gst_ximagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
-{
-  GstXImageSink *ximagesink;
-
-  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
-  ximagesink = GST_XIMAGESINK (bsink);
-
-  /* If this buffer has been allocated using our buffer management we simply
-     put the ximage which is in the PRIVATE pointer */
-  if (GST_IS_XIMAGE_BUFFER (buf)) {
-    GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
-    if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
-      goto no_window;
-  } else {
-    /* Else we have to copy the data into our private image, */
-    /* if we have one... */
-    GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it");
-    if (!ximagesink->ximage) {
-      GST_DEBUG_OBJECT (ximagesink, "creating our ximage");
-      ximagesink->ximage = gst_ximagesink_ximage_new (ximagesink,
-          GST_BUFFER_CAPS (buf));
-      if (!ximagesink->ximage)
-        /* The create method should have posted an informative error */
-        goto no_ximage;
-
-      if (ximagesink->ximage->size < GST_BUFFER_SIZE (buf)) {
-        GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
-            ("Failed to create output image buffer of %dx%d pixels",
-                ximagesink->ximage->width, ximagesink->ximage->height),
-            ("XServer allocated buffer size did not match input buffer"));
-
-        gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
-        ximagesink->ximage = NULL;
-        goto no_ximage;
-      }
-    }
-    memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
-        MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size));
-    if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
-      goto no_window;
-  }
-
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-no_ximage:
-  {
-    /* No image available. That's very bad ! */
-    GST_DEBUG ("could not create image");
-    return GST_FLOW_ERROR;
-  }
-no_window:
-  {
-    /* No Window available to put our image into */
-    GST_WARNING_OBJECT (ximagesink, "could not output image - no window");
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* Buffer management
- *
- * The buffer_alloc function must either return a buffer with given size and
- * caps or create a buffer with different caps attached to the buffer. This
- * last option is called reverse negotiation, ie, where the sink suggests a
- * different format from the upstream peer. 
- *
- * We try to do reverse negotiation when our geometry changes and we like a
- * resized buffer.
- */
-static GstFlowReturn
-gst_ximagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstXImageSink *ximagesink;
-  GstXImageBuffer *ximage = NULL;
-  GstStructure *structure = NULL;
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstCaps *alloc_caps;
-  gboolean alloc_unref = FALSE;
-  gint width, height;
-
-  ximagesink = GST_XIMAGESINK (bsink);
-
-  GST_LOG_OBJECT (ximagesink,
-      "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT
-      " and offset %" G_GUINT64_FORMAT, size, caps, offset);
-
-  /* assume we're going to alloc what was requested, keep track of
-   * wheter we need to unref or not. When we suggest a new format 
-   * upstream we will create a new caps that we need to unref. */
-  alloc_caps = caps;
-  alloc_unref = FALSE;
-
-  /* get struct to see what is requested */
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (gst_structure_get_int (structure, "width", &width) &&
-      gst_structure_get_int (structure, "height", &height)) {
-    GstVideoRectangle dst, src, result;
-
-    src.w = width;
-    src.h = height;
-
-    /* We take the flow_lock because the window might go away */
-    g_mutex_lock (ximagesink->flow_lock);
-    if (!ximagesink->xwindow) {
-      g_mutex_unlock (ximagesink->flow_lock);
-      goto alloc;
-    }
-
-    /* What is our geometry */
-    gst_ximagesink_xwindow_update_geometry (ximagesink, ximagesink->xwindow);
-    dst.w = ximagesink->xwindow->width;
-    dst.h = ximagesink->xwindow->height;
-
-    g_mutex_unlock (ximagesink->flow_lock);
-
-    if (ximagesink->keep_aspect) {
-      GST_LOG_OBJECT (ximagesink, "enforcing aspect ratio in reverse caps "
-          "negotiation");
-      gst_video_sink_center_rect (src, dst, &result, TRUE);
-    } else {
-      GST_LOG_OBJECT (ximagesink, "trying to resize to window geometry "
-          "ignoring aspect ratio");
-      result.x = result.y = 0;
-      result.w = dst.w;
-      result.h = dst.h;
-    }
-
-    /* We would like another geometry */
-    if (width != result.w || height != result.h) {
-      int nom, den;
-      GstCaps *desired_caps;
-      GstStructure *desired_struct;
-
-      /* make a copy of the incomming caps to create the new
-       * suggestion. We can't use make_writable because we might
-       * then destroy the original caps which we still need when the
-       * peer does not accept the suggestion. */
-      desired_caps = gst_caps_copy (caps);
-      desired_struct = gst_caps_get_structure (desired_caps, 0);
-
-      GST_DEBUG ("we would love to receive a %dx%d video", result.w, result.h);
-      gst_structure_set (desired_struct, "width", G_TYPE_INT, result.w, NULL);
-      gst_structure_set (desired_struct, "height", G_TYPE_INT, result.h, NULL);
-
-      /* PAR property overrides the X calculated one */
-      if (ximagesink->par) {
-        nom = gst_value_get_fraction_numerator (ximagesink->par);
-        den = gst_value_get_fraction_denominator (ximagesink->par);
-        gst_structure_set (desired_struct, "pixel-aspect-ratio",
-            GST_TYPE_FRACTION, nom, den, NULL);
-      } else if (ximagesink->xcontext->par) {
-        nom = gst_value_get_fraction_numerator (ximagesink->xcontext->par);
-        den = gst_value_get_fraction_denominator (ximagesink->xcontext->par);
-        gst_structure_set (desired_struct, "pixel-aspect-ratio",
-            GST_TYPE_FRACTION, nom, den, NULL);
-      }
-
-      /* see if peer accepts our new suggestion, if there is no peer, this 
-       * function returns true. */
-      if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (ximagesink),
-              desired_caps)) {
-        gint bpp;
-
-        bpp = size / height / width;
-        /* we will not alloc a buffer of the new suggested caps. Make sure
-         * we also unref this new caps after we set it on the buffer. */
-        alloc_caps = desired_caps;
-        alloc_unref = TRUE;
-        width = result.w;
-        height = result.h;
-        size = bpp * width * height;
-        GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT
-            " buffer size is now %d bytes", desired_caps, size);
-      } else {
-        GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT,
-            desired_caps);
-        /* we alloc a buffer with the original incomming caps */
-        width = GST_VIDEO_SINK_WIDTH (ximagesink);
-        height = GST_VIDEO_SINK_HEIGHT (ximagesink);
-      }
-    }
-  }
-
-alloc:
-  /* Inspect our buffer pool */
-  g_mutex_lock (ximagesink->pool_lock);
-  while (ximagesink->buffer_pool) {
-    ximage = (GstXImageBuffer *) ximagesink->buffer_pool->data;
-
-    if (ximage) {
-      /* Removing from the pool */
-      ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
-          ximagesink->buffer_pool);
-
-      /* If the ximage is invalid for our need, destroy */
-      if ((ximage->width != width) || (ximage->height != height)) {
-        gst_ximage_buffer_free (ximage);
-        ximage = NULL;
-      } else {
-        /* We found a suitable ximage */
-        break;
-      }
-    }
-  }
-  g_mutex_unlock (ximagesink->pool_lock);
-
-  /* We haven't found anything, creating a new one */
-  if (!ximage) {
-    ximage = gst_ximagesink_ximage_new (ximagesink, alloc_caps);
-  }
-  /* Now we should have a ximage, set appropriate caps on it */
-  if (ximage) {
-    gst_buffer_set_caps (GST_BUFFER_CAST (ximage), alloc_caps);
-  }
-
-  /* could be our new reffed suggestion or the original unreffed caps */
-  if (alloc_unref)
-    gst_caps_unref (alloc_caps);
-
-  *buf = GST_BUFFER_CAST (ximage);
-
-  return ret;
-}
-
-/* Interfaces stuff */
-
-static gboolean
-gst_ximagesink_interface_supported (GstImplementsInterface * iface, GType type)
-{
-  g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY);
-  return TRUE;
-}
-
-static void
-gst_ximagesink_interface_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = gst_ximagesink_interface_supported;
-}
-
-static void
-gst_ximagesink_navigation_send_event (GstNavigation * navigation,
-    GstStructure * structure)
-{
-  GstXImageSink *ximagesink = GST_XIMAGESINK (navigation);
-  GstEvent *event;
-  gint x_offset, y_offset;
-  gdouble x, y;
-  GstPad *pad = NULL;
-
-  event = gst_event_new_navigation (structure);
-
-  /* We are not converting the pointer coordinates as there's no hardware
-     scaling done here. The only possible scaling is done by videoscale and
-     videoscale will have to catch those events and tranform the coordinates
-     to match the applied scaling. So here we just add the offset if the image
-     is centered in the window.  */
-
-  /* We take the flow_lock while we look at the window */
-  g_mutex_lock (ximagesink->flow_lock);
-
-  if (!ximagesink->xwindow) {
-    g_mutex_unlock (ximagesink->flow_lock);
-    return;
-  }
-
-  x_offset = ximagesink->xwindow->width - GST_VIDEO_SINK_WIDTH (ximagesink);
-  y_offset = ximagesink->xwindow->height - GST_VIDEO_SINK_HEIGHT (ximagesink);
-
-  g_mutex_unlock (ximagesink->flow_lock);
-
-  if (gst_structure_get_double (structure, "pointer_x", &x)) {
-    x -= x_offset / 2;
-    gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL);
-  }
-  if (gst_structure_get_double (structure, "pointer_y", &y)) {
-    y -= y_offset / 2;
-    gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL);
-  }
-
-  pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (ximagesink));
-
-  if (GST_IS_PAD (pad) && GST_IS_EVENT (event)) {
-    gst_pad_send_event (pad, event);
-
-    gst_object_unref (pad);
-  }
-}
-
-static void
-gst_ximagesink_navigation_init (GstNavigationInterface * iface)
-{
-  iface->send_event = gst_ximagesink_navigation_send_event;
-}
-
-static void
-gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
-  GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
-  GstXWindow *xwindow = NULL;
-  XWindowAttributes attr;
-
-  /* We acquire the stream lock while setting this window in the element.
-     We are basically cleaning tons of stuff replacing the old window, putting
-     images while we do that would surely crash */
-  g_mutex_lock (ximagesink->flow_lock);
-
-  /* If we already use that window return */
-  if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win)) {
-    g_mutex_unlock (ximagesink->flow_lock);
-    return;
-  }
-
-  /* If the element has not initialized the X11 context try to do so */
-  if (!ximagesink->xcontext &&
-      !(ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink))) {
-    g_mutex_unlock (ximagesink->flow_lock);
-    /* we have thrown a GST_ELEMENT_ERROR now */
-    return;
-  }
-
-  /* If a window is there already we destroy it */
-  if (ximagesink->xwindow) {
-    gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
-    ximagesink->xwindow = NULL;
-  }
-
-  /* If the xid is 0 we go back to an internal window */
-  if (xwindow_id == 0) {
-    /* If no width/height caps nego did not happen window will be created
-       during caps nego then */
-    if (GST_VIDEO_SINK_WIDTH (ximagesink) && GST_VIDEO_SINK_HEIGHT (ximagesink)) {
-      xwindow = gst_ximagesink_xwindow_new (ximagesink,
-          GST_VIDEO_SINK_WIDTH (ximagesink),
-          GST_VIDEO_SINK_HEIGHT (ximagesink));
-    }
-  } else {
-    xwindow = g_new0 (GstXWindow, 1);
-
-    xwindow->win = xwindow_id;
-
-    /* We get window geometry, set the event we want to receive,
-       and create a GC */
-    g_mutex_lock (ximagesink->x_lock);
-    XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr);
-    xwindow->width = attr.width;
-    xwindow->height = attr.height;
-    xwindow->internal = FALSE;
-    if (ximagesink->handle_events) {
-      XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
-          StructureNotifyMask | PointerMotionMask | KeyPressMask |
-          KeyReleaseMask);
-    }
-
-    xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win, 0, NULL);
-    g_mutex_unlock (ximagesink->x_lock);
-  }
-
-  if (xwindow)
-    ximagesink->xwindow = xwindow;
-
-  g_mutex_unlock (ximagesink->flow_lock);
-}
-
-static void
-gst_ximagesink_expose (GstXOverlay * overlay)
-{
-  GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
-
-  gst_ximagesink_ximage_put (ximagesink, NULL);
-}
-
-static void
-gst_ximagesink_set_event_handling (GstXOverlay * overlay,
-    gboolean handle_events)
-{
-  GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
-
-  ximagesink->handle_events = handle_events;
-
-  g_mutex_lock (ximagesink->flow_lock);
-
-  if (G_UNLIKELY (!ximagesink->xwindow)) {
-    g_mutex_unlock (ximagesink->flow_lock);
-    return;
-  }
-
-  g_mutex_lock (ximagesink->x_lock);
-
-  if (handle_events) {
-    if (ximagesink->xwindow->internal) {
-      XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win,
-          ExposureMask | StructureNotifyMask | PointerMotionMask |
-          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-    } else {
-      XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win,
-          ExposureMask | StructureNotifyMask | PointerMotionMask |
-          KeyPressMask | KeyReleaseMask);
-    }
-  } else {
-    XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win, 0);
-  }
-
-  g_mutex_unlock (ximagesink->x_lock);
-
-  g_mutex_unlock (ximagesink->flow_lock);
-}
-
-static void
-gst_ximagesink_xoverlay_init (GstXOverlayClass * iface)
-{
-  iface->set_xwindow_id = gst_ximagesink_set_xwindow_id;
-  iface->expose = gst_ximagesink_expose;
-  iface->handle_events = gst_ximagesink_set_event_handling;
-}
-
-/* =========================================== */
-/*                                             */
-/*              Init & Class init              */
-/*                                             */
-/* =========================================== */
-
-static void
-gst_ximagesink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstXImageSink *ximagesink;
-
-  g_return_if_fail (GST_IS_XIMAGESINK (object));
-
-  ximagesink = GST_XIMAGESINK (object);
-
-  switch (prop_id) {
-    case PROP_DISPLAY:
-      ximagesink->display_name = g_strdup (g_value_get_string (value));
-      break;
-    case PROP_SYNCHRONOUS:
-      ximagesink->synchronous = g_value_get_boolean (value);
-      if (ximagesink->xcontext) {
-        GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s",
-            ximagesink->synchronous ? "TRUE" : "FALSE");
-        g_mutex_lock (ximagesink->x_lock);
-        XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous);
-        g_mutex_unlock (ximagesink->x_lock);
-      }
-      break;
-    case PROP_FORCE_ASPECT_RATIO:
-      ximagesink->keep_aspect = g_value_get_boolean (value);
-      break;
-    case PROP_PIXEL_ASPECT_RATIO:
-    {
-      GValue *tmp;
-
-      tmp = g_new0 (GValue, 1);
-      g_value_init (tmp, GST_TYPE_FRACTION);
-
-      if (!g_value_transform (value, tmp)) {
-        GST_WARNING_OBJECT (ximagesink,
-            "Could not transform string to aspect ratio");
-        g_free (tmp);
-      } else {
-        GST_DEBUG_OBJECT (ximagesink, "set PAR to %d/%d",
-            gst_value_get_fraction_numerator (tmp),
-            gst_value_get_fraction_denominator (tmp));
-        g_free (ximagesink->par);
-        ximagesink->par = tmp;
-      }
-    }
-      break;
-    case PROP_HANDLE_EVENTS:
-      gst_ximagesink_set_event_handling (GST_X_OVERLAY (ximagesink),
-          g_value_get_boolean (value));
-      break;
-    case PROP_HANDLE_EXPOSE:
-      ximagesink->handle_expose = g_value_get_boolean (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_ximagesink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstXImageSink *ximagesink;
-
-  g_return_if_fail (GST_IS_XIMAGESINK (object));
-
-  ximagesink = GST_XIMAGESINK (object);
-
-  switch (prop_id) {
-    case PROP_DISPLAY:
-      g_value_set_string (value, ximagesink->display_name);
-      break;
-    case PROP_SYNCHRONOUS:
-      g_value_set_boolean (value, ximagesink->synchronous);
-      break;
-    case PROP_FORCE_ASPECT_RATIO:
-      g_value_set_boolean (value, ximagesink->keep_aspect);
-      break;
-    case PROP_PIXEL_ASPECT_RATIO:
-      if (ximagesink->par)
-        g_value_transform (ximagesink->par, value);
-      break;
-    case PROP_HANDLE_EVENTS:
-      g_value_set_boolean (value, ximagesink->handle_events);
-      break;
-    case PROP_HANDLE_EXPOSE:
-      g_value_set_boolean (value, ximagesink->handle_expose);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_ximagesink_reset (GstXImageSink * ximagesink)
-{
-  GThread *thread;
-
-  GST_OBJECT_LOCK (ximagesink);
-  ximagesink->running = FALSE;
-  /* grab thread and mark it as NULL */
-  thread = ximagesink->event_thread;
-  ximagesink->event_thread = NULL;
-  GST_OBJECT_UNLOCK (ximagesink);
-
-  /* Wait for our event thread to finish before we clean up our stuff. */
-  if (thread)
-    g_thread_join (thread);
-
-  if (ximagesink->ximage) {
-    gst_buffer_unref (ximagesink->ximage);
-    ximagesink->ximage = NULL;
-  }
-  if (ximagesink->cur_image) {
-    gst_buffer_unref (ximagesink->cur_image);
-    ximagesink->cur_image = NULL;
-  }
-
-  gst_ximagesink_bufferpool_clear (ximagesink);
-
-  g_mutex_lock (ximagesink->flow_lock);
-  if (ximagesink->xwindow) {
-    gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
-    gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
-    ximagesink->xwindow = NULL;
-  }
-  g_mutex_unlock (ximagesink->flow_lock);
-
-  gst_ximagesink_xcontext_clear (ximagesink);
-}
-
-static void
-gst_ximagesink_finalize (GObject * object)
-{
-  GstXImageSink *ximagesink;
-
-  ximagesink = GST_XIMAGESINK (object);
-
-  gst_ximagesink_reset (ximagesink);
-
-  if (ximagesink->display_name) {
-    g_free (ximagesink->display_name);
-    ximagesink->display_name = NULL;
-  }
-  if (ximagesink->par) {
-    g_free (ximagesink->par);
-    ximagesink->par = NULL;
-  }
-  if (ximagesink->x_lock) {
-    g_mutex_free (ximagesink->x_lock);
-    ximagesink->x_lock = NULL;
-  }
-  if (ximagesink->flow_lock) {
-    g_mutex_free (ximagesink->flow_lock);
-    ximagesink->flow_lock = NULL;
-  }
-  if (ximagesink->pool_lock) {
-    g_mutex_free (ximagesink->pool_lock);
-    ximagesink->pool_lock = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_ximagesink_init (GstXImageSink * ximagesink)
-{
-  ximagesink->display_name = NULL;
-  ximagesink->xcontext = NULL;
-  ximagesink->xwindow = NULL;
-  ximagesink->ximage = NULL;
-  ximagesink->cur_image = NULL;
-
-  ximagesink->event_thread = NULL;
-  ximagesink->running = FALSE;
-
-  ximagesink->fps_n = 0;
-  ximagesink->fps_d = 1;
-
-  ximagesink->x_lock = g_mutex_new ();
-  ximagesink->flow_lock = g_mutex_new ();
-
-  ximagesink->par = NULL;
-
-  ximagesink->pool_lock = g_mutex_new ();
-  ximagesink->buffer_pool = NULL;
-
-  ximagesink->synchronous = FALSE;
-  ximagesink->keep_aspect = FALSE;
-  ximagesink->handle_events = TRUE;
-  ximagesink->handle_expose = TRUE;
-}
-
-static void
-gst_ximagesink_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_ximagesink_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_ximagesink_sink_template_factory));
-}
-
-static void
-gst_ximagesink_class_init (GstXImageSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSinkClass *gstbasesink_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesink_class = (GstBaseSinkClass *) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->finalize = gst_ximagesink_finalize;
-  gobject_class->set_property = gst_ximagesink_set_property;
-  gobject_class->get_property = gst_ximagesink_get_property;
-
-  g_object_class_install_property (gobject_class, PROP_DISPLAY,
-      g_param_spec_string ("display", "Display", "X Display name",
-          NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
-      g_param_spec_boolean ("synchronous", "Synchronous", "When enabled, runs "
-          "the X display in synchronous mode. (used only for debugging)", FALSE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
-      g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
-          "When enabled, reverse caps negotiation (scaling) will respect "
-          "original aspect ratio", FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
-      g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
-          "The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS,
-      g_param_spec_boolean ("handle-events", "Handle XEvents",
-          "When enabled, XEvents will be selected and handled", TRUE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_HANDLE_EXPOSE,
-      g_param_spec_boolean ("handle-expose", "Handle expose", "When enabled, "
-          "the current frame will always be drawn in response to X Expose "
-          "events", TRUE, G_PARAM_READWRITE));
-
-  gstelement_class->change_state = gst_ximagesink_change_state;
-
-  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
-  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
-  gstbasesink_class->buffer_alloc =
-      GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
-  gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
-  gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
-  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
-}
-
-/* ============================================================= */
-/*                                                               */
-/*                       Public Methods                          */
-/*                                                               */
-/* ============================================================= */
-
-/* =========================================== */
-/*                                             */
-/*          Object typing & Creation           */
-/*                                             */
-/* =========================================== */
-
-GType
-gst_ximagesink_get_type (void)
-{
-  static GType ximagesink_type = 0;
-
-  if (!ximagesink_type) {
-    static const GTypeInfo ximagesink_info = {
-      sizeof (GstXImageSinkClass),
-      gst_ximagesink_base_init,
-      NULL,
-      (GClassInitFunc) gst_ximagesink_class_init,
-      NULL,
-      NULL,
-      sizeof (GstXImageSink),
-      0,
-      (GInstanceInitFunc) gst_ximagesink_init,
-    };
-    static const GInterfaceInfo iface_info = {
-      (GInterfaceInitFunc) gst_ximagesink_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo navigation_info = {
-      (GInterfaceInitFunc) gst_ximagesink_navigation_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo overlay_info = {
-      (GInterfaceInitFunc) gst_ximagesink_xoverlay_init,
-      NULL,
-      NULL,
-    };
-
-    ximagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
-        "GstXImageSink", &ximagesink_info, 0);
-
-    g_type_add_interface_static (ximagesink_type, GST_TYPE_IMPLEMENTS_INTERFACE,
-        &iface_info);
-    g_type_add_interface_static (ximagesink_type, GST_TYPE_NAVIGATION,
-        &navigation_info);
-    g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY,
-        &overlay_info);
-
-    /* register type and create class in a more safe place instead of at
-     * runtime since the type registration and class creation is not
-     * threadsafe. */
-    g_type_class_ref (gst_ximage_buffer_get_type ());
-  }
-
-  return ximagesink_type;
-}
--- a/gst_plugins_base/sys/ximage/ximagesink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
- *
- * 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_XIMAGESINK_H__
-#define __GST_XIMAGESINK_H__
-
-#include <gst/video/gstvideosink.h>
-
-#ifdef HAVE_XSHM
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif /* HAVE_XSHM */
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#ifdef HAVE_XSHM
-#include <X11/extensions/XShm.h>
-#endif /* HAVE_XSHM */
-
-#include <string.h>
-#include <math.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_XIMAGESINK \
-  (gst_ximagesink_get_type())
-#define GST_XIMAGESINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XIMAGESINK, GstXImageSink))
-#define GST_XIMAGESINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XIMAGESINK, GstXImageSinkClass))
-#define GST_IS_XIMAGESINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XIMAGESINK))
-#define GST_IS_XIMAGESINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XIMAGESINK))
-
-typedef struct _GstXContext GstXContext;
-typedef struct _GstXWindow GstXWindow;
-
-typedef struct _GstXImageBuffer GstXImageBuffer;
-typedef struct _GstXImageBufferClass GstXImageBufferClass;
-
-typedef struct _GstXImageSink GstXImageSink;
-typedef struct _GstXImageSinkClass GstXImageSinkClass;
-
-/**
- * GstXContext:
- * @disp: the X11 Display of this context
- * @screen: the default Screen of Display @disp
- * @screen_num: the Screen number of @screen
- * @visual: the default Visual of Screen @screen
- * @root: the root Window of Display @disp
- * @white: the value of a white pixel on Screen @screen
- * @black: the value of a black pixel on Screen @screen
- * @depth: the color depth of Display @disp
- * @bpp: the number of bits per pixel on Display @disp
- * @endianness: the endianness of image bytes on Display @disp
- * @width: the width in pixels of Display @disp
- * @height: the height in pixels of Display @disp
- * @widthmm: the width in millimeters of Display @disp
- * @heightmm: the height in millimeters of Display @disp
- * @par: the pixel aspect ratio calculated from @width, @widthmm and @height, 
- * @heightmm ratio
- * @use_xshm: used to known wether of not XShm extension is usable or not even
- * if the Extension is present
- * @caps: the #GstCaps that Display @disp can accept
- *
- * Structure used to store various informations collected/calculated for a
- * Display.
- */
-struct _GstXContext {
-  Display *disp;
-
-  Screen *screen;
-  gint screen_num;
-
-  Visual *visual;
-
-  Window root;
-
-  gulong white, black;
-
-  gint depth;
-  gint bpp;
-  gint endianness;
-
-  gint width, height;
-  gint widthmm, heightmm;
-  GValue *par;                  /* calculated pixel aspect ratio */
-
-  gboolean use_xshm;
-
-  GstCaps *caps;
-};
-
-/**
- * GstXWindow:
- * @win: the Window ID of this X11 window
- * @width: the width in pixels of Window @win
- * @height: the height in pixels of Window @win
- * @internal: used to remember if Window @win was created internally or passed
- * through the #GstXOverlay interface
- * @gc: the Graphical Context of Window @win
- *
- * Structure used to store informations about a Window.
- */
-struct _GstXWindow {
-  Window win;
-  gint width, height;
-  gboolean internal;
-  GC gc;
-};
-
-/**
- * GstXImageBuffer:
- * @ximagesink: a reference to our #GstXImageSink
- * @ximage: the XImage of this buffer
- * @width: the width in pixels of XImage @ximage
- * @height: the height in pixels of XImage @ximage
- * @size: the size in bytes of XImage @ximage
- *
- * Subclass of #GstBuffer containing additional information about an XImage.
- */
-struct _GstXImageBuffer {
-  GstBuffer buffer;
-
-  /* Reference to the ximagesink we belong to */
-  GstXImageSink *ximagesink;
-
-  XImage *ximage;
-
-#ifdef HAVE_XSHM
-  XShmSegmentInfo SHMInfo;
-#endif /* HAVE_XSHM */
-
-  gint width, height;
-  size_t size;
-};
-
-/**
- * GstXImageSink:
- * @display_name: the name of the Display we want to render to
- * @xcontext: our instance's #GstXContext
- * @xwindow: the #GstXWindow we are rendering to
- * @ximage: internal #GstXImage used to store incoming buffers and render when
- * not using the buffer_alloc optimization mechanism
- * @cur_image: a reference to the last #GstXImage that was put to @xwindow. It
- * is used when Expose events are received to redraw the latest video frame
- * @event_thread: a thread listening for events on @xwindow and handling them
- * @running: used to inform @event_thread if it should run/shutdown
- * @fps_n: the framerate fraction numerator
- * @fps_d: the framerate fraction denominator
- * @x_lock: used to protect X calls as we are not using the XLib in threaded
- * mode
- * @flow_lock: used to protect data flow routines from external calls such as
- * events from @event_thread or methods from the #GstXOverlay interface
- * @par: used to override calculated pixel aspect ratio from @xcontext
- * @pool_lock: used to protect the buffer pool
- * @buffer_pool: a list of #GstXImageBuffer that could be reused at next buffer
- * allocation call
- * @synchronous: used to store if XSynchronous should be used or not (for 
- * debugging purpose only)
- * @keep_aspect: used to remember if reverse negotiation scaling should respect
- * aspect ratio
- * @handle_events: used to know if we should handle select XEvents or not
- *
- * The #GstXImageSink data structure.
- */
-struct _GstXImageSink {
-  /* Our element stuff */
-  GstVideoSink videosink;
-
-  char *display_name;
-
-  GstXContext *xcontext;
-  GstXWindow *xwindow;
-  GstXImageBuffer *ximage;
-  GstXImageBuffer *cur_image;
-  
-  GThread *event_thread;
-  gboolean running;
-
-  /* Framerate numerator and denominator */
-  gint fps_n;
-  gint fps_d;
-
-  GMutex *x_lock;
-  GMutex *flow_lock;
-  
-  /* object-set pixel aspect ratio */
-  GValue *par;
-
-  GMutex *pool_lock;
-  GSList *buffer_pool;
-
-  gboolean synchronous;
-  gboolean keep_aspect;
-  gboolean handle_events;
-  gboolean handle_expose;
-};
-
-struct _GstXImageSinkClass {
-  GstVideoSinkClass parent_class;
-};
-
-GType gst_ximagesink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_XIMAGESINK_H__ */
--- a/gst_plugins_base/sys/xvimage/xvimagesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3254 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
- *
- * 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.
- */
-
-/**
- * SECTION:element-xvimagesink
- *
- * <refsect2>
- * <para>
- * XvImageSink renders video frames to a drawable (XWindow) on a local display
- * using the XVideo extension. Rendering to a remote display is theorically
- * possible but i doubt that the XVideo extension is actually available when
- * connecting to a remote display. This element can receive a Window ID from the
- * application through the XOverlay interface and will then render video frames
- * in this drawable. If no Window ID was provided by the application, the
- * element will create its own internal window and render into it.
- * </para>
- * <title>Scaling</title>
- * <para>
- * The XVideo extension, when it's available, handles hardware accelerated
- * scaling of video frames. This means that the element will just accept
- * incoming video frames no matter their geometry and will then put them to the
- * drawable scaling them on the fly. Using the
- * <link linkend="GstXvImageSink--force-aspect-ratio">force-aspect-ratio</link>
- * property it is possible to enforce scaling with a constant aspect ratio,
- * which means drawing black borders around the video frame.
- * </para>
- * <title>Events</title>
- * <para>
- * XvImageSink creates a thread to handle events coming from the drawable. There
- * are several kind of events that can be grouped in 2 big categories: input
- * events and window state related events. Input events will be translated to
- * navigation events and pushed upstream for other elements to react on them.
- * This includes events such as pointer moves, key press/release, clicks etc...
- * Other events are used to handle the drawable appearance even when the data
- * is not flowing (GST_STATE_PAUSED). That means that even when the element is
- * paused, it will receive expose events from the drawable and draw the latest
- * frame with correct borders/aspect-ratio.
- * </para>
- * <title>Pixel aspect ratio</title>
- * <para>
- * When changing state to GST_STATE_READY, XvImageSink will open a connection to
- * the display specified in the
- * <link linkend="GstXvImageSink--display">display</link> property or the
- * default display if nothing specified. Once this connection is open it will
- * inspect the display configuration including the physical display geometry and
- * then calculate the pixel aspect ratio. When receiving video frames with a
- * different pixel aspect ratio, XvImageSink will use hardware scaling to
- * display the video frames correctly on display's pixel aspect ratio.
- * Sometimes the calculated pixel aspect ratio can be wrong, it is
- * then possible to enforce a specific pixel aspect ratio using the
- * <link linkend="GstXvImageSink--pixel-aspect-ratio">pixel-aspect-ratio</link>
- * property.
- * </para>
- * <title>Examples</title>
- * <para>
- * Here is a simple pipeline to test hardware scaling :
- * <programlisting>
- * gst-launch -v videotestsrc ! xvimagesink
- * </programlisting>
- * When the test video signal appears you can resize the window and see that
- * video frames are scaled through hardware (no extra CPU cost). You can try
- * again setting the force-aspect-ratio property to true and observe the borders
- * drawn around the scaled image respecting aspect ratio.
- * <programlisting>
- * gst-launch -v videotestsrc ! xvimagesink force-aspect-ratio=true
- * </programlisting>
- * </para>
- * <para>
- * Here is a simple pipeline to test navigation events :
- * <programlisting>
- * gst-launch -v videotestsrc ! navigationtest ! xvimagesink
- * </programlisting>
- * While moving the mouse pointer over the test signal you will see a black box
- * following the mouse pointer. If you press the mouse button somewhere on the
- * video and release it somewhere else a green box will appear where you pressed
- * the button and a red one where you released it. (The navigationtest element
- * is part of gst-plugins-good.) You can observe here that even if the images
- * are scaled through hardware the pointer coordinates are converted back to the
- * original video frame geometry so that the box can be drawn to the correct
- * position. This also handles borders correctly, limiting coordinates to the
- * image area
- * </para>
- * <para>
- * Here is a simple pipeline to test pixel aspect ratio :
- * <programlisting>
- * gst-launch -v videotestsrc ! video/x-raw-yuv, pixel-aspect-ratio=(fraction)4/3 ! xvimagesink
- * </programlisting>
- * This is faking a 4/3 pixel aspect ratio caps on video frames produced by
- * videotestsrc, in most cases the pixel aspect ratio of the display will be
- * 1/1. This means that XvImageSink will have to do the scaling to convert
- * incoming frames to a size that will match the display pixel aspect ratio
- * (from 320x240 to 320x180 in this case). Note that you might have to escape
- * some characters for your shell like '\(fraction\)'.
- * </para>
- * <para>
- * Here is a test pipeline to test the colorbalance interface :
- * <programlisting>
- * gst-launch -v videotestsrc ! xvimagesink hue=100 saturation=-100 brightness=100
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Our interfaces */
-#include <gst/interfaces/navigation.h>
-#include <gst/interfaces/xoverlay.h>
-#include <gst/interfaces/colorbalance.h>
-#include <gst/interfaces/propertyprobe.h>
-/* Helper functions */
-#include <gst/video/video.h>
-
-/* Object header */
-#include "xvimagesink.h"
-
-/* Debugging category */
-#include <gst/gstinfo.h>
-GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink);
-#define GST_CAT_DEFAULT gst_debug_xvimagesink
-
-typedef struct
-{
-  unsigned long flags;
-  unsigned long functions;
-  unsigned long decorations;
-  long input_mode;
-  unsigned long status;
-}
-MotifWmHints, MwmHints;
-
-#define MWM_HINTS_DECORATIONS   (1L << 1)
-
-static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
-
-static GstBufferClass *xvimage_buffer_parent_class = NULL;
-static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
-
-static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
-    xvimagesink, GstXWindow * xwindow);
-static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
-    GstCaps * caps);
-static void gst_xvimagesink_expose (GstXOverlay * overlay);
-
-/* ElementFactory information */
-static const GstElementDetails gst_xvimagesink_details =
-GST_ELEMENT_DETAILS ("Video sink",
-    "Sink/Video",
-    "A Xv based videosink",
-    "Julien Moutte <julien@moutte.net>");
-
-/* Default template - initiated with class struct to allow gst-register to work
-   without X running */
-static GstStaticPadTemplate gst_xvimagesink_sink_template_factory =
-    GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-rgb, "
-        "framerate = (fraction) [ 0, MAX ], "
-        "width = (int) [ 1, MAX ], "
-        "height = (int) [ 1, MAX ]; "
-        "video/x-raw-yuv, "
-        "framerate = (fraction) [ 0, MAX ], "
-        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
-    );
-
-enum
-{
-  ARG_0,
-  ARG_CONTRAST,
-  ARG_BRIGHTNESS,
-  ARG_HUE,
-  ARG_SATURATION,
-  ARG_DISPLAY,
-  ARG_SYNCHRONOUS,
-  ARG_PIXEL_ASPECT_RATIO,
-  ARG_FORCE_ASPECT_RATIO,
-  ARG_HANDLE_EVENTS,
-  ARG_DEVICE,
-  ARG_DEVICE_NAME,
-  ARG_HANDLE_EXPOSE,
-  ARG_DOUBLE_BUFFER
-};
-
-static GstVideoSinkClass *parent_class = NULL;
-
-/* ============================================================= */
-/*                                                               */
-/*                       Private Methods                         */
-/*                                                               */
-/* ============================================================= */
-
-/* xvimage buffers */
-
-#define GST_TYPE_XVIMAGE_BUFFER (gst_xvimage_buffer_get_type())
-
-#define GST_IS_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER))
-#define GST_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER, GstXvImageBuffer))
-
-/* This function destroys a GstXvImage handling XShm availability */
-static void
-gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
-{
-  GstXvImageSink *xvimagesink;
-
-  GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
-
-  xvimagesink = xvimage->xvimagesink;
-  if (G_UNLIKELY (xvimagesink == NULL))
-    goto no_sink;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  GST_OBJECT_LOCK (xvimagesink);
-
-  /* If the destroyed image is the current one we destroy our reference too */
-  if (xvimagesink->cur_image == xvimage)
-    xvimagesink->cur_image = NULL;
-
-  /* We might have some buffers destroyed after changing state to NULL */
-  if (xvimagesink->xcontext == NULL) {
-    GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
-#ifdef HAVE_XSHM
-    /* Need to free the shared memory segment even if the x context
-     * was already cleaned up */
-    if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
-      shmdt (xvimage->SHMInfo.shmaddr);
-    }
-#endif
-    goto beach;
-  }
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-#ifdef HAVE_XSHM
-  if (xvimagesink->xcontext->use_xshm) {
-    if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
-      GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
-          xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
-      XShmDetach (xvimagesink->xcontext->disp, &xvimage->SHMInfo);
-      XSync (xvimagesink->xcontext->disp, FALSE);
-
-      shmdt (xvimage->SHMInfo.shmaddr);
-    }
-    if (xvimage->xvimage)
-      XFree (xvimage->xvimage);
-  } else
-#endif /* HAVE_XSHM */
-  {
-    if (xvimage->xvimage) {
-      if (xvimage->xvimage->data) {
-        g_free (xvimage->xvimage->data);
-      }
-      XFree (xvimage->xvimage);
-    }
-  }
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-beach:
-  GST_OBJECT_UNLOCK (xvimagesink);
-  xvimage->xvimagesink = NULL;
-  gst_object_unref (xvimagesink);
-
-  GST_MINI_OBJECT_CLASS (xvimage_buffer_parent_class)->
-      finalize (GST_MINI_OBJECT (xvimage));
-
-  return;
-
-no_sink:
-  {
-    GST_WARNING ("no sink found");
-    return;
-  }
-}
-
-static void
-gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
-{
-  GstXvImageSink *xvimagesink;
-  gboolean running;
-
-  xvimagesink = xvimage->xvimagesink;
-  if (G_UNLIKELY (xvimagesink == NULL))
-    goto no_sink;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  GST_OBJECT_LOCK (xvimagesink);
-  running = xvimagesink->running;
-  GST_OBJECT_UNLOCK (xvimagesink);
-
-  /* If our geometry changed we can't reuse that image. */
-  if (running == FALSE) {
-    GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
-    gst_xvimage_buffer_destroy (xvimage);
-  } else if ((xvimage->width != xvimagesink->video_width) ||
-      (xvimage->height != xvimagesink->video_height)) {
-    GST_LOG_OBJECT (xvimage,
-        "destroy image as its size changed %dx%d vs current %dx%d",
-        xvimage->width, xvimage->height,
-        xvimagesink->video_width, xvimagesink->video_height);
-    gst_xvimage_buffer_destroy (xvimage);
-  } else {
-    /* In that case we can reuse the image and add it to our image pool. */
-    GST_LOG_OBJECT (xvimage, "recycling image in pool");
-    /* need to increment the refcount again to recycle */
-    gst_buffer_ref (GST_BUFFER (xvimage));
-    g_mutex_lock (xvimagesink->pool_lock);
-    xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
-        xvimage);
-    g_mutex_unlock (xvimagesink->pool_lock);
-  }
-  return;
-
-no_sink:
-  {
-    GST_WARNING ("no sink found");
-    return;
-  }
-}
-
-static void
-gst_xvimage_buffer_free (GstXvImageBuffer * xvimage)
-{
-  /* make sure it is not recycled */
-  xvimage->width = -1;
-  xvimage->height = -1;
-  gst_buffer_unref (GST_BUFFER (xvimage));
-}
-
-static void
-gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
-{
-#ifdef HAVE_XSHM
-  xvimage->SHMInfo.shmaddr = ((void *) -1);
-  xvimage->SHMInfo.shmid = -1;
-#endif
-}
-
-static void
-gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
-{
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
-  xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
-
-  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-      gst_xvimage_buffer_finalize;
-}
-
-static GType
-gst_xvimage_buffer_get_type (void)
-{
-  static GType _gst_xvimage_buffer_type;
-
-  if (G_UNLIKELY (_gst_xvimage_buffer_type == 0)) {
-    static const GTypeInfo xvimage_buffer_info = {
-      sizeof (GstBufferClass),
-      NULL,
-      NULL,
-      gst_xvimage_buffer_class_init,
-      NULL,
-      NULL,
-      sizeof (GstXvImageBuffer),
-      0,
-      (GInstanceInitFunc) gst_xvimage_buffer_init,
-      NULL
-    };
-    _gst_xvimage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
-        "GstXvImageBuffer", &xvimage_buffer_info, 0);
-  }
-  return _gst_xvimage_buffer_type;
-}
-
-/* X11 stuff */
-
-static gboolean error_caught = FALSE;
-
-static int
-gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
-{
-  char error_msg[1024];
-
-  XGetErrorText (display, xevent->error_code, error_msg, 1024);
-  GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
-  error_caught = TRUE;
-  return 0;
-}
-
-#ifdef HAVE_XSHM
-/* This function checks that it is actually really possible to create an image
-   using XShm */
-static gboolean
-gst_xvimagesink_check_xshm_calls (GstXContext * xcontext)
-{
-  XvImage *xvimage;
-  XShmSegmentInfo SHMInfo;
-  gint size;
-  int (*handler) (Display *, XErrorEvent *);
-  gboolean result = FALSE;
-  gboolean did_attach = FALSE;
-
-  g_return_val_if_fail (xcontext != NULL, FALSE);
-
-  /* Sync to ensure any older errors are already processed */
-  XSync (xcontext->disp, FALSE);
-
-  /* Set defaults so we don't free these later unnecessarily */
-  SHMInfo.shmaddr = ((void *) -1);
-  SHMInfo.shmid = -1;
-
-  /* Setting an error handler to catch failure */
-  error_caught = FALSE;
-  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
-  /* Trying to create a 1x1 picture */
-  GST_DEBUG ("XvShmCreateImage of 1x1");
-  xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
-      xcontext->im_format, NULL, 1, 1, &SHMInfo);
-
-  /* Might cause an error, sync to ensure it is noticed */
-  XSync (xcontext->disp, FALSE);
-  if (!xvimage || error_caught) {
-    GST_WARNING ("could not XvShmCreateImage a 1x1 image");
-    goto beach;
-  }
-  size = xvimage->data_size;
-
-  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
-  if (SHMInfo.shmid == -1) {
-    GST_WARNING ("could not get shared memory of %d bytes", size);
-    goto beach;
-  }
-
-  SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
-  if (SHMInfo.shmaddr == ((void *) -1)) {
-    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
-    /* Clean up the shared memory segment */
-    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-    goto beach;
-  }
-
-  /* Delete the shared memory segment as soon as we manage to attach.
-   * This way, it will be deleted as soon as we detach later, and not
-   * leaked if we crash. */
-  shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-
-  xvimage->data = SHMInfo.shmaddr;
-  SHMInfo.readOnly = FALSE;
-
-  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
-    GST_WARNING ("Failed to XShmAttach");
-    goto beach;
-  }
-
-  /* Sync to ensure we see any errors we caused */
-  XSync (xcontext->disp, FALSE);
-
-  GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
-      SHMInfo.shmseg);
-
-  if (!error_caught) {
-    did_attach = TRUE;
-    /* store whether we succeeded in result */
-    result = TRUE;
-  }
-
-beach:
-  /* Sync to ensure we swallow any errors we caused and reset error_caught */
-  XSync (xcontext->disp, FALSE);
-
-  error_caught = FALSE;
-  XSetErrorHandler (handler);
-
-  if (did_attach) {
-    GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
-        SHMInfo.shmid, SHMInfo.shmseg);
-    XShmDetach (xcontext->disp, &SHMInfo);
-    XSync (xcontext->disp, FALSE);
-  }
-  if (SHMInfo.shmaddr != ((void *) -1))
-    shmdt (SHMInfo.shmaddr);
-  if (xvimage)
-    XFree (xvimage);
-  return result;
-}
-#endif /* HAVE_XSHM */
-
-/* This function handles GstXvImage creation depending on XShm availability */
-static GstXvImageBuffer *
-gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
-{
-  GstXvImageBuffer *xvimage = NULL;
-  GstStructure *structure = NULL;
-  gboolean succeeded = FALSE;
-  int (*handler) (Display *, XErrorEvent *);
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
-  xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
-  GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer");
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
-      !gst_structure_get_int (structure, "height", &xvimage->height)) {
-    GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
-  }
-
-  GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
-      xvimage->height);
-
-  xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
-  if (xvimage->im_format == -1) {
-    GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
-        GST_PTR_FORMAT, caps);
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-        ("Failed to create output image buffer of %dx%d pixels",
-            xvimage->width, xvimage->height), ("Invalid input caps"));
-    goto beach_unlocked;
-  }
-  xvimage->xvimagesink = gst_object_ref (xvimagesink);
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  /* Setting an error handler to catch failure */
-  error_caught = FALSE;
-  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
-  if (xvimagesink->xcontext->use_xshm) {
-    int expected_size;
-
-    xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimage->im_format, NULL,
-        xvimage->width, xvimage->height, &xvimage->SHMInfo);
-    if (!xvimage->xvimage || error_caught) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      /* Reset error handler */
-      error_caught = FALSE;
-      XSetErrorHandler (handler);
-      /* Push an error */
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("could not XvShmCreateImage a %dx%d image",
-              xvimage->width, xvimage->height));
-      goto beach_unlocked;
-    }
-
-    /* we have to use the returned data_size for our shm size */
-    xvimage->size = xvimage->xvimage->data_size;
-    GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
-        xvimage->size);
-
-    /* calculate the expected size.  This is only for sanity checking the
-     * number we get from X. */
-    switch (xvimage->im_format) {
-      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
-        expected_size =
-            GST_ROUND_UP_2 (xvimage->height) * GST_ROUND_UP_4 (xvimage->width);
-        expected_size +=
-            GST_ROUND_UP_2 (xvimage->height) * GST_ROUND_UP_8 (xvimage->width) /
-            2;
-        break;
-      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
-      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
-      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
-        expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2);
-        break;
-      default:
-        expected_size = 0;
-        break;
-    }
-    if (expected_size != 0 && xvimage->size != expected_size) {
-      GST_WARNING_OBJECT (xvimagesink,
-          "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
-          xvimage->size, expected_size);
-    }
-
-    /* Be verbose about our XvImage stride */
-    {
-      guint plane;
-
-      for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
-        GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
-            "offset of %d", plane, xvimage->xvimage->pitches[plane],
-            xvimage->xvimage->offsets[plane]);
-      }
-    }
-
-    xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
-        IPC_CREAT | 0777);
-    if (xvimage->SHMInfo.shmid == -1) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
-              xvimage->size));
-      goto beach_unlocked;
-    }
-
-    xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
-    if (xvimage->SHMInfo.shmaddr == ((void *) -1)) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("Failed to shmat: %s", g_strerror (errno)));
-      /* Clean up the shared memory segment */
-      shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
-      goto beach_unlocked;
-    }
-
-    /* Delete the shared memory segment as soon as we manage to attach.
-     * This way, it will be deleted as soon as we detach later, and not
-     * leaked if we crash. */
-    shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
-
-    xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
-    xvimage->SHMInfo.readOnly = FALSE;
-
-    if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height), ("Failed to XShmAttach"));
-      goto beach_unlocked;
-    }
-
-    XSync (xvimagesink->xcontext->disp, FALSE);
-    GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
-        xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
-  } else
-#endif /* HAVE_XSHM */
-  {
-    xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimage->im_format, NULL, xvimage->width, xvimage->height);
-    if (!xvimage->xvimage || error_caught) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      /* Reset error handler */
-      error_caught = FALSE;
-      XSetErrorHandler (handler);
-      /* Push an error */
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create outputimage buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("could not XvCreateImage a %dx%d image",
-              xvimage->width, xvimage->height));
-      goto beach_unlocked;
-    }
-
-    /* we have to use the returned data_size for our image size */
-    xvimage->size = xvimage->xvimage->data_size;
-    xvimage->xvimage->data = g_malloc (xvimage->size);
-
-    XSync (xvimagesink->xcontext->disp, FALSE);
-  }
-
-  /* Reset error handler */
-  error_caught = FALSE;
-  XSetErrorHandler (handler);
-
-  succeeded = TRUE;
-
-  GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
-  GST_BUFFER_SIZE (xvimage) = xvimage->size;
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-beach_unlocked:
-  if (!succeeded) {
-    gst_xvimage_buffer_free (xvimage);
-    xvimage = NULL;
-  }
-
-  return xvimage;
-}
-
-/* We are called with the x_lock taken */
-static void
-gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
-    GstXWindow * xwindow, GstVideoRectangle rect)
-{
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-  g_return_if_fail (xwindow != NULL);
-
-  XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
-      xvimagesink->xcontext->black);
-
-  /* Left border */
-  if (rect.x > 0) {
-    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        0, 0, rect.x, xwindow->height);
-  }
-
-  /* Right border */
-  if ((rect.x + rect.w) < xwindow->width) {
-    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        rect.x + rect.w, 0, xwindow->width, xwindow->height);
-  }
-
-  /* Top border */
-  if (rect.y > 0) {
-    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        0, 0, xwindow->width, rect.y);
-  }
-
-  /* Bottom border */
-  if ((rect.y + rect.h) < xwindow->height) {
-    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
-        0, rect.y + rect.h, xwindow->width, xwindow->height);
-  }
-}
-
-/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
- * if no window was available  */
-static gboolean
-gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
-    GstXvImageBuffer * xvimage)
-{
-  GstVideoRectangle src, dst, result;
-  gboolean draw_border = FALSE;
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
-
-  /* We take the flow_lock. If expose is in there we don't want to run
-     concurrently from the data flow thread */
-  g_mutex_lock (xvimagesink->flow_lock);
-
-  if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
-    g_mutex_unlock (xvimagesink->flow_lock);
-    return FALSE;
-  }
-
-  /* Draw borders when displaying the first frame. After this
-     draw borders only on expose event or after a size change. */
-  if (!xvimagesink->cur_image || xvimagesink->draw_border) {
-    draw_border = TRUE;
-    xvimagesink->draw_border = FALSE;
-  }
-
-  /* Store a reference to the last image we put, lose the previous one */
-  if (xvimage && xvimagesink->cur_image != xvimage) {
-    if (xvimagesink->cur_image) {
-      GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
-      gst_buffer_unref (xvimagesink->cur_image);
-    }
-    GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
-    xvimagesink->cur_image =
-        GST_XVIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER (xvimage)));
-  }
-
-  /* Expose sends a NULL image, we take the latest frame */
-  if (!xvimage) {
-    draw_border = TRUE;
-    if (xvimagesink->cur_image) {
-      xvimage = xvimagesink->cur_image;
-    } else {
-      g_mutex_unlock (xvimagesink->flow_lock);
-      return TRUE;
-    }
-  }
-
-  gst_xvimagesink_xwindow_update_geometry (xvimagesink, xvimagesink->xwindow);
-
-  /* We use the calculated geometry from _setcaps as a source to respect
-     source and screen pixel aspect ratios. */
-  src.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
-  src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
-  dst.w = xvimagesink->xwindow->width;
-  dst.h = xvimagesink->xwindow->height;
-
-  if (xvimagesink->keep_aspect) {
-    gst_video_sink_center_rect (src, dst, &result, TRUE);
-  } else {
-    result.x = result.y = 0;
-    result.w = dst.w;
-    result.h = dst.h;
-  }
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  if (draw_border) {
-    gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow,
-        result);
-  }
-
-  /* We scale to the window's geometry */
-#ifdef HAVE_XSHM
-  if (xvimagesink->xcontext->use_xshm) {
-    GST_LOG_OBJECT (xvimagesink,
-        "XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
-        GST_PTR_FORMAT,
-        xvimage->width, xvimage->height,
-        xvimagesink->xwindow->width, xvimagesink->xwindow->height, xvimage);
-
-    XvShmPutImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimagesink->xwindow->win,
-        xvimagesink->xwindow->gc, xvimage->xvimage,
-        0, 0, xvimage->width, xvimage->height,
-        result.x, result.y, result.w, result.h, FALSE);
-  } else
-#endif /* HAVE_XSHM */
-  {
-    XvPutImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimagesink->xwindow->win,
-        xvimagesink->xwindow->gc, xvimage->xvimage,
-        0, 0, xvimage->width, xvimage->height,
-        result.x, result.y, result.w, result.h);
-  }
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  g_mutex_unlock (xvimagesink->flow_lock);
-
-  return TRUE;
-}
-
-static gboolean
-gst_xvimagesink_xwindow_decorate (GstXvImageSink * xvimagesink,
-    GstXWindow * window)
-{
-  Atom hints_atom = None;
-  MotifWmHints *hints;
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
-  g_return_val_if_fail (window != NULL, FALSE);
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  hints_atom = XInternAtom (xvimagesink->xcontext->disp, "_MOTIF_WM_HINTS",
-      True);
-  if (hints_atom == None) {
-    g_mutex_unlock (xvimagesink->x_lock);
-    return FALSE;
-  }
-
-  hints = g_malloc0 (sizeof (MotifWmHints));
-
-  hints->flags |= MWM_HINTS_DECORATIONS;
-  hints->decorations = 1 << 0;
-
-  XChangeProperty (xvimagesink->xcontext->disp, window->win,
-      hints_atom, hints_atom, 32, PropModeReplace,
-      (guchar *) hints, sizeof (MotifWmHints) / sizeof (long));
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  g_free (hints);
-
-  return TRUE;
-}
-
-/* This function handles a GstXWindow creation
- * The width and height are the actual pixel size on the display */
-static GstXWindow *
-gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
-    gint width, gint height)
-{
-  GstXWindow *xwindow = NULL;
-  XGCValues values;
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
-  xwindow = g_new0 (GstXWindow, 1);
-
-  xwindow->width = width;
-  xwindow->height = height;
-  xwindow->internal = TRUE;
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  xwindow->win = XCreateSimpleWindow (xvimagesink->xcontext->disp,
-      xvimagesink->xcontext->root,
-      0, 0, xwindow->width, xwindow->height,
-      0, 0, xvimagesink->xcontext->black);
-
-  /* We have to do that to prevent X from redrawing the background on
-   * ConfigureNotify. This takes away flickering of video when resizing. */
-  XSetWindowBackgroundPixmap (xvimagesink->xcontext->disp, xwindow->win, None);
-
-  if (xvimagesink->handle_events) {
-    Atom wm_delete;
-
-    XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
-        StructureNotifyMask | PointerMotionMask | KeyPressMask |
-        KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-
-    /* Tell the window manager we'd like delete client messages instead of
-     * being killed */
-    wm_delete = XInternAtom (xvimagesink->xcontext->disp,
-        "WM_DELETE_WINDOW", True);
-    if (wm_delete != None) {
-      (void) XSetWMProtocols (xvimagesink->xcontext->disp, xwindow->win,
-          &wm_delete, 1);
-    }
-  }
-
-  xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
-      xwindow->win, 0, &values);
-
-  XMapRaised (xvimagesink->xcontext->disp, xwindow->win);
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  gst_xvimagesink_xwindow_decorate (xvimagesink, xwindow);
-
-  gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (xvimagesink), xwindow->win);
-
-  return xwindow;
-}
-
-/* This function destroys a GstXWindow */
-static void
-gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink,
-    GstXWindow * xwindow)
-{
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  /* If we did not create that window we just free the GC and let it live */
-  if (xwindow->internal)
-    XDestroyWindow (xvimagesink->xcontext->disp, xwindow->win);
-  else
-    XSelectInput (xvimagesink->xcontext->disp, xwindow->win, 0);
-
-  XFreeGC (xvimagesink->xcontext->disp, xwindow->gc);
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  g_free (xwindow);
-}
-
-static void
-gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink,
-    GstXWindow * xwindow)
-{
-  XWindowAttributes attr;
-
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  /* Update the window geometry */
-  g_mutex_lock (xvimagesink->x_lock);
-
-  XGetWindowAttributes (xvimagesink->xcontext->disp,
-      xvimagesink->xwindow->win, &attr);
-
-  xvimagesink->xwindow->width = attr.width;
-  xvimagesink->xwindow->height = attr.height;
-
-  g_mutex_unlock (xvimagesink->x_lock);
-}
-
-static void
-gst_xvimagesink_xwindow_clear (GstXvImageSink * xvimagesink,
-    GstXWindow * xwindow)
-{
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
-      xwindow->win);
-
-  XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
-      xvimagesink->xcontext->black);
-
-  XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
-      0, 0, xwindow->width, xwindow->height);
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-}
-
-/* This function commits our internal colorbalance settings to our grabbed Xv
-   port. If the xcontext is not initialized yet it simply returns */
-static void
-gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink)
-{
-  GList *channels = NULL;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  /* If we haven't initialized the X context we can't update anything */
-  if (xvimagesink->xcontext == NULL)
-    return;
-
-  /* For each channel of the colorbalance we calculate the correct value
-     doing range conversion and then set the Xv port attribute to match our
-     values. */
-  channels = xvimagesink->xcontext->channels_list;
-
-  while (channels) {
-    if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
-      GstColorBalanceChannel *channel = NULL;
-      Atom prop_atom;
-      gint value = 0;
-      gdouble convert_coef;
-
-      channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
-      g_object_ref (channel);
-
-      /* Our range conversion coef */
-      convert_coef = (channel->max_value - channel->min_value) / 2000.0;
-
-      if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
-        value = (xvimagesink->hue + 1000) * convert_coef + channel->min_value;
-      } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
-        value = (xvimagesink->saturation + 1000) * convert_coef +
-            channel->min_value;
-      } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
-        value = (xvimagesink->contrast + 1000) * convert_coef +
-            channel->min_value;
-      } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
-        value = (xvimagesink->brightness + 1000) * convert_coef +
-            channel->min_value;
-      } else {
-        g_warning ("got an unknown channel %s", channel->label);
-        g_object_unref (channel);
-        return;
-      }
-
-      /* Committing to Xv port */
-      g_mutex_lock (xvimagesink->x_lock);
-      prop_atom =
-          XInternAtom (xvimagesink->xcontext->disp, channel->label, True);
-      if (prop_atom != None) {
-        XvSetPortAttribute (xvimagesink->xcontext->disp,
-            xvimagesink->xcontext->xv_port_id, prop_atom, value);
-      }
-      g_mutex_unlock (xvimagesink->x_lock);
-
-      g_object_unref (channel);
-    }
-    channels = g_list_next (channels);
-  }
-}
-
-/* This function handles XEvents that might be in the queue. It generates
-   GstEvent that will be sent upstream in the pipeline to handle interactivity
-   and navigation. It will also listen for configure events on the window to
-   trigger caps renegotiation so on the fly software scaling can work. */
-static void
-gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
-{
-  XEvent e;
-  guint pointer_x = 0, pointer_y = 0;
-  gboolean pointer_moved = FALSE;
-  gboolean exposed = FALSE, configured = FALSE;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  /* We get all pointer motion events, only the last position is
-     interesting. */
-  g_mutex_lock (xvimagesink->flow_lock);
-  g_mutex_lock (xvimagesink->x_lock);
-  while (XCheckWindowEvent (xvimagesink->xcontext->disp,
-          xvimagesink->xwindow->win, PointerMotionMask, &e)) {
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_mutex_unlock (xvimagesink->flow_lock);
-
-    switch (e.type) {
-      case MotionNotify:
-        pointer_x = e.xmotion.x;
-        pointer_y = e.xmotion.y;
-        pointer_moved = TRUE;
-        break;
-      default:
-        break;
-    }
-    g_mutex_lock (xvimagesink->flow_lock);
-    g_mutex_lock (xvimagesink->x_lock);
-  }
-  if (pointer_moved) {
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_mutex_unlock (xvimagesink->flow_lock);
-
-    GST_DEBUG ("xvimagesink pointer moved over window at %d,%d",
-        pointer_x, pointer_y);
-    gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
-        "mouse-move", 0, e.xbutton.x, e.xbutton.y);
-
-    g_mutex_lock (xvimagesink->flow_lock);
-    g_mutex_lock (xvimagesink->x_lock);
-  }
-
-  /* We get all events on our window to throw them upstream */
-  while (XCheckWindowEvent (xvimagesink->xcontext->disp,
-          xvimagesink->xwindow->win,
-          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
-          &e)) {
-    KeySym keysym;
-
-    /* We lock only for the X function call */
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_mutex_unlock (xvimagesink->flow_lock);
-
-    switch (e.type) {
-      case ButtonPress:
-        /* Mouse button pressed over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("xvimagesink button %d pressed over window at %d,%d",
-            e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
-            "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        break;
-      case ButtonRelease:
-        /* Mouse button released over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("xvimagesink button %d released over window at %d,%d",
-            e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
-            "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        break;
-      case KeyPress:
-      case KeyRelease:
-        /* Key pressed/released over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("xvimagesink key %d pressed over window at %d,%d",
-            e.xkey.keycode, e.xkey.x, e.xkey.y);
-        g_mutex_lock (xvimagesink->x_lock);
-        keysym = XKeycodeToKeysym (xvimagesink->xcontext->disp,
-            e.xkey.keycode, 0);
-        g_mutex_unlock (xvimagesink->x_lock);
-        if (keysym != NoSymbol) {
-          char *key_str = NULL;
-
-          g_mutex_lock (xvimagesink->x_lock);
-          key_str = XKeysymToString (keysym);
-          g_mutex_unlock (xvimagesink->x_lock);
-          gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
-              e.type == KeyPress ? "key-press" : "key-release", key_str);
-        } else {
-          gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
-              e.type == KeyPress ? "key-press" : "key-release", "unknown");
-        }
-        break;
-      default:
-        GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type);
-    }
-    g_mutex_lock (xvimagesink->flow_lock);
-    g_mutex_lock (xvimagesink->x_lock);
-  }
-
-  /* Handle Expose */
-  while (XCheckWindowEvent (xvimagesink->xcontext->disp,
-          xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
-    switch (e.type) {
-      case Expose:
-        exposed = TRUE;
-        break;
-      case ConfigureNotify:
-        configured = TRUE;
-        break;
-      default:
-        break;
-    }
-  }
-
-  if (xvimagesink->handle_expose && (exposed || configured)) {
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_mutex_unlock (xvimagesink->flow_lock);
-
-    gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
-
-    g_mutex_lock (xvimagesink->flow_lock);
-    g_mutex_lock (xvimagesink->x_lock);
-  }
-
-  /* Handle Display events */
-  while (XPending (xvimagesink->xcontext->disp)) {
-    XNextEvent (xvimagesink->xcontext->disp, &e);
-
-    switch (e.type) {
-      case ClientMessage:{
-        Atom wm_delete;
-
-        wm_delete = XInternAtom (xvimagesink->xcontext->disp,
-            "WM_DELETE_WINDOW", True);
-        if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) {
-          /* Handle window deletion by posting an error on the bus */
-          GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND,
-              ("Output window was closed"), (NULL));
-
-          g_mutex_unlock (xvimagesink->x_lock);
-          gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
-          xvimagesink->xwindow = NULL;
-          g_mutex_lock (xvimagesink->x_lock);
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  g_mutex_unlock (xvimagesink->x_lock);
-  g_mutex_unlock (xvimagesink->flow_lock);
-}
-
-static void
-gst_lookup_xv_port_from_adaptor (GstXContext * xcontext,
-    XvAdaptorInfo * adaptors, int adaptor_no)
-{
-  gint j;
-
-  /* Do we support XvImageMask ? */
-  if (!(adaptors[adaptor_no].type & XvImageMask))
-    return;
-
-  /* We found such an adaptor, looking for an available port */
-  for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
-    /* We try to grab the port */
-    if (Success == XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j,
-            0)) {
-      xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
-      GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name,
-          adaptors[adaptor_no].num_ports);
-    }
-  }
-}
-
-/* This function generates a caps with all supported format by the first
-   Xv grabable port we find. We store each one of the supported formats in a
-   format list and append the format to a newly created caps that we return
-   If this function does not return NULL because of an error, it also grabs
-   the port via XvGrabPort */
-static GstCaps *
-gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
-    GstXContext * xcontext)
-{
-  gint i;
-  XvAdaptorInfo *adaptors;
-  gint nb_formats;
-  XvImageFormatValues *formats = NULL;
-  guint nb_encodings;
-  XvEncodingInfo *encodings = NULL;
-  gulong max_w = G_MAXINT, max_h = G_MAXINT;
-  GstCaps *caps = NULL;
-  GstCaps *rgb_caps = NULL;
-
-  g_return_val_if_fail (xcontext != NULL, NULL);
-
-  /* First let's check that XVideo extension is available */
-  if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS,
-        ("Could not initialise Xv output"),
-        ("XVideo extension is not available"));
-    return NULL;
-  }
-
-  /* Then we get adaptors list */
-  if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
-          &xcontext->nb_adaptors, &adaptors)) {
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS,
-        ("Could not initialise Xv output"),
-        ("Failed getting XV adaptors list"));
-    return NULL;
-  }
-
-  xcontext->xv_port_id = 0;
-
-  GST_DEBUG ("Found %u XV adaptor(s)", xcontext->nb_adaptors);
-
-  xcontext->adaptors =
-      (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
-
-  /* Now fill up our adaptor name array */
-  for (i = 0; i < xcontext->nb_adaptors; i++) {
-    xcontext->adaptors[i] = g_strdup (adaptors[i].name);
-  }
-
-  if (xvimagesink->adaptor_no >= 0 &&
-      xvimagesink->adaptor_no < xcontext->nb_adaptors) {
-    /* Find xv port from user defined adaptor */
-    gst_lookup_xv_port_from_adaptor (xcontext, adaptors,
-        xvimagesink->adaptor_no);
-  }
-
-  if (!xcontext->xv_port_id) {
-    /* Now search for an adaptor that supports XvImageMask */
-    for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
-      gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
-      xvimagesink->adaptor_no = i;
-    }
-  }
-
-  XvFreeAdaptorInfo (adaptors);
-
-  if (!xcontext->xv_port_id) {
-    xvimagesink->adaptor_no = -1;
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, BUSY,
-        ("Could not initialise Xv output"), ("No port available"));
-    return NULL;
-  }
-
-  /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
-  {
-    int count;
-    XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
-        xcontext->xv_port_id, &count);
-    static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
-    static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
-    static const char colorkey[] = "XV_COLORKEY";
-
-    for (i = 0; i < count; i++)
-      if (!strcmp (attr[i].name, autopaint)) {
-        const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
-
-        XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, 1);
-        break;
-      }
-
-    for (i = 0; i < count; i++)
-      if (!strcmp (attr[i].name, dbl_buffer)) {
-        const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
-
-        XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
-            (xvimagesink->double_buffer ? 1 : 0));
-        break;
-      }
-
-    /* Set the colorkey to something that is dark but hopefully won't randomly
-     * appear on the screen elsewhere (ie not black or greys) */
-    for (i = 0; i < count; i++)
-      if (!strcmp (attr[i].name, colorkey)) {
-        const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
-        guint32 ckey;
-        guint32 keymask;
-        gint bits;
-        gboolean set_attr = TRUE;
-
-        /* Count the bits in the colorkey mask 'max' value */
-        bits = 0;
-        for (keymask = (guint32) (attr[i].max_value);
-            keymask != 0; keymask >>= 1)
-          bits++;
-
-        /* set a colorkey in the right format RGB565/RGB888
-         * note that the colorkey is independent from the display
-         * depth (xcontext->depth). We only handle these 2 cases, because
-         * they're the only types of devices we've encountered. If we don't
-         * recognise it, leave it alone  */
-        if (bits == 16)
-          ckey = (1 << 10) | (2 << 5) | 3;
-        else if (bits == 24 || bits == 32)
-          ckey = (1 << 16) | (2 << 8) | 3;
-        else
-          set_attr = FALSE;
-
-
-        if (set_attr) {
-          ckey = CLAMP (ckey, (guint32) attr[i].min_value,
-              (guint32) attr[i].max_value);
-          GST_LOG_OBJECT (xvimagesink,
-              "Setting color key for display depth %d to 0x%x",
-              xcontext->depth, ckey);
-
-          XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
-              (gint) ckey);
-        } else {
-          GST_LOG_OBJECT (xvimagesink,
-              "Unknown bit depth for Xv Colorkey - not adjusting ");
-        }
-        break;
-      }
-
-    XFree (attr);
-  }
-
-  /* Get the list of encodings supported by the adapter and look for the
-   * XV_IMAGE encoding so we can determine the maximum width and height
-   * supported */
-  XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
-      &encodings);
-
-  for (i = 0; i < nb_encodings; i++) {
-    GST_LOG_OBJECT (xvimagesink,
-        "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
-        i, encodings[i].name, encodings[i].width, encodings[i].height,
-        encodings[i].rate.numerator, encodings[i].rate.denominator);
-    if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
-      max_w = encodings[i].width;
-      max_h = encodings[i].height;
-    }
-  }
-
-  XvFreeEncodingInfo (encodings);
-
-  /* We get all image formats supported by our port */
-  formats = XvListImageFormats (xcontext->disp,
-      xcontext->xv_port_id, &nb_formats);
-  caps = gst_caps_new_empty ();
-  for (i = 0; i < nb_formats; i++) {
-    GstCaps *format_caps = NULL;
-    gboolean is_rgb_format = FALSE;
-
-    /* We set the image format of the xcontext to an existing one. This
-       is just some valid image format for making our xshm calls check before
-       caps negotiation really happens. */
-    xcontext->im_format = formats[i].id;
-
-    switch (formats[i].type) {
-      case XvRGB:
-      {
-        XvImageFormatValues *fmt = &(formats[i]);
-        gint endianness = G_BIG_ENDIAN;
-
-        if (fmt->byte_order == LSBFirst) {
-          /* our caps system handles 24/32bpp RGB as big-endian. */
-          if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
-            fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
-            fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
-            fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
-
-            if (fmt->bits_per_pixel == 24) {
-              fmt->red_mask >>= 8;
-              fmt->green_mask >>= 8;
-              fmt->blue_mask >>= 8;
-            }
-          } else
-            endianness = G_LITTLE_ENDIAN;
-        }
-
-        format_caps = gst_caps_new_simple ("video/x-raw-rgb",
-            "endianness", G_TYPE_INT, endianness,
-            "depth", G_TYPE_INT, fmt->depth,
-            "bpp", G_TYPE_INT, fmt->bits_per_pixel,
-            "red_mask", G_TYPE_INT, fmt->red_mask,
-            "green_mask", G_TYPE_INT, fmt->green_mask,
-            "blue_mask", G_TYPE_INT, fmt->blue_mask,
-            "width", GST_TYPE_INT_RANGE, 1, max_w,
-            "height", GST_TYPE_INT_RANGE, 1, max_h,
-            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-
-        is_rgb_format = TRUE;
-        break;
-      }
-      case XvYUV:
-        format_caps = gst_caps_new_simple ("video/x-raw-yuv",
-            "format", GST_TYPE_FOURCC, formats[i].id,
-            "width", GST_TYPE_INT_RANGE, 1, max_w,
-            "height", GST_TYPE_INT_RANGE, 1, max_h,
-            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-        break;
-      default:
-        g_assert_not_reached ();
-        break;
-    }
-
-    if (format_caps) {
-      GstXvImageFormat *format = NULL;
-
-      format = g_new0 (GstXvImageFormat, 1);
-      if (format) {
-        format->format = formats[i].id;
-        format->caps = gst_caps_copy (format_caps);
-        xcontext->formats_list = g_list_append (xcontext->formats_list, format);
-      }
-
-      if (is_rgb_format) {
-        if (rgb_caps == NULL)
-          rgb_caps = format_caps;
-        else
-          gst_caps_append (rgb_caps, format_caps);
-      } else
-        gst_caps_append (caps, format_caps);
-    }
-  }
-
-  /* Collected all caps into either the caps or rgb_caps structures.
-   * Append rgb_caps on the end of YUV, so that YUV is always preferred */
-  if (rgb_caps)
-    gst_caps_append (caps, rgb_caps);
-
-  if (formats)
-    XFree (formats);
-
-  GST_DEBUG ("Generated the following caps: %" GST_PTR_FORMAT, caps);
-
-  if (gst_caps_is_empty (caps)) {
-    gst_caps_unref (caps);
-    XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
-    GST_ELEMENT_ERROR (xvimagesink, STREAM, WRONG_TYPE, (NULL),
-        ("No supported format found"));
-    return NULL;
-  }
-
-  return caps;
-}
-
-static gpointer
-gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink)
-{
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
-  GST_OBJECT_LOCK (xvimagesink);
-  while (xvimagesink->running) {
-    GST_OBJECT_UNLOCK (xvimagesink);
-
-    if (xvimagesink->xwindow) {
-      gst_xvimagesink_handle_xevents (xvimagesink);
-    }
-    g_usleep (50000);
-
-    GST_OBJECT_LOCK (xvimagesink);
-  }
-  GST_OBJECT_UNLOCK (xvimagesink);
-
-  return NULL;
-}
-
-/* This function calculates the pixel aspect ratio based on the properties
- * in the xcontext structure and stores it there. */
-static void
-gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
-{
-  static const gint par[][2] = {
-    {1, 1},                     /* regular screen */
-    {16, 15},                   /* PAL TV */
-    {11, 10},                   /* 525 line Rec.601 video */
-    {54, 59},                   /* 625 line Rec.601 video */
-    {64, 45},                   /* 1280x1024 on 16:9 display */
-    {5, 3},                     /* 1280x1024 on 4:3 display */
-    {4, 3}                      /*  800x600 on 16:9 display */
-  };
-  gint i;
-  gint index;
-  gdouble ratio;
-  gdouble delta;
-
-#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
-
-  /* first calculate the "real" ratio based on the X values;
-   * which is the "physical" w/h divided by the w/h in pixels of the display */
-  ratio = (gdouble) (xcontext->widthmm * xcontext->height)
-      / (xcontext->heightmm * xcontext->width);
-
-  /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
-   * override here */
-  if (xcontext->width == 720 && xcontext->height == 576) {
-    ratio = 4.0 * 576 / (3.0 * 720);
-  }
-  GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
-  /* now find the one from par[][2] with the lowest delta to the real one */
-  delta = DELTA (0);
-  index = 0;
-
-  for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
-    gdouble this_delta = DELTA (i);
-
-    if (this_delta < delta) {
-      index = i;
-      delta = this_delta;
-    }
-  }
-
-  GST_DEBUG ("Decided on index %d (%d/%d)", index,
-      par[index][0], par[index][1]);
-
-  g_free (xcontext->par);
-  xcontext->par = g_new0 (GValue, 1);
-  g_value_init (xcontext->par, GST_TYPE_FRACTION);
-  gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
-  GST_DEBUG ("set xcontext PAR to %d/%d",
-      gst_value_get_fraction_numerator (xcontext->par),
-      gst_value_get_fraction_denominator (xcontext->par));
-}
-
-/* This function gets the X Display and global info about it. Everything is
-   stored in our object and will be cleaned when the object is disposed. Note
-   here that caps for supported format are generated without any window or
-   image creation */
-static GstXContext *
-gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
-{
-  GstXContext *xcontext = NULL;
-  XPixmapFormatValues *px_formats = NULL;
-  gint nb_formats = 0, i, j, N_attr;
-  XvAttribute *xv_attr;
-  Atom prop_atom;
-  char *channels[4] = { "XV_HUE", "XV_SATURATION",
-    "XV_BRIGHTNESS", "XV_CONTRAST"
-  };
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
-  xcontext = g_new0 (GstXContext, 1);
-  xcontext->im_format = 0;
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  xcontext->disp = XOpenDisplay (xvimagesink->display_name);
-
-  if (!xcontext->disp) {
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_free (xcontext);
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-        ("Could not initialise Xv output"), ("Could not open display"));
-    return NULL;
-  }
-
-  xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
-  xcontext->screen_num = DefaultScreen (xcontext->disp);
-  xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
-  xcontext->root = DefaultRootWindow (xcontext->disp);
-  xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
-  xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
-  xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
-
-  xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
-  xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
-  xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
-  xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
-
-  GST_DEBUG_OBJECT (xvimagesink, "X reports %dx%d pixels and %d mm x %d mm",
-      xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
-
-  gst_xvimagesink_calculate_pixel_aspect_ratio (xcontext);
-  /* We get supported pixmap formats at supported depth */
-  px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
-
-  if (!px_formats) {
-    XCloseDisplay (xcontext->disp);
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_free (xcontext->par);
-    g_free (xcontext);
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS,
-        ("Could not initialise Xv output"), ("Could not get pixel formats"));
-    return NULL;
-  }
-
-  /* We get bpp value corresponding to our running depth */
-  for (i = 0; i < nb_formats; i++) {
-    if (px_formats[i].depth == xcontext->depth)
-      xcontext->bpp = px_formats[i].bits_per_pixel;
-  }
-
-  XFree (px_formats);
-
-  xcontext->endianness =
-      (ImageByteOrder (xcontext->disp) ==
-      LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
-
-  /* our caps system handles 24/32bpp RGB as big-endian. */
-  if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
-      xcontext->endianness == G_LITTLE_ENDIAN) {
-    xcontext->endianness = G_BIG_ENDIAN;
-    xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
-    xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
-    xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
-    if (xcontext->bpp == 24) {
-      xcontext->visual->red_mask >>= 8;
-      xcontext->visual->green_mask >>= 8;
-      xcontext->visual->blue_mask >>= 8;
-    }
-  }
-
-  xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext);
-
-  if (!xcontext->caps) {
-    XCloseDisplay (xcontext->disp);
-    g_mutex_unlock (xvimagesink->x_lock);
-    g_free (xcontext->par);
-    g_free (xcontext);
-    /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */
-    return NULL;
-  }
-#ifdef HAVE_XSHM
-  /* Search for XShm extension support */
-  if (XShmQueryExtension (xcontext->disp) &&
-      gst_xvimagesink_check_xshm_calls (xcontext)) {
-    xcontext->use_xshm = TRUE;
-    GST_DEBUG ("xvimagesink is using XShm extension");
-  } else
-#endif /* HAVE_XSHM */
-  {
-    xcontext->use_xshm = FALSE;
-    GST_DEBUG ("xvimagesink is not using XShm extension");
-  }
-
-  xv_attr = XvQueryPortAttributes (xcontext->disp,
-      xcontext->xv_port_id, &N_attr);
-
-
-  /* Generate the channels list */
-  for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
-    XvAttribute *matching_attr = NULL;
-
-    /* Retrieve the property atom if it exists. If it doesn't exist, 
-     * the attribute itself must not either, so we can skip */
-    prop_atom = XInternAtom (xcontext->disp, channels[i], True);
-    if (prop_atom == None)
-      continue;
-
-    if (xv_attr != NULL) {
-      for (j = 0; j < N_attr && matching_attr == NULL; ++j)
-        if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name))
-          matching_attr = xv_attr + j;
-    }
-
-    if (matching_attr) {
-      GstColorBalanceChannel *channel;
-
-      channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
-      channel->label = g_strdup (channels[i]);
-      channel->min_value = matching_attr ? matching_attr->min_value : -1000;
-      channel->max_value = matching_attr ? matching_attr->max_value : 1000;
-
-      xcontext->channels_list = g_list_append (xcontext->channels_list,
-          channel);
-
-      /* If the colorbalance settings have not been touched we get Xv values
-         as defaults and update our internal variables */
-      if (!xvimagesink->cb_changed) {
-        gint val;
-
-        XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id,
-            prop_atom, &val);
-        /* Normalize val to [-1000, 1000] */
-        val = -1000 + 2000 * (val - channel->min_value) /
-            (channel->max_value - channel->min_value);
-
-        if (!g_ascii_strcasecmp (channels[i], "XV_HUE"))
-          xvimagesink->hue = val;
-        else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION"))
-          xvimagesink->saturation = val;
-        else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS"))
-          xvimagesink->brightness = val;
-        else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST"))
-          xvimagesink->contrast = val;
-      }
-    }
-  }
-
-  if (xv_attr)
-    XFree (xv_attr);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  /* Setup our event listening thread */
-  GST_OBJECT_LOCK (xvimagesink);
-  xvimagesink->running = TRUE;
-  xvimagesink->event_thread = g_thread_create (
-      (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL);
-  GST_OBJECT_UNLOCK (xvimagesink);
-
-  return xcontext;
-}
-
-/* This function cleans the X context. Closing the Display, releasing the XV
-   port and unrefing the caps for supported formats. */
-static void
-gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
-{
-  GList *formats_list, *channels_list;
-  GstXContext *xcontext;
-  gint i = 0;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  GST_OBJECT_LOCK (xvimagesink);
-  if (xvimagesink->xcontext == NULL) {
-    GST_OBJECT_UNLOCK (xvimagesink);
-    return;
-  }
-
-  /* Take the XContext from the sink and clean it up */
-  xcontext = xvimagesink->xcontext;
-  xvimagesink->xcontext = NULL;
-
-  GST_OBJECT_UNLOCK (xvimagesink);
-
-
-  formats_list = xcontext->formats_list;
-
-  while (formats_list) {
-    GstXvImageFormat *format = formats_list->data;
-
-    gst_caps_unref (format->caps);
-    g_free (format);
-    formats_list = g_list_next (formats_list);
-  }
-
-  if (xcontext->formats_list)
-    g_list_free (xcontext->formats_list);
-
-  channels_list = xcontext->channels_list;
-
-  while (channels_list) {
-    GstColorBalanceChannel *channel = channels_list->data;
-
-    g_object_unref (channel);
-    channels_list = g_list_next (channels_list);
-  }
-
-  if (xcontext->channels_list)
-    g_list_free (xcontext->channels_list);
-
-  gst_caps_unref (xcontext->caps);
-  if (xcontext->last_caps)
-    gst_caps_replace (&xcontext->last_caps, NULL);
-
-  for (i = 0; i < xcontext->nb_adaptors; i++) {
-    g_free (xcontext->adaptors[i]);
-  }
-
-  g_free (xcontext->adaptors);
-
-  g_free (xcontext->par);
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  GST_DEBUG_OBJECT (xvimagesink, "Closing display and freeing X Context");
-
-  XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
-
-  XCloseDisplay (xcontext->disp);
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  g_free (xcontext);
-}
-
-static void
-gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
-{
-  g_mutex_lock (xvimagesink->pool_lock);
-
-  while (xvimagesink->image_pool) {
-    GstXvImageBuffer *xvimage = xvimagesink->image_pool->data;
-
-    xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
-        xvimagesink->image_pool);
-    gst_xvimage_buffer_free (xvimage);
-  }
-
-  g_mutex_unlock (xvimagesink->pool_lock);
-}
-
-/* Element stuff */
-
-/* This function tries to get a format matching with a given caps in the
-   supported list of formats we generated in gst_xvimagesink_get_xv_support */
-static gint
-gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
-    GstCaps * caps)
-{
-  GList *list = NULL;
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
-
-  list = xvimagesink->xcontext->formats_list;
-
-  while (list) {
-    GstXvImageFormat *format = list->data;
-
-    if (format) {
-      GstCaps *icaps = NULL;
-
-      icaps = gst_caps_intersect (caps, format->caps);
-      if (!gst_caps_is_empty (icaps)) {
-        gst_caps_unref (icaps);
-        return format->format;
-      }
-      gst_caps_unref (icaps);
-    }
-    list = g_list_next (list);
-  }
-
-  return -1;
-}
-
-static GstCaps *
-gst_xvimagesink_getcaps (GstBaseSink * bsink)
-{
-  GstXvImageSink *xvimagesink;
-
-  xvimagesink = GST_XVIMAGESINK (bsink);
-
-  if (xvimagesink->xcontext)
-    return gst_caps_ref (xvimagesink->xcontext->caps);
-
-  return
-      gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
-          (xvimagesink)));
-}
-
-static gboolean
-gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
-{
-  GstXvImageSink *xvimagesink;
-  GstStructure *structure;
-  GstCaps *intersection;
-  guint32 im_format = 0;
-  gboolean ret;
-  gint video_width, video_height;
-  gint video_par_n, video_par_d;        /* video's PAR */
-  gint display_par_n, display_par_d;    /* display's PAR */
-  const GValue *caps_par;
-  const GValue *fps;
-  guint num, den;
-
-  xvimagesink = GST_XVIMAGESINK (bsink);
-
-  GST_DEBUG_OBJECT (xvimagesink,
-      "In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %"
-      GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps);
-
-  intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps);
-  GST_DEBUG_OBJECT (xvimagesink, "intersection returned %" GST_PTR_FORMAT,
-      intersection);
-  if (gst_caps_is_empty (intersection)) {
-    gst_caps_unref (intersection);
-    return FALSE;
-  }
-
-  gst_caps_unref (intersection);
-
-  structure = gst_caps_get_structure (caps, 0);
-  ret = gst_structure_get_int (structure, "width", &video_width);
-  ret &= gst_structure_get_int (structure, "height", &video_height);
-  fps = gst_structure_get_value (structure, "framerate");
-  ret &= (fps != NULL);
-
-  if (!ret) {
-    GST_DEBUG_OBJECT (xvimagesink, "Failed to retrieve either width, "
-        "height or framerate from intersected caps");
-    return FALSE;
-  }
-
-  xvimagesink->fps_n = gst_value_get_fraction_numerator (fps);
-  xvimagesink->fps_d = gst_value_get_fraction_denominator (fps);
-
-  xvimagesink->video_width = video_width;
-  xvimagesink->video_height = video_height;
-  im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
-  if (im_format == -1) {
-    GST_DEBUG_OBJECT (xvimagesink,
-        "Could not locate image format from caps %" GST_PTR_FORMAT, caps);
-    return FALSE;
-  }
-
-  /* get aspect ratio from caps if it's present, and
-   * convert video width and height to a display width and height
-   * using wd / hd = wv / hv * PARv / PARd */
-
-  /* get video's PAR */
-  caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
-  if (caps_par) {
-    video_par_n = gst_value_get_fraction_numerator (caps_par);
-    video_par_d = gst_value_get_fraction_denominator (caps_par);
-  } else {
-    video_par_n = 1;
-    video_par_d = 1;
-  }
-  /* get display's PAR */
-  if (xvimagesink->par) {
-    display_par_n = gst_value_get_fraction_numerator (xvimagesink->par);
-    display_par_d = gst_value_get_fraction_denominator (xvimagesink->par);
-  } else {
-    display_par_n = 1;
-    display_par_d = 1;
-  }
-
-  if (!gst_video_calculate_display_ratio (&num, &den, video_width,
-          video_height, video_par_n, video_par_d, display_par_n,
-          display_par_d)) {
-    GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
-        ("Error calculating the output display ratio of the video."));
-    return FALSE;
-  }
-
-  GST_DEBUG_OBJECT (xvimagesink,
-      "video width/height: %dx%d, calculated display ratio: %d/%d",
-      video_width, video_height, num, den);
-
-  /* now find a width x height that respects this display ratio.
-   * prefer those that have one of w/h the same as the incoming video
-   * using wd / hd = num / den */
-
-  /* start with same height, because of interlaced video */
-  /* check hd / den is an integer scale factor, and scale wd with the PAR */
-  if (video_height % den == 0) {
-    GST_DEBUG_OBJECT (xvimagesink, "keeping video height");
-    GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
-        gst_util_uint64_scale_int (video_height, num, den);
-    GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height;
-  } else if (video_width % num == 0) {
-    GST_DEBUG_OBJECT (xvimagesink, "keeping video width");
-    GST_VIDEO_SINK_WIDTH (xvimagesink) = video_width;
-    GST_VIDEO_SINK_HEIGHT (xvimagesink) = (guint)
-        gst_util_uint64_scale_int (video_width, den, num);
-  } else {
-    GST_DEBUG_OBJECT (xvimagesink, "approximating while keeping video height");
-    GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
-        gst_util_uint64_scale_int (video_height, num, den);
-    GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height;
-  }
-  GST_DEBUG_OBJECT (xvimagesink, "scaling to %dx%d",
-      GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink));
-
-  /* Notify application to set xwindow id now */
-  g_mutex_lock (xvimagesink->flow_lock);
-  if (!xvimagesink->xwindow) {
-    g_mutex_unlock (xvimagesink->flow_lock);
-    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (xvimagesink));
-  } else {
-    g_mutex_unlock (xvimagesink->flow_lock);
-  }
-
-  /* Creating our window and our image with the display size in pixels */
-  if (GST_VIDEO_SINK_WIDTH (xvimagesink) <= 0 ||
-      GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0) {
-    GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
-        ("Error calculating the output display ratio of the video."));
-    return FALSE;
-  }
-
-  g_mutex_lock (xvimagesink->flow_lock);
-  if (!xvimagesink->xwindow) {
-    xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
-        GST_VIDEO_SINK_WIDTH (xvimagesink),
-        GST_VIDEO_SINK_HEIGHT (xvimagesink));
-  }
-
-  /* After a resize, we want to redraw the borders in case the new frame size 
-   * doesn't cover the same area */
-  xvimagesink->draw_border = TRUE;
-
-  /* We renew our xvimage only if size or format changed;
-   * the xvimage is the same size as the video pixel size */
-  if ((xvimagesink->xvimage) &&
-      ((im_format != xvimagesink->xvimage->im_format) ||
-          (video_width != xvimagesink->xvimage->width) ||
-          (video_height != xvimagesink->xvimage->height))) {
-    GST_DEBUG_OBJECT (xvimagesink,
-        "old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
-        GST_FOURCC_ARGS (xvimagesink->xvimage->im_format),
-        GST_FOURCC_ARGS (im_format));
-    GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
-    gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
-    xvimagesink->xvimage = NULL;
-  }
-
-  g_mutex_unlock (xvimagesink->flow_lock);
-
-  return TRUE;
-}
-
-static GstStateChangeReturn
-gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
-{
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstXvImageSink *xvimagesink;
-  GstXContext *xcontext = NULL;
-
-  xvimagesink = GST_XVIMAGESINK (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      /* Initializing the XContext */
-      if (xvimagesink->xcontext == NULL) {
-        xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
-        if (xcontext == NULL)
-          return GST_STATE_CHANGE_FAILURE;
-        GST_OBJECT_LOCK (xvimagesink);
-        if (xcontext)
-          xvimagesink->xcontext = xcontext;
-        GST_OBJECT_UNLOCK (xvimagesink);
-      }
-
-      /* update object's par with calculated one if not set yet */
-      if (!xvimagesink->par) {
-        xvimagesink->par = g_new0 (GValue, 1);
-        gst_value_init_and_copy (xvimagesink->par, xvimagesink->xcontext->par);
-        GST_DEBUG_OBJECT (xvimagesink, "set calculated PAR on object's PAR");
-      }
-      /* call XSynchronize with the current value of synchronous */
-      GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s",
-          xvimagesink->synchronous ? "TRUE" : "FALSE");
-      XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
-      gst_xvimagesink_update_colorbalance (xvimagesink);
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      g_mutex_lock (xvimagesink->flow_lock);
-      if (xvimagesink->xwindow)
-        gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
-      g_mutex_unlock (xvimagesink->flow_lock);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      xvimagesink->fps_n = 0;
-      xvimagesink->fps_d = 1;
-      GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
-      GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      gst_xvimagesink_reset (xvimagesink);
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-static void
-gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
-    GstClockTime * start, GstClockTime * end)
-{
-  GstXvImageSink *xvimagesink;
-
-  xvimagesink = GST_XVIMAGESINK (bsink);
-
-  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
-    *start = GST_BUFFER_TIMESTAMP (buf);
-    if (GST_BUFFER_DURATION_IS_VALID (buf)) {
-      *end = *start + GST_BUFFER_DURATION (buf);
-    } else {
-      if (xvimagesink->fps_n > 0) {
-        *end = *start +
-            gst_util_uint64_scale_int (GST_SECOND, xvimagesink->fps_d,
-            xvimagesink->fps_n);
-      }
-    }
-  }
-}
-
-static GstFlowReturn
-gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
-{
-  GstXvImageSink *xvimagesink;
-
-  xvimagesink = GST_XVIMAGESINK (bsink);
-
-  /* If this buffer has been allocated using our buffer management we simply
-     put the ximage which is in the PRIVATE pointer */
-  if (GST_IS_XVIMAGE_BUFFER (buf)) {
-    GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer");
-    if (!gst_xvimagesink_xvimage_put (xvimagesink, GST_XVIMAGE_BUFFER (buf)))
-      goto no_window;
-  } else {
-    GST_LOG_OBJECT (xvimagesink, "slow copy into bufferpool buffer");
-    /* Else we have to copy the data into our private image, */
-    /* if we have one... */
-    if (!xvimagesink->xvimage) {
-      GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
-
-      xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
-          GST_BUFFER_CAPS (buf));
-
-      if (!xvimagesink->xvimage)
-        /* The create method should have posted an informative error */
-        goto no_image;
-
-      if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) {
-        GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-            ("Failed to create output image buffer of %dx%d pixels",
-                xvimagesink->xvimage->width, xvimagesink->xvimage->height),
-            ("XServer allocated buffer size did not match input buffer"));
-
-        gst_xvimage_buffer_destroy (xvimagesink->xvimage);
-        xvimagesink->xvimage = NULL;
-        goto no_image;
-      }
-    }
-
-    memcpy (xvimagesink->xvimage->xvimage->data,
-        GST_BUFFER_DATA (buf),
-        MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
-
-    if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
-      goto no_window;
-  }
-
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-no_image:
-  {
-    /* No image available. That's very bad ! */
-    GST_WARNING_OBJECT (xvimagesink, "could not create image");
-    return GST_FLOW_ERROR;
-  }
-no_window:
-  {
-    /* No Window available to put our image into */
-    GST_WARNING_OBJECT (xvimagesink, "could not output image - no window");
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* Buffer management */
-
-static GstFlowReturn
-gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstXvImageSink *xvimagesink;
-  GstXvImageBuffer *xvimage = NULL;
-  GstCaps *intersection = NULL;
-  GstStructure *structure = NULL;
-  gint width, height, image_format;
-
-  xvimagesink = GST_XVIMAGESINK (bsink);
-
-  if (G_LIKELY (xvimagesink->xcontext->last_caps &&
-          gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) {
-    GST_DEBUG_OBJECT (xvimagesink,
-        "buffer alloc for same last_caps, reusing caps");
-    intersection = gst_caps_ref (caps);
-    image_format = xvimagesink->xcontext->last_format;
-
-    goto reuse_last_caps;
-  }
-
-  GST_DEBUG_OBJECT (xvimagesink, "buffer alloc requested with caps %"
-      GST_PTR_FORMAT ", intersecting with our caps %" GST_PTR_FORMAT, caps,
-      xvimagesink->xcontext->caps);
-
-  /* Check the caps against our xcontext */
-  intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps);
-
-  /* Ensure the returned caps are fixed */
-  gst_caps_truncate (intersection);
-
-  GST_DEBUG_OBJECT (xvimagesink, "intersection in buffer alloc returned %"
-      GST_PTR_FORMAT, intersection);
-
-  if (gst_caps_is_empty (intersection)) {
-    /* So we don't support this kind of buffer, let's define one we'd like */
-    GstCaps *new_caps = gst_caps_copy (caps);
-
-    structure = gst_caps_get_structure (new_caps, 0);
-
-    /* Try with YUV first */
-    gst_structure_set_name (structure, "video/x-raw-yuv");
-    gst_structure_remove_field (structure, "format");
-    gst_structure_remove_field (structure, "endianness");
-    gst_structure_remove_field (structure, "depth");
-    gst_structure_remove_field (structure, "bpp");
-    gst_structure_remove_field (structure, "red_mask");
-    gst_structure_remove_field (structure, "green_mask");
-    gst_structure_remove_field (structure, "blue_mask");
-    gst_structure_remove_field (structure, "alpha_mask");
-
-    /* Reuse intersection with Xcontext */
-    gst_caps_unref (intersection);
-    intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
-
-    if (gst_caps_is_empty (intersection)) {
-      /* Now try with RGB */
-      gst_structure_set_name (structure, "video/x-raw-rgb");
-      /* And interset again */
-      gst_caps_unref (intersection);
-      intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
-
-      if (gst_caps_is_empty (intersection)) {
-        GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with "
-            "caps %" GST_PTR_FORMAT ", but our xcontext caps %" GST_PTR_FORMAT
-            " are completely incompatible with those caps", new_caps,
-            xvimagesink->xcontext->caps);
-        gst_caps_unref (new_caps);
-        ret = GST_FLOW_UNEXPECTED;
-        goto beach;
-      }
-    }
-
-    /* Clean this copy */
-    gst_caps_unref (new_caps);
-    /* We want fixed caps */
-    gst_caps_truncate (intersection);
-
-    GST_DEBUG_OBJECT (xvimagesink, "allocating a buffer with caps %"
-        GST_PTR_FORMAT, intersection);
-  } else if (gst_caps_is_equal (intersection, caps)) {
-    /* Things work better if we return a buffer with the same caps ptr
-     * as was asked for when we can */
-    gst_caps_replace (&intersection, caps);
-  }
-
-  /* Get image format from caps */
-  image_format = gst_xvimagesink_get_format_from_caps (xvimagesink,
-      intersection);
-
-  /* Store our caps and format as the last_caps to avoid expensive
-   * caps intersection next time */
-  gst_caps_replace (&xvimagesink->xcontext->last_caps, intersection);
-  xvimagesink->xcontext->last_format = image_format;
-
-reuse_last_caps:
-
-  /* Get geometry from caps */
-  structure = gst_caps_get_structure (intersection, 0);
-  if (!gst_structure_get_int (structure, "width", &width) ||
-      !gst_structure_get_int (structure, "height", &height) ||
-      image_format == -1) {
-    GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %"
-        GST_PTR_FORMAT, intersection);
-    ret = GST_FLOW_UNEXPECTED;
-    goto beach;
-  }
-
-  g_mutex_lock (xvimagesink->pool_lock);
-
-  /* Walking through the pool cleaning unusable images and searching for a
-     suitable one */
-  while (xvimagesink->image_pool) {
-    xvimage = xvimagesink->image_pool->data;
-
-    if (xvimage) {
-      /* Removing from the pool */
-      xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
-          xvimagesink->image_pool);
-
-      /* We check for geometry or image format changes */
-      if ((xvimage->width != width) ||
-          (xvimage->height != height) || (xvimage->im_format != image_format)) {
-        /* This image is unusable. Destroying... */
-        gst_xvimage_buffer_free (xvimage);
-        xvimage = NULL;
-      } else {
-        /* We found a suitable image */
-        GST_LOG_OBJECT (xvimagesink, "found usable image in pool");
-        break;
-      }
-    }
-  }
-
-  g_mutex_unlock (xvimagesink->pool_lock);
-
-  if (!xvimage) {
-    /* We found no suitable image in the pool. Creating... */
-    GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
-    xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection);
-    if (xvimage && xvimage->size < size) {
-      /* This image is unusable. Destroying... */
-      gst_xvimage_buffer_free (xvimage);
-      xvimage = NULL;
-    }
-  }
-
-  if (xvimage) {
-    gst_buffer_set_caps (GST_BUFFER (xvimage), intersection);
-  }
-
-  *buf = GST_BUFFER (xvimage);
-
-beach:
-  if (intersection) {
-    gst_caps_unref (intersection);
-  }
-
-  return ret;
-}
-
-/* Interfaces stuff */
-
-static gboolean
-gst_xvimagesink_interface_supported (GstImplementsInterface * iface, GType type)
-{
-  g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY ||
-      type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
-  return TRUE;
-}
-
-static void
-gst_xvimagesink_interface_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = gst_xvimagesink_interface_supported;
-}
-
-static void
-gst_xvimagesink_navigation_send_event (GstNavigation * navigation,
-    GstStructure * structure)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (navigation);
-  GstPad *peer;
-
-  if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (xvimagesink)))) {
-    GstEvent *event;
-    GstVideoRectangle src, dst, result;
-    gdouble x, y, xscale = 1.0, yscale = 1.0;
-
-    event = gst_event_new_navigation (structure);
-
-    /* We take the flow_lock while we look at the window */
-    g_mutex_lock (xvimagesink->flow_lock);
-
-    if (!xvimagesink->xwindow) {
-      g_mutex_unlock (xvimagesink->flow_lock);
-      return;
-    }
-
-    /* We get the frame position using the calculated geometry from _setcaps
-       that respect pixel aspect ratios */
-    src.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
-    src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
-    dst.w = xvimagesink->xwindow->width;
-    dst.h = xvimagesink->xwindow->height;
-
-    g_mutex_unlock (xvimagesink->flow_lock);
-
-    if (xvimagesink->keep_aspect) {
-      gst_video_sink_center_rect (src, dst, &result, TRUE);
-    } else {
-      result.x = result.y = 0;
-      result.w = dst.w;
-      result.h = dst.h;
-    }
-
-    /* We calculate scaling using the original video frames geometry to include
-       pixel aspect ratio scaling. */
-    xscale = (gdouble) xvimagesink->video_width / result.w;
-    yscale = (gdouble) xvimagesink->video_height / result.h;
-
-    /* Converting pointer coordinates to the non scaled geometry */
-    if (gst_structure_get_double (structure, "pointer_x", &x)) {
-      x = MIN (x, result.x + result.w);
-      x = MAX (x - result.x, 0);
-      gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
-          (gdouble) x * xscale, NULL);
-    }
-    if (gst_structure_get_double (structure, "pointer_y", &y)) {
-      y = MIN (y, result.y + result.h);
-      y = MAX (y - result.y, 0);
-      gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
-          (gdouble) y * yscale, NULL);
-    }
-
-    gst_pad_send_event (peer, event);
-    gst_object_unref (peer);
-  }
-}
-
-static void
-gst_xvimagesink_navigation_init (GstNavigationInterface * iface)
-{
-  iface->send_event = gst_xvimagesink_navigation_send_event;
-}
-
-static void
-gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
-  GstXWindow *xwindow = NULL;
-  XWindowAttributes attr;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
-  g_mutex_lock (xvimagesink->flow_lock);
-
-  /* If we already use that window return */
-  if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) {
-    g_mutex_unlock (xvimagesink->flow_lock);
-    return;
-  }
-
-  /* If the element has not initialized the X11 context try to do so */
-  if (!xvimagesink->xcontext &&
-      !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink))) {
-    g_mutex_unlock (xvimagesink->flow_lock);
-    /* we have thrown a GST_ELEMENT_ERROR now */
-    return;
-  }
-
-  gst_xvimagesink_update_colorbalance (xvimagesink);
-
-  /* Clear image pool as the images are unusable anyway */
-  gst_xvimagesink_imagepool_clear (xvimagesink);
-
-  /* Clear the xvimage */
-  if (xvimagesink->xvimage) {
-    gst_xvimage_buffer_free (xvimagesink->xvimage);
-    xvimagesink->xvimage = NULL;
-  }
-
-  /* If a window is there already we destroy it */
-  if (xvimagesink->xwindow) {
-    gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
-    xvimagesink->xwindow = NULL;
-  }
-
-  /* If the xid is 0 we go back to an internal window */
-  if (xwindow_id == 0) {
-    /* If no width/height caps nego did not happen window will be created
-       during caps nego then */
-    if (GST_VIDEO_SINK_WIDTH (xvimagesink)
-        && GST_VIDEO_SINK_HEIGHT (xvimagesink)) {
-      xwindow =
-          gst_xvimagesink_xwindow_new (xvimagesink,
-          GST_VIDEO_SINK_WIDTH (xvimagesink),
-          GST_VIDEO_SINK_HEIGHT (xvimagesink));
-    }
-  } else {
-    xwindow = g_new0 (GstXWindow, 1);
-
-    xwindow->win = xwindow_id;
-
-    /* We get window geometry, set the event we want to receive,
-       and create a GC */
-    g_mutex_lock (xvimagesink->x_lock);
-    XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr);
-    xwindow->width = attr.width;
-    xwindow->height = attr.height;
-    xwindow->internal = FALSE;
-    if (xvimagesink->handle_events) {
-      XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
-          StructureNotifyMask | PointerMotionMask | KeyPressMask |
-          KeyReleaseMask);
-    }
-
-    xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
-        xwindow->win, 0, NULL);
-    g_mutex_unlock (xvimagesink->x_lock);
-  }
-
-  if (xwindow)
-    xvimagesink->xwindow = xwindow;
-
-  g_mutex_unlock (xvimagesink->flow_lock);
-}
-
-static void
-gst_xvimagesink_expose (GstXOverlay * overlay)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
-
-  gst_xvimagesink_xvimage_put (xvimagesink, NULL);
-}
-
-static void
-gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
-    gboolean handle_events)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
-
-  xvimagesink->handle_events = handle_events;
-
-  g_mutex_lock (xvimagesink->flow_lock);
-
-  if (G_UNLIKELY (!xvimagesink->xwindow)) {
-    g_mutex_unlock (xvimagesink->flow_lock);
-    return;
-  }
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  if (handle_events) {
-    if (xvimagesink->xwindow->internal) {
-      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
-          ExposureMask | StructureNotifyMask | PointerMotionMask |
-          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-    } else {
-      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
-          ExposureMask | StructureNotifyMask | PointerMotionMask |
-          KeyPressMask | KeyReleaseMask);
-    }
-  } else {
-    XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, 0);
-  }
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  g_mutex_unlock (xvimagesink->flow_lock);
-}
-
-static void
-gst_xvimagesink_xoverlay_init (GstXOverlayClass * iface)
-{
-  iface->set_xwindow_id = gst_xvimagesink_set_xwindow_id;
-  iface->expose = gst_xvimagesink_expose;
-  iface->handle_events = gst_xvimagesink_set_event_handling;
-}
-
-static const GList *
-gst_xvimagesink_colorbalance_list_channels (GstColorBalance * balance)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance);
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
-  if (xvimagesink->xcontext)
-    return xvimagesink->xcontext->channels_list;
-  else
-    return NULL;
-}
-
-static void
-gst_xvimagesink_colorbalance_set_value (GstColorBalance * balance,
-    GstColorBalanceChannel * channel, gint value)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance);
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-  g_return_if_fail (channel->label != NULL);
-
-  xvimagesink->cb_changed = TRUE;
-
-  /* Normalize val to [-1000, 1000] */
-  value = -1000 + 2000 * (value - channel->min_value) /
-      (channel->max_value - channel->min_value);
-
-  if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
-    xvimagesink->hue = value;
-  } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
-    xvimagesink->saturation = value;
-  } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
-    xvimagesink->contrast = value;
-  } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
-    xvimagesink->brightness = value;
-  } else {
-    g_warning ("got an unknown channel %s", channel->label);
-    return;
-  }
-
-  gst_xvimagesink_update_colorbalance (xvimagesink);
-}
-
-static gint
-gst_xvimagesink_colorbalance_get_value (GstColorBalance * balance,
-    GstColorBalanceChannel * channel)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance);
-  gint value = 0;
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
-  g_return_val_if_fail (channel->label != NULL, 0);
-
-  if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
-    value = xvimagesink->hue;
-  } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
-    value = xvimagesink->saturation;
-  } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
-    value = xvimagesink->contrast;
-  } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
-    value = xvimagesink->brightness;
-  } else {
-    g_warning ("got an unknown channel %s", channel->label);
-  }
-
-  /* Normalize val to [channel->min_value, channel->max_value] */
-  value = channel->min_value + (channel->max_value - channel->min_value) *
-      (value + 1000) / 2000;
-
-  return value;
-}
-
-static void
-gst_xvimagesink_colorbalance_init (GstColorBalanceClass * iface)
-{
-  GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
-  iface->list_channels = gst_xvimagesink_colorbalance_list_channels;
-  iface->set_value = gst_xvimagesink_colorbalance_set_value;
-  iface->get_value = gst_xvimagesink_colorbalance_get_value;
-}
-
-static const GList *
-gst_xvimagesink_probe_get_properties (GstPropertyProbe * probe)
-{
-  GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
-  static GList *list = NULL;
-
-  if (!list) {
-    list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
-  }
-
-  return list;
-}
-
-static void
-gst_xvimagesink_probe_probe_property (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe);
-
-  switch (prop_id) {
-    case ARG_DEVICE:
-      GST_DEBUG_OBJECT (xvimagesink, "probing device list");
-      if (!xvimagesink->xcontext) {
-        GST_DEBUG_OBJECT (xvimagesink, "generating xcontext");
-        xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
-      }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_xvimagesink_probe_needs_probe (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe);
-  gboolean ret = FALSE;
-
-  switch (prop_id) {
-    case ARG_DEVICE:
-      if (xvimagesink->xcontext != NULL) {
-        ret = FALSE;
-      } else {
-        ret = TRUE;
-      }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-      break;
-  }
-
-  return ret;
-}
-
-static GValueArray *
-gst_xvimagesink_probe_get_values (GstPropertyProbe * probe,
-    guint prop_id, const GParamSpec * pspec)
-{
-  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe);
-  GValueArray *array = NULL;
-
-  if (G_UNLIKELY (!xvimagesink->xcontext)) {
-    GST_WARNING_OBJECT (xvimagesink, "we don't have any xcontext, can't "
-        "get values");
-    goto beach;
-  }
-
-  switch (prop_id) {
-    case ARG_DEVICE:
-    {
-      guint i;
-      GValue value = { 0 };
-
-      array = g_value_array_new (xvimagesink->xcontext->nb_adaptors);
-      g_value_init (&value, G_TYPE_STRING);
-
-      for (i = 0; i < xvimagesink->xcontext->nb_adaptors; i++) {
-        gchar *adaptor_id_s = g_strdup_printf ("%u", i);
-
-        g_value_set_string (&value, adaptor_id_s);
-        g_value_array_append (array, &value);
-        g_free (adaptor_id_s);
-      }
-      g_value_unset (&value);
-      break;
-    }
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
-      break;
-  }
-
-beach:
-  return array;
-}
-
-static void
-gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface *
-    iface)
-{
-  iface->get_properties = gst_xvimagesink_probe_get_properties;
-  iface->probe_property = gst_xvimagesink_probe_probe_property;
-  iface->needs_probe = gst_xvimagesink_probe_needs_probe;
-  iface->get_values = gst_xvimagesink_probe_get_values;
-}
-
-/* =========================================== */
-/*                                             */
-/*              Init & Class init              */
-/*                                             */
-/* =========================================== */
-
-static void
-gst_xvimagesink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstXvImageSink *xvimagesink;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (object));
-
-  xvimagesink = GST_XVIMAGESINK (object);
-
-  switch (prop_id) {
-    case ARG_HUE:
-      xvimagesink->hue = g_value_get_int (value);
-      xvimagesink->cb_changed = TRUE;
-      gst_xvimagesink_update_colorbalance (xvimagesink);
-      break;
-    case ARG_CONTRAST:
-      xvimagesink->contrast = g_value_get_int (value);
-      xvimagesink->cb_changed = TRUE;
-      gst_xvimagesink_update_colorbalance (xvimagesink);
-      break;
-    case ARG_BRIGHTNESS:
-      xvimagesink->brightness = g_value_get_int (value);
-      xvimagesink->cb_changed = TRUE;
-      gst_xvimagesink_update_colorbalance (xvimagesink);
-      break;
-    case ARG_SATURATION:
-      xvimagesink->saturation = g_value_get_int (value);
-      xvimagesink->cb_changed = TRUE;
-      gst_xvimagesink_update_colorbalance (xvimagesink);
-      break;
-    case ARG_DISPLAY:
-      xvimagesink->display_name = g_strdup (g_value_get_string (value));
-      break;
-    case ARG_SYNCHRONOUS:
-      xvimagesink->synchronous = g_value_get_boolean (value);
-      if (xvimagesink->xcontext) {
-        XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
-        GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s",
-            xvimagesink->synchronous ? "TRUE" : "FALSE");
-      }
-      break;
-    case ARG_PIXEL_ASPECT_RATIO:
-      g_free (xvimagesink->par);
-      xvimagesink->par = g_new0 (GValue, 1);
-      g_value_init (xvimagesink->par, GST_TYPE_FRACTION);
-      if (!g_value_transform (value, xvimagesink->par)) {
-        g_warning ("Could not transform string to aspect ratio");
-        gst_value_set_fraction (xvimagesink->par, 1, 1);
-      }
-      GST_DEBUG_OBJECT (xvimagesink, "set PAR to %d/%d",
-          gst_value_get_fraction_numerator (xvimagesink->par),
-          gst_value_get_fraction_denominator (xvimagesink->par));
-      break;
-    case ARG_FORCE_ASPECT_RATIO:
-      xvimagesink->keep_aspect = g_value_get_boolean (value);
-      break;
-    case ARG_HANDLE_EVENTS:
-      gst_xvimagesink_set_event_handling (GST_X_OVERLAY (xvimagesink),
-          g_value_get_boolean (value));
-      break;
-    case ARG_DEVICE:
-      xvimagesink->adaptor_no = atoi (g_value_get_string (value));
-      break;
-    case ARG_HANDLE_EXPOSE:
-      xvimagesink->handle_expose = g_value_get_boolean (value);
-      break;
-    case ARG_DOUBLE_BUFFER:
-      xvimagesink->double_buffer = g_value_get_boolean (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_xvimagesink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstXvImageSink *xvimagesink;
-
-  g_return_if_fail (GST_IS_XVIMAGESINK (object));
-
-  xvimagesink = GST_XVIMAGESINK (object);
-
-  switch (prop_id) {
-    case ARG_HUE:
-      g_value_set_int (value, xvimagesink->hue);
-      break;
-    case ARG_CONTRAST:
-      g_value_set_int (value, xvimagesink->contrast);
-      break;
-    case ARG_BRIGHTNESS:
-      g_value_set_int (value, xvimagesink->brightness);
-      break;
-    case ARG_SATURATION:
-      g_value_set_int (value, xvimagesink->saturation);
-      break;
-    case ARG_DISPLAY:
-      g_value_set_string (value, xvimagesink->display_name);
-      break;
-    case ARG_SYNCHRONOUS:
-      g_value_set_boolean (value, xvimagesink->synchronous);
-      break;
-    case ARG_PIXEL_ASPECT_RATIO:
-      if (xvimagesink->par)
-        g_value_transform (xvimagesink->par, value);
-      break;
-    case ARG_FORCE_ASPECT_RATIO:
-      g_value_set_boolean (value, xvimagesink->keep_aspect);
-      break;
-    case ARG_HANDLE_EVENTS:
-      g_value_set_boolean (value, xvimagesink->handle_events);
-      break;
-    case ARG_DEVICE:
-    {
-      char *adaptor_no_s = g_strdup_printf ("%u", xvimagesink->adaptor_no);
-
-      g_value_set_string (value, adaptor_no_s);
-      g_free (adaptor_no_s);
-      break;
-    }
-    case ARG_DEVICE_NAME:
-      if (xvimagesink->xcontext && xvimagesink->xcontext->adaptors) {
-        g_value_set_string (value,
-            xvimagesink->xcontext->adaptors[xvimagesink->adaptor_no]);
-      } else {
-        g_value_set_string (value, NULL);
-      }
-      break;
-    case ARG_HANDLE_EXPOSE:
-      g_value_set_boolean (value, xvimagesink->handle_expose);
-      break;
-    case ARG_DOUBLE_BUFFER:
-      g_value_set_boolean (value, xvimagesink->double_buffer);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
-{
-  GThread *thread;
-
-  GST_OBJECT_LOCK (xvimagesink);
-  xvimagesink->running = FALSE;
-  /* grab thread and mark it as NULL */
-  thread = xvimagesink->event_thread;
-  xvimagesink->event_thread = NULL;
-  GST_OBJECT_UNLOCK (xvimagesink);
-
-  /* Wait for our event thread to finish before we clean up our stuff. */
-  if (thread)
-    g_thread_join (thread);
-
-  if (xvimagesink->cur_image) {
-    gst_buffer_unref (xvimagesink->cur_image);
-    xvimagesink->cur_image = NULL;
-  }
-  if (xvimagesink->xvimage) {
-    gst_buffer_unref (xvimagesink->xvimage);
-    xvimagesink->xvimage = NULL;
-  }
-
-  gst_xvimagesink_imagepool_clear (xvimagesink);
-
-  if (xvimagesink->xwindow) {
-    gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
-    gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
-    xvimagesink->xwindow = NULL;
-  }
-
-  gst_xvimagesink_xcontext_clear (xvimagesink);
-}
-
-/* Finalize is called only once, dispose can be called multiple times.
- * We use mutexes and don't reset stuff to NULL here so let's register
- * as a finalize. */
-static void
-gst_xvimagesink_finalize (GObject * object)
-{
-  GstXvImageSink *xvimagesink;
-
-  xvimagesink = GST_XVIMAGESINK (object);
-
-  gst_xvimagesink_reset (xvimagesink);
-
-  if (xvimagesink->display_name) {
-    g_free (xvimagesink->display_name);
-    xvimagesink->display_name = NULL;
-  }
-
-  if (xvimagesink->par) {
-    g_free (xvimagesink->par);
-    xvimagesink->par = NULL;
-  }
-  if (xvimagesink->x_lock) {
-    g_mutex_free (xvimagesink->x_lock);
-    xvimagesink->x_lock = NULL;
-  }
-  if (xvimagesink->flow_lock) {
-    g_mutex_free (xvimagesink->flow_lock);
-    xvimagesink->flow_lock = NULL;
-  }
-  if (xvimagesink->pool_lock) {
-    g_mutex_free (xvimagesink->pool_lock);
-    xvimagesink->pool_lock = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_xvimagesink_init (GstXvImageSink * xvimagesink)
-{
-  xvimagesink->display_name = NULL;
-  xvimagesink->adaptor_no = 0;
-  xvimagesink->xcontext = NULL;
-  xvimagesink->xwindow = NULL;
-  xvimagesink->xvimage = NULL;
-  xvimagesink->cur_image = NULL;
-
-  xvimagesink->hue = xvimagesink->saturation = 0;
-  xvimagesink->contrast = xvimagesink->brightness = 0;
-  xvimagesink->cb_changed = FALSE;
-
-  xvimagesink->fps_n = 0;
-  xvimagesink->fps_d = 0;
-  xvimagesink->video_width = 0;
-  xvimagesink->video_height = 0;
-
-  xvimagesink->x_lock = g_mutex_new ();
-  xvimagesink->flow_lock = g_mutex_new ();
-
-  xvimagesink->image_pool = NULL;
-  xvimagesink->pool_lock = g_mutex_new ();
-
-  xvimagesink->synchronous = FALSE;
-  xvimagesink->double_buffer = TRUE;
-  xvimagesink->running = FALSE;
-  xvimagesink->keep_aspect = FALSE;
-  xvimagesink->handle_events = TRUE;
-  xvimagesink->par = NULL;
-  xvimagesink->handle_expose = TRUE;
-}
-
-static void
-gst_xvimagesink_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details (element_class, &gst_xvimagesink_details);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_xvimagesink_sink_template_factory));
-}
-
-static void
-gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSinkClass *gstbasesink_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesink_class = (GstBaseSinkClass *) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->set_property = gst_xvimagesink_set_property;
-  gobject_class->get_property = gst_xvimagesink_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_CONTRAST,
-      g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
-          -1000, 1000, 0, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_BRIGHTNESS,
-      g_param_spec_int ("brightness", "Brightness",
-          "The brightness of the video", -1000, 1000, 0, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_HUE,
-      g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_SATURATION,
-      g_param_spec_int ("saturation", "Saturation",
-          "The saturation of the video", -1000, 1000, 0, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_DISPLAY,
-      g_param_spec_string ("display", "Display", "X Display name", NULL,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_SYNCHRONOUS,
-      g_param_spec_boolean ("synchronous", "Synchronous",
-          "When enabled, runs "
-          "the X display in synchronous mode. (used only for debugging)", FALSE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_PIXEL_ASPECT_RATIO,
-      g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
-          "The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_FORCE_ASPECT_RATIO,
-      g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
-          "When enabled, scaling will respect original aspect ratio", FALSE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_HANDLE_EVENTS,
-      g_param_spec_boolean ("handle-events", "Handle XEvents",
-          "When enabled, XEvents will be selected and handled", TRUE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_DEVICE,
-      g_param_spec_string ("device", "Adaptor number",
-          "The number of the video adaptor", "0", G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_DEVICE_NAME,
-      g_param_spec_string ("device-name", "Adaptor name",
-          "The name of the video adaptor", NULL, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class, ARG_HANDLE_EXPOSE,
-      g_param_spec_boolean ("handle-expose", "Handle expose", "When enabled, "
-          "the current frame will always be drawn in response to X Expose "
-          "events", TRUE, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_DOUBLE_BUFFER,
-      g_param_spec_boolean ("double-buffer", "Double-buffer",
-          "Whether to double-buffer the output", TRUE, G_PARAM_READWRITE));
-
-  gobject_class->finalize = gst_xvimagesink_finalize;
-
-  gstelement_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state);
-
-  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
-  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
-  gstbasesink_class->buffer_alloc =
-      GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc);
-  gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times);
-  gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame);
-  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame);
-}
-
-/* ============================================================= */
-/*                                                               */
-/*                       Public Methods                          */
-/*                                                               */
-/* ============================================================= */
-
-/* =========================================== */
-/*                                             */
-/*          Object typing & Creation           */
-/*                                             */
-/* =========================================== */
-
-GType
-gst_xvimagesink_get_type (void)
-{
-  static GType xvimagesink_type = 0;
-
-  if (!xvimagesink_type) {
-    static const GTypeInfo xvimagesink_info = {
-      sizeof (GstXvImageSinkClass),
-      gst_xvimagesink_base_init,
-      NULL,
-      (GClassInitFunc) gst_xvimagesink_class_init,
-      NULL,
-      NULL,
-      sizeof (GstXvImageSink),
-      0,
-      (GInstanceInitFunc) gst_xvimagesink_init,
-    };
-    static const GInterfaceInfo iface_info = {
-      (GInterfaceInitFunc) gst_xvimagesink_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo navigation_info = {
-      (GInterfaceInitFunc) gst_xvimagesink_navigation_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo overlay_info = {
-      (GInterfaceInitFunc) gst_xvimagesink_xoverlay_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo colorbalance_info = {
-      (GInterfaceInitFunc) gst_xvimagesink_colorbalance_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo propertyprobe_info = {
-      (GInterfaceInitFunc) gst_xvimagesink_property_probe_interface_init,
-      NULL,
-      NULL,
-    };
-    xvimagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
-        "GstXvImageSink", &xvimagesink_info, 0);
-
-    g_type_add_interface_static (xvimagesink_type,
-        GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
-    g_type_add_interface_static (xvimagesink_type, GST_TYPE_NAVIGATION,
-        &navigation_info);
-    g_type_add_interface_static (xvimagesink_type, GST_TYPE_X_OVERLAY,
-        &overlay_info);
-    g_type_add_interface_static (xvimagesink_type, GST_TYPE_COLOR_BALANCE,
-        &colorbalance_info);
-    g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE,
-        &propertyprobe_info);
-
-
-    /* register type and create class in a more safe place instead of at
-     * runtime since the type registration and class creation is not
-     * threadsafe. */
-    g_type_class_ref (gst_xvimage_buffer_get_type ());
-  }
-
-  return xvimagesink_type;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  if (!gst_element_register (plugin, "xvimagesink",
-          GST_RANK_PRIMARY, GST_TYPE_XVIMAGESINK))
-    return FALSE;
-
-  GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagesink, "xvimagesink", 0,
-      "xvimagesink element");
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "xvimagesink",
-    "XFree86 video output plugin using Xv extension",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/sys/xvimage/xvimagesink.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
- *
- * 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_XVIMAGESINK_H__
-#define __GST_XVIMAGESINK_H__
-
-#include <gst/video/gstvideosink.h>
-
-#ifdef HAVE_XSHM
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif /* HAVE_XSHM */
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#ifdef HAVE_XSHM
-#include <X11/extensions/XShm.h>
-#endif /* HAVE_XSHM */
-
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_XVIMAGESINK \
-  (gst_xvimagesink_get_type())
-#define GST_XVIMAGESINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XVIMAGESINK, GstXvImageSink))
-#define GST_XVIMAGESINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XVIMAGESINK, GstXvImageSinkClass))
-#define GST_IS_XVIMAGESINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIMAGESINK))
-#define GST_IS_XVIMAGESINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIMAGESINK))
-
-typedef struct _GstXContext GstXContext;
-typedef struct _GstXWindow GstXWindow;
-typedef struct _GstXvImageFormat GstXvImageFormat;
-typedef struct _GstXvImageBuffer GstXvImageBuffer;
-typedef struct _GstXvImageBufferClass GstXvImageBufferClass;
-
-typedef struct _GstXvImageSink GstXvImageSink;
-typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
-
-/**
- * GstXContext:
- * @disp: the X11 Display of this context
- * @screen: the default Screen of Display @disp
- * @screen_num: the Screen number of @screen
- * @visual: the default Visual of Screen @screen
- * @root: the root Window of Display @disp
- * @white: the value of a white pixel on Screen @screen
- * @black: the value of a black pixel on Screen @screen
- * @depth: the color depth of Display @disp
- * @bpp: the number of bits per pixel on Display @disp
- * @endianness: the endianness of image bytes on Display @disp
- * @width: the width in pixels of Display @disp
- * @height: the height in pixels of Display @disp
- * @widthmm: the width in millimeters of Display @disp
- * @heightmm: the height in millimeters of Display @disp
- * @par: the pixel aspect ratio calculated from @width, @widthmm and @height,
- * @heightmm ratio
- * @use_xshm: used to known wether of not XShm extension is usable or not even
- * if the Extension is present
- * @xv_port_id: the XVideo port ID
- * @im_format: used to store at least a valid format for XShm calls checks
- * @formats_list: list of supported image formats on @xv_port_id
- * @channels_list: list of #GstColorBalanceChannels
- * @caps: the #GstCaps that Display @disp can accept
- *
- * Structure used to store various informations collected/calculated for a
- * Display.
- */
-struct _GstXContext {
-  Display *disp;
-
-  Screen *screen;
-  gint screen_num;
-
-  Visual *visual;
-
-  Window root;
-
-  gulong white, black;
-
-  gint depth;
-  gint bpp;
-  gint endianness;
-
-  gint width, height;
-  gint widthmm, heightmm;
-  GValue *par;                  /* calculated pixel aspect ratio */
-
-  gboolean use_xshm;
-
-  XvPortID xv_port_id;
-  guint nb_adaptors;
-  gchar ** adaptors;
-  gint im_format;
-
-  GList *formats_list;
-  GList *channels_list;
-
-  GstCaps *caps;
-
-  /* Optimisation storage for buffer_alloc return */
-  GstCaps *last_caps;
-  gint last_format;
-};
-
-/**
- * GstXWindow:
- * @win: the Window ID of this X11 window
- * @width: the width in pixels of Window @win
- * @height: the height in pixels of Window @win
- * @internal: used to remember if Window @win was created internally or passed
- * through the #GstXOverlay interface
- * @gc: the Graphical Context of Window @win
- *
- * Structure used to store informations about a Window.
- */
-struct _GstXWindow {
-  Window win;
-  gint width, height;
-  gboolean internal;
-  GC gc;
-};
-
-/**
- * GstXvImageFormat:
- * @format: the image format
- * @caps: generated #GstCaps for this image format
- *
- * Structure storing image format to #GstCaps association.
- */
-struct _GstXvImageFormat {
-  gint format;
-  GstCaps *caps;
-};
-
-/**
- * GstXImageBuffer:
- * @xvimagesink: a reference to our #GstXvImageSink
- * @xvimage: the XvImage of this buffer
- * @width: the width in pixels of XvImage @xvimage
- * @height: the height in pixels of XvImage @xvimage
- * @im_format: the image format of XvImage @xvimage
- * @size: the size in bytes of XvImage @xvimage
- *
- * Subclass of #GstBuffer containing additional information about an XvImage.
- */
-struct _GstXvImageBuffer {
-  GstBuffer   buffer;
-
-  /* Reference to the xvimagesink we belong to */
-  GstXvImageSink *xvimagesink;
-
-  XvImage *xvimage;
-
-#ifdef HAVE_XSHM
-  XShmSegmentInfo SHMInfo;
-#endif /* HAVE_XSHM */
-
-  gint width, height, im_format;
-  size_t size;
-};
-
-/**
- * GstXvImageSink:
- * @display_name: the name of the Display we want to render to
- * @xcontext: our instance's #GstXContext
- * @xwindow: the #GstXWindow we are rendering to
- * @xvimage: internal #GstXvImage used to store incoming buffers and render when
- * not using the buffer_alloc optimization mechanism
- * @cur_image: a reference to the last #GstXvImage that was put to @xwindow. It
- * is used when Expose events are received to redraw the latest video frame
- * @event_thread: a thread listening for events on @xwindow and handling them
- * @running: used to inform @event_thread if it should run/shutdown
- * @fps_n: the framerate fraction numerator
- * @fps_d: the framerate fraction denominator
- * @x_lock: used to protect X calls as we are not using the XLib in threaded
- * mode
- * @flow_lock: used to protect data flow routines from external calls such as
- * events from @event_thread or methods from the #GstXOverlay interface
- * @par: used to override calculated pixel aspect ratio from @xcontext
- * @pool_lock: used to protect the buffer pool
- * @image_pool: a list of #GstXvImageBuffer that could be reused at next buffer
- * allocation call
- * @synchronous: used to store if XSynchronous should be used or not (for
- * debugging purpose only)
- * @keep_aspect: used to remember if reverse negotiation scaling should respect
- * aspect ratio
- * @handle_events: used to know if we should handle select XEvents or not
- * @brightness: used to store the user settings for color balance brightness
- * @contrast: used to store the user settings for color balance contrast
- * @hue: used to store the user settings for color balance hue
- * @saturation: used to store the user settings for color balance saturation
- * @cb_changed: used to store if the color balance settings where changed
- * @video_width: the width of incoming video frames in pixels
- * @video_height: the height of incoming video frames in pixels
- *
- * The #GstXvImageSink data structure.
- */
-struct _GstXvImageSink {
-  /* Our element stuff */
-  GstVideoSink videosink;
-
-  char *display_name;
-  guint adaptor_no;
-
-  GstXContext *xcontext;
-  GstXWindow *xwindow;
-  GstXvImageBuffer *xvimage;
-  GstXvImageBuffer *cur_image;
-
-  GThread *event_thread;
-  gboolean running;
-
-  gint fps_n;
-  gint fps_d;
-
-  GMutex *x_lock;
-  GMutex *flow_lock;
-
-  /* object-set pixel aspect ratio */
-  GValue *par;
-
-  GMutex *pool_lock;
-  GSList *image_pool;
-
-  gboolean synchronous;
-  gboolean double_buffer;
-  gboolean keep_aspect;
-  gboolean draw_border;
-  gboolean handle_events;
-  gboolean handle_expose;
-
-  gint brightness;
-  gint contrast;
-  gint hue;
-  gint saturation;
-  gboolean cb_changed;
-
-  guint video_width, video_height;     /* size of incoming video;
-                                        * used as the size for XvImage */
-};
-
-struct _GstXvImageSinkClass {
-  GstVideoSinkClass parent_class;
-};
-
-GType gst_xvimagesink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_XVIMAGESINK_H__ */
--- a/gst_plugins_base/tsrc/check/elements/adder/src/adder.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/adder/src/adder.c	Fri Apr 16 15:15:52 2010 +0300
@@ -42,11 +42,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 #include <gst/check/gstcheck.h>
 #include "libgstreamer_wsd_solution.h" 
--- a/gst_plugins_base/tsrc/check/elements/audioconvert/src/audioconvert.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/audioconvert/src/audioconvert.c	Fri Apr 16 15:15:52 2010 +0300
@@ -53,11 +53,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gst_plugins_base/tsrc/check/elements/audiorate/src/audiorate.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/audiorate/src/audiorate.c	Fri Apr 16 15:15:52 2010 +0300
@@ -36,11 +36,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gst_plugins_base/tsrc/check/elements/audioresample/src/audioresample.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/audioresample/src/audioresample.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,6 @@
 /* GStreamer
  *
- * unit test for audioresample
+ * unit test for audioresample, based on the audioresample unit test
  *
  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
  * Copyright (C) <2006> Tim-Philipp Müller <tim at centricular net>
@@ -20,27 +20,37 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-
-
 #include <gst/gst_global.h>
 #include <unistd.h>
+
 #include <gst/check/gstcheck.h>
 
-
-
+#include <gst/audio/audio.h>
 
 #define LOG_FILE "c:\\logs\\audioresample_logs.txt" 
 #include "std_log_result.h" 
 #define LOG_FILENAME_LINE __FILE__, __LINE__
 
+//char* xmlfile = "gstsystemclock";
+
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 #include "libgstreamer_wsd_solution.h" 
 
 
@@ -79,16 +89,19 @@
 #endif
 
 
-
-
-
 /* For ease of programming we use globals to keep refs for our floating
  * src and sink pads we create; otherwise we always have to do get_pad,
  * get_peer, and then remove references in every test function */
 static GstPad *mysrcpad, *mysinkpad;
 
+#define RESAMPLE_CAPS_FLOAT     \
+    "audio/x-raw-float, "               \
+    "channels = (int) [ 1, MAX ], "     \
+    "rate = (int) [ 1,  MAX ], "        \
+    "endianness = (int) BYTE_ORDER, "   \
+    "width = (int) { 32, 64 }"
 
-#define RESAMPLE_CAPS_TEMPLATE_STRING   \
+#define RESAMPLE_CAPS_INT       \
     "audio/x-raw-int, "                 \
     "channels = (int) [ 1, MAX ], "     \
     "rate = (int) [ 1,  MAX ], "        \
@@ -97,6 +110,10 @@
     "depth = (int) 16, "                \
     "signed = (bool) TRUE"
 
+#define RESAMPLE_CAPS_TEMPLATE_STRING   \
+    RESAMPLE_CAPS_FLOAT " ; " \
+    RESAMPLE_CAPS_INT
+
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
@@ -109,20 +126,25 @@
     );
 
 static GstElement *
-setup_audioresample (int channels, int inrate, int outrate)
+setup_audioresample (int channels, int inrate, int outrate, int width,
+    gboolean fp)
 {
   GstElement *audioresample;
   GstCaps *caps;
   GstStructure *structure;
-  GstPad *pad;
 
   GST_DEBUG ("setup_audioresample");
   audioresample = gst_check_setup_element ("audioresample");
 
-  caps = gst_caps_from_string (RESAMPLE_CAPS_TEMPLATE_STRING);
+  if (fp)
+    caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
+  else
+    caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
   structure = gst_caps_get_structure (caps, 0);
   gst_structure_set (structure, "channels", G_TYPE_INT, channels,
-      "rate", G_TYPE_INT, inrate, NULL);
+      "rate", G_TYPE_INT, inrate, "width", G_TYPE_INT, width, NULL);
+  if (!fp)
+    gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
   fail_unless (gst_caps_is_fixed (caps));
 
   fail_unless (gst_element_set_state (audioresample,
@@ -130,27 +152,30 @@
       "could not set to paused");
 
   mysrcpad = gst_check_setup_src_pad (audioresample, &srctemplate, caps);
-  pad = gst_pad_get_peer (mysrcpad);
-  gst_pad_set_caps (pad, caps);
-  gst_object_unref (GST_OBJECT (pad));
+  gst_pad_set_caps (mysrcpad, caps);
   gst_caps_unref (caps);
-  gst_pad_set_active (mysrcpad, TRUE);
 
-  caps = gst_caps_from_string (RESAMPLE_CAPS_TEMPLATE_STRING);
+  if (fp)
+    caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
+  else
+    caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
   structure = gst_caps_get_structure (caps, 0);
   gst_structure_set (structure, "channels", G_TYPE_INT, channels,
-      "rate", G_TYPE_INT, outrate, NULL);
+      "rate", G_TYPE_INT, outrate, "width", G_TYPE_INT, width, NULL);
+  if (!fp)
+    gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
   fail_unless (gst_caps_is_fixed (caps));
 
   mysinkpad = gst_check_setup_sink_pad (audioresample, &sinktemplate, caps);
   /* this installs a getcaps func that will always return the caps we set
    * later */
+  gst_pad_set_caps (mysinkpad, caps);
   gst_pad_use_fixed_caps (mysinkpad);
-  pad = gst_pad_get_peer (mysinkpad);
-  gst_pad_set_caps (pad, caps);
-  gst_object_unref (GST_OBJECT (pad));
+
+  gst_pad_set_active (mysinkpad, TRUE);
+  gst_pad_set_active (mysrcpad, TRUE);
+
   gst_caps_unref (caps);
-  gst_pad_set_active (mysinkpad, TRUE);
 
   return audioresample;
 }
@@ -183,8 +208,11 @@
     buffer = GST_BUFFER (l->data);
     ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
     GST_DEBUG ("buffer timestamp %" G_GUINT64_FORMAT ", duration %"
-        G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (buffer),
-        GST_BUFFER_DURATION (buffer));
+        G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
+        G_GUINT64_FORMAT,
+        GST_BUFFER_TIMESTAMP (buffer),
+        GST_BUFFER_DURATION (buffer),
+        GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer));
 
     fail_unless_equals_uint64 (timestamp, GST_BUFFER_TIMESTAMP (buffer));
     fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET (buffer));
@@ -207,12 +235,12 @@
   GstElement *audioresample;
   GstBuffer *inbuffer, *outbuffer;
   GstCaps *caps;
+  guint64 offset = 0;
 
   int i, j;
   gint16 *p;
-  
 
-  audioresample = setup_audioresample (2, inrate, outrate);
+  audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE);
   caps = gst_pad_get_negotiated_caps (mysrcpad);
   fail_unless (gst_caps_is_fixed (caps));
 
@@ -223,10 +251,11 @@
   for (j = 1; j <= numbuffers; ++j) {
 
     inbuffer = gst_buffer_new_and_alloc (samples * 4);
-    GST_BUFFER_DURATION (inbuffer) = samples * GST_SECOND / inrate;
+    GST_BUFFER_DURATION (inbuffer) = GST_FRAMES_TO_CLOCK_TIME (samples, inrate);
     GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_DURATION (inbuffer) * (j - 1);
-    GST_BUFFER_OFFSET (inbuffer) = 0;
-    GST_BUFFER_OFFSET_END (inbuffer) = samples;
+    GST_BUFFER_OFFSET (inbuffer) = offset;
+    offset += samples;
+    GST_BUFFER_OFFSET_END (inbuffer) = offset;
 
     gst_buffer_set_caps (inbuffer, caps);
 
@@ -264,9 +293,9 @@
  */
 void test_perfect_stream()
 {
-	xmlfile = "test_perfect_stream";
+  /* integral scalings */
+    xmlfile = "test_perfect_stream";
   std_log(LOG_FILENAME_LINE, "Test Started test_perfect_stream");
-  /* integral scalings */
   test_perfect_stream_instance (48000, 24000, 500, 20);
   test_perfect_stream_instance (48000, 12000, 500, 20);
   test_perfect_stream_instance (12000, 24000, 500, 20);
@@ -299,7 +328,10 @@
   int i, j;
   gint16 *p;
 
-  audioresample = setup_audioresample (2, inrate, outrate);
+  GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d",
+      inrate, outrate, samples, numbuffers);
+
+  audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE);
   caps = gst_pad_get_negotiated_caps (mysrcpad);
   fail_unless (gst_caps_is_fixed (caps));
 
@@ -329,6 +361,11 @@
       ++p;
     }
 
+    GST_DEBUG ("Sending Buffer time:%" G_GUINT64_FORMAT " duration:%"
+        G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
+        G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (inbuffer),
+        GST_BUFFER_DURATION (inbuffer), GST_BUFFER_IS_DISCONT (inbuffer),
+        GST_BUFFER_OFFSET (inbuffer), GST_BUFFER_OFFSET_END (inbuffer));
     /* pushing gives away my reference ... */
     fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
 
@@ -336,9 +373,14 @@
     outbuffer = g_list_nth_data (buffers, g_list_length (buffers) - 1);
     fail_if (outbuffer == NULL);
     fail_unless_equals_uint64 (ints, GST_BUFFER_TIMESTAMP (outbuffer));
+    GST_DEBUG ("Got Buffer time:%" G_GUINT64_FORMAT " duration:%"
+        G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
+        G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (outbuffer),
+        GST_BUFFER_DURATION (outbuffer), GST_BUFFER_IS_DISCONT (outbuffer),
+        GST_BUFFER_OFFSET (outbuffer), GST_BUFFER_OFFSET_END (outbuffer));
     if (j > 1) {
       fail_unless (GST_BUFFER_IS_DISCONT (outbuffer),
-          "expected discont buffer");
+          "expected discont for buffer #%d", j);
     }
   }
 
@@ -349,10 +391,9 @@
 
 void test_discont_stream()
 {
-	xmlfile = "test_discont_stream";
+  /* integral scalings */
+    xmlfile = "test_discont_stream";
   std_log(LOG_FILENAME_LINE, "Test Started test_discont_stream");
-
-  /* integral scalings */
   test_discont_stream_instance (48000, 24000, 500, 20);
   test_discont_stream_instance (48000, 12000, 500, 20);
   test_discont_stream_instance (12000, 24000, 500, 20);
@@ -364,7 +405,6 @@
 
   /* wacky scalings */
   test_discont_stream_instance (12345, 54321, 500, 20);
-
   test_discont_stream_instance (101, 99, 500, 20);
   
   std_log(LOG_FILENAME_LINE, "Test Successful");
@@ -382,9 +422,8 @@
   GstBuffer *inbuffer;
   GstCaps *caps;
   xmlfile = "test_reuse";
-  std_log(LOG_FILENAME_LINE, "Test Started test_reuse");
-
-  audioresample = setup_audioresample (1, 9343, 48000);
+std_log(LOG_FILENAME_LINE, "Test Started test_reuse");
+  audioresample = setup_audioresample (1, 9343, 48000, 16, FALSE);
   caps = gst_pad_get_negotiated_caps (mysrcpad);
   fail_unless (gst_caps_is_fixed (caps));
 
@@ -436,6 +475,7 @@
 
   cleanup_audioresample (audioresample);
   gst_caps_unref (caps);
+  
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0);
 }
@@ -448,10 +488,10 @@
   GstCaps *caps;
   guint i;
   xmlfile = "test_shutdown";
-  std_log(LOG_FILENAME_LINE, "Test Started test_shutdown");
-
+std_log(LOG_FILENAME_LINE, "Test Started test_shutdown");
   /* create pipeline, force audioresample to actually resample */
   pipeline = gst_pipeline_new (NULL);
+
   src = gst_check_setup_element ("audiotestsrc");
   cf1 = gst_check_setup_element ("capsfilter");
   ar = gst_check_setup_element ("audioresample");
@@ -486,31 +526,341 @@
   }
 
   gst_object_unref (pipeline);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+  create_xml(0);
+}
+
+
+
+static GstFlowReturn
+live_switch_alloc_only_48000 (GstPad * pad, guint64 offset,
+    guint size, GstCaps * caps, GstBuffer ** buf)
+{
+  GstStructure *structure;
+  gint rate;
+  gint channels;
+  GstCaps *desired;
+
+  structure = gst_caps_get_structure (caps, 0);
+  fail_unless (gst_structure_get_int (structure, "rate", &rate));
+  fail_unless (gst_structure_get_int (structure, "channels", &channels));
+
+  if (rate < 48000)
+    return GST_FLOW_NOT_NEGOTIATED;
+
+  desired = gst_caps_copy (caps);
+  gst_caps_set_simple (desired, "rate", G_TYPE_INT, 48000, NULL);
+
+  *buf = gst_buffer_new_and_alloc (channels * 48000);
+  gst_buffer_set_caps (*buf, desired);
+  gst_caps_unref (desired);
+
+  return GST_FLOW_OK;
+}
+
+static GstCaps *
+live_switch_get_sink_caps (GstPad * pad)
+{
+  GstCaps *result;
+
+  result = gst_caps_copy (GST_PAD_CAPS (pad));
+
+  gst_caps_set_simple (result,
+      "rate", GST_TYPE_INT_RANGE, 48000, G_MAXINT, NULL);
+
+  return result;
+}
+
+static void
+live_switch_push (int rate, GstCaps * caps)
+{
+  GstBuffer *inbuffer;
+  GstCaps *desired;
+  GList *l;
+
+  desired = gst_caps_copy (caps);
+  gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL);
+  gst_pad_set_caps (mysrcpad, desired);
+
+  fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad,
+          GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK);
+
+  /* When the basetransform hits the non-configured case it always
+   * returns a buffer with exactly the same caps as we requested so the actual
+   * renegotiation (if needed) will be done in the _chain*/
+  fail_unless (inbuffer != NULL);
+  GST_DEBUG ("desired: %" GST_PTR_FORMAT ".... got: %" GST_PTR_FORMAT,
+      desired, GST_BUFFER_CAPS (inbuffer));
+  fail_unless (gst_caps_is_equal (desired, GST_BUFFER_CAPS (inbuffer)));
+
+  memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer));
+  GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
+  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+  GST_BUFFER_OFFSET (inbuffer) = 0;
+
+  /* pushing gives away my reference ... */
+  fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+  /* ... but it ends up being collected on the global buffer list */
+  fail_unless_equals_int (g_list_length (buffers), 1);
+
+  for (l = buffers; l; l = l->next) {
+    GstBuffer *buffer = GST_BUFFER (l->data);
+
+    gst_buffer_unref (buffer);
+  }
+
+  g_list_free (buffers);
+  buffers = NULL;
+
+  gst_caps_unref (desired);
+}
+
+void test_live_switch()
+{
+  GstElement *audioresample;
+  GstEvent *newseg;
+  GstCaps *caps;
+  xmlfile = "test_live_switch";
+std_log(LOG_FILENAME_LINE, "Test Started test_live_switch");
+  audioresample = setup_audioresample (4, 48000, 48000, 16, FALSE);
+
+  /* Let the sinkpad act like something that can only handle things of
+   * rate 48000- and can only allocate buffers for that rate, but if someone
+   * tries to get a buffer with a rate higher then 48000 tries to renegotiate
+   * */
+  gst_pad_set_bufferalloc_function (mysinkpad, live_switch_alloc_only_48000);
+  gst_pad_set_getcaps_function (mysinkpad, live_switch_get_sink_caps);
+
+  gst_pad_use_fixed_caps (mysrcpad);
+
+  caps = gst_pad_get_negotiated_caps (mysrcpad);
+  fail_unless (gst_caps_is_fixed (caps));
+
+  fail_unless (gst_element_set_state (audioresample,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+      "could not set to playing");
+
+  newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
+  fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
+
+  /* downstream can provide the requested rate, a buffer alloc will be passed
+   * on */
+  live_switch_push (48000, caps);
+
+  /* Downstream can never accept this rate, buffer alloc isn't passed on */
+  live_switch_push (40000, caps);
+
+  /* Downstream can provide the requested rate but will re-negotiate */
+  live_switch_push (50000, caps);
+
+  cleanup_audioresample (audioresample);
+  gst_caps_unref (caps);
+  
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0);
 }
 
-/*
-audioresample_suite (void)
+
+
+#ifndef GST_DISABLE_PARSE
+
+static GMainLoop *loop;
+static gint messages = 0;
+
+static void
+element_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+  gchar *s;
+
+  s = gst_structure_to_string (gst_message_get_structure (message));
+  GST_DEBUG ("Received message: %s", s);
+  g_free (s);
+
+  messages++;
+}
+
+static void
+eos_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+  GST_DEBUG ("Received eos");
+  g_main_loop_quit (loop);
+}
+
+static void
+test_pipeline (gint width, gboolean fp, gint inrate, gint outrate, gint quality)
+{
+  GstElement *pipeline;
+  GstBus *bus;
+  GError *error = NULL;
+  gchar *pipe_str;
+
+  pipe_str =
+      g_strdup_printf
+      ("audiotestsrc num-buffers=10 ! audioconvert ! audio/x-raw-%s,rate=%d,width=%d,channels=2 ! audioresample quality=%d ! audio/x-raw-%s,rate=%d,width=%d ! identity check-imperfect-timestamp=TRUE ! fakesink",
+      (fp) ? "float" : "int", inrate, width, quality, (fp) ? "float" : "int",
+      outrate, width);
+
+  pipeline = gst_parse_launch (pipe_str, &error);
+  fail_unless (pipeline != NULL, "Error parsing pipeline: %s",
+      error ? error->message : "(invalid error)");
+  g_free (pipe_str);
+
+  bus = gst_element_get_bus (pipeline);
+  fail_if (bus == NULL);
+  gst_bus_add_signal_watch (bus);
+  g_signal_connect (bus, "message::element", (GCallback) element_message_cb,
+      NULL);
+  g_signal_connect (bus, "message::eos", (GCallback) eos_message_cb, NULL);
+
+  gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+  /* run until we receive EOS */
+  loop = g_main_loop_new (NULL, FALSE);
+
+  g_main_loop_run (loop);
+
+  g_main_loop_unref (loop);
+  loop = NULL;
+
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+
+  fail_if (messages > 0, "Received imperfect timestamp messages");
+  gst_object_unref (pipeline);
+}
+
+void test_pipelines()
 {
-test_perfect_stream();
-test_discont_stream();
-test_reuse();
-test_shutdown();
-}*/
+  gint quality;
+  xmlfile = "test_pipelines";
+std_log(LOG_FILENAME_LINE, "Test Started test_pipelines");
+  /* Test qualities 0, 5 and 10 */
+  for (quality = 0; quality < 11; quality += 5) {
+    test_pipeline (8, FALSE, 44100, 48000, quality);
+    test_pipeline (8, FALSE, 48000, 44100, quality);
+
+    test_pipeline (16, FALSE, 44100, 48000, quality);
+    test_pipeline (16, FALSE, 48000, 44100, quality);
+
+    test_pipeline (24, FALSE, 44100, 48000, quality);
+    test_pipeline (24, FALSE, 48000, 44100, quality);
+
+    test_pipeline (32, FALSE, 44100, 48000, quality);
+    test_pipeline (32, FALSE, 48000, 44100, quality);
+
+    test_pipeline (32, TRUE, 44100, 48000, quality);
+    test_pipeline (32, TRUE, 48000, 44100, quality);
+
+    test_pipeline (64, TRUE, 44100, 48000, quality);
+    test_pipeline (64, TRUE, 48000, 44100, quality); 
+  }
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+  create_xml(0);
+}
+
+
+
+void test_preference_passthrough()
+{
+  GstStateChangeReturn ret;
+  GstElement *pipeline, *src;
+  GstStructure *s;
+  GstMessage *msg;
+  GstCaps *caps;
+  GstPad *pad;
+  GstBus *bus;
+  GError *error = NULL;
+  gint rate = 0;
+
+  xmlfile = "test_preference_passthrough";
+std_log(LOG_FILENAME_LINE, "Test Started test_preference_passthrough");
+  pipeline = gst_parse_launch ("audiotestsrc num-buffers=1 name=src ! "
+      "audioresample ! "
+      "audio/x-raw-int,rate=8000,channels=1,width=16,depth=16,signed=(boolean)true,endianness=(int)BYTE_ORDER ! "
+      "fakesink can-activate-pull=0 ", &error);
+  fail_unless (pipeline != NULL, "Error parsing pipeline: %s",
+      error ? error->message : "(invalid error)");
+
+  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+  fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC);
+
+  /* run until we receive EOS */
+  bus = gst_element_get_bus (pipeline);
+  fail_if (bus == NULL);
+  msg = gst_bus_timed_pop_filtered (bus, -1, GST_MESSAGE_EOS);
+  gst_message_unref (msg);
+  gst_object_unref (bus);
+
+  src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
+  fail_unless (src != NULL);
+  pad = gst_element_get_static_pad (src, "src");
+  fail_unless (pad != NULL);
+  caps = gst_pad_get_negotiated_caps (pad);
+  GST_LOG ("negotiated audiotestsrc caps: %" GST_PTR_FORMAT, caps);
+  fail_unless (caps != NULL);
+  s = gst_caps_get_structure (caps, 0);
+  fail_unless (gst_structure_get_int (s, "rate", &rate));
+  /* there's no need to resample, audiotestsrc supports any rate, so make
+   * sure audioresample provided upstream with the right caps to negotiate
+   * this correctly */
+  fail_unless_equals_int (rate, 8000);
+  gst_caps_unref (caps);
+  gst_object_unref (pad);
+  gst_object_unref (src);
+
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+  gst_object_unref (pipeline);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+  create_xml(0);
+}
+
+
+
+#endif
+
+//static Suite *
+//audioresample_suite (void)
+//{
+//  Suite *s = suite_create ("audioresample");
+//  TCase *tc_chain = tcase_create ("general");
+//
+//  suite_add_tcase (s, tc_chain);
+//  tcase_add_test (tc_chain, test_perfect_stream);
+//  tcase_add_test (tc_chain, test_discont_stream);
+//  tcase_add_test (tc_chain, test_reuse);
+//  tcase_add_test (tc_chain, test_shutdown);
+//  tcase_add_test (tc_chain, test_live_switch);
+//
+//#ifndef GST_DISABLE_PARSE
+//  tcase_set_timeout (tc_chain, 360);
+//  tcase_add_test (tc_chain, test_pipelines);
+//  tcase_add_test (tc_chain, test_preference_passthrough);
+//#endif
+//
+//  return s;
+//}
 
 void (*fn[]) (void) = {
 test_perfect_stream,
 test_discont_stream,
 test_reuse,
-test_shutdown
+test_shutdown,
+test_live_switch,
+test_pipelines,
+test_preference_passthrough
 };
 
 char *args[] = {
 "test_perfect_stream",
 "test_discont_stream",
 "test_reuse",
-"test_shutdown"
+"test_shutdown",
+"test_live_switch",
+"test_pipelines",
+"test_preference_passthrough"
 };
 
 GST_CHECK_MAIN (audioresample);
--- a/gst_plugins_base/tsrc/check/elements/audiotestsrc/src/audiotestsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/audiotestsrc/src/audiotestsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gst_plugins_base/tsrc/check/elements/createelementbase/src/createelementbase.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/createelementbase/src/createelementbase.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,24 +1,16 @@
+//createelementbase.c
 /*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
+ *  Copyright © 2005 Nokia Corporation.
+ *  This material, including documentation and any related 
+ *  computer progrs, is protected by copyright controlled by 
+ *  Nokia Corporation. All rights are reserved. Copying, 
+ *  including reproducing, storing, adapting or translating, any 
+ *  or all of this material requires the prior written consent of 
+ *  Nokia Corporation. This material also contains confidential 
+ *  information which may not be disclosed to others without the 
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
 
 
 #ifdef HAVE_CONFIG_H
@@ -35,11 +27,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 #include <gst/check/gstcheck.h>
 #include "libgstreamer_wsd_solution.h" 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/tsrc/check/elements/createelementbasevideo/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+
+
+PRJ_TESTMMPFILES
+
+
+createelementbasevideo.mmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/tsrc/check/elements/createelementbasevideo/group/createelementbasevideo.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+                    
+#include <platform_paths.hrh>                    
+
+TARGET        createelementbasevideo.exe
+TARGETTYPE		EXE
+UID           0 0x0CDE34F4
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../../../../../include/gstreamer
+USERINCLUDE		../../../../../../include/gstreamer/gst
+USERINCLUDE		../../../../../../include/gstreamer/gst/base
+USERINCLUDE		../../../../../../include/gstreamer/gst/controller
+USERINCLUDE		../../../../../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../../../../../include/gstreamer/gst/net
+
+
+USERINCLUDE		../../../../../../gstreamer_core/libs/gst/check
+
+SYSTEMINCLUDE	../../../../../../gstreamer_core/libs
+
+SYSTEMINCLUDE	../../../../../../gstreamer_core/gst
+
+SYSTEMINCLUDE	../../../../../../gst_plugins_base
+
+
+
+USERINCLUDE ../inc
+SOURCEPATH	../src
+
+SOURCE             createelementbasevideo.c
+
+LIBRARY			libgstreamer.lib
+LIBRARY			euser.lib
+LIBRARY 		libc.lib
+LIBRARY 		libpthread.lib
+LIBRARY			libdl.lib
+LIBRARY			libglib.lib
+LIBRARY			libgmodule.lib
+LIBRARY			libgobject.lib
+LIBRARY			libgthread.lib
+LIBRARY			libm.lib
+LIBRARY 		libz.lib
+
+LIBRARY 		libgstnet.lib
+LIBRARY 		libgstbase.lib
+LIBRARY 		libgstcontroller.lib
+LIBRARY 		libgstdataprotocol.lib
+
+STATICLIBRARY  libcrt0.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/tsrc/check/elements/createelementbasevideo/src/createelementbasevideo.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,123 @@
+//createelementbase.c
+/*
+ *  Copyright © 2005 Nokia Corporation.
+ *  This material, including documentation and any related 
+ *  computer progrs, is protected by copyright controlled by 
+ *  Nokia Corporation. All rights are reserved. Copying, 
+ *  including reproducing, storing, adapting or translating, any 
+ *  or all of this material requires the prior written consent of 
+ *  Nokia Corporation. This material also contains confidential 
+ *  information which may not be disclosed to others without the 
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include <gst/gst_global.h>
+#include <unistd.h>
+
+#define LOG_FILE "c:\\logs\\createelementbasevideo_logs.txt" 
+#include "std_log_result.h" 
+#define LOG_FILENAME_LINE __FILE__, __LINE__
+
+void create_xml(int result)
+{
+
+    if(result)
+    {
+        assert_failed = 1;
+    } 
+
+    testResultXml(xmlfile);
+    close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
+}
+#include <gst/check/gstcheck.h>
+#include "libgstreamer_wsd_solution.h" 
+
+#if EMULATOR
+GET_GLOBAL_VAR_FROM_TLS(buffers,gstcheck,GList*)
+#define buffers (*GET_GSTREAMER_WSD_VAR_NAME(buffers,gstcheck,g)())
+#else 
+extern GList *buffers;
+#endif
+
+
+#if EMULATOR
+static GET_GLOBAL_VAR_FROM_TLS(raised_critical,gstcheck,gboolean)
+#define _gst_check_raised_critical (*GET_GSTREAMER_WSD_VAR_NAME(raised_critical,gstcheck,g)())
+#else 
+extern gboolean _gst_check_raised_critical ;
+#endif
+//gboolean _gst_check_raised_warning = FALSE;
+#if EMULATOR
+static GET_GLOBAL_VAR_FROM_TLS(raised_warning,gstcheck,gboolean)
+#define _gst_check_raised_warning (*GET_GSTREAMER_WSD_VAR_NAME(raised_warning,gstcheck,g)())
+#else 
+extern gboolean _gst_check_raised_warning ;
+#endif
+//gboolean _gst_check_expecting_log = FALSE;
+#if EMULATOR
+static GET_GLOBAL_VAR_FROM_TLS(expecting_log,gstcheck,gboolean)
+#define _gst_check_expecting_log (*GET_GSTREAMER_WSD_VAR_NAME(expecting_log,gstcheck,g)())
+#else 
+extern gboolean _gst_check_expecting_log ;
+#endif
+
+//gboolean _gst_check_expecting_log = FALSE;
+#if EMULATOR
+static GET_GLOBAL_VAR_FROM_TLS(threads_running,gstcheck,gboolean)
+#define _gst_check_threads_running (*GET_GSTREAMER_WSD_VAR_NAME(threads_running,gstcheck,g)())
+#else 
+extern gboolean _gst_check_threads_running ;
+#endif
+
+void test_createelementvideo_base()
+{
+  GstElement *videorate,*videoscale,*videotestsrc,*ffmpegcolorspace;
+  
+  // xmlfile = "create_test_element";
+    std_log(LOG_FILENAME_LINE, "Test Started element create base video");
+   
+    videorate       = gst_element_factory_make ("videorate", "videorate");
+    fail_unless (videorate != NULL, "Could not create videorate");
+ 
+    videoscale  = gst_element_factory_make ("videoscale", "videoscale");
+    fail_unless (videoscale != NULL, "Could not create videoscale");
+    
+    videotestsrc = gst_element_factory_make ("videotestsrc", "videotestsrc");
+    fail_unless (videotestsrc  != NULL, "Could not create videotestsrc ");
+    
+    ffmpegcolorspace    = gst_element_factory_make ("ffmpegcolorspace", "ffmpegcolorspace");
+    fail_unless (ffmpegcolorspace != NULL, "Could not create ffmpegcolorspace");
+
+  gst_object_unref (videorate);
+  gst_object_unref (videoscale);
+  gst_object_unref (videotestsrc);
+  gst_object_unref (ffmpegcolorspace);
+  
+   std_log(LOG_FILENAME_LINE, "Test Successful");
+   create_xml(0); 
+}
+
+void (*fn[]) (void) = {
+        test_createelementvideo_base
+};
+
+char *args[] = {
+        "test_createelementvideo_base"
+};
+
+
+
+GST_CHECK_MAIN (createelementbasevideo);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+
+PRJ_TESTMMPFILES
+
+
+ffmpegcolorspace.mmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/group/ffmpegcolorspace.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>                    
+              
+TARGET             ffmpegcolorspace.exe
+TARGETTYPE		exe
+UID           	0 0x0B0F0C1
+
+EPOCHEAPSIZE 0X5000 0x1000000
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+USERINCLUDE	 ../inc
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../../../../../include/gstreamer
+USERINCLUDE		../../../../../../include/gstreamer/gst
+USERINCLUDE		../../../../../../include/gstreamer/gst/base
+USERINCLUDE		../../../../../../include/gstreamer/gst/controller
+USERINCLUDE		../../../../../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../../../../../include/gstreamer/gst/net
+
+
+USERINCLUDE	../../../../../../gstreamer_core/libs/gst/check
+
+SYSTEMINCLUDE	../../../../../../gstreamer_core/libs
+
+SYSTEMINCLUDE	../../../../../../gstreamer_core/gst
+
+SYSTEMINCLUDE	../../../../../../gstreamer_core
+
+SOURCEPATH	../src
+
+
+
+
+
+SOURCE             ffmpegcolorspace.c
+
+LIBRARY			libgstreamer.lib
+LIBRARY			euser.lib
+LIBRARY 		libc.lib
+LIBRARY 		libpthread.lib
+LIBRARY			libdl.lib
+LIBRARY			libglib.lib
+LIBRARY			libgmodule.lib
+LIBRARY			libgobject.lib
+LIBRARY			libgthread.lib
+LIBRARY			libm.lib
+LIBRARY 		libz.lib
+
+LIBRARY 		libgstnet.lib
+LIBRARY 		libgstbase.lib
+LIBRARY 		libgstcontroller.lib
+LIBRARY 		libgstdataprotocol.lib
+STATICLIBRARY  libcrt0.lib
+EPOCHEAPSIZE 0xFFFFFF 0xFFFFFFF
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/tsrc/check/elements/decodebin/ffmpegcolorspace/src/ffmpegcolorspace.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,483 @@
+/* GStreamer
+ *
+ * unit test for ffmpegcolorspace
+ *
+ * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_VALGRIND
+# include <valgrind/valgrind.h>
+#endif
+
+#include <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+#include <gst/gst_global.h>
+
+#include <unistd.h>
+
+#include <gstcheck.h>
+
+#define LOG_FILE "c:\\logs\\ffmpegcolorspace_logs.txt" 
+#include "std_log_result.h" 
+#define LOG_FILENAME_LINE __FILE__, __LINE__
+
+void create_xml(int result)
+{
+
+    if(result)
+    {
+        assert_failed = 1;
+    } 
+
+    testResultXml(xmlfile);
+    close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
+}
+
+typedef struct _RGBFormat
+{
+  const gchar *nick;
+  guint bpp, depth;
+  guint32 red_mask, green_mask, blue_mask, alpha_mask;
+  guint endianness;
+} RGBFormat;
+
+typedef struct _RGBConversion
+{
+  RGBFormat from_fmt;
+  RGBFormat to_fmt;
+  GstCaps *from_caps;
+  GstCaps *to_caps;
+} RGBConversion;
+
+static GstCaps *
+rgb_format_to_caps (RGBFormat * fmt)
+{
+  GstCaps *caps;
+
+  g_assert (fmt != NULL);
+  g_assert (fmt->endianness != 0);
+
+  caps = gst_caps_new_simple ("video/x-raw-rgb",
+      "bpp", G_TYPE_INT, fmt->bpp,
+      "depth", G_TYPE_INT, fmt->depth,
+      "red_mask", G_TYPE_INT, fmt->red_mask,
+      "green_mask", G_TYPE_INT, fmt->green_mask,
+      "blue_mask", G_TYPE_INT, fmt->blue_mask,
+      "width", G_TYPE_INT, 16, "height", G_TYPE_INT, 16,
+      "endianness", G_TYPE_INT, fmt->endianness,
+      "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
+
+  fail_unless (fmt->alpha_mask == 0 || fmt->bpp == 32);
+
+  if (fmt->alpha_mask != 0) {
+    gst_structure_set (gst_caps_get_structure (caps, 0),
+        "alpha_mask", G_TYPE_INT, fmt->alpha_mask, NULL);
+  }
+
+  return caps;
+}
+
+static GList *
+create_rgb_conversions (void)
+{
+  const RGBFormat rgb_formats[] = {
+    {
+        "RGBA", 32, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 0}, {
+        "ARGB", 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, 0}, {
+        "BGRA", 32, 32, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff, 0}, {
+        "ABGR", 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, 0}, {
+        "RGBx", 32, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000, 0}, {
+        "xRGB", 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 0}, {
+        "BGRx", 32, 24, 0x0000ff00, 0x00ff0000, 0xff000000, 0x00000000, 0}, {
+        "xBGR", 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, 0}, {
+        "RGB ", 24, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 0}, {
+        "BGR ", 24, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, 0}, {
+        "RGB565", 16, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000, 0}, {
+        "xRGB1555", 16, 15, 0x00007c00, 0x000003e0, 0x0000001f, 0x0000000, 0}
+  };
+  const struct
+  {
+    guint from_endianness, to_endianness;
+  } end_arr[4] = {
+    {
+    G_LITTLE_ENDIAN, G_LITTLE_ENDIAN}, {
+    G_BIG_ENDIAN, G_LITTLE_ENDIAN}, {
+    G_LITTLE_ENDIAN, G_BIG_ENDIAN}, {
+    G_BIG_ENDIAN, G_BIG_ENDIAN}
+  };
+  GList *conversions = NULL;
+  guint from_fmt, to_fmt;
+
+  for (from_fmt = 0; from_fmt < G_N_ELEMENTS (rgb_formats); ++from_fmt) {
+    for (to_fmt = 0; to_fmt < G_N_ELEMENTS (rgb_formats); ++to_fmt) {
+      guint i;
+
+      for (i = 0; i < 4; ++i) {
+        RGBConversion *conversion;
+
+        conversion = g_new0 (RGBConversion, 1);
+        conversion->from_fmt = rgb_formats[from_fmt];
+        conversion->to_fmt = rgb_formats[to_fmt];
+        conversion->from_fmt.endianness = end_arr[i].from_endianness;
+        conversion->to_fmt.endianness = end_arr[i].to_endianness;
+        conversion->from_caps = rgb_format_to_caps (&conversion->from_fmt);
+        conversion->to_caps = rgb_format_to_caps (&conversion->to_fmt);
+        conversions = g_list_prepend (conversions, conversion);
+      }
+    }
+  }
+
+  return g_list_reverse (conversions);
+}
+
+static void
+rgb_conversion_free (RGBConversion * conv)
+{
+  gst_caps_unref (conv->from_caps);
+  gst_caps_unref (conv->to_caps);
+  memset (conv, 0x99, sizeof (RGBConversion));
+  g_free (conv);
+}
+
+static guint32
+right_shift_colour (guint32 mask, guint32 pixel)
+{
+  if (mask == 0)
+    return 0;
+
+  pixel = pixel & mask;
+  while ((mask & 0x01) == 0) {
+    mask = mask >> 1;
+    pixel = pixel >> 1;
+  }
+
+  return pixel;
+}
+
+static guint8
+fix_expected_colour (guint32 col_mask, guint8 col_expected)
+{
+  guint32 mask;
+  gint last = g_bit_nth_msf (col_mask, -1);
+  gint first = g_bit_nth_lsf (col_mask, -1);
+
+  mask = 1 << (last - first + 1);
+  mask -= 1;
+
+  g_assert (col_expected == 0x00 || col_expected == 0xff);
+
+  /* this only works because we only check for all-bits-set or no-bits-set */
+  return col_expected & mask;
+}
+
+static void
+check_rgb_buf (const guint8 * pixels, guint32 r_mask, guint32 g_mask,
+    guint32 b_mask, guint32 a_mask, guint8 r_expected, guint8 g_expected,
+    guint8 b_expected, guint endianness, guint bpp, guint depth)
+{
+  guint32 pixel, red, green, blue, alpha;
+
+  switch (bpp) {
+    case 32:{
+      if (endianness == G_LITTLE_ENDIAN)
+        pixel = GST_READ_UINT32_LE (pixels);
+      else
+        pixel = GST_READ_UINT32_BE (pixels);
+      break;
+    }
+    case 24:{
+      if (endianness == G_BIG_ENDIAN) {
+        pixel = (GST_READ_UINT8 (pixels) << 16) |
+            (GST_READ_UINT8 (pixels + 1) << 8) |
+            (GST_READ_UINT8 (pixels + 2) << 0);
+      } else {
+        pixel = (GST_READ_UINT8 (pixels + 2) << 16) |
+            (GST_READ_UINT8 (pixels + 1) << 8) |
+            (GST_READ_UINT8 (pixels + 0) << 0);
+      }
+      break;
+    }
+    case 16:{
+      if (endianness == G_LITTLE_ENDIAN)
+        pixel = GST_READ_UINT16_LE (pixels);
+      else
+        pixel = GST_READ_UINT16_BE (pixels);
+      break;
+    }
+    default:
+      g_return_if_reached ();
+  }
+
+  red = right_shift_colour (r_mask, pixel);
+  green = right_shift_colour (g_mask, pixel);
+  blue = right_shift_colour (b_mask, pixel);
+  alpha = right_shift_colour (a_mask, pixel);
+
+  /* can't enable this by default, valgrind will complain about accessing
+   * uninitialised memory for the depth=24,bpp=32 formats ... */
+  /* GST_LOG ("pixels: 0x%02x 0x%02x 0x%02x 0x%02x => pixel = 0x%08x",
+     pixels[0], (guint) pixels[1], pixels[2], pixels[3], pixel); */
+
+  /* fix up the mask (for rgb15/16) */
+  if (bpp == 16) {
+    r_expected = fix_expected_colour (r_mask, r_expected);
+    g_expected = fix_expected_colour (g_mask, g_expected);
+    b_expected = fix_expected_colour (b_mask, b_expected);
+  }
+
+  fail_unless (red == r_expected, "RED: expected 0x%02x, found 0x%02x    "
+      "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x    Pixel: 0x%08x", r_expected, red,
+      pixels[0], pixels[1], pixels[2], pixels[3], pixel);
+  fail_unless (green == g_expected, "GREEN: expected 0x%02x, found 0x%02x    "
+      "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x    Pixel: 0x%08x", g_expected, green,
+      pixels[0], pixels[1], pixels[2], pixels[3], pixel);
+  fail_unless (blue == b_expected, "BLUE: expected 0x%02x, found 0x%02x    "
+      "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x    Pixel: 0x%08x", b_expected, blue,
+      pixels[0], pixels[1], pixels[2], pixels[3], pixel);
+
+//  FIXME: fix alpha check
+//  fail_unless (a_mask == 0 || alpha != 0);      /* better than nothing */
+}
+
+static void
+got_buf_cb (GstElement * sink, GstBuffer * new_buf, GstPad * pad,
+    GstBuffer ** p_old_buf)
+{
+  gst_buffer_replace (p_old_buf, new_buf);
+}
+
+/* Note: lots of this code here is also in the videotestsrc.c unit test */
+void  test_rgb_to_rgb()
+{
+  const struct
+  {
+    const gchar *pattern_name;
+    gint pattern_enum;
+    guint8 r_expected;
+    guint8 g_expected;
+    guint8 b_expected;
+  } test_patterns[] = {
+    {
+    "white", 3, 0xff, 0xff, 0xff}, {
+    "red", 4, 0xff, 0x00, 0x00}, {
+    "green", 5, 0x00, 0xff, 0x00}, {
+    "blue", 6, 0x00, 0x00, 0xff}, {
+    "black", 2, 0x00, 0x00, 0x00}
+  };
+  GstElement *pipeline, *src, *filter1, *csp, *filter2, *sink;
+  const GstCaps *template_caps;
+  GstBuffer *buf = NULL;
+  GstPad *srcpad;
+  GList *conversions, *l;
+  gint p;
+
+  /* test check function */
+  fail_unless (right_shift_colour (0x00ff0000, 0x11223344) == 0x22);
+
+  pipeline = gst_pipeline_new ("pipeline");
+  src = gst_check_setup_element ("videotestsrc");
+  filter1 = gst_check_setup_element ("capsfilter");
+  csp = gst_check_setup_element ("ffmpegcolorspace");
+  filter2 = gst_element_factory_make ("capsfilter", "to_filter");
+  sink = gst_check_setup_element ("fakesink");
+
+  gst_bin_add_many (GST_BIN (pipeline), src, filter1, csp, filter2, sink, NULL);
+
+  fail_unless (gst_element_link (src, filter1));
+  fail_unless (gst_element_link (filter1, csp));
+  fail_unless (gst_element_link (csp, filter2));
+  fail_unless (gst_element_link (filter2, sink));
+
+  srcpad = gst_element_get_pad (src, "src");
+  template_caps = gst_pad_get_pad_template_caps (srcpad);
+  gst_object_unref (srcpad);
+
+  g_object_set (sink, "signal-handoffs", TRUE, NULL);
+  g_signal_connect (sink, "preroll-handoff", G_CALLBACK (got_buf_cb), &buf);
+
+  GST_LOG ("videotestsrc src template caps: %" GST_PTR_FORMAT, template_caps);
+
+  conversions = create_rgb_conversions ();
+
+  for (l = conversions; l != NULL; l = l->next) {
+    RGBConversion *conv = (RGBConversion *) l->data;
+
+    /* does videotestsrc support the from_caps? */
+    if (!gst_caps_is_subset (conv->from_caps, template_caps)) {
+      GST_DEBUG ("videotestsrc doesn't support from_caps %" GST_PTR_FORMAT,
+          conv->from_caps);
+      continue;
+    }
+
+    /* caps are supported, let's run some tests then ... */
+    for (p = 0; p < G_N_ELEMENTS (test_patterns); ++p) {
+      GstStateChangeReturn state_ret;
+      RGBFormat *from = &conv->from_fmt;
+      RGBFormat *to = &conv->to_fmt;
+
+      /* trick compiler into thinking from is used, might throw warning
+       * otherwise if the debugging system is disabled */
+      fail_unless (from != NULL);
+
+      gst_element_set_state (pipeline, GST_STATE_NULL);
+
+      g_object_set (src, "pattern", test_patterns[p].pattern_enum, NULL);
+
+      GST_INFO ("%5s %u/%u %08x %08x %08x %08x %u => "
+          "%5s %u/%u %08x %08x %08x %08x %u, pattern=%s",
+          from->nick, from->bpp, from->depth, from->red_mask,
+          from->green_mask, from->blue_mask, from->alpha_mask,
+          from->endianness, to->nick, to->bpp, to->depth, to->red_mask,
+          to->green_mask, to->blue_mask, to->alpha_mask, to->endianness,
+          test_patterns[p].pattern_name);
+
+      /* now get videotestsrc to produce a buffer with the given caps */
+      g_object_set (filter1, "caps", conv->from_caps, NULL);
+
+      /* ... and force ffmpegcolorspace to convert to our target caps */
+      g_object_set (filter2, "caps", conv->to_caps, NULL);
+
+      state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+      if (state_ret == GST_STATE_CHANGE_FAILURE) {
+        GstMessage *msg;
+        GError *err = NULL;
+
+        msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_ERROR, 0);
+        fail_if (msg == NULL, "expected ERROR message on the bus");
+        fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
+        gst_message_parse_error (msg, &err, NULL);
+        fail_unless (err != NULL);
+        if (msg->src == GST_OBJECT_CAST (src) &&
+            err->code == GST_STREAM_ERROR_FORMAT) {
+          GST_DEBUG ("ffmpegcolorspace does not support this conversion");
+          gst_message_unref (msg);
+          g_error_free (err);
+          continue;
+        }
+        fail_unless (state_ret != GST_STATE_CHANGE_FAILURE,
+            "pipeline _set_state() to PAUSED failed: %s", err->message);
+      }
+
+      state_ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
+     fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS,
+          "pipeline failed going to PAUSED state");
+
+      state_ret = gst_element_set_state (pipeline, GST_STATE_NULL);
+     fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
+
+      fail_unless (buf != NULL);
+
+      /* check buffer caps */
+      {
+        GstStructure *s;
+        gint v;
+
+        fail_unless (GST_BUFFER_CAPS (buf) != NULL);
+        s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
+        fail_unless (gst_structure_get_int (s, "bpp", &v));
+        fail_unless_equals_int (v, to->bpp);
+        fail_unless (gst_structure_get_int (s, "depth", &v));
+        fail_unless_equals_int (v, to->depth);
+        fail_unless (gst_structure_get_int (s, "red_mask", &v));
+        fail_unless_equals_int (v, to->red_mask);
+        fail_unless (gst_structure_get_int (s, "green_mask", &v));
+        fail_unless_equals_int (v, to->green_mask);
+        fail_unless (gst_structure_get_int (s, "blue_mask", &v));
+        fail_unless_equals_int (v, to->blue_mask);
+        /* there mustn't be an alpha_mask if there's no alpha component */
+        if (to->depth == 32) {
+          fail_unless (gst_structure_get_int (s, "alpha_mask", &v));
+          fail_unless_equals_int (v, to->alpha_mask);
+        } else {
+          fail_unless (gst_structure_get_value (s, "alpha_mask") == NULL);
+        }
+      }
+
+      /* now check the top-left pixel */
+      check_rgb_buf (GST_BUFFER_DATA (buf), to->red_mask,
+          to->green_mask, to->blue_mask, to->alpha_mask,
+          test_patterns[p].r_expected, test_patterns[p].g_expected,
+          test_patterns[p].b_expected, to->endianness, to->bpp, to->depth);
+
+      gst_buffer_unref (buf);
+      buf = NULL;
+    }
+  }
+
+  g_list_foreach (conversions, (GFunc) rgb_conversion_free, NULL);
+  g_list_free (conversions);
+
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+  gst_object_unref (pipeline);
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+  create_xml(0);
+}
+
+//GST_END_TEST;
+
+/*static Suite *
+ffmpegcolorspace_suite (void)
+{
+  Suite *s = suite_create ("ffmpegcolorspace");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+
+#ifdef HAVE_VALGRIND
+  if (RUNNING_ON_VALGRIND) {
+    otherwise valgrind errors out when liboil probes CPU extensions
+     during which it causes SIGILLs etc. to be fired 
+    g_setenv ("OIL_CPU_FLAGS", "0", 0);
+    test_rgb_formats takes a bit longer, so increase timeout 
+    tcase_set_timeout (tc_chain, 10 * 60);
+  }
+#endif
+
+  FIXME: add tests for YUV <=> YUV and YUV <=> RGB 
+  tcase_add_test (tc_chain, test_rgb_to_rgb);
+
+  return s;
+}*/
+void (*fn[]) (void) = {
+        test_rgb_to_rgb
+
+};
+
+char *args[] = {
+        "test_rgb_to_rgb"
+
+};
+/*void main()
+    {
+    gst_init (NULL, NULL);
+    test_rgb_to_rgb();
+ 
+    }*/
+GST_CHECK_MAIN (ffmpegcolorspace);
--- a/gst_plugins_base/tsrc/check/elements/decodebin/src/decodebin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/decodebin/src/decodebin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -37,11 +37,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #if EMULATOR
@@ -313,11 +322,26 @@
 */
 //GST_CHECK_MAIN (decodebin);
 
-int main (int argc, char **argv)
-{
-//gst_init(&argc, &argv);                
-gst_check_init (NULL, NULL); 
-test_text_plain_streams();
-test_reuse_without_decoders();
+//int main (int argc, char **argv)
+//{
+////gst_init(&argc, &argv);                
+//gst_check_init (NULL, NULL); 
+//test_text_plain_streams();
+//test_reuse_without_decoders();
+//
+//}
+
 
-}
+#if 1
+void (*fn[2]) (void) = {
+        test_text_plain_streams,
+        test_text_plain_streams
+};
+
+char *args[] = {
+        "test_text_plain_streams",
+        "test_text_plain_streams"
+};
+
+GST_CHECK_MAIN (filesrc);
+#endif
--- a/gst_plugins_base/tsrc/check/elements/ffmpegcolorspace/src/ffmpegcolorspace.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/ffmpegcolorspace/src/ffmpegcolorspace.c	Fri Apr 16 15:15:52 2010 +0300
@@ -44,12 +44,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 typedef struct _RGBFormat
 {
   const gchar *nick;
--- a/gst_plugins_base/tsrc/check/elements/gdpdepay/src/gdpdepay.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/gdpdepay/src/gdpdepay.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,11 +31,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
@@ -428,6 +437,7 @@
   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
   buffers = g_list_remove (buffers, outbuffer);
   ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+  sleep(1);
   fail_unless (GST_BUFFER_FLAG_IS_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS));
 
   padcaps = gst_pad_get_negotiated_caps (myshsinkpad);
--- a/gst_plugins_base/tsrc/check/elements/multifdsink/src/multifdsink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/multifdsink/src/multifdsink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -34,11 +34,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/check/gstcheck.h>
--- a/gst_plugins_base/tsrc/check/elements/playbin/src/playbin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/playbin/src/playbin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,11 +35,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #ifndef GST_DISABLE_REGISTRY
--- a/gst_plugins_base/tsrc/check/elements/subparse/src/subparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/subparse/src/subparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -49,11 +49,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
--- a/gst_plugins_base/tsrc/check/elements/videorate/src/videorate.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/videorate/src/videorate.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,11 +35,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 #include <gst/check/gstcheck.h>
 #include "libgstreamer_wsd_solution.h" 
--- a/gst_plugins_base/tsrc/check/elements/volume/src/volume.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/elements/volume/src/volume.c	Fri Apr 16 15:15:52 2010 +0300
@@ -51,11 +51,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #define VOLUME_CAPS_TEMPLATE_STRING     \
@@ -1482,8 +1491,8 @@
   
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
-  gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (volume), TRUE);
+  g_object_set (G_OBJECT (volume), "volume", 1.0, NULL);
+  
   fail_unless (gst_element_set_state (volume,
           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
       "could not set to playing");
@@ -1554,6 +1563,59 @@
   create_xml(0);
 }
 
+void test_controller_processing()
+{
+  GstInterpolationControlSource *csource;
+  GstController *c;
+  GstElement *volume;
+  GstBuffer *inbuffer, *outbuffer;
+  GstCaps *caps;
+  gint16 in[2] = { 16384, -256 };
+  gint16 *res;
+
+  std_log(LOG_FILENAME_LINE, "Test Started test_controller_processing");
+  volume = setup_volume ();
+
+  c = gst_controller_new (G_OBJECT (volume), "volume", NULL);
+
+  fail_unless (GST_IS_CONTROLLER (c));
+
+  csource = gst_interpolation_control_source_new ();
+  gst_interpolation_control_source_set_interpolation_mode (csource,
+      GST_INTERPOLATE_CUBIC);
+  gst_controller_set_control_source (c, "volume", GST_CONTROL_SOURCE (csource));
+  g_object_unref (csource);
+
+  fail_unless (gst_element_set_state (volume,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+      "could not set to playing");
+
+  inbuffer = gst_buffer_new_and_alloc (4);
+  memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
+  caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
+  gst_buffer_set_caps (inbuffer, caps);
+  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+  gst_caps_unref (caps);
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+  /* pushing gives away my reference ... */
+  fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+  /* ... but it ends up being collected on the global buffer list */
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+  fail_unless_equals_int (g_list_length (buffers), 1);
+  fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
+  fail_unless (inbuffer == outbuffer);
+  res = (gint16 *) GST_BUFFER_DATA (outbuffer);
+  GST_INFO ("expected %+5d %+5d  real %+5d %+5d", in[0], in[1], res[0], res[1]);
+  fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
+
+  g_object_unref (c);
+
+  cleanup_volume (volume);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+  create_xml(0);
+}
 
 
 //static Suite *
@@ -1594,7 +1656,7 @@
 //  return s;
 //}
 
-void (*fn[27]) (void) = {
+void (*fn[]) (void) = {
         test_unity_s8,
         test_half_s8,
         test_double_s8,
@@ -1621,7 +1683,8 @@
         test_mute_f64,
         test_wrong_caps,
         test_passthrough,
-        test_controller_usability
+        test_controller_usability,
+        test_controller_processing
 };
 
 char *args[] = {
@@ -1651,7 +1714,8 @@
         "test_mute_f64",
         "test_wrong_caps",
         "test_passthrough",
-        "test_controller_usability"
+        "test_controller_usability",
+        "test_controller_processing"    
 };
 
 GST_CHECK_MAIN (volume)
--- a/gst_plugins_base/tsrc/check/generic/clock-selection/src/clock-selection.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/generic/clock-selection/src/clock-selection.c	Fri Apr 16 15:15:52 2010 +0300
@@ -34,11 +34,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_add()
--- a/gst_plugins_base/tsrc/check/generic/states/src/states.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/generic/states/src/states.c	Fri Apr 16 15:15:52 2010 +0300
@@ -45,11 +45,20 @@
 int fd_new;
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gst_plugins_base/tsrc/check/gst/typefindfunctions/src/typefindfunctions.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/gst/typefindfunctions/src/typefindfunctions.c	Fri Apr 16 15:15:52 2010 +0300
@@ -48,11 +48,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_quicktime_mpeg4video()
--- a/gst_plugins_base/tsrc/check/libs/fft/src/fft.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/fft/src/fft.c	Fri Apr 16 15:15:52 2010 +0300
@@ -42,11 +42,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_next_fast_length()
--- a/gst_plugins_base/tsrc/check/libs/netbuffer/src/netbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/netbuffer/src/netbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -38,11 +38,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -78,7 +87,7 @@
   GST_BUFFER_FLAG_SET (netbuf, GST_BUFFER_FLAG_DISCONT);
   GST_BUFFER_FLAG_SET (netbuf, GST_BUFFER_FLAG_READONLY);
 
-  copy = (GstNetBuffer *) gst_buffer_copy (netbuf);
+  copy = (GstNetBuffer *) gst_buffer_copy ( GST_BUFFER_CAST (netbuf));
   fail_unless (copy != NULL, "failed to copy net buffer");
   fail_unless (GST_IS_NETBUFFER (copy), "copied buffer is not a GstNetBuffer!");
 
@@ -102,8 +111,8 @@
   fail_unless (port == ipv6_port,
       "Copied buffer has wrong IPv6 destination port");
 
-  gst_buffer_unref (netbuf);
-  gst_buffer_unref (copy);
+  gst_buffer_unref ( GST_BUFFER_CAST (netbuf));
+  gst_buffer_unref ( GST_BUFFER_CAST (copy));
 
     std_log(LOG_FILENAME_LINE, "Test Successful");
     create_xml(0);
--- a/gst_plugins_base/tsrc/check/libs/pbutils/src/pbutils.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/pbutils/src/pbutils.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,11 +31,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/check/gstcheck.h>
--- a/gst_plugins_base/tsrc/check/libs/rtp/src/rtp.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/rtp/src/rtp.c	Fri Apr 16 15:15:52 2010 +0300
@@ -28,23 +28,33 @@
 
 
 
-#define LOG_FILE "c:\\logs\\gstpad_logs.txt" 
+#define LOG_FILE "c:\\logs\\gstrtp_logs.txt" 
 #include "std_log_result.h" 
 #define LOG_FILENAME_LINE __FILE__, __LINE__
 
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
 
 #include <gst/rtp/gstrtpbuffer.h>
+#include <gst/rtp/gstrtcpbuffer.h>
 #include <string.h>
 
 #if EMULATOR
@@ -55,6 +65,13 @@
 #endif
 
 #if EMULATOR
+static GET_GLOBAL_VAR_FROM_TLS(raised_warning,gstcheck,gboolean)
+#define _gst_check_raised_warning (*GET_GSTREAMER_WSD_VAR_NAME(raised_warning,gstcheck,g)())
+#else 
+extern gboolean _gst_check_raised_warning;
+#endif
+
+#if EMULATOR
 static GET_GLOBAL_VAR_FROM_TLS(expecting_log,gstcheck,gboolean)
 #define _gst_check_expecting_log (*GET_GSTREAMER_WSD_VAR_NAME(expecting_log,gstcheck,g)())
 #else 
@@ -187,8 +204,8 @@
   data = GST_BUFFER_DATA (buf);
 
   /* should be impossible to set the extension data */
-  fail_unless (gst_rtp_buffer_set_extension_data (buf, 0, 4) == FALSE);
-  fail_unless (gst_rtp_buffer_get_extension (buf) == TRUE);
+  ASSERT_WARNING (fail_unless (gst_rtp_buffer_set_extension_data (buf, 0, 4) == FALSE));
+  fail_unless (gst_rtp_buffer_get_extension (buf) == FALSE);
 
   /* should be possible to set the extension data */
   fail_unless (gst_rtp_buffer_set_extension_data (buf, 270, 0) == TRUE);
@@ -217,27 +234,301 @@
       create_xml(0);
 }
 
+void test_rtp_seqnum_compare()
+{
+    xmlfile = "test_rtp_seqnum_compare";
+    std_log(LOG_FILENAME_LINE, "Test Started test_rtp_seqnum_compare");
+    
+#define ASSERT_COMP(a,b,c) fail_unless (gst_rtp_buffer_compare_seqnum ((guint16)a,(guint16)b) == c);
+  ASSERT_COMP (0xfffe, 0xfffd, -1);
+  ASSERT_COMP (0xffff, 0xfffe, -1);
+  ASSERT_COMP (0x0000, 0xffff, -1);
+  ASSERT_COMP (0x0001, 0x0000, -1);
+  ASSERT_COMP (0x0002, 0x0001, -1);
+
+  ASSERT_COMP (0xffff, 0xfffd, -2);
+  ASSERT_COMP (0x0000, 0xfffd, -3);
+  ASSERT_COMP (0x0001, 0xfffd, -4);
+  ASSERT_COMP (0x0002, 0xfffd, -5);
+
+  ASSERT_COMP (0x7ffe, 0x7ffd, -1);
+  ASSERT_COMP (0x7fff, 0x7ffe, -1);
+  ASSERT_COMP (0x8000, 0x7fff, -1);
+  ASSERT_COMP (0x8001, 0x8000, -1);
+  ASSERT_COMP (0x8002, 0x8001, -1);
+
+  ASSERT_COMP (0x7fff, 0x7ffd, -2);
+  ASSERT_COMP (0x8000, 0x7ffd, -3);
+  ASSERT_COMP (0x8001, 0x7ffd, -4);
+  ASSERT_COMP (0x8002, 0x7ffd, -5);
+
+  ASSERT_COMP (0x7ffd, 0xffff, -0x7ffe);
+  ASSERT_COMP (0x7ffe, 0x0000, -0x7ffe);
+  ASSERT_COMP (0x7fff, 0x0001, -0x7ffe);
+  ASSERT_COMP (0x7fff, 0x0000, -0x7fff);
+  ASSERT_COMP (0x8000, 0x0001, -0x7fff);
+  ASSERT_COMP (0x8001, 0x0002, -0x7fff);
+
+  ASSERT_COMP (0xfffd, 0x7ffe, -0x7fff);
+  ASSERT_COMP (0xfffe, 0x7fff, -0x7fff);
+  ASSERT_COMP (0xffff, 0x8000, -0x7fff);
+  ASSERT_COMP (0x0000, 0x8001, -0x7fff);
+  ASSERT_COMP (0x0001, 0x8002, -0x7fff);
+
+  ASSERT_COMP (0xfffe, 0x7ffe, -0x8000);
+  ASSERT_COMP (0xffff, 0x7fff, -0x8000);
+  ASSERT_COMP (0x0000, 0x8000, -0x8000);
+  ASSERT_COMP (0x0001, 0x8001, -0x8000);
+
+  ASSERT_COMP (0x7ffe, 0xfffe, -0x8000);
+  ASSERT_COMP (0x7fff, 0xffff, -0x8000);
+  ASSERT_COMP (0x8000, 0x0000, -0x8000);
+  ASSERT_COMP (0x8001, 0x0001, -0x8000);
+
+  ASSERT_COMP (0x0001, 0x0002, 1);
+  ASSERT_COMP (0x0000, 0x0001, 1);
+  ASSERT_COMP (0xffff, 0x0000, 1);
+  ASSERT_COMP (0xfffe, 0xffff, 1);
+  ASSERT_COMP (0xfffd, 0xfffe, 1);
+
+  ASSERT_COMP (0x0000, 0x0002, 2);
+  ASSERT_COMP (0xffff, 0x0002, 3);
+  ASSERT_COMP (0xfffe, 0x0002, 4);
+  ASSERT_COMP (0xfffd, 0x0002, 5);
+
+  ASSERT_COMP (0x8001, 0x8002, 1);
+  ASSERT_COMP (0x8000, 0x8001, 1);
+  ASSERT_COMP (0x7fff, 0x8000, 1);
+  ASSERT_COMP (0x7ffe, 0x7fff, 1);
+  ASSERT_COMP (0x7ffd, 0x7ffe, 1);
+
+  ASSERT_COMP (0x8000, 0x8002, 2);
+  ASSERT_COMP (0x7fff, 0x8002, 3);
+  ASSERT_COMP (0x7ffe, 0x8002, 4);
+  ASSERT_COMP (0x7ffd, 0x8002, 5);
+
+  ASSERT_COMP (0xfffe, 0x7ffd, 0x7fff);
+  ASSERT_COMP (0xffff, 0x7ffe, 0x7fff);
+  ASSERT_COMP (0x0000, 0x7fff, 0x7fff);
+  ASSERT_COMP (0x0001, 0x8000, 0x7fff);
+  ASSERT_COMP (0x0002, 0x8001, 0x7fff);
+
+  ASSERT_COMP (0x7ffe, 0xfffd, 0x7fff);
+  ASSERT_COMP (0x7fff, 0xfffe, 0x7fff);
+  ASSERT_COMP (0x8000, 0xffff, 0x7fff);
+  ASSERT_COMP (0x8001, 0x0000, 0x7fff);
+  ASSERT_COMP (0x8002, 0x0001, 0x7fff);
+#undef ASSERT_COMP
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
+}
 
 
-void
-rtp_suite (void)
+void test_rtcp_buffer()
 {
-test_rtp_buffer();
-test_rtp_buffer_set_extension_data();
+  GstBuffer *buf;
+  GstRTCPPacket packet;
+  guint8 *data;
+  
+  xmlfile = "test_rtcp_buffer";
+  std_log(LOG_FILENAME_LINE, "Test Started test_rtcp_buffer");
+
+  buf = gst_rtcp_buffer_new (1400);
+  fail_unless (buf != NULL);
+  fail_unless_equals_int (GST_BUFFER_SIZE (buf), 1400);
+  data = GST_BUFFER_DATA (buf);
+
+  fail_unless (gst_rtcp_buffer_get_first_packet (buf, &packet) == FALSE);
+  fail_unless (gst_rtcp_buffer_get_packet_count (buf) == 0);
+  fail_unless (gst_rtcp_buffer_validate (buf) == FALSE);
+
+  /* add an SR packet */
+  fail_unless (gst_rtcp_buffer_add_packet (buf, GST_RTCP_TYPE_SR,
+          &packet) == TRUE);
+
+  fail_unless (gst_rtcp_packet_get_padding (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_count (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SR);
+  fail_unless (gst_rtcp_packet_get_length (&packet) == 6);
+
+  gst_rtcp_packet_sr_set_sender_info (&packet, 0x44556677,
+      G_GUINT64_CONSTANT (1), 0x11111111, 101, 123456);
+  {
+    guint32 ssrc;
+    guint64 ntptime;
+    guint32 rtptime;
+    guint32 packet_count;
+    guint32 octet_count;
+
+    gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, &rtptime,
+        &packet_count, &octet_count);
+
+    fail_unless (ssrc == 0x44556677);
+    fail_unless (ntptime == G_GUINT64_CONSTANT (1));
+    fail_unless (rtptime == 0x11111111);
+    fail_unless (packet_count == 101);
+    fail_unless (octet_count == 123456);
+  }
+
+  /* go to first packet, this should be the packet we just added */
+  fail_unless (gst_rtcp_buffer_get_first_packet (buf, &packet) == TRUE);
+
+  fail_unless (gst_rtcp_packet_get_padding (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_count (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SR);
+  fail_unless (gst_rtcp_packet_get_length (&packet) == 6);
+
+  fail_unless (gst_rtcp_packet_move_to_next (&packet) == FALSE);
+
+  /* add some SDES */
+  fail_unless (gst_rtcp_buffer_add_packet (buf, GST_RTCP_TYPE_SDES,
+          &packet) == TRUE);
+  fail_unless (gst_rtcp_packet_sdes_add_item (&packet, 0xff658743) == TRUE);
+  fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
+          sizeof ("test@foo.bar"), (guint8 *) "test@foo.bar") == TRUE);
+
+  /* add some BYE */
+  fail_unless (gst_rtcp_buffer_add_packet (buf, GST_RTCP_TYPE_BYE,
+          &packet) == TRUE);
+  fail_unless (gst_rtcp_packet_bye_add_ssrc (&packet, 0x5613212f) == TRUE);
+  fail_unless (gst_rtcp_packet_bye_add_ssrc (&packet, 0x00112233) == TRUE);
+  fail_unless (gst_rtcp_packet_bye_get_ssrc_count (&packet) == 2);
+
+  fail_unless (gst_rtcp_packet_get_padding (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_count (&packet) == 2);
+  fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_BYE);
+  fail_unless (gst_rtcp_packet_get_length (&packet) == 2);
+
+  /* move to SDES */
+  fail_unless (gst_rtcp_buffer_get_first_packet (buf, &packet) == TRUE);
+  fail_unless (gst_rtcp_packet_move_to_next (&packet) == TRUE);
+
+  fail_unless (gst_rtcp_packet_get_padding (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_count (&packet) == 1);
+  fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SDES);
+  fail_unless (gst_rtcp_packet_get_length (&packet) == 5);
+
+  /* remove the SDES */
+  fail_unless (gst_rtcp_packet_remove (&packet) == TRUE);
+
+  /* we are now at the BYE packet */
+  fail_unless (gst_rtcp_packet_get_padding (&packet) == 0);
+  fail_unless (gst_rtcp_packet_get_count (&packet) == 2);
+  fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_BYE);
+  fail_unless (gst_rtcp_packet_get_length (&packet) == 2);
+
+  /* close and validate */
+  gst_rtcp_buffer_end (buf);
+  fail_unless (gst_rtcp_buffer_validate (buf) == TRUE);
+  gst_buffer_unref (buf);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
 }
 
+void test_rtp_buffer_validate_corrupt()
+{
+  GstBuffer *buf;
+  guint8 corrupt_rtp_packet[58] = {
+    0x90, 0x7a, 0xbf, 0x28, 0x3a, 0x8a, 0x0a, 0xf4, 0x69, 0x6b, 0x76, 0xc0,
+    0x21, 0xe0, 0xe0, 0x60, 0x81, 0x10, 0x84, 0x30, 0x21, 0x52, 0x06, 0xc2,
+    0xb8, 0x30, 0x10, 0x4c, 0x08, 0x62, 0x67, 0xc2, 0x6e, 0x1a, 0x53, 0x3f,
+    0xaf, 0xd6, 0x1b, 0x29, 0x40, 0xe0, 0xa5, 0x83, 0x01, 0x4b, 0x04, 0x02,
+    0xb0, 0x97, 0x63, 0x08, 0x10, 0x4b, 0x43, 0x85, 0x37, 0x2c
+  };
+
+  xmlfile = "test_rtp_buffer_validate_corrupt";
+  std_log(LOG_FILENAME_LINE, "Test Started test_rtp_buffer_validate_corrupt");
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = corrupt_rtp_packet;
+  GST_BUFFER_SIZE (buf) = sizeof (corrupt_rtp_packet);
+  fail_if (gst_rtp_buffer_validate (buf));
+  gst_buffer_unref (buf);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
+}
+
+
+void test_rtp_buffer_list()
+{
+  GstBuffer *rtp_header;
+  GstBuffer *rtp_payload;
+  GstBufferList *list = NULL;
+  GstBufferListIterator *it;
+  guint i;
+
+  xmlfile = "test_rtp_buffer_list";
+  std_log(LOG_FILENAME_LINE, "Test Started test_rtp_buffer_list");
+  
+  list = gst_buffer_list_new ();
+  it = gst_buffer_list_iterate (list);
+
+  /* Creating a list of two RTP packages */
+
+  /* Create first group to hold the rtp header and the payload */
+  gst_buffer_list_iterator_add_group (it);
+  rtp_header = gst_rtp_buffer_new_allocate (0, 0, 0);
+  gst_buffer_list_iterator_add (it, rtp_header);
+  rtp_payload = gst_buffer_new_and_alloc (42);
+  gst_buffer_list_iterator_add (it, rtp_payload);
+
+  /* Create second group to hold an rtp header and a payload */
+  gst_buffer_list_iterator_add_group (it);
+  rtp_header = gst_rtp_buffer_new_allocate (0, 0, 0);
+  gst_buffer_list_iterator_add (it, rtp_header);
+  rtp_payload = gst_buffer_new_and_alloc (42);
+  gst_buffer_list_iterator_add (it, rtp_payload);
+
+  gst_buffer_list_iterator_free (it);
+
+  /* Test SEQ number */
+  i = gst_rtp_buffer_list_set_seq (list, 1024);
+  fail_if (1026 != i);
+  fail_if (!gst_rtp_buffer_list_validate (list));
+
+  /* Timestamp */
+  gst_rtp_buffer_list_set_timestamp (list, 432191);
+  fail_unless_equals_int (gst_rtp_buffer_list_get_timestamp (list), 432191);
+
+  /* SSRC */
+  gst_rtp_buffer_list_set_ssrc (list, 0xf04043C2);
+  fail_unless_equals_int (gst_rtp_buffer_list_get_ssrc (list),
+      (gint) 0xf04043c2);
+
+  /* Payload type */
+  gst_rtp_buffer_list_set_payload_type (list, 127);
+  fail_unless_equals_int (gst_rtp_buffer_list_get_payload_type (list), 127);
+
+  gst_buffer_list_unref (list);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
+}
+
+
 void (*fn[]) (void) = {
 test_rtp_buffer,
-test_rtp_buffer_set_extension_data
+test_rtp_buffer_set_extension_data,
+test_rtp_buffer_validate_corrupt,
+test_rtp_seqnum_compare,
+test_rtp_buffer_list,
+test_rtcp_buffer
 };
 
 char *args[] = {
 "test_rtp_buffer",
-"test_rtp_buffer_set_extension_data"
+"test_rtp_buffer_set_extension_data",
+"test_rtp_buffer_validate_corrupt",
+"test_rtp_seqnum_compare",
+"test_rtp_buffer_list",
+"test_rtcp_buffer"
 };
 
 GST_CHECK_MAIN (gst_rtp);
 
+
 #if 0
 void main()
     {
--- a/gst_plugins_base/tsrc/check/libs/tag/src/tag.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/tag/src/tag.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
@@ -383,7 +392,7 @@
   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE, "Licoo");
   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE_URI,
       "http://creativecommons.org/licenses/by/3.0/");
-  ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LOCATION, "Bristol, UK");
+  ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GEO_LOCATION_NAME, "Bristol, UK");
   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ORGANIZATION, "Orgoo");
   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GENRE, "Goo");
   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_CONTACT, "Coo");
--- a/gst_plugins_base/tsrc/check/libs/taudio/src/taudio.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/taudio/src/taudio.c	Fri Apr 16 15:15:52 2010 +0300
@@ -55,11 +55,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static gboolean
--- a/gst_plugins_base/tsrc/check/libs/video/src/video.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/libs/video/src/video.c	Fri Apr 16 15:15:52 2010 +0300
@@ -53,11 +53,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gst_plugins_base/tsrc/check/pipelines/simple-launch-lines/src/simple-launch-lines.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/pipelines/simple-launch-lines/src/simple-launch-lines.c	Fri Apr 16 15:15:52 2010 +0300
@@ -28,11 +28,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gst_plugins_base/tsrc/check/pipelines/streamheader/src/streamheader.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/check/pipelines/streamheader/src/streamheader.c	Fri Apr 16 15:15:52 2010 +0300
@@ -38,11 +38,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #if EMULATOR
--- a/gst_plugins_base/tsrc/examples/dynamic/addstream/src/addstream.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/tsrc/examples/dynamic/addstream/src/addstream.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,11 +35,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/gstqtmuxu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstalawu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,5 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_alaw_dec_get_type @ 2 NONAME
+	gst_alaw_enc_get_type @ 3 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstalphacoloru.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_alpha_color_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstalphau.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_alpha_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstaudiofxu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,20 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	asinh @ 2 NONAME
+	cosh @ 3 NONAME
+	gst_audio_amplify_get_type @ 4 NONAME
+	gst_audio_cheb_band_get_type @ 5 NONAME
+	gst_audio_cheb_limit_get_type @ 6 NONAME
+	gst_audio_dynamic_get_type @ 7 NONAME
+	gst_audio_echo_get_type @ 8 NONAME
+	gst_audio_fir_filter_get_type @ 9 NONAME
+	gst_audio_fx_base_fir_filter_get_type @ 10 NONAME
+	gst_audio_fx_base_iir_filter_get_type @ 11 NONAME
+	gst_audio_iir_filter_get_type @ 12 NONAME
+	gst_audio_invert_get_type @ 13 NONAME
+	gst_audio_karaoke_get_type @ 14 NONAME
+	gst_audio_panorama_get_type @ 15 NONAME
+	gst_audio_wsincband_get_type @ 16 NONAME
+	gst_audio_wsinclimit_get_type @ 17 NONAME
+	sinh @ 18 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstauparseu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_au_parse_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstaviu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_avi_subtitle_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstjpegU.DEF	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstmulawu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstpngu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_pngenc_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/bwins/libgstqtdemuxu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_rtp_xqt_depay_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/gstqtmuxu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstalawu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,5 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_alaw_dec_get_type @ 2 NONAME
+	gst_alaw_enc_get_type @ 3 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstalphacoloru.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_alpha_color_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstalphau.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_alpha_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstaudiofxu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,17 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_audio_amplify_get_type @ 2 NONAME
+	gst_audio_cheb_band_get_type @ 3 NONAME
+	gst_audio_cheb_limit_get_type @ 4 NONAME
+	gst_audio_dynamic_get_type @ 5 NONAME
+	gst_audio_echo_get_type @ 6 NONAME
+	gst_audio_fir_filter_get_type @ 7 NONAME
+	gst_audio_fx_base_fir_filter_get_type @ 8 NONAME
+	gst_audio_fx_base_iir_filter_get_type @ 9 NONAME
+	gst_audio_iir_filter_get_type @ 10 NONAME
+	gst_audio_invert_get_type @ 11 NONAME
+	gst_audio_karaoke_get_type @ 12 NONAME
+	gst_audio_panorama_get_type @ 13 NONAME
+	gst_audio_wsincband_get_type @ 14 NONAME
+	gst_audio_wsinclimit_get_type @ 15 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstauparseu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_au_parse_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstaviu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_avi_subtitle_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstjpegU.DEF	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstmulawu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstpngu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_pngenc_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/eabi/libgstqtdemuxu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_rtp_xqt_depay_get_type @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,20 @@
+The Smoke Codec
+---------------
+
+This is a very simple compression algorithm I was toying with when doing a
+Java based player. Decoding a JPEG in Java has acceptable speed so this codec
+tries to exploit that feature. The algorithm first compares the last and the 
+new image and finds all 16x16 blocks that have a squared difference bigger than
+a configurable threshold. Then all these blocks are compressed into an NxM JPEG.
+The quality of the JPEG is inversely proportional to the number of blocks, this
+way, the picture quality degrades with heavy motion scenes but the bitrate stays
+more or less constant.
+Decoding decompresses the JPEG and then updates the old picture with the new
+blocks.
+
+
+TODO:
+----
+- make format extensible
+- motion vectors
+- do some real bitrate control
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstjpeg.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,92 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gst/gst.h>
+
+#include "gstjpegdec.h"
+#include "gstjpegenc.h"
+#include "gstsmokeenc.h"
+#include "gstsmokedec.h"
+
+#if 0
+static GstStaticCaps smoke_caps = GST_STATIC_CAPS ("video/x-smoke");
+
+#define SMOKE_CAPS (gst_static_caps_get(&smoke_caps))
+static void
+smoke_type_find (GstTypeFind * tf, gpointer private)
+{
+  guint8 *data = gst_type_find_peek (tf, 0, 6);
+
+  if (data) {
+    if (data[0] != 0x80)
+      return;
+    if (memcmp (&data[1], "smoke", 5) != 0)
+      return;
+    gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SMOKE_CAPS);
+  }
+}
+#endif
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+
+  if (!gst_element_register (plugin, "jpegenc", GST_RANK_NONE,
+          GST_TYPE_JPEGENC))
+    return FALSE;
+
+  if (!gst_element_register (plugin, "jpegdec", GST_RANK_PRIMARY,
+          GST_TYPE_JPEG_DEC))
+    return FALSE;
+
+  if (!gst_element_register (plugin, "smokeenc", GST_RANK_PRIMARY,
+          GST_TYPE_SMOKEENC))
+    return FALSE;
+
+  if (!gst_element_register (plugin, "smokedec", GST_RANK_PRIMARY,
+          GST_TYPE_SMOKEDEC))
+    return FALSE;
+
+#if 0
+  if (!gst_type_find_register (plugin, "video/x-smoke", GST_RANK_PRIMARY,
+          smoke_type_find, NULL, SMOKE_CAPS, NULL))
+    return FALSE;
+#endif
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "jpeg",
+    "JPeg plugin library",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+#ifdef SYMBIAN
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+	return &gst_plugin_desc;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstjpegdec.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,998 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+
+#include "gstjpegdec.h"
+#include <gst/video/video.h>
+#include "gst/gst-i18n-plugin.h"
+#include <jerror.h>
+
+static const GstElementDetails gst_jpeg_dec_details =
+GST_ELEMENT_DETAILS ("JPEG image decoder",
+    "Codec/Decoder/Image",
+    "Decode images from JPEG format",
+    "Wim Taymans <wim.taymans@tvd.be>");
+
+#define MIN_WIDTH  16
+#define MAX_WIDTH  4096
+#define MIN_HEIGHT 16
+#define MAX_HEIGHT 4096
+
+static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+    );
+
+static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("image/jpeg, "
+        "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
+        " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
+        G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (fraction) [ 0/1, MAX ]")
+    );
+
+GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
+#define GST_CAT_DEFAULT jpeg_dec_debug
+
+/* These macros are adapted from videotestsrc.c 
+ *  and/or gst-plugins/gst/games/gstvideoimage.c */
+#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
+#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
+#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
+
+#define I420_Y_OFFSET(w,h) (0)
+#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
+#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
+
+#define I420_SIZE(w,h)     (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
+
+static GstElementClass *parent_class;   /* NULL */
+
+static void gst_jpeg_dec_base_init (gpointer g_class);
+static void gst_jpeg_dec_class_init (GstJpegDecClass * klass);
+static void gst_jpeg_dec_init (GstJpegDec * jpegdec);
+
+static GstFlowReturn gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps);
+static GstStateChangeReturn gst_jpeg_dec_change_state (GstElement * element,
+    GstStateChange transition);
+
+GType
+gst_jpeg_dec_get_type (void)
+{
+  static GType type = 0;
+
+  if (!type) {
+    static const GTypeInfo jpeg_dec_info = {
+      sizeof (GstJpegDecClass),
+      (GBaseInitFunc) gst_jpeg_dec_base_init,
+      NULL,
+      (GClassInitFunc) gst_jpeg_dec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstJpegDec),
+      0,
+      (GInstanceInitFunc) gst_jpeg_dec_init,
+    };
+
+    type = g_type_register_static (GST_TYPE_ELEMENT, "GstJpegDec",
+        &jpeg_dec_info, 0);
+  }
+  return type;
+}
+
+static void
+gst_jpeg_dec_finalize (GObject * object)
+{
+  GstJpegDec *dec = GST_JPEG_DEC (object);
+
+  jpeg_destroy_decompress (&dec->cinfo);
+
+  if (dec->tempbuf)
+    gst_buffer_unref (dec->tempbuf);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_jpeg_dec_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
+  gst_element_class_set_details (element_class, &gst_jpeg_dec_details);
+}
+
+static void
+gst_jpeg_dec_class_init (GstJpegDecClass * klass)
+{
+  GstElementClass *gstelement_class;
+  GObjectClass *gobject_class;
+
+  gstelement_class = (GstElementClass *) klass;
+  gobject_class = (GObjectClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_jpeg_dec_finalize;
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
+
+  GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
+}
+
+static gboolean
+gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
+{
+/*
+  struct GstJpegDecSourceMgr *src_mgr;
+  GstJpegDec *dec;
+
+  src_mgr = (struct GstJpegDecSourceMgr*) &cinfo->src;
+  dec = GST_JPEG_DEC (src_mgr->dec);
+*/
+  GST_DEBUG ("fill_input_buffer");
+/*
+  g_return_val_if_fail (dec != NULL, TRUE);
+
+  src_mgr->pub.next_input_byte = GST_BUFFER_DATA (dec->tempbuf);
+  src_mgr->pub.bytes_in_buffer = GST_BUFFER_SIZE (dec->tempbuf);
+*/
+  return TRUE;
+}
+
+static void
+gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
+{
+  GST_DEBUG ("init_source");
+}
+
+
+static void
+gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
+{
+  GST_DEBUG ("skip_input_data: %ld bytes", num_bytes);
+
+  if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
+    cinfo->src->next_input_byte += (size_t) num_bytes;
+    cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
+  }
+}
+
+static gboolean
+gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
+{
+  GST_DEBUG ("resync_to_start");
+  return TRUE;
+}
+
+static void
+gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
+{
+  GST_DEBUG ("term_source");
+  return;
+}
+
+METHODDEF (void)
+    gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
+{
+  return;                       /* do nothing */
+}
+
+METHODDEF (void)
+    gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
+{
+  /* GST_DEBUG ("emit_message: msg_level = %d", msg_level); */
+  return;
+}
+
+METHODDEF (void)
+    gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
+{
+  struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
+
+  (*cinfo->err->output_message) (cinfo);
+  longjmp (err_mgr->setjmp_buffer, 1);
+}
+
+static void
+gst_jpeg_dec_init (GstJpegDec * dec)
+{
+  GST_DEBUG ("initializing");
+
+  /* create the sink and src pads */
+  dec->sinkpad =
+      gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
+      "sink");
+  gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
+  gst_pad_set_setcaps_function (dec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
+  gst_pad_set_chain_function (dec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_jpeg_dec_chain));
+
+  dec->srcpad =
+      gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
+  gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
+
+  /* setup jpeglib */
+  memset (&dec->cinfo, 0, sizeof (dec->cinfo));
+  memset (&dec->jerr, 0, sizeof (dec->jerr));
+  dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
+  dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
+  dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
+  dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
+
+  jpeg_create_decompress (&dec->cinfo);
+
+  dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
+  dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
+  dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
+  dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
+  dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
+  dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
+  dec->jsrc.dec = dec;
+}
+
+static inline gboolean
+is_jpeg_start_marker (const guint8 * data)
+{
+  return (data[0] == 0xff && data[1] == 0xd8);
+}
+
+static inline gboolean
+is_jpeg_end_marker (const guint8 * data)
+{
+  return (data[0] == 0xff && data[1] == 0xd9);
+}
+
+static gboolean
+gst_jpeg_dec_find_jpeg_header (GstJpegDec * dec)
+{
+  const guint8 *data;
+  guint size;
+
+  data = GST_BUFFER_DATA (dec->tempbuf);
+  size = GST_BUFFER_SIZE (dec->tempbuf);
+
+  g_return_val_if_fail (size >= 2, FALSE);
+
+  while (!is_jpeg_start_marker (data) || data[2] != 0xff) {
+    const guint8 *marker;
+    GstBuffer *tmp;
+    guint off;
+
+    marker = memchr (data + 1, 0xff, size - 1 - 2);
+    if (marker == NULL) {
+      off = size - 1;           /* keep last byte */
+    } else {
+      off = marker - data;
+    }
+
+    tmp = gst_buffer_create_sub (dec->tempbuf, off, size - off);
+    gst_buffer_unref (dec->tempbuf);
+    dec->tempbuf = tmp;
+
+    data = GST_BUFFER_DATA (dec->tempbuf);
+    size = GST_BUFFER_SIZE (dec->tempbuf);
+
+    if (size < 2)
+      return FALSE;             /* wait for more data */
+  }
+
+  return TRUE;                  /* got header */
+}
+
+static gboolean
+gst_jpeg_dec_ensure_header (GstJpegDec * dec)
+{
+  g_return_val_if_fail (dec->tempbuf != NULL, FALSE);
+
+check_header:
+
+  /* we need at least a start marker (0xff 0xd8)
+   *   and an end marker (0xff 0xd9) */
+  if (GST_BUFFER_SIZE (dec->tempbuf) <= 4) {
+    GST_DEBUG ("Not enough data");
+    return FALSE;               /* we need more data */
+  }
+
+  if (!is_jpeg_start_marker (GST_BUFFER_DATA (dec->tempbuf))) {
+    GST_DEBUG ("Not a JPEG header, resyncing to header...");
+    if (!gst_jpeg_dec_find_jpeg_header (dec)) {
+      GST_DEBUG ("No JPEG header in current buffer");
+      return FALSE;             /* we need more data */
+    }
+    GST_DEBUG ("Found JPEG header");
+    goto check_header;          /* buffer might have changed */
+  }
+
+  return TRUE;
+}
+
+#if 0
+static gboolean
+gst_jpeg_dec_have_end_marker (GstJpegDec * dec)
+{
+  guint8 *data = GST_BUFFER_DATA (dec->tempbuf);
+  guint size = GST_BUFFER_SIZE (dec->tempbuf);
+
+  return (size > 2 && data && is_jpeg_end_marker (data + size - 2));
+}
+#endif
+
+static inline gboolean
+gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
+{
+  if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
+    return TRUE;
+  return FALSE;
+}
+
+/* returns image length in bytes if parsed 
+ * successfully, otherwise 0 */
+static guint
+gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
+{
+  guint8 *start, *data, *end;
+  guint size;
+
+  size = GST_BUFFER_SIZE (dec->tempbuf);
+  start = GST_BUFFER_DATA (dec->tempbuf);
+  end = start + size;
+  data = start;
+
+  g_return_val_if_fail (is_jpeg_start_marker (data), 0);
+
+  GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
+
+  /* skip start marker */
+  data += 2;
+
+  while (1) {
+    guint frame_len;
+
+    /* enough bytes left for EOI marker? (we need 0xff 0xNN, thus end-1) */
+    if (data >= end - 1) {
+      GST_DEBUG ("at end of input and no EOI marker found, need more data");
+      return 0;
+    }
+
+    if (is_jpeg_end_marker (data)) {
+      GST_DEBUG ("0x%08x: end marker", data - start);
+      goto found_eoi;
+    }
+
+    /* do we need to resync? */
+    if (*data != 0xff) {
+      GST_DEBUG ("Lost sync at 0x%08x, resyncing", data - start);
+      /* at the very least we expect 0xff 0xNN, thus end-1 */
+      while (*data != 0xff && data < end - 1)
+        ++data;
+      if (is_jpeg_end_marker (data)) {
+        GST_DEBUG ("resynced to end marker");
+        goto found_eoi;
+      }
+      /* we need 0xFF 0xNN 0xLL 0xLL */
+      if (data >= end - 1 - 2) {
+        GST_DEBUG ("at end of input, without new sync, need more data");
+        return 0;
+      }
+      /* check if we will still be in sync if we interpret
+       * this as a sync point and skip this frame */
+      frame_len = GST_READ_UINT16_BE (data + 2);
+      GST_DEBUG ("possible sync at 0x%08x, frame_len=%u", data - start,
+          frame_len);
+      if (data + 2 + frame_len >= end - 1 || data[2 + frame_len] != 0xff) {
+        /* ignore and continue resyncing until we hit the end
+         * of our data or find a sync point that looks okay */
+        ++data;
+        continue;
+      }
+      GST_DEBUG ("found sync at 0x%08x", data - size);
+    }
+    while (*data == 0xff)
+      ++data;
+    if (data + 2 >= end)
+      return 0;
+    if (*data >= 0xd0 && *data <= 0xd7)
+      frame_len = 0;
+    else
+      frame_len = GST_READ_UINT16_BE (data + 1);
+    GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", data - start - 1, *data,
+        frame_len);
+    /* the frame length includes the 2 bytes for the length; here we want at
+     * least 2 more bytes at the end for an end marker, thus end-2 */
+    if (data + 1 + frame_len >= end - 2) {
+      /* theoretically we could have lost sync and not really need more
+       * data, but that's just tough luck and a broken image then */
+      GST_DEBUG ("at end of input and no EOI marker found, need more data");
+      return 0;
+    }
+    if (gst_jpeg_dec_parse_tag_has_entropy_segment (*data)) {
+      guint8 *d2 = data + 1 + frame_len;
+      guint eseglen = 0;
+
+      GST_DEBUG ("0x%08x: finding entropy segment length", data - start - 1);
+      while (1) {
+        if (d2[eseglen] == 0xff && d2[eseglen + 1] != 0x00)
+          break;
+        if (d2 + eseglen >= end - 1)
+          return 0;             /* need more data */
+        ++eseglen;
+      }
+      frame_len += eseglen;
+      GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
+          frame_len);
+    }
+    data += 1 + frame_len;
+  }
+
+found_eoi:
+  /* data is assumed to point to the 0xff sync point of the
+   *  EOI marker (so there is one more byte after that) */
+  g_assert (is_jpeg_end_marker (data));
+  return ((data + 1) - start + 1);
+}
+
+/* shamelessly ripped from jpegutils.c in mjpegtools */
+static void
+add_huff_table (j_decompress_ptr dinfo,
+    JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
+/* Define a Huffman table */
+{
+  int nsymbols, len;
+
+  if (*htblptr == NULL)
+    *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
+
+  /* Copy the number-of-symbols-of-each-code-length counts */
+  memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
+
+  /* Validate the counts.  We do this here mainly so we can copy the right
+   * number of symbols from the val[] array, without risking marching off
+   * the end of memory.  jchuff.c will do a more thorough test later.
+   */
+  nsymbols = 0;
+  for (len = 1; len <= 16; len++)
+    nsymbols += bits[len];
+  if (nsymbols < 1 || nsymbols > 256)
+    g_error ("jpegutils.c:  add_huff_table failed badly. ");
+
+  memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
+}
+
+
+
+static void
+std_huff_tables (j_decompress_ptr dinfo)
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+{
+  static const UINT8 bits_dc_luminance[17] =
+      { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+  static const UINT8 val_dc_luminance[] =
+      { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+  static const UINT8 bits_dc_chrominance[17] =
+      { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+  static const UINT8 val_dc_chrominance[] =
+      { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+  static const UINT8 bits_ac_luminance[17] =
+      { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+  static const UINT8 val_ac_luminance[] =
+      { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+    0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+    0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+    0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+    0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+    0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+    0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+    0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+    0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+    0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+    0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+    0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+    0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+    0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+    0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+    0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+    0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+    0xf9, 0xfa
+  };
+
+  static const UINT8 bits_ac_chrominance[17] =
+      { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+  static const UINT8 val_ac_chrominance[] =
+      { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+    0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+    0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+    0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+    0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+    0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+    0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+    0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+    0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+    0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+    0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+    0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+    0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+    0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+    0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+    0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+    0xf9, 0xfa
+  };
+
+  add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
+      bits_dc_luminance, val_dc_luminance);
+  add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
+      bits_ac_luminance, val_ac_luminance);
+  add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
+      bits_dc_chrominance, val_dc_chrominance);
+  add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
+      bits_ac_chrominance, val_ac_chrominance);
+}
+
+
+
+static void
+guarantee_huff_tables (j_decompress_ptr dinfo)
+{
+  if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
+      (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
+      (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
+      (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
+    GST_DEBUG ("Generating standard Huffman tables for this frame.");
+    std_huff_tables (dinfo);
+  }
+}
+
+static gboolean
+gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstStructure *s;
+  GstJpegDec *dec;
+  const GValue *framerate;
+
+  dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
+  s = gst_caps_get_structure (caps, 0);
+
+  if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
+    dec->framerate_numerator = gst_value_get_fraction_numerator (framerate);
+    dec->framerate_denominator = gst_value_get_fraction_denominator (framerate);
+    dec->packetized = TRUE;
+    GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
+        dec->framerate_numerator, dec->framerate_denominator);
+  }
+
+  /* do not extract width/height here. we do that in the chain
+   * function on a per-frame basis (including the line[] array
+   * setup) */
+
+  /* But we can take the framerate values and set them on the src pad */
+
+  return TRUE;
+}
+
+static void
+gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
+    guchar * last[3], guint width, guint height, gint r_v)
+{
+#ifdef SYMBIAN
+  static guchar y[16][MAX_WIDTH];
+  static guchar u[8][MAX_WIDTH / 2];
+  static guchar v[8][MAX_WIDTH / 2];
+  static guchar *y_rows[16] = { y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7],
+    y[8], y[9], y[10], y[11], y[12], y[13], y[14], y[15]
+  };
+  static guchar *u_rows[8] = { u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7] };
+  static guchar *v_rows[8] = { v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7] };
+  static guchar **scanarray[3] = { y_rows, u_rows, v_rows };
+#else // SYMBIAN
+  guchar y[16][MAX_WIDTH];
+  guchar u[8][MAX_WIDTH / 2];
+  guchar v[8][MAX_WIDTH / 2];
+  guchar *y_rows[16] = { y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7],
+    y[8], y[9], y[10], y[11], y[12], y[13], y[14], y[15]
+  };
+  guchar *u_rows[8] = { u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7] };
+  guchar *v_rows[8] = { v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7] };
+  guchar **scanarray[3] = { y_rows, u_rows, v_rows };
+#endif // SYMBIAN
+  gint i, j, k;
+
+  GST_DEBUG_OBJECT (dec,
+      "unadvantageous width, taking slow route involving memcpy");
+
+  for (i = 0; i < height; i += r_v * DCTSIZE) {
+    jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
+    for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
+      memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
+      if (base[0] < last[0])
+        base[0] += I420_Y_ROWSTRIDE (width);
+      if (r_v == 2) {
+        memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
+        if (base[0] < last[0])
+          base[0] += I420_Y_ROWSTRIDE (width);
+      }
+      memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
+      memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
+      if (r_v == 2 || (k & 1) != 0) {
+        if (base[1] < last[1] && base[2] < last[2]) {
+          base[1] += I420_U_ROWSTRIDE (width);
+          base[2] += I420_V_ROWSTRIDE (width);
+        }
+      }
+    }
+  }
+}
+
+static void
+gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
+    guchar * last[3], guint width, guint height, gint r_v)
+{
+  guchar **line[3];             /* the jpeg line buffer */
+  gint i, j, k;
+
+  line[0] = g_new0 (guchar *, (r_v * DCTSIZE));
+  line[1] = g_new0 (guchar *, (r_v * DCTSIZE));
+  line[2] = g_new0 (guchar *, (r_v * DCTSIZE));
+
+  /* let jpeglib decode directly into our final buffer */
+  GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
+  for (i = 0; i < height; i += r_v * DCTSIZE) {
+    for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
+      line[0][j] = base[0];
+      if (base[0] < last[0])
+        base[0] += I420_Y_ROWSTRIDE (width);
+      if (r_v == 2) {
+        line[0][j + 1] = base[0];
+        if (base[0] < last[0])
+          base[0] += I420_Y_ROWSTRIDE (width);
+      }
+      line[1][k] = base[1];
+      line[2][k] = base[2];
+      if (r_v == 2 || (k & 1) != 0) {
+        if (base[1] < last[1] && base[2] < last[2]) {
+          base[1] += I420_U_ROWSTRIDE (width);
+          base[2] += I420_V_ROWSTRIDE (width);
+        }
+      }
+    }
+    jpeg_read_raw_data (&dec->cinfo, line, r_v * DCTSIZE);
+  }
+
+  g_free (line[0]);
+  g_free (line[1]);
+  g_free (line[2]);
+}
+
+
+static GstFlowReturn
+gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstFlowReturn ret;
+  GstJpegDec *dec;
+  GstBuffer *outbuf;
+  gulong size;
+  guchar *data, *outdata;
+  guchar *base[3], *last[3];
+  guint img_len;
+  gint width, height;
+  gint r_h, r_v;
+  gint i;
+  guint code;
+  GstClockTime timestamp, duration;
+
+  dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
+
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  duration = GST_BUFFER_DURATION (buf);
+
+/*
+  GST_LOG_OBJECT (dec, "Received buffer: %d bytes, ts=%" GST_TIME_FORMAT
+      ", dur=%" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
+      GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
+*/
+
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    dec->next_ts = timestamp;
+  }
+
+  if (dec->tempbuf) {
+    dec->tempbuf = gst_buffer_join (dec->tempbuf, buf);
+  } else {
+    dec->tempbuf = buf;
+  }
+  buf = NULL;
+
+  if (!gst_jpeg_dec_ensure_header (dec))
+    goto need_more_data;
+
+  /* If we know that each input buffer contains data
+   * for a whole jpeg image (e.g. MJPEG streams), just 
+   * do some sanity checking instead of parsing all of 
+   * the jpeg data */
+  if (dec->packetized) {
+    img_len = GST_BUFFER_SIZE (dec->tempbuf);
+  } else {
+    /* Parse jpeg image to handle jpeg input that
+     * is not aligned to buffer boundaries */
+    img_len = gst_jpeg_dec_parse_image_data (dec);
+
+    if (img_len == 0)
+      goto need_more_data;
+  }
+
+  data = (guchar *) GST_BUFFER_DATA (dec->tempbuf);
+  size = img_len;
+  GST_LOG_OBJECT (dec, "image size = %u", img_len);
+
+  dec->jsrc.pub.next_input_byte = data;
+  dec->jsrc.pub.bytes_in_buffer = size;
+
+  if (setjmp (dec->jerr.setjmp_buffer)) {
+    code = dec->jerr.pub.msg_code;
+
+    if (code == JERR_INPUT_EOF) {
+      GST_DEBUG ("jpeg input EOF error, we probably need more data");
+      goto need_more_data;
+    }
+    goto decode_error;
+  }
+
+  GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
+      data[2], data[3]);
+  jpeg_read_header (&dec->cinfo, TRUE);
+
+  r_h = dec->cinfo.cur_comp_info[0]->h_samp_factor;
+  r_v = dec->cinfo.cur_comp_info[0]->v_samp_factor;
+
+  GST_DEBUG ("num_components=%d, comps_in_scan=%d\n",
+      dec->cinfo.num_components, dec->cinfo.comps_in_scan);
+  for (i = 0; i < dec->cinfo.num_components; ++i) {
+    GST_DEBUG ("[%d] h_samp_factor=%d, v_samp_factor=%d\n", i,
+        dec->cinfo.cur_comp_info[i]->h_samp_factor,
+        dec->cinfo.cur_comp_info[i]->v_samp_factor);
+  }
+
+  dec->cinfo.do_fancy_upsampling = FALSE;
+  dec->cinfo.do_block_smoothing = FALSE;
+  dec->cinfo.out_color_space = JCS_YCbCr;
+  dec->cinfo.dct_method = JDCT_IFAST;
+  dec->cinfo.raw_data_out = TRUE;
+  GST_LOG_OBJECT (dec, "starting decompress");
+  guarantee_huff_tables (&dec->cinfo);
+  jpeg_start_decompress (&dec->cinfo);
+  width = dec->cinfo.output_width;
+  height = dec->cinfo.output_height;
+
+  if (width < MIN_WIDTH || width > MAX_WIDTH ||
+      height < MIN_HEIGHT || height > MAX_HEIGHT)
+    goto wrong_size;
+
+  if (width != dec->caps_width || height != dec->caps_height ||
+      dec->framerate_numerator != dec->caps_framerate_numerator ||
+      dec->framerate_denominator != dec->caps_framerate_denominator) {
+    GstCaps *caps;
+
+    /* framerate == 0/1 is a still frame */
+    if (dec->framerate_denominator == 0) {
+      dec->framerate_numerator = 0;
+      dec->framerate_denominator = 1;
+    }
+
+    caps = gst_caps_new_simple ("video/x-raw-yuv",
+        "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+        "width", G_TYPE_INT, width,
+        "height", G_TYPE_INT, height,
+        "framerate", GST_TYPE_FRACTION, dec->framerate_numerator,
+        dec->framerate_denominator, NULL);
+
+    GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
+    GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d",
+        dec->cinfo.max_v_samp_factor);
+
+    gst_pad_use_fixed_caps (dec->srcpad);
+    gst_pad_set_caps (dec->srcpad, caps);
+    gst_caps_unref (caps);
+
+    dec->caps_width = width;
+    dec->caps_height = height;
+    dec->caps_framerate_numerator = dec->framerate_numerator;
+    dec->caps_framerate_denominator = dec->framerate_denominator;
+  }
+
+  ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
+      I420_SIZE (width, height), GST_PAD_CAPS (dec->srcpad), &outbuf);
+  if (ret != GST_FLOW_OK)
+    goto alloc_failed;
+
+  outdata = GST_BUFFER_DATA (outbuf);
+  GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
+
+  if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
+    if (GST_CLOCK_TIME_IS_VALID (duration)) {
+      /* use duration from incoming buffer for outgoing buffer */
+      dec->next_ts += duration;
+    } else if (dec->framerate_numerator != 0) {
+      duration = gst_util_uint64_scale (GST_SECOND,
+          dec->framerate_denominator, dec->framerate_numerator);
+      dec->next_ts += duration;
+    } else {
+      duration = GST_CLOCK_TIME_NONE;
+      dec->next_ts = GST_CLOCK_TIME_NONE;
+    }
+  } else {
+    duration = GST_CLOCK_TIME_NONE;
+    dec->next_ts = GST_CLOCK_TIME_NONE;
+  }
+  GST_BUFFER_DURATION (outbuf) = duration;
+
+  GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
+      width, height, GST_BUFFER_SIZE (outbuf), I420_SIZE (width, height));
+
+  /* mind the swap, jpeglib outputs blue chroma first */
+  base[0] = outdata + I420_Y_OFFSET (width, height);
+  base[1] = outdata + I420_U_OFFSET (width, height);
+  base[2] = outdata + I420_V_OFFSET (width, height);
+
+  /* make sure we don't make jpeglib write beyond our buffer,
+   * which might happen if (height % (r_v*DCTSIZE)) != 0 */
+  last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
+  last[1] =
+      base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
+          1));
+  last[2] =
+      base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
+          1));
+
+  GST_LOG_OBJECT (dec, "decompressing %u", dec->cinfo.rec_outbuf_height);
+  GST_LOG_OBJECT (dec, "max_h_samp_factor=%u", dec->cinfo.max_h_samp_factor);
+
+  /* For some widths jpeglib requires more horizontal padding than I420 
+   * provides. In those cases we need to decode into separate buffers and then
+   * copy over the data into our final picture buffer, otherwise jpeglib might
+   * write over the end of a line into the beginning of the next line,
+   * resulting in blocky artifacts on the left side of the picture. */
+  if (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0) {
+    gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v);
+  } else {
+    gst_jpeg_dec_decode_direct (dec, base, last, width, height, r_v);
+  }
+
+  GST_LOG_OBJECT (dec, "decompressing finished");
+  jpeg_finish_decompress (&dec->cinfo);
+
+  GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
+      GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
+
+  ret = gst_pad_push (dec->srcpad, outbuf);
+
+done:
+  if (GST_BUFFER_SIZE (dec->tempbuf) == img_len) {
+    gst_buffer_unref (dec->tempbuf);
+    dec->tempbuf = NULL;
+  } else {
+    GstBuffer *buf = gst_buffer_create_sub (dec->tempbuf, img_len,
+        GST_BUFFER_SIZE (dec->tempbuf) - img_len);
+
+    gst_buffer_unref (dec->tempbuf);
+    dec->tempbuf = buf;
+  }
+  return ret;
+
+  /* special cases */
+need_more_data:
+  {
+    GST_LOG_OBJECT (dec, "we need more data");
+    return GST_FLOW_OK;
+  }
+  /* ERRORS */
+wrong_size:
+  {
+    GST_ELEMENT_ERROR (dec, STREAM, DECODE,
+        ("Picture is too small or too big (%ux%u)", width, height),
+        ("Picture is too small or too big (%ux%u)", width, height));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+decode_error:
+  {
+    GST_ELEMENT_ERROR (dec, STREAM, DECODE,
+        (_("Failed to decode JPEG image")),
+        ("Error #%u: %s", code, dec->jerr.pub.jpeg_message_table[code]));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+alloc_failed:
+  {
+    const gchar *reason;
+
+    reason = gst_flow_get_name (ret);
+
+    GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
+    if (GST_FLOW_IS_FATAL (ret)) {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE,
+          ("Buffer allocation failed, reason: %s", reason),
+          ("Buffer allocation failed, reason: %s", reason));
+    }
+    return ret;
+  }
+}
+
+static GstStateChangeReturn
+gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstJpegDec *dec;
+
+  dec = GST_JPEG_DEC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      dec->framerate_numerator = 0;
+      dec->framerate_denominator = 1;
+      dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
+      dec->caps_width = -1;
+      dec->caps_height = -1;
+      dec->packetized = FALSE;
+      dec->next_ts = 0;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret != GST_STATE_CHANGE_SUCCESS)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      if (dec->tempbuf) {
+        gst_buffer_unref (dec->tempbuf);
+        dec->tempbuf = NULL;
+      }
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstjpegdec.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,103 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_JPEG_DEC_H__
+#define __GST_JPEG_DEC_H__
+
+
+#include <setjmp.h>
+#include <gst/gstelement.h>
+
+/* this is a hack hack hack to get around jpeglib header bugs... */
+#ifdef HAVE_STDLIB_H
+# undef HAVE_STDLIB_H
+#endif
+#include <jpeglib.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_JPEG_DEC \
+  (gst_jpeg_dec_get_type())
+#define GST_JPEG_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JPEG_DEC,GstJpegDec))
+#define GST_JPEG_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JPEG_DEC,GstJpegDecClass))
+#define GST_IS_JPEG_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JPEG_DEC))
+#define GST_IS_JPEG_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JPEG_DEC))
+
+typedef struct _GstJpegDec           GstJpegDec;
+typedef struct _GstJpegDecClass      GstJpegDecClass;
+
+struct GstJpegDecErrorMgr {
+  struct jpeg_error_mgr    pub;   /* public fields */
+  jmp_buf                  setjmp_buffer;
+};
+
+struct GstJpegDecSourceMgr {
+  struct jpeg_source_mgr   pub;   /* public fields */
+  GstJpegDec              *dec;
+};
+
+/* Can't use GstBaseTransform, because GstBaseTransform
+ * doesn't handle the N buffers in, 1 buffer out case,
+ * but only the 1-in 1-out case */
+struct _GstJpegDec {
+  GstElement element;
+
+  /* pads */
+  GstPad  *sinkpad;
+  GstPad  *srcpad;
+
+  GstBuffer *tempbuf;
+
+  /* TRUE if each input buffer contains a whole jpeg image */
+  gboolean packetized;
+
+  /* the (expected) timestamp of the next frame */
+  guint64  next_ts;
+
+  /* video state */
+  gint framerate_numerator;
+  gint framerate_denominator;
+
+  /* negotiated state */
+  gint     caps_framerate_numerator;
+  gint     caps_framerate_denominator;
+  gint     caps_width;
+  gint     caps_height;
+
+  struct jpeg_decompress_struct cinfo;
+  struct GstJpegDecErrorMgr     jerr;
+  struct GstJpegDecSourceMgr    jsrc;
+};
+
+struct _GstJpegDecClass {
+  GstElementClass  parent_class;
+};
+
+GType gst_jpeg_dec_get_type(void);
+
+
+G_END_DECLS
+
+
+#endif /* __GST_JPEG_DEC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstjpegenc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,565 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+
+#include "gstjpegenc.h"
+#include <gst/video/video.h>
+
+/* elementfactory information */
+static const GstElementDetails gst_jpegenc_details =
+GST_ELEMENT_DETAILS ("JPEG image encoder",
+    "Codec/Encoder/Image",
+    "Encode images in JPEG format",
+    "Wim Taymans <wim.taymans@tvd.be>");
+
+GST_DEBUG_CATEGORY (jpegenc_debug);
+#define GST_CAT_DEFAULT jpegenc_debug
+
+#define JPEG_DEFAULT_QUALITY 85
+
+/* These macros are adapted from videotestsrc.c 
+ *  and/or gst-plugins/gst/games/gstvideoimage.c */
+
+/* I420 */
+#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
+#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
+#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
+
+#define I420_Y_OFFSET(w,h) (0)
+#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
+#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
+
+#define I420_SIZE(w,h)     (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
+
+/* JpegEnc signals and args */
+enum
+{
+  FRAME_ENCODED,
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_QUALITY,
+  ARG_SMOOTHING
+      /* FILL ME */
+};
+
+static void gst_jpegenc_base_init (gpointer g_class);
+static void gst_jpegenc_class_init (GstJpegEnc * klass);
+static void gst_jpegenc_init (GstJpegEnc * jpegenc);
+static void gst_jpegenc_finalize (GObject * object);
+
+static GstFlowReturn gst_jpegenc_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_jpegenc_setcaps (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_jpegenc_getcaps (GstPad * pad);
+
+static void gst_jpegenc_resync (GstJpegEnc * jpegenc);
+static void gst_jpegenc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_jpegenc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static GstStateChangeReturn gst_jpegenc_change_state (GstElement * element,
+    GstStateChange transition);
+
+
+static GstElementClass *parent_class = NULL;
+static guint gst_jpegenc_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_jpegenc_get_type (void)
+{
+  static GType jpegenc_type = 0;
+
+  if (!jpegenc_type) {
+    static const GTypeInfo jpegenc_info = {
+      sizeof (GstJpegEnc),
+      (GBaseInitFunc) gst_jpegenc_base_init,
+      NULL,
+      (GClassInitFunc) gst_jpegenc_class_init,
+      NULL,
+      NULL,
+      sizeof (GstJpegEnc),
+      0,
+      (GInstanceInitFunc) gst_jpegenc_init,
+    };
+
+    jpegenc_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstJpegEnc", &jpegenc_info,
+        0);
+  }
+  return jpegenc_type;
+}
+
+static GstStaticPadTemplate gst_jpegenc_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+    );
+
+static GstStaticPadTemplate gst_jpegenc_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("image/jpeg, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0/1, MAX ]")
+    );
+
+static void
+gst_jpegenc_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_jpegenc_sink_pad_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_jpegenc_src_pad_template));
+  gst_element_class_set_details (element_class, &gst_jpegenc_details);
+}
+
+static void
+gst_jpegenc_class_init (GstJpegEnc * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gst_jpegenc_signals[FRAME_ENCODED] =
+      g_signal_new ("frame-encoded", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstJpegEncClass, frame_encoded), NULL,
+      NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+  gobject_class->set_property = gst_jpegenc_set_property;
+  gobject_class->get_property = gst_jpegenc_get_property;
+
+
+  g_object_class_install_property (gobject_class, ARG_QUALITY,
+      g_param_spec_int ("quality", "Quality", "Quality of encoding",
+          0, 100, JPEG_DEFAULT_QUALITY, G_PARAM_READWRITE));
+#if 0
+  /* disabled, since it doesn't seem to work */
+  g_object_class_install_property (gobject_class, ARG_SMOOTHING,
+      g_param_spec_int ("smoothing", "Smoothing", "Smoothing factor",
+          0, 100, 0, G_PARAM_READWRITE));
+#endif
+
+  gstelement_class->change_state = gst_jpegenc_change_state;
+
+  gobject_class->finalize = gst_jpegenc_finalize;
+
+  GST_DEBUG_CATEGORY_INIT (jpegenc_debug, "jpegenc", 0,
+      "JPEG encoding element");
+}
+
+static void
+gst_jpegenc_init_destination (j_compress_ptr cinfo)
+{
+  GST_DEBUG ("gst_jpegenc_chain: init_destination");
+}
+
+static gboolean
+gst_jpegenc_flush_destination (j_compress_ptr cinfo)
+{
+  GST_DEBUG ("gst_jpegenc_chain: flush_destination: buffer too small !!!");
+  return TRUE;
+}
+
+static void
+gst_jpegenc_term_destination (j_compress_ptr cinfo)
+{
+  GST_DEBUG ("gst_jpegenc_chain: term_source");
+}
+
+static void
+gst_jpegenc_init (GstJpegEnc * jpegenc)
+{
+  /* create the sink and src pads */
+  jpegenc->sinkpad =
+      gst_pad_new_from_static_template (&gst_jpegenc_sink_pad_template, "sink");
+  gst_pad_set_chain_function (jpegenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_jpegenc_chain));
+  gst_pad_set_getcaps_function (jpegenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_jpegenc_getcaps));
+  gst_pad_set_setcaps_function (jpegenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_jpegenc_setcaps));
+  gst_element_add_pad (GST_ELEMENT (jpegenc), jpegenc->sinkpad);
+
+  jpegenc->srcpad =
+      gst_pad_new_from_static_template (&gst_jpegenc_src_pad_template, "src");
+  gst_pad_set_getcaps_function (jpegenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_jpegenc_getcaps));
+  /*gst_pad_set_setcaps_function (jpegenc->sinkpad, gst_jpegenc_setcaps); */
+  gst_pad_use_fixed_caps (jpegenc->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (jpegenc), jpegenc->srcpad);
+
+  /* reset the initial video state */
+  jpegenc->width = -1;
+  jpegenc->height = -1;
+
+  /* setup jpeglib */
+  memset (&jpegenc->cinfo, 0, sizeof (jpegenc->cinfo));
+  memset (&jpegenc->jerr, 0, sizeof (jpegenc->jerr));
+  jpegenc->cinfo.err = jpeg_std_error (&jpegenc->jerr);
+  jpeg_create_compress (&jpegenc->cinfo);
+
+  jpegenc->jdest.init_destination = gst_jpegenc_init_destination;
+  jpegenc->jdest.empty_output_buffer = gst_jpegenc_flush_destination;
+  jpegenc->jdest.term_destination = gst_jpegenc_term_destination;
+  jpegenc->cinfo.dest = &jpegenc->jdest;
+
+  jpegenc->quality = JPEG_DEFAULT_QUALITY;
+  jpegenc->smoothing = 0;
+}
+
+static void
+gst_jpegenc_finalize (GObject * object)
+{
+
+  GstJpegEnc *filter = GST_JPEGENC (object);
+
+  jpeg_destroy_compress (&filter->cinfo);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GstCaps *
+gst_jpegenc_getcaps (GstPad * pad)
+{
+  GstJpegEnc *jpegenc = GST_JPEGENC (gst_pad_get_parent (pad));
+  GstPad *otherpad;
+  GstCaps *caps;
+  const char *name;
+  int i;
+  GstStructure *structure = NULL;
+
+  /* we want to proxy properties like width, height and framerate from the
+     other end of the element */
+  otherpad = (pad == jpegenc->srcpad) ? jpegenc->sinkpad : jpegenc->srcpad;
+  caps = gst_pad_get_allowed_caps (otherpad);
+  if (pad == jpegenc->srcpad) {
+    name = "image/jpeg";
+  } else {
+    name = "video/x-raw-yuv";
+  }
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    structure = gst_caps_get_structure (caps, i);
+
+    gst_structure_set_name (structure, name);
+    gst_structure_remove_field (structure, "format");
+    /* ... but for the sink pad, we only do I420 anyway, so add that */
+    if (pad == jpegenc->sinkpad) {
+      gst_structure_set (structure, "format", GST_TYPE_FOURCC,
+          GST_STR_FOURCC ("I420"), NULL);
+    }
+  }
+  gst_object_unref (jpegenc);
+
+  return caps;
+}
+
+static gboolean
+gst_jpegenc_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstJpegEnc *jpegenc = GST_JPEGENC (gst_pad_get_parent (pad));
+  GstStructure *structure;
+  GstCaps *othercaps;
+  GstPad *otherpad;
+  gboolean ret;
+  const GValue *framerate;
+
+  otherpad = (pad == jpegenc->srcpad) ? jpegenc->sinkpad : jpegenc->srcpad;
+
+  structure = gst_caps_get_structure (caps, 0);
+  framerate = gst_structure_get_value (structure, "framerate");
+  gst_structure_get_int (structure, "width", &jpegenc->width);
+  gst_structure_get_int (structure, "height", &jpegenc->height);
+
+  othercaps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
+  if (framerate) {
+    gst_caps_set_simple (othercaps,
+        "width", G_TYPE_INT, jpegenc->width,
+        "height", G_TYPE_INT, jpegenc->height,
+        "framerate", GST_TYPE_FRACTION,
+        gst_value_get_fraction_numerator (framerate),
+        gst_value_get_fraction_denominator (framerate), NULL);
+  } else {
+    gst_caps_set_simple (othercaps,
+        "width", G_TYPE_INT, jpegenc->width,
+        "height", G_TYPE_INT, jpegenc->height, NULL);
+  }
+
+  ret = gst_pad_set_caps (jpegenc->srcpad, othercaps);
+  gst_caps_unref (othercaps);
+
+  if (GST_PAD_LINK_SUCCESSFUL (ret)) {
+    gst_jpegenc_resync (jpegenc);
+  }
+
+  gst_object_unref (jpegenc);
+
+  return ret;
+}
+
+static void
+gst_jpegenc_resync (GstJpegEnc * jpegenc)
+{
+  gint width, height;
+
+  GST_DEBUG_OBJECT (jpegenc, "resync");
+
+  jpegenc->cinfo.image_width = width = jpegenc->width;
+  jpegenc->cinfo.image_height = height = jpegenc->height;
+  jpegenc->cinfo.input_components = 3;
+
+  GST_DEBUG_OBJECT (jpegenc, "width %d, height %d", width, height);
+
+  jpeg_set_defaults (&jpegenc->cinfo);
+  jpegenc->cinfo.dct_method = JDCT_FASTEST;
+  /*jpegenc->cinfo.dct_method = JDCT_DEFAULT; */
+  /*jpegenc->cinfo.smoothing_factor = jpegenc->smoothing; */
+  jpeg_set_quality (&jpegenc->cinfo, jpegenc->quality, TRUE);
+
+#if 0
+  switch (jpegenc->format) {
+    case GST_COLORSPACE_RGB24:
+      jpegenc->bufsize = jpegenc->width * jpegenc->height * 3;
+      GST_DEBUG ("gst_jpegenc_resync: setting format to RGB24");
+      jpegenc->cinfo.in_color_space = JCS_RGB;
+      jpegenc->cinfo.raw_data_in = FALSE;
+      break;
+    case GST_COLORSPACE_YUV420P:
+#endif
+      jpegenc->bufsize = I420_SIZE (jpegenc->width, jpegenc->height);
+      jpegenc->cinfo.raw_data_in = TRUE;
+      jpegenc->cinfo.in_color_space = JCS_YCbCr;
+      GST_DEBUG_OBJECT (jpegenc, "setting format to YUV420P");
+      jpegenc->cinfo.comp_info[0].h_samp_factor = 2;
+      jpegenc->cinfo.comp_info[0].v_samp_factor = 2;
+      jpegenc->cinfo.comp_info[1].h_samp_factor = 1;
+      jpegenc->cinfo.comp_info[1].v_samp_factor = 1;
+      jpegenc->cinfo.comp_info[2].h_samp_factor = 1;
+      jpegenc->cinfo.comp_info[2].v_samp_factor = 1;
+
+      if (height != -1) {
+        jpegenc->line[0] =
+            g_realloc (jpegenc->line[0], height * sizeof (char *));
+        jpegenc->line[1] =
+            g_realloc (jpegenc->line[1], height * sizeof (char *) / 2);
+        jpegenc->line[2] =
+            g_realloc (jpegenc->line[2], height * sizeof (char *) / 2);
+      }
+
+      GST_DEBUG_OBJECT (jpegenc, "setting format done");
+#if 0
+      break;
+    default:
+      printf ("gst_jpegenc_resync: unsupported colorspace, using RGB\n");
+      jpegenc->bufsize = jpegenc->width * jpegenc->height * 3;
+      jpegenc->cinfo.in_color_space = JCS_RGB;
+      break;
+  }
+#endif
+
+  jpeg_suppress_tables (&jpegenc->cinfo, TRUE);
+  //jpeg_suppress_tables(&jpegenc->cinfo, FALSE);
+
+  jpegenc->buffer = NULL;
+  GST_DEBUG_OBJECT (jpegenc, "resync done");
+}
+
+static GstFlowReturn
+gst_jpegenc_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstFlowReturn ret;
+  GstJpegEnc *jpegenc;
+  guchar *data;
+  gulong size;
+  GstBuffer *outbuf;
+  guint height, width;
+  guchar *base[3], *end[3];
+  gint i, j, k;
+
+  jpegenc = GST_JPEGENC (GST_OBJECT_PARENT (pad));
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  GST_DEBUG_OBJECT (jpegenc, "got buffer of %u bytes", size);
+
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (jpegenc->srcpad,
+      GST_BUFFER_OFFSET_NONE, jpegenc->bufsize, GST_PAD_CAPS (jpegenc->srcpad),
+      &outbuf);
+
+  if (ret != GST_FLOW_OK)
+    goto done;
+
+  gst_buffer_stamp (outbuf, buf);
+
+  width = jpegenc->width;
+  height = jpegenc->height;
+
+  base[0] = data + I420_Y_OFFSET (width, height);
+  base[1] = data + I420_U_OFFSET (width, height);
+  base[2] = data + I420_V_OFFSET (width, height);
+
+  end[0] = base[0] + height * I420_Y_ROWSTRIDE (width);
+  end[1] = base[1] + (height / 2) * I420_U_ROWSTRIDE (width);
+  end[2] = base[2] + (height / 2) * I420_V_ROWSTRIDE (width);
+
+  jpegenc->jdest.next_output_byte = GST_BUFFER_DATA (outbuf);
+  jpegenc->jdest.free_in_buffer = GST_BUFFER_SIZE (outbuf);
+
+  jpegenc->cinfo.smoothing_factor = jpegenc->smoothing;
+  jpeg_set_quality (&jpegenc->cinfo, jpegenc->quality, TRUE);
+  jpeg_start_compress (&jpegenc->cinfo, TRUE);
+
+  GST_DEBUG_OBJECT (jpegenc, "compressing");
+
+  for (i = 0; i < height; i += 2 * DCTSIZE) {
+    /*g_print ("next scanline: %d\n", jpegenc->cinfo.next_scanline); */
+    for (j = 0, k = 0; j < (2 * DCTSIZE); j += 2, k++) {
+      jpegenc->line[0][j] = base[0];
+      if (base[0] + I420_Y_ROWSTRIDE (width) < end[0])
+        base[0] += I420_Y_ROWSTRIDE (width);
+      jpegenc->line[0][j + 1] = base[0];
+      if (base[0] + I420_Y_ROWSTRIDE (width) < end[0])
+        base[0] += I420_Y_ROWSTRIDE (width);
+      jpegenc->line[1][k] = base[1];
+      if (base[1] + I420_U_ROWSTRIDE (width) < end[1])
+        base[1] += I420_U_ROWSTRIDE (width);
+      jpegenc->line[2][k] = base[2];
+      if (base[2] + I420_V_ROWSTRIDE (width) < end[2])
+        base[2] += I420_V_ROWSTRIDE (width);
+    }
+    jpeg_write_raw_data (&jpegenc->cinfo, jpegenc->line, 2 * DCTSIZE);
+  }
+
+  jpeg_finish_compress (&jpegenc->cinfo);
+  GST_DEBUG_OBJECT (jpegenc, "compressing done");
+
+  GST_BUFFER_SIZE (outbuf) =
+      GST_ROUND_UP_4 (jpegenc->bufsize - jpegenc->jdest.free_in_buffer);
+
+  g_signal_emit (G_OBJECT (jpegenc), gst_jpegenc_signals[FRAME_ENCODED], 0);
+
+  ret = gst_pad_push (jpegenc->srcpad, outbuf);
+
+done:
+  gst_buffer_unref (buf);
+
+  return ret;
+}
+
+static void
+gst_jpegenc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstJpegEnc *jpegenc = GST_JPEGENC (object);
+
+  GST_OBJECT_LOCK (jpegenc);
+
+  switch (prop_id) {
+    case ARG_QUALITY:
+      jpegenc->quality = g_value_get_int (value);
+      break;
+    case ARG_SMOOTHING:
+      jpegenc->smoothing = g_value_get_int (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+
+  GST_OBJECT_UNLOCK (jpegenc);
+}
+
+static void
+gst_jpegenc_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstJpegEnc *jpegenc = GST_JPEGENC (object);
+
+  GST_OBJECT_LOCK (jpegenc);
+
+  switch (prop_id) {
+    case ARG_QUALITY:
+      g_value_set_int (value, jpegenc->quality);
+      break;
+    case ARG_SMOOTHING:
+      g_value_set_int (value, jpegenc->smoothing);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+
+  GST_OBJECT_UNLOCK (jpegenc);
+}
+
+static GstStateChangeReturn
+gst_jpegenc_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstJpegEnc *filter = GST_JPEGENC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      GST_DEBUG_OBJECT (element, "setting line buffers");
+      filter->line[0] = NULL;
+      filter->line[1] = NULL;
+      filter->line[2] = NULL;
+      gst_jpegenc_resync (filter);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      g_free (filter->line[0]);
+      g_free (filter->line[1]);
+      g_free (filter->line[2]);
+      filter->line[0] = NULL;
+      filter->line[1] = NULL;
+      filter->line[2] = NULL;
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstjpegenc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,84 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_JPEGENC_H__
+#define __GST_JPEGENC_H__
+
+
+#include <gst/gst.h>
+/* this is a hack hack hack to get around jpeglib header bugs... */
+#ifdef HAVE_STDLIB_H
+# undef HAVE_STDLIB_H
+#endif
+#include <jpeglib.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_JPEGENC \
+  (gst_jpegenc_get_type())
+#define GST_JPEGENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JPEGENC,GstJpegEnc))
+#define GST_JPEGENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JPEGENC,GstJpegEnc))
+#define GST_IS_JPEGENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JPEGENC))
+#define GST_IS_JPEGENC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JPEGENC))
+
+typedef struct _GstJpegEnc GstJpegEnc;
+typedef struct _GstJpegEncClass GstJpegEncClass;
+
+struct _GstJpegEnc {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  /* video state */
+  gint format;
+  gint width;
+  gint height;
+  /* the video buffer */
+  gint bufsize;
+  GstBuffer *buffer;
+  guint row_stride;
+  /* the jpeg line buffer */
+  guchar **line[3];
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  struct jpeg_destination_mgr jdest;
+
+  int quality;
+  int smoothing;
+};
+
+struct _GstJpegEncClass {
+  GstElementClass parent_class;
+
+  /* signals */
+  void (*frame_encoded) (GstElement *element);
+};
+
+GType gst_jpegenc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_JPEGENC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstsmokedec.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,273 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+
+/*#define DEBUG_ENABLED*/
+#include "gstsmokedec.h"
+#include <gst/video/video.h>
+
+/* elementfactory information */
+static const GstElementDetails gst_smokedec_details =
+GST_ELEMENT_DETAILS ("Smoke video decoder",
+    "Codec/Decoder/Video",
+    "Decode video from Smoke format",
+    "Wim Taymans <wim@fluendo.com>");
+
+GST_DEBUG_CATEGORY (smokedec_debug);
+#define GST_CAT_DEFAULT smokedec_debug
+
+/* SmokeDec signals and args */
+enum
+{
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0
+};
+
+static void gst_smokedec_base_init (gpointer g_class);
+static void gst_smokedec_class_init (GstSmokeDec * klass);
+static void gst_smokedec_init (GstSmokeDec * smokedec);
+
+static GstFlowReturn gst_smokedec_chain (GstPad * pad, GstBuffer * buf);
+
+static GstElementClass *parent_class = NULL;
+
+/*static guint gst_smokedec_signals[LAST_SIGNAL] = { 0 }; */
+
+GType
+gst_smokedec_get_type (void)
+{
+  static GType smokedec_type = 0;
+
+  if (!smokedec_type) {
+    static const GTypeInfo smokedec_info = {
+      sizeof (GstSmokeDecClass),
+      gst_smokedec_base_init,
+      NULL,
+      (GClassInitFunc) gst_smokedec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstSmokeDec),
+      0,
+      (GInstanceInitFunc) gst_smokedec_init,
+    };
+
+    smokedec_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstSmokeDec", &smokedec_info,
+        0);
+  }
+  return smokedec_type;
+}
+
+static GstStaticPadTemplate gst_smokedec_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+    );
+
+static GstStaticPadTemplate gst_smokedec_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-smoke, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0/1, MAX ]")
+    );
+
+static void
+gst_smokedec_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_smokedec_src_pad_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_smokedec_sink_pad_template));
+  gst_element_class_set_details (element_class, &gst_smokedec_details);
+}
+
+static void
+gst_smokedec_class_init (GstSmokeDec * klass)
+{
+  GstElementClass *gstelement_class;
+
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  GST_DEBUG_CATEGORY_INIT (smokedec_debug, "smokedec", 0, "Smoke decoder");
+}
+
+static void
+gst_smokedec_init (GstSmokeDec * smokedec)
+{
+  GST_DEBUG_OBJECT (smokedec, "gst_smokedec_init: initializing");
+  /* create the sink and src pads */
+
+  smokedec->sinkpad =
+      gst_pad_new_from_static_template (&gst_smokedec_sink_pad_template,
+      "sink");
+  gst_pad_set_chain_function (smokedec->sinkpad, gst_smokedec_chain);
+  gst_element_add_pad (GST_ELEMENT (smokedec), smokedec->sinkpad);
+
+  smokedec->srcpad =
+      gst_pad_new_from_static_template (&gst_smokedec_src_pad_template, "src");
+  gst_pad_use_fixed_caps (smokedec->srcpad);
+  gst_element_add_pad (GST_ELEMENT (smokedec), smokedec->srcpad);
+
+  /* reset the initial video state */
+  smokedec->format = -1;
+  smokedec->width = -1;
+  smokedec->height = -1;
+  smokedec->fps_num = -1;
+  smokedec->fps_denom = -1;
+  smokedec->next_time = 0;
+
+  smokecodec_decode_new (&smokedec->info);
+}
+
+static GstFlowReturn
+gst_smokedec_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstSmokeDec *smokedec;
+  guint8 *data, *outdata;
+  gulong size, outsize;
+  GstBuffer *outbuf;
+  SmokeCodecFlags flags;
+  GstClockTime time;
+  guint width, height;
+  guint fps_num, fps_denom;
+  gint smokeret;
+  GstFlowReturn ret;
+
+  smokedec = GST_SMOKEDEC (gst_pad_get_parent (pad));
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+  time = GST_BUFFER_TIMESTAMP (buf);
+
+  GST_DEBUG_OBJECT (smokedec,
+      "gst_smokedec_chain: got buffer of %ld bytes in '%s'", size,
+      GST_OBJECT_NAME (smokedec));
+
+  /* have the ID packet. */
+  if (data[0] == SMOKECODEC_TYPE_ID) {
+    smokeret = smokecodec_parse_id (smokedec->info, data, size);
+    if (smokeret != SMOKECODEC_OK)
+      goto header_error;
+
+    ret = GST_FLOW_OK;
+    goto done;
+  }
+
+  /* now handle data packets */
+  GST_DEBUG_OBJECT (smokedec, "gst_smokedec_chain: reading header %08lx",
+      *(gulong *) data);
+  smokecodec_parse_header (smokedec->info, data, size, &flags, &width, &height,
+      &fps_num, &fps_denom);
+
+  if (smokedec->height != height || smokedec->width != width ||
+      smokedec->fps_num != fps_num || smokedec->fps_denom != fps_denom) {
+    GstCaps *caps;
+
+    smokedec->height = height;
+    smokedec->width = width;
+
+    caps = gst_caps_new_simple ("video/x-raw-yuv",
+        "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+        "width", G_TYPE_INT, width,
+        "height", G_TYPE_INT, height,
+        "framerate", GST_TYPE_FRACTION, fps_num, fps_denom, NULL);
+
+    gst_pad_set_caps (smokedec->srcpad, caps);
+    gst_caps_unref (caps);
+  }
+
+
+  if (smokedec->need_keyframe) {
+    if (!(flags & SMOKECODEC_KEYFRAME))
+      goto keyframe_skip;
+
+    smokedec->need_keyframe = FALSE;
+  }
+
+  outbuf = gst_buffer_new ();
+  outsize = GST_BUFFER_SIZE (outbuf) = width * height + width * height / 2;
+  outdata = g_malloc (outsize);
+  GST_BUFFER_DATA (outbuf) = outdata;
+  GST_BUFFER_MALLOCDATA (outbuf) = outdata;
+
+  GST_BUFFER_DURATION (outbuf) = GST_SECOND * fps_denom / fps_num;
+  GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smokedec->srcpad));
+
+  if (time == GST_CLOCK_TIME_NONE) {
+    if (GST_BUFFER_OFFSET (buf) == -1) {
+      time = smokedec->next_time;
+    } else {
+      time = GST_BUFFER_OFFSET (buf) * GST_BUFFER_DURATION (outbuf);
+    }
+  }
+  GST_BUFFER_TIMESTAMP (outbuf) = time;
+  smokedec->next_time = time + GST_BUFFER_DURATION (outbuf);
+
+  smokeret = smokecodec_decode (smokedec->info, data, size, outdata);
+  if (smokeret != SMOKECODEC_OK)
+    goto decode_error;
+
+  GST_DEBUG_OBJECT (smokedec, "gst_smokedec_chain: sending buffer");
+  ret = gst_pad_push (smokedec->srcpad, outbuf);
+
+done:
+  gst_buffer_unref (buf);
+  gst_object_unref (smokedec);
+
+  return ret;
+
+  /* ERRORS */
+header_error:
+  {
+    GST_ELEMENT_ERROR (smokedec, STREAM, DECODE,
+        (NULL), ("Could not parse smoke header, reason: %d", smokeret));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+keyframe_skip:
+  {
+    GST_DEBUG_OBJECT (smokedec, "dropping buffer while waiting for keyframe");
+    ret = GST_FLOW_OK;
+    goto done;
+  }
+decode_error:
+  {
+    GST_ELEMENT_ERROR (smokedec, STREAM, DECODE,
+        (NULL), ("Could not decode smoke frame, reason: %d", smokeret));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstsmokedec.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,75 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_SMOKEDEC_H__
+#define __GST_SMOKEDEC_H__
+
+
+#include <gst/gst.h>
+#include "smokecodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SMOKEDEC \
+  (gst_smokedec_get_type())
+#define GST_SMOKEDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SMOKEDEC,GstSmokeDec))
+#define GST_SMOKEDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SMOKEDEC,GstSmokeDec))
+#define GST_IS_SMOKEDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SMOKEDEC))
+#define GST_IS_SMOKEDEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SMOKEDEC))
+
+typedef struct _GstSmokeDec GstSmokeDec;
+typedef struct _GstSmokeDecClass GstSmokeDecClass;
+
+struct _GstSmokeDec {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  /* video state */
+  gint format;
+  gint width;
+  gint height;
+  gint fps_num;
+  gint fps_denom;
+  GstClockTime next_time;
+
+  SmokeCodecInfo *info;
+
+  gint threshold;
+  gint quality;
+  gint smoothing;
+
+  gboolean need_keyframe;
+};
+
+struct _GstSmokeDecClass {
+  GstElementClass parent_class;
+};
+
+GType gst_smokedec_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_SMOKEDEC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstsmokeenc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,412 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+
+#include "gstsmokeenc.h"
+#include <gst/video/video.h>
+
+/* elementfactory information */
+static const GstElementDetails gst_smokeenc_details =
+GST_ELEMENT_DETAILS ("Smoke video encoder",
+    "Codec/Encoder/Video",
+    "Encode images into the Smoke format",
+    "Wim Taymans <wim@fluendo.com>");
+
+GST_DEBUG_CATEGORY (smokeenc_debug);
+#define GST_CAT_DEFAULT smokeenc_debug
+
+#define SMOKEENC_DEFAULT_MIN_QUALITY 10
+#define SMOKEENC_DEFAULT_MAX_QUALITY 85
+#define SMOKEENC_DEFAULT_THRESHOLD 3000
+#define SMOKEENC_DEFAULT_KEYFRAME 20
+
+/* SmokeEnc signals and args */
+enum
+{
+  FRAME_ENCODED,
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+  ARG_MIN_QUALITY,
+  ARG_MAX_QUALITY,
+  ARG_THRESHOLD,
+  ARG_KEYFRAME
+      /* FILL ME */
+};
+
+static void gst_smokeenc_base_init (gpointer g_class);
+static void gst_smokeenc_class_init (GstSmokeEnc * klass);
+static void gst_smokeenc_init (GstSmokeEnc * smokeenc);
+
+static GstFlowReturn gst_smokeenc_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_smokeenc_setcaps (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_smokeenc_getcaps (GstPad * pad);
+
+static void gst_smokeenc_resync (GstSmokeEnc * smokeenc);
+static void gst_smokeenc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_smokeenc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static GstElementClass *parent_class = NULL;
+
+//static guint gst_smokeenc_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_smokeenc_get_type (void)
+{
+  static GType smokeenc_type = 0;
+
+  if (!smokeenc_type) {
+    static const GTypeInfo smokeenc_info = {
+      sizeof (GstSmokeEncClass),
+      (GBaseInitFunc) gst_smokeenc_base_init,
+      NULL,
+      (GClassInitFunc) gst_smokeenc_class_init,
+      NULL,
+      NULL,
+      sizeof (GstSmokeEnc),
+      0,
+      (GInstanceInitFunc) gst_smokeenc_init,
+    };
+
+    smokeenc_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstSmokeEnc", &smokeenc_info,
+        0);
+  }
+  return smokeenc_type;
+}
+
+static GstStaticPadTemplate gst_smokeenc_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+    );
+
+static GstStaticPadTemplate gst_smokeenc_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-smoke, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0/1, MAX ]")
+    );
+
+static void
+gst_smokeenc_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_smokeenc_sink_pad_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_smokeenc_src_pad_template));
+  gst_element_class_set_details (element_class, &gst_smokeenc_details);
+}
+
+static void
+gst_smokeenc_class_init (GstSmokeEnc * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->set_property = gst_smokeenc_set_property;
+  gobject_class->get_property = gst_smokeenc_get_property;
+
+  g_object_class_install_property (gobject_class, ARG_MIN_QUALITY,
+      g_param_spec_int ("qmin", "Qmin", "Minimum quality",
+          0, 100, SMOKEENC_DEFAULT_MIN_QUALITY, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, ARG_MAX_QUALITY,
+      g_param_spec_int ("qmax", "Qmax", "Maximum quality",
+          0, 100, SMOKEENC_DEFAULT_MAX_QUALITY, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, ARG_THRESHOLD,
+      g_param_spec_int ("threshold", "Threshold", "Motion estimation threshold",
+          0, 100000000, SMOKEENC_DEFAULT_THRESHOLD, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, ARG_KEYFRAME,
+      g_param_spec_int ("keyframe", "Keyframe",
+          "Insert keyframe every N frames", 1, 100000,
+          SMOKEENC_DEFAULT_KEYFRAME, G_PARAM_READWRITE));
+
+  GST_DEBUG_CATEGORY_INIT (smokeenc_debug, "smokeenc", 0,
+      "Smoke encoding element");
+}
+
+static void
+gst_smokeenc_init (GstSmokeEnc * smokeenc)
+{
+  /* create the sink and src pads */
+  smokeenc->sinkpad =
+      gst_pad_new_from_static_template (&gst_smokeenc_sink_pad_template,
+      "sink");
+  gst_pad_set_chain_function (smokeenc->sinkpad, gst_smokeenc_chain);
+  gst_pad_set_getcaps_function (smokeenc->sinkpad, gst_smokeenc_getcaps);
+  gst_pad_set_setcaps_function (smokeenc->sinkpad, gst_smokeenc_setcaps);
+  gst_element_add_pad (GST_ELEMENT (smokeenc), smokeenc->sinkpad);
+
+  smokeenc->srcpad =
+      gst_pad_new_from_static_template (&gst_smokeenc_src_pad_template, "src");
+  gst_pad_set_getcaps_function (smokeenc->sinkpad, gst_smokeenc_getcaps);
+  gst_pad_use_fixed_caps (smokeenc->sinkpad);
+  /*gst_pad_set_link_function (smokeenc->sinkpad, gst_smokeenc_link); */
+  gst_element_add_pad (GST_ELEMENT (smokeenc), smokeenc->srcpad);
+
+  /* reset the initial video state */
+  smokeenc->width = 0;
+  smokeenc->height = 0;
+  smokeenc->frame = 0;
+  smokeenc->need_header = TRUE;
+
+  gst_smokeenc_resync (smokeenc);
+
+  smokeenc->min_quality = SMOKEENC_DEFAULT_MIN_QUALITY;
+  smokeenc->max_quality = SMOKEENC_DEFAULT_MAX_QUALITY;
+  smokeenc->threshold = SMOKEENC_DEFAULT_THRESHOLD;
+  smokeenc->keyframe = SMOKEENC_DEFAULT_KEYFRAME;
+}
+
+static GstCaps *
+gst_smokeenc_getcaps (GstPad * pad)
+{
+  GstSmokeEnc *smokeenc = GST_SMOKEENC (gst_pad_get_parent (pad));
+  GstPad *otherpad;
+  GstCaps *caps;
+  const char *name;
+  int i;
+  GstStructure *structure = NULL;
+
+  /* we want to proxy properties like width, height and framerate from the
+     other end of the element */
+  otherpad = (pad == smokeenc->srcpad) ? smokeenc->sinkpad : smokeenc->srcpad;
+  caps = gst_pad_get_allowed_caps (otherpad);
+  if (pad == smokeenc->srcpad) {
+    name = "image/x-smoke";
+  } else {
+    name = "video/x-raw-yuv";
+  }
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    structure = gst_caps_get_structure (caps, i);
+
+    gst_structure_set_name (structure, name);
+    gst_structure_remove_field (structure, "format");
+    /* ... but for the sink pad, we only do I420 anyway, so add that */
+    if (pad == smokeenc->sinkpad) {
+      gst_structure_set (structure, "format", GST_TYPE_FOURCC,
+          GST_STR_FOURCC ("I420"), NULL);
+    }
+  }
+
+  gst_object_unref (smokeenc);
+
+  return caps;
+}
+
+static gboolean
+gst_smokeenc_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstSmokeEnc *smokeenc = GST_SMOKEENC (gst_pad_get_parent (pad));
+  GstStructure *structure;
+  gboolean ret = TRUE;
+  GstCaps *othercaps;
+  GstPad *otherpad;
+  const GValue *framerate;
+
+  otherpad = (pad == smokeenc->srcpad) ? smokeenc->sinkpad : smokeenc->srcpad;
+
+  structure = gst_caps_get_structure (caps, 0);
+  framerate = gst_structure_get_value (structure, "framerate");
+  if (framerate) {
+    smokeenc->fps_num = gst_value_get_fraction_numerator (framerate);
+    smokeenc->fps_denom = gst_value_get_fraction_denominator (framerate);
+  } else {
+    smokeenc->fps_num = 0;
+    smokeenc->fps_denom = 1;
+  }
+
+  gst_structure_get_int (structure, "width", &smokeenc->width);
+  gst_structure_get_int (structure, "height", &smokeenc->height);
+
+  othercaps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
+  gst_caps_set_simple (othercaps,
+      "width", G_TYPE_INT, smokeenc->width,
+      "height", G_TYPE_INT, smokeenc->height,
+      "framerate", GST_TYPE_FRACTION, smokeenc->fps_num, smokeenc->fps_denom,
+      NULL);
+
+  ret = gst_pad_set_caps (smokeenc->srcpad, othercaps);
+  gst_caps_unref (othercaps);
+
+  if (GST_PAD_LINK_SUCCESSFUL (ret)) {
+    gst_smokeenc_resync (smokeenc);
+  }
+
+  gst_object_unref (smokeenc);
+
+  return ret;
+}
+
+static void
+gst_smokeenc_resync (GstSmokeEnc * smokeenc)
+{
+  GST_DEBUG ("gst_smokeenc_resync: resync");
+
+  smokecodec_encode_new (&smokeenc->info, smokeenc->width, smokeenc->height,
+      smokeenc->fps_num, smokeenc->fps_denom);
+  smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
+      smokeenc->max_quality);
+
+  GST_DEBUG ("gst_smokeenc_resync: resync done");
+}
+
+static GstFlowReturn
+gst_smokeenc_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstSmokeEnc *smokeenc;
+  guchar *data, *outdata;
+  gulong size;
+  gint outsize;
+  guint encsize;
+  GstBuffer *outbuf;
+  SmokeCodecFlags flags;
+  GstFlowReturn ret;
+
+  smokeenc = GST_SMOKEENC (GST_OBJECT_PARENT (pad));
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  GST_DEBUG ("gst_smokeenc_chain: got buffer of %ld bytes in '%s'", size,
+      GST_OBJECT_NAME (smokeenc));
+
+  if (smokeenc->need_header) {
+    outbuf = gst_buffer_new ();
+    outsize = 256;
+    outdata = g_malloc (outsize);
+    GST_BUFFER_DATA (outbuf) = outdata;
+    GST_BUFFER_MALLOCDATA (outbuf) = outdata;
+    GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
+    GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
+
+    smokecodec_encode_id (smokeenc->info, outdata, &encsize);
+
+    GST_BUFFER_SIZE (outbuf) = encsize;
+
+    ret = gst_pad_push (smokeenc->srcpad, outbuf);
+
+    smokeenc->need_header = FALSE;
+  }
+
+  outbuf = gst_buffer_new ();
+  outsize = smokeenc->width * smokeenc->height * 3;
+  outdata = g_malloc (outsize);
+  GST_BUFFER_DATA (outbuf) = outdata;
+  GST_BUFFER_MALLOCDATA (outbuf) = outdata;
+  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
+  GST_BUFFER_DURATION (outbuf) =
+      smokeenc->fps_denom * GST_SECOND / smokeenc->fps_num;
+
+  flags = 0;
+  if ((smokeenc->frame % smokeenc->keyframe) == 0) {
+    flags |= SMOKECODEC_KEYFRAME;
+  }
+  smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
+      smokeenc->max_quality);
+  smokecodec_set_threshold (smokeenc->info, smokeenc->threshold);
+  smokecodec_encode (smokeenc->info, data, flags, outdata, &encsize);
+  gst_buffer_unref (buf);
+
+  GST_BUFFER_SIZE (outbuf) = encsize;
+  GST_BUFFER_OFFSET (outbuf) = smokeenc->frame;
+  GST_BUFFER_OFFSET_END (outbuf) = smokeenc->frame + 1;
+
+  ret = gst_pad_push (smokeenc->srcpad, outbuf);
+
+  smokeenc->frame++;
+
+  return ret;
+}
+
+static void
+gst_smokeenc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSmokeEnc *smokeenc;
+
+  g_return_if_fail (GST_IS_SMOKEENC (object));
+  smokeenc = GST_SMOKEENC (object);
+
+  switch (prop_id) {
+    case ARG_MIN_QUALITY:
+      smokeenc->min_quality = g_value_get_int (value);
+      break;
+    case ARG_MAX_QUALITY:
+      smokeenc->max_quality = g_value_get_int (value);
+      break;
+    case ARG_THRESHOLD:
+      smokeenc->threshold = g_value_get_int (value);
+      break;
+    case ARG_KEYFRAME:
+      smokeenc->keyframe = g_value_get_int (value);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_smokeenc_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstSmokeEnc *smokeenc;
+
+  g_return_if_fail (GST_IS_SMOKEENC (object));
+  smokeenc = GST_SMOKEENC (object);
+
+  switch (prop_id) {
+    case ARG_MIN_QUALITY:
+      g_value_set_int (value, smokeenc->min_quality);
+      break;
+    case ARG_MAX_QUALITY:
+      g_value_set_int (value, smokeenc->max_quality);
+      break;
+    case ARG_THRESHOLD:
+      g_value_set_int (value, smokeenc->threshold);
+      break;
+    case ARG_KEYFRAME:
+      g_value_set_int (value, smokeenc->keyframe);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/gstsmokeenc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,75 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_SMOKEENC_H__
+#define __GST_SMOKEENC_H__
+
+
+#include <gst/gst.h>
+#include "smokecodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SMOKEENC \
+  (gst_smokeenc_get_type())
+#define GST_SMOKEENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SMOKEENC,GstSmokeEnc))
+#define GST_SMOKEENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SMOKEENC,GstSmokeEnc))
+#define GST_IS_SMOKEENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SMOKEENC))
+#define GST_IS_SMOKEENC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SMOKEENC))
+
+typedef struct _GstSmokeEnc GstSmokeEnc;
+typedef struct _GstSmokeEncClass GstSmokeEncClass;
+
+struct _GstSmokeEnc {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  /* video state */
+  gint format;
+  gint width;
+  gint height;
+  gint frame;
+  gint keyframe;
+  gint fps_num, fps_denom;
+
+  SmokeCodecInfo *info;
+
+  gint threshold;
+  gint min_quality;
+  gint max_quality;
+
+  gboolean need_header;
+};
+
+struct _GstSmokeEncClass {
+  GstElementClass parent_class;
+};
+
+GType gst_smokeenc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_SMOKEENC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/smokecodec.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,715 @@
+/* Smoke codec
+ * Copyright (C) <2004> Wim Taymans <wim@fluendo.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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/* this is a hack hack hack to get around jpeglib header bugs... */
+#ifdef HAVE_STDLIB_H
+# undef HAVE_STDLIB_H
+#endif
+#include <jpeglib.h>
+
+#include "smokecodec.h"
+#include "smokeformat.h"
+
+#ifdef SYMBIAN
+#define DEBUG(a...)   printf( a );
+#else // SYMBIAN
+#ifndef WIN32
+//#define DEBUG(a...)   printf( a );
+#define DEBUG(a,...)
+#else
+#include <gst/gstinfo.h>
+#define DEBUG GST_DEBUG
+#endif
+#endif // SYMBIAN
+
+
+struct _SmokeCodecInfo
+{
+  unsigned int width;
+  unsigned int height;
+  unsigned int fps_num;
+  unsigned int fps_denom;
+
+  unsigned int minquality;
+  unsigned int maxquality;
+  unsigned int bitrate;
+  unsigned int threshold;
+
+  unsigned int refdec;
+
+  unsigned char **line[3];
+  unsigned char *compbuf[3];
+
+  struct jpeg_error_mgr jerr;
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_destination_mgr jdest;
+
+  struct jpeg_decompress_struct dinfo;
+  struct jpeg_source_mgr jsrc;
+
+  int need_keyframe;
+  unsigned char *reference;
+};
+
+static void
+smokecodec_init_destination (j_compress_ptr cinfo)
+{
+}
+
+static int
+smokecodec_flush_destination (j_compress_ptr cinfo)
+{
+  return 1;
+}
+
+static void
+smokecodec_term_destination (j_compress_ptr cinfo)
+{
+}
+
+static void
+smokecodec_init_source (j_decompress_ptr cinfo)
+{
+}
+
+static int
+smokecodec_fill_input_buffer (j_decompress_ptr cinfo)
+{
+  return 1;
+}
+
+static void
+smokecodec_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+}
+
+static int
+smokecodec_resync_to_restart (j_decompress_ptr cinfo, int desired)
+{
+  return 1;
+}
+
+static void
+smokecodec_term_source (j_decompress_ptr cinfo)
+{
+}
+
+
+int
+smokecodec_encode_new (SmokeCodecInfo ** info,
+    const unsigned int width,
+    const unsigned int height,
+    const unsigned int fps_num, const unsigned int fps_denom)
+{
+  SmokeCodecInfo *newinfo;
+  int i, j;
+  unsigned char *base[3];
+
+  if (!info)
+    return SMOKECODEC_NULLPTR;
+  if ((width & 0xf) || (height & 0xf))
+    return SMOKECODEC_WRONGSIZE;
+
+  newinfo = malloc (sizeof (SmokeCodecInfo));
+  if (!newinfo) {
+    return SMOKECODEC_NOMEM;
+  }
+  newinfo->width = width;
+  newinfo->height = height;
+  newinfo->fps_num = fps_num;
+  newinfo->fps_denom = fps_denom;
+
+  /* setup jpeglib */
+  memset (&newinfo->cinfo, 0, sizeof (newinfo->cinfo));
+  memset (&newinfo->jerr, 0, sizeof (newinfo->jerr));
+  newinfo->cinfo.err = jpeg_std_error (&newinfo->jerr);
+  jpeg_create_compress (&newinfo->cinfo);
+  newinfo->cinfo.input_components = 3;
+  jpeg_set_defaults (&newinfo->cinfo);
+
+  newinfo->cinfo.dct_method = JDCT_FASTEST;
+
+  newinfo->cinfo.raw_data_in = TRUE;
+  newinfo->cinfo.in_color_space = JCS_YCbCr;
+  newinfo->cinfo.comp_info[0].h_samp_factor = 2;
+  newinfo->cinfo.comp_info[0].v_samp_factor = 2;
+  newinfo->cinfo.comp_info[1].h_samp_factor = 1;
+  newinfo->cinfo.comp_info[1].v_samp_factor = 1;
+  newinfo->cinfo.comp_info[2].h_samp_factor = 1;
+  newinfo->cinfo.comp_info[2].v_samp_factor = 1;
+
+  newinfo->line[0] = malloc (DCTSIZE * 2 * sizeof (char *));
+  newinfo->line[1] = malloc (DCTSIZE * sizeof (char *));
+  newinfo->line[2] = malloc (DCTSIZE * sizeof (char *));
+  base[0] = newinfo->compbuf[0] = malloc (256 * 2 * DCTSIZE * 2 * DCTSIZE);
+  base[1] = newinfo->compbuf[1] = malloc (256 * DCTSIZE * DCTSIZE);
+  base[2] = newinfo->compbuf[2] = malloc (256 * DCTSIZE * DCTSIZE);
+
+  for (i = 0, j = 0; i < 2 * DCTSIZE; i += 2, j++) {
+    newinfo->line[0][i] = base[0];
+    base[0] += 2 * DCTSIZE * 256;
+    newinfo->line[0][i + 1] = base[0];
+    base[0] += 2 * DCTSIZE * 256;
+    newinfo->line[1][j] = base[1];
+    base[1] += DCTSIZE * 256;
+    newinfo->line[2][j] = base[2];
+    base[2] += DCTSIZE * 256;
+  }
+
+  newinfo->jdest.init_destination = smokecodec_init_destination;
+  newinfo->jdest.empty_output_buffer = smokecodec_flush_destination;
+  newinfo->jdest.term_destination = smokecodec_term_destination;
+  newinfo->cinfo.dest = &newinfo->jdest;
+
+  jpeg_suppress_tables (&newinfo->cinfo, FALSE);
+
+  memset (&newinfo->dinfo, 0, sizeof (newinfo->dinfo));
+  newinfo->dinfo.err = jpeg_std_error (&newinfo->jerr);
+  jpeg_create_decompress (&newinfo->dinfo);
+
+  newinfo->jsrc.init_source = smokecodec_init_source;
+  newinfo->jsrc.fill_input_buffer = smokecodec_fill_input_buffer;
+  newinfo->jsrc.skip_input_data = smokecodec_skip_input_data;
+  newinfo->jsrc.resync_to_restart = smokecodec_resync_to_restart;
+  newinfo->jsrc.term_source = smokecodec_term_source;
+  newinfo->dinfo.src = &newinfo->jsrc;
+
+  newinfo->need_keyframe = 1;
+  newinfo->threshold = 4000;
+  newinfo->minquality = 10;
+  newinfo->maxquality = 85;
+  newinfo->reference = malloc (3 * (width * height) / 2);
+  newinfo->refdec = 0;
+
+  *info = newinfo;
+
+  return SMOKECODEC_OK;
+}
+
+int
+smokecodec_decode_new (SmokeCodecInfo ** info)
+{
+  return smokecodec_encode_new (info, 16, 16, 1, 1);
+}
+
+int
+smokecodec_info_free (SmokeCodecInfo * info)
+{
+  free (info->line[0]);
+  free (info->line[1]);
+  free (info->line[2]);
+  free (info->compbuf[0]);
+  free (info->compbuf[1]);
+  free (info->compbuf[2]);
+  free (info->reference);
+  jpeg_destroy_compress (&info->cinfo);
+  jpeg_destroy_decompress (&info->dinfo);
+  free (info);
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_set_quality (SmokeCodecInfo * info,
+    const unsigned int min, const unsigned int max)
+{
+  info->minquality = min;
+  info->maxquality = max;
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_get_quality (SmokeCodecInfo * info,
+    unsigned int *min, unsigned int *max)
+{
+  *min = info->minquality;
+  *max = info->maxquality;
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_set_threshold (SmokeCodecInfo * info, const unsigned int threshold)
+{
+  info->threshold = threshold;
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_get_threshold (SmokeCodecInfo * info, unsigned int *threshold)
+{
+  *threshold = info->threshold;
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_set_bitrate (SmokeCodecInfo * info, const unsigned int bitrate)
+{
+  info->bitrate = bitrate;
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_get_bitrate (SmokeCodecInfo * info, unsigned int *bitrate)
+{
+  *bitrate = info->bitrate;
+
+  return SMOKECODEC_OK;
+}
+
+static void
+find_best_size (int blocks, unsigned int *width, unsigned int *height)
+{
+  int sqchng;
+  int w, h;
+  int best, bestw;
+  int free;
+
+  sqchng = ceil (sqrt (blocks));
+  w = sqchng;
+  h = sqchng;
+
+  DEBUG ("guess: %d %d\n", w, h);
+
+  free = w * h - blocks;
+  best = free;
+  bestw = w;
+
+  while (w < 256) {
+    DEBUG ("current: %d %d\n", w, h);
+    if (free < best) {
+      best = free;
+      bestw = w;
+      if (free == 0)
+        break;
+    }
+    // if we cannot reduce the height, increase width
+    if (free < w) {
+      w++;
+      free += h;
+    }
+    // reduce height while possible
+    while (free >= w) {
+      h--;
+      free -= w;
+    }
+  }
+  *width = bestw;
+  *height = (blocks + best) / bestw;
+}
+
+static int
+abs_diff (const unsigned char *in1, const unsigned char *in2, const int stride)
+{
+  int s;
+  int i, j, diff;
+
+  s = 0;
+
+  for (i = 0; i < 2 * DCTSIZE; i++) {
+    for (j = 0; j < 2 * DCTSIZE; j++) {
+      diff = in1[j] - in2[j];
+      s += diff * diff;
+    }
+    in1 += stride;
+    in2 += stride;
+  }
+  return s;
+}
+
+static void
+put (const unsigned char *src, unsigned char *dest,
+    int width, int height, int srcstride, int deststride)
+{
+  int i, j;
+
+  for (i = 0; i < height; i++) {
+    for (j = 0; j < width; j++) {
+      dest[j] = src[j];
+    }
+    src += srcstride;
+    dest += deststride;
+  }
+}
+
+/* encoding */
+SmokeCodecResult
+smokecodec_encode_id (SmokeCodecInfo * info,
+    unsigned char *out, unsigned int *outsize)
+{
+  int i;
+
+  *out++ = SMOKECODEC_TYPE_ID;
+  for (i = 0; i < strlen (SMOKECODEC_ID_STRING); i++) {
+    *out++ = SMOKECODEC_ID_STRING[i];
+  }
+  *out++ = 0;
+  *out++ = 1;
+  *out++ = 0;
+
+  *outsize = 9;
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_encode (SmokeCodecInfo * info,
+    const unsigned char *in,
+    SmokeCodecFlags flags, unsigned char *out, unsigned int *outsize)
+{
+  unsigned int i, j, s;
+  const unsigned char *ip;
+  unsigned char *op;
+  unsigned int blocks, encoding;
+  unsigned int size;
+  unsigned int width, height;
+  unsigned int blocks_w, blocks_h;
+  unsigned int threshold;
+  unsigned int max;
+
+  if (info->need_keyframe) {
+    flags |= SMOKECODEC_KEYFRAME;
+    info->need_keyframe = 0;
+  }
+
+  if (flags & SMOKECODEC_KEYFRAME)
+    threshold = 0;
+  else
+    threshold = info->threshold;
+
+  ip = in;
+  op = info->reference;
+
+  width = info->width;
+  height = info->height;
+
+  blocks_w = width / (DCTSIZE * 2);
+  blocks_h = height / (DCTSIZE * 2);
+
+  max = blocks_w * blocks_h;
+
+  out[IDX_TYPE] = SMOKECODEC_TYPE_DATA;
+
+#define STORE16(var, pos, x) \
+   var[pos]   = (x >> 8); \
+   var[pos+1] = (x & 0xff);
+#define STORE32(var, pos, x) \
+   var[pos]   = ((x >> 24) & 0xff); \
+   var[pos+1] = ((x >> 16) & 0xff); \
+   var[pos+2] = ((x >> 8) & 0xff); \
+   var[pos+3] =  (x & 0xff);
+
+  /* write dimension */
+  STORE16 (out, IDX_WIDTH, width);
+  STORE16 (out, IDX_HEIGHT, height);
+
+  /* write framerate */
+  STORE32 (out, IDX_FPS_NUM, info->fps_num);
+  STORE32 (out, IDX_FPS_DENOM, info->fps_denom);
+
+  if (!(flags & SMOKECODEC_KEYFRAME)) {
+    int block = 0;
+
+    blocks = 0;
+    for (i = 0; i < height; i += 2 * DCTSIZE) {
+      for (j = 0; j < width; j += 2 * DCTSIZE) {
+        s = abs_diff (ip, op, width);
+        if (s >= threshold) {
+          STORE16 (out, blocks * 2 + IDX_BLOCKS, block);
+          blocks++;
+        }
+
+        ip += 2 * DCTSIZE;
+        op += 2 * DCTSIZE;
+        block++;
+      }
+      ip += (2 * DCTSIZE - 1) * width;
+      op += (2 * DCTSIZE - 1) * width;
+    }
+    if (blocks == max) {
+      flags |= SMOKECODEC_KEYFRAME;
+      blocks = 0;
+      encoding = max;
+    } else {
+      encoding = blocks;
+    }
+  } else {
+    blocks = 0;
+    encoding = max;
+  }
+  STORE16 (out, IDX_NUM_BLOCKS, blocks);
+  out[IDX_FLAGS] = (flags & 0xff);
+
+  DEBUG ("blocks %d, encoding %d\n", blocks, encoding);
+
+  info->jdest.next_output_byte = &out[blocks * 2 + OFFS_PICT];
+  info->jdest.free_in_buffer = (*outsize) - OFFS_PICT;
+
+  if (encoding > 0) {
+    int quality;
+
+    if (!(flags & SMOKECODEC_KEYFRAME))
+      find_best_size (encoding, &blocks_w, &blocks_h);
+
+    DEBUG ("best: %d %d\n", blocks_w, blocks_h);
+
+    info->cinfo.image_width = blocks_w * DCTSIZE * 2;
+    info->cinfo.image_height = blocks_h * DCTSIZE * 2;
+
+    if (flags & SMOKECODEC_KEYFRAME) {
+      quality = (info->maxquality * 60) / 100;
+    } else {
+      quality =
+          info->maxquality - ((info->maxquality -
+              info->minquality) * blocks) / max;
+    }
+
+    DEBUG ("set q %d %d %d\n", quality, encoding, max);
+    jpeg_set_quality (&info->cinfo, quality, TRUE);
+    DEBUG ("start\n");
+    jpeg_start_compress (&info->cinfo, TRUE);
+
+    for (i = 0; i < encoding; i++) {
+      int pos;
+      int x, y;
+
+      if (flags & SMOKECODEC_KEYFRAME)
+        pos = i;
+      else
+        pos = (out[i * 2 + IDX_BLOCKS] << 8) | (out[i * 2 + IDX_BLOCKS + 1]);
+
+      x = pos % (width / (DCTSIZE * 2));
+      y = pos / (width / (DCTSIZE * 2));
+
+      ip = in + (x * (DCTSIZE * 2)) + (y * (DCTSIZE * 2) * width);
+      op = info->compbuf[0] + (i % blocks_w) * (DCTSIZE * 2);
+      put (ip, op, 2 * DCTSIZE, 2 * DCTSIZE, width, 256 * (DCTSIZE * 2));
+
+      ip = in + width * height + (x * DCTSIZE) + (y * DCTSIZE * width / 2);
+      op = info->compbuf[1] + (i % blocks_w) * (DCTSIZE);
+      put (ip, op, DCTSIZE, DCTSIZE, width / 2, 256 * DCTSIZE);
+
+      ip = in + 5 * (width * height) / 4 + (x * DCTSIZE) +
+          (y * DCTSIZE * width / 2);
+      op = info->compbuf[2] + (i % blocks_w) * (DCTSIZE);
+      put (ip, op, DCTSIZE, DCTSIZE, width / 2, 256 * DCTSIZE);
+
+      if ((i % blocks_w) == (blocks_w - 1) || (i == encoding - 1)) {
+        DEBUG ("write %d\n", pos);
+        jpeg_write_raw_data (&info->cinfo, info->line, 2 * DCTSIZE);
+      }
+    }
+    DEBUG ("finish\n");
+    jpeg_finish_compress (&info->cinfo);
+  }
+
+  size = ((((*outsize) - OFFS_PICT - info->jdest.free_in_buffer) + 3) & ~3);
+  STORE16 (out, IDX_SIZE, size);
+
+  *outsize = size + blocks * 2 + OFFS_PICT;
+  DEBUG ("outsize %d\n", *outsize);
+
+  // and decode in reference frame again
+  if (info->refdec) {
+    smokecodec_decode (info, out, *outsize, info->reference);
+  } else {
+    memcpy (info->reference, in, 3 * (width * height) / 2);
+  }
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_parse_id (SmokeCodecInfo * info,
+    const unsigned char *in, const unsigned int insize)
+{
+  int i;
+
+  if (insize < 4 + strlen (SMOKECODEC_ID_STRING)) {
+    return SMOKECODEC_WRONGVERSION;
+  }
+
+  if (*in++ != SMOKECODEC_TYPE_ID)
+    return SMOKECODEC_ERROR;
+
+  for (i = 0; i < strlen (SMOKECODEC_ID_STRING); i++) {
+    if (*in++ != SMOKECODEC_ID_STRING[i])
+      return SMOKECODEC_ERROR;
+  }
+  if (*in++ != 0 || *in++ != 1 || *in++ != 0)
+    return SMOKECODEC_ERROR;
+
+  return SMOKECODEC_OK;
+}
+
+#define READ16(var, pos, x) \
+ x = var[pos]<<8 | var[pos+1];
+
+#define READ32(var, pos, x) \
+ x = var[pos]<<24 | var[pos+1]<<16 | \
+     var[pos+2]<<8 | var[pos+3];
+
+/* decoding */
+SmokeCodecResult
+smokecodec_parse_header (SmokeCodecInfo * info,
+    const unsigned char *in,
+    const unsigned int insize,
+    SmokeCodecFlags * flags,
+    unsigned int *width,
+    unsigned int *height, unsigned int *fps_num, unsigned int *fps_denom)
+{
+
+  READ16 (in, IDX_WIDTH, *width);
+  READ16 (in, IDX_HEIGHT, *height);
+  *flags = in[IDX_FLAGS];
+  READ32 (in, IDX_FPS_NUM, *fps_num);
+  READ32 (in, IDX_FPS_DENOM, *fps_denom);
+
+  if (info->width != *width ||
+      info->height != *height ||
+      info->fps_num != *fps_num || info->fps_denom != *fps_denom) {
+    DEBUG ("new width: %d %d\n", *width, *height);
+
+    info->reference = realloc (info->reference, 3 * ((*width) * (*height)) / 2);
+    info->width = *width;
+    info->height = *height;
+    info->fps_num = *fps_num;
+    info->fps_denom = *fps_denom;
+  }
+
+  return SMOKECODEC_OK;
+}
+
+SmokeCodecResult
+smokecodec_decode (SmokeCodecInfo * info,
+    const unsigned char *in, const unsigned int insize, unsigned char *out)
+{
+  unsigned int width, height;
+  unsigned int fps_num, fps_denom;
+  SmokeCodecFlags flags;
+  int i, j;
+  int blocks_w, blocks_h;
+  int blockptr;
+  int blocks, decoding;
+  const unsigned char *ip;
+  unsigned char *op;
+  int res;
+
+  smokecodec_parse_header (info, in, insize, &flags, &width, &height,
+      &fps_num, &fps_denom);
+
+  READ16 (in, IDX_NUM_BLOCKS, blocks);
+  DEBUG ("blocks %d\n", blocks);
+
+  if (flags & SMOKECODEC_KEYFRAME)
+    decoding = width / (DCTSIZE * 2) * height / (DCTSIZE * 2);
+  else
+    decoding = blocks;
+
+  if (decoding > 0) {
+    info->jsrc.next_input_byte = &in[blocks * 2 + OFFS_PICT];
+    info->jsrc.bytes_in_buffer = insize - (blocks * 2 + OFFS_PICT);
+
+    DEBUG ("header %02x %d\n", in[blocks * 2 + OFFS_PICT], insize);
+    res = jpeg_read_header (&info->dinfo, TRUE);
+    DEBUG ("header %d %d %d\n", res, info->dinfo.image_width,
+        info->dinfo.image_height);
+
+    blocks_w = info->dinfo.image_width / (2 * DCTSIZE);
+    blocks_h = info->dinfo.image_height / (2 * DCTSIZE);
+
+    info->dinfo.output_width = info->dinfo.image_width;
+    info->dinfo.output_height = info->dinfo.image_height;
+
+    DEBUG ("start\n");
+    info->dinfo.do_fancy_upsampling = FALSE;
+    info->dinfo.do_block_smoothing = FALSE;
+    info->dinfo.out_color_space = JCS_YCbCr;
+    info->dinfo.dct_method = JDCT_IFAST;
+    info->dinfo.raw_data_out = TRUE;
+    jpeg_start_decompress (&info->dinfo);
+
+    blockptr = 0;
+
+    for (i = 0; i < blocks_h; i++) {
+      DEBUG ("read\n");
+      jpeg_read_raw_data (&info->dinfo, info->line, 2 * DCTSIZE);
+
+      DEBUG ("copy %d\n", blocks_w);
+      for (j = 0; j < blocks_w; j++) {
+        int pos;
+        int x, y;
+
+        if (flags & SMOKECODEC_KEYFRAME)
+          pos = blockptr;
+        else
+          READ16 (in, blockptr * 2 + IDX_BLOCKS, pos);
+
+        x = pos % (width / (DCTSIZE * 2));
+        y = pos / (width / (DCTSIZE * 2));
+
+        DEBUG ("block %d %d %d\n", pos, x, y);
+
+        ip = info->compbuf[0] + j * (DCTSIZE * 2);
+        op = info->reference + (x * (DCTSIZE * 2)) +
+            (y * (DCTSIZE * 2) * width);
+        put (ip, op, 2 * DCTSIZE, 2 * DCTSIZE, 256 * (DCTSIZE * 2), width);
+
+        ip = info->compbuf[1] + j * (DCTSIZE);
+        op = info->reference + width * height + (x * DCTSIZE) +
+            (y * DCTSIZE * width / 2);
+        put (ip, op, DCTSIZE, DCTSIZE, 256 * DCTSIZE, width / 2);
+
+        ip = info->compbuf[2] + j * (DCTSIZE);
+        op = info->reference + 5 * (width * height) / 4 + (x * DCTSIZE) +
+            (y * DCTSIZE * width / 2);
+        put (ip, op, DCTSIZE, DCTSIZE, 256 * DCTSIZE, width / 2);
+
+        DEBUG ("block done %d %d %d\n", pos, x, y);
+        blockptr++;
+        if (blockptr >= decoding)
+          break;
+      }
+    }
+    DEBUG ("finish\n");
+    jpeg_finish_decompress (&info->dinfo);
+  }
+
+  DEBUG ("copy\n");
+  if (out != info->reference)
+    memcpy (out, info->reference, 3 * (width * height) / 2);
+  DEBUG ("copy done\n");
+
+  return SMOKECODEC_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/smokecodec.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,119 @@
+/* Smoke Codec
+ * Copyright (C) <2004> Wim Taymans <wim@fluendo.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 __SMOKECODEC_H__
+#define __SMOKECODEC_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _SmokeCodecInfo SmokeCodecInfo;
+
+typedef enum {
+  SMOKECODEC_WRONGVERSION       = -5,
+  SMOKECODEC_WRONGSIZE          = -4,
+  SMOKECODEC_ERROR              = -3,
+  SMOKECODEC_NOMEM              = -2,
+  SMOKECODEC_NULLPTR            = -1,
+  SMOKECODEC_OK                 =  0 
+} SmokeCodecResult;
+        
+typedef enum {
+  SMOKECODEC_KEYFRAME           = (1<<0),
+  SMOKECODEC_MOTION_VECTORS     = (1<<1)
+} SmokeCodecFlags;
+        
+#define SMOKECODEC_ID_STRING "smoke"
+
+typedef enum {
+  SMOKECODEC_TYPE_ID            = 0x80,
+  SMOKECODEC_TYPE_COMMENT       = 0x81,
+  SMOKECODEC_TYPE_EXTRA         = 0x83,
+  SMOKECODEC_TYPE_DATA          = 0x40 
+} SmokePacketType;
+
+/* init */
+int                     smokecodec_encode_new   (SmokeCodecInfo **info,
+                                                 const unsigned int width,
+                                                 const unsigned int height,
+                                                 const unsigned int fps_num,
+                                                 const unsigned int fps_denom);
+
+int                     smokecodec_decode_new   (SmokeCodecInfo **info);
+
+int                     smokecodec_info_free    (SmokeCodecInfo * info);
+
+/* config */
+SmokeCodecResult        smokecodec_set_quality  (SmokeCodecInfo *info,
+                                                 const unsigned int min,
+                                                 const unsigned int max);
+SmokeCodecResult        smokecodec_get_quality  (SmokeCodecInfo *info,
+                                                 unsigned int *min,
+                                                 unsigned int *max);
+
+SmokeCodecResult        smokecodec_set_threshold (SmokeCodecInfo *info,
+                                                 const unsigned int threshold);
+SmokeCodecResult        smokecodec_get_threshold (SmokeCodecInfo *info,
+                                                 unsigned int *threshold);
+
+SmokeCodecResult        smokecodec_set_bitrate  (SmokeCodecInfo *info,
+                                                 const unsigned int bitrate);
+SmokeCodecResult        smokecodec_get_bitrate  (SmokeCodecInfo *info,
+                                                 unsigned int *bitrate);
+
+/* encoding */
+SmokeCodecResult        smokecodec_encode_id    (SmokeCodecInfo *info,
+                                                 unsigned char *out,
+                                                 unsigned int *outsize);
+
+SmokeCodecResult        smokecodec_encode       (SmokeCodecInfo *info,
+                                                 const unsigned char *in,
+                                                 SmokeCodecFlags flags,
+                                                 unsigned char *out,
+                                                 unsigned int *outsize);
+
+/* decoding */
+SmokeCodecResult        smokecodec_parse_id     (SmokeCodecInfo *info,
+                                                 const unsigned char *in,
+                                                 const unsigned int insize);
+
+SmokeCodecResult        smokecodec_parse_header (SmokeCodecInfo *info,
+                                                 const unsigned char *in,
+                                                 const unsigned int insize,
+                                                 SmokeCodecFlags *flags,
+                                                 unsigned int *width,
+                                                 unsigned int *height,
+                                                 unsigned int *fps_num,
+                                                 unsigned int *fps_denom);
+
+SmokeCodecResult        smokecodec_decode       (SmokeCodecInfo *info,
+                                                 const unsigned char *in,
+                                                 const unsigned int insize,
+                                                 unsigned char *out);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __SMOKECODEC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/jpeg/smokeformat.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,46 @@
+/* Smoke Codec
+ * Copyright (C) <2004> Wim Taymans <wim@fluendo.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 __SMOKEFORMAT_H__
+#define __SMOKEFORMAT_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define IDX_TYPE        0
+#define IDX_WIDTH       1
+#define IDX_HEIGHT      3
+#define IDX_FPS_NUM     5
+#define IDX_FPS_DENOM   9
+#define IDX_FLAGS       13
+#define IDX_NUM_BLOCKS  14
+#define IDX_SIZE        16
+#define IDX_BLOCKS      18
+#define OFFS_PICT       18
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __SMOKEFORMAT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/libpng/gstpng.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,54 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * Filter:
+ * Copyright (C) 2000 Donald A. Graft
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gst/gst.h>
+
+#include "gstpngdec.h"
+#include "gstpngenc.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "pngdec", GST_RANK_PRIMARY,
+          GST_TYPE_PNGDEC))
+    return FALSE;
+
+  if (!gst_element_register (plugin, "pngenc", GST_RANK_PRIMARY,
+          GST_TYPE_PNGENC))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "png",
+    "PNG plugin library", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
+    GST_PACKAGE_ORIGIN)
+
+#ifdef __SYMBIAN32__
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+    return &gst_plugin_desc;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/libpng/gstpngdec.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,881 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ *
+ */
+/**
+ * SECTION:element-pngdec
+ *
+ * Decodes png images. If there is no framerate set on sink caps, it sends EOS
+ * after the first picture.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstpngdec.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <gst/video/video.h>
+#include <gst/gst-i18n-plugin.h>
+
+static const GstElementDetails gst_pngdec_details =
+GST_ELEMENT_DETAILS ("PNG image decoder",
+    "Codec/Decoder/Image",
+    "Decode a png video frame to a raw image",
+    "Wim Taymans <wim@fluendo.com>");
+
+GST_DEBUG_CATEGORY_STATIC (pngdec_debug);
+#define GST_CAT_DEFAULT pngdec_debug
+
+static void gst_pngdec_base_init (gpointer g_class);
+static void gst_pngdec_class_init (GstPngDecClass * klass);
+static void gst_pngdec_init (GstPngDec * pngdec);
+
+static gboolean gst_pngdec_libpng_init (GstPngDec * pngdec);
+static gboolean gst_pngdec_libpng_clear (GstPngDec * pngdec);
+
+static GstStateChangeReturn gst_pngdec_change_state (GstElement * element,
+    GstStateChange transition);
+
+static gboolean gst_pngdec_sink_activate_push (GstPad * sinkpad,
+    gboolean active);
+static gboolean gst_pngdec_sink_activate_pull (GstPad * sinkpad,
+    gboolean active);
+static gboolean gst_pngdec_sink_activate (GstPad * sinkpad);
+
+static GstFlowReturn gst_pngdec_caps_create_and_set (GstPngDec * pngdec);
+
+static void gst_pngdec_task (GstPad * pad);
+static GstFlowReturn gst_pngdec_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_pngdec_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_pngdec_sink_setcaps (GstPad * pad, GstCaps * caps);
+
+static GstElementClass *parent_class = NULL;
+
+GType
+gst_pngdec_get_type (void)
+{
+  static GType pngdec_type = 0;
+
+  if (!pngdec_type) {
+    static const GTypeInfo pngdec_info = {
+      sizeof (GstPngDecClass),
+      gst_pngdec_base_init,
+      NULL,
+      (GClassInitFunc) gst_pngdec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstPngDec),
+      0,
+      (GInstanceInitFunc) gst_pngdec_init,
+    };
+
+    pngdec_type = g_type_register_static (GST_TYPE_ELEMENT, "GstPngDec",
+        &pngdec_info, 0);
+  }
+  return pngdec_type;
+}
+
+static GstStaticPadTemplate gst_pngdec_src_pad_template =
+    GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_RGB)
+    );
+
+static GstStaticPadTemplate gst_pngdec_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("image/png")
+    );
+
+static void
+gst_pngdec_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_pngdec_src_pad_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_pngdec_sink_pad_template));
+  gst_element_class_set_details (element_class, &gst_pngdec_details);
+}
+
+static void
+gst_pngdec_class_init (GstPngDecClass * klass)
+{
+  GstElementClass *gstelement_class;
+
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gstelement_class->change_state = gst_pngdec_change_state;
+
+  GST_DEBUG_CATEGORY_INIT (pngdec_debug, "pngdec", 0, "PNG image decoder");
+}
+
+static void
+gst_pngdec_init (GstPngDec * pngdec)
+{
+  pngdec->sinkpad =
+      gst_pad_new_from_static_template (&gst_pngdec_sink_pad_template, "sink");
+  gst_pad_set_activate_function (pngdec->sinkpad, gst_pngdec_sink_activate);
+  gst_pad_set_activatepush_function (pngdec->sinkpad,
+      gst_pngdec_sink_activate_push);
+  gst_pad_set_activatepull_function (pngdec->sinkpad,
+      gst_pngdec_sink_activate_pull);
+  gst_pad_set_chain_function (pngdec->sinkpad, gst_pngdec_chain);
+  gst_pad_set_event_function (pngdec->sinkpad, gst_pngdec_sink_event);
+  gst_pad_set_setcaps_function (pngdec->sinkpad, gst_pngdec_sink_setcaps);
+  gst_element_add_pad (GST_ELEMENT (pngdec), pngdec->sinkpad);
+
+  pngdec->srcpad =
+      gst_pad_new_from_static_template (&gst_pngdec_src_pad_template, "src");
+  gst_pad_use_fixed_caps (pngdec->srcpad);
+  gst_element_add_pad (GST_ELEMENT (pngdec), pngdec->srcpad);
+
+  pngdec->buffer_out = NULL;
+  pngdec->png = NULL;
+  pngdec->info = NULL;
+  pngdec->endinfo = NULL;
+  pngdec->setup = FALSE;
+
+  pngdec->color_type = -1;
+  pngdec->width = -1;
+  pngdec->height = -1;
+  pngdec->bpp = -1;
+  pngdec->fps_n = 0;
+  pngdec->fps_d = 1;
+
+  pngdec->in_timestamp = GST_CLOCK_TIME_NONE;
+  pngdec->in_duration = GST_CLOCK_TIME_NONE;
+
+  gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED);
+
+  pngdec->image_ready = FALSE;
+}
+
+static void
+user_error_fn (png_structp png_ptr, png_const_charp error_msg)
+{
+  GST_ERROR ("%s", error_msg);
+}
+
+static void
+user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
+{
+  GST_WARNING ("%s", warning_msg);
+}
+
+static void
+user_info_callback (png_structp png_ptr, png_infop info)
+{
+  GstPngDec *pngdec = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+  size_t buffer_size;
+  GstBuffer *buffer = NULL;
+
+  pngdec = GST_PNGDEC (png_ptr->io_ptr);
+
+  GST_LOG ("info ready");
+
+  /* Generate the caps and configure */
+  ret = gst_pngdec_caps_create_and_set (pngdec);
+  if (ret != GST_FLOW_OK) {
+    goto beach;
+  }
+
+  /* Allocate output buffer */
+  pngdec->rowbytes = png_get_rowbytes (pngdec->png, pngdec->info);
+  buffer_size = pngdec->height * GST_ROUND_UP_4 (pngdec->rowbytes);
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE,
+      buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer);
+  if (ret != GST_FLOW_OK) {
+    goto beach;
+  }
+
+  pngdec->buffer_out = buffer;
+
+beach:
+  pngdec->ret = ret;
+}
+
+static void
+user_endrow_callback (png_structp png_ptr, png_bytep new_row,
+    png_uint_32 row_num, int pass)
+{
+  GstPngDec *pngdec = NULL;
+
+  pngdec = GST_PNGDEC (png_ptr->io_ptr);
+
+  /* FIXME: implement interlaced pictures */
+
+  /* If buffer_out doesn't exist, it means buffer_alloc failed, which 
+   * will already have set the return code */
+  if (GST_IS_BUFFER (pngdec->buffer_out)) {
+    size_t offset = row_num * GST_ROUND_UP_4 (pngdec->rowbytes);
+
+    GST_LOG ("got row %u, copying in buffer %p at offset %" G_GSIZE_FORMAT,
+        (guint) row_num, pngdec->buffer_out, offset);
+    memcpy (GST_BUFFER_DATA (pngdec->buffer_out) + offset, new_row,
+        pngdec->rowbytes);
+    pngdec->ret = GST_FLOW_OK;
+  }
+}
+
+static gboolean
+buffer_clip (GstPngDec * dec, GstBuffer * buffer)
+{
+  gboolean res = TRUE;
+  gint64 cstart, cstop;
+
+
+  if ((!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) ||
+      (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) ||
+      (dec->segment.format != GST_FORMAT_TIME))
+    goto beach;
+
+  cstart = GST_BUFFER_TIMESTAMP (buffer);
+  cstop = GST_BUFFER_DURATION (buffer);
+
+  if ((res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
+              cstart, cstart + cstop, &cstart, &cstop))) {
+    GST_BUFFER_TIMESTAMP (buffer) = cstart;
+    GST_BUFFER_DURATION (buffer) = cstop - cstart;
+  }
+
+beach:
+  return res;
+}
+
+static void
+user_end_callback (png_structp png_ptr, png_infop info)
+{
+  GstPngDec *pngdec = NULL;
+
+  pngdec = GST_PNGDEC (png_ptr->io_ptr);
+
+  GST_LOG_OBJECT (pngdec, "and we are done reading this image");
+
+  if (!pngdec->buffer_out)
+    return;
+
+  if (GST_CLOCK_TIME_IS_VALID (pngdec->in_timestamp))
+    GST_BUFFER_TIMESTAMP (pngdec->buffer_out) = pngdec->in_timestamp;
+  if (GST_CLOCK_TIME_IS_VALID (pngdec->in_duration))
+    GST_BUFFER_DURATION (pngdec->buffer_out) = pngdec->in_duration;
+
+  /* buffer clipping */
+  if (buffer_clip (pngdec, pngdec->buffer_out)) {
+    /* Push our buffer and then EOS if needed */
+    GST_LOG_OBJECT (pngdec, "pushing buffer with ts=%" GST_TIME_FORMAT,
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (pngdec->buffer_out)));
+
+    pngdec->ret = gst_pad_push (pngdec->srcpad, pngdec->buffer_out);
+  } else {
+    GST_LOG_OBJECT (pngdec, "dropped decoded buffer");
+    gst_buffer_unref (pngdec->buffer_out);
+  }
+  pngdec->buffer_out = NULL;
+  pngdec->image_ready = TRUE;
+}
+
+static void
+user_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+  GstPngDec *pngdec;
+  GstBuffer *buffer;
+  GstFlowReturn ret = GST_FLOW_OK;
+  guint size;
+
+  pngdec = GST_PNGDEC (png_ptr->io_ptr);
+
+  GST_LOG ("reading %" G_GSIZE_FORMAT " bytes of data at offset %d", length,
+      pngdec->offset);
+
+  ret = gst_pad_pull_range (pngdec->sinkpad, pngdec->offset, length, &buffer);
+  if (ret != GST_FLOW_OK)
+    goto pause;
+
+  size = GST_BUFFER_SIZE (buffer);
+
+  if (size != length)
+    goto short_buffer;
+
+  memcpy (data, GST_BUFFER_DATA (buffer), size);
+
+  gst_buffer_unref (buffer);
+
+  pngdec->offset += length;
+
+  return;
+
+  /* ERRORS */
+pause:
+  {
+    GST_INFO_OBJECT (pngdec, "pausing task, reason %s",
+        gst_flow_get_name (ret));
+    gst_pad_pause_task (pngdec->sinkpad);
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
+      GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
+          (_("Internal data stream error.")),
+          ("stream stopped, reason %s", gst_flow_get_name (ret)));
+      gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
+    }
+    return;
+  }
+short_buffer:
+  {
+    gst_buffer_unref (buffer);
+    GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
+        (_("Internal data stream error.")),
+        ("Read %u, needed %" G_GSIZE_FORMAT "bytes", size, length));
+    ret = GST_FLOW_ERROR;
+    goto pause;
+  }
+}
+
+static GstFlowReturn
+gst_pngdec_caps_create_and_set (GstPngDec * pngdec)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstCaps *caps = NULL, *res = NULL;
+  GstPadTemplate *templ = NULL;
+  gint bpc = 0, color_type;
+  png_uint_32 width, height;
+
+  g_return_val_if_fail (GST_IS_PNGDEC (pngdec), GST_FLOW_ERROR);
+
+  /* Get bits per channel */
+  bpc = png_get_bit_depth (pngdec->png, pngdec->info);
+
+  /* We don't handle 16 bits per color, strip down to 8 */
+  if (bpc == 16) {
+    GST_LOG_OBJECT (pngdec,
+        "this is a 16 bits per channel PNG image, strip down to 8 bits");
+    png_set_strip_16 (pngdec->png);
+  }
+
+  /* Get Color type */
+  color_type = png_get_color_type (pngdec->png, pngdec->info);
+
+#if 0
+  /* We used to have this HACK to reverse the outgoing bytes, but the problem
+   * that originally required the hack seems to have been in ffmpegcolorspace's
+   * RGBA descriptions. It doesn't seem needed now that's fixed, but might
+   * still be needed on big-endian systems, I'm not sure. J.S. 6/7/2007 */
+  if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+    png_set_bgr (pngdec->png);
+#endif
+
+  /* Gray scale converted to RGB and upscaled to 8 bits */
+  if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
+      (color_type == PNG_COLOR_TYPE_GRAY)) {
+    GST_LOG_OBJECT (pngdec, "converting grayscale png to RGB");
+    png_set_gray_to_rgb (pngdec->png);
+    if (bpc < 8) {              /* Convert to 8 bits */
+      GST_LOG_OBJECT (pngdec, "converting grayscale image to 8 bits");
+      png_set_gray_1_2_4_to_8 (pngdec->png);
+    }
+  }
+
+  /* Palette converted to RGB */
+  if (color_type == PNG_COLOR_TYPE_PALETTE) {
+    GST_LOG_OBJECT (pngdec, "converting palette png to RGB");
+    png_set_palette_to_rgb (pngdec->png);
+  }
+
+  /* Update the info structure */
+  png_read_update_info (pngdec->png, pngdec->info);
+
+  /* Get IHDR header again after transformation settings */
+
+  png_get_IHDR (pngdec->png, pngdec->info, &width, &height,
+      &bpc, &pngdec->color_type, NULL, NULL, NULL);
+
+  pngdec->width = width;
+  pngdec->height = height;
+
+  GST_LOG_OBJECT (pngdec, "this is a %dx%d PNG image", pngdec->width,
+      pngdec->height);
+
+  switch (pngdec->color_type) {
+    case PNG_COLOR_TYPE_RGB:
+      GST_LOG_OBJECT (pngdec, "we have no alpha channel, depth is 24 bits");
+      pngdec->bpp = 24;
+      break;
+    case PNG_COLOR_TYPE_RGB_ALPHA:
+      GST_LOG_OBJECT (pngdec, "we have an alpha channel, depth is 32 bits");
+      pngdec->bpp = 32;
+      break;
+    default:
+      GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL),
+          ("pngdec does not support this color type"));
+      ret = GST_FLOW_NOT_SUPPORTED;
+      goto beach;
+  }
+
+  caps = gst_caps_new_simple ("video/x-raw-rgb",
+      "width", G_TYPE_INT, pngdec->width,
+      "height", G_TYPE_INT, pngdec->height,
+      "bpp", G_TYPE_INT, pngdec->bpp,
+      "framerate", GST_TYPE_FRACTION, pngdec->fps_n, pngdec->fps_d, NULL);
+
+  templ = gst_static_pad_template_get (&gst_pngdec_src_pad_template);
+
+  res = gst_caps_intersect (caps, gst_pad_template_get_caps (templ));
+
+  gst_caps_unref (caps);
+  gst_object_unref (templ);
+
+  if (!gst_pad_set_caps (pngdec->srcpad, res))
+    ret = GST_FLOW_NOT_NEGOTIATED;
+
+  GST_DEBUG_OBJECT (pngdec, "our caps %" GST_PTR_FORMAT, res);
+
+  gst_caps_unref (res);
+
+  /* Push a newsegment event */
+  if (pngdec->need_newsegment) {
+    gst_pad_push_event (pngdec->srcpad,
+        gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
+    pngdec->need_newsegment = FALSE;
+  }
+
+beach:
+  return ret;
+}
+
+static void
+gst_pngdec_task (GstPad * pad)
+{
+  GstPngDec *pngdec;
+  GstBuffer *buffer = NULL;
+  size_t buffer_size = 0;
+  gint i = 0;
+  png_bytep *rows, inp;
+  png_uint_32 rowbytes;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  pngdec = GST_PNGDEC (GST_OBJECT_PARENT (pad));
+
+  GST_LOG_OBJECT (pngdec, "read frame");
+
+  /* Let libpng come back here on error */
+  if (setjmp (png_jmpbuf (pngdec->png))) {
+    ret = GST_FLOW_ERROR;
+    goto pause;
+  }
+
+  /* Set reading callback */
+  png_set_read_fn (pngdec->png, pngdec, user_read_data);
+
+  /* Read info */
+  png_read_info (pngdec->png, pngdec->info);
+
+  /* Generate the caps and configure */
+  ret = gst_pngdec_caps_create_and_set (pngdec);
+  if (ret != GST_FLOW_OK) {
+    goto pause;
+  }
+
+  /* Allocate output buffer */
+  rowbytes = png_get_rowbytes (pngdec->png, pngdec->info);
+  buffer_size = pngdec->height * GST_ROUND_UP_4 (rowbytes);
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE,
+      buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer);
+  if (ret != GST_FLOW_OK)
+    goto pause;
+
+  rows = (png_bytep *) g_malloc (sizeof (png_bytep) * pngdec->height);
+
+  inp = GST_BUFFER_DATA (buffer);
+
+  for (i = 0; i < pngdec->height; i++) {
+    rows[i] = inp;
+    inp += GST_ROUND_UP_4 (rowbytes);
+  }
+
+  /* Read the actual picture */
+  png_read_image (pngdec->png, rows);
+  free (rows);
+
+  /* Push the raw RGB frame */
+  ret = gst_pad_push (pngdec->srcpad, buffer);
+  if (ret != GST_FLOW_OK)
+    goto pause;
+
+  /* And we are done */
+  gst_pad_pause_task (pngdec->sinkpad);
+  gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
+  return;
+
+pause:
+  {
+    GST_INFO_OBJECT (pngdec, "pausing task, reason %s",
+        gst_flow_get_name (ret));
+    gst_pad_pause_task (pngdec->sinkpad);
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
+      GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
+          (_("Internal data stream error.")),
+          ("stream stopped, reason %s", gst_flow_get_name (ret)));
+      gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
+    }
+  }
+}
+
+static GstFlowReturn
+gst_pngdec_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstPngDec *pngdec;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
+
+  GST_LOG_OBJECT (pngdec, "Got buffer, size=%u", GST_BUFFER_SIZE (buffer));
+
+  if (G_UNLIKELY (!pngdec->setup))
+    goto not_configured;
+
+  /* Something is going wrong in our callbacks */
+  ret = pngdec->ret;
+  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+    GST_WARNING_OBJECT (pngdec, "we have a pending return code of %d", ret);
+    goto beach;
+  }
+
+  /* Let libpng come back here on error */
+  if (setjmp (png_jmpbuf (pngdec->png))) {
+    GST_WARNING_OBJECT (pngdec, "error during decoding");
+    ret = GST_FLOW_ERROR;
+    goto beach;
+  }
+
+  pngdec->in_timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  pngdec->in_duration = GST_BUFFER_DURATION (buffer);
+
+  /* Progressive loading of the PNG image */
+  png_process_data (pngdec->png, pngdec->info, GST_BUFFER_DATA (buffer),
+      GST_BUFFER_SIZE (buffer));
+
+  if (pngdec->image_ready) {
+    if (pngdec->framed) {
+      /* Reset ourselves for the next frame */
+      gst_pngdec_libpng_clear (pngdec);
+      gst_pngdec_libpng_init (pngdec);
+      GST_LOG_OBJECT (pngdec, "setting up callbacks for next frame");
+      png_set_progressive_read_fn (pngdec->png, pngdec,
+          user_info_callback, user_endrow_callback, user_end_callback);
+    } else {
+      GST_LOG_OBJECT (pngdec, "sending EOS");
+      pngdec->ret = gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
+    }
+    pngdec->image_ready = FALSE;
+  }
+
+  /* grab new return code */
+  ret = pngdec->ret;
+
+  /* And release the buffer */
+  gst_buffer_unref (buffer);
+
+beach:
+  gst_object_unref (pngdec);
+
+  return ret;
+
+  /* ERRORS */
+not_configured:
+  {
+    GST_LOG_OBJECT (pngdec, "we are not configured yet");
+    ret = GST_FLOW_WRONG_STATE;
+    goto beach;
+  }
+}
+
+static gboolean
+gst_pngdec_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstStructure *s;
+  GstPngDec *pngdec;
+  gint num, denom;
+
+  pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
+
+  s = gst_caps_get_structure (caps, 0);
+  if (gst_structure_get_fraction (s, "framerate", &num, &denom)) {
+    GST_DEBUG_OBJECT (pngdec, "framed input");
+    pngdec->framed = TRUE;
+    pngdec->fps_n = num;
+    pngdec->fps_d = denom;
+  } else {
+    GST_DEBUG_OBJECT (pngdec, "single picture input");
+    pngdec->framed = FALSE;
+    pngdec->fps_n = 0;
+    pngdec->fps_d = 1;
+  }
+
+  gst_object_unref (pngdec);
+  return TRUE;
+}
+
+static gboolean
+gst_pngdec_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstPngDec *pngdec;
+  gboolean res;
+
+  pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:{
+      gdouble rate, arate;
+      gboolean update;
+      gint64 start, stop, position;
+      GstFormat fmt;
+
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
+          &start, &stop, &position);
+
+      gst_segment_set_newsegment_full (&pngdec->segment, update, rate, arate,
+          fmt, start, stop, position);
+
+      GST_LOG_OBJECT (pngdec, "NEWSEGMENT (%s)", gst_format_get_name (fmt));
+
+      if (fmt == GST_FORMAT_TIME) {
+        pngdec->need_newsegment = FALSE;
+        res = gst_pad_push_event (pngdec->srcpad, event);
+      } else {
+        gst_event_unref (event);
+        res = TRUE;
+      }
+      break;
+    }
+    case GST_EVENT_FLUSH_STOP:
+    {
+      gst_pngdec_libpng_clear (pngdec);
+      gst_pngdec_libpng_init (pngdec);
+      png_set_progressive_read_fn (pngdec->png, pngdec,
+          user_info_callback, user_endrow_callback, user_end_callback);
+      pngdec->ret = GST_FLOW_OK;
+      gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED);
+      res = gst_pad_push_event (pngdec->srcpad, event);
+      break;
+    }
+    case GST_EVENT_EOS:
+    {
+      GST_LOG_OBJECT (pngdec, "EOS");
+      gst_pngdec_libpng_clear (pngdec);
+      pngdec->ret = GST_FLOW_UNEXPECTED;
+      res = gst_pad_push_event (pngdec->srcpad, event);
+      break;
+    }
+    default:
+      res = gst_pad_push_event (pngdec->srcpad, event);
+      break;
+  }
+
+  gst_object_unref (pngdec);
+  return res;
+}
+
+
+/* Clean up the libpng structures */
+static gboolean
+gst_pngdec_libpng_clear (GstPngDec * pngdec)
+{
+  png_infopp info = NULL, endinfo = NULL;
+
+  g_return_val_if_fail (GST_IS_PNGDEC (pngdec), FALSE);
+
+  GST_LOG ("cleaning up libpng structures");
+
+  if (pngdec->info) {
+    info = &pngdec->info;
+  }
+
+  if (pngdec->endinfo) {
+    endinfo = &pngdec->endinfo;
+  }
+
+  if (pngdec->png) {
+    png_destroy_read_struct (&(pngdec->png), info, endinfo);
+    pngdec->png = NULL;
+    pngdec->info = NULL;
+    pngdec->endinfo = NULL;
+  }
+
+  pngdec->bpp = pngdec->color_type = pngdec->height = pngdec->width = -1;
+  pngdec->offset = 0;
+  pngdec->rowbytes = 0;
+  pngdec->buffer_out = NULL;
+
+  pngdec->setup = FALSE;
+
+  pngdec->in_timestamp = GST_CLOCK_TIME_NONE;
+  pngdec->in_duration = GST_CLOCK_TIME_NONE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_pngdec_libpng_init (GstPngDec * pngdec)
+{
+  g_return_val_if_fail (GST_IS_PNGDEC (pngdec), FALSE);
+
+  if (pngdec->setup)
+    return TRUE;
+
+  GST_LOG ("init libpng structures");
+
+  /* initialize png struct stuff */
+  pngdec->png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
+      (png_voidp) NULL, user_error_fn, user_warning_fn);
+
+  if (pngdec->png == NULL)
+    goto init_failed;
+
+  pngdec->info = png_create_info_struct (pngdec->png);
+  if (pngdec->info == NULL)
+    goto info_failed;
+
+  pngdec->endinfo = png_create_info_struct (pngdec->png);
+  if (pngdec->endinfo == NULL)
+    goto endinfo_failed;
+
+  pngdec->setup = TRUE;
+
+  return TRUE;
+
+  /* ERRORS */
+init_failed:
+  {
+    GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
+        ("Failed to initialize png structure"));
+    return FALSE;
+  }
+info_failed:
+  {
+    gst_pngdec_libpng_clear (pngdec);
+    GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
+        ("Failed to initialize info structure"));
+    return FALSE;
+  }
+endinfo_failed:
+  {
+    gst_pngdec_libpng_clear (pngdec);
+    GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
+        ("Failed to initialize endinfo structure"));
+    return FALSE;
+  }
+}
+
+static GstStateChangeReturn
+gst_pngdec_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstPngDec *pngdec;
+
+  pngdec = GST_PNGDEC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_pngdec_libpng_init (pngdec);
+      pngdec->need_newsegment = TRUE;
+      pngdec->framed = FALSE;
+      pngdec->ret = GST_FLOW_OK;
+      gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED);
+      break;
+    default:
+      break;
+  }
+
+  ret = parent_class->change_state (element, transition);
+  if (ret != GST_STATE_CHANGE_SUCCESS)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_pngdec_libpng_clear (pngdec);
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+/* this function gets called when we activate ourselves in push mode. */
+static gboolean
+gst_pngdec_sink_activate_push (GstPad * sinkpad, gboolean active)
+{
+  GstPngDec *pngdec;
+
+  pngdec = GST_PNGDEC (GST_OBJECT_PARENT (sinkpad));
+
+  pngdec->ret = GST_FLOW_OK;
+
+  if (active) {
+    /* Let libpng come back here on error */
+    if (setjmp (png_jmpbuf (pngdec->png)))
+      goto setup_failed;
+
+    GST_LOG ("setting up progressive loading callbacks");
+    png_set_progressive_read_fn (pngdec->png, pngdec,
+        user_info_callback, user_endrow_callback, user_end_callback);
+  }
+  return TRUE;
+
+setup_failed:
+  {
+    GST_LOG ("failed setting up libpng jmpbuf");
+    gst_pngdec_libpng_clear (pngdec);
+    return FALSE;
+  }
+}
+
+/* this function gets called when we activate ourselves in pull mode.
+ * We can perform  random access to the resource and we start a task
+ * to start reading */
+static gboolean
+gst_pngdec_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+  if (active) {
+    return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_pngdec_task,
+        sinkpad);
+  } else {
+    return gst_pad_stop_task (sinkpad);
+  }
+}
+
+/* this function is called when the pad is activated and should start
+ * processing data.
+ *
+ * We check if we can do random access to decide if we work push or
+ * pull based.
+ */
+static gboolean
+gst_pngdec_sink_activate (GstPad * sinkpad)
+{
+  if (gst_pad_check_pull_range (sinkpad)) {
+    return gst_pad_activate_pull (sinkpad, TRUE);
+  } else {
+    return gst_pad_activate_push (sinkpad, TRUE);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/libpng/gstpngdec.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,89 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_PNGDEC_H__
+#define __GST_PNGDEC_H__
+
+#include <gst/gst.h>
+#include <png.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_TYPE_PNGDEC            (gst_pngdec_get_type())
+#define GST_PNGDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PNGDEC,GstPngDec))
+#define GST_PNGDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PNGDEC,GstPngDecClass))
+#define GST_IS_PNGDEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PNGDEC))
+#define GST_IS_PNGDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PNGDEC))
+
+typedef struct _GstPngDec GstPngDec;
+typedef struct _GstPngDecClass GstPngDecClass;
+
+struct _GstPngDec
+{
+  GstElement element;
+
+  GstPad *sinkpad, *srcpad;
+
+  gboolean need_newsegment;
+
+  /* Progressive */
+  GstBuffer *buffer_out;
+  GstFlowReturn ret;
+  png_uint_32 rowbytes;
+  
+  /* Pull range */
+  gint offset;
+
+  png_structp png;
+  png_infop info;
+  png_infop endinfo;
+  gboolean setup;
+
+  gint width;
+  gint height;
+  gint bpp;
+  gint color_type;
+  gint fps_n;
+  gint fps_d;
+
+  /* Chain */
+  gboolean framed;
+  GstClockTime in_timestamp;
+  GstClockTime in_duration;
+
+  GstSegment segment;
+  gboolean image_ready;
+};
+
+struct _GstPngDecClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_pngdec_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_PNGDEC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/libpng/gstpngenc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,394 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * Filter:
+ * Copyright (C) 2000 Donald A. Graft
+ *
+ * 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.
+ *
+ */
+/**
+ * SECTION:element-pngenc
+ *
+ * Encodes png images.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+#include <gst/gst.h>
+#include "gstpngenc.h"
+#include <gst/video/video.h>
+#include <zlib.h>
+
+#define MAX_HEIGHT              4096
+
+
+static const GstElementDetails gst_pngenc_details =
+GST_ELEMENT_DETAILS ("PNG image encoder",
+    "Codec/Encoder/Image",
+    "Encode a video frame to a .png image",
+    "Jeremy SIMON <jsimon13@yahoo.fr>");
+
+GST_DEBUG_CATEGORY_STATIC (pngenc_debug);
+#define GST_CAT_DEFAULT pngenc_debug
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+#define DEFAULT_SNAPSHOT                TRUE
+/* #define DEFAULT_NEWMEDIA             FALSE */
+#define DEFAULT_COMPRESSION_LEVEL       6
+
+enum
+{
+  ARG_0,
+  ARG_SNAPSHOT,
+/*   ARG_NEWMEDIA, */
+  ARG_COMPRESSION_LEVEL
+};
+
+static GstStaticPadTemplate pngenc_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("image/png, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0.0, MAX ]")
+    );
+
+static GstStaticPadTemplate pngenc_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_RGB)
+    );
+
+/* static GstElementClass *parent_class = NULL; */
+
+GST_BOILERPLATE (GstPngEnc, gst_pngenc, GstElement, GST_TYPE_ELEMENT);
+
+static void gst_pngenc_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_pngenc_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstFlowReturn gst_pngenc_chain (GstPad * pad, GstBuffer * data);
+
+static void
+user_error_fn (png_structp png_ptr, png_const_charp error_msg)
+{
+  g_warning ("%s", error_msg);
+}
+
+static void
+user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
+{
+  g_warning ("%s", warning_msg);
+}
+
+static void
+gst_pngenc_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template
+      (element_class, gst_static_pad_template_get (&pngenc_sink_template));
+  gst_element_class_add_pad_template
+      (element_class, gst_static_pad_template_get (&pngenc_src_template));
+  gst_element_class_set_details (element_class, &gst_pngenc_details);
+}
+
+static void
+gst_pngenc_class_init (GstPngEncClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->get_property = gst_pngenc_get_property;
+  gobject_class->set_property = gst_pngenc_set_property;
+
+  g_object_class_install_property (gobject_class, ARG_SNAPSHOT,
+      g_param_spec_boolean ("snapshot", "Snapshot",
+          "Send EOS after encoding a frame, useful for snapshots",
+          DEFAULT_SNAPSHOT, (GParamFlags) G_PARAM_READWRITE));
+
+/*   g_object_class_install_property (gobject_class, ARG_NEWMEDIA, */
+/*       g_param_spec_boolean ("newmedia", "newmedia", */
+/*           "Send new media discontinuity after encoding each frame", */
+/*           DEFAULT_NEWMEDIA, (GParamFlags) G_PARAM_READWRITE)); */
+
+  g_object_class_install_property
+      (gobject_class, ARG_COMPRESSION_LEVEL,
+      g_param_spec_uint ("compression-level", "compression-level",
+          "PNG compression level",
+          Z_NO_COMPRESSION, Z_BEST_COMPRESSION,
+          DEFAULT_COMPRESSION_LEVEL, (GParamFlags) G_PARAM_READWRITE));
+
+  GST_DEBUG_CATEGORY_INIT (pngenc_debug, "pngenc", 0, "PNG image encoder");
+}
+
+
+static gboolean
+gst_pngenc_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstPngEnc *pngenc;
+  const GValue *fps;
+  GstStructure *structure;
+  GstCaps *pcaps;
+  gboolean ret = TRUE;
+
+  pngenc = GST_PNGENC (gst_pad_get_parent (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+  gst_structure_get_int (structure, "width", &pngenc->width);
+  gst_structure_get_int (structure, "height", &pngenc->height);
+  fps = gst_structure_get_value (structure, "framerate");
+  gst_structure_get_int (structure, "bpp", &pngenc->bpp);
+
+  if (pngenc->bpp == 32)
+    pngenc->stride = pngenc->width * 4;
+  else
+    pngenc->stride = GST_ROUND_UP_4 (pngenc->width * 3);
+
+  pcaps = gst_caps_new_simple ("image/png",
+      "width", G_TYPE_INT, pngenc->width,
+      "height", G_TYPE_INT, pngenc->height, NULL);
+  structure = gst_caps_get_structure (pcaps, 0);
+  gst_structure_set_value (structure, "framerate", fps);
+
+  ret = gst_pad_set_caps (pngenc->srcpad, pcaps);
+
+  gst_caps_unref (pcaps);
+  gst_object_unref (pngenc);
+
+  return ret;
+}
+
+static void
+gst_pngenc_init (GstPngEnc * pngenc, GstPngEncClass * g_class)
+{
+  /* sinkpad */
+  pngenc->sinkpad = gst_pad_new_from_static_template
+      (&pngenc_sink_template, "sink");
+  gst_pad_set_chain_function (pngenc->sinkpad, gst_pngenc_chain);
+  /*   gst_pad_set_link_function (pngenc->sinkpad, gst_pngenc_sinklink); */
+  /*   gst_pad_set_getcaps_function (pngenc->sinkpad, gst_pngenc_sink_getcaps); */
+  gst_pad_set_setcaps_function (pngenc->sinkpad, gst_pngenc_setcaps);
+  gst_element_add_pad (GST_ELEMENT (pngenc), pngenc->sinkpad);
+
+  /* srcpad */
+  pngenc->srcpad = gst_pad_new_from_static_template
+      (&pngenc_src_template, "src");
+  /*   pngenc->srcpad = gst_pad_new ("src", GST_PAD_SRC); */
+  /*   gst_pad_set_getcaps_function (pngenc->srcpad, gst_pngenc_src_getcaps); */
+  /*   gst_pad_set_setcaps_function (pngenc->srcpad, gst_pngenc_setcaps); */
+  gst_element_add_pad (GST_ELEMENT (pngenc), pngenc->srcpad);
+
+  /* init settings */
+  pngenc->png_struct_ptr = NULL;
+  pngenc->png_info_ptr = NULL;
+
+  pngenc->snapshot = DEFAULT_SNAPSHOT;
+/*   pngenc->newmedia = FALSE; */
+  pngenc->compression_level = DEFAULT_COMPRESSION_LEVEL;
+}
+
+static void
+user_flush_data (png_structp png_ptr G_GNUC_UNUSED)
+{
+}
+
+static void
+user_write_data (png_structp png_ptr, png_bytep data, png_uint_32 length)
+{
+  GstPngEnc *pngenc;
+
+  pngenc = (GstPngEnc *) png_get_io_ptr (png_ptr);
+
+  if (pngenc->written + length >= GST_BUFFER_SIZE (pngenc->buffer_out)) {
+    GST_ERROR_OBJECT (pngenc, "output buffer bigger than the input buffer!?");
+    /* yuck */
+    longjmp (pngenc->png_struct_ptr->jmpbuf, 1);
+
+    /* never reached */
+    return;
+  }
+
+  memcpy (GST_BUFFER_DATA (pngenc->buffer_out) + pngenc->written, data, length);
+  pngenc->written += length;
+}
+
+static GstFlowReturn
+gst_pngenc_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstPngEnc *pngenc;
+  gint row_index;
+  png_byte *row_pointers[MAX_HEIGHT];
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstBuffer *encoded_buf = NULL;
+
+  pngenc = GST_PNGENC (gst_pad_get_parent (pad));
+
+  GST_DEBUG_OBJECT (pngenc, "BEGINNING");
+
+  /* initialize png struct stuff */
+  pngenc->png_struct_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
+      (png_voidp) NULL, user_error_fn, user_warning_fn);
+  if (pngenc->png_struct_ptr == NULL) {
+    gst_buffer_unref (buf);
+    GST_ELEMENT_ERROR (pngenc, LIBRARY, INIT, (NULL),
+        ("Failed to initialize png structure"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+
+  pngenc->png_info_ptr = png_create_info_struct (pngenc->png_struct_ptr);
+  if (!pngenc->png_info_ptr) {
+    gst_buffer_unref (buf);
+    png_destroy_write_struct (&(pngenc->png_struct_ptr), (png_infopp) NULL);
+    GST_ELEMENT_ERROR (pngenc, LIBRARY, INIT, (NULL),
+        ("Failed to initialize the png info structure"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+
+  /* non-0 return is from a longjmp inside of libpng */
+  if (setjmp (pngenc->png_struct_ptr->jmpbuf) != 0) {
+    gst_buffer_unref (buf);
+    png_destroy_write_struct (&pngenc->png_struct_ptr, &pngenc->png_info_ptr);
+    GST_ELEMENT_ERROR (pngenc, LIBRARY, FAILED, (NULL),
+        ("returning from longjmp"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+
+  png_set_filter (pngenc->png_struct_ptr, 0,
+      PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE);
+  png_set_compression_level (pngenc->png_struct_ptr, pngenc->compression_level);
+
+  png_set_IHDR (pngenc->png_struct_ptr,
+      pngenc->png_info_ptr,
+      pngenc->width,
+      pngenc->height,
+      8,
+      (pngenc->bpp == 32) ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
+      PNG_INTERLACE_NONE,
+      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+  png_set_write_fn (pngenc->png_struct_ptr, pngenc,
+      (png_rw_ptr) user_write_data, user_flush_data);
+
+  for (row_index = 0; row_index < pngenc->height; row_index++) {
+    row_pointers[row_index] = GST_BUFFER_DATA (buf) +
+        (row_index * pngenc->stride);
+  }
+
+  /* allocate the output buffer */
+  pngenc->buffer_out =
+      gst_buffer_new_and_alloc (pngenc->height * pngenc->stride);
+  pngenc->written = 0;
+
+  png_write_info (pngenc->png_struct_ptr, pngenc->png_info_ptr);
+  png_write_image (pngenc->png_struct_ptr, row_pointers);
+  png_write_end (pngenc->png_struct_ptr, NULL);
+
+  encoded_buf = gst_buffer_create_sub (pngenc->buffer_out, 0, pngenc->written);
+
+  png_destroy_info_struct (pngenc->png_struct_ptr, &pngenc->png_info_ptr);
+  png_destroy_write_struct (&pngenc->png_struct_ptr, (png_infopp) NULL);
+  gst_buffer_copy_metadata (encoded_buf, buf, GST_BUFFER_COPY_TIMESTAMPS);
+  gst_buffer_unref (buf);
+  gst_buffer_set_caps (encoded_buf, GST_PAD_CAPS (pngenc->srcpad));
+
+  if ((ret = gst_pad_push (pngenc->srcpad, encoded_buf)) != GST_FLOW_OK)
+    goto done;
+
+  if (pngenc->snapshot) {
+    GstEvent *event;
+
+    GST_DEBUG_OBJECT (pngenc, "snapshot mode, sending EOS");
+    /* send EOS event, since a frame has been pushed out */
+    event = gst_event_new_eos ();
+
+    gst_pad_push_event (pngenc->srcpad, event);
+    ret = GST_FLOW_UNEXPECTED;
+  }
+
+done:
+  GST_DEBUG_OBJECT (pngenc, "END, ret:%d", ret);
+
+  if (pngenc->buffer_out != NULL) {
+    gst_buffer_unref (pngenc->buffer_out);
+    pngenc->buffer_out = NULL;
+  }
+
+  gst_object_unref (pngenc);
+  return ret;
+}
+
+
+static void
+gst_pngenc_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstPngEnc *pngenc;
+
+  pngenc = GST_PNGENC (object);
+
+  switch (prop_id) {
+    case ARG_SNAPSHOT:
+      g_value_set_boolean (value, pngenc->snapshot);
+      break;
+/*     case ARG_NEWMEDIA: */
+/*       g_value_set_boolean (value, pngenc->newmedia); */
+/*       break; */
+    case ARG_COMPRESSION_LEVEL:
+      g_value_set_uint (value, pngenc->compression_level);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
+static void
+gst_pngenc_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstPngEnc *pngenc;
+
+  pngenc = GST_PNGENC (object);
+
+  switch (prop_id) {
+    case ARG_SNAPSHOT:
+      pngenc->snapshot = g_value_get_boolean (value);
+      break;
+/*     case ARG_NEWMEDIA: */
+/*       pngenc->newmedia = g_value_get_boolean (value); */
+/*       break; */
+    case ARG_COMPRESSION_LEVEL:
+      pngenc->compression_level = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/ext/libpng/gstpngenc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,75 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_PNGENC_H__
+#define __GST_PNGENC_H__
+
+#include <gst/gst.h>
+#include <png.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_PNGENC            (gst_pngenc_get_type())
+#define GST_PNGENC(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PNGENC,GstPngEnc))
+#define GST_PNGENC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PNGENC,GstPngEncClass))
+#define GST_IS_PNGENC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PNGENC))
+#define GST_IS_PNGENC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PNGENC))
+
+typedef struct _GstPngEnc GstPngEnc;
+typedef struct _GstPngEncClass GstPngEncClass;
+
+struct _GstPngEnc
+{
+  GstElement element;
+
+  GstPad *sinkpad, *srcpad;
+  GstBuffer *buffer_out;
+  guint written;
+
+  png_structp png_struct_ptr;
+  png_infop png_info_ptr;
+
+  gint width;
+  gint height;
+  gint bpp;
+  gint stride;
+  guint compression_level;
+
+  gboolean snapshot;
+  gboolean newmedia;
+};
+
+struct _GstPngEncClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_pngenc_get_type(void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_PNGENC_H__ */
--- a/gst_plugins_good/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -9,6 +9,9 @@
 gstwavparse.mmp
 gstwavenc.mmp
 gstautodetect.mmp
-gstphotography.mmp
-gstcamerabin.mmp
+gstavi.mmp
+gstqtmux.mmp
+gstamrmux.mmp
+//gstphotography.mmp
+//gstcamerabin.mmp
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstalaw.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,81 @@
+// Gstreamer.MMP
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstalaw.dll
+TARGETTYPE      DLL
+UID             0x20004c47 0x0DE80A1D
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           __SYMBIAN32__
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ..
+USERINCLUDE     ../gst/law
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+
+SOURCEPATH      ../gst/law
+SOURCE          alaw.c
+SOURCE          alaw-decode.c
+SOURCE          alaw-encode.c
+
+LIBRARY         libc.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstalpha.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+/*
+============================================================================
+ Name		: gstalpha.mmp
+ Author	  : 
+ Copyright   : Your copyright notice
+ Description : This is the project specification file for alpha.
+============================================================================
+*/
+
+#include <platform_paths.hrh> 
+TARGET		  libgstalpha.dll
+TARGETTYPE	  dll
+UID			 0x1000008d 0x0B6AF79A
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           SYMBIAN
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ../../..
+USERINCLUDE     ..
+USERINCLUDE     ../gst/alpha
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/riff
+
+SOURCEPATH      ../gst/alpha
+SOURCE gstalpha.c
+
+LIBRARY         libc.lib
+LIBRARY         libm.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+LIBRARY         libgstriff.lib
+LIBRARY         libgstcontroller.lib
+LIBRARY         libgstvideo.lib
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstalphacolor.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+/*
+============================================================================
+ Name		: alphacolor.mmp
+ Author	  : 
+ Copyright   : Your copyright notice
+ Description : This is the project specification file for alpha.
+============================================================================
+*/
+#include <platform_paths.hrh> 
+TARGET		  libgstalphacolor.dll
+TARGETTYPE	  dll
+UID			 0x1000008d 0x0B6AF79B
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           SYMBIAN
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ../../..
+USERINCLUDE     ..
+USERINCLUDE     ../gst/alpha
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/riff
+
+SOURCEPATH      ../gst/alpha
+SOURCE gstalphacolor.c
+
+LIBRARY         libc.lib
+LIBRARY         libm.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+LIBRARY         libgstriff.lib
+LIBRARY         libgstcontroller.lib
+LIBRARY         libgstvideo.lib
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstamrmux.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,62 @@
+/*
+ *  Copyright © 2010 Nokia Corporation.
+ *  This material, including documentation and any related
+ *  computer progrs, is protected by copyright controlled by
+ *  Nokia Corporation. All rights are reserved. Copying,
+ *  including reproducing, storing, adapting or translating, any
+ *  or all of this material requires the prior written consent of
+ *  Nokia Corporation. This material also contains confidential
+ *  information which may not be disclosed to others without the
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
+
+#include <platform_paths.hrh>                                                            
+
+TARGET			  libgstamrmux.dll
+TARGETTYPE		DLL
+UID           0x1000009d 0x0DE80A2C
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+
+#endif
+
+
+MACRO			HAVE_CONFIG_H
+
+USERINCLUDE     ..
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+
+
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+
+
+
+SOURCEPATH	  ../gst/amrmux
+SOURCE		    gstamrmux.c
+
+
+LIBRARY 		libc.lib
+LIBRARY			libglib.lib
+LIBRARY			libgmodule.lib
+LIBRARY			libgobject.lib
+LIBRARY			libgstreamer.lib
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstaudiofx.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,97 @@
+// Gstreamer.MMP
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstaudiofx.dll
+TARGETTYPE      DLL
+UID             0x20004c49 0x0DE80A1F
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           __SYMBIAN32__
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ..
+USERINCLUDE     ../gst/audiofx
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+
+SOURCEPATH      ../gst/audiofx
+SOURCE          audioamplify.c
+
+SOURCE          audiocheblimit.c
+SOURCE          audiodynamic.c
+SOURCE          audioecho.c
+SOURCE          audiofirfilter.c
+SOURCE          audiofx.c
+SOURCE          audiofxbasefirfilter.c
+SOURCE          audiofxbaseiirfilter.c
+SOURCE          audioiirfilter.c
+SOURCE          audioinvert.c
+SOURCE          audiokaraoke.c
+SOURCE          audiochebband.c
+SOURCE          audiopanorama.c
+SOURCE          audiowsinclimit.c
+SOURCE          audiowsincband.c
+
+
+LIBRARY         libc.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+LIBRARY					libgstcontroller.lib
+LIBRARY					libgstaudio.lib
+LIBRARY         libm.lib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstauparse.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,67 @@
+// Gstreamer.MMP
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstauparse.dll
+TARGETTYPE      DLL
+UID             0x20004c46 0x0DE80A1C
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           __SYMBIAN32__
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ..
+USERINCLUDE     ../gst/auparse
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+
+
+SOURCEPATH      ../gst/auparse
+SOURCE          gstauparse.c
+
+LIBRARY         libc.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+
--- a/gst_plugins_good/group/gstautodetect.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/group/gstautodetect.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -49,6 +49,8 @@
 
 SOURCEPATH      ../gst/autodetect
 SOURCE          gstautodetect.c
+SOURCE          gstautoaudiosrc.c
+SOURCE          gstautovideosrc.c
 SOURCE          gstautoaudiosink.c
 SOURCE          gstautovideosink.c
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstavi.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstavi.dll
+TARGETTYPE      DLL
+UID             0x20004c46 0x0DE80A1C
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           SYMBIAN
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ../../..
+USERINCLUDE     ..
+USERINCLUDE     ../gst/avi
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/riff
+
+SOURCEPATH      ../gst/avi
+SOURCE gstavi.c gstavimux.c gstavidemux.c gstavisubtitle.c
+
+LIBRARY         libc.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+LIBRARY         libgstriff.lib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstjpeg.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>   
+
+TARGET			libgstjpeg.dll
+TARGETTYPE		DLL
+UID             0x1000008d 0x0FDE0317
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+USERINCLUDE			../ext/jpeg/.
+USERINCLUDE			../gst-libs/gst/.
+USERINCLUDE			../.
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+
+SYSTEMINCLUDE		/epoc32/include/jpeg-6b
+
+SOURCEPATH		../ext/jpeg
+SOURCE			gstjpeg.c
+SOURCE			gstjpegdec.c
+SOURCE			gstjpegenc.c
+SOURCE			gstsmokedec.c
+SOURCE			gstsmokeenc.c
+SOURCE			smokecodec.c
+
+LIBRARY			euser.lib
+LIBRARY			libc.lib libm.lib
+LIBRARY			libgobject.lib libglib.lib
+LIBRARY			libgstreamer.lib
+LIBRARY			libjpeg.lib
+
+MACRO			__SYMBIAN32__
+MACRO			HAVE_CONFIG_H
+MACRO 			__SYMBIAN32__
+
+EPOCSTACKSIZE	0x12000
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstmulaw.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstmulaw.dll
+TARGETTYPE      DLL
+UID             0x20004c48 0x0DE80A1E
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           __SYMBIAN32__
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ..
+USERINCLUDE     ../gst/law
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+
+SOURCEPATH      ../gst/law
+SOURCE          mulaw.c
+SOURCE          mulaw-conversion.c
+SOURCE          mulaw-decode.c
+SOURCE          mulaw-encode.c
+
+
+LIBRARY         libc.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstpng.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+/*
+============================================================================
+ Name		: libgstpng.mmp
+ Author	  : 
+ Copyright   : Your copyright notice
+ Description : This is the project specification file for libpng.
+============================================================================
+*/
+
+#include <platform_paths.hrh> 
+
+TARGET		  libgstpng.dll
+TARGETTYPE	  dll
+UID			 0x1000008d 0x011746FD
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           SYMBIAN
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ../../..
+USERINCLUDE     ..
+USERINCLUDE     ../ext/libpng
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		/epoc32/include/libpng
+
+SOURCEPATH      ../ext/libpng
+SOURCE gstpng.c gstpngdec.c gstpngenc.c
+
+LIBRARY         libc.lib
+LIBRARY         libm.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+LIBRARY         libgstriff.lib
+LIBRARY         libgstcontroller.lib
+LIBRARY         libgstvideo.lib
+LIBRARY  	libpng.lib
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstqtdemux.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,82 @@
+// Gstreamer.MMP
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          libgstqtdemux.dll
+TARGETTYPE      DLL
+UID             0x20004c49 0x0DE80E1F
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           SYMBIAN
+MACRO           HAVE_CONFIG_H
+MACRO           __SYMBIAN32__
+
+USERINCLUDE     ..
+USERINCLUDE     ../gst/qtdemux
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+
+SOURCEPATH      ../gst/qtdemux
+SOURCE          quicktime.c gstrtpxqtdepay.c qtdemux.c qtdemux_types.c qtdemux_dump.c
+
+
+LIBRARY         libc.lib
+LIBRARY         libglib.lib
+LIBRARY         libgobject.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         libgstbase.lib
+LIBRARY			libgstcontroller.lib
+LIBRARY			libgstaudio.lib
+LIBRARY         libm.lib libgstrtp.lib libgsttag.lib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/group/gstqtmux.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,94 @@
+// Gstreamer.MMP
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+#include <platform_paths.hrh>                                                            
+
+TARGET          gstqtmux.dll
+TARGETTYPE      DLL
+UID             0x20004c45 0x0EF80A1C
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO           HAVE_CONFIG_H
+
+
+USERINCLUDE     ..
+USERINCLUDE     ../gst/qtmux
+USERINCLUDE     ../gst-libs
+USERINCLUDE     ../gst-libs/gst
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer/gst/audio
+USERINCLUDE		../../include/gstreamer/gst/cdda
+USERINCLUDE		../../include/gstreamer/gst/floatcast
+USERINCLUDE		../../include/gstreamer/gst/interfaces
+USERINCLUDE		../../include/gstreamer/gst/netbuffer
+USERINCLUDE		../../include/gstreamer/gst/riff
+USERINCLUDE		../../include/gstreamer/gst/rtp
+USERINCLUDE		../../include/gstreamer/gst/tag
+USERINCLUDE		../../include/gstreamer/gst/video
+
+SOURCEPATH ../gst/qtmux
+SOURCE atoms.c descriptors.c gstqtmux.c gstqtmuxmap.c properties.c
+ 
+LIBRARY         euser.lib
+LIBRARY         libc.lib
+LIBRARY         libpthread.lib
+LIBRARY         libdl.lib
+LIBRARY         libglib.lib
+LIBRARY         libgmodule.lib
+
+LIBRARY         libgobject.lib
+LIBRARY         libgthread.lib
+LIBRARY         libm.lib
+LIBRARY         libz.lib
+LIBRARY         libgstreamer.lib
+LIBRARY         LIBGSTRIFF.lib
+LIBRARY         libgstbase.lib
+LIBRARY         libgstaudio.lib
+LIBRARY         libgstinterfaces.lib
+
+#ifdef WINSCW
+LIBRARY		ewsd.lib //wsd solution
+#endif
+
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/alpha/gstalpha.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,930 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2007> Wim Taymans <wim.taymans@collabora.co.uk>
+ * Copyright (C) <2007> Edward Hervey <edward.hervey@collabora.co.uk>
+ * Copyright (C) <2007> Jan Schmidt <thaytan@noraisin.net>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/video/video.h>
+#include <gst/controller/gstcontroller.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI  3.14159265358979323846
+#endif
+
+#define GST_TYPE_ALPHA \
+  (gst_alpha_get_type())
+#define GST_ALPHA(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALPHA,GstAlpha))
+#define GST_ALPHA_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALPHA,GstAlphaClass))
+#define GST_IS_ALPHA(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALPHA))
+#define GST_IS_ALPHA_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALPHA))
+
+typedef struct _GstAlpha GstAlpha;
+typedef struct _GstAlphaClass GstAlphaClass;
+
+typedef enum
+{
+  ALPHA_METHOD_SET,
+  ALPHA_METHOD_GREEN,
+  ALPHA_METHOD_BLUE,
+  ALPHA_METHOD_CUSTOM,
+}
+GstAlphaMethod;
+
+GST_DEBUG_CATEGORY_STATIC (gst_alpha_debug);
+#define GST_CAT_DEFAULT gst_alpha_debug
+
+struct _GstAlpha
+{
+  GstBaseTransform parent;
+
+  /* caps */
+  GstVideoFormat format;
+  gint width, height;
+  gboolean ayuv;
+
+  gdouble alpha;
+
+  guint target_r;
+  guint target_g;
+  guint target_b;
+
+  GstAlphaMethod method;
+
+  gfloat angle;
+  gfloat noise_level;
+  guint black_sensitivity;
+  guint white_sensitivity;
+
+  gfloat y;                     /* chroma color */
+  gint8 cb, cr;
+  gint8 kg;
+  gfloat accept_angle_cos;
+  gfloat accept_angle_sin;
+  guint8 accept_angle_tg;
+  guint8 accept_angle_ctg;
+  guint8 one_over_kc;
+  guint8 kfgy_scale;
+};
+
+struct _GstAlphaClass
+{
+  GstBaseTransformClass parent_class;
+};
+
+/* elementfactory information */
+static const GstElementDetails gst_alpha_details =
+GST_ELEMENT_DETAILS ("Alpha filter",
+    "Filter/Effect/Video",
+    "Adds an alpha channel to video - uniform or via chroma-keying",
+    "Wim Taymans <wim@fluendo.com>\n"
+    "Edward Hervey <edward.hervey@collabora.co.uk>\n"
+    "Jan Schmidt <thaytan@noraisin.net>");
+
+/* Alpha signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+#define DEFAULT_METHOD ALPHA_METHOD_SET
+#define DEFAULT_ALPHA 1.0
+#define DEFAULT_TARGET_R 0
+#define DEFAULT_TARGET_G 255
+#define DEFAULT_TARGET_B 0
+#define DEFAULT_ANGLE 20.0
+#define DEFAULT_NOISE_LEVEL 2.0
+#define DEFAULT_BLACK_SENSITIVITY 100
+#define DEFAULT_WHITE_SENSITIVITY 100
+
+enum
+{
+  PROP_0,
+  PROP_METHOD,
+  PROP_ALPHA,
+  PROP_TARGET_R,
+  PROP_TARGET_G,
+  PROP_TARGET_B,
+  PROP_ANGLE,
+  PROP_NOISE_LEVEL,
+  PROP_BLACK_SENSITIVITY,
+  PROP_WHITE_SENSITIVITY,
+  PROP_LAST
+};
+
+static GstStaticPadTemplate gst_alpha_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV"))
+    );
+
+static GstStaticPadTemplate gst_alpha_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" GST_VIDEO_CAPS_YUV ("I420")
+    )
+    );
+
+static gboolean gst_alpha_start (GstBaseTransform * trans);
+static gboolean gst_alpha_get_unit_size (GstBaseTransform * btrans,
+    GstCaps * caps, guint * size);
+static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
+    GstPadDirection direction, GstCaps * caps);
+static gboolean gst_alpha_set_caps (GstBaseTransform * btrans,
+    GstCaps * incaps, GstCaps * outcaps);
+static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans,
+    GstBuffer * in, GstBuffer * out);
+
+static void gst_alpha_init_params (GstAlpha * alpha);
+
+static void gst_alpha_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_alpha_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+GST_BOILERPLATE (GstAlpha, gst_alpha, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM);
+
+#define GST_TYPE_ALPHA_METHOD (gst_alpha_method_get_type())
+static GType
+gst_alpha_method_get_type (void)
+{
+  static GType alpha_method_type = 0;
+  static const GEnumValue alpha_method[] = {
+    {ALPHA_METHOD_SET, "Set/adjust alpha channel", "set"},
+    {ALPHA_METHOD_GREEN, "Chroma Key green", "green"},
+    {ALPHA_METHOD_BLUE, "Chroma Key blue", "blue"},
+    {ALPHA_METHOD_CUSTOM, "Chroma Key on target_r/g/b", "custom"},
+    {0, NULL, NULL},
+  };
+
+  if (!alpha_method_type) {
+    alpha_method_type = g_enum_register_static ("GstAlphaMethod", alpha_method);
+  }
+  return alpha_method_type;
+}
+
+static void
+gst_alpha_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (element_class, &gst_alpha_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_alpha_sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_alpha_src_template));
+
+  GST_DEBUG_CATEGORY_INIT (gst_alpha_debug, "alpha", 0,
+      "alpha - Element for adding alpha channel to streams");
+}
+static void
+gst_alpha_class_init (GstAlphaClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstBaseTransformClass *btrans_class;
+
+  gobject_class = (GObjectClass *) klass;
+  btrans_class = (GstBaseTransformClass *) klass;
+
+  gobject_class->set_property = gst_alpha_set_property;
+  gobject_class->get_property = gst_alpha_get_property;
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_METHOD,
+      g_param_spec_enum ("method", "Method",
+          "How the alpha channels should be created", GST_TYPE_ALPHA_METHOD,
+          DEFAULT_METHOD, (GParamFlags) G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALPHA,
+      g_param_spec_double ("alpha", "Alpha", "The value for the alpha channel",
+          0.0, 1.0, DEFAULT_ALPHA,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_R,
+      g_param_spec_uint ("target_r", "Target Red", "The Red target", 0, 255,
+          DEFAULT_TARGET_R,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_G,
+      g_param_spec_uint ("target_g", "Target Green", "The Green target", 0, 255,
+          DEFAULT_TARGET_G,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TARGET_B,
+      g_param_spec_uint ("target_b", "Target Blue", "The Blue target", 0, 255,
+          DEFAULT_TARGET_B,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANGLE,
+      g_param_spec_float ("angle", "Angle", "Size of the colorcube to change",
+          0.0, 90.0, DEFAULT_ANGLE,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NOISE_LEVEL,
+      g_param_spec_float ("noise_level", "Noise Level", "Size of noise radius",
+          0.0, 64.0, DEFAULT_NOISE_LEVEL,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass),
+      PROP_BLACK_SENSITIVITY, g_param_spec_uint ("black-sensitivity",
+          "Black Sensitivity", "Sensitivity to dark colors", 0, 128,
+          DEFAULT_BLACK_SENSITIVITY,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass),
+      PROP_WHITE_SENSITIVITY, g_param_spec_uint ("white-sensitivity",
+          "Sensitivity", "Sensitivity to bright colors", 0, 128,
+          DEFAULT_WHITE_SENSITIVITY,
+          (GParamFlags) G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+
+  btrans_class->start = GST_DEBUG_FUNCPTR (gst_alpha_start);
+  btrans_class->transform = GST_DEBUG_FUNCPTR (gst_alpha_transform);
+  btrans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_alpha_get_unit_size);
+  btrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_alpha_transform_caps);
+  btrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_alpha_set_caps);
+}
+
+static void
+gst_alpha_init (GstAlpha * alpha, GstAlphaClass * klass)
+{
+  alpha->alpha = DEFAULT_ALPHA;
+  alpha->method = DEFAULT_METHOD;
+  alpha->target_r = DEFAULT_TARGET_R;
+  alpha->target_g = DEFAULT_TARGET_G;
+  alpha->target_b = DEFAULT_TARGET_B;
+  alpha->angle = DEFAULT_ANGLE;
+  alpha->noise_level = DEFAULT_NOISE_LEVEL;
+  alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
+  alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
+}
+
+/* do we need this function? */
+static void
+gst_alpha_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAlpha *alpha;
+
+  g_return_if_fail (GST_IS_ALPHA (object));
+
+  alpha = GST_ALPHA (object);
+
+  switch (prop_id) {
+    case PROP_METHOD:
+      alpha->method = g_value_get_enum (value);
+      switch (alpha->method) {
+        case ALPHA_METHOD_GREEN:
+          alpha->target_r = 0;
+          alpha->target_g = 255;
+          alpha->target_b = 0;
+          break;
+        case ALPHA_METHOD_BLUE:
+          alpha->target_r = 0;
+          alpha->target_g = 0;
+          alpha->target_b = 255;
+          break;
+        default:
+          break;
+      }
+      gst_alpha_init_params (alpha);
+      break;
+    case PROP_ALPHA:
+      alpha->alpha = g_value_get_double (value);
+      break;
+    case PROP_TARGET_R:
+      alpha->target_r = g_value_get_uint (value);
+      gst_alpha_init_params (alpha);
+      break;
+    case PROP_TARGET_G:
+      alpha->target_g = g_value_get_uint (value);
+      gst_alpha_init_params (alpha);
+      break;
+    case PROP_TARGET_B:
+      alpha->target_b = g_value_get_uint (value);
+      gst_alpha_init_params (alpha);
+      break;
+    case PROP_ANGLE:
+      alpha->angle = g_value_get_float (value);
+      gst_alpha_init_params (alpha);
+      break;
+    case PROP_NOISE_LEVEL:
+      alpha->noise_level = g_value_get_float (value);
+      gst_alpha_init_params (alpha);
+      break;
+    case PROP_BLACK_SENSITIVITY:
+      alpha->black_sensitivity = g_value_get_uint (value);
+      break;
+    case PROP_WHITE_SENSITIVITY:
+      alpha->white_sensitivity = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+static void
+gst_alpha_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstAlpha *alpha;
+
+  g_return_if_fail (GST_IS_ALPHA (object));
+
+  alpha = GST_ALPHA (object);
+
+  switch (prop_id) {
+    case PROP_METHOD:
+      g_value_set_enum (value, alpha->method);
+      break;
+    case PROP_ALPHA:
+      g_value_set_double (value, alpha->alpha);
+      break;
+    case PROP_TARGET_R:
+      g_value_set_uint (value, alpha->target_r);
+      break;
+    case PROP_TARGET_G:
+      g_value_set_uint (value, alpha->target_g);
+      break;
+    case PROP_TARGET_B:
+      g_value_set_uint (value, alpha->target_b);
+      break;
+    case PROP_ANGLE:
+      g_value_set_float (value, alpha->angle);
+      break;
+    case PROP_NOISE_LEVEL:
+      g_value_set_float (value, alpha->noise_level);
+      break;
+    case PROP_BLACK_SENSITIVITY:
+      g_value_set_uint (value, alpha->black_sensitivity);
+      break;
+    case PROP_WHITE_SENSITIVITY:
+      g_value_set_uint (value, alpha->white_sensitivity);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_alpha_get_unit_size (GstBaseTransform * btrans,
+    GstCaps * caps, guint * size)
+{
+  GstVideoFormat format;
+  gint width, height;
+
+  if (!gst_video_format_parse_caps (caps, &format, &width, &height))
+    return FALSE;
+
+  *size = gst_video_format_get_size (format, width, height);
+
+  GST_DEBUG_OBJECT (btrans, "unit size = %d for format %d w %d height %d",
+      *size, format, width, height);
+
+  return TRUE;
+}
+
+static GstCaps *
+gst_alpha_transform_caps (GstBaseTransform * btrans,
+    GstPadDirection direction, GstCaps * caps)
+{
+  GstCaps *ret;
+  GstStructure *structure;
+  gint i;
+
+  ret = gst_caps_copy (caps);
+
+  /* When going from the SINK pad to the src, we just need to make sure the
+   * format is AYUV */
+  if (direction == GST_PAD_SINK) {
+    for (i = 0; i < gst_caps_get_size (ret); i++) {
+      structure = gst_caps_get_structure (ret, i);
+      gst_structure_set (structure, "format",
+          GST_TYPE_FOURCC, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), NULL);
+    }
+  } else {
+    GstCaps *ayuv_caps;
+
+    /* In the other direction, prepend a copy of the caps with format AYUV, 
+     * and set the first to I420 */
+    ayuv_caps = gst_caps_copy (ret);
+
+    for (i = 0; i < gst_caps_get_size (ret); i++) {
+      structure = gst_caps_get_structure (ret, i);
+      gst_structure_set (structure, "format",
+          GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL);
+    }
+
+    gst_caps_append (ret, ayuv_caps);
+  }
+
+  gst_caps_do_simplify (ret);
+
+  return ret;
+}
+
+static gboolean
+gst_alpha_set_caps (GstBaseTransform * btrans,
+    GstCaps * incaps, GstCaps * outcaps)
+{
+  GstAlpha *alpha = GST_ALPHA (btrans);
+
+  if (!gst_video_format_parse_caps (incaps, &alpha->format,
+          &alpha->width, &alpha->height))
+    return FALSE;
+
+  if (alpha->format == GST_VIDEO_FORMAT_AYUV)
+    alpha->ayuv = TRUE;
+  else
+    alpha->ayuv = FALSE;
+
+  return TRUE;
+}
+
+static void
+gst_alpha_set_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
+    gdouble alpha)
+{
+  gint b_alpha = (gint) (alpha * 255);
+  gint y, x;
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      *dest++ = (*src++ * b_alpha) >> 8;
+      *dest++ = *src++;
+      *dest++ = *src++;
+      *dest++ = *src++;
+    }
+  }
+}
+
+static void
+gst_alpha_set_i420 (guint8 * src, guint8 * dest, gint width, gint height,
+    gdouble alpha)
+{
+  gint b_alpha = (gint) (alpha * 255);
+  guint8 *srcY;
+  guint8 *srcU;
+  guint8 *srcV;
+  gint i, j;
+  gint src_wrap, src_uv_wrap;
+  gint y_stride, uv_stride;
+  gboolean odd_width;
+
+  y_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, width);
+  uv_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, width);
+
+  src_wrap = y_stride - width;
+  src_uv_wrap = uv_stride - (width / 2);
+
+  srcY = src;
+  srcU = src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+      1, width, height);
+  srcV = src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+      2, width, height);
+
+  odd_width = (width % 2 != 0);
+
+  for (i = 0; i < height; i++) {
+    for (j = 0; j < width / 2; j++) {
+      *dest++ = b_alpha;
+      *dest++ = *srcY++;
+      *dest++ = *srcU;
+      *dest++ = *srcV;
+      *dest++ = b_alpha;
+      *dest++ = *srcY++;
+      *dest++ = *srcU++;
+      *dest++ = *srcV++;
+    }
+    /* Might have one odd column left to do */
+    if (odd_width) {
+      *dest++ = b_alpha;
+      *dest++ = *srcY++;
+      *dest++ = *srcU;
+      *dest++ = *srcV;
+    }
+    if (i % 2 == 0) {
+      srcU -= width / 2;
+      srcV -= width / 2;
+    } else {
+      srcU += src_uv_wrap;
+      srcV += src_uv_wrap;
+    }
+    srcY += src_wrap;
+  }
+}
+
+static void
+gst_alpha_chroma_key_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
+    GstAlpha * alpha)
+{
+  gint b_alpha;
+  guint8 *src1;
+  guint8 *dest1;
+  gint i, j;
+  gint x, z, u, v, y, a;
+  gint tmp, tmp1;
+  gint x1, y1;
+  gint smin, smax;
+
+  smin = 128 - alpha->black_sensitivity;
+  smax = 128 + alpha->white_sensitivity;
+
+  src1 = src;
+  dest1 = dest;
+
+  for (i = 0; i < height; i++) {
+    for (j = 0; j < width; j++) {
+      a = *src1++ * (alpha->alpha);
+      y = *src1++;
+      u = *src1++ - 128;
+      v = *src1++ - 128;
+
+      if (y < smin || y > smax) {
+        /* too dark or too bright, keep alpha */
+        b_alpha = a;
+      } else {
+        /* Convert foreground to XZ coords where X direction is defined by
+           the key color */
+        tmp = ((short) u * alpha->cb + (short) v * alpha->cr) >> 7;
+        x = CLAMP (tmp, -128, 127);
+        tmp = ((short) v * alpha->cb - (short) u * alpha->cr) >> 7;
+        z = CLAMP (tmp, -128, 127);
+
+        /* WARNING: accept angle should never be set greater than "somewhat less
+           than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
+           80 degrees should be enough if foreground is reasonable. If this seems
+           to be a problem, go to alternative ways of checking point position
+           (scalar product or line equations). This angle should not be too small
+           either to avoid infinite ctg (used to suppress foreground without use of
+           division) */
+
+        tmp = ((short) (x) * alpha->accept_angle_tg) >> 4;
+        tmp = MIN (tmp, 127);
+
+        if (abs (z) > tmp) {
+          /* keep foreground Kfg = 0 */
+          b_alpha = a;
+        } else {
+          /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
+             according to Kfg */
+          tmp = ((short) (z) * alpha->accept_angle_ctg) >> 4;
+          tmp = CLAMP (tmp, -128, 127);
+          x1 = abs (tmp);
+          y1 = z;
+
+          tmp1 = x - x1;
+          tmp1 = MAX (tmp1, 0);
+          b_alpha = (((unsigned char) (tmp1) *
+                  (unsigned short) (alpha->one_over_kc)) / 2);
+          b_alpha = 255 - CLAMP (b_alpha, 0, 255);
+          b_alpha = (a * b_alpha) >> 8;
+
+          tmp = ((unsigned short) (tmp1) * alpha->kfgy_scale) >> 4;
+          tmp1 = MIN (tmp, 255);
+
+          tmp = y - tmp1;
+          y = MAX (tmp, 0);
+
+          /* Convert suppressed foreground back to CbCr */
+          tmp = ((char) (x1) * (short) (alpha->cb) -
+              (char) (y1) * (short) (alpha->cr)) >> 7;
+          u = CLAMP (tmp, -128, 127);
+
+          tmp = ((char) (x1) * (short) (alpha->cr) +
+              (char) (y1) * (short) (alpha->cb)) >> 7;
+          v = CLAMP (tmp, -128, 127);
+
+          /* Deal with noise. For now, a circle around the key color with
+             radius of noise_level treated as exact key color. Introduces
+             sharp transitions.
+           */
+          tmp = z * (short) (z) + (x - alpha->kg) * (short) (x - alpha->kg);
+          tmp = MIN (tmp, 0xffff);
+
+          if (tmp < alpha->noise_level * alpha->noise_level) {
+            b_alpha = 0;
+          }
+        }
+      }
+
+      u += 128;
+      v += 128;
+
+      *dest1++ = b_alpha;
+      *dest1++ = y;
+      *dest1++ = u;
+      *dest1++ = v;
+    }
+  }
+}
+
+static void
+gst_alpha_chromakey_row_i420 (GstAlpha * alpha, guint8 * dest1, guint8 * dest2,
+    guint8 * srcY1, guint8 * srcY2, guint8 * srcU, guint8 * srcV, gint width)
+{
+  gint xpos;
+  gint b_alpha;
+  gint x, z, u, v, y11, y12, y21, y22, a;
+  gint tmp, tmp1;
+  gint x1, y1;
+  gint smin, smax;
+
+  a = 255 * alpha->alpha;
+  smin = 128 - alpha->black_sensitivity;
+  smax = 128 + alpha->white_sensitivity;
+
+  for (xpos = 0; xpos < width / 2; xpos++) {
+    y11 = *srcY1++;
+    y12 = *srcY1++;
+    y21 = *srcY2++;
+    y22 = *srcY2++;
+    u = *srcU++ - 128;
+    v = *srcV++ - 128;
+
+    if (y11 < smin || y11 > smax ||
+        y12 < smin || y12 > smax ||
+        y21 < smin || y21 > smax || y22 < smin || y22 > smax) {
+      /* too dark or too bright, make opaque */
+      b_alpha = 255;
+    } else {
+      /* Convert foreground to XZ coords where X direction is defined by
+         the key color */
+      tmp = ((short) u * alpha->cb + (short) v * alpha->cr) >> 7;
+      x = CLAMP (tmp, -128, 127);
+      tmp = ((short) v * alpha->cb - (short) u * alpha->cr) >> 7;
+      z = CLAMP (tmp, -128, 127);
+
+      /* WARNING: accept angle should never be set greater than "somewhat less
+         than 90 degrees" to avoid dealing with negative/infinite tg. In reality,
+         80 degrees should be enough if foreground is reasonable. If this seems
+         to be a problem, go to alternative ways of checking point position
+         (scalar product or line equations). This angle should not be too small
+         either to avoid infinite ctg (used to suppress foreground without use of
+         division) */
+
+      tmp = ((short) (x) * alpha->accept_angle_tg) >> 4;
+      tmp = MIN (tmp, 127);
+
+      if (abs (z) > tmp) {
+        /* keep foreground Kfg = 0 */
+        b_alpha = 255;
+      } else {
+        /* Compute Kfg (implicitly) and Kbg, suppress foreground in XZ coord
+           according to Kfg */
+        tmp = ((short) (z) * alpha->accept_angle_ctg) >> 4;
+        tmp = CLAMP (tmp, -128, 127);
+        x1 = abs (tmp);
+        y1 = z;
+
+        tmp1 = x - x1;
+        tmp1 = MAX (tmp1, 0);
+        b_alpha = (((unsigned char) (tmp1) *
+                (unsigned short) (alpha->one_over_kc)) / 2);
+        b_alpha = 255 - CLAMP (b_alpha, 0, 255);
+        b_alpha = (a * b_alpha) >> 8;
+
+        tmp = ((unsigned short) (tmp1) * alpha->kfgy_scale) >> 4;
+        tmp1 = MIN (tmp, 255);
+
+        tmp = y11 - tmp1;
+        y11 = MAX (tmp, 0);
+        tmp = y12 - tmp1;
+        y12 = MAX (tmp, 0);
+        tmp = y21 - tmp1;
+        y21 = MAX (tmp, 0);
+        tmp = y22 - tmp1;
+        y22 = MAX (tmp, 0);
+
+        /* Convert suppressed foreground back to CbCr */
+        tmp = ((char) (x1) * (short) (alpha->cb) -
+            (char) (y1) * (short) (alpha->cr)) >> 7;
+        u = CLAMP (tmp, -128, 127);
+
+        tmp = ((char) (x1) * (short) (alpha->cr) +
+            (char) (y1) * (short) (alpha->cb)) >> 7;
+        v = CLAMP (tmp, -128, 127);
+
+        /* Deal with noise. For now, a circle around the key color with
+           radius of noise_level treated as exact key color. Introduces
+           sharp transitions.
+         */
+        tmp = z * (short) (z) + (x - alpha->kg) * (short) (x - alpha->kg);
+        tmp = MIN (tmp, 0xffff);
+
+        if (tmp < alpha->noise_level * alpha->noise_level) {
+          /* Uncomment this if you want total suppression within the noise circle */
+          b_alpha = 0;
+        }
+      }
+    }
+
+    u += 128;
+    v += 128;
+
+    *dest1++ = b_alpha;
+    *dest1++ = y11;
+    *dest1++ = u;
+    *dest1++ = v;
+    *dest1++ = b_alpha;
+    *dest1++ = y12;
+    *dest1++ = u;
+    *dest1++ = v;
+
+    *dest2++ = b_alpha;
+    *dest2++ = y21;
+    *dest2++ = u;
+    *dest2++ = v;
+    *dest2++ = b_alpha;
+    *dest2++ = y22;
+    *dest2++ = u;
+    *dest2++ = v;
+  }
+}
+
+/* based on http://www.cs.utah.edu/~michael/chroma/
+ */
+static void
+gst_alpha_chroma_key_i420 (guint8 * src, guint8 * dest, gint width, gint height,
+    GstAlpha * alpha)
+{
+  guint8 *srcY1, *srcY2, *srcU, *srcV;
+  guint8 *dest1, *dest2;
+  gint ypos;
+  gint dest_stride, src_y_stride, src_uv_stride;
+
+  dest_stride =
+      gst_video_format_get_row_stride (GST_VIDEO_FORMAT_AYUV, 0, width);
+  src_y_stride =
+      gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, width);
+  src_uv_stride =
+      gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, width);
+
+  srcY1 = src;
+  srcY2 = src + src_y_stride;
+
+  srcU = src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+      1, width, height);
+  srcV = src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+      2, width, height);
+
+  dest1 = dest;
+  dest2 = dest + dest_stride;
+
+  /* Redefine Y strides to skip 2 lines at a time ... */
+  dest_stride *= 2;
+  src_y_stride *= 2;
+
+  for (ypos = 0; ypos < height / 2; ypos++) {
+
+    gst_alpha_chromakey_row_i420 (alpha, dest1, dest2,
+        srcY1, srcY2, srcU, srcV, width);
+
+    dest1 += dest_stride;
+    dest2 += dest_stride;
+    srcY1 += src_y_stride;
+    srcY2 += src_y_stride;
+    srcU += src_uv_stride;
+    srcV += src_uv_stride;
+  }
+}
+
+static void
+gst_alpha_init_params (GstAlpha * alpha)
+{
+  float kgl;
+  float tmp;
+  float tmp1, tmp2;
+
+  alpha->y =
+      0.257 * alpha->target_r + 0.504 * alpha->target_g +
+      0.098 * alpha->target_b;
+  tmp1 =
+      -0.148 * alpha->target_r - 0.291 * alpha->target_g +
+      0.439 * alpha->target_b;
+  tmp2 =
+      0.439 * alpha->target_r - 0.368 * alpha->target_g -
+      0.071 * alpha->target_b;
+  kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
+  alpha->cb = 127 * (tmp1 / kgl);
+  alpha->cr = 127 * (tmp2 / kgl);
+
+  alpha->accept_angle_cos = cos (M_PI * alpha->angle / 180);
+  alpha->accept_angle_sin = sin (M_PI * alpha->angle / 180);
+  tmp = 15 * tan (M_PI * alpha->angle / 180);
+  tmp = MIN (tmp, 255);
+  alpha->accept_angle_tg = tmp;
+  tmp = 15 / tan (M_PI * alpha->angle / 180);
+  tmp = MIN (tmp, 255);
+  alpha->accept_angle_ctg = tmp;
+  tmp = 1 / (kgl);
+  alpha->one_over_kc = 255 * 2 * tmp - 255;
+  tmp = 15 * (float) (alpha->y) / kgl;
+  tmp = MIN (tmp, 255);
+  alpha->kfgy_scale = tmp;
+  alpha->kg = MIN (kgl, 127);
+}
+
+static gboolean
+gst_alpha_start (GstBaseTransform * btrans)
+{
+  GstAlpha *alpha = GST_ALPHA (btrans);
+
+  gst_alpha_init_params (alpha);
+
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
+{
+  GstAlpha *alpha = GST_ALPHA (btrans);
+  gint width, height;
+  GstClockTime timestamp;
+
+  width = alpha->width;
+  height = alpha->height;
+
+  GST_BUFFER_TIMESTAMP (out) = GST_BUFFER_TIMESTAMP (in);
+  GST_BUFFER_DURATION (out) = GST_BUFFER_DURATION (in);
+  timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME,
+      GST_BUFFER_TIMESTAMP (in));
+  GST_LOG ("Got stream time of %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
+  if (GST_CLOCK_TIME_IS_VALID (timestamp))
+    gst_object_sync_values (G_OBJECT (alpha), timestamp);
+
+  switch (alpha->method) {
+    case ALPHA_METHOD_SET:
+      if (alpha->ayuv) {
+        gst_alpha_set_ayuv (GST_BUFFER_DATA (in),
+            GST_BUFFER_DATA (out), width, height, alpha->alpha);
+      } else {
+        gst_alpha_set_i420 (GST_BUFFER_DATA (in),
+            GST_BUFFER_DATA (out), width, height, alpha->alpha);
+      }
+      break;
+    case ALPHA_METHOD_GREEN:
+    case ALPHA_METHOD_BLUE:
+    case ALPHA_METHOD_CUSTOM:
+      if (alpha->ayuv) {
+        gst_alpha_chroma_key_ayuv (GST_BUFFER_DATA (in),
+            GST_BUFFER_DATA (out), width, height, alpha);
+      } else {
+        gst_alpha_chroma_key_i420 (GST_BUFFER_DATA (in),
+            GST_BUFFER_DATA (out), width, height, alpha);
+      }
+      break;
+    default:
+      break;
+  }
+
+  return GST_FLOW_OK;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  gst_controller_init (NULL, NULL);
+
+  return gst_element_register (plugin, "alpha", GST_RANK_NONE, GST_TYPE_ALPHA);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "alpha",
+    "adds an alpha channel to video - constant or via chroma-keying",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+
+#ifdef __SYMBIAN32__
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+    return &gst_plugin_desc;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/alpha/gstalphacolor.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,279 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-alphacolor
+ *
+ * The alphacolor element does memory-efficient (in-place) colourspace
+ * conversion from RGBA to AYUV, preserving the alpha channel.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstalphacolor.h"
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+#include <string.h>
+
+GST_DEBUG_CATEGORY_STATIC (alpha_color_debug);
+#define GST_CAT_DEFAULT alpha_color_debug
+
+/* elementfactory information */
+static const GstElementDetails gst_alpha_color_details =
+GST_ELEMENT_DETAILS ("Alpha color filter",
+    "Filter/Effect/Video",
+    "RGBA to AYUV colorspace conversion preserving the alpha channel",
+    "Wim Taymans <wim@fluendo.com>");
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA)
+    );
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV"))
+    );
+
+GST_BOILERPLATE (GstAlphaColor, gst_alpha_color, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM);
+
+static GstCaps *gst_alpha_color_transform_caps (GstBaseTransform * btrans,
+    GstPadDirection direction, GstCaps * caps);
+static gboolean gst_alpha_color_set_caps (GstBaseTransform * btrans,
+    GstCaps * incaps, GstCaps * outcaps);
+static GstFlowReturn gst_alpha_color_transform_ip (GstBaseTransform * btrans,
+    GstBuffer * inbuf);
+
+static void
+gst_alpha_color_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (element_class, &gst_alpha_color_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+}
+
+static void
+gst_alpha_color_class_init (GstAlphaColorClass * klass)
+{
+  GstBaseTransformClass *gstbasetransform_class;
+
+  gstbasetransform_class = (GstBaseTransformClass *) klass;
+
+  gstbasetransform_class->transform_caps =
+      GST_DEBUG_FUNCPTR (gst_alpha_color_transform_caps);
+  gstbasetransform_class->set_caps =
+      GST_DEBUG_FUNCPTR (gst_alpha_color_set_caps);
+  gstbasetransform_class->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_alpha_color_transform_ip);
+
+  GST_DEBUG_CATEGORY_INIT (alpha_color_debug, "alphacolor", 0,
+      "RGB->YUV colorspace conversion preserving the alpha channels");
+}
+
+static void
+gst_alpha_color_init (GstAlphaColor * alpha, GstAlphaColorClass * g_class)
+{
+  GstBaseTransform *btrans = NULL;
+
+  btrans = GST_BASE_TRANSFORM (alpha);
+
+  btrans->always_in_place = TRUE;
+}
+
+static GstCaps *
+gst_alpha_color_transform_caps (GstBaseTransform * btrans,
+    GstPadDirection direction, GstCaps * caps)
+{
+  const GstCaps *tmpl_caps = NULL;
+  GstCaps *result = NULL, *local_caps = NULL;
+  guint i;
+
+  local_caps = gst_caps_copy (caps);
+
+  for (i = 0; i < gst_caps_get_size (local_caps); i++) {
+    GstStructure *structure = gst_caps_get_structure (local_caps, i);
+
+    /* Throw away the structure name and set it to transformed format */
+    if (direction == GST_PAD_SINK) {
+      gst_structure_set_name (structure, "video/x-raw-yuv");
+    } else if (direction == GST_PAD_SRC) {
+      gst_structure_set_name (structure, "video/x-raw-rgb");
+    }
+    /* Remove any specific parameter from the structure */
+    gst_structure_remove_field (structure, "format");
+    gst_structure_remove_field (structure, "endianness");
+    gst_structure_remove_field (structure, "depth");
+    gst_structure_remove_field (structure, "bpp");
+    gst_structure_remove_field (structure, "red_mask");
+    gst_structure_remove_field (structure, "green_mask");
+    gst_structure_remove_field (structure, "blue_mask");
+    gst_structure_remove_field (structure, "alpha_mask");
+  }
+
+  /* Get the appropriate template */
+  if (direction == GST_PAD_SINK) {
+    tmpl_caps = gst_static_pad_template_get_caps (&src_template);
+  } else if (direction == GST_PAD_SRC) {
+    tmpl_caps = gst_static_pad_template_get_caps (&sink_template);
+  }
+
+  /* Intersect with our template caps */
+  result = gst_caps_intersect (local_caps, tmpl_caps);
+
+  gst_caps_unref (local_caps);
+  gst_caps_do_simplify (result);
+
+  GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, result);
+
+  return result;
+}
+
+static gboolean
+gst_alpha_color_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
+    GstCaps * outcaps)
+{
+  GstAlphaColor *alpha;
+  GstStructure *structure;
+  gboolean ret;
+  const GValue *fps;
+  gint red_mask, alpha_mask;
+  gint w, h, depth, bpp;
+
+  alpha = GST_ALPHA_COLOR (btrans);
+  structure = gst_caps_get_structure (incaps, 0);
+
+  ret = gst_structure_get_int (structure, "width", &w);
+  ret &= gst_structure_get_int (structure, "height", &h);
+  fps = gst_structure_get_value (structure, "framerate");
+  ret &= (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
+  ret &= gst_structure_get_int (structure, "red_mask", &red_mask);
+
+  /* make sure these are really full RGBA caps */
+  ret &= gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
+  ret &= gst_structure_get_int (structure, "depth", &depth);
+  ret &= gst_structure_get_int (structure, "bpp", &bpp);
+
+  if (!ret || alpha_mask == 0 || red_mask == 0 || depth != 32 || bpp != 32) {
+    GST_DEBUG_OBJECT (alpha, "incomplete or non-RGBA input caps!");
+    return FALSE;
+  }
+
+  alpha->in_width = w;
+  alpha->in_height = h;
+  alpha->in_rgba = TRUE;
+#if (G_BYTE_ORDER == G_BIG_ENDIAN)
+  if (red_mask != 0x000000ff)
+#else
+  if (red_mask != 0xff000000)
+#endif
+    alpha->in_rgba = FALSE;
+
+  return TRUE;
+}
+
+static void
+transform_rgb (guint8 * data, gint size)
+{
+  guint8 y, u, v;
+
+  while (size > 0) {
+    y = data[0] * 0.299 + data[1] * 0.587 + data[2] * 0.114 + 0;
+    u = data[0] * -0.169 + data[1] * -0.332 + data[2] * 0.500 + 128;
+    v = data[0] * 0.500 + data[1] * -0.419 + data[2] * -0.0813 + 128;
+
+    data[0] = data[3];
+    data[1] = y;
+    data[2] = u;
+    data[3] = v;
+
+    data += 4;
+    size -= 4;
+  }
+}
+
+static void
+transform_bgr (guint8 * data, gint size)
+{
+  guint8 y, u, v;
+
+  while (size > 0) {
+    y = data[2] * 0.299 + data[1] * 0.587 + data[0] * 0.114 + 0;
+    u = data[2] * -0.169 + data[1] * -0.332 + data[0] * 0.500 + 128;
+    v = data[2] * 0.500 + data[1] * -0.419 + data[0] * -0.0813 + 128;
+
+    data[0] = data[3];
+    data[1] = y;
+    data[2] = u;
+    data[3] = v;
+
+    data += 4;
+    size -= 4;
+  }
+}
+
+static GstFlowReturn
+gst_alpha_color_transform_ip (GstBaseTransform * btrans, GstBuffer * inbuf)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstAlphaColor *alpha;
+
+  alpha = GST_ALPHA_COLOR (btrans);
+
+  /* Transform in place */
+  if (alpha->in_rgba)
+    transform_rgb (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
+  else
+    transform_bgr (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
+
+  return ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "alphacolor", GST_RANK_NONE,
+      GST_TYPE_ALPHA_COLOR);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "alphacolor",
+    "RGBA to AYUV colorspace conversion preserving the alpha channel",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+
+#ifdef __SYMBIAN32__
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+    return &gst_plugin_desc;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/alpha/gstalphacolor.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,57 @@
+/* GStreamer alphacolor element
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.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_ALPHA_COLOR_H_
+#define _GST_ALPHA_COLOR_H_
+
+#include <gst/base/gstbasetransform.h>
+
+#define GST_TYPE_ALPHA_COLOR \
+  (gst_alpha_color_get_type())
+#define GST_ALPHA_COLOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALPHA_COLOR,GstAlphaColor))
+#define GST_ALPHA_COLOR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALPHA_COLOR,GstAlphaColorClass))
+#define GST_IS_ALPHA_COLOR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALPHA_COLOR))
+#define GST_IS_ALPHA_COLOR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALPHA_COLOR))
+
+typedef struct _GstAlphaColor GstAlphaColor;
+typedef struct _GstAlphaColorClass GstAlphaColorClass;
+
+struct _GstAlphaColor
+{
+  GstBaseTransform element;
+
+  /*< private >*/
+  /* caps */
+  gint in_width, in_height;
+  gboolean in_rgba;
+  gint out_width, out_height;
+};
+
+struct _GstAlphaColorClass
+{
+  GstBaseTransformClass parent_class;
+};
+
+GType   gst_alpha_color_get_type (void);
+
+#endif /* _GST_ALPHA_COLOR_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/amrmux/gstamrmux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,321 @@
+/*
+ *  Copyright © 2010 Nokia Corporation.
+ *  This material, including documentation and any related
+ *  computer progrs, is protected by copyright controlled by
+ *  Nokia Corporation. All rights are reserved. Copying,
+ *  including reproducing, storing, adapting or translating, any
+ *  or all of this material requires the prior written consent of
+ *  Nokia Corporation. This material also contains confidential
+ *  information which may not be disclosed to others without the
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "gstamrmux.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#ifdef __SYMBIAN32__
+#include <gst/gstinfo.h>
+#endif
+
+/* AMR nb header value */
+const char* amrnbmagicnumber = "#!AMR\n";
+
+static void gst_amrmux_base_init (gpointer g_class);
+static void gst_amrmux_class_init (GstAmrMuxClass * klass);
+static void gst_amrmux_init ( GstAmrMux * filter, GstAmrMuxClass *filter_klass);
+
+static GstFlowReturn gst_amrmux_chain (GstPad * pad, GstBuffer * buf);
+
+static void gst_amrmux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_amrmux_set_property (GObject *object, guint prop_id,
+                                     const GValue *value, GParamSpec *pspec);
+                                     
+static GstStateChangeReturn gst_amrmux_change_state (GstElement * element,
+    GstStateChange transition);
+
+static void gst_amrmux_dispose(GObject * object);
+
+static GstElementClass *parent_class= NULL;
+
+static const GstElementDetails gst_amrmux_details =
+GST_ELEMENT_DETAILS ("AMR MUX Details",
+        "Codec/Muxer/Audio",
+        "Adaptive Multi-Rate Narrow-Band Muxer",
+        "");
+
+static GstStaticPadTemplate sink_factory =
+GST_STATIC_PAD_TEMPLATE (
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_STATIC_CAPS ("audio/amr")
+);
+
+static GstStaticPadTemplate source_factory =
+GST_STATIC_PAD_TEMPLATE (
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_STATIC_CAPS ("audio/amr")
+);
+
+enum {
+  ARG_0,
+  ARG_HEADER
+};
+
+
+GType
+gst_amrmux_get_type (void)
+{
+  static GType gst_amrmux_type = 0;
+
+  if (!gst_amrmux_type) {
+    static const GTypeInfo amrmux_info = {
+      sizeof (GstAmrMuxClass),
+      gst_amrmux_base_init,
+      NULL,
+      (GClassInitFunc) gst_amrmux_class_init,
+      NULL,
+      NULL,
+      sizeof (GstAmrMux),
+      0,
+      (GInstanceInitFunc) gst_amrmux_init,
+    };
+
+    gst_amrmux_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstAmrMux",
+        &amrmux_info, 0);
+  }
+  return gst_amrmux_type;
+}
+
+
+static void
+gst_amrmux_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+   
+  gst_element_class_add_pad_template(element_class,
+    gst_static_pad_template_get(&sink_factory)); 
+  
+  gst_element_class_add_pad_template(element_class,
+  gst_static_pad_template_get(&source_factory));
+          
+  gst_element_class_set_details (element_class, &gst_amrmux_details);
+}
+
+static void
+gst_amrmux_class_init ( GstAmrMuxClass * klass )
+{
+  GObjectClass *object_class;
+  GstElementClass *gstelement_class;
+
+  gstelement_class = (GstElementClass *) klass;
+  object_class = (GObjectClass *) klass;
+
+  
+  object_class->set_property = gst_amrmux_set_property;
+  object_class->get_property = gst_amrmux_get_property;
+  
+  gstelement_class->change_state = gst_amrmux_change_state;
+  
+  object_class->dispose = gst_amrmux_dispose;
+  
+  parent_class = g_type_class_peek_parent(klass);
+  
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEADER,
+        g_param_spec_boolean ("header", "header",
+            "For writing AMR header", TRUE, G_PARAM_READWRITE));
+  
+ 
+ }
+
+static void gst_amrmux_dispose(GObject * object)
+{
+    G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_amrmux_init( GstAmrMux * amrmux, GstAmrMuxClass *amrmux_klass)
+{  
+   GstElementClass *klass = GST_ELEMENT_CLASS (amrmux_klass);
+   
+   //By default we have to write header   
+   amrmux->writeheader= TRUE;
+   
+   //Add Sink pad to this element
+      
+   amrmux->sinkpad = gst_pad_new_from_template (
+    gst_element_class_get_pad_template (klass, "sink"), "sink");  
+  
+  gst_element_add_pad (GST_ELEMENT (amrmux), amrmux->sinkpad);
+
+    
+  //Add Src pad to this element
+  amrmux->srcpad = gst_pad_new_from_template (
+    gst_element_class_get_pad_template (klass, "src"), "src");
+
+  gst_element_add_pad (GST_ELEMENT (amrmux), amrmux->srcpad);  
+    
+  gst_pad_set_chain_function (amrmux->sinkpad, gst_amrmux_chain);
+
+}
+
+
+static void
+gst_amrmux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+    
+  GstAmrMux *amrmux = GST_AMRMUX( object );
+  
+  switch (prop_id) {
+      case ARG_HEADER:
+            g_value_set_boolean (value, amrmux->writeheader);
+            break;
+          
+          default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+  }
+}
+
+
+static void
+gst_amrmux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+GstAmrMux *amrmux = GST_AMRMUX( object );
+  
+  switch (prop_id) {
+      case ARG_HEADER:
+          amrmux->writeheader = g_value_get_boolean (value);
+          break;
+        default:
+          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+          break;
+  }
+}
+
+
+
+static GstFlowReturn
+gst_amrmux_chain (GstPad * pad, GstBuffer * buf)
+{    
+  
+  gint8 *codecdata;
+  guint8* amrdata;
+  guint8* amrheaderstart; 
+  
+  int codecdatasize = GST_BUFFER_SIZE(buf); 
+   
+  int magicnumberlength = strlen( amrnbmagicnumber );   
+  
+  GstAmrMux *amrmux = GST_AMRMUX (GST_PAD_PARENT (pad)); 
+
+  if ( amrmux->writeheader )
+   {
+     
+      buf = gst_buffer_make_writable( buf );  
+      
+      //Allocate a buffer which will hold codec data + magic number
+      
+      amrdata = ( guint8* )g_malloc( GST_BUFFER_SIZE(buf) + magicnumberlength );
+      
+      //To save the starting address of amr data
+      
+      amrheaderstart = amrdata;
+      
+      //Copy magic number to newly allocated buffer
+      
+      memcpy( amrdata, amrnbmagicnumber, magicnumberlength);
+      
+      codecdata = (gint8*)GST_BUFFER_DATA (buf);  
+      
+      //Move the pointer to the end of magic number
+           
+      amrdata += magicnumberlength;
+      
+      //Copy codec data to newly allocated buffer
+           
+      memcpy( amrdata , codecdata, codecdatasize );
+      
+      // free codec data from GstBuffer
+      
+      g_free(  buf->malloc_data );
+      
+      //Copying the newly allocated buffer and size in GstBuffer
+      
+      buf->data = amrheaderstart;
+      
+      buf->malloc_data = amrheaderstart;
+      
+      buf->size+= magicnumberlength; 
+      
+      //Do it only first time
+      
+      amrmux->writeheader = FALSE;  
+   }  
+  
+  return gst_pad_push( amrmux->srcpad , buf );
+  
+}
+
+static GstStateChangeReturn
+gst_amrmux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstAmrMux *amrmux = GST_AMRMUX (element);
+  
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  
+  if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
+      return ret; 
+
+  switch (transition) {
+        case GST_STATE_CHANGE_READY_TO_NULL: 
+         {
+            amrmux->writeheader = TRUE; 
+            break;
+         }               
+      
+         default:
+            break;
+  }
+  
+  return ret;    
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ 
+  return gst_element_register (plugin, "amrmux", GST_RANK_PRIMARY,
+          GST_TYPE_AMRMUX);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "amrmux",
+    "Add header to amr-nb encoded stream",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+	return &gst_plugin_desc;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/amrmux/gstamrmux.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,63 @@
+/*
+ *  Copyright © 2010 Nokia Corporation.
+ *  This material, including documentation and any related
+ *  computer progrs, is protected by copyright controlled by
+ *  Nokia Corporation. All rights are reserved. Copying,
+ *  including reproducing, storing, adapting or translating, any
+ *  or all of this material requires the prior written consent of
+ *  Nokia Corporation. This material also contains confidential
+ *  information which may not be disclosed to others without the
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
+
+
+#ifndef __GST_AMRMUX_H__
+#define __GST_AMRMUX_H__
+
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AMRMUX \
+  (gst_amrmux_get_type())
+#define GST_AMRMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AMRMUX,GstAmrMux))
+#define GST_AMRMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AMRMUX,GstAmrMuxClass))
+#define GST_IS_AMRMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AMRMUX))
+#define GST_IS_AMRMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AMRMUX))
+
+
+typedef struct _GstAmrMux GstAmrMux;
+typedef struct _GstAmrMuxClass GstAmrMuxClass;
+
+/**
+ * GstAmrMux:
+ *
+ * 
+ */
+struct _GstAmrMux {
+  GstElement parent;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+    
+  /* Flag to decide whether to write amr header or not */
+  gboolean writeheader;  
+};
+
+struct _GstAmrMuxClass {
+  GstElementClass parent_class;
+};
+
+GType gst_amrmux_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_AMRMUX_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/amrmux/gstamrmux.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,58 @@
+/*
+ *  Copyright © 2010 Nokia Corporation.
+ *  This material, including documentation and any related
+ *  computer progrs, is protected by copyright controlled by
+ *  Nokia Corporation. All rights are reserved. Copying,
+ *  including reproducing, storing, adapting or translating, any
+ *  or all of this material requires the prior written consent of
+ *  Nokia Corporation. This material also contains confidential
+ *  information which may not be disclosed to others without the
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
+
+#include <platform_paths.hrh>                                                            
+
+TARGET			  libgstamrmux.dll
+TARGETTYPE		DLL
+UID           0x2002C38F 0x2002C390 
+
+#ifdef EKA2
+LANG            SC
+CAPABILITY All -Tcb
+VENDORID        VID_DEFAULT
+
+#endif
+
+#if !defined(__WINSCW__) && !defined(__WINS__)
+EpocAllowDllData
+#endif
+
+MACRO			HAVE_CONFIG_H
+
+
+
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+OS_LAYER_GLIB_SYSTEMINCLUDE
+
+
+USERINCLUDE		../../../include/gstreamer
+USERINCLUDE		../../../include/gstreamer/gst
+USERINCLUDE		../../../include/gstreamer/gst/base
+USERINCLUDE		../../../include/gstreamer/gst/controller
+USERINCLUDE		../../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../../include/gstreamer/gst/net
+
+
+
+SOURCEPATH	  ../gst/amrmux
+SOURCE		    gstamrmux.c
+
+
+LIBRARY 		libc.lib
+LIBRARY			libglib.lib
+LIBRARY			libgmodule.lib
+LIBRARY			libgobject.lib
+LIBRARY			libgstreamer.lib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioamplify.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,495 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-audioamplify
+ *
+ * Amplifies an audio stream by a given factor and allows the selection of different clipping modes.
+ * The difference between the clipping modes is best evaluated by testing.
+ * <title>Example launch line</title>
+ * <refsect2>
+ * |[
+ * gst-launch audiotestsrc wave=saw ! audioamplify amplification=1.5 ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioamplify amplification=1.5 method=wrap-negative ! alsasink
+ * gst-launch audiotestsrc wave=saw ! audioconvert ! audioamplify amplification=1.5 method=wrap-positive ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audioamplify.h"
+
+#define GST_CAT_DEFAULT gst_audio_amplify_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("Audio amplifier",
+    "Filter/Effect/Audio",
+    "Amplifies an audio stream by a given factor",
+    "Sebastian Dröge <slomo@circular-chaos.org>");
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_AMPLIFICATION,
+  PROP_CLIPPING_METHOD
+};
+
+enum
+{
+  METHOD_CLIP = 0,
+  METHOD_WRAP_NEGATIVE,
+  METHOD_WRAP_POSITIVE,
+  METHOD_NOCLIP,
+  NUM_METHODS
+};
+
+#define GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD (gst_audio_amplify_clipping_method_get_type ())
+static GType
+gst_audio_amplify_clipping_method_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {METHOD_CLIP, "Normal clipping (default)", "clip"},
+      {METHOD_WRAP_NEGATIVE,
+            "Push overdriven values back from the opposite side",
+          "wrap-negative"},
+      {METHOD_WRAP_POSITIVE, "Push overdriven values back from the same side",
+          "wrap-positive"},
+      {METHOD_NOCLIP, "No clipping", "none"},
+      {0, NULL, NULL}
+    };
+
+    /* FIXME 0.11: rename to GstAudioAmplifyClippingMethod */
+    gtype = g_enum_register_static ("GstAudioPanoramaClippingMethod", values);
+  }
+  return gtype;
+}
+
+#define ALLOWED_CAPS                                                  \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)8,"                                                  \
+    " width=(int)8,"                                                  \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)16,"                                                 \
+    " width=(int)16,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)32,"                                                 \
+    " width=(int)32,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-float,"                                              \
+    " width=(int){32,64},"                                            \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_amplify_debug, "audioamplify", 0, "audioamplify element");
+
+GST_BOILERPLATE_FULL (GstAudioAmplify, gst_audio_amplify, GstAudioFilter,
+    GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+
+static gboolean gst_audio_amplify_set_process_function (GstAudioAmplify *
+    filter, gint clipping, gint format, gint width);
+static void gst_audio_amplify_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_amplify_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_audio_amplify_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+static GstFlowReturn gst_audio_amplify_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf);
+
+#define MIN_gint8 G_MININT8
+#define MAX_gint8 G_MAXINT8
+#define MIN_gint16 G_MININT16
+#define MAX_gint16 G_MAXINT16
+#define MIN_gint32 G_MININT32
+#define MAX_gint32 G_MAXINT32
+
+#define MAKE_INT_FUNCS(type,largetype)                                        \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter,          \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    largetype val = *d * filter->amplification;                               \
+    *d++ =  CLAMP (val, MIN_##type, MAX_##type);                              \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify * filter, \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    largetype val = *d * filter->amplification;                               \
+    if (val > MAX_##type)                                                     \
+      val = MIN_##type + (val - MIN_##type) % ((largetype) MAX_##type + 1 -   \
+          MIN_##type);                                                        \
+    else if (val < MIN_##type)                                                \
+      val = MAX_##type - (MAX_##type - val) % ((largetype) MAX_##type + 1 -   \
+          MIN_##type);                                                        \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    largetype val = *d * filter->amplification;                               \
+    do {                                                                      \
+      if (val > MAX_##type)                                                   \
+        val = MAX_##type - (val - MAX_##type);                                \
+      else if (val < MIN_##type)                                              \
+        val = MIN_##type + (MIN_##type - val);                                \
+      else                                                                    \
+        break;                                                                \
+    } while (1);                                                              \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter,        \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--)                                                       \
+    *d++ *= filter->amplification;                                            \
+}
+
+#define MAKE_FLOAT_FUNCS(type)                                                \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter,          \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    type val = *d* filter->amplification;                                     \
+    *d++ = CLAMP (val, -1.0, +1.0);                                           \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify *         \
+    filter, void * data, guint num_samples)                                   \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    type val = *d * filter->amplification;                                    \
+    do {                                                                      \
+      if (val > 1.0)                                                          \
+        val = -1.0 + (val - 1.0);                                             \
+      else if (val < -1.0)                                                    \
+        val = 1.0 - (1.0 - val);                                              \
+      else                                                                    \
+        break;                                                                \
+    } while (1);                                                              \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    type val = *d* filter->amplification;                                     \
+    do {                                                                      \
+      if (val > 1.0)                                                          \
+        val = 1.0 - (val - 1.0);                                              \
+      else if (val < -1.0)                                                    \
+        val = -1.0 + (-1.0 - val);                                            \
+      else                                                                    \
+        break;                                                                \
+    } while (1);                                                              \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter,        \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--)                                                       \
+    *d++ *= filter->amplification;                                            \
+}
+
+/* *INDENT-OFF* */
+MAKE_INT_FUNCS (gint8,gint)
+MAKE_INT_FUNCS (gint16,gint)
+MAKE_INT_FUNCS (gint32,gint64)
+MAKE_FLOAT_FUNCS (gfloat)
+MAKE_FLOAT_FUNCS (gdouble)
+/* *INDENT-ON* */
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_amplify_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *caps;
+
+  gst_element_class_set_details (element_class, &element_details);
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_amplify_class_init (GstAudioAmplifyClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_audio_amplify_set_property;
+  gobject_class->get_property = gst_audio_amplify_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_AMPLIFICATION,
+      g_param_spec_float ("amplification", "Amplification",
+          "Factor of amplification", 0.0, G_MAXFLOAT,
+          1.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  /**
+   * GstAudioAmplify:clipping-method
+   *
+   * Clipping method: clip mode set values higher than the maximum to the
+   * maximum. The wrap-negative mode pushes those values back from the
+   * opposite side, wrap-positive pushes them back from the same side.
+   *
+   **/
+  g_object_class_install_property (gobject_class, PROP_CLIPPING_METHOD,
+      g_param_spec_enum ("clipping-method", "Clipping method",
+          "Selects how to handle values higher than the maximum",
+          GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD, METHOD_CLIP,
+          G_PARAM_READWRITE));
+
+  GST_AUDIO_FILTER_CLASS (klass)->setup =
+      GST_DEBUG_FUNCPTR (gst_audio_amplify_setup);
+  GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_audio_amplify_transform_ip);
+}
+
+static void
+gst_audio_amplify_init (GstAudioAmplify * filter, GstAudioAmplifyClass * klass)
+{
+  filter->amplification = 1.0;
+  gst_audio_amplify_set_process_function (filter, METHOD_CLIP,
+      GST_BUFTYPE_LINEAR, 16);
+  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
+  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
+}
+
+static GstAudioAmplifyProcessFunc
+gst_audio_amplify_process_function (gint clipping, gint format, gint width)
+{
+  static const struct process
+  {
+    gint format;
+    gint width;
+    gint clipping;
+    GstAudioAmplifyProcessFunc func;
+  } process[] = {
+    {
+    GST_BUFTYPE_FLOAT, 32, METHOD_CLIP,
+          gst_audio_amplify_transform_gfloat_clip}, {
+    GST_BUFTYPE_FLOAT, 32, METHOD_WRAP_NEGATIVE,
+          gst_audio_amplify_transform_gfloat_wrap_negative}, {
+    GST_BUFTYPE_FLOAT, 32, METHOD_WRAP_POSITIVE,
+          gst_audio_amplify_transform_gfloat_wrap_positive}, {
+    GST_BUFTYPE_FLOAT, 32, METHOD_NOCLIP,
+          gst_audio_amplify_transform_gfloat_noclip}, {
+    GST_BUFTYPE_FLOAT, 64, METHOD_CLIP,
+          gst_audio_amplify_transform_gdouble_clip}, {
+    GST_BUFTYPE_FLOAT, 64, METHOD_WRAP_NEGATIVE,
+          gst_audio_amplify_transform_gdouble_wrap_negative}, {
+    GST_BUFTYPE_FLOAT, 64, METHOD_WRAP_POSITIVE,
+          gst_audio_amplify_transform_gdouble_wrap_positive}, {
+    GST_BUFTYPE_FLOAT, 64, METHOD_NOCLIP,
+          gst_audio_amplify_transform_gdouble_noclip}, {
+    GST_BUFTYPE_LINEAR, 8, METHOD_CLIP, gst_audio_amplify_transform_gint8_clip}, {
+    GST_BUFTYPE_LINEAR, 8, METHOD_WRAP_NEGATIVE,
+          gst_audio_amplify_transform_gint8_wrap_negative}, {
+    GST_BUFTYPE_LINEAR, 8, METHOD_WRAP_POSITIVE,
+          gst_audio_amplify_transform_gint8_wrap_positive}, {
+    GST_BUFTYPE_LINEAR, 8, METHOD_NOCLIP,
+          gst_audio_amplify_transform_gint8_noclip}, {
+    GST_BUFTYPE_LINEAR, 16, METHOD_CLIP,
+          gst_audio_amplify_transform_gint16_clip}, {
+    GST_BUFTYPE_LINEAR, 16, METHOD_WRAP_NEGATIVE,
+          gst_audio_amplify_transform_gint16_wrap_negative}, {
+    GST_BUFTYPE_LINEAR, 16, METHOD_WRAP_POSITIVE,
+          gst_audio_amplify_transform_gint16_wrap_positive}, {
+    GST_BUFTYPE_LINEAR, 16, METHOD_NOCLIP,
+          gst_audio_amplify_transform_gint16_noclip}, {
+    GST_BUFTYPE_LINEAR, 32, METHOD_CLIP,
+          gst_audio_amplify_transform_gint32_clip}, {
+    GST_BUFTYPE_LINEAR, 32, METHOD_WRAP_NEGATIVE,
+          gst_audio_amplify_transform_gint32_wrap_negative}, {
+    GST_BUFTYPE_LINEAR, 32, METHOD_WRAP_POSITIVE,
+          gst_audio_amplify_transform_gint32_wrap_positive}, {
+    GST_BUFTYPE_LINEAR, 32, METHOD_NOCLIP,
+          gst_audio_amplify_transform_gint32_noclip}, {
+    0, 0, 0, NULL}
+  };
+  const struct process *p;
+
+  for (p = process; p->func; p++)
+    if (p->format == format && p->width == width && p->clipping == clipping)
+      return p->func;
+  return NULL;
+}
+
+static gboolean
+gst_audio_amplify_set_process_function (GstAudioAmplify * filter, gint
+    clipping_method, gint format, gint width)
+{
+  GstAudioAmplifyProcessFunc process;
+
+  /* set processing function */
+
+  process = gst_audio_amplify_process_function (clipping_method, format, width);
+  if (!process) {
+    GST_DEBUG ("wrong format");
+    return FALSE;
+  }
+
+  filter->process = process;
+  filter->clipping_method = clipping_method;
+  filter->format = format;
+  filter->width = width;
+
+  return TRUE;
+}
+
+static void
+gst_audio_amplify_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (object);
+
+  switch (prop_id) {
+    case PROP_AMPLIFICATION:
+      filter->amplification = g_value_get_float (value);
+      gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
+          filter->amplification == 1.0);
+      break;
+    case PROP_CLIPPING_METHOD:
+      gst_audio_amplify_set_process_function (filter, g_value_get_enum (value),
+          filter->format, filter->width);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_amplify_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (object);
+
+  switch (prop_id) {
+    case PROP_AMPLIFICATION:
+      g_value_set_float (value, filter->amplification);
+      break;
+    case PROP_CLIPPING_METHOD:
+      g_value_set_enum (value, filter->clipping_method);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+static gboolean
+gst_audio_amplify_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
+
+  return gst_audio_amplify_set_process_function (filter,
+      filter->clipping_method, format->type, format->width);
+}
+
+/* GstBaseTransform vmethod implementations */
+static GstFlowReturn
+gst_audio_amplify_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+  GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
+  guint num_samples =
+      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
+    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
+
+  if (gst_base_transform_is_passthrough (base) ||
+      G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
+    return GST_FLOW_OK;
+
+  filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
+
+  return GST_FLOW_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioamplify.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,63 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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_AUDIO_AMPLIFY_H__
+#define __GST_AUDIO_AMPLIFY_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+#define GST_TYPE_AUDIO_AMPLIFY            (gst_audio_amplify_get_type())
+#define GST_AUDIO_AMPLIFY(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_AMPLIFY,GstAudioAmplify))
+#define GST_IS_AUDIO_AMPLIFY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_AMPLIFY))
+#define GST_AUDIO_AMPLIFY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_AMPLIFY,GstAudioAmplifyClass))
+#define GST_IS_AUDIO_AMPLIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_AMPLIFY))
+#define GST_AUDIO_AMPLIFY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_AMPLIFY,GstAudioAmplifyClass))
+typedef struct _GstAudioAmplify GstAudioAmplify;
+typedef struct _GstAudioAmplifyClass GstAudioAmplifyClass;
+
+typedef void (*GstAudioAmplifyProcessFunc) (GstAudioAmplify *, void *, guint);
+
+struct _GstAudioAmplify
+{
+  GstAudioFilter audiofilter;
+
+  gfloat amplification;
+
+  /* < private > */
+  GstAudioAmplifyProcessFunc process;
+  gint clipping_method;
+  gint format;
+  gint width;
+};
+
+struct _GstAudioAmplifyClass
+{
+  GstAudioFilterClass parent;
+};
+
+GType gst_audio_amplify_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_AUDIO_AMPLIFY_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiochebband.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,666 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+/* 
+ * Chebyshev type 1 filter design based on
+ * "The Scientist and Engineer's Guide to DSP", Chapter 20.
+ * http://www.dspguide.com/
+ *
+ * For type 2 and Chebyshev filters in general read
+ * http://en.wikipedia.org/wiki/Chebyshev_filter
+ *
+ * Transformation from lowpass to bandpass/bandreject:
+ * http://docs.dewresearch.com/DspHelp/html/IDH_LinearSystems_LowpassToBandPassZ.htm
+ * http://docs.dewresearch.com/DspHelp/html/IDH_LinearSystems_LowpassToBandStopZ.htm
+ * 
+ */
+
+/**
+ * SECTION:element-audiochebband
+ *
+ * Attenuates all frequencies outside (bandpass) or inside (bandreject) of a frequency
+ * band. The number of poles and the ripple parameter control the rolloff.
+ *
+ * This element has the advantage over the windowed sinc bandpass and bandreject filter that it is
+ * much faster and produces almost as good results. It's only disadvantages are the highly
+ * non-linear phase and the slower rolloff compared to a windowed sinc filter with a large kernel.
+ *
+ * For type 1 the ripple parameter specifies how much ripple in dB is allowed in the passband, i.e.
+ * some frequencies in the passband will be amplified by that value. A higher ripple value will allow
+ * a faster rolloff.
+ *
+ * For type 2 the ripple parameter specifies the stopband attenuation. In the stopband the gain will
+ * be at most this value. A lower ripple value will allow a faster rolloff.
+ *
+ * As a special case, a Chebyshev type 1 filter with no ripple is a Butterworth filter.
+ *
+ * <note>
+ * Be warned that a too large number of poles can produce noise. The most poles are possible with
+ * a cutoff frequency at a quarter of the sampling rate.
+ * </note>
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc freq=1500 ! audioconvert ! audiochebband mode=band-pass lower-frequency=1000 upper-frequenc=6000 poles=4 ! audioconvert ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiochebband mode=band-reject lower-frequency=1000 upper-frequency=4000 ripple=0.2 ! audioconvert ! alsasink
+ * gst-launch audiotestsrc wave=white-noise ! audioconvert ! audiochebband mode=band-pass lower-frequency=1000 upper-frequency=4000 type=2 ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include <math.h>
+
+#include "math_compat.h"
+
+#include "audiochebband.h"
+
+#define GST_CAT_DEFAULT gst_audio_cheb_band_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  PROP_0,
+  PROP_MODE,
+  PROP_TYPE,
+  PROP_LOWER_FREQUENCY,
+  PROP_UPPER_FREQUENCY,
+  PROP_RIPPLE,
+  PROP_POLES
+};
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_cheb_band_debug, "audiochebband", 0, "audiochebband element");
+
+GST_BOILERPLATE_FULL (GstAudioChebBand, gst_audio_cheb_band,
+    GstAudioFXBaseIIRFilter, GST_TYPE_AUDIO_FX_BASE_IIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_cheb_band_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_audio_cheb_band_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_audio_cheb_band_finalize (GObject * object);
+
+static gboolean gst_audio_cheb_band_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+
+enum
+{
+  MODE_BAND_PASS = 0,
+  MODE_BAND_REJECT
+};
+
+#define GST_TYPE_AUDIO_CHEBYSHEV_FREQ_BAND_MODE (gst_audio_cheb_band_mode_get_type ())
+static GType
+gst_audio_cheb_band_mode_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {MODE_BAND_PASS, "Band pass (default)",
+          "band-pass"},
+      {MODE_BAND_REJECT, "Band reject",
+          "band-reject"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioChebBandMode", values);
+  }
+  return gtype;
+}
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_cheb_band_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details_simple (element_class,
+      "Band pass & band reject filter", "Filter/Effect/Audio",
+      "Chebyshev band pass and band reject filter",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_cheb_band_class_init (GstAudioChebBandClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_cheb_band_set_property;
+  gobject_class->get_property = gst_audio_cheb_band_get_property;
+  gobject_class->finalize = gst_audio_cheb_band_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode", "Mode",
+          "Low pass or high pass mode", GST_TYPE_AUDIO_CHEBYSHEV_FREQ_BAND_MODE,
+          MODE_BAND_PASS,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_TYPE,
+      g_param_spec_int ("type", "Type", "Type of the chebychev filter", 1, 2, 1,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  /* FIXME: Don't use the complete possible range but restrict the upper boundary
+   * so automatically generated UIs can use a slider without */
+  g_object_class_install_property (gobject_class, PROP_LOWER_FREQUENCY,
+      g_param_spec_float ("lower-frequency", "Lower frequency",
+          "Start frequency of the band (Hz)", 0.0, 100000.0,
+          0.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_UPPER_FREQUENCY,
+      g_param_spec_float ("upper-frequency", "Upper frequency",
+          "Stop frequency of the band (Hz)", 0.0, 100000.0, 0.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_RIPPLE,
+      g_param_spec_float ("ripple", "Ripple", "Amount of ripple (dB)", 0.0,
+          200.0, 0.25,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  /* FIXME: What to do about this upper boundary? With a frequencies near
+   * rate/4 32 poles are completely possible, with frequencies very low
+   * or very high 16 poles already produces only noise */
+  g_object_class_install_property (gobject_class, PROP_POLES,
+      g_param_spec_int ("poles", "Poles",
+          "Number of poles to use, will be rounded up to the next multiply of four",
+          4, 32, 4,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_cheb_band_setup);
+}
+
+static void
+gst_audio_cheb_band_init (GstAudioChebBand * filter,
+    GstAudioChebBandClass * klass)
+{
+  filter->lower_frequency = filter->upper_frequency = 0.0;
+  filter->mode = MODE_BAND_PASS;
+  filter->type = 1;
+  filter->poles = 4;
+  filter->ripple = 0.25;
+
+  filter->lock = g_mutex_new ();
+}
+
+static void
+generate_biquad_coefficients (GstAudioChebBand * filter,
+    gint p, gdouble * a0, gdouble * a1, gdouble * a2, gdouble * a3,
+    gdouble * a4, gdouble * b1, gdouble * b2, gdouble * b3, gdouble * b4)
+{
+  gint np = filter->poles / 2;
+  gdouble ripple = filter->ripple;
+
+  /* pole location in s-plane */
+  gdouble rp, ip;
+
+  /* zero location in s-plane */
+  gdouble iz = 0.0;
+
+  /* transfer function coefficients for the z-plane */
+  gdouble x0, x1, x2, y1, y2;
+  gint type = filter->type;
+
+  /* Calculate pole location for lowpass at frequency 1 */
+  {
+    gdouble angle = (M_PI / 2.0) * (2.0 * p - 1) / np;
+
+    rp = -sin (angle);
+    ip = cos (angle);
+  }
+
+  /* If we allow ripple, move the pole from the unit
+   * circle to an ellipse and keep cutoff at frequency 1 */
+  if (ripple > 0 && type == 1) {
+    gdouble es, vx;
+
+    es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
+
+    vx = (1.0 / np) * asinh (1.0 / es);
+    rp = rp * sinh (vx);
+    ip = ip * cosh (vx);
+  } else if (type == 2) {
+    gdouble es, vx;
+
+    es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
+    vx = (1.0 / np) * asinh (es);
+    rp = rp * sinh (vx);
+    ip = ip * cosh (vx);
+  }
+
+  /* Calculate inverse of the pole location to move from
+   * type I to type II */
+  if (type == 2) {
+    gdouble mag2 = rp * rp + ip * ip;
+
+    rp /= mag2;
+    ip /= mag2;
+  }
+
+  /* Calculate zero location for frequency 1 on the
+   * unit circle for type 2 */
+  if (type == 2) {
+    gdouble angle = M_PI / (np * 2.0) + ((p - 1) * M_PI) / (np);
+    gdouble mag2;
+
+    iz = cos (angle);
+    mag2 = iz * iz;
+    iz /= mag2;
+  }
+
+  /* Convert from s-domain to z-domain by
+   * using the bilinear Z-transform, i.e.
+   * substitute s by (2/t)*((z-1)/(z+1))
+   * with t = 2 * tan(0.5).
+   */
+  if (type == 1) {
+    gdouble t, m, d;
+
+    t = 2.0 * tan (0.5);
+    m = rp * rp + ip * ip;
+    d = 4.0 - 4.0 * rp * t + m * t * t;
+
+    x0 = (t * t) / d;
+    x1 = 2.0 * x0;
+    x2 = x0;
+    y1 = (8.0 - 2.0 * m * t * t) / d;
+    y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
+  } else {
+    gdouble t, m, d;
+
+    t = 2.0 * tan (0.5);
+    m = rp * rp + ip * ip;
+    d = 4.0 - 4.0 * rp * t + m * t * t;
+
+    x0 = (t * t * iz * iz + 4.0) / d;
+    x1 = (-8.0 + 2.0 * iz * iz * t * t) / d;
+    x2 = x0;
+    y1 = (8.0 - 2.0 * m * t * t) / d;
+    y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
+  }
+
+  /* Convert from lowpass at frequency 1 to either bandpass
+   * or band reject.
+   *
+   * For bandpass substitute z^(-1) with:
+   *
+   *   -2            -1
+   * -z   + alpha * z   - beta
+   * ----------------------------
+   *         -2            -1
+   * beta * z   - alpha * z   + 1
+   *
+   * alpha = (2*a*b)/(1+b)
+   * beta = (b-1)/(b+1)
+   * a = cos((w1 + w0)/2) / cos((w1 - w0)/2)
+   * b = tan(1/2) * cot((w1 - w0)/2)
+   *
+   * For bandreject substitute z^(-1) with:
+   * 
+   *  -2            -1
+   * z   - alpha * z   + beta
+   * ----------------------------
+   *         -2            -1
+   * beta * z   - alpha * z   + 1
+   *
+   * alpha = (2*a)/(1+b)
+   * beta = (1-b)/(1+b)
+   * a = cos((w1 + w0)/2) / cos((w1 - w0)/2)
+   * b = tan(1/2) * tan((w1 - w0)/2)
+   *
+   */
+  {
+    gdouble a, b, d;
+    gdouble alpha, beta;
+    gdouble w0 =
+        2.0 * M_PI * (filter->lower_frequency /
+        GST_AUDIO_FILTER (filter)->format.rate);
+    gdouble w1 =
+        2.0 * M_PI * (filter->upper_frequency /
+        GST_AUDIO_FILTER (filter)->format.rate);
+
+    if (filter->mode == MODE_BAND_PASS) {
+      a = cos ((w1 + w0) / 2.0) / cos ((w1 - w0) / 2.0);
+      b = tan (1.0 / 2.0) / tan ((w1 - w0) / 2.0);
+
+      alpha = (2.0 * a * b) / (1.0 + b);
+      beta = (b - 1.0) / (b + 1.0);
+
+      d = 1.0 + beta * (y1 - beta * y2);
+
+      *a0 = (x0 + beta * (-x1 + beta * x2)) / d;
+      *a1 = (alpha * (-2.0 * x0 + x1 + beta * x1 - 2.0 * beta * x2)) / d;
+      *a2 =
+          (-x1 - beta * beta * x1 + 2.0 * beta * (x0 + x2) +
+          alpha * alpha * (x0 - x1 + x2)) / d;
+      *a3 = (alpha * (x1 + beta * (-2.0 * x0 + x1) - 2.0 * x2)) / d;
+      *a4 = (beta * (beta * x0 - x1) + x2) / d;
+      *b1 = (alpha * (2.0 + y1 + beta * y1 - 2.0 * beta * y2)) / d;
+      *b2 =
+          (-y1 - beta * beta * y1 - alpha * alpha * (1.0 + y1 - y2) +
+          2.0 * beta * (-1.0 + y2)) / d;
+      *b3 = (alpha * (y1 + beta * (2.0 + y1) - 2.0 * y2)) / d;
+      *b4 = (-beta * beta - beta * y1 + y2) / d;
+    } else {
+      a = cos ((w1 + w0) / 2.0) / cos ((w1 - w0) / 2.0);
+      b = tan (1.0 / 2.0) * tan ((w1 - w0) / 2.0);
+
+      alpha = (2.0 * a) / (1.0 + b);
+      beta = (1.0 - b) / (1.0 + b);
+
+      d = -1.0 + beta * (beta * y2 + y1);
+
+      *a0 = (-x0 - beta * x1 - beta * beta * x2) / d;
+      *a1 = (alpha * (2.0 * x0 + x1 + beta * x1 + 2.0 * beta * x2)) / d;
+      *a2 =
+          (-x1 - beta * beta * x1 - 2.0 * beta * (x0 + x2) -
+          alpha * alpha * (x0 + x1 + x2)) / d;
+      *a3 = (alpha * (x1 + beta * (2.0 * x0 + x1) + 2.0 * x2)) / d;
+      *a4 = (-beta * beta * x0 - beta * x1 - x2) / d;
+      *b1 = (alpha * (-2.0 + y1 + beta * y1 + 2.0 * beta * y2)) / d;
+      *b2 =
+          -(y1 + beta * beta * y1 + 2.0 * beta * (-1.0 + y2) +
+          alpha * alpha * (-1.0 + y1 + y2)) / d;
+      *b3 = (alpha * (beta * (-2.0 + y1) + y1 + 2.0 * y2)) / d;
+      *b4 = -(-beta * beta + beta * y1 + y2) / d;
+    }
+  }
+}
+
+static void
+generate_coefficients (GstAudioChebBand * filter)
+{
+  if (GST_AUDIO_FILTER (filter)->format.rate == 0) {
+    gdouble *a = g_new0 (gdouble, 1);
+
+    a[0] = 1.0;
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, 1, NULL, 0);
+    GST_LOG_OBJECT (filter, "rate was not set yet");
+    return;
+  }
+
+  if (filter->upper_frequency <= filter->lower_frequency) {
+    gdouble *a = g_new0 (gdouble, 1);
+
+    a[0] = (filter->mode == MODE_BAND_PASS) ? 0.0 : 1.0;
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, 1, NULL, 0);
+
+    GST_LOG_OBJECT (filter, "frequency band had no or negative dimension");
+    return;
+  }
+
+  if (filter->upper_frequency > GST_AUDIO_FILTER (filter)->format.rate / 2) {
+    filter->upper_frequency = GST_AUDIO_FILTER (filter)->format.rate / 2;
+    GST_LOG_OBJECT (filter, "clipped upper frequency to nyquist frequency");
+  }
+
+  if (filter->lower_frequency < 0.0) {
+    filter->lower_frequency = 0.0;
+    GST_LOG_OBJECT (filter, "clipped lower frequency to 0.0");
+  }
+
+  /* Calculate coefficients for the chebyshev filter */
+  {
+    gint np = filter->poles;
+    gdouble *a, *b;
+    gint i, p;
+
+    a = g_new0 (gdouble, np + 5);
+    b = g_new0 (gdouble, np + 5);
+
+    /* Calculate transfer function coefficients */
+    a[4] = 1.0;
+    b[4] = 1.0;
+
+    for (p = 1; p <= np / 4; p++) {
+      gdouble a0, a1, a2, a3, a4, b1, b2, b3, b4;
+      gdouble *ta = g_new0 (gdouble, np + 5);
+      gdouble *tb = g_new0 (gdouble, np + 5);
+
+      generate_biquad_coefficients (filter, p, &a0, &a1, &a2, &a3, &a4, &b1,
+          &b2, &b3, &b4);
+
+      memcpy (ta, a, sizeof (gdouble) * (np + 5));
+      memcpy (tb, b, sizeof (gdouble) * (np + 5));
+
+      /* add the new coefficients for the new two poles
+       * to the cascade by multiplication of the transfer
+       * functions */
+      for (i = 4; i < np + 5; i++) {
+        a[i] =
+            a0 * ta[i] + a1 * ta[i - 1] + a2 * ta[i - 2] + a3 * ta[i - 3] +
+            a4 * ta[i - 4];
+        b[i] =
+            tb[i] - b1 * tb[i - 1] - b2 * tb[i - 2] - b3 * tb[i - 3] -
+            b4 * tb[i - 4];
+      }
+      g_free (ta);
+      g_free (tb);
+    }
+
+    /* Move coefficients to the beginning of the array
+     * and multiply the b coefficients with -1 to move from
+     * the transfer function's coefficients to the difference
+     * equation's coefficients */
+    b[4] = 0.0;
+    for (i = 0; i <= np; i++) {
+      a[i] = a[i + 4];
+      b[i] = -b[i + 4];
+    }
+
+    /* Normalize to unity gain at frequency 0 and frequency
+     * 0.5 for bandreject and unity gain at band center frequency
+     * for bandpass */
+    if (filter->mode == MODE_BAND_REJECT) {
+      /* gain is sqrt(H(0)*H(0.5)) */
+
+      gdouble gain1 =
+          gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
+          1.0, 0.0);
+      gdouble gain2 =
+          gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
+          -1.0, 0.0);
+
+      gain1 = sqrt (gain1 * gain2);
+
+      for (i = 0; i <= np; i++) {
+        a[i] /= gain1;
+      }
+    } else {
+      /* gain is H(wc), wc = center frequency */
+
+      gdouble w1 =
+          2.0 * M_PI * (filter->lower_frequency /
+          GST_AUDIO_FILTER (filter)->format.rate);
+      gdouble w2 =
+          2.0 * M_PI * (filter->upper_frequency /
+          GST_AUDIO_FILTER (filter)->format.rate);
+      gdouble w0 = (w2 + w1) / 2.0;
+      gdouble zr = cos (w0), zi = sin (w0);
+      gdouble gain =
+          gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1, zr,
+          zi);
+
+      for (i = 0; i <= np; i++) {
+        a[i] /= gain;
+      }
+    }
+
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, np + 1, b, np + 1);
+
+    GST_LOG_OBJECT (filter,
+        "Generated IIR coefficients for the Chebyshev filter");
+    GST_LOG_OBJECT (filter,
+        "mode: %s, type: %d, poles: %d, lower-frequency: %.2f Hz, upper-frequency: %.2f Hz, ripple: %.2f dB",
+        (filter->mode == MODE_BAND_PASS) ? "band-pass" : "band-reject",
+        filter->type, filter->poles, filter->lower_frequency,
+        filter->upper_frequency, filter->ripple);
+
+    GST_LOG_OBJECT (filter, "%.2f dB gain @ 0Hz",
+        20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
+                np + 1, 1.0, 0.0)));
+    {
+      gdouble w1 =
+          2.0 * M_PI * (filter->lower_frequency /
+          GST_AUDIO_FILTER (filter)->format.rate);
+      gdouble w2 =
+          2.0 * M_PI * (filter->upper_frequency /
+          GST_AUDIO_FILTER (filter)->format.rate);
+      gdouble w0 = (w2 + w1) / 2.0;
+      gdouble zr, zi;
+
+      zr = cos (w1);
+      zi = sin (w1);
+      GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
+          20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
+                  b, np + 1, zr, zi)), (int) filter->lower_frequency);
+      zr = cos (w0);
+      zi = sin (w0);
+      GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
+          20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
+                  b, np + 1, zr, zi)),
+          (int) ((filter->lower_frequency + filter->upper_frequency) / 2.0));
+      zr = cos (w2);
+      zi = sin (w2);
+      GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
+          20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
+                  b, np + 1, zr, zi)), (int) filter->upper_frequency);
+    }
+    GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
+        20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
+                np + 1, -1.0, 0.0)),
+        GST_AUDIO_FILTER (filter)->format.rate / 2);
+  }
+}
+
+static void
+gst_audio_cheb_band_finalize (GObject * object)
+{
+  GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
+
+  g_mutex_free (filter->lock);
+  filter->lock = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_cheb_band_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      g_mutex_lock (filter->lock);
+      filter->mode = g_value_get_enum (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_TYPE:
+      g_mutex_lock (filter->lock);
+      filter->type = g_value_get_int (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_LOWER_FREQUENCY:
+      g_mutex_lock (filter->lock);
+      filter->lower_frequency = g_value_get_float (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_UPPER_FREQUENCY:
+      g_mutex_lock (filter->lock);
+      filter->upper_frequency = g_value_get_float (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_RIPPLE:
+      g_mutex_lock (filter->lock);
+      filter->ripple = g_value_get_float (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_POLES:
+      g_mutex_lock (filter->lock);
+      filter->poles = GST_ROUND_UP_4 (g_value_get_int (value));
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_cheb_band_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      g_value_set_enum (value, filter->mode);
+      break;
+    case PROP_TYPE:
+      g_value_set_int (value, filter->type);
+      break;
+    case PROP_LOWER_FREQUENCY:
+      g_value_set_float (value, filter->lower_frequency);
+      break;
+    case PROP_UPPER_FREQUENCY:
+      g_value_set_float (value, filter->upper_frequency);
+      break;
+    case PROP_RIPPLE:
+      g_value_set_float (value, filter->ripple);
+      break;
+    case PROP_POLES:
+      g_value_set_int (value, filter->poles);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_cheb_band_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (base);
+
+  generate_coefficients (filter);
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiochebband.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,69 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_CHEB_BAND_H__
+#define __GST_AUDIO_CHEB_BAND_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+#include "audiofxbaseiirfilter.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_AUDIO_CHEB_BAND            (gst_audio_cheb_band_get_type())
+#define GST_AUDIO_CHEB_BAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_CHEB_BAND,GstAudioChebBand))
+#define GST_IS_AUDIO_CHEB_BAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_CHEB_BAND))
+#define GST_AUDIO_CHEB_BAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_CHEB_BAND,GstAudioChebBandClass))
+#define GST_IS_AUDIO_CHEB_BAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_CHEB_BAND))
+#define GST_AUDIO_CHEB_BAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_CHEB_BAND,GstAudioChebBandClass))
+typedef struct _GstAudioChebBand GstAudioChebBand;
+typedef struct _GstAudioChebBandClass GstAudioChebBandClass;
+
+struct _GstAudioChebBand
+{
+  GstAudioFXBaseIIRFilter parent;
+
+  gint mode;
+  gint type;
+  gint poles;
+  gfloat lower_frequency;
+  gfloat upper_frequency;
+  gfloat ripple;
+
+  /* < private > */
+  GMutex *lock;
+};
+
+struct _GstAudioChebBandClass
+{
+  GstAudioFXBaseIIRFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_cheb_band_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_AUDIO_CHEB_BAND_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiocheblimit.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,568 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+/* 
+ * Chebyshev type 1 filter design based on
+ * "The Scientist and Engineer's Guide to DSP", Chapter 20.
+ * http://www.dspguide.com/
+ *
+ * For type 2 and Chebyshev filters in general read
+ * http://en.wikipedia.org/wiki/Chebyshev_filter
+ *
+ */
+
+/**
+ * SECTION:element-audiocheblimit
+ *
+ * Attenuates all frequencies above the cutoff frequency (low-pass) or all frequencies below the
+ * cutoff frequency (high-pass). The number of poles and the ripple parameter control the rolloff.
+ *
+ * This element has the advantage over the windowed sinc lowpass and highpass filter that it is
+ * much faster and produces almost as good results. It's only disadvantages are the highly
+ * non-linear phase and the slower rolloff compared to a windowed sinc filter with a large kernel.
+ *
+ * For type 1 the ripple parameter specifies how much ripple in dB is allowed in the passband, i.e.
+ * some frequencies in the passband will be amplified by that value. A higher ripple value will allow
+ * a faster rolloff.
+ *
+ * For type 2 the ripple parameter specifies the stopband attenuation. In the stopband the gain will
+ * be at most this value. A lower ripple value will allow a faster rolloff.
+ *
+ * As a special case, a Chebyshev type 1 filter with no ripple is a Butterworth filter.
+ * </para>
+ * <note><para>
+ * Be warned that a too large number of poles can produce noise. The most poles are possible with
+ * a cutoff frequency at a quarter of the sampling rate.
+ * </para></note>
+ * <para>
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc freq=1500 ! audioconvert ! audiocheblimit mode=low-pass cutoff=1000 poles=4 ! audioconvert ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiocheblimit mode=high-pass cutoff=400 ripple=0.2 ! audioconvert ! alsasink
+ * gst-launch audiotestsrc wave=white-noise ! audioconvert ! audiocheblimit mode=low-pass cutoff=800 type=2 ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include <math.h>
+
+#include "math_compat.h"
+
+#include "audiocheblimit.h"
+
+#define GST_CAT_DEFAULT gst_audio_cheb_limit_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  PROP_0,
+  PROP_MODE,
+  PROP_TYPE,
+  PROP_CUTOFF,
+  PROP_RIPPLE,
+  PROP_POLES
+};
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_cheb_limit_debug, "audiocheblimit", 0, "audiocheblimit element");
+
+GST_BOILERPLATE_FULL (GstAudioChebLimit,
+    gst_audio_cheb_limit, GstAudioFXBaseIIRFilter,
+    GST_TYPE_AUDIO_FX_BASE_IIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_cheb_limit_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_audio_cheb_limit_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_audio_cheb_limit_finalize (GObject * object);
+
+static gboolean gst_audio_cheb_limit_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+
+enum
+{
+  MODE_LOW_PASS = 0,
+  MODE_HIGH_PASS
+};
+
+#define GST_TYPE_AUDIO_CHEBYSHEV_FREQ_LIMIT_MODE (gst_audio_cheb_limit_mode_get_type ())
+static GType
+gst_audio_cheb_limit_mode_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {MODE_LOW_PASS, "Low pass (default)",
+          "low-pass"},
+      {MODE_HIGH_PASS, "High pass",
+          "high-pass"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioChebLimitMode", values);
+  }
+  return gtype;
+}
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_cheb_limit_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details_simple (element_class,
+      "Low pass & high pass filter",
+      "Filter/Effect/Audio",
+      "Chebyshev low pass and high pass filter",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_cheb_limit_class_init (GstAudioChebLimitClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_cheb_limit_set_property;
+  gobject_class->get_property = gst_audio_cheb_limit_get_property;
+  gobject_class->finalize = gst_audio_cheb_limit_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode", "Mode",
+          "Low pass or high pass mode",
+          GST_TYPE_AUDIO_CHEBYSHEV_FREQ_LIMIT_MODE, MODE_LOW_PASS,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_TYPE,
+      g_param_spec_int ("type", "Type", "Type of the chebychev filter", 1, 2, 1,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  /* FIXME: Don't use the complete possible range but restrict the upper boundary
+   * so automatically generated UIs can use a slider without */
+  g_object_class_install_property (gobject_class, PROP_CUTOFF,
+      g_param_spec_float ("cutoff", "Cutoff", "Cut off frequency (Hz)", 0.0,
+          100000.0, 0.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_RIPPLE,
+      g_param_spec_float ("ripple", "Ripple", "Amount of ripple (dB)", 0.0,
+          200.0, 0.25,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  /* FIXME: What to do about this upper boundary? With a cutoff frequency of
+   * rate/4 32 poles are completely possible, with a cutoff frequency very low
+   * or very high 16 poles already produces only noise */
+  g_object_class_install_property (gobject_class, PROP_POLES,
+      g_param_spec_int ("poles", "Poles",
+          "Number of poles to use, will be rounded up to the next even number",
+          2, 32, 4,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_cheb_limit_setup);
+}
+
+static void
+gst_audio_cheb_limit_init (GstAudioChebLimit * filter,
+    GstAudioChebLimitClass * klass)
+{
+  filter->cutoff = 0.0;
+  filter->mode = MODE_LOW_PASS;
+  filter->type = 1;
+  filter->poles = 4;
+  filter->ripple = 0.25;
+
+  filter->lock = g_mutex_new ();
+}
+
+static void
+generate_biquad_coefficients (GstAudioChebLimit * filter,
+    gint p, gdouble * a0, gdouble * a1, gdouble * a2,
+    gdouble * b1, gdouble * b2)
+{
+  gint np = filter->poles;
+  gdouble ripple = filter->ripple;
+
+  /* pole location in s-plane */
+  gdouble rp, ip;
+
+  /* zero location in s-plane */
+  gdouble iz = 0.0;
+
+  /* transfer function coefficients for the z-plane */
+  gdouble x0, x1, x2, y1, y2;
+  gint type = filter->type;
+
+  /* Calculate pole location for lowpass at frequency 1 */
+  {
+    gdouble angle = (M_PI / 2.0) * (2.0 * p - 1) / np;
+
+    rp = -sin (angle);
+    ip = cos (angle);
+  }
+
+  /* If we allow ripple, move the pole from the unit
+   * circle to an ellipse and keep cutoff at frequency 1 */
+  if (ripple > 0 && type == 1) {
+    gdouble es, vx;
+
+    es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
+
+    vx = (1.0 / np) * asinh (1.0 / es);
+    rp = rp * sinh (vx);
+    ip = ip * cosh (vx);
+  } else if (type == 2) {
+    gdouble es, vx;
+
+    es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
+    vx = (1.0 / np) * asinh (es);
+    rp = rp * sinh (vx);
+    ip = ip * cosh (vx);
+  }
+
+  /* Calculate inverse of the pole location to convert from
+   * type I to type II */
+  if (type == 2) {
+    gdouble mag2 = rp * rp + ip * ip;
+
+    rp /= mag2;
+    ip /= mag2;
+  }
+
+  /* Calculate zero location for frequency 1 on the
+   * unit circle for type 2 */
+  if (type == 2) {
+    gdouble angle = M_PI / (np * 2.0) + ((p - 1) * M_PI) / (np);
+    gdouble mag2;
+
+    iz = cos (angle);
+    mag2 = iz * iz;
+    iz /= mag2;
+  }
+
+  /* Convert from s-domain to z-domain by
+   * using the bilinear Z-transform, i.e.
+   * substitute s by (2/t)*((z-1)/(z+1))
+   * with t = 2 * tan(0.5).
+   */
+  if (type == 1) {
+    gdouble t, m, d;
+
+    t = 2.0 * tan (0.5);
+    m = rp * rp + ip * ip;
+    d = 4.0 - 4.0 * rp * t + m * t * t;
+
+    x0 = (t * t) / d;
+    x1 = 2.0 * x0;
+    x2 = x0;
+    y1 = (8.0 - 2.0 * m * t * t) / d;
+    y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
+  } else {
+    gdouble t, m, d;
+
+    t = 2.0 * tan (0.5);
+    m = rp * rp + ip * ip;
+    d = 4.0 - 4.0 * rp * t + m * t * t;
+
+    x0 = (t * t * iz * iz + 4.0) / d;
+    x1 = (-8.0 + 2.0 * iz * iz * t * t) / d;
+    x2 = x0;
+    y1 = (8.0 - 2.0 * m * t * t) / d;
+    y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
+  }
+
+  /* Convert from lowpass at frequency 1 to either lowpass
+   * or highpass.
+   *
+   * For lowpass substitute z^(-1) with:
+   *  -1
+   * z   - k
+   * ------------
+   *          -1
+   * 1 - k * z
+   *
+   * k = sin((1-w)/2) / sin((1+w)/2)
+   *
+   * For highpass substitute z^(-1) with:
+   *
+   *   -1
+   * -z   - k
+   * ------------
+   *          -1
+   * 1 + k * z
+   *
+   * k = -cos((1+w)/2) / cos((1-w)/2)
+   *
+   */
+  {
+    gdouble k, d;
+    gdouble omega =
+        2.0 * M_PI * (filter->cutoff / GST_AUDIO_FILTER (filter)->format.rate);
+
+    if (filter->mode == MODE_LOW_PASS)
+      k = sin ((1.0 - omega) / 2.0) / sin ((1.0 + omega) / 2.0);
+    else
+      k = -cos ((omega + 1.0) / 2.0) / cos ((omega - 1.0) / 2.0);
+
+    d = 1.0 + y1 * k - y2 * k * k;
+    *a0 = (x0 + k * (-x1 + k * x2)) / d;
+    *a1 = (x1 + k * k * x1 - 2.0 * k * (x0 + x2)) / d;
+    *a2 = (x0 * k * k - x1 * k + x2) / d;
+    *b1 = (2.0 * k + y1 + y1 * k * k - 2.0 * y2 * k) / d;
+    *b2 = (-k * k - y1 * k + y2) / d;
+
+    if (filter->mode == MODE_HIGH_PASS) {
+      *a1 = -*a1;
+      *b1 = -*b1;
+    }
+  }
+}
+
+static void
+generate_coefficients (GstAudioChebLimit * filter)
+{
+  if (GST_AUDIO_FILTER (filter)->format.rate == 0) {
+    gdouble *a = g_new0 (gdouble, 1);
+
+    a[0] = 1.0;
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, 1, NULL, 0);
+
+    GST_LOG_OBJECT (filter, "rate was not set yet");
+    return;
+  }
+
+  if (filter->cutoff >= GST_AUDIO_FILTER (filter)->format.rate / 2.0) {
+    gdouble *a = g_new0 (gdouble, 1);
+
+    a[0] = (filter->mode == MODE_LOW_PASS) ? 1.0 : 0.0;
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, 1, NULL, 0);
+    GST_LOG_OBJECT (filter, "cutoff was higher than nyquist frequency");
+    return;
+  } else if (filter->cutoff <= 0.0) {
+    gdouble *a = g_new0 (gdouble, 1);
+
+    a[0] = (filter->mode == MODE_LOW_PASS) ? 0.0 : 1.0;
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, 1, NULL, 0);
+    GST_LOG_OBJECT (filter, "cutoff is lower than zero");
+    return;
+  }
+
+  /* Calculate coefficients for the chebyshev filter */
+  {
+    gint np = filter->poles;
+    gdouble *a, *b;
+    gint i, p;
+
+    a = g_new0 (gdouble, np + 3);
+    b = g_new0 (gdouble, np + 3);
+
+    /* Calculate transfer function coefficients */
+    a[2] = 1.0;
+    b[2] = 1.0;
+
+    for (p = 1; p <= np / 2; p++) {
+      gdouble a0, a1, a2, b1, b2;
+      gdouble *ta = g_new0 (gdouble, np + 3);
+      gdouble *tb = g_new0 (gdouble, np + 3);
+
+      generate_biquad_coefficients (filter, p, &a0, &a1, &a2, &b1, &b2);
+
+      memcpy (ta, a, sizeof (gdouble) * (np + 3));
+      memcpy (tb, b, sizeof (gdouble) * (np + 3));
+
+      /* add the new coefficients for the new two poles
+       * to the cascade by multiplication of the transfer
+       * functions */
+      for (i = 2; i < np + 3; i++) {
+        a[i] = a0 * ta[i] + a1 * ta[i - 1] + a2 * ta[i - 2];
+        b[i] = tb[i] - b1 * tb[i - 1] - b2 * tb[i - 2];
+      }
+      g_free (ta);
+      g_free (tb);
+    }
+
+    /* Move coefficients to the beginning of the array
+     * and multiply the b coefficients with -1 to move from
+     * the transfer function's coefficients to the difference
+     * equation's coefficients */
+    b[2] = 0.0;
+    for (i = 0; i <= np; i++) {
+      a[i] = a[i + 2];
+      b[i] = -b[i + 2];
+    }
+
+    /* Normalize to unity gain at frequency 0 for lowpass
+     * and frequency 0.5 for highpass */
+    {
+      gdouble gain;
+
+      if (filter->mode == MODE_LOW_PASS)
+        gain =
+            gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
+            1.0, 0.0);
+      else
+        gain =
+            gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
+            -1.0, 0.0);
+
+      for (i = 0; i <= np; i++) {
+        a[i] /= gain;
+      }
+    }
+
+    gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+        (filter), a, np + 1, b, np + 1);
+
+    GST_LOG_OBJECT (filter,
+        "Generated IIR coefficients for the Chebyshev filter");
+    GST_LOG_OBJECT (filter,
+        "mode: %s, type: %d, poles: %d, cutoff: %.2f Hz, ripple: %.2f dB",
+        (filter->mode == MODE_LOW_PASS) ? "low-pass" : "high-pass",
+        filter->type, filter->poles, filter->cutoff, filter->ripple);
+    GST_LOG_OBJECT (filter, "%.2f dB gain @ 0 Hz",
+        20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
+                np + 1, 1.0, 0.0)));
+
+#ifndef GST_DISABLE_GST_DEBUG
+    {
+      gdouble wc =
+          2.0 * M_PI * (filter->cutoff /
+          GST_AUDIO_FILTER (filter)->format.rate);
+      gdouble zr = cos (wc), zi = sin (wc);
+
+      GST_LOG_OBJECT (filter, "%.2f dB gain @ %d Hz",
+          20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
+                  b, np + 1, zr, zi)), (int) filter->cutoff);
+    }
+#endif
+
+    GST_LOG_OBJECT (filter, "%.2f dB gain @ %d Hz",
+        20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
+                np + 1, -1.0, 0.0)),
+        GST_AUDIO_FILTER (filter)->format.rate / 2);
+  }
+}
+
+static void
+gst_audio_cheb_limit_finalize (GObject * object)
+{
+  GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
+
+  g_mutex_free (filter->lock);
+  filter->lock = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_cheb_limit_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      g_mutex_lock (filter->lock);
+      filter->mode = g_value_get_enum (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_TYPE:
+      g_mutex_lock (filter->lock);
+      filter->type = g_value_get_int (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_CUTOFF:
+      g_mutex_lock (filter->lock);
+      filter->cutoff = g_value_get_float (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_RIPPLE:
+      g_mutex_lock (filter->lock);
+      filter->ripple = g_value_get_float (value);
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    case PROP_POLES:
+      g_mutex_lock (filter->lock);
+      filter->poles = GST_ROUND_UP_2 (g_value_get_int (value));
+      generate_coefficients (filter);
+      g_mutex_unlock (filter->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_cheb_limit_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      g_value_set_enum (value, filter->mode);
+      break;
+    case PROP_TYPE:
+      g_value_set_int (value, filter->type);
+      break;
+    case PROP_CUTOFF:
+      g_value_set_float (value, filter->cutoff);
+      break;
+    case PROP_RIPPLE:
+      g_value_set_float (value, filter->ripple);
+      break;
+    case PROP_POLES:
+      g_value_set_int (value, filter->poles);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_cheb_limit_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (base);
+
+  generate_coefficients (filter);
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiocheblimit.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,71 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_CHEB_LIMIT_H__
+#define __GST_AUDIO_CHEB_LIMIT_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+#include "audiofxbaseiirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_CHEB_LIMIT            (gst_audio_cheb_limit_get_type())
+#define GST_AUDIO_CHEB_LIMIT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_CHEB_LIMIT,GstAudioChebLimit))
+#define GST_IS_AUDIO_CHEB_LIMIT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_CHEB_LIMIT))
+#define GST_AUDIO_CHEB_LIMIT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_CHEB_LIMIT,GstAudioChebLimitClass))
+#define GST_IS_AUDIO_CHEB_LIMIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_CHEB_LIMIT))
+#define GST_AUDIO_CHEB_LIMIT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_CHEB_LIMIT,GstAudioChebLimitClass))
+
+typedef struct _GstAudioChebLimit GstAudioChebLimit;
+typedef struct _GstAudioChebLimitClass GstAudioChebLimitClass;
+
+struct _GstAudioChebLimit
+{
+  GstAudioFXBaseIIRFilter parent;
+
+  gint mode;
+  gint type;
+  gint poles;
+  gfloat cutoff;
+  gfloat ripple;
+
+  /* < private > */
+  GMutex *lock;
+};
+
+struct _GstAudioChebLimitClass
+{
+  GstAudioFXBaseIIRFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_cheb_limit_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_CHEB_LIMIT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiodynamic.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,711 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-audiodynamic
+ *
+ * This element can act as a compressor or expander. A compressor changes the
+ * amplitude of all samples above a specific threshold with a specific ratio,
+ * a expander does the same for all samples below a specific threshold. If
+ * soft-knee mode is selected the ratio is applied smoothly.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc wave=saw ! audiodynamic characteristics=soft-knee mode=compressor threshold=0.5 rate=0.5 ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiodynamic characteristics=hard-knee mode=expander threshold=0.2 rate=4.0 ! alsasink
+ * gst-launch audiotestsrc wave=saw ! audioconvert ! audiodynamic ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+/* TODO: Implement attack and release parameters */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiodynamic.h"
+
+#define GST_CAT_DEFAULT gst_audio_dynamic_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("Dynamic range controller",
+    "Filter/Effect/Audio",
+    "Compressor and Expander",
+    "Sebastian Dröge <slomo@circular-chaos.org>");
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_CHARACTERISTICS,
+  PROP_MODE,
+  PROP_THRESHOLD,
+  PROP_RATIO
+};
+
+#define ALLOWED_CAPS \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)16,"                                                 \
+    " width=(int)16,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-float,"                                              \
+    " width=(int)32,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_dynamic_debug, "audiodynamic", 0, "audiodynamic element");
+
+GST_BOILERPLATE_FULL (GstAudioDynamic, gst_audio_dynamic, GstAudioFilter,
+    GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+
+static void gst_audio_dynamic_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_dynamic_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_audio_dynamic_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+static GstFlowReturn gst_audio_dynamic_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf);
+
+static void
+gst_audio_dynamic_transform_hard_knee_compressor_int (GstAudioDynamic * filter,
+    gint16 * data, guint num_samples);
+static void
+gst_audio_dynamic_transform_hard_knee_compressor_float (GstAudioDynamic *
+    filter, gfloat * data, guint num_samples);
+static void
+gst_audio_dynamic_transform_soft_knee_compressor_int (GstAudioDynamic * filter,
+    gint16 * data, guint num_samples);
+static void
+gst_audio_dynamic_transform_soft_knee_compressor_float (GstAudioDynamic *
+    filter, gfloat * data, guint num_samples);
+static void gst_audio_dynamic_transform_hard_knee_expander_int (GstAudioDynamic
+    * filter, gint16 * data, guint num_samples);
+static void
+gst_audio_dynamic_transform_hard_knee_expander_float (GstAudioDynamic * filter,
+    gfloat * data, guint num_samples);
+static void gst_audio_dynamic_transform_soft_knee_expander_int (GstAudioDynamic
+    * filter, gint16 * data, guint num_samples);
+static void
+gst_audio_dynamic_transform_soft_knee_expander_float (GstAudioDynamic * filter,
+    gfloat * data, guint num_samples);
+
+static GstAudioDynamicProcessFunc process_functions[] = {
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_hard_knee_compressor_int,
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_hard_knee_compressor_float,
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_soft_knee_compressor_int,
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_soft_knee_compressor_float,
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_hard_knee_expander_int,
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_hard_knee_expander_float,
+  (GstAudioDynamicProcessFunc)
+      gst_audio_dynamic_transform_soft_knee_expander_int,
+  (GstAudioDynamicProcessFunc)
+  gst_audio_dynamic_transform_soft_knee_expander_float
+};
+
+enum
+{
+  CHARACTERISTICS_HARD_KNEE = 0,
+  CHARACTERISTICS_SOFT_KNEE
+};
+
+#define GST_TYPE_AUDIO_DYNAMIC_CHARACTERISTICS (gst_audio_dynamic_characteristics_get_type ())
+static GType
+gst_audio_dynamic_characteristics_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {CHARACTERISTICS_HARD_KNEE, "Hard Knee (default)",
+          "hard-knee"},
+      {CHARACTERISTICS_SOFT_KNEE, "Soft Knee (smooth)",
+          "soft-knee"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioDynamicCharacteristics", values);
+  }
+  return gtype;
+}
+
+enum
+{
+  MODE_COMPRESSOR = 0,
+  MODE_EXPANDER
+};
+
+#define GST_TYPE_AUDIO_DYNAMIC_MODE (gst_audio_dynamic_mode_get_type ())
+static GType
+gst_audio_dynamic_mode_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {MODE_COMPRESSOR, "Compressor (default)",
+          "compressor"},
+      {MODE_EXPANDER, "Expander", "expander"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioDynamicMode", values);
+  }
+  return gtype;
+}
+
+static gboolean
+gst_audio_dynamic_set_process_function (GstAudioDynamic * filter)
+{
+  gint func_index;
+
+  func_index = (filter->mode == MODE_COMPRESSOR) ? 0 : 4;
+  func_index += (filter->characteristics == CHARACTERISTICS_HARD_KNEE) ? 0 : 2;
+  func_index +=
+      (GST_AUDIO_FILTER (filter)->format.type == GST_BUFTYPE_FLOAT) ? 1 : 0;
+
+  if (func_index >= 0 && func_index < 8) {
+    filter->process = process_functions[func_index];
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_dynamic_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *caps;
+
+  gst_element_class_set_details (element_class, &element_details);
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_dynamic_class_init (GstAudioDynamicClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_audio_dynamic_set_property;
+  gobject_class->get_property = gst_audio_dynamic_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_CHARACTERISTICS,
+      g_param_spec_enum ("characteristics", "Characteristics",
+          "Selects whether the ratio should be applied smooth (soft-knee) "
+          "or hard (hard-knee).",
+          GST_TYPE_AUDIO_DYNAMIC_CHARACTERISTICS, CHARACTERISTICS_HARD_KNEE,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode", "Mode",
+          "Selects whether the filter should work on loud samples (compressor) or"
+          "quiet samples (expander).",
+          GST_TYPE_AUDIO_DYNAMIC_MODE, MODE_COMPRESSOR, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_THRESHOLD,
+      g_param_spec_float ("threshold", "Threshold",
+          "Threshold until the filter is activated", 0.0, 1.0,
+          0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_RATIO,
+      g_param_spec_float ("ratio", "Ratio",
+          "Ratio that should be applied", 0.0, G_MAXFLOAT,
+          1.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  GST_AUDIO_FILTER_CLASS (klass)->setup =
+      GST_DEBUG_FUNCPTR (gst_audio_dynamic_setup);
+  GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_audio_dynamic_transform_ip);
+}
+
+static void
+gst_audio_dynamic_init (GstAudioDynamic * filter, GstAudioDynamicClass * klass)
+{
+  filter->ratio = 1.0;
+  filter->threshold = 0.0;
+  filter->characteristics = CHARACTERISTICS_HARD_KNEE;
+  filter->mode = MODE_COMPRESSOR;
+  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
+  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
+}
+
+static void
+gst_audio_dynamic_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioDynamic *filter = GST_AUDIO_DYNAMIC (object);
+
+  switch (prop_id) {
+    case PROP_CHARACTERISTICS:
+      filter->characteristics = g_value_get_enum (value);
+      gst_audio_dynamic_set_process_function (filter);
+      break;
+    case PROP_MODE:
+      filter->mode = g_value_get_enum (value);
+      gst_audio_dynamic_set_process_function (filter);
+      break;
+    case PROP_THRESHOLD:
+      filter->threshold = g_value_get_float (value);
+      break;
+    case PROP_RATIO:
+      filter->ratio = g_value_get_float (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_dynamic_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioDynamic *filter = GST_AUDIO_DYNAMIC (object);
+
+  switch (prop_id) {
+    case PROP_CHARACTERISTICS:
+      g_value_set_enum (value, filter->characteristics);
+      break;
+    case PROP_MODE:
+      g_value_set_enum (value, filter->mode);
+      break;
+    case PROP_THRESHOLD:
+      g_value_set_float (value, filter->threshold);
+      break;
+    case PROP_RATIO:
+      g_value_set_float (value, filter->ratio);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_dynamic_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioDynamic *filter = GST_AUDIO_DYNAMIC (base);
+  gboolean ret = TRUE;
+
+  ret = gst_audio_dynamic_set_process_function (filter);
+
+  return ret;
+}
+
+static void
+gst_audio_dynamic_transform_hard_knee_compressor_int (GstAudioDynamic * filter,
+    gint16 * data, guint num_samples)
+{
+  glong val;
+  glong thr_p = filter->threshold * G_MAXINT16;
+  glong thr_n = filter->threshold * G_MININT16;
+
+  /* Nothing to do for us if ratio is 1.0 or if the threshold
+   * equals 1.0. */
+  if (filter->threshold == 1.0 || filter->ratio == 1.0)
+    return;
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val > thr_p) {
+      val = thr_p + (val - thr_p) * filter->ratio;
+    } else if (val < thr_n) {
+      val = thr_n + (val - thr_n) * filter->ratio;
+    }
+    *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_dynamic_transform_hard_knee_compressor_float (GstAudioDynamic *
+    filter, gfloat * data, guint num_samples)
+{
+  gdouble val, threshold = filter->threshold;
+
+  /* Nothing to do for us if ratio == 1.0.
+   * As float values can be above 1.0 we have to do something
+   * if threshold is greater than 1.0. */
+  if (filter->ratio == 1.0)
+    return;
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val > threshold) {
+      val = threshold + (val - threshold) * filter->ratio;
+    } else if (val < -threshold) {
+      val = -threshold + (val + threshold) * filter->ratio;
+    }
+    *data++ = (gfloat) val;
+  }
+}
+
+static void
+gst_audio_dynamic_transform_soft_knee_compressor_int (GstAudioDynamic * filter,
+    gint16 * data, guint num_samples)
+{
+  glong val;
+  glong thr_p = filter->threshold * G_MAXINT16;
+  glong thr_n = filter->threshold * G_MININT16;
+  gdouble a_p, b_p, c_p;
+  gdouble a_n, b_n, c_n;
+
+  /* Nothing to do for us if ratio is 1.0 or if the threshold
+   * equals 1.0. */
+  if (filter->threshold == 1.0 || filter->ratio == 1.0)
+    return;
+
+  /* We build a 2nd degree polynomial here for
+   * values greater than threshold or small than
+   * -threshold with:
+   * f(t) = t, f'(t) = 1, f'(m) = r
+   * =>
+   * a = (1-r)/(2*(t-m))
+   * b = (r*t - m)/(t-m)
+   * c = t * (1 - b - a*t)
+   * f(x) = ax^2 + bx + c
+   */
+
+  /* shouldn't happen because this would only be the case
+   * for threshold == 1.0 which we catch above */
+  g_assert (thr_p - G_MAXINT16 != 0);
+  g_assert (thr_n - G_MININT != 0);
+
+  a_p = (1 - filter->ratio) / (2 * (thr_p - G_MAXINT16));
+  b_p = (filter->ratio * thr_p - G_MAXINT16) / (thr_p - G_MAXINT16);
+  c_p = thr_p * (1 - b_p - a_p * thr_p);
+  a_n = (1 - filter->ratio) / (2 * (thr_n - G_MININT16));
+  b_n = (filter->ratio * thr_n - G_MININT16) / (thr_n - G_MININT16);
+  c_n = thr_n * (1 - b_n - a_n * thr_n);
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val > thr_p) {
+      val = a_p * val * val + b_p * val + c_p;
+    } else if (val < thr_n) {
+      val = a_n * val * val + b_n * val + c_n;
+    }
+    *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_dynamic_transform_soft_knee_compressor_float (GstAudioDynamic *
+    filter, gfloat * data, guint num_samples)
+{
+  gdouble val;
+  gdouble threshold = filter->threshold;
+  gdouble a_p, b_p, c_p;
+  gdouble a_n, b_n, c_n;
+
+  /* Nothing to do for us if ratio == 1.0.
+   * As float values can be above 1.0 we have to do something
+   * if threshold is greater than 1.0. */
+  if (filter->ratio == 1.0)
+    return;
+
+  /* We build a 2nd degree polynomial here for
+   * values greater than threshold or small than
+   * -threshold with:
+   * f(t) = t, f'(t) = 1, f'(m) = r
+   * =>
+   * a = (1-r)/(2*(t-m))
+   * b = (r*t - m)/(t-m)
+   * c = t * (1 - b - a*t)
+   * f(x) = ax^2 + bx + c
+   */
+
+  /* FIXME: If treshold is the same as the maximum
+   * we need to raise it a bit to prevent
+   * division by zero. */
+  if (threshold == 1.0)
+    threshold = 1.0 + 0.00001;
+
+  a_p = (1.0 - filter->ratio) / (2.0 * (threshold - 1.0));
+  b_p = (filter->ratio * threshold - 1.0) / (threshold - 1.0);
+  c_p = threshold * (1.0 - b_p - a_p * threshold);
+  a_n = (1.0 - filter->ratio) / (2.0 * (-threshold + 1.0));
+  b_n = (-filter->ratio * threshold + 1.0) / (-threshold + 1.0);
+  c_n = -threshold * (1.0 - b_n + a_n * threshold);
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val > 1.0) {
+      val = 1.0 + (val - 1.0) * filter->ratio;
+    } else if (val > threshold) {
+      val = a_p * val * val + b_p * val + c_p;
+    } else if (val < -1.0) {
+      val = -1.0 + (val + 1.0) * filter->ratio;
+    } else if (val < -threshold) {
+      val = a_n * val * val + b_n * val + c_n;
+    }
+    *data++ = (gfloat) val;
+  }
+}
+
+static void
+gst_audio_dynamic_transform_hard_knee_expander_int (GstAudioDynamic * filter,
+    gint16 * data, guint num_samples)
+{
+  glong val;
+  glong thr_p = filter->threshold * G_MAXINT16;
+  glong thr_n = filter->threshold * G_MININT16;
+  gdouble zero_p, zero_n;
+
+  /* Nothing to do for us here if threshold equals 0.0
+   * or ratio equals 1.0 */
+  if (filter->threshold == 0.0 || filter->ratio == 1.0)
+    return;
+
+  /* zero crossing of our function */
+  if (filter->ratio != 0.0) {
+    zero_p = thr_p - thr_p / filter->ratio;
+    zero_n = thr_n - thr_n / filter->ratio;
+  } else {
+    zero_p = zero_n = 0.0;
+  }
+
+  if (zero_p < 0.0)
+    zero_p = 0.0;
+  if (zero_n > 0.0)
+    zero_n = 0.0;
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val < thr_p && val > zero_p) {
+      val = filter->ratio * val + thr_p * (1 - filter->ratio);
+    } else if ((val <= zero_p && val > 0) || (val >= zero_n && val < 0)) {
+      val = 0;
+    } else if (val > thr_n && val < zero_n) {
+      val = filter->ratio * val + thr_n * (1 - filter->ratio);
+    }
+    *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_dynamic_transform_hard_knee_expander_float (GstAudioDynamic * filter,
+    gfloat * data, guint num_samples)
+{
+  gdouble val, threshold = filter->threshold, zero;
+
+  /* Nothing to do for us here if threshold equals 0.0
+   * or ratio equals 1.0 */
+  if (filter->threshold == 0.0 || filter->ratio == 1.0)
+    return;
+
+  /* zero crossing of our function */
+  if (filter->ratio != 0.0)
+    zero = threshold - threshold / filter->ratio;
+  else
+    zero = 0.0;
+
+  if (zero < 0.0)
+    zero = 0.0;
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val < threshold && val > zero) {
+      val = filter->ratio * val + threshold * (1.0 - filter->ratio);
+    } else if ((val <= zero && val > 0.0) || (val >= -zero && val < 0.0)) {
+      val = 0.0;
+    } else if (val > -threshold && val < -zero) {
+      val = filter->ratio * val - threshold * (1.0 - filter->ratio);
+    }
+    *data++ = (gfloat) val;
+  }
+}
+
+static void
+gst_audio_dynamic_transform_soft_knee_expander_int (GstAudioDynamic * filter,
+    gint16 * data, guint num_samples)
+{
+  glong val;
+  glong thr_p = filter->threshold * G_MAXINT16;
+  glong thr_n = filter->threshold * G_MININT16;
+  gdouble zero_p, zero_n;
+  gdouble a_p, b_p, c_p;
+  gdouble a_n, b_n, c_n;
+
+  /* Nothing to do for us here if threshold equals 0.0
+   * or ratio equals 1.0 */
+  if (filter->threshold == 0.0 || filter->ratio == 1.0)
+    return;
+
+  /* zero crossing of our function */
+  zero_p = (thr_p * (filter->ratio - 1.0)) / (1.0 + filter->ratio);
+  zero_n = (thr_n * (filter->ratio - 1.0)) / (1.0 + filter->ratio);
+
+  if (zero_p < 0.0)
+    zero_p = 0.0;
+  if (zero_n > 0.0)
+    zero_n = 0.0;
+
+  /* shouldn't happen as this would only happen
+   * with threshold == 0.0 */
+  g_assert (thr_p != 0);
+  g_assert (thr_n != 0);
+
+  /* We build a 2n degree polynomial here for values between
+   * 0 and threshold or 0 and -threshold with:
+   * f(t) = t, f'(t) = 1, f(z) = 0, f'(z) = r
+   * z between 0 and t
+   * =>
+   * a = (1 - r^2) / (4 * t)
+   * b = (1 + r^2) / 2
+   * c = t * (1.0 - b - a*t)
+   * f(x) = ax^2 + bx + c */
+  a_p = (1.0 - filter->ratio * filter->ratio) / (4.0 * thr_p);
+  b_p = (1.0 + filter->ratio * filter->ratio) / 2.0;
+  c_p = thr_p * (1.0 - b_p - a_p * thr_p);
+  a_n = (1.0 - filter->ratio * filter->ratio) / (4.0 * thr_n);
+  b_n = (1.0 + filter->ratio * filter->ratio) / 2.0;
+  c_n = thr_n * (1.0 - b_n - a_n * thr_n);
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val < thr_p && val > zero_p) {
+      val = a_p * val * val + b_p * val + c_p;
+    } else if ((val <= zero_p && val > 0) || (val >= zero_n && val < 0)) {
+      val = 0;
+    } else if (val > thr_n && val < zero_n) {
+      val = a_n * val * val + b_n * val + c_n;
+    }
+    *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_dynamic_transform_soft_knee_expander_float (GstAudioDynamic * filter,
+    gfloat * data, guint num_samples)
+{
+  gdouble val;
+  gdouble threshold = filter->threshold;
+  gdouble zero;
+  gdouble a_p, b_p, c_p;
+  gdouble a_n, b_n, c_n;
+
+  /* Nothing to do for us here if threshold equals 0.0
+   * or ratio equals 1.0 */
+  if (filter->threshold == 0.0 || filter->ratio == 1.0)
+    return;
+
+  /* zero crossing of our function */
+  zero = (threshold * (filter->ratio - 1.0)) / (1.0 + filter->ratio);
+
+  if (zero < 0.0)
+    zero = 0.0;
+
+  /* shouldn't happen as this only happens with
+   * threshold == 0.0 */
+  g_assert (threshold != 0.0);
+
+  /* We build a 2n degree polynomial here for values between
+   * 0 and threshold or 0 and -threshold with:
+   * f(t) = t, f'(t) = 1, f(z) = 0, f'(z) = r
+   * z between 0 and t
+   * =>
+   * a = (1 - r^2) / (4 * t)
+   * b = (1 + r^2) / 2
+   * c = t * (1.0 - b - a*t)
+   * f(x) = ax^2 + bx + c */
+  a_p = (1.0 - filter->ratio * filter->ratio) / (4.0 * threshold);
+  b_p = (1.0 + filter->ratio * filter->ratio) / 2.0;
+  c_p = threshold * (1.0 - b_p - a_p * threshold);
+  a_n = (1.0 - filter->ratio * filter->ratio) / (-4.0 * threshold);
+  b_n = (1.0 + filter->ratio * filter->ratio) / 2.0;
+  c_n = -threshold * (1.0 - b_n + a_n * threshold);
+
+  for (; num_samples; num_samples--) {
+    val = *data;
+
+    if (val < threshold && val > zero) {
+      val = a_p * val * val + b_p * val + c_p;
+    } else if ((val <= zero && val > 0.0) || (val >= -zero && val < 0.0)) {
+      val = 0.0;
+    } else if (val > -threshold && val < -zero) {
+      val = a_n * val * val + b_n * val + c_n;
+    }
+    *data++ = (gfloat) val;
+  }
+}
+
+/* GstBaseTransform vmethod implementations */
+static GstFlowReturn
+gst_audio_dynamic_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+  GstAudioDynamic *filter = GST_AUDIO_DYNAMIC (base);
+  guint num_samples =
+      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
+    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
+
+  if (gst_base_transform_is_passthrough (base) ||
+      G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
+    return GST_FLOW_OK;
+
+  filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
+
+  return GST_FLOW_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiodynamic.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,70 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * 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_AUDIO_DYNAMIC_H__
+#define __GST_AUDIO_DYNAMIC_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_DYNAMIC            (gst_audio_dynamic_get_type())
+#define GST_AUDIO_DYNAMIC(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_DYNAMIC,GstAudioDynamic))
+#define GST_IS_AUDIO_DYNAMIC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_DYNAMIC))
+#define GST_AUDIO_DYNAMIC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_DYNAMIC,GstAudioDynamicClass))
+#define GST_IS_AUDIO_DYNAMIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_DYNAMIC))
+#define GST_AUDIO_DYNAMIC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_DYNAMIC,GstAudioDynamicClass))
+typedef struct _GstAudioDynamic GstAudioDynamic;
+typedef struct _GstAudioDynamicClass GstAudioDynamicClass;
+
+typedef void (*GstAudioDynamicProcessFunc) (GstAudioDynamic *, guint8 *, guint);
+
+struct _GstAudioDynamic
+{
+  GstAudioFilter audiofilter;
+
+  gfloat degree;
+
+  /* < private > */
+  GstAudioDynamicProcessFunc process;
+  gint characteristics;
+  gint mode;
+  gfloat threshold;
+  gfloat ratio;
+};
+
+struct _GstAudioDynamicClass
+{
+  GstAudioFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_dynamic_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_DYNAMIC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioecho.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,391 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-audioecho
+ * @Since: 0.10.14
+ *
+ * audioecho adds an echo or (simple) reverb effect to an audio stream. The echo
+ * delay, intensity and the percentage of feedback can be configured.
+ *
+ * For getting an echo effect you have to set the delay to a larger value,
+ * for example 200ms and more. Everything below will result in a simple
+ * reverb effect, which results in a slightly metallic sound.
+ *
+ * Use the max-delay property to set the maximum amount of delay that
+ * will be used. This can only be set before going to the PAUSED or PLAYING
+ * state and will be set to the current delay by default.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location="melo1.ogg" ! audioconvert ! audioecho delay=500000000 intensity=0.6 feedback=0.4 ! audioconvert ! autoaudiosink
+ * gst-launch filesrc location="melo1.ogg" ! decodebin ! audioconvert ! audioecho delay=50000000 intensity=0.6 feedback=0.4 ! audioconvert ! autoaudiosink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audioecho.h"
+
+#define GST_CAT_DEFAULT gst_audio_echo_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  PROP_0,
+  PROP_DELAY,
+  PROP_MAX_DELAY,
+  PROP_INTENSITY,
+  PROP_FEEDBACK
+};
+
+#define ALLOWED_CAPS \
+    "audio/x-raw-float,"                                              \
+    " width=(int) { 32, 64 }, "                                       \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_echo_debug, "audioecho", 0, "audioecho element");
+
+GST_BOILERPLATE_FULL (GstAudioEcho, gst_audio_echo, GstAudioFilter,
+    GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+
+static void gst_audio_echo_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_echo_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_echo_finalize (GObject * object);
+
+static gboolean gst_audio_echo_setup (GstAudioFilter * self,
+    GstRingBufferSpec * format);
+static gboolean gst_audio_echo_stop (GstBaseTransform * base);
+static GstFlowReturn gst_audio_echo_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf);
+
+static void gst_audio_echo_transform_float (GstAudioEcho * self,
+    gfloat * data, guint num_samples);
+static void gst_audio_echo_transform_double (GstAudioEcho * self,
+    gdouble * data, guint num_samples);
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_echo_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *caps;
+
+  gst_element_class_set_details_simple (element_class, "Audio echo",
+      "Filter/Effect/Audio",
+      "Adds an echo or reverb effect to an audio stream",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_echo_class_init (GstAudioEchoClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBaseTransformClass *basetransform_class = (GstBaseTransformClass *) klass;
+  GstAudioFilterClass *audioself_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_echo_set_property;
+  gobject_class->get_property = gst_audio_echo_get_property;
+  gobject_class->finalize = gst_audio_echo_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_DELAY,
+      g_param_spec_uint64 ("delay", "Delay",
+          "Delay of the echo in nanoseconds", 1, G_MAXUINT64,
+          1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
+          | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_MAX_DELAY,
+      g_param_spec_uint64 ("max-delay", "Maximum Delay",
+          "Maximum delay of the echo in nanoseconds"
+          " (can't be changed in PLAYING or PAUSED state)",
+          1, G_MAXUINT64, 1,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_INTENSITY,
+      g_param_spec_float ("intensity", "Intensity",
+          "Intensity of the echo", 0.0, 1.0,
+          0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
+          | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_FEEDBACK,
+      g_param_spec_float ("feedback", "Feedback",
+          "Amount of feedback", 0.0, 1.0,
+          0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
+          | GST_PARAM_CONTROLLABLE));
+
+  audioself_class->setup = GST_DEBUG_FUNCPTR (gst_audio_echo_setup);
+  basetransform_class->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_audio_echo_transform_ip);
+  basetransform_class->stop = GST_DEBUG_FUNCPTR (gst_audio_echo_stop);
+}
+
+static void
+gst_audio_echo_init (GstAudioEcho * self, GstAudioEchoClass * klass)
+{
+  self->delay = 1;
+  self->max_delay = 1;
+  self->intensity = 0.0;
+  self->feedback = 0.0;
+
+  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (self), TRUE);
+}
+
+static void
+gst_audio_echo_finalize (GObject * object)
+{
+  GstAudioEcho *self = GST_AUDIO_ECHO (object);
+
+  g_free (self->buffer);
+  self->buffer = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_echo_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioEcho *self = GST_AUDIO_ECHO (object);
+
+  switch (prop_id) {
+    case PROP_DELAY:{
+      guint64 max_delay, delay;
+
+      GST_BASE_TRANSFORM_LOCK (self);
+      delay = g_value_get_uint64 (value);
+      max_delay = self->max_delay;
+
+      if (delay > max_delay && GST_STATE (self) > GST_STATE_READY) {
+        GST_WARNING_OBJECT (self, "New delay (%" GST_TIME_FORMAT ") "
+            "is larger than maximum delay (%" GST_TIME_FORMAT ")",
+            GST_TIME_ARGS (delay), GST_TIME_ARGS (max_delay));
+        self->delay = max_delay;
+      } else {
+        self->delay = delay;
+        self->max_delay = MAX (delay, max_delay);
+      }
+      GST_BASE_TRANSFORM_UNLOCK (self);
+    }
+      break;
+    case PROP_MAX_DELAY:{
+      guint64 max_delay, delay;
+
+      GST_BASE_TRANSFORM_LOCK (self);
+      max_delay = g_value_get_uint64 (value);
+      delay = self->delay;
+
+      if (GST_STATE (self) > GST_STATE_READY) {
+        GST_ERROR_OBJECT (self, "Can't change maximum delay in"
+            " PLAYING or PAUSED state");
+      } else {
+        self->delay = delay;
+        self->max_delay = max_delay;
+      }
+      GST_BASE_TRANSFORM_UNLOCK (self);
+    }
+      break;
+    case PROP_INTENSITY:{
+      GST_BASE_TRANSFORM_LOCK (self);
+      self->intensity = g_value_get_float (value);
+      GST_BASE_TRANSFORM_UNLOCK (self);
+    }
+      break;
+    case PROP_FEEDBACK:{
+      GST_BASE_TRANSFORM_LOCK (self);
+      self->feedback = g_value_get_float (value);
+      GST_BASE_TRANSFORM_UNLOCK (self);
+    }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_echo_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioEcho *self = GST_AUDIO_ECHO (object);
+
+  switch (prop_id) {
+    case PROP_DELAY:
+      GST_BASE_TRANSFORM_LOCK (self);
+      g_value_set_uint64 (value, self->delay);
+      GST_BASE_TRANSFORM_UNLOCK (self);
+      break;
+    case PROP_MAX_DELAY:
+      GST_BASE_TRANSFORM_LOCK (self);
+      g_value_set_uint64 (value, self->max_delay);
+      GST_BASE_TRANSFORM_UNLOCK (self);
+      break;
+    case PROP_INTENSITY:
+      GST_BASE_TRANSFORM_LOCK (self);
+      g_value_set_float (value, self->intensity);
+      GST_BASE_TRANSFORM_UNLOCK (self);
+      break;
+    case PROP_FEEDBACK:
+      GST_BASE_TRANSFORM_LOCK (self);
+      g_value_set_float (value, self->feedback);
+      GST_BASE_TRANSFORM_UNLOCK (self);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_echo_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioEcho *self = GST_AUDIO_ECHO (base);
+  gboolean ret = TRUE;
+
+  if (format->type == GST_BUFTYPE_FLOAT && format->width == 32)
+    self->process = (GstAudioEchoProcessFunc)
+        gst_audio_echo_transform_float;
+  else if (format->type == GST_BUFTYPE_FLOAT && format->width == 64)
+    self->process = (GstAudioEchoProcessFunc)
+        gst_audio_echo_transform_double;
+  else
+    ret = FALSE;
+
+  g_free (self->buffer);
+  self->buffer = NULL;
+  self->buffer_pos = 0;
+  self->buffer_size = 0;
+  self->buffer_size_frames = 0;
+
+  return ret;
+}
+
+static gboolean
+gst_audio_echo_stop (GstBaseTransform * base)
+{
+  GstAudioEcho *self = GST_AUDIO_ECHO (base);
+
+  g_free (self->buffer);
+  self->buffer = NULL;
+  self->buffer_pos = 0;
+  self->buffer_size = 0;
+  self->buffer_size_frames = 0;
+
+  return TRUE;
+}
+
+#define TRANSFORM_FUNC(name, type) \
+static void \
+gst_audio_echo_transform_##name (GstAudioEcho * self, \
+    type * data, guint num_samples) \
+{ \
+  type *buffer = (type *) self->buffer; \
+  guint channels = GST_AUDIO_FILTER (self)->format.channels; \
+  guint rate = GST_AUDIO_FILTER (self)->format.rate; \
+  guint i, j; \
+  guint echo_index = self->buffer_size_frames - self->delay_frames; \
+  gdouble echo_off = ((((gdouble) self->delay) * rate) / GST_SECOND) - self->delay_frames; \
+  \
+  if (echo_off < 0.0) \
+    echo_off = 0.0; \
+  \
+  num_samples /= channels; \
+  \
+  for (i = 0; i < num_samples; i++) { \
+    guint echo0_index = ((echo_index + self->buffer_pos) % self->buffer_size_frames) * channels; \
+    guint echo1_index = ((echo_index + self->buffer_pos +1) % self->buffer_size_frames) * channels; \
+    guint rbout_index = (self->buffer_pos % self->buffer_size_frames) * channels; \
+    for (j = 0; j < channels; j++) { \
+      gdouble in = data[i*channels + j]; \
+      gdouble echo0 = buffer[echo0_index + j]; \
+      gdouble echo1 = buffer[echo1_index + j]; \
+      gdouble echo = echo0 + (echo1-echo0)*echo_off; \
+      type out = in + self->intensity * echo; \
+      \
+      data[i*channels + j] = out; \
+      \
+      buffer[rbout_index + j] = in + self->feedback * echo; \
+    } \
+    self->buffer_pos = (self->buffer_pos + 1) % self->buffer_size_frames; \
+  } \
+}
+
+TRANSFORM_FUNC (float, gfloat);
+TRANSFORM_FUNC (double, gdouble);
+
+/* GstBaseTransform vmethod implementations */
+static GstFlowReturn
+gst_audio_echo_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+  GstAudioEcho *self = GST_AUDIO_ECHO (base);
+  guint num_samples =
+      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (self)->format.width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
+    gst_object_sync_values (G_OBJECT (self), GST_BUFFER_TIMESTAMP (buf));
+
+  if (self->buffer == NULL) {
+    guint width, rate, channels;
+
+    width = GST_AUDIO_FILTER (self)->format.width / 8;
+    rate = GST_AUDIO_FILTER (self)->format.rate;
+    channels = GST_AUDIO_FILTER (self)->format.channels;
+
+    self->delay_frames =
+        MAX (gst_util_uint64_scale (self->delay, rate, GST_SECOND), 1);
+    self->buffer_size_frames =
+        MAX (gst_util_uint64_scale (self->max_delay, rate, GST_SECOND), 1);
+
+    self->buffer_size = self->buffer_size_frames * width * channels;
+    self->buffer = g_try_malloc0 (self->buffer_size);
+    self->buffer_pos = 0;
+
+    if (self->buffer == NULL) {
+      GST_ERROR_OBJECT (self, "Failed to allocate %u bytes", self->buffer_size);
+      return GST_FLOW_ERROR;
+    }
+  }
+
+  self->process (self, GST_BUFFER_DATA (buf), num_samples);
+
+  return GST_FLOW_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioecho.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,74 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_ECHO_H__
+#define __GST_AUDIO_ECHO_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_ECHO            (gst_audio_echo_get_type())
+#define GST_AUDIO_ECHO(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_ECHO,GstAudioEcho))
+#define GST_IS_AUDIO_ECHO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_ECHO))
+#define GST_AUDIO_ECHO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_ECHO,GstAudioEchoClass))
+#define GST_IS_AUDIO_ECHO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_ECHO))
+#define GST_AUDIO_ECHO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_ECHO,GstAudioEchoClass))
+typedef struct _GstAudioEcho GstAudioEcho;
+typedef struct _GstAudioEchoClass GstAudioEchoClass;
+
+typedef void (*GstAudioEchoProcessFunc) (GstAudioEcho *, guint8 *, guint);
+
+struct _GstAudioEcho
+{
+  GstAudioFilter audiofilter;
+
+  guint64 delay;
+  guint64 max_delay;
+  gfloat intensity;
+  gfloat feedback;
+
+  /* < private > */
+  GstAudioEchoProcessFunc process;
+  guint delay_frames;
+  guint8 *buffer;
+  guint buffer_pos;
+  guint buffer_size;
+  guint buffer_size_frames;
+};
+
+struct _GstAudioEchoClass
+{
+  GstAudioFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_echo_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_ECHO_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofirfilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,269 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ * 
+ */
+
+/**
+ * SECTION:element-audiofirfilter
+ *
+ * audiofirfilter implements a generic audio <ulink url="http://en.wikipedia.org/wiki/Finite_impulse_response">FIR filter</ulink>. Before usage the
+ * "kernel" property has to be set to the filter kernel that should be
+ * used and the "latency" property has to be set to the latency (in samples)
+ * that is introduced by the filter kernel. Setting a latency of n samples
+ * will lead to the first n samples being dropped from the output and
+ * n samples added to the end.
+ *
+ * The filter kernel describes the impulse response of the filter. To
+ * calculate the frequency response of the filter you have to calculate
+ * the Fourier Transform of the impulse response.
+ *
+ * To change the filter kernel whenever the sampling rate changes the
+ * "rate-changed" signal can be used. This should be done for most
+ * FIR filters as they're depending on the sampling rate.
+ *
+ * <refsect2>
+ * <title>Example application</title>
+ * |[
+ * <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" parse="text" href="../../../../tests/examples/audiofx/firfilter-example.c" />
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiofirfilter.h"
+
+#define GST_CAT_DEFAULT gst_audio_fir_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  SIGNAL_RATE_CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_KERNEL,
+  PROP_LATENCY
+};
+
+static guint gst_audio_fir_filter_signals[LAST_SIGNAL] = { 0, };
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_fir_filter_debug, "audiofirfilter", 0, \
+      "Generic audio FIR filter plugin");
+
+GST_BOILERPLATE_FULL (GstAudioFIRFilter, gst_audio_fir_filter, GstAudioFilter,
+    GST_TYPE_AUDIO_FX_BASE_FIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_fir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_fir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_fir_filter_finalize (GObject * object);
+
+static gboolean gst_audio_fir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+/* Element class */
+static void
+gst_audio_fir_filter_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Audio FIR filter", "Filter/Effect/Audio",
+      "Generic audio FIR filter with custom filter kernel",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_fir_filter_class_init (GstAudioFIRFilterClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_fir_filter_set_property;
+  gobject_class->get_property = gst_audio_fir_filter_get_property;
+  gobject_class->finalize = gst_audio_fir_filter_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_KERNEL,
+      g_param_spec_value_array ("kernel", "Filter Kernel",
+          "Filter kernel for the FIR filter",
+          g_param_spec_double ("Element", "Filter Kernel Element",
+              "Element of the filter kernel", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_LATENCY,
+      g_param_spec_uint64 ("latency", "Latecy",
+          "Filter latency in samples",
+          0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fir_filter_setup);
+
+  /**
+   * GstAudioFIRFilter::rate-changed:
+   * @filter: the filter on which the signal is emitted
+   * @rate: the new sampling rate
+   *
+   * Will be emitted when the sampling rate changes. The callbacks
+   * will be called from the streaming thread and processing will
+   * stop until the event is handled.
+   */
+  gst_audio_fir_filter_signals[SIGNAL_RATE_CHANGED] =
+      g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioFIRFilterClass, rate_changed),
+      NULL, NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+static void
+gst_audio_fir_filter_update_kernel (GstAudioFIRFilter * self, GValueArray * va)
+{
+  gdouble *kernel;
+  guint i;
+
+  gst_audio_fx_base_fir_filter_push_residue (GST_AUDIO_FX_BASE_FIR_FILTER
+      (self));
+
+  if (va) {
+    if (self->kernel)
+      g_value_array_free (self->kernel);
+
+    self->kernel = va;
+  }
+
+  kernel = g_new (gdouble, self->kernel->n_values);
+
+  for (i = 0; i < self->kernel->n_values; i++) {
+    GValue *v = g_value_array_get_nth (self->kernel, i);
+    kernel[i] = g_value_get_double (v);
+  }
+
+  gst_audio_fx_base_fir_filter_set_kernel (GST_AUDIO_FX_BASE_FIR_FILTER (self),
+      kernel, self->kernel->n_values, self->latency);
+}
+
+static void
+gst_audio_fir_filter_init (GstAudioFIRFilter * self,
+    GstAudioFIRFilterClass * g_class)
+{
+  GValue v = { 0, };
+  GValueArray *va;
+
+  self->latency = 0;
+  va = g_value_array_new (1);
+
+  g_value_init (&v, G_TYPE_DOUBLE);
+  g_value_set_double (&v, 1.0);
+  g_value_array_append (va, &v);
+  g_value_unset (&v);
+  gst_audio_fir_filter_update_kernel (self, va);
+
+  self->lock = g_mutex_new ();
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_fir_filter_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (base);
+
+  if (self->rate != format->rate) {
+    g_signal_emit (G_OBJECT (self),
+        gst_audio_fir_filter_signals[SIGNAL_RATE_CHANGED], 0, format->rate);
+    self->rate = format->rate;
+  }
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
+
+static void
+gst_audio_fir_filter_finalize (GObject * object)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
+
+  g_mutex_free (self->lock);
+  self->lock = NULL;
+
+  if (self->kernel)
+    g_value_array_free (self->kernel);
+  self->kernel = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_fir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
+
+  g_return_if_fail (GST_IS_AUDIO_FIR_FILTER (self));
+
+  switch (prop_id) {
+    case PROP_KERNEL:
+      g_mutex_lock (self->lock);
+      gst_audio_fx_base_fir_filter_push_residue (GST_AUDIO_FX_BASE_FIR_FILTER
+          (self));
+
+      gst_audio_fir_filter_update_kernel (self, g_value_dup_boxed (value));
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_LATENCY:
+      g_mutex_lock (self->lock);
+      self->latency = g_value_get_uint64 (value);
+      gst_audio_fir_filter_update_kernel (self, NULL);
+      g_mutex_unlock (self->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_fir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
+
+  switch (prop_id) {
+    case PROP_KERNEL:
+      g_value_set_boxed (value, self->kernel);
+      break;
+    case PROP_LATENCY:
+      g_value_set_uint64 (value, self->latency);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofirfilter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,77 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_FIR_FILTER_H__
+#define __GST_AUDIO_FIR_FILTER_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/audio/gstaudiofilter.h>
+
+#include "audiofxbasefirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_FIR_FILTER \
+  (gst_audio_fir_filter_get_type())
+#define GST_AUDIO_FIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FIR_FILTER,GstAudioFIRFilter))
+#define GST_AUDIO_FIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_FIR_FILTER,GstAudioFIRFilterClass))
+#define GST_IS_AUDIO_FIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FIR_FILTER))
+#define GST_IS_AUDIO_FIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_FIR_FILTER))
+
+typedef struct _GstAudioFIRFilter GstAudioFIRFilter;
+typedef struct _GstAudioFIRFilterClass GstAudioFIRFilterClass;
+
+/**
+ * GstAudioFIRFilter:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioFIRFilter {
+  GstAudioFXBaseFIRFilter parent;
+
+  GValueArray *kernel;
+  guint64 latency;
+
+  /* < private > */
+  GMutex *lock;
+  gint rate;
+};
+
+struct _GstAudioFIRFilterClass {
+  GstAudioFXBaseFIRFilterClass parent;
+
+  void (*rate_changed) (GstElement * element, gint rate);
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_fir_filter_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_FIR_FILTER_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofx.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,89 @@
+/*
+ * GStreamer
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiopanorama.h"
+#include "audioinvert.h"
+#include "audiokaraoke.h"
+#include "audioamplify.h"
+#include "audiodynamic.h"
+#include "audiocheblimit.h"
+#include "audiochebband.h"
+#include "audioiirfilter.h"
+#include "audiowsincband.h"
+#include "audiowsinclimit.h"
+#include "audiofirfilter.h"
+#include "audioecho.h"
+
+/* entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and pad templates
+ * register the features
+ */
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  /* initialize gst controller library */
+  gst_controller_init (NULL, NULL);
+
+  return (gst_element_register (plugin, "audiopanorama", GST_RANK_NONE,
+          GST_TYPE_AUDIO_PANORAMA) &&
+      gst_element_register (plugin, "audioinvert", GST_RANK_NONE,
+          GST_TYPE_AUDIO_INVERT) &&
+      gst_element_register (plugin, "audiokaraoke", GST_RANK_NONE,
+          GST_TYPE_AUDIO_KARAOKE) &&
+      gst_element_register (plugin, "audioamplify", GST_RANK_NONE,
+          GST_TYPE_AUDIO_AMPLIFY) &&
+      gst_element_register (plugin, "audiodynamic", GST_RANK_NONE,
+          GST_TYPE_AUDIO_DYNAMIC) &&
+      gst_element_register (plugin, "audiocheblimit", GST_RANK_NONE,
+          GST_TYPE_AUDIO_CHEB_LIMIT) &&
+      gst_element_register (plugin, "audiochebband", GST_RANK_NONE,
+          GST_TYPE_AUDIO_CHEB_BAND) &&
+      gst_element_register (plugin, "audioiirfilter", GST_RANK_NONE,
+          GST_TYPE_AUDIO_IIR_FILTER) &&
+      gst_element_register (plugin, "audiowsinclimit", GST_RANK_NONE,
+          GST_TYPE_AUDIO_WSINC_LIMIT) &&
+      gst_element_register (plugin, "audiowsincband", GST_RANK_NONE,
+          GST_TYPE_AUDIO_WSINC_BAND) &&
+      gst_element_register (plugin, "audiofirfilter", GST_RANK_NONE,
+          GST_TYPE_AUDIO_FIR_FILTER) &&
+      gst_element_register (plugin, "audioecho", GST_RANK_NONE,
+          GST_TYPE_AUDIO_ECHO));
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "audiofx",
+    "Audio effects plugin",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+    
+    
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+	return &gst_plugin_desc;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofxbasefirfilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,527 @@
+/* -*- c-basic-offset: 2 -*-
+ * 
+ * GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2006 Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>
+ *               2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ * 
+ * 
+ * TODO:  - Implement the convolution in place, probably only makes sense
+ *          when using FFT convolution as currently the convolution itself
+ *          is probably the bottleneck
+ *        - Maybe allow cascading the filter to get a better stopband attenuation.
+ *          Can be done by convolving a filter kernel with itself
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiofxbasefirfilter.h"
+
+#define GST_CAT_DEFAULT gst_audio_fx_base_fir_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define ALLOWED_CAPS \
+    "audio/x-raw-float, "                                             \
+    " width = (int) { 32, 64 }, "                                     \
+    " endianness = (int) BYTE_ORDER, "                                \
+    " rate = (int) [ 1, MAX ], "                                      \
+    " channels = (int) [ 1, MAX ]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_fx_base_fir_filter_debug, "audiofxbasefirfilter", 0, \
+      "FIR filter base class");
+
+GST_BOILERPLATE_FULL (GstAudioFXBaseFIRFilter, gst_audio_fx_base_fir_filter,
+    GstAudioFilter, GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+
+static GstFlowReturn gst_audio_fx_base_fir_filter_transform (GstBaseTransform *
+    base, GstBuffer * inbuf, GstBuffer * outbuf);
+static gboolean gst_audio_fx_base_fir_filter_start (GstBaseTransform * base);
+static gboolean gst_audio_fx_base_fir_filter_stop (GstBaseTransform * base);
+static gboolean gst_audio_fx_base_fir_filter_event (GstBaseTransform * base,
+    GstEvent * event);
+static gboolean gst_audio_fx_base_fir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+static gboolean gst_audio_fx_base_fir_filter_query (GstPad * pad,
+    GstQuery * query);
+static const GstQueryType *gst_audio_fx_base_fir_filter_query_type (GstPad *
+    pad);
+
+/* Element class */
+
+static void
+gst_audio_fx_base_fir_filter_dispose (GObject * object)
+{
+  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (object);
+
+  if (self->residue) {
+    g_free (self->residue);
+    self->residue = NULL;
+  }
+
+  if (self->kernel) {
+    g_free (self->kernel);
+    self->kernel = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_audio_fx_base_fir_filter_base_init (gpointer g_class)
+{
+  GstCaps *caps;
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (g_class),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_fx_base_fir_filter_class_init (GstAudioFXBaseFIRFilterClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->dispose = gst_audio_fx_base_fir_filter_dispose;
+
+  trans_class->transform =
+      GST_DEBUG_FUNCPTR (gst_audio_fx_base_fir_filter_transform);
+  trans_class->start = GST_DEBUG_FUNCPTR (gst_audio_fx_base_fir_filter_start);
+  trans_class->stop = GST_DEBUG_FUNCPTR (gst_audio_fx_base_fir_filter_stop);
+  trans_class->event = GST_DEBUG_FUNCPTR (gst_audio_fx_base_fir_filter_event);
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fx_base_fir_filter_setup);
+}
+
+static void
+gst_audio_fx_base_fir_filter_init (GstAudioFXBaseFIRFilter * self,
+    GstAudioFXBaseFIRFilterClass * g_class)
+{
+  self->kernel = NULL;
+  self->residue = NULL;
+
+  self->next_ts = GST_CLOCK_TIME_NONE;
+  self->next_off = GST_BUFFER_OFFSET_NONE;
+
+  gst_pad_set_query_function (GST_BASE_TRANSFORM (self)->srcpad,
+      gst_audio_fx_base_fir_filter_query);
+  gst_pad_set_query_type_function (GST_BASE_TRANSFORM (self)->srcpad,
+      gst_audio_fx_base_fir_filter_query_type);
+}
+
+#define DEFINE_PROCESS_FUNC(width,ctype) \
+static void \
+process_##width (GstAudioFXBaseFIRFilter * self, g##ctype * src, g##ctype * dst, guint input_samples) \
+{ \
+  gint kernel_length = self->kernel_length; \
+  gint i, j, k, l; \
+  gint channels = GST_AUDIO_FILTER (self)->format.channels; \
+  gint res_start; \
+  \
+  /* convolution */ \
+  for (i = 0; i < input_samples; i++) { \
+    dst[i] = 0.0; \
+    k = i % channels; \
+    l = i / channels; \
+    for (j = 0; j < kernel_length; j++) \
+      if (l < j) \
+        dst[i] += \
+            self->residue[(kernel_length + l - j) * channels + \
+            k] * self->kernel[j]; \
+      else \
+        dst[i] += src[(l - j) * channels + k] * self->kernel[j]; \
+  } \
+  \
+  /* copy the tail of the current input buffer to the residue, while \
+   * keeping parts of the residue if the input buffer is smaller than \
+   * the kernel length */ \
+  if (input_samples < kernel_length * channels) \
+    res_start = kernel_length * channels - input_samples; \
+  else \
+    res_start = 0; \
+  \
+  for (i = 0; i < res_start; i++) \
+    self->residue[i] = self->residue[i + input_samples]; \
+  for (i = res_start; i < kernel_length * channels; i++) \
+    self->residue[i] = src[input_samples - kernel_length * channels + i]; \
+  \
+  self->residue_length += kernel_length * channels - res_start; \
+  if (self->residue_length > kernel_length * channels) \
+    self->residue_length = kernel_length * channels; \
+}
+
+DEFINE_PROCESS_FUNC (32, float);
+DEFINE_PROCESS_FUNC (64, double);
+
+#undef DEFINE_PROCESS_FUNC
+
+void
+gst_audio_fx_base_fir_filter_push_residue (GstAudioFXBaseFIRFilter * self)
+{
+  GstBuffer *outbuf;
+  GstFlowReturn res;
+  gint rate = GST_AUDIO_FILTER (self)->format.rate;
+  gint channels = GST_AUDIO_FILTER (self)->format.channels;
+  gint outsize, outsamples;
+  gint diffsize, diffsamples;
+  guint8 *in, *out;
+
+  if (channels == 0 || rate == 0) {
+    self->residue_length = 0;
+    return;
+  }
+
+  /* Calculate the number of samples and their memory size that
+   * should be pushed from the residue */
+  outsamples = MIN (self->latency, self->residue_length / channels);
+  outsize = outsamples * channels * (GST_AUDIO_FILTER (self)->format.width / 8);
+  if (outsize == 0) {
+    self->residue_length = 0;
+    return;
+  }
+
+  /* Process the difference between latency and residue_length samples
+   * to start at the actual data instead of starting at the zeros before
+   * when we only got one buffer smaller than latency */
+  diffsamples = self->latency - self->residue_length / channels;
+  diffsize =
+      diffsamples * channels * (GST_AUDIO_FILTER (self)->format.width / 8);
+  if (diffsize > 0) {
+    in = g_new0 (guint8, diffsize);
+    out = g_new0 (guint8, diffsize);
+    self->process (self, in, out, diffsamples * channels);
+    g_free (in);
+    g_free (out);
+  }
+
+  res = gst_pad_alloc_buffer (GST_BASE_TRANSFORM (self)->srcpad,
+      GST_BUFFER_OFFSET_NONE, outsize,
+      GST_PAD_CAPS (GST_BASE_TRANSFORM (self)->srcpad), &outbuf);
+
+  if (G_UNLIKELY (res != GST_FLOW_OK)) {
+    GST_WARNING_OBJECT (self, "failed allocating buffer of %d bytes", outsize);
+    self->residue_length = 0;
+    return;
+  }
+
+  /* Convolve the residue with zeros to get the actual remaining data */
+  in = g_new0 (guint8, outsize);
+  self->process (self, in, GST_BUFFER_DATA (outbuf), outsamples * channels);
+  g_free (in);
+
+  /* Set timestamp, offset, etc from the values we
+   * saved when processing the regular buffers */
+  if (GST_CLOCK_TIME_IS_VALID (self->next_ts))
+    GST_BUFFER_TIMESTAMP (outbuf) = self->next_ts;
+  else
+    GST_BUFFER_TIMESTAMP (outbuf) = 0;
+  GST_BUFFER_DURATION (outbuf) =
+      gst_util_uint64_scale (outsamples, GST_SECOND, rate);
+  self->next_ts += gst_util_uint64_scale (outsamples, GST_SECOND, rate);
+
+  if (self->next_off != GST_BUFFER_OFFSET_NONE) {
+    GST_BUFFER_OFFSET (outbuf) = self->next_off;
+    GST_BUFFER_OFFSET_END (outbuf) = self->next_off + outsamples;
+    self->next_off = GST_BUFFER_OFFSET_END (outbuf);
+  }
+
+  GST_DEBUG_OBJECT (self, "Pushing residue buffer of size %d with timestamp: %"
+      GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %lld,"
+      " offset_end: %lld, nsamples: %d", GST_BUFFER_SIZE (outbuf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
+      GST_BUFFER_OFFSET_END (outbuf), outsamples);
+
+  res = gst_pad_push (GST_BASE_TRANSFORM (self)->srcpad, outbuf);
+
+  if (G_UNLIKELY (res != GST_FLOW_OK)) {
+    GST_WARNING_OBJECT (self, "failed to push residue");
+  }
+
+  self->residue_length = 0;
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_fx_base_fir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format)
+{
+  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);
+  gboolean ret = TRUE;
+
+  if (self->residue) {
+    gst_audio_fx_base_fir_filter_push_residue (self);
+    g_free (self->residue);
+    self->residue = NULL;
+    self->residue_length = 0;
+    self->next_ts = GST_CLOCK_TIME_NONE;
+    self->next_off = GST_BUFFER_OFFSET_NONE;
+  }
+
+  if (format->width == 32)
+    self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_32;
+  else if (format->width == 64)
+    self->process = (GstAudioFXBaseFIRFilterProcessFunc) process_64;
+  else
+    ret = FALSE;
+
+  return TRUE;
+}
+
+/* GstBaseTransform vmethod implementations */
+
+static GstFlowReturn
+gst_audio_fx_base_fir_filter_transform (GstBaseTransform * base,
+    GstBuffer * inbuf, GstBuffer * outbuf)
+{
+  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);
+  GstClockTime timestamp;
+  gint channels = GST_AUDIO_FILTER (self)->format.channels;
+  gint rate = GST_AUDIO_FILTER (self)->format.rate;
+  gint input_samples =
+      GST_BUFFER_SIZE (outbuf) / (GST_AUDIO_FILTER (self)->format.width / 8);
+  gint output_samples = input_samples;
+  gint diff = 0;
+
+  timestamp = GST_BUFFER_TIMESTAMP (outbuf);
+  if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    GST_ERROR_OBJECT (self, "Invalid timestamp");
+    return GST_FLOW_ERROR;
+  }
+
+  gst_object_sync_values (G_OBJECT (self), timestamp);
+
+  g_return_val_if_fail (self->kernel != NULL, GST_FLOW_ERROR);
+  g_return_val_if_fail (channels != 0, GST_FLOW_ERROR);
+
+  if (!self->residue)
+    self->residue = g_new0 (gdouble, self->kernel_length * channels);
+
+  /* Reset the residue if already existing on discont buffers */
+  if (GST_BUFFER_IS_DISCONT (inbuf) || (GST_CLOCK_TIME_IS_VALID (self->next_ts)
+          && timestamp - gst_util_uint64_scale (MIN (self->latency,
+                  self->residue_length / channels), GST_SECOND,
+              rate) - self->next_ts > 5 * GST_MSECOND)) {
+    GST_DEBUG_OBJECT (self, "Discontinuity detected - flushing");
+    if (GST_CLOCK_TIME_IS_VALID (self->next_ts))
+      gst_audio_fx_base_fir_filter_push_residue (self);
+    self->residue_length = 0;
+    self->next_ts = timestamp;
+    self->next_off = GST_BUFFER_OFFSET (inbuf);
+  } else if (!GST_CLOCK_TIME_IS_VALID (self->next_ts)) {
+    self->next_ts = timestamp;
+    self->next_off = GST_BUFFER_OFFSET (inbuf);
+  }
+
+  /* Calculate the number of samples we can push out now without outputting
+   * latency zeros in the beginning */
+  diff = self->latency * channels - self->residue_length;
+  if (diff > 0)
+    output_samples -= diff;
+
+  self->process (self, GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (outbuf),
+      input_samples);
+
+  if (output_samples <= 0) {
+    return GST_BASE_TRANSFORM_FLOW_DROPPED;
+  }
+
+  GST_BUFFER_TIMESTAMP (outbuf) = self->next_ts;
+  GST_BUFFER_DURATION (outbuf) =
+      gst_util_uint64_scale (output_samples / channels, GST_SECOND, rate);
+  GST_BUFFER_OFFSET (outbuf) = self->next_off;
+  if (GST_BUFFER_OFFSET_IS_VALID (outbuf))
+    GST_BUFFER_OFFSET_END (outbuf) = self->next_off + output_samples / channels;
+  else
+    GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
+
+  if (output_samples < input_samples) {
+    GST_BUFFER_DATA (outbuf) +=
+        diff * (GST_AUDIO_FILTER (self)->format.width / 8);
+    GST_BUFFER_SIZE (outbuf) -=
+        diff * (GST_AUDIO_FILTER (self)->format.width / 8);
+  }
+
+  self->next_ts += GST_BUFFER_DURATION (outbuf);
+  self->next_off = GST_BUFFER_OFFSET_END (outbuf);
+
+  GST_DEBUG_OBJECT (self, "Pushing buffer of size %d with timestamp: %"
+      GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %lld,"
+      " offset_end: %lld, nsamples: %d", GST_BUFFER_SIZE (outbuf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
+      GST_BUFFER_OFFSET_END (outbuf), output_samples / channels);
+
+  return GST_FLOW_OK;
+}
+
+static gboolean
+gst_audio_fx_base_fir_filter_start (GstBaseTransform * base)
+{
+  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);
+
+  self->residue_length = 0;
+  self->next_ts = GST_CLOCK_TIME_NONE;
+  self->next_off = GST_BUFFER_OFFSET_NONE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_audio_fx_base_fir_filter_stop (GstBaseTransform * base)
+{
+  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);
+
+  g_free (self->residue);
+  self->residue = NULL;
+
+  return TRUE;
+}
+
+static gboolean
+gst_audio_fx_base_fir_filter_query (GstPad * pad, GstQuery * query)
+{
+  GstAudioFXBaseFIRFilter *self =
+      GST_AUDIO_FX_BASE_FIR_FILTER (gst_pad_get_parent (pad));
+  gboolean res = TRUE;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_LATENCY:
+    {
+      GstClockTime min, max;
+      gboolean live;
+      guint64 latency;
+      GstPad *peer;
+      gint rate = GST_AUDIO_FILTER (self)->format.rate;
+
+      if (rate == 0) {
+        res = FALSE;
+      } else if ((peer = gst_pad_get_peer (GST_BASE_TRANSFORM (self)->sinkpad))) {
+        if ((res = gst_pad_query (peer, query))) {
+          gst_query_parse_latency (query, &live, &min, &max);
+
+          GST_DEBUG_OBJECT (self, "Peer latency: min %"
+              GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
+              GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+
+          /* add our own latency */
+          latency = gst_util_uint64_scale (self->latency, GST_SECOND, rate);
+
+          GST_DEBUG_OBJECT (self, "Our latency: %"
+              GST_TIME_FORMAT, GST_TIME_ARGS (latency));
+
+          min += latency;
+          if (max != GST_CLOCK_TIME_NONE)
+            max += latency;
+
+          GST_DEBUG_OBJECT (self, "Calculated total latency : min %"
+              GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
+              GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+
+          gst_query_set_latency (query, live, min, max);
+        }
+        gst_object_unref (peer);
+      }
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, query);
+      break;
+  }
+  gst_object_unref (self);
+  return res;
+}
+
+static const GstQueryType *
+gst_audio_fx_base_fir_filter_query_type (GstPad * pad)
+{
+  static const GstQueryType types[] = {
+    GST_QUERY_LATENCY,
+    0
+  };
+
+  return types;
+}
+
+static gboolean
+gst_audio_fx_base_fir_filter_event (GstBaseTransform * base, GstEvent * event)
+{
+  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:
+      gst_audio_fx_base_fir_filter_push_residue (self);
+      self->next_ts = GST_CLOCK_TIME_NONE;
+      self->next_off = GST_BUFFER_OFFSET_NONE;
+      break;
+    default:
+      break;
+  }
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->event (base, event);
+}
+
+void
+gst_audio_fx_base_fir_filter_set_kernel (GstAudioFXBaseFIRFilter * self,
+    gdouble * kernel, guint kernel_length, guint64 latency)
+{
+  g_return_if_fail (kernel != NULL);
+  g_return_if_fail (self != NULL);
+
+  GST_BASE_TRANSFORM_LOCK (self);
+  if (self->residue) {
+    gst_audio_fx_base_fir_filter_push_residue (self);
+    self->next_ts = GST_CLOCK_TIME_NONE;
+    self->next_off = GST_BUFFER_OFFSET_NONE;
+    self->residue_length = 0;
+  }
+
+  g_free (self->kernel);
+  g_free (self->residue);
+
+  self->kernel = kernel;
+  self->kernel_length = kernel_length;
+
+  if (GST_AUDIO_FILTER (self)->format.channels) {
+    self->residue =
+        g_new0 (gdouble,
+        kernel_length * GST_AUDIO_FILTER (self)->format.channels);
+    self->residue_length = 0;
+  }
+
+  if (self->latency != latency) {
+    self->latency = latency;
+    gst_element_post_message (GST_ELEMENT (self),
+        gst_message_new_latency (GST_OBJECT (self)));
+  }
+
+  GST_BASE_TRANSFORM_UNLOCK (self);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofxbasefirfilter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,86 @@
+/* -*- c-basic-offset: 2 -*-
+ * 
+ * GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2006 Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>
+ *               2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_FX_BASE_FIR_FILTER_H__
+#define __GST_AUDIO_FX_BASE_FIR_FILTER_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_FX_BASE_FIR_FILTER \
+  (gst_audio_fx_base_fir_filter_get_type())
+#define GST_AUDIO_FX_BASE_FIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FX_BASE_FIR_FILTER,GstAudioFXBaseFIRFilter))
+#define GST_AUDIO_FX_BASE_FIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_FX_BASE_FIR_FILTER,GstAudioFXBaseFIRFilterClass))
+#define GST_IS_AUDIO_FX_BASE_FIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FX_BASE_FIR_FILTER))
+#define GST_IS_AUDIO_FX_BASE_FIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_FX_BASE_FIR_FILTER))
+
+typedef struct _GstAudioFXBaseFIRFilter GstAudioFXBaseFIRFilter;
+typedef struct _GstAudioFXBaseFIRFilterClass GstAudioFXBaseFIRFilterClass;
+
+typedef void (*GstAudioFXBaseFIRFilterProcessFunc) (GstAudioFXBaseFIRFilter *, guint8 *, guint8 *, guint);
+
+/**
+ * GstAudioFXBaseFIRFilter:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioFXBaseFIRFilter {
+  GstAudioFilter element;
+
+  /* < private > */
+  GstAudioFXBaseFIRFilterProcessFunc process;
+
+  gdouble *kernel;              /* filter kernel */
+  guint kernel_length;           /* length of the filter kernel */
+  gdouble *residue;             /* buffer for left-over samples from previous buffer */
+  guint residue_length;
+
+  guint64 latency;
+
+  GstClockTime next_ts;
+  guint64 next_off;
+};
+
+struct _GstAudioFXBaseFIRFilterClass {
+  GstAudioFilterClass parent_class;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_fx_base_fir_filter_get_type (void);
+void gst_audio_fx_base_fir_filter_set_kernel (GstAudioFXBaseFIRFilter *filter, gdouble *kernel, guint kernel_length, guint64 latency);
+void gst_audio_fx_base_fir_filter_push_residue (GstAudioFXBaseFIRFilter *filter);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_FX_BASE_FIR_FILTER_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofxbaseiirfilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,396 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include <math.h>
+
+#include "audiofxbaseiirfilter.h"
+
+#define GST_CAT_DEFAULT gst_audio_fx_base_iir_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define ALLOWED_CAPS \
+    "audio/x-raw-float,"                                              \
+    " width = (int) { 32, 64 }, "                                     \
+    " endianness = (int) BYTE_ORDER,"                                 \
+    " rate = (int) [ 1, MAX ],"                                       \
+    " channels = (int) [ 1, MAX ]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_fx_base_iir_filter_debug, "audiofxbaseiirfilter", 0, "Audio IIR Filter Base Class");
+
+GST_BOILERPLATE_FULL (GstAudioFXBaseIIRFilter,
+    gst_audio_fx_base_iir_filter, GstAudioFilter, GST_TYPE_AUDIO_FILTER,
+    DEBUG_INIT);
+
+static gboolean gst_audio_fx_base_iir_filter_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+static GstFlowReturn
+gst_audio_fx_base_iir_filter_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf);
+static gboolean gst_audio_fx_base_iir_filter_stop (GstBaseTransform * base);
+
+static void process_64 (GstAudioFXBaseIIRFilter * filter,
+    gdouble * data, guint num_samples);
+static void process_32 (GstAudioFXBaseIIRFilter * filter,
+    gfloat * data, guint num_samples);
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_fx_base_iir_filter_base_init (gpointer klass)
+{
+  GstCaps *caps;
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_fx_base_iir_filter_dispose (GObject * object)
+{
+  GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (object);
+
+  if (filter->a) {
+    g_free (filter->a);
+    filter->a = NULL;
+  }
+
+  if (filter->b) {
+    g_free (filter->b);
+    filter->b = NULL;
+  }
+
+  if (filter->channels) {
+    GstAudioFXBaseIIRFilterChannelCtx *ctx;
+    guint i;
+
+    for (i = 0; i < filter->nchannels; i++) {
+      ctx = &filter->channels[i];
+      g_free (ctx->x);
+      g_free (ctx->y);
+    }
+
+    g_free (filter->channels);
+    filter->channels = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_audio_fx_base_iir_filter_class_init (GstAudioFXBaseIIRFilterClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->dispose = gst_audio_fx_base_iir_filter_dispose;
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_setup);
+
+  trans_class->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_transform_ip);
+  trans_class->stop = GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_stop);
+}
+
+static void
+gst_audio_fx_base_iir_filter_init (GstAudioFXBaseIIRFilter * filter,
+    GstAudioFXBaseIIRFilterClass * klass)
+{
+  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
+
+  filter->a = NULL;
+  filter->na = 0;
+  filter->b = NULL;
+  filter->nb = 0;
+  filter->channels = NULL;
+  filter->nchannels = 0;
+}
+
+/* Evaluate the transfer function that corresponds to the IIR
+ * coefficients at zr + zi*I and return the magnitude */
+gdouble
+gst_audio_fx_base_iir_filter_calculate_gain (gdouble * a, guint na, gdouble * b,
+    guint nb, gdouble zr, gdouble zi)
+{
+  gdouble sum_ar, sum_ai;
+  gdouble sum_br, sum_bi;
+  gdouble gain_r, gain_i;
+
+  gdouble sum_r_old;
+  gdouble sum_i_old;
+
+  gint i;
+
+  sum_ar = 0.0;
+  sum_ai = 0.0;
+  for (i = na - 1; i >= 0; i--) {
+    sum_r_old = sum_ar;
+    sum_i_old = sum_ai;
+
+    sum_ar = (sum_r_old * zr - sum_i_old * zi) + a[i];
+    sum_ai = (sum_r_old * zi + sum_i_old * zr) + 0.0;
+  }
+
+  sum_br = 0.0;
+  sum_bi = 0.0;
+  for (i = nb - 1; i >= 0; i--) {
+    sum_r_old = sum_br;
+    sum_i_old = sum_bi;
+
+    sum_br = (sum_r_old * zr - sum_i_old * zi) - b[i];
+    sum_bi = (sum_r_old * zi + sum_i_old * zr) - 0.0;
+  }
+  sum_br += 1.0;
+  sum_bi += 0.0;
+
+  gain_r =
+      (sum_ar * sum_br + sum_ai * sum_bi) / (sum_br * sum_br + sum_bi * sum_bi);
+  gain_i =
+      (sum_ai * sum_br - sum_ar * sum_bi) / (sum_br * sum_br + sum_bi * sum_bi);
+
+  return (sqrt (gain_r * gain_r + gain_i * gain_i));
+}
+
+void
+gst_audio_fx_base_iir_filter_set_coefficients (GstAudioFXBaseIIRFilter * filter,
+    gdouble * a, guint na, gdouble * b, guint nb)
+{
+  guint i;
+
+  g_return_if_fail (GST_IS_AUDIO_FX_BASE_IIR_FILTER (filter));
+
+  GST_BASE_TRANSFORM_LOCK (filter);
+
+  g_free (filter->a);
+  g_free (filter->b);
+
+  filter->a = filter->b = NULL;
+
+  if (filter->channels) {
+    GstAudioFXBaseIIRFilterChannelCtx *ctx;
+    gboolean free = (na != filter->na || nb != filter->nb);
+
+    for (i = 0; i < filter->nchannels; i++) {
+      ctx = &filter->channels[i];
+
+      if (free)
+        g_free (ctx->x);
+      else
+        memset (ctx->x, 0, filter->na * sizeof (gdouble));
+
+      if (free)
+        g_free (ctx->y);
+      else
+        memset (ctx->y, 0, filter->nb * sizeof (gdouble));
+    }
+
+    g_free (filter->channels);
+    filter->channels = NULL;
+  }
+
+  filter->na = na;
+  filter->nb = nb;
+
+  filter->a = a;
+  filter->b = b;
+
+  if (filter->nchannels && !filter->channels) {
+    GstAudioFXBaseIIRFilterChannelCtx *ctx;
+
+    filter->channels =
+        g_new0 (GstAudioFXBaseIIRFilterChannelCtx, filter->nchannels);
+    for (i = 0; i < filter->nchannels; i++) {
+      ctx = &filter->channels[i];
+
+      ctx->x = g_new0 (gdouble, filter->na);
+      ctx->y = g_new0 (gdouble, filter->nb);
+    }
+  }
+
+  GST_BASE_TRANSFORM_UNLOCK (filter);
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_fx_base_iir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format)
+{
+  GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
+  gboolean ret = TRUE;
+
+  if (format->width == 32)
+    filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
+        process_32;
+  else if (format->width == 64)
+    filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
+        process_64;
+  else
+    ret = FALSE;
+
+  if (format->channels != filter->nchannels) {
+    guint i;
+    GstAudioFXBaseIIRFilterChannelCtx *ctx;
+
+    if (filter->channels) {
+
+      for (i = 0; i < filter->nchannels; i++) {
+        ctx = &filter->channels[i];
+
+        g_free (ctx->x);
+        g_free (ctx->y);
+      }
+
+      g_free (filter->channels);
+      filter->channels = NULL;
+    }
+
+    filter->nchannels = format->channels;
+
+    filter->channels =
+        g_new0 (GstAudioFXBaseIIRFilterChannelCtx, filter->nchannels);
+    for (i = 0; i < filter->nchannels; i++) {
+      ctx = &filter->channels[i];
+
+      ctx->x = g_new0 (gdouble, filter->na);
+      ctx->y = g_new0 (gdouble, filter->nb);
+    }
+  }
+
+  return ret;
+}
+
+static inline gdouble
+process (GstAudioFXBaseIIRFilter * filter,
+    GstAudioFXBaseIIRFilterChannelCtx * ctx, gdouble x0)
+{
+  gdouble val = filter->a[0] * x0;
+  gint i, j;
+
+  for (i = 1, j = ctx->x_pos; i < filter->na; i++) {
+    val += filter->a[i] * ctx->x[j];
+    j--;
+    if (j < 0)
+      j = filter->na - 1;
+  }
+
+  for (i = 1, j = ctx->y_pos; i < filter->nb; i++) {
+    val += filter->b[i] * ctx->y[j];
+    j--;
+    if (j < 0)
+      j = filter->nb - 1;
+  }
+
+  if (ctx->x) {
+    ctx->x_pos++;
+    if (ctx->x_pos >= filter->na)
+      ctx->x_pos = 0;
+    ctx->x[ctx->x_pos] = x0;
+  }
+  if (ctx->y) {
+    ctx->y_pos++;
+    if (ctx->y_pos >= filter->nb)
+      ctx->y_pos = 0;
+
+    ctx->y[ctx->y_pos] = val;
+  }
+
+  return val;
+}
+
+#define DEFINE_PROCESS_FUNC(width,ctype) \
+static void \
+process_##width (GstAudioFXBaseIIRFilter * filter, \
+    g##ctype * data, guint num_samples) \
+{ \
+  gint i, j, channels = GST_AUDIO_FILTER (filter)->format.channels; \
+  gdouble val; \
+  \
+  for (i = 0; i < num_samples / channels; i++) { \
+    for (j = 0; j < channels; j++) { \
+      val = process (filter, &filter->channels[j], *data); \
+      *data++ = val; \
+    } \
+  } \
+}
+
+DEFINE_PROCESS_FUNC (32, float);
+DEFINE_PROCESS_FUNC (64, double);
+
+#undef DEFINE_PROCESS_FUNC
+
+/* GstBaseTransform vmethod implementations */
+static GstFlowReturn
+gst_audio_fx_base_iir_filter_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf)
+{
+  GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
+  guint num_samples =
+      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
+    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
+
+  if (gst_base_transform_is_passthrough (base))
+    return GST_FLOW_OK;
+
+  g_return_val_if_fail (filter->a != NULL, GST_FLOW_ERROR);
+
+  filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
+
+  return GST_FLOW_OK;
+}
+
+
+static gboolean
+gst_audio_fx_base_iir_filter_stop (GstBaseTransform * base)
+{
+  GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
+  guint channels = GST_AUDIO_FILTER (filter)->format.channels;
+  GstAudioFXBaseIIRFilterChannelCtx *ctx;
+  guint i;
+
+  /* Reset the history of input and output values if
+   * already existing */
+  if (channels && filter->channels) {
+    for (i = 0; i < channels; i++) {
+      ctx = &filter->channels[i];
+      g_free (ctx->x);
+      g_free (ctx->y);
+    }
+    g_free (filter->channels);
+  }
+  filter->channels = NULL;
+
+  return TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiofxbaseiirfilter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,82 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_FX_BASE_IIR_FILTER_H__
+#define __GST_AUDIO_FX_BASE_IIR_FILTER_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_FX_BASE_IIR_FILTER            (gst_audio_fx_base_iir_filter_get_type())
+#define GST_AUDIO_FX_BASE_IIR_FILTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FX_BASE_IIR_FILTER,GstAudioFXBaseIIRFilter))
+#define GST_IS_AUDIO_FX_BASE_IIR_FILTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FX_BASE_IIR_FILTER))
+#define GST_AUDIO_FX_BASE_IIR_FILTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_FX_BASE_IIR_FILTER,GstAudioFXBaseIIRFilterClass))
+#define GST_IS_AUDIO_FX_BASE_IIR_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_FX_BASE_IIR_FILTER))
+#define GST_AUDIO_FX_BASE_IIR_FILTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_FX_BASE_IIR_FILTER,GstAudioFXBaseIIRFilterClass))
+typedef struct _GstAudioFXBaseIIRFilter GstAudioFXBaseIIRFilter;
+typedef struct _GstAudioFXBaseIIRFilterClass GstAudioFXBaseIIRFilterClass;
+
+typedef void (*GstAudioFXBaseIIRFilterProcessFunc) (GstAudioFXBaseIIRFilter *, guint8 *, guint);
+
+typedef struct
+{
+  gdouble *x;
+  gint x_pos;
+  gdouble *y;
+  gint y_pos;
+} GstAudioFXBaseIIRFilterChannelCtx;
+
+struct _GstAudioFXBaseIIRFilter
+{
+  GstAudioFilter audiofilter;
+
+  /* < private > */
+  GstAudioFXBaseIIRFilterProcessFunc process;
+
+  gboolean have_coeffs;
+  gdouble *a;
+  guint na;
+  gdouble *b;
+  guint nb;
+  GstAudioFXBaseIIRFilterChannelCtx *channels;
+  guint nchannels;
+};
+
+struct _GstAudioFXBaseIIRFilterClass
+{
+  GstAudioFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_fx_base_iir_filter_get_type (void);
+void gst_audio_fx_base_iir_filter_set_coefficients (GstAudioFXBaseIIRFilter *filter, gdouble *a, guint na, gdouble *b, guint nb);
+gdouble gst_audio_fx_base_iir_filter_calculate_gain (gdouble *a, guint na, gdouble *b, guint nb, gdouble zr, gdouble zi);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_FX_BASE_IIR_FILTER_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioiirfilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,287 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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.
+ * 
+ */
+
+/**
+ * SECTION:element-audioiirfilter
+ *
+ * audioiirfilter implements a generic audio <ulink url="http://en.wikipedia.org/wiki/Infinite_impulse_response">IIR filter</ulink>. Before usage the
+ * "a" and "b" properties have to be set to the filter coefficients that
+ * should be used.
+ *
+ * The filter coefficients describe the numerator and denominator of the
+ * transfer function.
+ *
+ * To change the filter coefficients whenever the sampling rate changes the
+ * "rate-changed" signal can be used. This should be done for most
+ * IIR filters as they're depending on the sampling rate.
+ *
+ * <refsect2>
+ * <title>Example application</title>
+ * |[
+ * <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" parse="text" href="../../../../tests/examples/audiofx/iirfilter-example.c" />
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audioiirfilter.h"
+
+#define GST_CAT_DEFAULT gst_audio_iir_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  SIGNAL_RATE_CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_A,
+  PROP_B
+};
+
+static guint gst_audio_iir_filter_signals[LAST_SIGNAL] = { 0, };
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_iir_filter_debug, "audioiirfilter", 0, \
+      "Generic audio IIR filter plugin");
+
+GST_BOILERPLATE_FULL (GstAudioIIRFilter, gst_audio_iir_filter, GstAudioFilter,
+    GST_TYPE_AUDIO_FX_BASE_IIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_iir_filter_finalize (GObject * object);
+
+static gboolean gst_audio_iir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+/* Element class */
+static void
+gst_audio_iir_filter_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Audio IIR filter", "Filter/Effect/Audio",
+      "Generic audio IIR filter with custom filter kernel",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_iir_filter_class_init (GstAudioIIRFilterClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_iir_filter_set_property;
+  gobject_class->get_property = gst_audio_iir_filter_get_property;
+  gobject_class->finalize = gst_audio_iir_filter_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_A,
+      g_param_spec_value_array ("a", "A",
+          "Filter coefficients (numerator of transfer function)",
+          g_param_spec_double ("Coefficient", "Filter Coefficient",
+              "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_B,
+      g_param_spec_value_array ("b", "B",
+          "Filter coefficients (denominator of transfer function)",
+          g_param_spec_double ("Coefficient", "Filter Coefficient",
+              "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_iir_filter_setup);
+
+  /**
+   * GstAudioIIRFilter::rate-changed:
+   * @filter: the filter on which the signal is emitted
+   * @rate: the new sampling rate
+   *
+   * Will be emitted when the sampling rate changes. The callbacks
+   * will be called from the streaming thread and processing will
+   * stop until the event is handled.
+   */
+  gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED] =
+      g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioIIRFilterClass, rate_changed),
+      NULL, NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+static void
+gst_audio_iir_filter_update_coefficients (GstAudioIIRFilter * self,
+    GValueArray * va, GValueArray * vb)
+{
+  gdouble *a = NULL, *b = NULL;
+  guint i;
+
+  if (va) {
+    if (self->a)
+      g_value_array_free (self->a);
+
+    self->a = va;
+  }
+  if (vb) {
+    if (self->b)
+      g_value_array_free (self->b);
+
+    self->b = vb;
+  }
+
+  if (self->a && self->a->n_values > 0)
+    a = g_new (gdouble, self->a->n_values);
+  if (self->b && self->b->n_values > 0)
+    b = g_new (gdouble, self->b->n_values);
+
+  if (self->a) {
+    for (i = 0; i < self->a->n_values; i++) {
+      GValue *v = g_value_array_get_nth (self->a, i);
+      a[i] = g_value_get_double (v);
+    }
+  }
+
+  if (self->b) {
+    for (i = 0; i < self->b->n_values; i++) {
+      GValue *v = g_value_array_get_nth (self->b, i);
+      b[i] = g_value_get_double (v);
+    }
+  }
+
+  gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+      (self), a, (self->a) ? self->a->n_values : 0, b,
+      (self->b) ? self->b->n_values : 0);
+}
+
+static void
+gst_audio_iir_filter_init (GstAudioIIRFilter * self,
+    GstAudioIIRFilterClass * g_class)
+{
+  GValue v = { 0, };
+  GValueArray *a, *b;
+
+  a = g_value_array_new (1);
+
+  g_value_init (&v, G_TYPE_DOUBLE);
+  g_value_set_double (&v, 1.0);
+  g_value_array_append (a, &v);
+  g_value_unset (&v);
+
+  b = NULL;
+  gst_audio_iir_filter_update_coefficients (self, a, b);
+
+  self->lock = g_mutex_new ();
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_iir_filter_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (base);
+
+  if (self->rate != format->rate) {
+    g_signal_emit (G_OBJECT (self),
+        gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED], 0, format->rate);
+    self->rate = format->rate;
+  }
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
+
+static void
+gst_audio_iir_filter_finalize (GObject * object)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
+
+  g_mutex_free (self->lock);
+  self->lock = NULL;
+
+  if (self->a)
+    g_value_array_free (self->a);
+  self->a = NULL;
+  if (self->b)
+    g_value_array_free (self->b);
+  self->b = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
+
+  g_return_if_fail (GST_IS_AUDIO_IIR_FILTER (self));
+
+  switch (prop_id) {
+    case PROP_A:
+      g_mutex_lock (self->lock);
+      gst_audio_iir_filter_update_coefficients (self, g_value_dup_boxed (value),
+          NULL);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_B:
+      g_mutex_lock (self->lock);
+      gst_audio_iir_filter_update_coefficients (self, NULL,
+          g_value_dup_boxed (value));
+      g_mutex_unlock (self->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
+
+  switch (prop_id) {
+    case PROP_A:
+      g_value_set_boxed (value, self->a);
+      break;
+    case PROP_B:
+      g_value_set_boxed (value, self->b);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioiirfilter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,76 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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_AUDIO_IIR_FILTER_H__
+#define __GST_AUDIO_IIR_FILTER_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/audio/gstaudiofilter.h>
+
+#include "audiofxbaseiirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_IIR_FILTER \
+  (gst_audio_iir_filter_get_type())
+#define GST_AUDIO_IIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_IIR_FILTER,GstAudioIIRFilter))
+#define GST_AUDIO_IIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_IIR_FILTER,GstAudioIIRFilterClass))
+#define GST_IS_AUDIO_IIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_IIR_FILTER))
+#define GST_IS_AUDIO_IIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_IIR_FILTER))
+
+typedef struct _GstAudioIIRFilter GstAudioIIRFilter;
+typedef struct _GstAudioIIRFilterClass GstAudioIIRFilterClass;
+
+/**
+ * GstAudioIIRFilter:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioIIRFilter {
+  GstAudioFXBaseIIRFilter parent;
+
+  GValueArray *a, *b;
+
+  /* < private > */
+  GMutex *lock;
+  gint rate;
+};
+
+struct _GstAudioIIRFilterClass {
+  GstAudioFXBaseIIRFilterClass parent;
+
+  void (*rate_changed) (GstElement * element, gint rate);
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_iir_filter_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_IIR_FILTER_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioinvert.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,252 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-audioinvert
+ *
+ * Swaps upper and lower half of audio samples. Mixing an inverted sample on top of
+ * the original with a slight delay can produce effects that sound like resonance.
+ * Creating a stereo sample from a mono source, with one channel inverted produces wide-stereo sounds.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc wave=saw ! audioinvert invert=0.4 ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioinvert invert=0.4 ! alsasink
+ * gst-launch audiotestsrc wave=saw ! audioconvert ! audioinvert invert=0.4 ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audioinvert.h"
+
+#define GST_CAT_DEFAULT gst_audio_invert_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("Audio inversion",
+    "Filter/Effect/Audio",
+    "Swaps upper and lower half of audio samples",
+    "Sebastian Dröge <slomo@circular-chaos.org>");
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_DEGREE
+};
+
+#define ALLOWED_CAPS \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)16,"                                                 \
+    " width=(int)16,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-float,"                                              \
+    " width=(int)32,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_invert_debug, "audioinvert", 0, "audioinvert element");
+
+GST_BOILERPLATE_FULL (GstAudioInvert, gst_audio_invert, GstAudioFilter,
+    GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+
+static void gst_audio_invert_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_invert_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_audio_invert_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+static GstFlowReturn gst_audio_invert_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf);
+
+static void gst_audio_invert_transform_int (GstAudioInvert * filter,
+    gint16 * data, guint num_samples);
+static void gst_audio_invert_transform_float (GstAudioInvert * filter,
+    gfloat * data, guint num_samples);
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_invert_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *caps;
+
+  gst_element_class_set_details (element_class, &element_details);
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_invert_class_init (GstAudioInvertClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_audio_invert_set_property;
+  gobject_class->get_property = gst_audio_invert_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_DEGREE,
+      g_param_spec_float ("degree", "Degree",
+          "Degree of inversion", 0.0, 1.0,
+          0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  GST_AUDIO_FILTER_CLASS (klass)->setup =
+      GST_DEBUG_FUNCPTR (gst_audio_invert_setup);
+  GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_audio_invert_transform_ip);
+}
+
+static void
+gst_audio_invert_init (GstAudioInvert * filter, GstAudioInvertClass * klass)
+{
+  filter->degree = 0.0;
+  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
+  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
+}
+
+static void
+gst_audio_invert_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioInvert *filter = GST_AUDIO_INVERT (object);
+
+  switch (prop_id) {
+    case PROP_DEGREE:
+      filter->degree = g_value_get_float (value);
+      gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
+          filter->degree == 0.0);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_invert_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioInvert *filter = GST_AUDIO_INVERT (object);
+
+  switch (prop_id) {
+    case PROP_DEGREE:
+      g_value_set_float (value, filter->degree);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_invert_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioInvert *filter = GST_AUDIO_INVERT (base);
+  gboolean ret = TRUE;
+
+  if (format->type == GST_BUFTYPE_FLOAT && format->width == 32)
+    filter->process = (GstAudioInvertProcessFunc)
+        gst_audio_invert_transform_float;
+  else if (format->type == GST_BUFTYPE_LINEAR && format->width == 16)
+    filter->process = (GstAudioInvertProcessFunc)
+        gst_audio_invert_transform_int;
+  else
+    ret = FALSE;
+
+  return ret;
+}
+
+static void
+gst_audio_invert_transform_int (GstAudioInvert * filter,
+    gint16 * data, guint num_samples)
+{
+  gint i;
+  gfloat dry = 1.0 - filter->degree;
+  glong val;
+
+  for (i = 0; i < num_samples; i++) {
+    val = (*data) * dry + (-1 - (*data)) * filter->degree;
+    *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_invert_transform_float (GstAudioInvert * filter,
+    gfloat * data, guint num_samples)
+{
+  gint i;
+  gfloat dry = 1.0 - filter->degree;
+  glong val;
+
+  for (i = 0; i < num_samples; i++) {
+    val = (*data) * dry - (*data) * filter->degree;
+    *data++ = val;
+  }
+}
+
+/* GstBaseTransform vmethod implementations */
+static GstFlowReturn
+gst_audio_invert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+  GstAudioInvert *filter = GST_AUDIO_INVERT (base);
+  guint num_samples =
+      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
+    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
+
+  if (gst_base_transform_is_passthrough (base) ||
+      G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
+    return GST_FLOW_OK;
+
+  filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
+
+  return GST_FLOW_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audioinvert.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,65 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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_AUDIO_INVERT_H__
+#define __GST_AUDIO_INVERT_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+#define GST_TYPE_AUDIO_INVERT            (gst_audio_invert_get_type())
+#define GST_AUDIO_INVERT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_INVERT,GstAudioInvert))
+#define GST_IS_AUDIO_INVERT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_INVERT))
+#define GST_AUDIO_INVERT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_INVERT,GstAudioInvertClass))
+#define GST_IS_AUDIO_INVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_INVERT))
+#define GST_AUDIO_INVERT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_INVERT,GstAudioInvertClass))
+typedef struct _GstAudioInvert GstAudioInvert;
+typedef struct _GstAudioInvertClass GstAudioInvertClass;
+
+typedef void (*GstAudioInvertProcessFunc) (GstAudioInvert *, guint8 *, guint);
+
+struct _GstAudioInvert
+{
+  GstAudioFilter audiofilter;
+
+  gfloat degree;
+
+  /* < private > */
+  GstAudioInvertProcessFunc process;
+};
+
+struct _GstAudioInvertClass
+{
+  GstAudioFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_invert_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_AUDIO_INVERT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiokaraoke.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,357 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2008 Wim Taymans <wim.taymans@gmail.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.
+ */
+
+/**
+ * SECTION:element-audiokaraoke
+ *
+ * Remove the voice from audio by filtering the center channel.
+ * This plugin is useful for karaoke applications.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=song.ogg ! oggdemux ! vorbisdec ! audiokaraoke ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiokaraoke.h"
+
+#define GST_CAT_DEFAULT gst_audio_karaoke_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("AudioKaraoke",
+    "Filter/Effect/Audio",
+    "Removes voice from sound",
+    "Wim Taymans <wim.taymans@gmail.com>");
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+#define DEFAULT_LEVEL		1.0
+#define DEFAULT_MONO_LEVEL	1.0
+#define DEFAULT_FILTER_BAND	220.0
+#define DEFAULT_FILTER_WIDTH	100.0
+
+enum
+{
+  PROP_0,
+  PROP_LEVEL,
+  PROP_MONO_LEVEL,
+  PROP_FILTER_BAND,
+  PROP_FILTER_WIDTH,
+  PROP_LAST
+};
+
+#define ALLOWED_CAPS \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)16,"                                                 \
+    " width=(int)16,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-float,"                                              \
+    " width=(int)32,"                                                 \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]"
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_karaoke_debug, "audiokaraoke", 0, "audiokaraoke element");
+
+GST_BOILERPLATE_FULL (GstAudioKaraoke, gst_audio_karaoke, GstAudioFilter,
+    GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+
+static void gst_audio_karaoke_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_karaoke_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_audio_karaoke_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * format);
+static GstFlowReturn gst_audio_karaoke_transform_ip (GstBaseTransform * base,
+    GstBuffer * buf);
+
+static void gst_audio_karaoke_transform_int (GstAudioKaraoke * filter,
+    gint16 * data, guint num_samples);
+static void gst_audio_karaoke_transform_float (GstAudioKaraoke * filter,
+    gfloat * data, guint num_samples);
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_karaoke_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *caps;
+
+  gst_element_class_set_details (element_class, &element_details);
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
+}
+
+static void
+gst_audio_karaoke_class_init (GstAudioKaraokeClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_audio_karaoke_set_property;
+  gobject_class->get_property = gst_audio_karaoke_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_LEVEL,
+      g_param_spec_float ("level", "Level",
+          "Level of the effect (1.0 = full)", 0.0, 1.0, DEFAULT_LEVEL,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_MONO_LEVEL,
+      g_param_spec_float ("mono-level", "Mono Level",
+          "Level of the mono channel (1.0 = full)", 0.0, 1.0, DEFAULT_LEVEL,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_FILTER_BAND,
+      g_param_spec_float ("filter-band", "Filter Band",
+          "The Frequency band of the filter", 0.0, 441.0, DEFAULT_FILTER_BAND,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_FILTER_WIDTH,
+      g_param_spec_float ("filter-width", "Filter Width",
+          "The Frequency width of the filter", 0.0, 100.0, DEFAULT_FILTER_WIDTH,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  GST_AUDIO_FILTER_CLASS (klass)->setup =
+      GST_DEBUG_FUNCPTR (gst_audio_karaoke_setup);
+  GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_audio_karaoke_transform_ip);
+}
+
+static void
+gst_audio_karaoke_init (GstAudioKaraoke * filter, GstAudioKaraokeClass * klass)
+{
+  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
+  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
+
+  filter->level = DEFAULT_LEVEL;
+  filter->mono_level = DEFAULT_MONO_LEVEL;
+  filter->filter_band = DEFAULT_FILTER_BAND;
+  filter->filter_width = DEFAULT_FILTER_WIDTH;
+}
+
+static void
+update_filter (GstAudioKaraoke * filter, gint rate)
+{
+  gfloat A, B, C;
+
+  if (rate == 0)
+    return;
+
+  C = exp (-2 * M_PI * filter->filter_width / rate);
+  B = -4 * C / (1 + C) * cos (2 * M_PI * filter->filter_band / rate);
+  A = sqrt (1 - B * B / (4 * C)) * (1 - C);
+
+  filter->A = A;
+  filter->B = B;
+  filter->C = C;
+  filter->y1 = 0.0;
+  filter->y2 = 0.0;
+}
+
+static void
+gst_audio_karaoke_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioKaraoke *filter;
+
+  filter = GST_AUDIO_KARAOKE (object);
+
+  switch (prop_id) {
+    case PROP_LEVEL:
+      filter->level = g_value_get_float (value);
+      break;
+    case PROP_MONO_LEVEL:
+      filter->mono_level = g_value_get_float (value);
+      break;
+    case PROP_FILTER_BAND:
+      filter->filter_band = g_value_get_float (value);
+      update_filter (filter, filter->rate);
+      break;
+    case PROP_FILTER_WIDTH:
+      filter->filter_width = g_value_get_float (value);
+      update_filter (filter, filter->rate);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_karaoke_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioKaraoke *filter;
+
+  filter = GST_AUDIO_KARAOKE (object);
+
+  switch (prop_id) {
+    case PROP_LEVEL:
+      g_value_set_float (value, filter->level);
+      break;
+    case PROP_MONO_LEVEL:
+      g_value_set_float (value, filter->mono_level);
+      break;
+    case PROP_FILTER_BAND:
+      g_value_set_float (value, filter->filter_band);
+      break;
+    case PROP_FILTER_WIDTH:
+      g_value_set_float (value, filter->filter_width);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstAudioFilter vmethod implementations */
+
+static gboolean
+gst_audio_karaoke_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioKaraoke *filter = GST_AUDIO_KARAOKE (base);
+  gboolean ret = TRUE;
+
+  filter->channels = format->channels;
+  filter->rate = format->rate;
+
+  if (format->type == GST_BUFTYPE_FLOAT && format->width == 32)
+    filter->process = (GstAudioKaraokeProcessFunc)
+        gst_audio_karaoke_transform_float;
+  else if (format->type == GST_BUFTYPE_LINEAR && format->width == 16)
+    filter->process = (GstAudioKaraokeProcessFunc)
+        gst_audio_karaoke_transform_int;
+  else
+    ret = FALSE;
+
+  update_filter (filter, format->rate);
+
+  return ret;
+}
+
+static void
+gst_audio_karaoke_transform_int (GstAudioKaraoke * filter,
+    gint16 * data, guint num_samples)
+{
+  gint i, l, r, o, x;
+  gint channels;
+  gdouble y;
+  gint level;
+
+  channels = filter->channels;
+  level = filter->level * 256;
+
+  for (i = 0; i < num_samples; i += channels) {
+    /* get left and right inputs */
+    l = data[i];
+    r = data[i + 1];
+    /* do filtering */
+    x = (l + r) / 2;
+    y = (filter->A * x - filter->B * filter->y1) - filter->C * filter->y2;
+    filter->y2 = filter->y1;
+    filter->y1 = y;
+    /* filter mono signal */
+    o = (int) (y * filter->mono_level);
+    o = CLAMP (o, G_MININT16, G_MAXINT16);
+    o = (o * level) >> 8;
+    /* now cut the center */
+    x = l - ((r * level) >> 8) + o;
+    r = r - ((l * level) >> 8) + o;
+    data[i] = CLAMP (x, G_MININT16, G_MAXINT16);
+    data[i + 1] = CLAMP (r, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_karaoke_transform_float (GstAudioKaraoke * filter,
+    gfloat * data, guint num_samples)
+{
+  gint i;
+  gint channels;
+  gdouble l, r, o;
+  gdouble y;
+
+  channels = filter->channels;
+
+  for (i = 0; i < num_samples; i += channels) {
+    /* get left and right inputs */
+    l = data[i];
+    r = data[i + 1];
+    /* do filtering */
+    y = (filter->A * ((l + r) / 2.0) - filter->B * filter->y1) -
+        filter->C * filter->y2;
+    filter->y2 = filter->y1;
+    filter->y1 = y;
+    /* filter mono signal */
+    o = y * filter->mono_level * filter->level;
+    /* now cut the center */
+    data[i] = l - (r * filter->level) + o;
+    data[i + 1] = r - (l * filter->level) + o;
+  }
+}
+
+/* GstBaseTransform vmethod implementations */
+static GstFlowReturn
+gst_audio_karaoke_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+  GstAudioKaraoke *filter = GST_AUDIO_KARAOKE (base);
+  guint num_samples =
+      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
+    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
+
+  if (gst_base_transform_is_passthrough (base) ||
+      G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
+    return GST_FLOW_OK;
+
+  filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
+
+  return GST_FLOW_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiokaraoke.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,75 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2008 Wim Taymans <wim.taymans@gmail.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_AUDIO_KARAOKE_H__
+#define __GST_AUDIO_KARAOKE_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiofilter.h>
+
+G_BEGIN_DECLS
+#define GST_TYPE_AUDIO_KARAOKE            (gst_audio_karaoke_get_type())
+#define GST_AUDIO_KARAOKE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_KARAOKE,GstAudioKaraoke))
+#define GST_IS_AUDIO_KARAOKE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_KARAOKE))
+#define GST_AUDIO_KARAOKE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_KARAOKE,GstAudioKaraokeClass))
+#define GST_IS_AUDIO_KARAOKE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_KARAOKE))
+#define GST_AUDIO_KARAOKE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_KARAOKE,GstAudioKaraokeClass))
+typedef struct _GstAudioKaraoke GstAudioKaraoke;
+typedef struct _GstAudioKaraokeClass GstAudioKaraokeClass;
+
+typedef void (*GstAudioKaraokeProcessFunc) (GstAudioKaraoke *, guint8 *, guint);
+
+struct _GstAudioKaraoke
+{
+  GstAudioFilter audiofilter;
+
+  gint channels;
+  gint rate;
+
+  /* properties */
+  gfloat level;
+  gfloat mono_level;
+  gfloat filter_band;
+  gfloat filter_width;
+
+  /* filter coef */
+  gfloat A, B, C;
+  gfloat y1, y2;
+
+  /* < private > */
+  GstAudioKaraokeProcessFunc process;
+};
+
+struct _GstAudioKaraokeClass
+{
+  GstAudioFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_karaoke_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_AUDIO_KARAOKE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiopanorama.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,648 @@
+/*
+ * GStreamer
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ * Copyright (C) 2006 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-audiopanorama
+ *
+ * Stereo panorama effect with controllable pan position. One can choose between the default psychoacoustic panning method,
+ * which keeps the same perceived loudness, and a simple panning method that just controls the volume on one channel.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc wave=saw ! audiopanorama panorama=-1.00 ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiopanorama panorama=-1.00 ! alsasink
+ * gst-launch audiotestsrc wave=saw ! audioconvert ! audiopanorama panorama=-1.00 ! audioconvert ! alsasink
+ * gst-launch audiotestsrc wave=saw ! audioconvert ! audiopanorama method=simple panorama=-0.50 ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiopanorama.h"
+
+#define GST_CAT_DEFAULT gst_audio_panorama_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("Stereo positioning",
+    "Filter/Effect/Audio",
+    "Positions audio streams in the stereo panorama",
+    "Stefan Kost <ensonic@users.sf.net>");
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_PANORAMA,
+  PROP_METHOD
+};
+
+enum
+{
+  METHOD_PSYCHOACOUSTIC = 0,
+  METHOD_SIMPLE,
+  NUM_METHODS
+};
+
+#define GST_TYPE_AUDIO_PANORAMA_METHOD (gst_audio_panorama_method_get_type ())
+static GType
+gst_audio_panorama_method_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {METHOD_PSYCHOACOUSTIC, "Psychoacoustic Panning (default)",
+          "psychoacoustic"},
+      {METHOD_SIMPLE, "Simple Panning", "simple"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioPanoramaMethod", values);
+  }
+  return gtype;
+}
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-float, "
+        "rate = (int) [ 1, MAX ], "
+        "channels = (int) [ 1, 2 ], "
+        "endianness = (int) BYTE_ORDER, " "width = (int) 32; "
+        "audio/x-raw-int, "
+        "rate = (int) [ 1, MAX ], "
+        "channels = (int) [ 1, 2 ], "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
+    );
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-float, "
+        "rate = (int) [ 1, MAX ], "
+        "channels = (int) 2, "
+        "endianness = (int) BYTE_ORDER, " "width = (int) 32; "
+        "audio/x-raw-int, "
+        "rate = (int) [ 1, MAX ], "
+        "channels = (int) 2, "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
+    );
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_panorama_debug, "audiopanorama", 0, "audiopanorama element");
+
+GST_BOILERPLATE_FULL (GstAudioPanorama, gst_audio_panorama, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
+
+static void gst_audio_panorama_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_panorama_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_audio_panorama_get_unit_size (GstBaseTransform * base,
+    GstCaps * caps, guint * size);
+static GstCaps *gst_audio_panorama_transform_caps (GstBaseTransform * base,
+    GstPadDirection direction, GstCaps * caps);
+static gboolean gst_audio_panorama_set_caps (GstBaseTransform * base,
+    GstCaps * incaps, GstCaps * outcaps);
+
+static void gst_audio_panorama_transform_m2s_int (GstAudioPanorama * filter,
+    gint16 * idata, gint16 * odata, guint num_samples);
+static void gst_audio_panorama_transform_s2s_int (GstAudioPanorama * filter,
+    gint16 * idata, gint16 * odata, guint num_samples);
+static void gst_audio_panorama_transform_m2s_float (GstAudioPanorama * filter,
+    gfloat * idata, gfloat * odata, guint num_samples);
+static void gst_audio_panorama_transform_s2s_float (GstAudioPanorama * filter,
+    gfloat * idata, gfloat * odata, guint num_samples);
+
+static void gst_audio_panorama_transform_m2s_int_simple (GstAudioPanorama *
+    filter, gint16 * idata, gint16 * odata, guint num_samples);
+static void gst_audio_panorama_transform_s2s_int_simple (GstAudioPanorama *
+    filter, gint16 * idata, gint16 * odata, guint num_samples);
+static void gst_audio_panorama_transform_m2s_float_simple (GstAudioPanorama *
+    filter, gfloat * idata, gfloat * odata, guint num_samples);
+static void gst_audio_panorama_transform_s2s_float_simple (GstAudioPanorama *
+    filter, gfloat * idata, gfloat * odata, guint num_samples);
+
+static GstFlowReturn gst_audio_panorama_transform (GstBaseTransform * base,
+    GstBuffer * inbuf, GstBuffer * outbuf);
+
+
+/* Table with processing functions: [channels][format][method] */
+static GstAudioPanoramaProcessFunc panorama_process_functions[2][2][2] = {
+  {
+        {(GstAudioPanoramaProcessFunc) gst_audio_panorama_transform_m2s_int,
+              (GstAudioPanoramaProcessFunc)
+            gst_audio_panorama_transform_m2s_int_simple},
+        {(GstAudioPanoramaProcessFunc) gst_audio_panorama_transform_m2s_float,
+              (GstAudioPanoramaProcessFunc)
+            gst_audio_panorama_transform_m2s_float_simple}
+      },
+  {
+        {(GstAudioPanoramaProcessFunc) gst_audio_panorama_transform_s2s_int,
+              (GstAudioPanoramaProcessFunc)
+            gst_audio_panorama_transform_s2s_int_simple},
+        {(GstAudioPanoramaProcessFunc) gst_audio_panorama_transform_s2s_float,
+              (GstAudioPanoramaProcessFunc)
+            gst_audio_panorama_transform_s2s_float_simple}
+      }
+};
+
+/* GObject vmethod implementations */
+
+static void
+gst_audio_panorama_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_set_details (element_class, &element_details);
+}
+
+static void
+gst_audio_panorama_class_init (GstAudioPanoramaClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_audio_panorama_set_property;
+  gobject_class->get_property = gst_audio_panorama_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_PANORAMA,
+      g_param_spec_float ("panorama", "Panorama",
+          "Position in stereo panorama (-1.0 left -> 1.0 right)", -1.0, 1.0,
+          0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  /**
+   * GstAudioPanorama:method
+   *
+   * Panning method: psychoacoustic mode keeps the same perceived loudness,
+   * while simple mode just controls the volume of one channel. It's merely
+   * a matter of taste which method should be chosen. 
+   *
+   * Since: 0.10.6
+   **/
+  g_object_class_install_property (gobject_class, PROP_METHOD,
+      g_param_spec_enum ("method", "Panning method",
+          "Psychoacoustic mode keeps same perceived loudness, "
+          "simple mode just controls volume of one channel.",
+          GST_TYPE_AUDIO_PANORAMA_METHOD, METHOD_PSYCHOACOUSTIC,
+          G_PARAM_READWRITE));
+
+  GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
+      GST_DEBUG_FUNCPTR (gst_audio_panorama_get_unit_size);
+  GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
+      GST_DEBUG_FUNCPTR (gst_audio_panorama_transform_caps);
+  GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
+      GST_DEBUG_FUNCPTR (gst_audio_panorama_set_caps);
+  GST_BASE_TRANSFORM_CLASS (klass)->transform =
+      GST_DEBUG_FUNCPTR (gst_audio_panorama_transform);
+}
+
+static void
+gst_audio_panorama_init (GstAudioPanorama * filter,
+    GstAudioPanoramaClass * klass)
+{
+
+  filter->panorama = 0;
+  filter->method = METHOD_PSYCHOACOUSTIC;
+  filter->width = 0;
+  filter->channels = 0;
+  filter->format_float = FALSE;
+  filter->process = NULL;
+
+  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
+}
+
+static gboolean
+gst_audio_panorama_set_process_function (GstAudioPanorama * filter)
+{
+  gint channel_index, format_index, method_index;
+
+  /* set processing function */
+  channel_index = filter->channels - 1;
+  if (channel_index > 1 || channel_index < 0) {
+    filter->process = NULL;
+    return FALSE;
+  }
+
+  format_index = (filter->format_float) ? 1 : 0;
+
+  method_index = filter->method;
+  if (method_index >= NUM_METHODS || method_index < 0)
+    method_index = METHOD_PSYCHOACOUSTIC;
+
+  filter->process =
+      panorama_process_functions[channel_index][format_index][method_index];
+  return TRUE;
+}
+
+static void
+gst_audio_panorama_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioPanorama *filter = GST_AUDIO_PANORAMA (object);
+
+  switch (prop_id) {
+    case PROP_PANORAMA:
+      filter->panorama = g_value_get_float (value);
+      break;
+    case PROP_METHOD:
+      filter->method = g_value_get_enum (value);
+      gst_audio_panorama_set_process_function (filter);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_panorama_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioPanorama *filter = GST_AUDIO_PANORAMA (object);
+
+  switch (prop_id) {
+    case PROP_PANORAMA:
+      g_value_set_float (value, filter->panorama);
+      break;
+    case PROP_METHOD:
+      g_value_set_enum (value, filter->method);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* GstBaseTransform vmethod implementations */
+
+static gboolean
+gst_audio_panorama_get_unit_size (GstBaseTransform * base, GstCaps * caps,
+    guint * size)
+{
+  gint width, channels;
+  GstStructure *structure;
+  gboolean ret;
+
+  g_assert (size);
+
+  /* this works for both float and int */
+  structure = gst_caps_get_structure (caps, 0);
+  ret = gst_structure_get_int (structure, "width", &width);
+  ret &= gst_structure_get_int (structure, "channels", &channels);
+
+  *size = width * channels / 8;
+
+  return ret;
+}
+
+static GstCaps *
+gst_audio_panorama_transform_caps (GstBaseTransform * base,
+    GstPadDirection direction, GstCaps * caps)
+{
+  GstCaps *res;
+  GstStructure *structure;
+
+  /* transform caps gives one single caps so we can just replace
+   * the channel property with our range. */
+  res = gst_caps_copy (caps);
+  structure = gst_caps_get_structure (res, 0);
+  if (direction == GST_PAD_SRC) {
+    GST_INFO ("allow 1-2 channels");
+    gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
+  } else {
+    GST_INFO ("allow 2 channels");
+    gst_structure_set (structure, "channels", G_TYPE_INT, 2, NULL);
+  }
+
+  return res;
+}
+
+static gboolean
+gst_audio_panorama_set_caps (GstBaseTransform * base, GstCaps * incaps,
+    GstCaps * outcaps)
+{
+  GstAudioPanorama *filter = GST_AUDIO_PANORAMA (base);
+  const GstStructure *structure;
+  gboolean ret;
+  gint width;
+  const gchar *fmt;
+
+  /*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */
+
+  structure = gst_caps_get_structure (incaps, 0);
+  ret = gst_structure_get_int (structure, "channels", &filter->channels);
+  if (!ret)
+    goto no_channels;
+
+  ret = gst_structure_get_int (structure, "width", &width);
+  if (!ret)
+    goto no_width;
+  filter->width = width / 8;
+
+  fmt = gst_structure_get_name (structure);
+  if (!strcmp (fmt, "audio/x-raw-int"))
+    filter->format_float = FALSE;
+  else
+    filter->format_float = TRUE;
+
+  GST_DEBUG ("try to process %s input with %d channels", fmt, filter->channels);
+
+  ret = gst_audio_panorama_set_process_function (filter);
+
+  if (!ret)
+    GST_WARNING ("can't process input with %d channels", filter->channels);
+
+  return ret;
+
+no_channels:
+  GST_DEBUG ("no channels in caps");
+  return ret;
+no_width:
+  GST_DEBUG ("no width in caps");
+  return ret;
+}
+
+/* psychoacoustic processing functions */
+static void
+gst_audio_panorama_transform_m2s_int (GstAudioPanorama * filter, gint16 * idata,
+    gint16 * odata, guint num_samples)
+{
+  guint i;
+  gdouble val;
+  glong lval, rval;
+  gdouble rpan, lpan;
+
+  /* pan:  -1.0  0.0  1.0
+   * lpan:  1.0  0.5  0.0  
+   * rpan:  0.0  0.5  1.0
+   *
+   * FIXME: we should use -3db (1/sqtr(2)) for 50:50
+   */
+  rpan = (gdouble) (filter->panorama + 1.0) / 2.0;
+  lpan = 1.0 - rpan;
+
+  for (i = 0; i < num_samples; i++) {
+    val = (gdouble) * idata++;
+
+    lval = (glong) (val * lpan);
+    rval = (glong) (val * rpan);
+
+    *odata++ = (gint16) CLAMP (lval, G_MININT16, G_MAXINT16);
+    *odata++ = (gint16) CLAMP (rval, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_panorama_transform_s2s_int (GstAudioPanorama * filter, gint16 * idata,
+    gint16 * odata, guint num_samples)
+{
+  guint i;
+  glong lval, rval;
+  gdouble lival, rival;
+  gdouble lrpan, llpan, rrpan, rlpan;
+
+  /* pan:  -1.0  0.0  1.0
+   * llpan: 1.0  1.0  0.0
+   * lrpan: 1.0  0.0  0.0
+   * rrpan: 0.0  1.0  1.0
+   * rlpan: 0.0  0.0  1.0
+   */
+  if (filter->panorama > 0) {
+    rlpan = (gdouble) filter->panorama;
+    llpan = 1.0 - rlpan;
+    lrpan = 0.0;
+    rrpan = 1.0;
+  } else {
+    rrpan = (gdouble) (1.0 + filter->panorama);
+    lrpan = 1.0 - rrpan;
+    rlpan = 0.0;
+    llpan = 1.0;
+  }
+
+  for (i = 0; i < num_samples; i++) {
+    lival = (gdouble) * idata++;
+    rival = (gdouble) * idata++;
+
+    lval = lival * llpan + rival * lrpan;
+    rval = lival * rlpan + rival * rrpan;
+
+    *odata++ = (gint16) CLAMP (lval, G_MININT16, G_MAXINT16);
+    *odata++ = (gint16) CLAMP (rval, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_panorama_transform_m2s_float (GstAudioPanorama * filter,
+    gfloat * idata, gfloat * odata, guint num_samples)
+{
+  guint i;
+  gfloat val;
+  gdouble rpan, lpan;
+
+  /* pan:  -1.0  0.0  1.0
+   * lpan:  1.0  0.5  0.0  
+   * rpan:  0.0  0.5  1.0
+   *
+   * FIXME: we should use -3db (1/sqtr(2)) for 50:50
+   */
+  rpan = (gdouble) (filter->panorama + 1.0) / 2.0;
+  lpan = 1.0 - rpan;
+
+  for (i = 0; i < num_samples; i++) {
+    val = *idata++;
+
+    *odata++ = val * lpan;
+    *odata++ = val * rpan;
+  }
+}
+
+static void
+gst_audio_panorama_transform_s2s_float (GstAudioPanorama * filter,
+    gfloat * idata, gfloat * odata, guint num_samples)
+{
+  guint i;
+  gfloat lival, rival;
+  gdouble lrpan, llpan, rrpan, rlpan;
+
+  /* pan:  -1.0  0.0  1.0
+   * llpan: 1.0  1.0  0.0
+   * lrpan: 1.0  0.0  0.0
+   * rrpan: 0.0  1.0  1.0
+   * rlpan: 0.0  0.0  1.0
+   */
+  if (filter->panorama > 0) {
+    rlpan = (gdouble) filter->panorama;
+    llpan = 1.0 - rlpan;
+    lrpan = 0.0;
+    rrpan = 1.0;
+  } else {
+    rrpan = (gdouble) (1.0 + filter->panorama);
+    lrpan = 1.0 - rrpan;
+    rlpan = 0.0;
+    llpan = 1.0;
+  }
+
+  for (i = 0; i < num_samples; i++) {
+    lival = *idata++;
+    rival = *idata++;
+
+    *odata++ = lival * llpan + rival * lrpan;
+    *odata++ = lival * rlpan + rival * rrpan;
+  }
+}
+
+/* simple processing functions */
+static void
+gst_audio_panorama_transform_m2s_int_simple (GstAudioPanorama * filter,
+    gint16 * idata, gint16 * odata, guint num_samples)
+{
+  guint i;
+  gdouble val;
+  glong lval, rval;
+
+  for (i = 0; i < num_samples; i++) {
+    val = (gdouble) * idata++;
+
+    if (filter->panorama > 0.0) {
+      lval = (glong) (val * (1.0 - filter->panorama));
+      rval = (glong) val;
+    } else {
+      lval = (glong) val;
+      rval = (glong) (val * (1.0 + filter->panorama));
+    }
+
+    *odata++ = (gint16) CLAMP (lval, G_MININT16, G_MAXINT16);
+    *odata++ = (gint16) CLAMP (rval, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_panorama_transform_s2s_int_simple (GstAudioPanorama * filter,
+    gint16 * idata, gint16 * odata, guint num_samples)
+{
+  guint i;
+  glong lval, rval;
+  gdouble lival, rival;
+
+  for (i = 0; i < num_samples; i++) {
+    lival = (gdouble) * idata++;
+    rival = (gdouble) * idata++;
+
+    if (filter->panorama > 0.0) {
+      lval = (glong) (lival * (1.0 - filter->panorama));
+      rval = (glong) rival;
+    } else {
+      lval = (glong) lival;
+      rval = (glong) (rival * (1.0 + filter->panorama));
+    }
+
+    *odata++ = (gint16) CLAMP (lval, G_MININT16, G_MAXINT16);
+    *odata++ = (gint16) CLAMP (rval, G_MININT16, G_MAXINT16);
+  }
+}
+
+static void
+gst_audio_panorama_transform_m2s_float_simple (GstAudioPanorama * filter,
+    gfloat * idata, gfloat * odata, guint num_samples)
+{
+  guint i;
+  gfloat val;
+
+
+  for (i = 0; i < num_samples; i++) {
+    val = *idata++;
+
+    if (filter->panorama > 0.0) {
+      *odata++ = val * (1.0 - filter->panorama);
+      *odata++ = val;
+    } else {
+      *odata++ = val;
+      *odata++ = val * (1.0 + filter->panorama);
+    }
+  }
+}
+
+static void
+gst_audio_panorama_transform_s2s_float_simple (GstAudioPanorama * filter,
+    gfloat * idata, gfloat * odata, guint num_samples)
+{
+  guint i;
+  gfloat lival, rival;
+
+  for (i = 0; i < num_samples; i++) {
+    lival = *idata++;
+    rival = *idata++;
+
+    if (filter->panorama > 0.0) {
+      *odata++ = lival * (1.0 - filter->panorama);
+      *odata++ = rival;
+    } else {
+      *odata++ = lival;
+      *odata++ = rival * (1.0 + filter->panorama);
+    }
+  }
+}
+
+/* this function does the actual processing
+ */
+static GstFlowReturn
+gst_audio_panorama_transform (GstBaseTransform * base, GstBuffer * inbuf,
+    GstBuffer * outbuf)
+{
+  GstAudioPanorama *filter = GST_AUDIO_PANORAMA (base);
+  guint num_samples = GST_BUFFER_SIZE (outbuf) / (2 * filter->width);
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (outbuf)))
+    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (outbuf));
+
+  if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))) {
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
+    memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf));
+    return GST_FLOW_OK;
+  }
+
+  filter->process (filter, GST_BUFFER_DATA (inbuf),
+      GST_BUFFER_DATA (outbuf), num_samples);
+
+  return GST_FLOW_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiopanorama.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,67 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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_AUDIO_PANORAMA_H__
+#define __GST_AUDIO_PANORAMA_H__
+
+#include <gst/gst.h>
+#include <gst/gst_global.h>
+#include <gst/base/gstbasetransform.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_PANORAMA            (gst_audio_panorama_get_type())
+#define GST_AUDIO_PANORAMA(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_PANORAMA,GstAudioPanorama))
+#define GST_IS_AUDIO_PANORAMA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_PANORAMA))
+#define GST_AUDIO_PANORAMA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_PANORAMA,GstAudioPanoramaClass))
+#define GST_IS_AUDIO_PANORAMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_PANORAMA))
+#define GST_AUDIO_PANORAMA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_PANORAMA,GstAudioPanoramaClass))
+
+typedef struct _GstAudioPanorama      GstAudioPanorama;
+typedef struct _GstAudioPanoramaClass GstAudioPanoramaClass;
+
+typedef void (*GstAudioPanoramaProcessFunc)(GstAudioPanorama*, guint8*, guint8*, guint);
+
+struct _GstAudioPanorama {
+  GstBaseTransform element;
+
+  gfloat panorama;
+  
+  /* < private > */
+  GstAudioPanoramaProcessFunc process;
+  gint channels;
+  gboolean format_float;
+  gint width;
+  gint method;
+};
+
+struct _GstAudioPanoramaClass {
+  GstBaseTransformClass parent_class;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_panorama_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_PANORAMA_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiowsincband.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,440 @@
+/* -*- c-basic-offset: 2 -*-
+ * 
+ * GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2006 Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>
+ *               2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 windowed sinc filter is taken from the freely downloadable DSP book,
+ * "The Scientist and Engineer's Guide to Digital Signal Processing",
+ * chapter 16
+ * available at http://www.dspguide.com/
+ *
+ */
+
+/**
+ * SECTION:element-audiowsincband
+ *
+ * Attenuates all frequencies outside (bandpass) or inside (bandreject) of a frequency
+ * band. The length parameter controls the rolloff, the window parameter
+ * controls rolloff and stopband attenuation. The Hamming window provides a faster rolloff but a bit
+ * worse stopband attenuation, the other way around for the Blackman window.
+ *
+ * This element has the advantage over the Chebyshev bandpass and bandreject filter that it has
+ * a much better rolloff when using a larger kernel size and almost linear phase. The only
+ * disadvantage is the much slower execution time with larger kernels.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc freq=1500 ! audioconvert ! audiosincband mode=band-pass lower-frequency=3000 upper-frequency=10000 length=501 window=blackman ! audioconvert ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiowsincband mode=band-reject lower-frequency=59 upper-frequency=61 length=10001 window=hamming ! audioconvert ! alsasink
+ * gst-launch audiotestsrc wave=white-noise ! audioconvert ! audiowsincband mode=band-pass lower-frequency=1000 upper-frequency=2000 length=31 ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiowsincband.h"
+
+#define GST_CAT_DEFAULT gst_gst_audio_wsincband_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  PROP_0,
+  PROP_LENGTH,
+  PROP_LOWER_FREQUENCY,
+  PROP_UPPER_FREQUENCY,
+  PROP_MODE,
+  PROP_WINDOW
+};
+
+enum
+{
+  MODE_BAND_PASS = 0,
+  MODE_BAND_REJECT
+};
+
+#define GST_TYPE_AUDIO_WSINC_BAND_MODE (gst_gst_audio_wsincband_mode_get_type ())
+static GType
+gst_gst_audio_wsincband_mode_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {MODE_BAND_PASS, "Band pass (default)",
+          "band-pass"},
+      {MODE_BAND_REJECT, "Band reject",
+          "band-reject"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioWSincBandMode", values);
+  }
+  return gtype;
+}
+
+enum
+{
+  WINDOW_HAMMING = 0,
+  WINDOW_BLACKMAN
+};
+
+#define GST_TYPE_AUDIO_WSINC_BAND_WINDOW (gst_gst_audio_wsincband_window_get_type ())
+static GType
+gst_gst_audio_wsincband_window_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {WINDOW_HAMMING, "Hamming window (default)",
+          "hamming"},
+      {WINDOW_BLACKMAN, "Blackman window",
+          "blackman"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioWSincBandWindow", values);
+  }
+  return gtype;
+}
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_gst_audio_wsincband_debug, "audiowsincband", 0, \
+      "Band-pass and Band-reject Windowed sinc filter plugin");
+
+GST_BOILERPLATE_FULL (GstAudioWSincBand, gst_audio_wsincband, GstAudioFilter,
+    GST_TYPE_AUDIO_FX_BASE_FIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_wsincband_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_wsincband_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_wsincband_finalize (GObject * object);
+
+static gboolean gst_audio_wsincband_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+/* Element class */
+static void
+gst_audio_wsincband_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Band pass & band reject filter", "Filter/Effect/Audio",
+      "Band pass and band reject windowed sinc filter",
+      "Thomas Vander Stichele <thomas at apestaart dot org>, "
+      "Steven W. Smith, "
+      "Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>, "
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_wsincband_class_init (GstAudioWSincBandClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_wsincband_set_property;
+  gobject_class->get_property = gst_audio_wsincband_get_property;
+  gobject_class->finalize = gst_audio_wsincband_finalize;
+
+  /* FIXME: Don't use the complete possible range but restrict the upper boundary
+   * so automatically generated UIs can use a slider */
+  g_object_class_install_property (gobject_class, PROP_LOWER_FREQUENCY,
+      g_param_spec_float ("lower-frequency", "Lower Frequency",
+          "Cut-off lower frequency (Hz)", 0.0, 100000.0, 0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_UPPER_FREQUENCY,
+      g_param_spec_float ("upper-frequency", "Upper Frequency",
+          "Cut-off upper frequency (Hz)", 0.0, 100000.0, 0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_LENGTH,
+      g_param_spec_int ("length", "Length",
+          "Filter kernel length, will be rounded to the next odd number", 3,
+          50000, 101,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode", "Mode",
+          "Band pass or band reject mode", GST_TYPE_AUDIO_WSINC_BAND_MODE,
+          MODE_BAND_PASS,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_WINDOW,
+      g_param_spec_enum ("window", "Window",
+          "Window function to use", GST_TYPE_AUDIO_WSINC_BAND_WINDOW,
+          WINDOW_HAMMING,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_wsincband_setup);
+}
+
+static void
+gst_audio_wsincband_init (GstAudioWSincBand * self,
+    GstAudioWSincBandClass * g_class)
+{
+  self->kernel_length = 101;
+  self->lower_frequency = 0.0;
+  self->upper_frequency = 0.0;
+  self->mode = MODE_BAND_PASS;
+  self->window = WINDOW_HAMMING;
+
+  self->lock = g_mutex_new ();
+}
+
+static void
+gst_audio_wsincband_build_kernel (GstAudioWSincBand * self)
+{
+  gint i = 0;
+  gdouble sum = 0.0;
+  gint len = 0;
+  gdouble *kernel_lp, *kernel_hp;
+  gdouble w;
+  gdouble *kernel;
+
+  len = self->kernel_length;
+
+  if (GST_AUDIO_FILTER (self)->format.rate == 0) {
+    GST_DEBUG ("rate not set yet");
+    return;
+  }
+
+  if (GST_AUDIO_FILTER (self)->format.channels == 0) {
+    GST_DEBUG ("channels not set yet");
+    return;
+  }
+
+  /* Clamp frequencies */
+  self->lower_frequency =
+      CLAMP (self->lower_frequency, 0.0,
+      GST_AUDIO_FILTER (self)->format.rate / 2);
+  self->upper_frequency =
+      CLAMP (self->upper_frequency, 0.0,
+      GST_AUDIO_FILTER (self)->format.rate / 2);
+  if (self->lower_frequency > self->upper_frequency) {
+    gint tmp = self->lower_frequency;
+
+    self->lower_frequency = self->upper_frequency;
+    self->upper_frequency = tmp;
+  }
+
+  GST_DEBUG ("gst_audio_wsincband: initializing filter kernel of length %d "
+      "with lower frequency %.2lf Hz "
+      ", upper frequency %.2lf Hz for mode %s",
+      len, self->lower_frequency, self->upper_frequency,
+      (self->mode == MODE_BAND_PASS) ? "band-pass" : "band-reject");
+
+  /* fill the lp kernel */
+  w = 2 * M_PI * (self->lower_frequency / GST_AUDIO_FILTER (self)->format.rate);
+  kernel_lp = g_new (gdouble, len);
+  for (i = 0; i < len; ++i) {
+    if (i == len / 2)
+      kernel_lp[i] = w;
+    else
+      kernel_lp[i] = sin (w * (i - len / 2))
+          / (i - len / 2);
+    /* Windowing */
+    if (self->window == WINDOW_HAMMING)
+      kernel_lp[i] *= (0.54 - 0.46 * cos (2 * M_PI * i / len));
+    else
+      kernel_lp[i] *=
+          (0.42 - 0.5 * cos (2 * M_PI * i / len) +
+          0.08 * cos (4 * M_PI * i / len));
+  }
+
+  /* normalize for unity gain at DC */
+  sum = 0.0;
+  for (i = 0; i < len; ++i)
+    sum += kernel_lp[i];
+  for (i = 0; i < len; ++i)
+    kernel_lp[i] /= sum;
+
+  /* fill the hp kernel */
+  w = 2 * M_PI * (self->upper_frequency / GST_AUDIO_FILTER (self)->format.rate);
+  kernel_hp = g_new (gdouble, len);
+  for (i = 0; i < len; ++i) {
+    if (i == len / 2)
+      kernel_hp[i] = w;
+    else
+      kernel_hp[i] = sin (w * (i - len / 2))
+          / (i - len / 2);
+    /* Windowing */
+    if (self->window == WINDOW_HAMMING)
+      kernel_hp[i] *= (0.54 - 0.46 * cos (2 * M_PI * i / len));
+    else
+      kernel_hp[i] *=
+          (0.42 - 0.5 * cos (2 * M_PI * i / len) +
+          0.08 * cos (4 * M_PI * i / len));
+  }
+
+  /* normalize for unity gain at DC */
+  sum = 0.0;
+  for (i = 0; i < len; ++i)
+    sum += kernel_hp[i];
+  for (i = 0; i < len; ++i)
+    kernel_hp[i] /= sum;
+
+  /* do spectral inversion to go from lowpass to highpass */
+  for (i = 0; i < len; ++i)
+    kernel_hp[i] = -kernel_hp[i];
+  kernel_hp[len / 2] += 1;
+
+  /* combine the two kernels */
+  kernel = g_new (gdouble, len);
+
+  for (i = 0; i < len; ++i)
+    kernel[i] = kernel_lp[i] + kernel_hp[i];
+
+  /* free the helper kernels */
+  g_free (kernel_lp);
+  g_free (kernel_hp);
+
+  /* do spectral inversion to go from bandreject to bandpass
+   * if specified */
+  if (self->mode == MODE_BAND_PASS) {
+    for (i = 0; i < len; ++i)
+      kernel[i] = -kernel[i];
+    kernel[len / 2] += 1;
+  }
+
+  gst_audio_fx_base_fir_filter_set_kernel (GST_AUDIO_FX_BASE_FIR_FILTER (self),
+      kernel, self->kernel_length, (len - 1) / 2);
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_wsincband_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioWSincBand *self = GST_AUDIO_WSINC_BAND (base);
+
+  gst_audio_wsincband_build_kernel (self);
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
+
+static void
+gst_audio_wsincband_finalize (GObject * object)
+{
+  GstAudioWSincBand *self = GST_AUDIO_WSINC_BAND (object);
+
+  g_mutex_free (self->lock);
+  self->lock = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_wsincband_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioWSincBand *self = GST_AUDIO_WSINC_BAND (object);
+
+  g_return_if_fail (GST_IS_AUDIO_WSINC_BAND (self));
+
+  switch (prop_id) {
+    case PROP_LENGTH:{
+      gint val;
+
+      g_mutex_lock (self->lock);
+      val = g_value_get_int (value);
+      if (val % 2 == 0)
+        val++;
+
+      if (val != self->kernel_length) {
+        gst_audio_fx_base_fir_filter_push_residue (GST_AUDIO_FX_BASE_FIR_FILTER
+            (self));
+        self->kernel_length = val;
+        gst_audio_wsincband_build_kernel (self);
+      }
+      g_mutex_unlock (self->lock);
+      break;
+    }
+    case PROP_LOWER_FREQUENCY:
+      g_mutex_lock (self->lock);
+      self->lower_frequency = g_value_get_float (value);
+      gst_audio_wsincband_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_UPPER_FREQUENCY:
+      g_mutex_lock (self->lock);
+      self->upper_frequency = g_value_get_float (value);
+      gst_audio_wsincband_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_MODE:
+      g_mutex_lock (self->lock);
+      self->mode = g_value_get_enum (value);
+      gst_audio_wsincband_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_WINDOW:
+      g_mutex_lock (self->lock);
+      self->window = g_value_get_enum (value);
+      gst_audio_wsincband_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_wsincband_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioWSincBand *self = GST_AUDIO_WSINC_BAND (object);
+
+  switch (prop_id) {
+    case PROP_LENGTH:
+      g_value_set_int (value, self->kernel_length);
+      break;
+    case PROP_LOWER_FREQUENCY:
+      g_value_set_float (value, self->lower_frequency);
+      break;
+    case PROP_UPPER_FREQUENCY:
+      g_value_set_float (value, self->upper_frequency);
+      break;
+    case PROP_MODE:
+      g_value_set_enum (value, self->mode);
+      break;
+    case PROP_WINDOW:
+      g_value_set_enum (value, self->window);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiowsincband.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,85 @@
+/* -*- c-basic-offset: 2 -*-
+ * 
+ * GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2006 Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>
+ *               2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 windowed sinc filter is taken from the freely downloadable DSP book,
+ * "The Scientist and Engineer's Guide to Digital Signal Processing",
+ * chapter 16
+ * available at http://www.dspguide.com/
+ *
+ */
+
+#ifndef __GST_AUDIO_WSINC_BAND_H__
+#define __GST_AUDIO_WSINC_BAND_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/gst_global.h>
+
+#include "audiofxbasefirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_WSINC_BAND \
+  (gst_audio_wsincband_get_type())
+#define GST_AUDIO_WSINC_BAND(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_WSINC_BAND,GstAudioWSincBand))
+#define GST_AUDIO_WSINC_BAND_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_WSINC_BAND,GstAudioWSincBandClass))
+#define GST_IS_AUDIO_WSINC_BAND(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_WSINC_BAND))
+#define GST_IS_AUDIO_WSINC_BAND_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_WSINC_BAND))
+
+typedef struct _GstAudioWSincBand GstAudioWSincBand;
+typedef struct _GstAudioWSincBandClass GstAudioWSincBandClass;
+
+/**
+ * GstAudioWSincBand:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioWSincBand {
+  GstAudioFXBaseFIRFilter parent;
+
+  gint mode;
+  gint window;
+  gfloat lower_frequency, upper_frequency;
+  gint kernel_length;           /* length of the filter kernel */
+
+  /* < private > */
+  GMutex *lock;
+};
+
+struct _GstAudioWSincBandClass {
+  GstAudioFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_wsincband_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_WSINC_BAND_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiowsinclimit.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,373 @@
+/* -*- c-basic-offset: 2 -*-
+ * 
+ * GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2006 Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>
+ *               2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 windowed sinc filter is taken from the freely downloadable DSP book,
+ * "The Scientist and Engineer's Guide to Digital Signal Processing",
+ * chapter 16
+ * available at http://www.dspguide.com/
+ *
+ */
+
+/**
+ * SECTION:element-audiowsinclimit
+ *
+ * Attenuates all frequencies above the cutoff frequency (low-pass) or all frequencies below the
+ * cutoff frequency (high-pass). The length parameter controls the rolloff, the window parameter
+ * controls rolloff and stopband attenuation. The Hamming window provides a faster rolloff but a bit
+ * worse stopband attenuation, the other way around for the Blackman window.
+ *
+ * This element has the advantage over the Chebyshev lowpass and highpass filter that it has
+ * a much better rolloff when using a larger kernel size and almost linear phase. The only
+ * disadvantage is the much slower execution time with larger kernels.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc freq=1500 ! audioconvert ! audiowsinclimit mode=low-pass frequency=1000 length=501 ! audioconvert ! alsasink
+ * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiowsinclimit mode=high-pass frequency=15000 length=501 ! audioconvert ! alsasink
+ * gst-launch audiotestsrc wave=white-noise ! audioconvert ! audiowsinclimit mode=low-pass frequency=1000 length=10001 window=blackman ! audioconvert ! alsasink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiowsinclimit.h"
+
+#define GST_CAT_DEFAULT gst_audio_wsinclimit_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  PROP_0,
+  PROP_LENGTH,
+  PROP_FREQUENCY,
+  PROP_MODE,
+  PROP_WINDOW
+};
+
+enum
+{
+  MODE_LOW_PASS = 0,
+  MODE_HIGH_PASS
+};
+
+#define GST_TYPE_AUDIO_WSINC_LIMIT_MODE (gst_audio_wsinclimit_mode_get_type ())
+static GType
+gst_audio_wsinclimit_mode_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {MODE_LOW_PASS, "Low pass (default)",
+          "low-pass"},
+      {MODE_HIGH_PASS, "High pass",
+          "high-pass"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioWSincLimitMode", values);
+  }
+  return gtype;
+}
+
+enum
+{
+  WINDOW_HAMMING = 0,
+  WINDOW_BLACKMAN
+};
+
+#define GST_TYPE_AUDIO_WSINC_LIMIT_WINDOW (gst_audio_wsinclimit_window_get_type ())
+static GType
+gst_audio_wsinclimit_window_get_type (void)
+{
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {WINDOW_HAMMING, "Hamming window (default)",
+          "hamming"},
+      {WINDOW_BLACKMAN, "Blackman window",
+          "blackman"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstAudioWSincLimitWindow", values);
+  }
+  return gtype;
+}
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_wsinclimit_debug, "audiowsinclimit", 0, \
+      "Low-pass and High-pass Windowed sinc filter plugin");
+
+GST_BOILERPLATE_FULL (GstAudioWSincLimit, gst_audio_wsinclimit, GstAudioFilter,
+    GST_TYPE_AUDIO_FX_BASE_FIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_wsinclimit_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_wsinclimit_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_wsinclimit_finalize (GObject * object);
+
+static gboolean gst_audio_wsinclimit_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+/* Element class */
+
+static void
+gst_audio_wsinclimit_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Low pass & high pass filter", "Filter/Effect/Audio",
+      "Low pass and high pass windowed sinc filter",
+      "Thomas Vander Stichele <thomas at apestaart dot org>, "
+      "Steven W. Smith, "
+      "Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>, "
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_wsinclimit_class_init (GstAudioWSincLimitClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_wsinclimit_set_property;
+  gobject_class->get_property = gst_audio_wsinclimit_get_property;
+  gobject_class->finalize = gst_audio_wsinclimit_finalize;
+
+  /* FIXME: Don't use the complete possible range but restrict the upper boundary
+   * so automatically generated UIs can use a slider */
+  g_object_class_install_property (gobject_class, PROP_FREQUENCY,
+      g_param_spec_float ("cutoff", "Cutoff",
+          "Cut-off Frequency (Hz)", 0.0, 100000.0, 0.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_LENGTH,
+      g_param_spec_int ("length", "Length",
+          "Filter kernel length, will be rounded to the next odd number",
+          3, 50000, 101,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode", "Mode",
+          "Low pass or high pass mode", GST_TYPE_AUDIO_WSINC_LIMIT_MODE,
+          MODE_LOW_PASS,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_WINDOW,
+      g_param_spec_enum ("window", "Window",
+          "Window function to use", GST_TYPE_AUDIO_WSINC_LIMIT_WINDOW,
+          WINDOW_HAMMING,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_wsinclimit_setup);
+}
+
+static void
+gst_audio_wsinclimit_init (GstAudioWSincLimit * self,
+    GstAudioWSincLimitClass * g_class)
+{
+  self->mode = MODE_LOW_PASS;
+  self->window = WINDOW_HAMMING;
+  self->kernel_length = 101;
+  self->cutoff = 0.0;
+
+  self->lock = g_mutex_new ();
+}
+
+static void
+gst_audio_wsinclimit_build_kernel (GstAudioWSincLimit * self)
+{
+  gint i = 0;
+  gdouble sum = 0.0;
+  gint len = 0;
+  gdouble w;
+  gdouble *kernel = NULL;
+
+  len = self->kernel_length;
+
+  if (GST_AUDIO_FILTER (self)->format.rate == 0) {
+    GST_DEBUG ("rate not set yet");
+    return;
+  }
+
+  if (GST_AUDIO_FILTER (self)->format.channels == 0) {
+    GST_DEBUG ("channels not set yet");
+    return;
+  }
+
+  /* Clamp cutoff frequency between 0 and the nyquist frequency */
+  self->cutoff =
+      CLAMP (self->cutoff, 0.0, GST_AUDIO_FILTER (self)->format.rate / 2);
+
+  GST_DEBUG ("gst_audio_wsinclimit_: initializing filter kernel of length %d "
+      "with cutoff %.2lf Hz "
+      "for mode %s",
+      len, self->cutoff,
+      (self->mode == MODE_LOW_PASS) ? "low-pass" : "high-pass");
+
+  /* fill the kernel */
+  w = 2 * M_PI * (self->cutoff / GST_AUDIO_FILTER (self)->format.rate);
+
+  kernel = g_new (gdouble, len);
+
+  for (i = 0; i < len; ++i) {
+    if (i == len / 2)
+      kernel[i] = w;
+    else
+      kernel[i] = sin (w * (i - len / 2)) / (i - len / 2);
+    /* windowing */
+    if (self->window == WINDOW_HAMMING)
+      kernel[i] *= (0.54 - 0.46 * cos (2 * M_PI * i / len));
+    else
+      kernel[i] *= (0.42 - 0.5 * cos (2 * M_PI * i / len) +
+          0.08 * cos (4 * M_PI * i / len));
+  }
+
+  /* normalize for unity gain at DC */
+  for (i = 0; i < len; ++i)
+    sum += kernel[i];
+  for (i = 0; i < len; ++i)
+    kernel[i] /= sum;
+
+  /* convert to highpass if specified */
+  if (self->mode == MODE_HIGH_PASS) {
+    for (i = 0; i < len; ++i)
+      kernel[i] = -kernel[i];
+    kernel[len / 2] += 1.0;
+  }
+
+  gst_audio_fx_base_fir_filter_set_kernel (GST_AUDIO_FX_BASE_FIR_FILTER (self),
+      kernel, self->kernel_length, (len - 1) / 2);
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_wsinclimit_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioWSincLimit *self = GST_AUDIO_WSINC_LIMIT (base);
+
+  gst_audio_wsinclimit_build_kernel (self);
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
+
+static void
+gst_audio_wsinclimit_finalize (GObject * object)
+{
+  GstAudioWSincLimit *self = GST_AUDIO_WSINC_LIMIT (object);
+
+  g_mutex_free (self->lock);
+  self->lock = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_wsinclimit_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioWSincLimit *self = GST_AUDIO_WSINC_LIMIT (object);
+
+  g_return_if_fail (GST_IS_AUDIO_WSINC_LIMIT (self));
+
+  switch (prop_id) {
+    case PROP_LENGTH:{
+      gint val;
+
+      g_mutex_lock (self->lock);
+      val = g_value_get_int (value);
+      if (val % 2 == 0)
+        val++;
+
+      if (val != self->kernel_length) {
+        gst_audio_fx_base_fir_filter_push_residue (GST_AUDIO_FX_BASE_FIR_FILTER
+            (self));
+        self->kernel_length = val;
+        gst_audio_wsinclimit_build_kernel (self);
+      }
+      g_mutex_unlock (self->lock);
+      break;
+    }
+    case PROP_FREQUENCY:
+      g_mutex_lock (self->lock);
+      self->cutoff = g_value_get_float (value);
+      gst_audio_wsinclimit_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_MODE:
+      g_mutex_lock (self->lock);
+      self->mode = g_value_get_enum (value);
+      gst_audio_wsinclimit_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_WINDOW:
+      g_mutex_lock (self->lock);
+      self->window = g_value_get_enum (value);
+      gst_audio_wsinclimit_build_kernel (self);
+      g_mutex_unlock (self->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_wsinclimit_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioWSincLimit *self = GST_AUDIO_WSINC_LIMIT (object);
+
+  switch (prop_id) {
+    case PROP_LENGTH:
+      g_value_set_int (value, self->kernel_length);
+      break;
+    case PROP_FREQUENCY:
+      g_value_set_float (value, self->cutoff);
+      break;
+    case PROP_MODE:
+      g_value_set_enum (value, self->mode);
+      break;
+    case PROP_WINDOW:
+      g_value_set_enum (value, self->window);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/audiowsinclimit.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,85 @@
+/* -*- c-basic-offset: 2 -*-
+ * 
+ * GStreamer
+ * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2006 Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>
+ *               2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 windowed sinc filter is taken from the freely downloadable DSP book,
+ * "The Scientist and Engineer's Guide to Digital Signal Processing",
+ * chapter 16
+ * available at http://www.dspguide.com/
+ *
+ */
+
+#ifndef __GST_AUDIO_WSINC_LIMIT_H__
+#define __GST_AUDIO_WSINC_LIMIT_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/gst_global.h>
+
+#include "audiofxbasefirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_WSINC_LIMIT \
+  (gst_audio_wsinclimit_get_type())
+#define GST_AUDIO_WSINC_LIMIT(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_WSINC_LIMIT,GstAudioWSincLimit))
+#define GST_AUDIO_WSINC_LIMIT_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_WSINC_LIMIT,GstAudioWSincLimitClass))
+#define GST_IS_AUDIO_WSINC_LIMIT(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_WSINC_LIMIT))
+#define GST_IS_AUDIO_WSINC_LIMIT_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_WSINC_LIMIT))
+
+typedef struct _GstAudioWSincLimit GstAudioWSincLimit;
+typedef struct _GstAudioWSincLimitClass GstAudioWSincLimitClass;
+
+/**
+ * GstAudioWSincLimit:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioWSincLimit {
+  GstAudioFXBaseFIRFilter parent;
+
+  gint mode;
+  gint window;
+  gfloat cutoff;
+  gint kernel_length;
+
+  /* < private > */
+  GMutex *lock;
+};
+
+struct _GstAudioWSincLimitClass {
+  GstAudioFXBaseFIRFilterClass parent;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_audio_wsinclimit_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_WSINC_LIMIT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/audiofx/math_compat.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,55 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * 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 __MATH_COMPAT_H__
+#define __MATH_COMPAT_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <math.h>
+
+#ifndef HAVE_ASINH
+static inline gdouble
+asinh (gdouble x)
+{
+  return log(x + sqrt (x * x + 1));
+}
+#endif
+
+#ifndef HAVE_SINH
+static inline gdouble
+sinh (gdouble x)
+{
+  return 0.5 * (exp (x) - exp (-x));
+}
+#endif
+
+#ifndef HAVE_COSH
+static inline gdouble
+cosh (gdouble x)
+{
+  return 0.5 * (exp (x) + exp (-x));
+}
+#endif
+
+#endif /* __MATH_COMPAT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/auparse/gstauparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,726 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-auparse
+ *
+ * Parses .au files mostly originating from sun os based computers.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gstauparse.h"
+#include <gst/audio/audio.h>
+
+GST_DEBUG_CATEGORY_STATIC (auparse_debug);
+#define GST_CAT_DEFAULT (auparse_debug)
+
+static const GstElementDetails gst_au_parse_details =
+GST_ELEMENT_DETAILS ("AU audio demuxer",
+    "Codec/Demuxer/Audio",
+    "Parse an .au file into raw audio",
+    "Erik Walthinsen <omega@cse.ogi.edu>");
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-au")
+    );
+
+#define GST_AU_PARSE_ALAW_PAD_TEMPLATE_CAPS \
+    "audio/x-alaw, "                        \
+    "rate = (int) [ 8000, 192000 ], "       \
+    "channels = (int) [ 1, 2 ]"
+
+#define GST_AU_PARSE_MULAW_PAD_TEMPLATE_CAPS \
+    "audio/x-mulaw, "                        \
+    "rate = (int) [ 8000, 192000 ], "        \
+    "channels = (int) [ 1, 2 ]"
+
+/* Nothing to decode those ADPCM streams for now */
+#define GST_AU_PARSE_ADPCM_PAD_TEMPLATE_CAPS \
+    "audio/x-adpcm, "                        \
+    "layout = (string) { g721, g722, g723_3, g723_5 }"
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
+        GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS ";"
+        GST_AU_PARSE_ALAW_PAD_TEMPLATE_CAPS ";"
+        GST_AU_PARSE_MULAW_PAD_TEMPLATE_CAPS ";"
+        GST_AU_PARSE_ADPCM_PAD_TEMPLATE_CAPS));
+
+
+static void gst_au_parse_dispose (GObject * object);
+static GstFlowReturn gst_au_parse_chain (GstPad * pad, GstBuffer * buf);
+static GstStateChangeReturn gst_au_parse_change_state (GstElement * element,
+    GstStateChange transition);
+static void gst_au_parse_reset (GstAuParse * auparse);
+static gboolean gst_au_parse_remove_srcpad (GstAuParse * auparse);
+static gboolean gst_au_parse_add_srcpad (GstAuParse * auparse, GstCaps * caps);
+static gboolean gst_au_parse_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_au_parse_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_au_parse_sink_event (GstPad * pad, GstEvent * event);
+
+GST_BOILERPLATE (GstAuParse, gst_au_parse, GstElement, GST_TYPE_ELEMENT);
+
+static void
+gst_au_parse_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+  gst_element_class_set_details (element_class, &gst_au_parse_details);
+
+  GST_DEBUG_CATEGORY_INIT (auparse_debug, "auparse", 0, ".au parser");
+}
+
+static void
+gst_au_parse_class_init (GstAuParseClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->dispose = gst_au_parse_dispose;
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_au_parse_change_state);
+}
+
+static void
+gst_au_parse_init (GstAuParse * auparse, GstAuParseClass * klass)
+{
+  auparse->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
+  gst_pad_set_chain_function (auparse->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_au_parse_chain));
+  gst_pad_set_event_function (auparse->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_au_parse_sink_event));
+  gst_element_add_pad (GST_ELEMENT (auparse), auparse->sinkpad);
+
+  auparse->srcpad = NULL;
+  auparse->adapter = gst_adapter_new ();
+  gst_au_parse_reset (auparse);
+}
+
+static void
+gst_au_parse_dispose (GObject * object)
+{
+  GstAuParse *au = GST_AU_PARSE (object);
+
+  if (au->adapter != NULL) {
+    g_object_unref (au->adapter);
+    au->adapter = NULL;
+  }
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_au_parse_reset (GstAuParse * auparse)
+{
+  gst_au_parse_remove_srcpad (auparse);
+
+  auparse->offset = 0;
+  auparse->buffer_offset = 0;
+  auparse->encoding = 0;
+  auparse->samplerate = 0;
+  auparse->channels = 0;
+
+  gst_adapter_clear (auparse->adapter);
+
+  /* gst_segment_init (&auparse->segment, GST_FORMAT_TIME); */
+}
+
+static gboolean
+gst_au_parse_add_srcpad (GstAuParse * auparse, GstCaps * new_caps)
+{
+  if (auparse->src_caps && gst_caps_is_equal (new_caps, auparse->src_caps)) {
+    GST_LOG_OBJECT (auparse, "same caps, nothing to do");
+    return TRUE;
+  }
+
+  gst_caps_replace (&auparse->src_caps, new_caps);
+  if (auparse->srcpad != NULL) {
+    GST_DEBUG_OBJECT (auparse, "Changing src pad caps to %" GST_PTR_FORMAT,
+        auparse->src_caps);
+    gst_pad_set_caps (auparse->srcpad, auparse->src_caps);
+  }
+
+  if (auparse->srcpad == NULL) {
+    auparse->srcpad = gst_pad_new_from_static_template (&src_template, "src");
+    g_return_val_if_fail (auparse->srcpad != NULL, FALSE);
+
+#if 0
+    gst_pad_set_query_type_function (auparse->srcpad,
+        GST_DEBUG_FUNCPTR (gst_au_parse_src_get_query_types));
+#endif
+    gst_pad_set_query_function (auparse->srcpad,
+        GST_DEBUG_FUNCPTR (gst_au_parse_src_query));
+    gst_pad_set_event_function (auparse->srcpad,
+        GST_DEBUG_FUNCPTR (gst_au_parse_src_event));
+
+    gst_pad_use_fixed_caps (auparse->srcpad);
+    gst_pad_set_active (auparse->srcpad, TRUE);
+
+    if (auparse->src_caps)
+      gst_pad_set_caps (auparse->srcpad, auparse->src_caps);
+
+    GST_DEBUG_OBJECT (auparse, "Adding src pad with caps %" GST_PTR_FORMAT,
+        auparse->src_caps);
+
+    gst_object_ref (auparse->srcpad);
+    if (!gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad))
+      return FALSE;
+    gst_element_no_more_pads (GST_ELEMENT (auparse));
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_au_parse_remove_srcpad (GstAuParse * auparse)
+{
+  gboolean res = TRUE;
+
+  if (auparse->srcpad != NULL) {
+    GST_DEBUG_OBJECT (auparse, "Removing src pad");
+    res = gst_element_remove_pad (GST_ELEMENT (auparse), auparse->srcpad);
+    g_return_val_if_fail (res != FALSE, FALSE);
+    gst_object_unref (auparse->srcpad);
+    auparse->srcpad = NULL;
+  }
+
+  return res;
+}
+
+static GstFlowReturn
+gst_au_parse_parse_header (GstAuParse * auparse)
+{
+  GstCaps *tempcaps;
+  guint32 size;
+  guint8 *head;
+  gchar layout[7] = { 0, };
+  gint law = 0, depth = 0, ieee = 0;
+
+  head = (guint8 *) gst_adapter_peek (auparse->adapter, 24);
+  g_assert (head != NULL);
+
+  GST_DEBUG_OBJECT (auparse, "[%c%c%c%c]", head[0], head[1], head[2], head[3]);
+
+  switch (GST_READ_UINT32_BE (head)) {
+      /* normal format is big endian (au is a Sparc format) */
+    case 0x2e736e64:{          /* ".snd" */
+      auparse->endianness = G_BIG_ENDIAN;
+      break;
+    }
+      /* and of course, someone had to invent a little endian
+       * version.  Used by DEC systems. */
+    case 0x646e732e:           /* dns.                          */
+    case 0x0064732e:{          /* other source say it is "dns." */
+      auparse->endianness = G_LITTLE_ENDIAN;
+      break;
+    }
+    default:{
+      goto unknown_header;
+    }
+  }
+
+  auparse->offset = GST_READ_UINT32_BE (head + 4);
+  /* Do not trust size, could be set to -1 : unknown */
+  size = GST_READ_UINT32_BE (head + 8);
+  auparse->encoding = GST_READ_UINT32_BE (head + 12);
+  auparse->samplerate = GST_READ_UINT32_BE (head + 16);
+  auparse->channels = GST_READ_UINT32_BE (head + 20);
+
+  if (auparse->samplerate < 8000 || auparse->samplerate > 192000)
+    goto unsupported_sample_rate;
+
+  if (auparse->channels < 1 || auparse->channels > 2)
+    goto unsupported_number_of_channels;
+
+  GST_DEBUG_OBJECT (auparse, "offset %" G_GINT64_FORMAT ", size %u, "
+      "encoding %u, frequency %u, channels %u", auparse->offset, size,
+      auparse->encoding, auparse->samplerate, auparse->channels);
+
+  /* Docs:
+   * http://www.opengroup.org/public/pubs/external/auformat.html
+   * http://astronomy.swin.edu.au/~pbourke/dataformats/au/
+   * Solaris headers : /usr/include/audio/au.h
+   * libsndfile : src/au.c
+   *
+   * Samples :
+   * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/AU/Samples.html
+   */
+
+  switch (auparse->encoding) {
+    case 1:                    /* 8-bit ISDN mu-law G.711 */
+      law = 1;
+      depth = 8;
+      break;
+    case 27:                   /* 8-bit ISDN  A-law G.711 */
+      law = 2;
+      depth = 8;
+      break;
+
+    case 2:                    /*  8-bit linear PCM */
+      depth = 8;
+      break;
+    case 3:                    /* 16-bit linear PCM */
+      depth = 16;
+      break;
+    case 4:                    /* 24-bit linear PCM */
+      depth = 24;
+      break;
+    case 5:                    /* 32-bit linear PCM */
+      depth = 32;
+      break;
+
+    case 6:                    /* 32-bit IEEE floating point */
+      ieee = 1;
+      depth = 32;
+      break;
+    case 7:                    /* 64-bit IEEE floating point */
+      ieee = 1;
+      depth = 64;
+      break;
+
+    case 23:                   /* 4-bit CCITT G.721   ADPCM 32kbps -> modplug/libsndfile (compressed 8-bit mu-law) */
+      strcpy (layout, "g721");
+      break;
+    case 24:                   /* 8-bit CCITT G.722   ADPCM        -> rtp */
+      strcpy (layout, "g722");
+      break;
+    case 25:                   /* 3-bit CCITT G.723.3 ADPCM 24kbps -> rtp/xine/modplug/libsndfile */
+      strcpy (layout, "g723_3");
+      break;
+    case 26:                   /* 5-bit CCITT G.723.5 ADPCM 40kbps -> rtp/xine/modplug/libsndfile */
+      strcpy (layout, "g723_5");
+      break;
+
+    case 8:                    /* Fragmented sample data */
+    case 9:                    /* AU_ENCODING_NESTED */
+
+    case 10:                   /* DSP program */
+    case 11:                   /* DSP  8-bit fixed point */
+    case 12:                   /* DSP 16-bit fixed point */
+    case 13:                   /* DSP 24-bit fixed point */
+    case 14:                   /* DSP 32-bit fixed point */
+
+    case 16:                   /* AU_ENCODING_DISPLAY : non-audio display data */
+    case 17:                   /* AU_ENCODING_MULAW_SQUELCH */
+
+    case 18:                   /* 16-bit linear with emphasis */
+    case 19:                   /* 16-bit linear compressed (NeXT) */
+    case 20:                   /* 16-bit linear with emphasis and compression */
+
+    case 21:                   /* Music kit DSP commands */
+    case 22:                   /* Music kit DSP commands samples */
+
+    default:
+      goto unknown_format;
+  }
+
+  if (law) {
+    tempcaps =
+        gst_caps_new_simple ((law == 1) ? "audio/x-mulaw" : "audio/x-alaw",
+        "rate", G_TYPE_INT, auparse->samplerate,
+        "channels", G_TYPE_INT, auparse->channels, NULL);
+    auparse->sample_size = auparse->channels;
+  } else if (ieee) {
+    tempcaps = gst_caps_new_simple ("audio/x-raw-float",
+        "rate", G_TYPE_INT, auparse->samplerate,
+        "channels", G_TYPE_INT, auparse->channels,
+        "endianness", G_TYPE_INT, auparse->endianness,
+        "width", G_TYPE_INT, depth, NULL);
+    auparse->sample_size = auparse->channels * depth / 8;
+  } else if (layout[0]) {
+    tempcaps = gst_caps_new_simple ("audio/x-adpcm",
+        "layout", G_TYPE_STRING, layout, NULL);
+    auparse->sample_size = 0;
+  } else {
+    tempcaps = gst_caps_new_simple ("audio/x-raw-int",
+        "rate", G_TYPE_INT, auparse->samplerate,
+        "channels", G_TYPE_INT, auparse->channels,
+        "endianness", G_TYPE_INT, auparse->endianness,
+        "depth", G_TYPE_INT, depth, "width", G_TYPE_INT, depth,
+        /* FIXME: signed TRUE even for 8-bit PCM? */
+        "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+    auparse->sample_size = auparse->channels * depth / 8;
+  }
+
+  GST_DEBUG_OBJECT (auparse, "sample_size=%d", auparse->sample_size);
+
+  if (!gst_au_parse_add_srcpad (auparse, tempcaps))
+    goto add_pad_failed;
+
+  GST_DEBUG_OBJECT (auparse, "offset=%" G_GINT64_FORMAT, auparse->offset);
+  gst_adapter_flush (auparse->adapter, auparse->offset);
+
+  gst_caps_unref (tempcaps);
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+unknown_header:
+  {
+    GST_ELEMENT_ERROR (auparse, STREAM, WRONG_TYPE, (NULL), (NULL));
+    return GST_FLOW_ERROR;
+  }
+unsupported_sample_rate:
+  {
+    GST_ELEMENT_ERROR (auparse, STREAM, FORMAT, (NULL),
+        ("Unsupported samplerate: %u", auparse->samplerate));
+    return GST_FLOW_ERROR;
+  }
+unsupported_number_of_channels:
+  {
+    GST_ELEMENT_ERROR (auparse, STREAM, FORMAT, (NULL),
+        ("Unsupported number of channels: %u", auparse->channels));
+    return GST_FLOW_ERROR;
+  }
+unknown_format:
+  {
+    GST_ELEMENT_ERROR (auparse, STREAM, FORMAT, (NULL),
+        ("Unsupported encoding: %u", auparse->encoding));
+    return GST_FLOW_ERROR;
+  }
+add_pad_failed:
+  {
+    GST_ELEMENT_ERROR (auparse, STREAM, FAILED, (NULL),
+        ("Failed to add srcpad"));
+    gst_caps_unref (tempcaps);
+    return GST_FLOW_ERROR;
+  }
+}
+
+#define AU_HEADER_SIZE 24
+
+static GstFlowReturn
+gst_au_parse_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstAuParse *auparse;
+  gint avail, sendnow = 0;
+
+  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));
+
+  GST_LOG_OBJECT (auparse, "got buffer of size %u", GST_BUFFER_SIZE (buf));
+
+  gst_adapter_push (auparse->adapter, buf);
+  buf = NULL;
+
+  /* if we haven't seen any data yet... */
+  if (auparse->srcpad == NULL) {
+    if (gst_adapter_available (auparse->adapter) < AU_HEADER_SIZE) {
+      GST_DEBUG_OBJECT (auparse, "need more data to parse header");
+      ret = GST_FLOW_OK;
+      goto out;
+    }
+
+    ret = gst_au_parse_parse_header (auparse);
+    if (ret != GST_FLOW_OK)
+      goto out;
+
+    gst_pad_push_event (auparse->srcpad,
+        gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_DEFAULT,
+            0, GST_CLOCK_TIME_NONE, 0));
+  }
+
+  avail = gst_adapter_available (auparse->adapter);
+
+  if (auparse->sample_size > 0) {
+    /* Ensure we push a buffer that's a multiple of the frame size downstream */
+    sendnow = avail - (avail % auparse->sample_size);
+  } else {
+    /* It's something non-trivial (such as ADPCM), we don't understand it, so
+     * just push downstream and assume it will know what to do with it */
+    sendnow = avail;
+  }
+
+  if (sendnow > 0) {
+    GstBuffer *outbuf;
+    const guint8 *data;
+
+    ret = gst_pad_alloc_buffer_and_set_caps (auparse->srcpad,
+        auparse->buffer_offset, sendnow, GST_PAD_CAPS (auparse->srcpad),
+        &outbuf);
+
+    if (ret != GST_FLOW_OK) {
+      GST_DEBUG_OBJECT (auparse, "pad alloc flow: %s", gst_flow_get_name (ret));
+      goto out;
+    }
+
+    data = gst_adapter_peek (auparse->adapter, sendnow);
+    memcpy (GST_BUFFER_DATA (outbuf), data, sendnow);
+    gst_adapter_flush (auparse->adapter, sendnow);
+
+    auparse->buffer_offset += sendnow;
+
+    ret = gst_pad_push (auparse->srcpad, outbuf);
+  }
+
+out:
+
+  gst_object_unref (auparse);
+  return ret;
+}
+
+static gboolean
+gst_au_parse_src_convert (GstAuParse * auparse, GstFormat src_format,
+    gint64 srcval, GstFormat dest_format, gint64 * destval)
+{
+  gboolean ret = TRUE;
+  guint samplesize, rate;
+
+  if (dest_format == src_format) {
+    *destval = srcval;
+    return TRUE;
+  }
+
+  GST_OBJECT_LOCK (auparse);
+  samplesize = auparse->sample_size;
+  rate = auparse->samplerate;
+  GST_OBJECT_UNLOCK (auparse);
+
+  if (samplesize == 0 || rate == 0) {
+    GST_LOG_OBJECT (auparse, "cannot convert, sample_size or rate unknown");
+    return FALSE;
+  }
+
+  switch (src_format) {
+    case GST_FORMAT_BYTES:
+      srcval /= samplesize;
+      /* fallthrough */
+    case GST_FORMAT_DEFAULT:{
+      switch (dest_format) {
+        case GST_FORMAT_BYTES:
+          *destval = srcval * samplesize;
+          break;
+        case GST_FORMAT_TIME:
+          *destval = gst_util_uint64_scale_int (srcval, GST_SECOND, rate);
+          break;
+        default:
+          ret = FALSE;
+          break;
+      }
+      break;
+    }
+    case GST_FORMAT_TIME:{
+      switch (dest_format) {
+        case GST_FORMAT_BYTES:
+          *destval =
+              gst_util_uint64_scale_int (srcval, rate * samplesize, GST_SECOND);
+          break;
+        case GST_FORMAT_DEFAULT:
+          *destval = gst_util_uint64_scale_int (srcval, rate, GST_SECOND);
+          break;
+        default:
+          ret = FALSE;
+          break;
+      }
+      break;
+    }
+    default:{
+      ret = FALSE;
+      break;
+    }
+  }
+
+  if (!ret) {
+    GST_DEBUG_OBJECT (auparse, "could not convert from %s to %s format",
+        gst_format_get_name (src_format), gst_format_get_name (dest_format));
+  }
+
+  return ret;
+}
+
+static gboolean
+gst_au_parse_src_query (GstPad * pad, GstQuery * query)
+{
+  GstAuParse *auparse;
+  gboolean ret = FALSE;
+
+  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_DURATION:{
+      GstFormat bformat = GST_FORMAT_BYTES;
+      GstFormat format;
+      gint64 len, val;
+
+      gst_query_parse_duration (query, &format, NULL);
+      if (!gst_pad_query_peer_duration (auparse->sinkpad, &bformat, &len)) {
+        GST_DEBUG_OBJECT (auparse, "failed to query upstream length");
+        break;
+      }
+      GST_OBJECT_LOCK (auparse);
+      len -= auparse->offset;
+      GST_OBJECT_UNLOCK (auparse);
+
+      ret = gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, len,
+          format, &val);
+
+      if (ret) {
+        gst_query_set_duration (query, format, val);
+      }
+      break;
+    }
+    case GST_QUERY_POSITION:{
+      GstFormat bformat = GST_FORMAT_BYTES;
+      GstFormat format;
+      gint64 pos, val;
+
+      gst_query_parse_position (query, &format, NULL);
+      if (!gst_pad_query_peer_position (auparse->sinkpad, &bformat, &pos)) {
+        GST_DEBUG_OBJECT (auparse, "failed to query upstream position");
+        break;
+      }
+      GST_OBJECT_LOCK (auparse);
+      pos -= auparse->offset;
+      GST_OBJECT_UNLOCK (auparse);
+
+      ret = gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos,
+          format, &val);
+
+      if (ret) {
+        gst_query_set_position (query, format, val);
+      }
+      break;
+    }
+    default:
+      ret = gst_pad_query_default (pad, query);
+      break;
+  }
+
+  gst_object_unref (auparse);
+  return ret;
+}
+
+static gboolean
+gst_au_parse_handle_seek (GstAuParse * auparse, GstEvent * event)
+{
+  GstSeekType start_type, stop_type;
+  GstSeekFlags flags;
+  GstFormat format;
+  gdouble rate;
+  gint64 start, stop;
+
+  gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+      &stop_type, &stop);
+
+  if (format != GST_FORMAT_TIME) {
+    GST_DEBUG_OBJECT (auparse, "only support seeks in TIME format");
+    return FALSE;
+  }
+
+  /* FIXME: implement seeking */
+  return FALSE;
+}
+
+static gboolean
+gst_au_parse_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstAuParse *auparse;
+  gboolean ret;
+
+  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    default:
+      ret = gst_pad_event_default (pad, event);
+      break;
+  }
+
+  gst_object_unref (auparse);
+  return ret;
+}
+
+static gboolean
+gst_au_parse_src_event (GstPad * pad, GstEvent * event)
+{
+  GstAuParse *auparse;
+  gboolean ret;
+
+  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+      ret = gst_au_parse_handle_seek (auparse, event);
+      break;
+    default:
+      ret = gst_pad_event_default (pad, event);
+      break;
+  }
+
+  gst_object_unref (auparse);
+  return ret;
+}
+
+static GstStateChangeReturn
+gst_au_parse_change_state (GstElement * element, GstStateChange transition)
+{
+  GstAuParse *auparse = GST_AU_PARSE (element);
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+  ret = parent_class->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_au_parse_reset (auparse);
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "auparse", GST_RANK_SECONDARY,
+          GST_TYPE_AU_PARSE)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "auparse",
+    "parses au streams", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
+    GST_PACKAGE_ORIGIN)
+	
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+	return &gst_plugin_desc;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/auparse/gstauparse.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
+ *
+ * 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_AU_PARSE_H__
+#define __GST_AU_PARSE_H__
+
+
+#include "gst/gst.h"
+#include <gst/gst_global.h>
+#include <gst/base/gstadapter.h>
+
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AU_PARSE \
+  (gst_au_parse_get_type())
+#define GST_AU_PARSE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AU_PARSE,GstAuParse))
+#define GST_AU_PARSE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AU_PARSE,GstAuParseClass))
+#define GST_IS_AU_PARSE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AU_PARSE))
+#define GST_IS_AU_PARSE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AU_PARSE))
+
+typedef struct _GstAuParse GstAuParse;
+typedef struct _GstAuParseClass GstAuParseClass;
+
+struct _GstAuParse {
+  GstElement element;
+
+  GstPad     *sinkpad;
+  GstPad     *srcpad;
+
+  GstCaps    *src_caps;
+
+  GstAdapter *adapter;
+
+  /* GstSegment  segment; */
+
+  gint64      offset;        /* where sample data starts */
+  gint64      buffer_offset;
+  guint       sample_size;
+  guint       encoding;
+  guint       samplerate;
+  guint       endianness;
+  guint       channels;
+};
+
+struct _GstAuParseClass {
+  GstElementClass parent_class;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_au_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AU_PARSE_H__ */
--- a/gst_plugins_good/gst/autodetect/gstautoaudiosink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/autodetect/gstautoaudiosink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,19 +22,16 @@
  * SECTION:element-autoaudiosink
  * @see_also: autovideosink, alsasink, osssink
  *
- * <refsect2>
- * <para>
  * autoaudiosink is an audio sink that automatically detects an appropriate
  * audio sink to use.  It does so by scanning the registry for all elements
  * that have <quote>Sink</quote> and <quote>Audio</quote> in the class field
  * of their element information, and also have a non-zero autoplugging rank.
- * </para>
+ *
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v -m audiotestsrc ! audioconvert ! audioresample ! autoaudiosink
- * </programlisting>
- * </para>
+ * ]|
  * </refsect2>
  */
 
@@ -71,7 +68,7 @@
     "Sink/Audio",
     "Wrapper audio sink for automatically detected audio sink",
     "Ronald Bultje <rbultje@ronald.bitfreak.net>\n"
-    "Jan Schmidt <thaytan@noraisin.net");
+    "Jan Schmidt <thaytan@noraisin.net>");
 
 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -161,7 +158,7 @@
   gst_bin_add (GST_BIN (sink), sink->kid);
 
   /* pad */
-  targetpad = gst_element_get_pad (sink->kid, "sink");
+  targetpad = gst_element_get_static_pad (sink->kid, "sink");
   gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
   gst_object_unref (targetpad);
 }
@@ -349,9 +346,8 @@
 
   /* find element */
   GST_DEBUG_OBJECT (sink, "Creating new kid");
-  if (!(esink = gst_auto_audio_sink_find_best (sink))) {
-    return FALSE;
-  }
+  if (!(esink = gst_auto_audio_sink_find_best (sink)))
+    goto no_sink;
 
   sink->kid = esink;
   /* Ensure the child is brought up to the right state to match the parent
@@ -364,12 +360,29 @@
 
   /* attach ghost pad */
   GST_DEBUG_OBJECT (sink, "Re-assigning ghostpad");
-  targetpad = gst_element_get_pad (sink->kid, "sink");
-  gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
+  targetpad = gst_element_get_static_pad (sink->kid, "sink");
+  if (!gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad))
+    goto target_failed;
+
   gst_object_unref (targetpad);
   GST_DEBUG_OBJECT (sink, "done changing auto audio sink");
 
   return TRUE;
+
+  /* ERRORS */
+no_sink:
+  {
+    GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
+        ("Failed to find a supported audio sink"));
+    return FALSE;
+  }
+target_failed:
+  {
+    GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
+        ("Failed to set target pad"));
+    gst_object_unref (targetpad);
+    return FALSE;
+  }
 }
 
 static GstStateChangeReturn
--- a/gst_plugins_good/gst/autodetect/gstautoaudiosink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/autodetect/gstautoaudiosink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -49,11 +49,11 @@
 typedef struct _GstAutoAudioSinkClass {
   GstBinClass parent_class;
 } GstAutoAudioSinkClass;
+
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-
 GType   gst_auto_audio_sink_get_type    (void);
 
 G_END_DECLS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/autodetect/gstautoaudiosrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,453 @@
+/* GStreamer
+ * (c) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * (c) 2006 Jan Schmidt <thaytan@noraisin.net>
+ * (c) 2008 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-autoaudiosrc
+ * @see_also: autovideosrc, alsasrc, osssrc
+ *
+ * autoaudiosrc is an audio source that automatically detects an appropriate
+ * audio source to use.  It does so by scanning the registry for all elements
+ * that have <quote>Source</quote> and <quote>Audio</quote> in the class field
+ * of their element information, and also have a non-zero autoplugging rank.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v -m autoaudiosrc ! audioconvert ! audioresample ! autoaudiosink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstautoaudiosrc.h"
+#include "gstautodetect.h"
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_CAPS,
+};
+
+static GstStateChangeReturn
+gst_auto_audio_src_change_state (GstElement * element,
+    GstStateChange transition);
+static void gst_auto_audio_src_dispose (GstAutoAudioSrc * src);
+static void gst_auto_audio_src_clear_kid (GstAutoAudioSrc * src);
+static void gst_auto_audio_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_auto_audio_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+GST_BOILERPLATE (GstAutoAudioSrc, gst_auto_audio_src, GstBin, GST_TYPE_BIN);
+
+static const GstElementDetails gst_auto_audio_src_details =
+GST_ELEMENT_DETAILS ("Auto audio source",
+    "Source/Audio",
+    "Wrapper audio source for automatically detected audio source",
+    "Ronald Bultje <rbultje@ronald.bitfreak.net>\n"
+    "Jan Schmidt <thaytan@noraisin.net>\n"
+    "Stefan Kost <ensonic@users.sf.net>");
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static void
+gst_auto_audio_src_base_init (gpointer klass)
+{
+  GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (eklass,
+      gst_static_pad_template_get (&src_template));
+
+  gst_element_class_set_details (eklass, &gst_auto_audio_src_details);
+}
+
+static void
+gst_auto_audio_src_class_init (GstAutoAudioSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *eklass;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  eklass = GST_ELEMENT_CLASS (klass);
+
+  gobject_class->dispose =
+      (GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_auto_audio_src_dispose);
+  eklass->change_state = GST_DEBUG_FUNCPTR (gst_auto_audio_src_change_state);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_auto_audio_src_set_property);
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_auto_audio_src_get_property);
+
+  /**
+   * GstAutoAudioSrc:filter-caps
+   *
+   * This property will filter out candidate sinks that can handle the specified
+   * caps. By default only audio sinks that support raw floating point and
+   * integer audio are selected.
+   *
+   * This property can only be set before the element goes to the READY state.
+   *
+   * Since: 0.10.14
+   **/
+  g_object_class_install_property (gobject_class, PROP_CAPS,
+      g_param_spec_boxed ("filter-caps", "Filter caps",
+          "Filter sink candidates using these caps.", GST_TYPE_CAPS,
+          G_PARAM_READWRITE));
+}
+
+static void
+gst_auto_audio_src_dispose (GstAutoAudioSrc * sink)
+{
+  gst_auto_audio_src_clear_kid (sink);
+
+  if (sink->filter_caps)
+    gst_caps_unref (sink->filter_caps);
+  sink->filter_caps = NULL;
+
+  G_OBJECT_CLASS (parent_class)->dispose ((GObject *) sink);
+}
+
+static void
+gst_auto_audio_src_clear_kid (GstAutoAudioSrc * sink)
+{
+  if (sink->kid) {
+    gst_element_set_state (sink->kid, GST_STATE_NULL);
+    gst_bin_remove (GST_BIN (sink), sink->kid);
+    sink->kid = NULL;
+  }
+}
+
+/*
+ * Hack to make initial linking work; ideally, this'd work even when
+ * no target has been assigned to the ghostpad yet.
+ */
+static void
+gst_auto_audio_src_reset (GstAutoAudioSrc * src)
+{
+  GstPad *targetpad;
+
+  gst_auto_audio_src_clear_kid (src);
+
+  /* fakesink placeholder */
+  src->kid = gst_element_factory_make ("fakesrc", "tempsrc");
+  gst_bin_add (GST_BIN (src), src->kid);
+
+  /* pad */
+  targetpad = gst_element_get_static_pad (src->kid, "src");
+  gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
+  gst_object_unref (targetpad);
+}
+
+static GstStaticCaps raw_caps =
+    GST_STATIC_CAPS ("audio/x-raw-int; audio/x-raw-float");
+
+static void
+gst_auto_audio_src_init (GstAutoAudioSrc * src, GstAutoAudioSrcClass * g_class)
+{
+  src->pad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
+  gst_element_add_pad (GST_ELEMENT (src), src->pad);
+
+  gst_auto_audio_src_reset (src);
+
+  /* set the default raw audio caps */
+  src->filter_caps = gst_static_caps_get (&raw_caps);
+
+  /* mark as source */
+  GST_OBJECT_FLAG_UNSET (src, GST_ELEMENT_IS_SINK);
+}
+
+static gboolean
+gst_auto_audio_src_factory_filter (GstPluginFeature * feature, gpointer data)
+{
+  guint rank;
+  const gchar *klass;
+
+  /* we only care about element factories */
+  if (!GST_IS_ELEMENT_FACTORY (feature))
+    return FALSE;
+
+  /* audio sinks */
+  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
+  if (!(strstr (klass, "Source") && strstr (klass, "Audio")))
+    return FALSE;
+
+  /* only select elements with autoplugging rank */
+  rank = gst_plugin_feature_get_rank (feature);
+  if (rank < GST_RANK_MARGINAL)
+    return FALSE;
+
+  return TRUE;
+}
+
+static gint
+gst_auto_audio_src_compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
+{
+  gint diff;
+
+  diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
+  if (diff != 0)
+    return diff;
+  return strcmp (gst_plugin_feature_get_name (f2),
+      gst_plugin_feature_get_name (f1));
+}
+
+static GstElement *
+gst_auto_audio_src_create_element_with_pretty_name (GstAutoAudioSrc * src,
+    GstElementFactory * factory)
+{
+  GstElement *element;
+  gchar *name, *marker;
+
+  marker = g_strdup (GST_PLUGIN_FEATURE (factory)->name);
+  if (g_str_has_suffix (marker, "src"))
+    marker[strlen (marker) - 4] = '\0';
+  if (g_str_has_prefix (marker, "gst"))
+    g_memmove (marker, marker + 3, strlen (marker + 3) + 1);
+  name = g_strdup_printf ("%s-actual-src-%s", GST_OBJECT_NAME (src), marker);
+  g_free (marker);
+
+  element = gst_element_factory_create (factory, name);
+  g_free (name);
+
+  return element;
+}
+
+static GstElement *
+gst_auto_audio_src_find_best (GstAutoAudioSrc * src)
+{
+  GList *list, *item;
+  GstElement *choice = NULL;
+  GstMessage *message = NULL;
+  GSList *errors = NULL;
+  GstBus *bus = gst_bus_new ();
+  GstPad *el_pad = NULL;
+  GstCaps *el_caps = NULL, *intersect = NULL;
+  gboolean no_match = TRUE;
+
+  list = gst_registry_feature_filter (gst_registry_get_default (),
+      (GstPluginFeatureFilter) gst_auto_audio_src_factory_filter, FALSE, src);
+  list = g_list_sort (list, (GCompareFunc) gst_auto_audio_src_compare_ranks);
+
+  /* We don't treat sound server sources special. Our policy is that sound
+   * server sources that have a rank must not auto-spawn a daemon under any
+   * circumstances, so there's nothing for us to worry about here */
+  GST_LOG_OBJECT (src, "Trying to find usable audio devices ...");
+
+  for (item = list; item != NULL; item = item->next) {
+    GstElementFactory *f = GST_ELEMENT_FACTORY (item->data);
+    GstElement *el;
+
+    if ((el = gst_auto_audio_src_create_element_with_pretty_name (src, f))) {
+      GstStateChangeReturn ret;
+
+      GST_DEBUG_OBJECT (src, "Testing %s", GST_PLUGIN_FEATURE (f)->name);
+
+      /* If autoAudioSrc has been provided with filter caps,
+       * accept only sources that match with the filter caps */
+      if (src->filter_caps) {
+        el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "src");
+        el_caps = gst_pad_get_caps (el_pad);
+        gst_object_unref (el_pad);
+        GST_DEBUG_OBJECT (src,
+            "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT,
+            src->filter_caps, el_caps);
+        intersect = gst_caps_intersect (src->filter_caps, el_caps);
+        no_match = gst_caps_is_empty (intersect);
+        gst_caps_unref (el_caps);
+        gst_caps_unref (intersect);
+
+        if (no_match) {
+          GST_DEBUG_OBJECT (src, "Incompatible caps");
+          gst_object_unref (el);
+          continue;
+        } else {
+          GST_DEBUG_OBJECT (src, "Found compatible caps");
+        }
+      }
+
+      gst_element_set_bus (el, bus);
+      ret = gst_element_set_state (el, GST_STATE_READY);
+      if (ret == GST_STATE_CHANGE_SUCCESS) {
+        GST_DEBUG_OBJECT (src, "This worked!");
+        choice = el;
+        break;
+      }
+
+      /* collect all error messages */
+      while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) {
+        GST_DEBUG_OBJECT (src, "error message %" GST_PTR_FORMAT, message);
+        errors = g_slist_append (errors, message);
+      }
+
+      gst_element_set_state (el, GST_STATE_NULL);
+      gst_object_unref (el);
+    }
+  }
+
+  GST_DEBUG_OBJECT (src, "done trying");
+  if (!choice) {
+    if (errors) {
+      /* FIXME: we forward the first error for now; but later on it might make
+       * sense to actually analyse them */
+      gst_message_ref (GST_MESSAGE (errors->data));
+      GST_DEBUG_OBJECT (src, "reposting message %p", errors->data);
+      gst_element_post_message (GST_ELEMENT (src), GST_MESSAGE (errors->data));
+    } else {
+      /* send warning message to application and use a fakesrc */
+      GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL),
+          ("Failed to find a usable audio source"));
+      choice = gst_element_factory_make ("fakesrc", "fake-audio-src");
+      if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync"))
+        g_object_set (choice, "sync", TRUE, NULL);
+      gst_element_set_state (choice, GST_STATE_READY);
+    }
+  }
+  gst_object_unref (bus);
+  gst_plugin_feature_list_free (list);
+  g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL);
+  g_slist_free (errors);
+
+  return choice;
+}
+
+static gboolean
+gst_auto_audio_src_detect (GstAutoAudioSrc * src)
+{
+  GstElement *esrc;
+  GstPad *targetpad;
+
+  gst_auto_audio_src_clear_kid (src);
+
+  /* find element */
+  GST_DEBUG_OBJECT (src, "Creating new kid");
+  if (!(esrc = gst_auto_audio_src_find_best (src)))
+    goto no_src;
+
+  src->kid = esrc;
+  /* Ensure the child is brought up to the right state to match the parent
+   * although it's currently always in READY and 
+   * we're always doing NULL->READY. */
+  if (GST_STATE (src->kid) < GST_STATE (src))
+    gst_element_set_state (src->kid, GST_STATE (src));
+
+  gst_bin_add (GST_BIN (src), esrc);
+
+  /* attach ghost pad */
+  GST_DEBUG_OBJECT (src, "Re-assigning ghostpad");
+  targetpad = gst_element_get_static_pad (src->kid, "src");
+  if (!gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad))
+    goto target_failed;
+
+  gst_object_unref (targetpad);
+  GST_DEBUG_OBJECT (src, "done changing auto audio source");
+
+  return TRUE;
+
+  /* ERRORS */
+no_src:
+  {
+    GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
+        ("Failed to find a supported audio source"));
+    return FALSE;
+  }
+target_failed:
+  {
+    GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
+        ("Failed to set target pad"));
+    gst_object_unref (targetpad);
+    return FALSE;
+  }
+}
+
+static GstStateChangeReturn
+gst_auto_audio_src_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstAutoAudioSrc *src = GST_AUTO_AUDIO_SRC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      if (!gst_auto_audio_src_detect (src))
+        return GST_STATE_CHANGE_FAILURE;
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      gst_auto_audio_src_reset (src);
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static void
+gst_auto_audio_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAutoAudioSrc *src = GST_AUTO_AUDIO_SRC (object);
+
+  switch (prop_id) {
+    case PROP_CAPS:
+      if (src->filter_caps)
+        gst_caps_unref (src->filter_caps);
+      src->filter_caps = gst_caps_copy (gst_value_get_caps (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_auto_audio_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAutoAudioSrc *src = GST_AUTO_AUDIO_SRC (object);
+
+  switch (prop_id) {
+    case PROP_CAPS:{
+      gst_value_set_caps (value, src->filter_caps);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/autodetect/gstautoaudiosrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,61 @@
+/* GStreamer
+ * (c) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * (c) 2008 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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_AUTO_AUDIO_SRC_H__
+#define __GST_AUTO_AUDIO_SRC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUTO_AUDIO_SRC \
+  (gst_auto_audio_src_get_type ())
+#define GST_AUTO_AUDIO_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AUTO_AUDIO_SRC, \
+                               GstAutoAudioSrc))
+#define GST_AUTO_AUDIO_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AUTO_AUDIO_SRC, \
+                            GstAutoAudioSrcClass))
+#define GST_IS_AUTO_AUDIO_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_AUTO_AUDIO_SRC))
+#define GST_IS_AUTO_AUDIO_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_AUTO_AUDIO_SRC))
+
+typedef struct _GstAutoAudioSrc {
+  GstBin parent;
+
+  /* explicit pointers to stuff used */
+  GstPad *pad;
+  GstElement *kid;
+  GstCaps *filter_caps;
+} GstAutoAudioSrc;
+
+typedef struct _GstAutoAudioSrcClass {
+  GstBinClass parent_class;
+} GstAutoAudioSrcClass;
+
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+GType   gst_auto_audio_src_get_type    (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUTO_AUDIO_SRC_H__ */
--- a/gst_plugins_good/gst/autodetect/gstautodetect.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/autodetect/gstautodetect.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,7 +25,9 @@
 
 #include "gstautodetect.h"
 #include "gstautoaudiosink.h"
+#include "gstautoaudiosrc.h"
 #include "gstautovideosink.h"
+#include "gstautovideosrc.h"
 
 GST_DEBUG_CATEGORY (autodetect_debug);
 
@@ -37,14 +39,18 @@
 
   return gst_element_register (plugin, "autovideosink",
       GST_RANK_NONE, GST_TYPE_AUTO_VIDEO_SINK) &&
+      gst_element_register (plugin, "autovideosrc",
+      GST_RANK_NONE, GST_TYPE_AUTO_VIDEO_SRC) &&
       gst_element_register (plugin, "autoaudiosink",
-      GST_RANK_NONE, GST_TYPE_AUTO_AUDIO_SINK);
+      GST_RANK_NONE, GST_TYPE_AUTO_AUDIO_SINK) &&
+      gst_element_register (plugin, "autoaudiosrc",
+      GST_RANK_NONE, GST_TYPE_AUTO_AUDIO_SRC);
 }
 
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "autodetect",
-    "Plugin contains auto-detection plugins for video/audio outputs",
+    "Plugin contains auto-detection plugins for video/audio in- and outputs",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
 
 #ifdef __SYMBIAN32__
--- a/gst_plugins_good/gst/autodetect/gstautovideosink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/autodetect/gstautovideosink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,19 +22,16 @@
  * SECTION:element-autovideosink
  * @see_also: autoaudiosink, ximagesink, xvimagesink, sdlvideosink
  *
- * <refsect2>
- * <para>
  * autovideosink is a video sink that automatically detects an appropriate
  * video sink to use.  It does so by scanning the registry for all elements
  * that have <quote>Sink</quote> and <quote>Video</quote> in the class field
  * of their element information, and also have a non-zero autoplugging rank.
- * </para>
+ *
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v -m videotestsrc ! autovideosink
- * </programlisting>
- * </para>
+ * ]|
  * </refsect2>
  */
 
@@ -72,7 +69,7 @@
     "Sink/Video",
     "Wrapper video sink for automatically detected video sink",
     "Ronald Bultje <rbultje@ronald.bitfreak.net>\n"
-    "Jan Schmidt <thaytan@noraisin.net");
+    "Jan Schmidt <thaytan@noraisin.net>");
 
 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -160,8 +157,8 @@
   sink->kid = gst_element_factory_make ("fakesink", "tempsink");
   gst_bin_add (GST_BIN (sink), sink->kid);
 
-  /* pad */
-  targetpad = gst_element_get_pad (sink->kid, "sink");
+  /* pad, setting this target should always work */
+  targetpad = gst_element_get_static_pad (sink->kid, "sink");
   gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
   gst_object_unref (targetpad);
 }
@@ -354,8 +351,10 @@
 
   /* attach ghost pad */
   GST_DEBUG_OBJECT (sink, "Re-assigning ghostpad");
-  targetpad = gst_element_get_pad (sink->kid, "sink");
-  gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
+  targetpad = gst_element_get_static_pad (sink->kid, "sink");
+  if (!gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad))
+    goto target_failed;
+
   gst_object_unref (targetpad);
   GST_DEBUG_OBJECT (sink, "done changing auto video sink");
 
@@ -368,6 +367,13 @@
         ("Failed to find a supported video sink"));
     return FALSE;
   }
+target_failed:
+  {
+    GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
+        ("Failed to set target pad"));
+    gst_object_unref (targetpad);
+    return FALSE;
+  }
 }
 
 static GstStateChangeReturn
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/autodetect/gstautovideosrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,442 @@
+/* GStreamer
+ * (c) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * (c) 2006 Jan Schmidt <thaytan@noraisin.net>
+ * (c) 2008 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-autovideosrc
+ * @see_also: autoaudiosrc, v4l2src, v4lsrc
+ *
+ * autovideosrc is a video src that automatically detects an appropriate
+ * video source to use.  It does so by scanning the registry for all elements
+ * that have <quote>Source</quote> and <quote>Video</quote> in the class field
+ * of their element information, and also have a non-zero autoplugging rank.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v -m autovideosrc ! xvimagesink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstautovideosrc.h"
+#include "gstautodetect.h"
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_CAPS,
+};
+
+static GstStateChangeReturn
+gst_auto_video_src_change_state (GstElement * element,
+    GstStateChange transition);
+static void gst_auto_video_src_dispose (GstAutoVideoSrc * src);
+static void gst_auto_video_src_clear_kid (GstAutoVideoSrc * src);
+
+static void gst_auto_video_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_auto_video_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+GST_BOILERPLATE (GstAutoVideoSrc, gst_auto_video_src, GstBin, GST_TYPE_BIN);
+
+static const GstElementDetails gst_auto_video_src_details =
+GST_ELEMENT_DETAILS ("Auto video source",
+    "Source/Video",
+    "Wrapper video source for automatically detected video source",
+    "Ronald Bultje <rbultje@ronald.bitfreak.net>\n"
+    "Jan Schmidt <thaytan@noraisin.net>\n"
+    "Stefan Kost <ensonic@users.sf.net>");
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static void
+gst_auto_video_src_base_init (gpointer klass)
+{
+  GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (eklass,
+      gst_static_pad_template_get (&src_template));
+  gst_element_class_set_details (eklass, &gst_auto_video_src_details);
+}
+
+static void
+gst_auto_video_src_class_init (GstAutoVideoSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->dispose =
+      (GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_auto_video_src_dispose);
+  eklass->change_state = GST_DEBUG_FUNCPTR (gst_auto_video_src_change_state);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_auto_video_src_set_property);
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_auto_video_src_get_property);
+
+  /**
+   * GstAutoVideoSrc:filter-caps
+   *
+   * This property will filter out candidate sources that can handle the specified
+   * caps. By default only video sources that support raw rgb and yuv video
+   * are selected.
+   *
+   * This property can only be set before the element goes to the READY state.
+   *
+   * Since: 0.10.14
+   **/
+  g_object_class_install_property (gobject_class, PROP_CAPS,
+      g_param_spec_boxed ("filter-caps", "Filter caps",
+          "Filter src candidates using these caps.", GST_TYPE_CAPS,
+          G_PARAM_READWRITE));
+}
+
+static void
+gst_auto_video_src_dispose (GstAutoVideoSrc * src)
+{
+  gst_auto_video_src_clear_kid (src);
+
+  if (src->filter_caps)
+    gst_caps_unref (src->filter_caps);
+  src->filter_caps = NULL;
+
+  G_OBJECT_CLASS (parent_class)->dispose ((GObject *) src);
+}
+
+static void
+gst_auto_video_src_clear_kid (GstAutoVideoSrc * src)
+{
+  if (src->kid) {
+    gst_element_set_state (src->kid, GST_STATE_NULL);
+    gst_bin_remove (GST_BIN (src), src->kid);
+    src->kid = NULL;
+  }
+}
+
+/*
+ * Hack to make initial linking work; ideally, this'd work even when
+ * no target has been assigned to the ghostpad yet.
+ */
+
+static void
+gst_auto_video_src_reset (GstAutoVideoSrc * src)
+{
+  GstPad *targetpad;
+
+  /* Remove any existing element */
+  gst_auto_video_src_clear_kid (src);
+
+  /* fakesrc placeholder */
+  src->kid = gst_element_factory_make ("fakesrc", "tempsrc");
+  gst_bin_add (GST_BIN (src), src->kid);
+
+  /* pad */
+  targetpad = gst_element_get_static_pad (src->kid, "src");
+  gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
+  gst_object_unref (targetpad);
+}
+
+static GstStaticCaps raw_caps =
+    GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb");
+
+static void
+gst_auto_video_src_init (GstAutoVideoSrc * src, GstAutoVideoSrcClass * g_class)
+{
+  src->pad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
+  gst_element_add_pad (GST_ELEMENT (src), src->pad);
+
+  gst_auto_video_src_reset (src);
+
+  /* set the default raw video caps */
+  src->filter_caps = gst_static_caps_get (&raw_caps);
+
+  /* mark as source */
+  GST_OBJECT_FLAG_UNSET (src, GST_ELEMENT_IS_SINK);
+}
+
+static gboolean
+gst_auto_video_src_factory_filter (GstPluginFeature * feature, gpointer data)
+{
+  guint rank;
+  const gchar *klass;
+
+  /* we only care about element factories */
+  if (!GST_IS_ELEMENT_FACTORY (feature))
+    return FALSE;
+
+  /* video sources */
+  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
+  if (!(strstr (klass, "Source") && strstr (klass, "Video")))
+    return FALSE;
+
+  /* only select elements with autoplugging rank */
+  rank = gst_plugin_feature_get_rank (feature);
+  if (rank < GST_RANK_MARGINAL)
+    return FALSE;
+
+  return TRUE;
+}
+
+static gint
+gst_auto_video_src_compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
+{
+  gint diff;
+
+  diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
+  if (diff != 0)
+    return diff;
+  return strcmp (gst_plugin_feature_get_name (f2),
+      gst_plugin_feature_get_name (f1));
+}
+
+static GstElement *
+gst_auto_video_src_create_element_with_pretty_name (GstAutoVideoSrc * src,
+    GstElementFactory * factory)
+{
+  GstElement *element;
+  gchar *name, *marker;
+
+  marker = g_strdup (GST_PLUGIN_FEATURE (factory)->name);
+  if (g_str_has_suffix (marker, "src"))
+    marker[strlen (marker) - 4] = '\0';
+  if (g_str_has_prefix (marker, "gst"))
+    g_memmove (marker, marker + 3, strlen (marker + 3) + 1);
+  name = g_strdup_printf ("%s-actual-src-%s", GST_OBJECT_NAME (src), marker);
+  g_free (marker);
+
+  element = gst_element_factory_create (factory, name);
+  g_free (name);
+
+  return element;
+}
+
+static GstElement *
+gst_auto_video_src_find_best (GstAutoVideoSrc * src)
+{
+  GList *list, *item;
+  GstElement *choice = NULL;
+  GstMessage *message = NULL;
+  GSList *errors = NULL;
+  GstBus *bus = gst_bus_new ();
+  GstPad *el_pad = NULL;
+  GstCaps *el_caps = NULL, *intersect = NULL;
+  gboolean no_match = TRUE;
+
+  list = gst_registry_feature_filter (gst_registry_get_default (),
+      (GstPluginFeatureFilter) gst_auto_video_src_factory_filter, FALSE, src);
+  list = g_list_sort (list, (GCompareFunc) gst_auto_video_src_compare_ranks);
+
+  GST_LOG_OBJECT (src, "Trying to find usable video devices ...");
+
+  for (item = list; item != NULL; item = item->next) {
+    GstElementFactory *f = GST_ELEMENT_FACTORY (item->data);
+    GstElement *el;
+
+    if ((el = gst_auto_video_src_create_element_with_pretty_name (src, f))) {
+      GstStateChangeReturn ret;
+
+      GST_DEBUG_OBJECT (src, "Testing %s", GST_PLUGIN_FEATURE (f)->name);
+
+      /* If AutoVideoSrc has been provided with filter caps,
+       * accept only sources that match with the filter caps */
+      if (src->filter_caps) {
+        el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "src");
+        el_caps = gst_pad_get_caps (el_pad);
+        gst_object_unref (el_pad);
+        GST_DEBUG_OBJECT (src,
+            "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT,
+            src->filter_caps, el_caps);
+        intersect = gst_caps_intersect (src->filter_caps, el_caps);
+        no_match = gst_caps_is_empty (intersect);
+        gst_caps_unref (el_caps);
+        gst_caps_unref (intersect);
+
+        if (no_match) {
+          GST_DEBUG_OBJECT (src, "Incompatible caps");
+          gst_object_unref (el);
+          continue;
+        } else {
+          GST_DEBUG_OBJECT (src, "Found compatible caps");
+        }
+      }
+
+      gst_element_set_bus (el, bus);
+      ret = gst_element_set_state (el, GST_STATE_READY);
+      if (ret == GST_STATE_CHANGE_SUCCESS) {
+        GST_DEBUG_OBJECT (src, "This worked!");
+        choice = el;
+        break;
+      }
+
+      /* collect all error messages */
+      while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) {
+        GST_DEBUG_OBJECT (src, "error message %" GST_PTR_FORMAT, message);
+        errors = g_slist_append (errors, message);
+      }
+
+      gst_element_set_state (el, GST_STATE_NULL);
+      gst_object_unref (el);
+    }
+  }
+
+  GST_DEBUG_OBJECT (src, "done trying");
+  if (!choice) {
+    if (errors) {
+      /* FIXME: we forward the first error for now; but later on it might make
+       * sense to actually analyse them */
+      gst_message_ref (GST_MESSAGE (errors->data));
+      GST_DEBUG_OBJECT (src, "reposting message %p", errors->data);
+      gst_element_post_message (GST_ELEMENT (src), GST_MESSAGE (errors->data));
+    } else {
+      /* send warning message to application and use a fakesrc */
+      GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL),
+          ("Failed to find a usable video source"));
+      choice = gst_element_factory_make ("fakesrc", "fake-video-src");
+      if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync"))
+        g_object_set (choice, "sync", TRUE, NULL);
+      gst_element_set_state (choice, GST_STATE_READY);
+    }
+  }
+  gst_object_unref (bus);
+  gst_plugin_feature_list_free (list);
+  g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL);
+  g_slist_free (errors);
+
+  return choice;
+}
+
+static gboolean
+gst_auto_video_src_detect (GstAutoVideoSrc * src)
+{
+  GstElement *esrc;
+  GstPad *targetpad;
+
+  gst_auto_video_src_clear_kid (src);
+
+  /* find element */
+  GST_DEBUG_OBJECT (src, "Creating new kid");
+  if (!(esrc = gst_auto_video_src_find_best (src)))
+    goto no_src;
+
+  src->kid = esrc;
+  gst_bin_add (GST_BIN (src), esrc);
+
+  /* attach ghost pad */
+  GST_DEBUG_OBJECT (src, "Re-assigning ghostpad");
+  targetpad = gst_element_get_static_pad (src->kid, "src");
+  if (!gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad))
+    goto target_failed;
+
+  gst_object_unref (targetpad);
+  GST_DEBUG_OBJECT (src, "done changing auto video source");
+
+  return TRUE;
+
+  /* ERRORS */
+no_src:
+  {
+    GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
+        ("Failed to find a supported video source"));
+    return FALSE;
+  }
+target_failed:
+  {
+    GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
+        ("Failed to set target pad"));
+    gst_object_unref (targetpad);
+    return FALSE;
+  }
+}
+
+static GstStateChangeReturn
+gst_auto_video_src_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstAutoVideoSrc *src = GST_AUTO_VIDEO_SRC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      if (!gst_auto_video_src_detect (src))
+        return GST_STATE_CHANGE_FAILURE;
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      gst_auto_video_src_reset (src);
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static void
+gst_auto_video_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAutoVideoSrc *src = GST_AUTO_VIDEO_SRC (object);
+
+  switch (prop_id) {
+    case PROP_CAPS:
+      if (src->filter_caps)
+        gst_caps_unref (src->filter_caps);
+      src->filter_caps = gst_caps_copy (gst_value_get_caps (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_auto_video_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAutoVideoSrc *src = GST_AUTO_VIDEO_SRC (object);
+
+  switch (prop_id) {
+    case PROP_CAPS:{
+      gst_value_set_caps (value, src->filter_caps);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/autodetect/gstautovideosrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,61 @@
+/* GStreamer
+ * (c) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * (c) 2008 Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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_AUTO_VIDEO_SRC_H__
+#define __GST_AUTO_VIDEO_SRC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUTO_VIDEO_SRC \
+  (gst_auto_video_src_get_type ())
+#define GST_AUTO_VIDEO_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AUTO_VIDEO_SRC, \
+                               GstAutoVideoSrc))
+#define GST_AUTO_VIDEO_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AUTO_VIDEO_SRC, \
+                            GstAutoVideoSrcClass))
+#define GST_IS_AUTO_VIDEO_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_AUTO_VIDEO_SRC))
+#define GST_IS_AUTO_VIDEO_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_AUTO_VIDEO_SRC))
+
+typedef struct _GstAutoVideoSrc {
+  GstBin parent;
+
+  /* explicit pointers to stuff used */
+  GstPad *pad;
+  GstElement *kid;
+  GstCaps *filter_caps;
+} GstAutoVideoSrc;
+
+typedef struct _GstAutoVideoSrcClass {
+  GstBinClass parent_class;
+} GstAutoVideoSrcClass;
+
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+GType   gst_auto_video_src_get_type    (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUTO_VIDEO_SRC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/README	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,72 @@
+The avi decoder plugins
+-----------------------
+
+The avi decoder consists of a set of gstreamer plugins:
+
+ - demuxer (avidemux)
+ - avi to gstreamer type converter (avitypes)
+ - windows dlls wrappers.
+
+the avidecoder element uses the above plugins to perform the avi
+decoding. It is constructed as a custom bin which initially only has
+the demuxer element in it. The demuxer has a set of padtemplates for
+raw audio and video.
+
+  (------------------------------------)
+  ! avidecoder                         !
+  !                                 (video/raw)...
+  !     (----------)                   !
+  !     ! demuxer (video/x-msvideo, auds)..
+  !     !          !                   !
+  !   -src         !                   !
+  !  /  !         (video/x-msvideo, vids)..
+ - src  !          !                   !
+  !     (----------)                (audio/raw)...
+  !                                    !
+  (------------------------------------)
+
+the demuxer has a set of padtemplates for the raw avi header properties.
+
+The avi decoder will act on the new_pad signal of the demuxer element
+and will attach an avitype plugin to the new pad. Caps negotiation will
+convert the raw avi caps to the gstreamer caps. If the src pad of the
+avitypes plugin are compatible with the avidecoder padtemplate, the 
+avitype pad is ghosted to the avidecoder bin, this is the case where no
+codec is needed (for raw PCM samples, for example).
+
+When the avitypes caps are not compatible with one of the avidecoder 
+templates, a static autoplugger is used the find an element to connect
+the demuxers pad to the decoders padtemplate.
+
+When no element could be found, an windec plugin is attached to the 
+demuxers pad and the avitypes plugin is removed from the decoder.
+
+
+example:
+--------
+
+ An avidecoder that has a video pad (decoded with windows dlls) and an
+ audio pad (raw PCM).
+
+  (----------------------------------------------------------------)
+  ! avidecoder               (--------)    (------)                !
+  !                          !avitypes!    !windec!       /-- (video/raw)
+  !     (----------)     /-sink      src--sink   src -----         !
+  !     !demuxer (video/x-msvideo,    !    !      !                !
+  !     !          ! auds).. (--------)    (------)                !  
+  !   -sink        !         (--------)                            !
+  !  /  !        (video/x-..,!avitypes!                            !
+ -sink  !          ! vids).. !        !                            !
+  !     (----------)     \-sink      src -------------------- (audio/raw)
+  !                          (--------)                            !
+  (----------------------------------------------------------------)
+
+
+
+TODO
+----
+
+automatically generate the padtemplates from all possible avi types
+found in the registry.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/avi-ids.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,77 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_AVI_H__
+#define __GST_AVI_H__
+
+#include <gst/gst.h>
+
+typedef struct _gst_riff_avih {
+  guint32 us_frame;          /* microsec per frame */
+  guint32 max_bps;           /* byte/s overall */
+  guint32 pad_gran;          /* pad_granularity */
+  guint32 flags;
+/* flags values */
+#define GST_RIFF_AVIH_HASINDEX       0x00000010 /* has idx1 chunk */
+#define GST_RIFF_AVIH_MUSTUSEINDEX   0x00000020 /* must use idx1 chunk to determine order */
+#define GST_RIFF_AVIH_ISINTERLEAVED  0x00000100 /* AVI file is interleaved */
+#define GST_RIFF_AVIH_WASCAPTUREFILE 0x00010000 /* specially allocated used for capturing real time video */
+#define GST_RIFF_AVIH_COPYRIGHTED    0x00020000 /* contains copyrighted data */
+  guint32 tot_frames;        /* # of frames (all) */
+  guint32 init_frames;       /* initial frames (???) */
+  guint32 streams;
+  guint32 bufsize;           /* suggested buffer size */
+  guint32 width;
+  guint32 height;
+  guint32 scale;
+  guint32 rate;
+  guint32 start;
+  guint32 length;
+} gst_riff_avih;
+
+/* vprp (video properties) ODML header */
+/* see ODML spec for some/more explanation */
+#define GST_RIFF_TAG_vprp GST_MAKE_FOURCC ('v','p','r','p')
+#define GST_RIFF_VPRP_VIDEO_FIELDS        (2)
+
+typedef struct _gst_riff_vprp_video_field_desc {
+  guint32 compressed_bm_height;
+  guint32 compressed_bm_width;
+  guint32 valid_bm_height;
+  guint32 valid_bm_width;
+  guint32 valid_bm_x_offset;
+  guint32 valid_bm_y_offset;
+  guint32 video_x_t_offset;
+  guint32 video_y_start;
+} gst_riff_vprp_video_field_desc;
+
+typedef struct _gst_riff_vprp {
+  guint32 format_token;      /* whether fields defined by standard */
+  guint32 standard;          /* video display standard, UNKNOWN, PAL, etc */
+  guint32 vert_rate;         /* vertical refresh rate */
+  guint32 hor_t_total;       /* width */
+  guint32 vert_lines;        /* height */
+  guint32 aspect;            /* aspect ratio high word:low word */
+  guint32 width;             /* active width */
+  guint32 height;            /* active height */
+  guint32 fields;            /* field count */
+  gst_riff_vprp_video_field_desc field_info[GST_RIFF_VPRP_VIDEO_FIELDS];
+} gst_riff_vprp;
+
+#endif /* __GST_AVI_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavi.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,67 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
+ *
+ * gstavi.c: plugin registering
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst/gst-i18n-plugin.h"
+
+#include "gstavidemux.h"
+#include "gstavimux.h"
+#include "gstavisubtitle.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  gst_riff_init ();
+
+#ifdef ENABLE_NLS
+  setlocale (LC_ALL, "");
+  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif /* ENABLE_NLS */
+
+  if (!gst_element_register (plugin, "avidemux", GST_RANK_PRIMARY,
+          GST_TYPE_AVI_DEMUX) ||
+      !gst_element_register (plugin, "avimux", GST_RANK_PRIMARY,
+          GST_TYPE_AVI_MUX) ||
+      !gst_element_register (plugin, "avisubtitle", GST_RANK_PRIMARY,
+          GST_TYPE_AVI_SUBTITLE)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "avi",
+    "AVI stream handling",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+#ifdef SYMBIAN
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+    return &gst_plugin_desc;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavidemux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4574 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
+ * Copyright (C) <2006> Nokia Corporation (contact <stefan.kost@nokia.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.
+ */
+/* Element-Checklist-Version: 5 */
+
+/**
+ * SECTION:element-avidemux
+ *
+ * Demuxes an .avi file into raw or compressed audio and/or video streams.
+ *
+ * This element supports both push and pull-based scheduling, depending on the
+ * capabilities of the upstream elements.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=test.avi ! avidemux name=demux  demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
+ * ]| Play (parse and decode) an .avi file and try to output it to
+ * an automatically detected soundcard and videosink. If the AVI file contains
+ * compressed audio or video data, this will only work if you have the
+ * right decoder elements/plugins installed.
+ * </refsect2>
+ *
+ * Last reviewed on 2006-12-29 (0.10.6)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gst/riff/riff-media.h"
+#include "gstavidemux.h"
+#include "avi-ids.h"
+#include <gst/gst-i18n-plugin.h>
+#include <gst/base/gstadapter.h>
+
+GST_DEBUG_CATEGORY_STATIC (avidemux_debug);
+#define GST_CAT_DEFAULT avidemux_debug
+
+GST_DEBUG_CATEGORY_EXTERN (GST_CAT_EVENT);
+
+static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-msvideo")
+    );
+
+static void gst_avi_demux_base_init (GstAviDemuxClass * klass);
+static void gst_avi_demux_class_init (GstAviDemuxClass * klass);
+static void gst_avi_demux_init (GstAviDemux * avi);
+static void gst_avi_demux_finalize (GObject * object);
+
+static void gst_avi_demux_reset (GstAviDemux * avi);
+
+#if 0
+static const GstEventMask *gst_avi_demux_get_event_mask (GstPad * pad);
+#endif
+static gboolean gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_avi_demux_handle_sink_event (GstPad * pad,
+    GstEvent * event);
+static gboolean gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event);
+
+#if 0
+static const GstFormat *gst_avi_demux_get_src_formats (GstPad * pad);
+#endif
+static const GstQueryType *gst_avi_demux_get_src_query_types (GstPad * pad);
+static gboolean gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_avi_demux_src_convert (GstPad * pad, GstFormat src_format,
+    gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
+
+static gboolean gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment);
+static gboolean gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad,
+    GstEvent * event);
+static void gst_avi_demux_loop (GstPad * pad);
+static gboolean gst_avi_demux_sink_activate (GstPad * sinkpad);
+static gboolean gst_avi_demux_sink_activate_pull (GstPad * sinkpad,
+    gboolean active);
+static gboolean gst_avi_demux_activate_push (GstPad * pad, gboolean active);
+static GstFlowReturn gst_avi_demux_chain (GstPad * pad, GstBuffer * buf);
+
+static GstStateChangeReturn gst_avi_demux_change_state (GstElement * element,
+    GstStateChange transition);
+
+static GstElementClass *parent_class = NULL;
+
+/* GObject methods */
+
+GType
+gst_avi_demux_get_type (void)
+{
+  static GType avi_demux_type = 0;
+
+  if (!avi_demux_type) {
+    static const GTypeInfo avi_demux_info = {
+      sizeof (GstAviDemuxClass),
+      (GBaseInitFunc) gst_avi_demux_base_init,
+      NULL,
+      (GClassInitFunc) gst_avi_demux_class_init,
+      NULL,
+      NULL,
+      sizeof (GstAviDemux),
+      0,
+      (GInstanceInitFunc) gst_avi_demux_init,
+    };
+
+    avi_demux_type =
+        g_type_register_static (GST_TYPE_ELEMENT,
+        "GstAviDemux", &avi_demux_info, 0);
+  }
+
+  return avi_demux_type;
+}
+
+static void
+gst_avi_demux_base_init (GstAviDemuxClass * klass)
+{
+  static const GstElementDetails gst_avi_demux_details =
+      GST_ELEMENT_DETAILS ("Avi demuxer",
+      "Codec/Demuxer",
+      "Demultiplex an avi file into audio and video",
+      "Erik Walthinsen <omega@cse.ogi.edu>\n"
+      "Wim Taymans <wim.taymans@chello.be>\n"
+      "Ronald Bultje <rbultje@ronald.bitfreak.net>\n"
+      "Thijs Vermeir <thijsvermeir@gmail.com>");
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstPadTemplate *videosrctempl, *audiosrctempl, *subsrctempl;
+  GstCaps *audcaps, *vidcaps, *subcaps;
+
+  audcaps = gst_riff_create_audio_template_caps ();
+  gst_caps_append (audcaps, gst_caps_new_simple ("audio/x-avi-unknown", NULL));
+  audiosrctempl = gst_pad_template_new ("audio_%02d",
+      GST_PAD_SRC, GST_PAD_SOMETIMES, audcaps);
+
+  vidcaps = gst_riff_create_video_template_caps ();
+  gst_caps_append (vidcaps, gst_riff_create_iavs_template_caps ());
+  gst_caps_append (vidcaps, gst_caps_new_simple ("video/x-avi-unknown", NULL));
+  videosrctempl = gst_pad_template_new ("video_%02d",
+      GST_PAD_SRC, GST_PAD_SOMETIMES, vidcaps);
+
+  subcaps = gst_caps_new_simple ("application/x-subtitle-avi", NULL);
+  subsrctempl = gst_pad_template_new ("subtitle_%02d",
+      GST_PAD_SRC, GST_PAD_SOMETIMES, subcaps);
+  gst_element_class_add_pad_template (element_class, audiosrctempl);
+  gst_element_class_add_pad_template (element_class, videosrctempl);
+  gst_element_class_add_pad_template (element_class, subsrctempl);
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_templ));
+  gst_element_class_set_details (element_class, &gst_avi_demux_details);
+}
+
+static void
+gst_avi_demux_class_init (GstAviDemuxClass * klass)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+
+  GST_DEBUG_CATEGORY_INIT (avidemux_debug, "avidemux",
+      0, "Demuxer for AVI streams");
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_avi_demux_finalize;
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_avi_demux_change_state);
+}
+
+static void
+gst_avi_demux_init (GstAviDemux * avi)
+{
+  avi->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
+  gst_pad_set_activate_function (avi->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_sink_activate));
+  gst_pad_set_activatepull_function (avi->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_sink_activate_pull));
+  gst_pad_set_activatepush_function (avi->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_activate_push));
+  gst_pad_set_chain_function (avi->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_chain));
+  gst_pad_set_event_function (avi->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_handle_sink_event));
+  gst_element_add_pad (GST_ELEMENT (avi), avi->sinkpad);
+
+  avi->adapter = gst_adapter_new ();
+
+  gst_avi_demux_reset (avi);
+}
+
+static void
+gst_avi_demux_finalize (GObject * object)
+{
+  GstAviDemux *avi = GST_AVI_DEMUX (object);
+
+  GST_DEBUG ("AVI: finalize");
+
+  g_object_unref (avi->adapter);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_avi_demux_reset (GstAviDemux * avi)
+{
+  gint i;
+
+  GST_DEBUG ("AVI: reset");
+
+  for (i = 0; i < avi->num_streams; i++) {
+    g_free (avi->stream[i].strh);
+    g_free (avi->stream[i].strf.data);
+    if (avi->stream[i].name)
+      g_free (avi->stream[i].name);
+    if (avi->stream[i].initdata)
+      gst_buffer_unref (avi->stream[i].initdata);
+    if (avi->stream[i].extradata)
+      gst_buffer_unref (avi->stream[i].extradata);
+    if (avi->stream[i].pad) {
+      gst_pad_set_active (avi->stream[i].pad, FALSE);
+      gst_element_remove_pad (GST_ELEMENT (avi), avi->stream[i].pad);
+    }
+    if (avi->stream[i].taglist) {
+      gst_tag_list_free (avi->stream[i].taglist);
+      avi->stream[i].taglist = NULL;
+    }
+  }
+  memset (&avi->stream, 0, sizeof (avi->stream));
+
+  avi->header_state = GST_AVI_DEMUX_HEADER_TAG_LIST;
+  avi->num_streams = 0;
+  avi->num_v_streams = 0;
+  avi->num_a_streams = 0;
+  avi->num_t_streams = 0;
+
+  avi->state = GST_AVI_DEMUX_START;
+  avi->offset = 0;
+
+  g_free (avi->index_entries);
+  avi->index_entries = NULL;
+  avi->index_size = 0;
+  avi->index_offset = 0;
+  avi->current_entry = 0;
+  g_free (avi->avih);
+  avi->avih = NULL;
+
+  if (avi->seek_event) {
+    gst_event_unref (avi->seek_event);
+    avi->seek_event = NULL;
+  }
+
+  if (avi->globaltags)
+    gst_tag_list_free (avi->globaltags);
+  avi->globaltags = NULL;
+
+  avi->got_tags = TRUE;         /* we always want to push global tags */
+  avi->have_eos = FALSE;
+
+  gst_adapter_clear (avi->adapter);
+
+  gst_segment_init (&avi->segment, GST_FORMAT_TIME);
+}
+
+/* Index helper */
+static gst_avi_index_entry *
+gst_avi_demux_index_last (GstAviDemux * avi, gint stream_nr)
+{
+  gint i;
+  gst_avi_index_entry *result = NULL;
+
+  for (i = avi->index_size - 1; i >= 0; i--) {
+    if (avi->index_entries[i].stream_nr == stream_nr) {
+      result = &avi->index_entries[i];
+      break;
+    }
+  }
+  return result;
+}
+
+static gst_avi_index_entry *
+gst_avi_demux_index_next (GstAviDemux * avi, gint stream_nr, gint last,
+    guchar flags)
+{
+  gint i;
+  gst_avi_index_entry *result = NULL, *entry;
+
+  for (i = last + 1; i < avi->index_size; i++) {
+    entry = &avi->index_entries[i];
+
+    if (entry->stream_nr != stream_nr)
+      continue;
+
+    if ((entry->flags & flags) == flags) {
+      result = entry;
+      break;
+    }
+  }
+  return result;
+}
+
+static gst_avi_index_entry *
+gst_avi_demux_index_prev (GstAviDemux * avi, gint stream_nr, gint last,
+    guchar flags)
+{
+  gint i;
+  gst_avi_index_entry *result = NULL, *entry;
+
+  for (i = last - 1; i >= 0; i--) {
+    entry = &avi->index_entries[i];
+
+    if (entry->stream_nr != stream_nr)
+      continue;
+
+    if ((entry->flags & flags) == flags) {
+      result = entry;
+      break;
+    }
+  }
+  return result;
+}
+
+static gint
+gst_avi_demux_index_entry_search (gst_avi_index_entry * entry, guint64 * time)
+{
+  if (entry->ts < *time)
+    return -1;
+  else if (entry->ts > *time)
+    return 1;
+  return 0;
+}
+
+/*
+ * gst_avi_index_entry:
+ * @avi: Avi object
+ * @stream_nr: stream number
+ * @time: seek time position
+ *
+ * Finds the index entry which time is less or equal than the requested time.
+ *
+ * Returns: the found index entry or %NULL
+ */
+static gst_avi_index_entry *
+gst_avi_demux_index_entry_for_time (GstAviDemux * avi,
+    gint stream_nr, guint64 time)
+{
+  gst_avi_index_entry *entry = NULL;
+  guint n;
+
+  GST_LOG_OBJECT (avi, "stream_nr:%d , time:%" GST_TIME_FORMAT,
+      stream_nr, GST_TIME_ARGS (time));
+
+  entry = gst_util_array_binary_search (avi->index_entries,
+      avi->index_size,
+      sizeof (gst_avi_index_entry),
+      (GCompareDataFunc) gst_avi_demux_index_entry_search,
+      GST_SEARCH_MODE_BEFORE, &time, NULL);
+
+  n = entry - avi->index_entries;
+  if (entry == NULL) {
+    entry = &avi->index_entries[0];
+    n = 0;
+    while (entry->stream_nr != stream_nr && n < avi->index_size - 1) {
+      n++;
+      entry = &avi->index_entries[n];
+    }
+  } else if (entry->stream_nr != stream_nr) {
+    while (entry->stream_nr != stream_nr && n > 0) {
+      n--;
+      entry = &avi->index_entries[n];
+    }
+  }
+
+  GST_LOG_OBJECT (avi,
+      "best at entry %u / ts:%" GST_TIME_FORMAT " / dur:%" GST_TIME_FORMAT
+      " flags:%02x", n, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur),
+      entry->flags);
+
+  return entry;
+}
+
+/* GstElement methods */
+
+#if 0
+static const GstFormat *
+gst_avi_demux_get_src_formats (GstPad * pad)
+{
+  avi_stream_context *stream = gst_pad_get_element_private (pad);
+
+  static const GstFormat src_a_formats[] = {
+    GST_FORMAT_TIME,
+    GST_FORMAT_BYTES,
+    GST_FORMAT_DEFAULT,
+    0
+  };
+  static const GstFormat src_v_formats[] = {
+    GST_FORMAT_TIME,
+    GST_FORMAT_DEFAULT,
+    0
+  };
+
+  return (stream->strh->type == GST_RIFF_FCC_auds ?
+      src_a_formats : src_v_formats);
+}
+#endif
+
+/* assumes stream->strf.auds->av_bps != 0 */
+static inline GstClockTime
+avi_stream_convert_bytes_to_time_unchecked (avi_stream_context * stream,
+    guint64 bytes)
+{
+  return gst_util_uint64_scale (bytes, GST_SECOND, stream->strf.auds->av_bps);
+}
+
+/* assumes stream->strh->rate != 0 */
+static inline GstClockTime
+avi_stream_convert_frames_to_time_unchecked (avi_stream_context * stream,
+    guint64 frames)
+{
+  return gst_util_uint64_scale (frames, stream->strh->scale * GST_SECOND,
+      stream->strh->rate);
+}
+
+static gboolean
+gst_avi_demux_src_convert (GstPad * pad,
+    GstFormat src_format,
+    gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
+{
+  avi_stream_context *stream = gst_pad_get_element_private (pad);
+  gboolean res = TRUE;
+
+  GST_LOG_OBJECT (pad,
+      "Received  src_format:%s, src_value:%" G_GUINT64_FORMAT
+      ", dest_format:%s", gst_format_get_name (src_format), src_value,
+      gst_format_get_name (*dest_format));
+
+  if (G_UNLIKELY (src_format == *dest_format)) {
+    *dest_value = src_value;
+    goto done;
+  }
+  if (G_UNLIKELY (!stream->strh || !stream->strf.data)) {
+    res = FALSE;
+    goto done;
+  }
+  if (G_UNLIKELY (stream->strh->type == GST_RIFF_FCC_vids &&
+          (src_format == GST_FORMAT_BYTES
+              || *dest_format == GST_FORMAT_BYTES))) {
+    res = FALSE;
+    goto done;
+  }
+
+  switch (src_format) {
+    case GST_FORMAT_TIME:
+      switch (*dest_format) {
+        case GST_FORMAT_BYTES:
+          *dest_value = gst_util_uint64_scale (src_value,
+              (guint64) stream->strf.auds->av_bps, GST_SECOND);
+          break;
+        case GST_FORMAT_DEFAULT:
+        {
+          gdouble error;
+
+          *dest_value = gst_util_uint64_scale (src_value, stream->strh->rate,
+              stream->strh->scale * GST_SECOND);
+
+          /* Attempt to round to nearest integer: if the difference is more
+           * than 0.5 (less than -0.5), it means that gst_util_uint64_scale()
+           * just truncated an integer, while it had to be rounded
+           */
+          error = *dest_value * GST_SECOND -
+              src_value * stream->strh->rate / stream->strh->scale;
+          if (error <= -0.5)
+            *dest_value += 1;
+          break;
+        }
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_BYTES:
+      switch (*dest_format) {
+        case GST_FORMAT_TIME:
+          if (stream->strf.auds->av_bps != 0) {
+            *dest_value = avi_stream_convert_bytes_to_time_unchecked (stream,
+                src_value);
+          } else
+            res = FALSE;
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_DEFAULT:
+      switch (*dest_format) {
+        case GST_FORMAT_TIME:
+          *dest_value =
+              avi_stream_convert_frames_to_time_unchecked (stream, src_value);
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    default:
+      res = FALSE;
+  }
+
+done:
+  GST_LOG_OBJECT (pad,
+      "Returning res:%d dest_format:%s dest_value:%" G_GUINT64_FORMAT, res,
+      gst_format_get_name (*dest_format), *dest_value);
+  return res;
+}
+
+static const GstQueryType *
+gst_avi_demux_get_src_query_types (GstPad * pad)
+{
+  static const GstQueryType src_types[] = {
+    GST_QUERY_POSITION,
+    GST_QUERY_DURATION,
+    GST_QUERY_SEEKING,
+    GST_QUERY_CONVERT,
+    0
+  };
+
+  return src_types;
+}
+
+static gboolean
+gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
+{
+  gboolean res = TRUE;
+  GstAviDemux *avi = GST_AVI_DEMUX (gst_pad_get_parent (pad));
+
+  avi_stream_context *stream = gst_pad_get_element_private (pad);
+
+  if (!stream->strh || !stream->strf.data)
+    return gst_pad_query_default (pad, query);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:{
+      gint64 pos = 0;
+
+      GST_DEBUG ("pos query for stream %d: frames %d, bytes %" G_GUINT64_FORMAT,
+          stream->num, stream->current_frame, stream->current_byte);
+
+      if (stream->strh->type == GST_RIFF_FCC_auds) {
+        if (stream->is_vbr) {
+          /* VBR */
+          pos = gst_util_uint64_scale ((gint64) stream->current_frame *
+              stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate);
+          GST_DEBUG_OBJECT (avi, "VBR convert frame %u, time %"
+              GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos));
+        } else if (stream->strf.auds->av_bps != 0) {
+          /* CBR */
+          pos = gst_util_uint64_scale (stream->current_byte, GST_SECOND,
+              (guint64) stream->strf.auds->av_bps);
+          GST_DEBUG_OBJECT (avi,
+              "CBR convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
+              stream->current_byte, GST_TIME_ARGS (pos));
+        } else if (stream->total_frames != 0 && stream->total_bytes != 0) {
+          /* calculate timestamps based on percentage of length */
+          guint64 xlen = avi->avih->us_frame *
+              avi->avih->tot_frames * GST_USECOND;
+
+          if (stream->is_vbr) {
+            pos = gst_util_uint64_scale (xlen, stream->current_frame,
+                stream->total_frames);
+            GST_DEBUG_OBJECT (avi, "VBR perc convert frame %u, time %"
+                GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos));
+          } else {
+            pos = gst_util_uint64_scale (xlen, stream->current_byte,
+                stream->total_bytes);
+            GST_DEBUG_OBJECT (avi, "CBR perc convert bytes %" G_GUINT64_FORMAT
+                ", time %" GST_TIME_FORMAT, stream->current_byte,
+                GST_TIME_ARGS (pos));
+          }
+        } else {
+          /* we don't know */
+          res = FALSE;
+        }
+      } else {
+        if (stream->strh->rate != 0) {
+          pos = gst_util_uint64_scale ((guint64) stream->current_frame *
+              stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate);
+        } else {
+          pos = stream->current_frame * avi->avih->us_frame * GST_USECOND;
+        }
+      }
+      if (res) {
+        GST_DEBUG ("pos query : %" GST_TIME_FORMAT, GST_TIME_ARGS (pos));
+        gst_query_set_position (query, GST_FORMAT_TIME, pos);
+      } else
+        GST_WARNING ("pos query failed");
+      break;
+    }
+    case GST_QUERY_DURATION:
+    {
+      GstFormat fmt;
+
+      if (stream->strh->type != GST_RIFF_FCC_auds &&
+          stream->strh->type != GST_RIFF_FCC_vids) {
+        res = FALSE;
+        break;
+      }
+
+      gst_query_parse_duration (query, &fmt, NULL);
+
+      switch (fmt) {
+        case GST_FORMAT_TIME:
+          gst_query_set_duration (query, fmt, stream->duration);
+          break;
+        case GST_FORMAT_DEFAULT:
+        {
+          gint64 dur;
+          GST_DEBUG_OBJECT (query, "total frames is %" G_GUINT32_FORMAT,
+              stream->total_frames);
+
+          if (stream->total_frames >= 0)
+            gst_query_set_duration (query, fmt, stream->total_frames);
+          else if (gst_pad_query_convert (pad, GST_FORMAT_TIME,
+                  stream->duration, &fmt, &dur))
+            gst_query_set_duration (query, fmt, dur);
+          break;
+        }
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    }
+    case GST_QUERY_SEEKING:{
+      GstFormat fmt;
+
+      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        gboolean seekable = TRUE;
+
+        if (avi->streaming) {
+          seekable = FALSE;
+        } else {
+          if (avi->index_entries == NULL) {
+            seekable = FALSE;
+            /* FIXME: when building index_entried, count keyframes
+               if (!(avi->key_frame_ct > 1))
+               seekable = FALSE;
+             */
+          }
+        }
+
+        gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
+            0, stream->duration);
+        res = TRUE;
+      }
+      break;
+    }
+    case GST_QUERY_CONVERT:{
+      GstFormat src_fmt, dest_fmt;
+      gint64 src_val, dest_val;
+
+      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
+      if ((res = gst_avi_demux_src_convert (pad, src_fmt, src_val, &dest_fmt,
+                  &dest_val)))
+        gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
+      else
+        res = gst_pad_query_default (pad, query);
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, query);
+      break;
+  }
+
+  gst_object_unref (avi);
+  return res;
+}
+
+#if 0
+static const GstEventMask *
+gst_avi_demux_get_event_mask (GstPad * pad)
+{
+  static const GstEventMask masks[] = {
+    {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_KEY_UNIT},
+    {0,}
+  };
+
+  return masks;
+}
+#endif
+
+static gboolean
+gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res = TRUE;
+  GstAviDemux *avi = GST_AVI_DEMUX (gst_pad_get_parent (pad));
+
+  GST_DEBUG_OBJECT (avi,
+      "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+      /* Drop NEWSEGMENT events, new ones are generated later */
+      gst_event_unref (event);
+      break;
+    case GST_EVENT_EOS:
+    {
+      if (avi->state != GST_AVI_DEMUX_MOVI) {
+        gst_event_unref (event);
+        GST_ELEMENT_ERROR (avi, STREAM, DEMUX,
+            (NULL), ("got eos and didn't receive a complete header object"));
+      } else if (!gst_avi_demux_push_event (avi, event)) {
+        GST_ELEMENT_ERROR (avi, STREAM, DEMUX,
+            (NULL), ("got eos but no streams (yet)"));
+      }
+      break;
+    }
+    default:
+      res = gst_pad_event_default (pad, event);
+      break;
+  }
+
+  gst_object_unref (avi);
+
+  return res;
+}
+
+static gboolean
+gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res = TRUE;
+  GstAviDemux *avi = GST_AVI_DEMUX (gst_pad_get_parent (pad));
+
+  GST_DEBUG_OBJECT (avi,
+      "have event type %s: %p on src pad", GST_EVENT_TYPE_NAME (event), event);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+      /* handle seeking only in pull mode */
+      if (!avi->streaming) {
+        res = gst_avi_demux_handle_seek (avi, pad, event);
+        gst_event_unref (event);
+      } else {
+        res = gst_pad_event_default (pad, event);
+      }
+      break;
+    case GST_EVENT_QOS:
+    case GST_EVENT_NAVIGATION:
+      res = FALSE;
+      gst_event_unref (event);
+      break;
+    default:
+      res = gst_pad_event_default (pad, event);
+      break;
+  }
+
+  gst_object_unref (avi);
+
+  return res;
+}
+
+/* streaming helper (push) */
+
+/*
+ * gst_avi_demux_peek_chunk_info:
+ * @avi: Avi object
+ * @tag: holder for tag
+ * @size: holder for tag size
+ *
+ * Peek next chunk info (tag and size)
+ *
+ * Returns: TRUE when one chunk info has been got
+ */
+static gboolean
+gst_avi_demux_peek_chunk_info (GstAviDemux * avi, guint32 * tag, guint32 * size)
+{
+  const guint8 *data = NULL;
+
+  if (gst_adapter_available (avi->adapter) < 8) {
+    return FALSE;
+  }
+
+  data = gst_adapter_peek (avi->adapter, 8);
+  *tag = GST_READ_UINT32_LE (data);
+  *size = GST_READ_UINT32_LE (data + 4);
+
+  return TRUE;
+}
+
+/*
+ * gst_avi_demux_peek_chunk:
+ * @avi: Avi object
+ * @tag: holder for tag
+ * @size: holder for tag size
+ *
+ * Peek enough data for one full chunk
+ *
+ * Returns: %TRUE when one chunk has been got
+ */
+static gboolean
+gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size)
+{
+  guint32 peek_size = 0;
+  gint available;
+
+  if (!gst_avi_demux_peek_chunk_info (avi, tag, size)) {
+    return FALSE;
+  }
+  /* FIXME: shouldn't this check go to gst_avi_demux_peek_chunk_info() already */
+  if (!(*size) || (*size) == -1) {
+    GST_INFO ("Invalid chunk size %d for tag %" GST_FOURCC_FORMAT,
+        *size, GST_FOURCC_ARGS (*tag));
+    return FALSE;
+  }
+  peek_size = (*size + 1) & ~1;
+  available = gst_adapter_available (avi->adapter);
+
+  GST_DEBUG ("Need to peek chunk of %d bytes to read chunk %" GST_FOURCC_FORMAT
+      ", %d bytes available", *size, GST_FOURCC_ARGS (*tag), available);
+
+  if (available >= (8 + peek_size)) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/* AVI init */
+
+/*
+ * gst_avi_demux_parse_file_header:
+ * @element: caller element (used for errors/debug).
+ * @buf: input data to be used for parsing.
+ *
+ * "Open" a RIFF/AVI file. The buffer should be at least 12
+ * bytes long. Takes ownership of @buf.
+ *
+ * Returns: TRUE if the file is a RIFF/AVI file, FALSE otherwise.
+ *          Throws an error, caller should error out (fatal).
+ */
+static gboolean
+gst_avi_demux_parse_file_header (GstElement * element, GstBuffer * buf)
+{
+  guint32 doctype;
+
+  /* riff_parse posts an error */
+  if (!gst_riff_parse_file_header (element, buf, &doctype))
+    return FALSE;
+
+  if (doctype != GST_RIFF_RIFF_AVI)
+    goto not_avi;
+
+  return TRUE;
+
+  /* ERRORS */
+not_avi:
+  {
+    GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
+        ("File is not an AVI file: %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (doctype)));
+    return FALSE;
+  }
+}
+
+/*
+ * Read AVI file tag when streaming
+ */
+static GstFlowReturn
+gst_avi_demux_stream_init_push (GstAviDemux * avi)
+{
+  if (gst_adapter_available (avi->adapter) >= 12) {
+    GstBuffer *tmp;
+
+    tmp = gst_adapter_take_buffer (avi->adapter, 12);
+
+    GST_DEBUG ("Parsing avi header");
+    if (!gst_avi_demux_parse_file_header (GST_ELEMENT (avi), tmp)) {
+      return GST_FLOW_ERROR;
+    }
+    GST_DEBUG ("header ok");
+    avi->offset += 12;
+
+    avi->state = GST_AVI_DEMUX_HEADER;
+  }
+  return GST_FLOW_OK;
+}
+
+/*
+ * Read AVI file tag
+ */
+static GstFlowReturn
+gst_avi_demux_stream_init_pull (GstAviDemux * avi)
+{
+  GstFlowReturn res;
+  GstBuffer *buf = NULL;
+
+  res = gst_pad_pull_range (avi->sinkpad, avi->offset, 12, &buf);
+  if (res != GST_FLOW_OK)
+    return res;
+  else if (!gst_avi_demux_parse_file_header (GST_ELEMENT_CAST (avi), buf))
+    goto wrong_header;
+
+  avi->offset += 12;
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+wrong_header:
+  {
+    GST_DEBUG_OBJECT (avi, "error parsing file header");
+    return GST_FLOW_ERROR;
+  }
+}
+
+/* AVI header handling */
+
+/*
+ * gst_avi_demux_parse_avih:
+ * @element: caller element (used for errors/debug).
+ * @buf: input data to be used for parsing.
+ * @avih: pointer to structure (filled in by function) containing
+ *        stream information (such as flags, number of streams, etc.).
+ *
+ * Read 'avih' header. Discards buffer after use.
+ *
+ * Returns: TRUE on success, FALSE otherwise. Throws an error if
+ *          the header is invalid. The caller should error out
+ *          (fatal).
+ */
+static gboolean
+gst_avi_demux_parse_avih (GstElement * element,
+    GstBuffer * buf, gst_riff_avih ** _avih)
+{
+  gst_riff_avih *avih;
+
+  if (buf == NULL)
+    goto no_buffer;
+
+  if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_avih))
+    goto avih_too_small;
+
+  avih = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+#if (G_BYTE_ORDER == G_BIG_ENDIAN)
+  avih->us_frame = GUINT32_FROM_LE (avih->us_frame);
+  avih->max_bps = GUINT32_FROM_LE (avih->max_bps);
+  avih->pad_gran = GUINT32_FROM_LE (avih->pad_gran);
+  avih->flags = GUINT32_FROM_LE (avih->flags);
+  avih->tot_frames = GUINT32_FROM_LE (avih->tot_frames);
+  avih->init_frames = GUINT32_FROM_LE (avih->init_frames);
+  avih->streams = GUINT32_FROM_LE (avih->streams);
+  avih->bufsize = GUINT32_FROM_LE (avih->bufsize);
+  avih->width = GUINT32_FROM_LE (avih->width);
+  avih->height = GUINT32_FROM_LE (avih->height);
+  avih->scale = GUINT32_FROM_LE (avih->scale);
+  avih->rate = GUINT32_FROM_LE (avih->rate);
+  avih->start = GUINT32_FROM_LE (avih->start);
+  avih->length = GUINT32_FROM_LE (avih->length);
+#endif
+
+  /* debug stuff */
+  GST_INFO_OBJECT (element, "avih tag found:");
+  GST_INFO_OBJECT (element, " us_frame    %u", avih->us_frame);
+  GST_INFO_OBJECT (element, " max_bps     %u", avih->max_bps);
+  GST_INFO_OBJECT (element, " pad_gran    %u", avih->pad_gran);
+  GST_INFO_OBJECT (element, " flags       0x%08x", avih->flags);
+  GST_INFO_OBJECT (element, " tot_frames  %u", avih->tot_frames);
+  GST_INFO_OBJECT (element, " init_frames %u", avih->init_frames);
+  GST_INFO_OBJECT (element, " streams     %u", avih->streams);
+  GST_INFO_OBJECT (element, " bufsize     %u", avih->bufsize);
+  GST_INFO_OBJECT (element, " width       %u", avih->width);
+  GST_INFO_OBJECT (element, " height      %u", avih->height);
+  GST_INFO_OBJECT (element, " scale       %u", avih->scale);
+  GST_INFO_OBJECT (element, " rate        %u", avih->rate);
+  GST_INFO_OBJECT (element, " start       %u", avih->start);
+  GST_INFO_OBJECT (element, " length      %u", avih->length);
+
+  *_avih = avih;
+  gst_buffer_unref (buf);
+
+  return TRUE;
+
+  /* ERRORS */
+no_buffer:
+  {
+    GST_ELEMENT_ERROR (element, STREAM, DEMUX, (NULL), ("No buffer"));
+    return FALSE;
+  }
+avih_too_small:
+  {
+    GST_ELEMENT_ERROR (element, STREAM, DEMUX, (NULL),
+        ("Too small avih (%d available, %d needed)",
+            GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_avih)));
+    gst_buffer_unref (buf);
+    return FALSE;
+  }
+}
+
+/*
+ * gst_avi_demux_parse_superindex:
+ * @avi: caller element (used for debugging/errors).
+ * @buf: input data to use for parsing.
+ * @locations: locations in the file (byte-offsets) that contain
+ *             the actual indexes (see get_avi_demux_parse_subindex()).
+ *             The array ends with GST_BUFFER_OFFSET_NONE.
+ *
+ * Reads superindex (openDML-2 spec stuff) from the provided data.
+ *
+ * Returns: TRUE on success, FALSE otherwise. Indexes should be skipped
+ *          on error, but they are not fatal.
+ */
+static gboolean
+gst_avi_demux_parse_superindex (GstAviDemux * avi,
+    GstBuffer * buf, guint64 ** _indexes)
+{
+  guint8 *data;
+  guint16 bpe = 16;
+  guint32 num, i;
+  guint64 *indexes;
+  guint size;
+
+  *_indexes = NULL;
+
+  size = buf ? GST_BUFFER_SIZE (buf) : 0;
+  if (size < 24)
+    goto too_small;
+
+  data = GST_BUFFER_DATA (buf);
+
+  /* check type of index. The opendml2 specs state that
+   * there should be 4 dwords per array entry. Type can be
+   * either frame or field (and we don't care). */
+  if (GST_READ_UINT16_LE (data) != 4 ||
+      (data[2] & 0xfe) != 0x0 || data[3] != 0x0) {
+    GST_WARNING_OBJECT (avi,
+        "Superindex for stream has unexpected "
+        "size_entry %d (bytes) or flags 0x%02x/0x%02x",
+        GST_READ_UINT16_LE (data), data[2], data[3]);
+    bpe = GST_READ_UINT16_LE (data) * 4;
+  }
+  num = GST_READ_UINT32_LE (&data[4]);
+
+  indexes = g_new (guint64, num + 1);
+  for (i = 0; i < num; i++) {
+    if (size < 24 + bpe * (i + 1))
+      break;
+    indexes[i] = GST_READ_UINT64_LE (&data[24 + bpe * i]);
+  }
+  indexes[i] = GST_BUFFER_OFFSET_NONE;
+  *_indexes = indexes;
+
+  gst_buffer_unref (buf);
+
+  return TRUE;
+
+  /* ERRORS */
+too_small:
+  {
+    GST_ERROR_OBJECT (avi,
+        "Not enough data to parse superindex (%d available, 24 needed)", size);
+    if (buf)
+      gst_buffer_unref (buf);
+    return FALSE;
+  }
+}
+
+/*
+ * gst_avi_demux_parse_subindex:
+ * @avi: Avi object
+ * @buf: input data to use for parsing.
+ * @stream: stream context.
+ * @entries_list: a list (returned by the function) containing all the
+ *           indexes parsed in this specific subindex. The first
+ *           entry is also a pointer to allocated memory that needs
+ *           to be free´ed. May be NULL if no supported indexes were
+ *           found.
+ *
+ * Reads superindex (openDML-2 spec stuff) from the provided data.
+ * The buffer will be discarded after use.
+ *
+ * Returns: TRUE on success, FALSE otherwise. Errors are fatal, we
+ *          throw an error, caller should bail out asap.
+ */
+static gboolean
+gst_avi_demux_parse_subindex (GstAviDemux * avi,
+    GstBuffer * buf, avi_stream_context * stream, GList ** _entries_list)
+{
+  guint8 *data = GST_BUFFER_DATA (buf);
+  guint16 bpe;
+  guint32 num, i;
+  guint64 baseoff;
+  gst_avi_index_entry *entries, *entry;
+  GList *entries_list = NULL;
+  guint size;
+
+  *_entries_list = NULL;
+
+  size = buf ? GST_BUFFER_SIZE (buf) : 0;
+
+  /* check size */
+  if (size < 24)
+    goto too_small;
+
+  /* We don't support index-data yet */
+  if (data[3] & 0x80)
+    goto not_implemented;
+
+  /* check type of index. The opendml2 specs state that
+   * there should be 4 dwords per array entry. Type can be
+   * either frame or field (and we don't care). */
+  bpe = (data[2] & 0x01) ? 12 : 8;
+  if (GST_READ_UINT16_LE (data) != bpe / 4 ||
+      (data[2] & 0xfe) != 0x0 || data[3] != 0x1) {
+    GST_WARNING_OBJECT (avi,
+        "Superindex for stream %d has unexpected "
+        "size_entry %d (bytes) or flags 0x%02x/0x%02x",
+        stream->num, GST_READ_UINT16_LE (data), data[2], data[3]);
+    bpe = GST_READ_UINT16_LE (data) * 4;
+  }
+  num = GST_READ_UINT32_LE (&data[4]);
+  baseoff = GST_READ_UINT64_LE (&data[12]);
+
+  /* If there's nothing, just return ! */
+  if (num == 0)
+    return TRUE;
+
+  if (!(entries = g_try_new (gst_avi_index_entry, num)))
+    goto out_of_mem;
+
+  for (i = 0; i < num; i++) {
+    gint64 next_ts;
+
+    entry = &entries[i];
+
+    if (size < 24 + bpe * (i + 1))
+      break;
+
+    /* fill in */
+    entry->offset = baseoff + GST_READ_UINT32_LE (&data[24 + bpe * i]);
+    entry->size = GST_READ_UINT32_LE (&data[24 + bpe * i + 4]);
+    entry->flags =
+        (entry->size & 0x80000000) ? 0 : GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME;
+    entry->size &= ~0x80000000;
+    entry->index_nr = i;
+    entry->stream_nr = stream->num;
+
+    /* stream duration unknown, now we can calculate it */
+    if (stream->idx_duration == -1)
+      stream->idx_duration = 0;
+
+    /* timestamps */
+    entry->ts = stream->idx_duration;
+    if (stream->is_vbr) {
+      /* VBR stream next timestamp */
+      if (stream->strh->type == GST_RIFF_FCC_auds) {
+        next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
+            stream->total_blocks + 1);
+      } else {
+        next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
+            stream->total_frames + 1);
+      }
+    } else {
+      /* CBR get next timestamp */
+      next_ts = avi_stream_convert_bytes_to_time_unchecked (stream,
+          stream->total_bytes + entry->size);
+    }
+    /* duration is next - current */
+    entry->dur = next_ts - entry->ts;
+
+    /* stream position */
+    entry->bytes_before = stream->total_bytes;
+    entry->frames_before = stream->total_frames;
+
+    stream->total_bytes += entry->size;
+    stream->total_frames++;
+    if (stream->strh->type == GST_RIFF_FCC_auds) {
+      if (stream->strf.auds->blockalign > 0)
+        stream->total_blocks +=
+            (entry->size + stream->strf.auds->blockalign -
+            1) / stream->strf.auds->blockalign;
+      else
+        stream->total_blocks++;
+    }
+    stream->idx_duration = next_ts;
+
+    entries_list = g_list_prepend (entries_list, entry);
+  }
+
+  GST_LOG_OBJECT (avi, "Read %d index entries", i);
+
+  gst_buffer_unref (buf);
+
+  if (i > 0) {
+    *_entries_list = g_list_reverse (entries_list);
+  } else {
+    g_free (entries);
+  }
+
+  return TRUE;
+
+  /* ERRORS */
+too_small:
+  {
+    GST_ERROR_OBJECT (avi,
+        "Not enough data to parse subindex (%d available, 24 needed)", size);
+    if (buf)
+      gst_buffer_unref (buf);
+    return TRUE;                /* continue */
+  }
+not_implemented:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, NOT_IMPLEMENTED, (NULL),
+        ("Subindex-is-data is not implemented"));
+    gst_buffer_unref (buf);
+    return FALSE;
+  }
+out_of_mem:
+  {
+    GST_ELEMENT_ERROR (avi, RESOURCE, NO_SPACE_LEFT, (NULL),
+        ("Cannot allocate memory for %u*%u=%u bytes",
+            (guint) sizeof (gst_avi_index_entry), num,
+            (guint) sizeof (gst_avi_index_entry) * num));
+    gst_buffer_unref (buf);
+    return FALSE;
+  }
+}
+
+#if 0
+/*
+ * Read AVI index when streaming
+ */
+static void
+gst_avi_demux_read_subindexes_push (GstAviDemux * avi,
+    GList ** index, GList ** alloc_list)
+{
+  GList *list = NULL;
+  guint32 tag = 0, size;
+  GstBuffer *buf = NULL;
+  gint i, n;
+
+  GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_push for %d streams",
+      avi->num_streams);
+
+  for (n = 0; n < avi->num_streams; n++) {
+    avi_stream_context *stream = &avi->stream[n];
+
+    for (i = 0; stream->indexes[i] != GST_BUFFER_OFFSET_NONE; i++) {
+      if (!gst_avi_demux_peek_chunk (avi, &tag, &size))
+        continue;
+      else if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + stream->num / 10,
+                  '0' + stream->num % 10)) &&
+          (tag != GST_MAKE_FOURCC ('0' + stream->num / 10,
+                  '0' + stream->num % 10, 'i', 'x'))) {
+        GST_WARNING_OBJECT (avi, "Not an ix## chunk (%" GST_FOURCC_FORMAT ")",
+            GST_FOURCC_ARGS (tag));
+        continue;
+      }
+
+      avi->offset += 8 + ((size + 1) & ~1);
+
+      buf = gst_buffer_new ();
+      GST_BUFFER_DATA (buf) = gst_adapter_take (avi->adapter, size);
+      GST_BUFFER_SIZE (buf) = size;
+
+      if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list))
+        continue;
+      if (list) {
+        GST_DEBUG_OBJECT (avi, "  adding %d entries", g_list_length (list));
+        *alloc_list = g_list_append (*alloc_list, list->data);
+        *index = g_list_concat (*index, list);
+      }
+    }
+
+    g_free (stream->indexes);
+    stream->indexes = NULL;
+  }
+  GST_DEBUG_OBJECT (avi, "index %s", ((*index) ? "!= 0" : "== 0"));
+}
+#endif
+
+/*
+ * Read AVI index
+ */
+static void
+gst_avi_demux_read_subindexes_pull (GstAviDemux * avi,
+    GList ** index, GList ** alloc_list)
+{
+  GList *list = NULL;
+  guint32 tag;
+  GstBuffer *buf;
+  gint i, n;
+
+  GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_pull for %d streams",
+      avi->num_streams);
+
+  for (n = 0; n < avi->num_streams; n++) {
+    avi_stream_context *stream = &avi->stream[n];
+
+    for (i = 0; stream->indexes[i] != GST_BUFFER_OFFSET_NONE; i++) {
+      if (gst_riff_read_chunk (GST_ELEMENT (avi), avi->sinkpad,
+              &stream->indexes[i], &tag, &buf) != GST_FLOW_OK)
+        continue;
+      else if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + stream->num / 10,
+                  '0' + stream->num % 10)) &&
+          (tag != GST_MAKE_FOURCC ('0' + stream->num / 10,
+                  '0' + stream->num % 10, 'i', 'x'))) {
+        /* Some ODML files (created by god knows what muxer) have a ##ix format
+         * instead of the 'official' ix##. They are still valid though. */
+        GST_WARNING_OBJECT (avi, "Not an ix## chunk (%" GST_FOURCC_FORMAT ")",
+            GST_FOURCC_ARGS (tag));
+        gst_buffer_unref (buf);
+        continue;
+      }
+
+      if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list))
+        continue;
+      if (list) {
+        GST_DEBUG_OBJECT (avi, "  adding %5d entries, total %2d %5d",
+            g_list_length (list), g_list_length (*alloc_list),
+            g_list_length (*index));
+        *alloc_list = g_list_append (*alloc_list, list->data);
+        *index = g_list_concat (*index, list);
+      }
+    }
+
+    g_free (stream->indexes);
+    stream->indexes = NULL;
+  }
+  GST_DEBUG_OBJECT (avi, "index %s", ((*index) ? "!= 0" : "== 0"));
+}
+
+/*
+ * gst_avi_demux_riff_parse_vprp:
+ * @element: caller element (used for debugging/error).
+ * @buf: input data to be used for parsing, stripped from header.
+ * @vprp: a pointer (returned by this function) to a filled-in vprp
+ *        structure. Caller should free it.
+ *
+ * Parses a video stream´s vprp. This function takes ownership of @buf.
+ *
+ * Returns: TRUE if parsing succeeded, otherwise FALSE. The stream
+ *          should be skipped on error, but it is not fatal.
+ */
+static gboolean
+gst_avi_demux_riff_parse_vprp (GstElement * element,
+    GstBuffer * buf, gst_riff_vprp ** _vprp)
+{
+  gst_riff_vprp *vprp;
+  gint k;
+
+  g_return_val_if_fail (buf != NULL, FALSE);
+  g_return_val_if_fail (_vprp != NULL, FALSE);
+
+  if (GST_BUFFER_SIZE (buf) < G_STRUCT_OFFSET (gst_riff_vprp, field_info))
+    goto too_small;
+
+  vprp = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+#if (G_BYTE_ORDER == G_BIG_ENDIAN)
+  vprp->format_token = GUINT32_FROM_LE (vprp->format_token);
+  vprp->standard = GUINT32_FROM_LE (vprp->standard);
+  vprp->vert_rate = GUINT32_FROM_LE (vprp->vert_rate);
+  vprp->hor_t_total = GUINT32_FROM_LE (vprp->hor_t_total);
+  vprp->vert_lines = GUINT32_FROM_LE (vprp->vert_lines);
+  vprp->aspect = GUINT32_FROM_LE (vprp->aspect);
+  vprp->width = GUINT32_FROM_LE (vprp->width);
+  vprp->height = GUINT32_FROM_LE (vprp->height);
+  vprp->fields = GUINT32_FROM_LE (vprp->fields);
+#endif
+
+  /* size checking */
+  /* calculate fields based on size */
+  k = (GST_BUFFER_SIZE (buf) - G_STRUCT_OFFSET (gst_riff_vprp, field_info)) /
+      vprp->fields;
+  if (vprp->fields > k) {
+    GST_WARNING_OBJECT (element,
+        "vprp header indicated %d fields, only %d available", vprp->fields, k);
+    vprp->fields = k;
+  }
+  if (vprp->fields > GST_RIFF_VPRP_VIDEO_FIELDS) {
+    GST_WARNING_OBJECT (element,
+        "vprp header indicated %d fields, at most %d supported", vprp->fields,
+        GST_RIFF_VPRP_VIDEO_FIELDS);
+    vprp->fields = GST_RIFF_VPRP_VIDEO_FIELDS;
+  }
+#if (G_BYTE_ORDER == G_BIG_ENDIAN)
+  for (k = 0; k < vprp->fields; k++) {
+    gst_riff_vprp_video_field_desc *fd;
+
+    fd = &vprp->field_info[k];
+    fd->compressed_bm_height = GUINT32_FROM_LE (fd->compressed_bm_height);
+    fd->compressed_bm_width = GUINT32_FROM_LE (fd->compressed_bm_width);
+    fd->valid_bm_height = GUINT32_FROM_LE (fd->valid_bm_height);
+    fd->valid_bm_width = GUINT16_FROM_LE (fd->valid_bm_width);
+    fd->valid_bm_x_offset = GUINT16_FROM_LE (fd->valid_bm_x_offset);
+    fd->valid_bm_y_offset = GUINT32_FROM_LE (fd->valid_bm_y_offset);
+    fd->video_x_t_offset = GUINT32_FROM_LE (fd->video_x_t_offset);
+    fd->video_y_start = GUINT32_FROM_LE (fd->video_y_start);
+  }
+#endif
+
+  /* debug */
+  GST_INFO_OBJECT (element, "vprp tag found in context vids:");
+  GST_INFO_OBJECT (element, " format_token  %d", vprp->format_token);
+  GST_INFO_OBJECT (element, " standard      %d", vprp->standard);
+  GST_INFO_OBJECT (element, " vert_rate     %d", vprp->vert_rate);
+  GST_INFO_OBJECT (element, " hor_t_total   %d", vprp->hor_t_total);
+  GST_INFO_OBJECT (element, " vert_lines    %d", vprp->vert_lines);
+  GST_INFO_OBJECT (element, " aspect        %d:%d", vprp->aspect >> 16,
+      vprp->aspect & 0xffff);
+  GST_INFO_OBJECT (element, " width         %d", vprp->width);
+  GST_INFO_OBJECT (element, " height        %d", vprp->height);
+  GST_INFO_OBJECT (element, " fields        %d", vprp->fields);
+  for (k = 0; k < vprp->fields; k++) {
+    gst_riff_vprp_video_field_desc *fd;
+
+    fd = &(vprp->field_info[k]);
+    GST_INFO_OBJECT (element, " field %u description:", k);
+    GST_INFO_OBJECT (element, "  compressed_bm_height  %d",
+        fd->compressed_bm_height);
+    GST_INFO_OBJECT (element, "  compressed_bm_width  %d",
+        fd->compressed_bm_width);
+    GST_INFO_OBJECT (element, "  valid_bm_height       %d",
+        fd->valid_bm_height);
+    GST_INFO_OBJECT (element, "  valid_bm_width        %d", fd->valid_bm_width);
+    GST_INFO_OBJECT (element, "  valid_bm_x_offset     %d",
+        fd->valid_bm_x_offset);
+    GST_INFO_OBJECT (element, "  valid_bm_y_offset     %d",
+        fd->valid_bm_y_offset);
+    GST_INFO_OBJECT (element, "  video_x_t_offset      %d",
+        fd->video_x_t_offset);
+    GST_INFO_OBJECT (element, "  video_y_start         %d", fd->video_y_start);
+  }
+
+  gst_buffer_unref (buf);
+
+  *_vprp = vprp;
+
+  return TRUE;
+
+  /* ERRORS */
+too_small:
+  {
+    GST_ERROR_OBJECT (element,
+        "Too small vprp (%d available, at least %d needed)",
+        GST_BUFFER_SIZE (buf),
+        (int) G_STRUCT_OFFSET (gst_riff_vprp, field_info));
+    gst_buffer_unref (buf);
+    return FALSE;
+  }
+}
+
+/*
+ * gst_avi_demux_parse_stream:
+ * @avi: calling element (used for debugging/errors).
+ * @buf: input buffer used to parse the stream.
+ *
+ * Parses all subchunks in a strl chunk (which defines a single
+ * stream). Discards the buffer after use. This function will
+ * increment the stream counter internally.
+ *
+ * Returns: whether the stream was identified successfully.
+ *          Errors are not fatal. It does indicate the stream
+ *          was skipped.
+ */
+static gboolean
+gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
+{
+  avi_stream_context *stream;
+  GstElementClass *klass;
+  GstPadTemplate *templ;
+  GstBuffer *sub = NULL;
+  guint offset = 4;
+  guint32 tag = 0;
+  gchar *codec_name = NULL, *padname = NULL;
+  const gchar *tag_name;
+  GstCaps *caps = NULL;
+  GstPad *pad;
+  GstElement *element;
+  gboolean got_strh = FALSE, got_strf = FALSE, got_vprp = FALSE;
+  gst_riff_vprp *vprp = NULL;
+
+  element = GST_ELEMENT_CAST (avi);
+
+  GST_DEBUG_OBJECT (avi, "Parsing stream");
+
+  if (avi->num_streams >= GST_AVI_DEMUX_MAX_STREAMS) {
+    GST_WARNING_OBJECT (avi,
+        "maximum no of streams (%d) exceeded, ignoring stream",
+        GST_AVI_DEMUX_MAX_STREAMS);
+    gst_buffer_unref (buf);
+    /* not a fatal error, let's say */
+    return TRUE;
+  }
+
+  stream = &avi->stream[avi->num_streams];
+
+  /* initial settings */
+  stream->idx_duration = GST_CLOCK_TIME_NONE;
+  stream->hdr_duration = GST_CLOCK_TIME_NONE;
+  stream->duration = GST_CLOCK_TIME_NONE;
+
+  while (gst_riff_parse_chunk (element, buf, &offset, &tag, &sub)) {
+    /* sub can be NULL if the chunk is empty */
+    if (sub == NULL) {
+      GST_DEBUG_OBJECT (avi, "ignoring empty chunk %" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (tag));
+      continue;
+    }
+    switch (tag) {
+      case GST_RIFF_TAG_strh:
+      {
+        gst_riff_strh *strh;
+
+        if (got_strh) {
+          GST_WARNING_OBJECT (avi, "Ignoring additional strh chunk");
+          break;
+        }
+        if (!gst_riff_parse_strh (element, sub, &stream->strh)) {
+          /* ownership given away */
+          sub = NULL;
+          GST_WARNING_OBJECT (avi, "Failed to parse strh chunk");
+          goto fail;
+        }
+        sub = NULL;
+        strh = stream->strh;
+        /* sanity check; stream header frame rate matches global header
+         * frame duration */
+        if (stream->strh->type == GST_RIFF_FCC_vids) {
+          GstClockTime s_dur;
+          GstClockTime h_dur = avi->avih->us_frame * GST_USECOND;
+
+          s_dur = gst_util_uint64_scale (GST_SECOND, strh->scale, strh->rate);
+          GST_DEBUG_OBJECT (avi, "verifying stream framerate %d/%d, "
+              "frame duration = %d ms", strh->rate, strh->scale,
+              s_dur / GST_MSECOND);
+          if (h_dur > (10 * GST_MSECOND) && (s_dur > 10 * h_dur)) {
+            strh->rate = GST_SECOND / GST_USECOND;
+            strh->scale = h_dur / GST_USECOND;
+            GST_DEBUG_OBJECT (avi, "correcting stream framerate to %d/%d",
+                strh->rate, strh->scale);
+          }
+        }
+        /* determine duration as indicated by header */
+        stream->hdr_duration = gst_util_uint64_scale ((guint64) strh->length *
+            strh->scale, GST_SECOND, (guint64) strh->rate);
+        GST_INFO ("Stream duration according to header: %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (stream->hdr_duration));
+        if (stream->hdr_duration == 0)
+          stream->hdr_duration = GST_CLOCK_TIME_NONE;
+
+        got_strh = TRUE;
+        break;
+      }
+      case GST_RIFF_TAG_strf:
+      {
+        gboolean res = FALSE;
+
+        if (got_strf) {
+          GST_WARNING_OBJECT (avi, "Ignoring additional strf chunk");
+          break;
+        }
+        if (!got_strh) {
+          GST_ERROR_OBJECT (avi, "Found strf chunk before strh chunk");
+          goto fail;
+        }
+        switch (stream->strh->type) {
+          case GST_RIFF_FCC_vids:
+            stream->is_vbr = TRUE;
+            res = gst_riff_parse_strf_vids (element, sub,
+                &stream->strf.vids, &stream->extradata);
+            sub = NULL;
+            GST_DEBUG_OBJECT (element, "marking video as VBR, res %d", res);
+            break;
+          case GST_RIFF_FCC_auds:
+            stream->is_vbr = (stream->strh->samplesize == 0)
+                && stream->strh->scale > 1;
+            res =
+                gst_riff_parse_strf_auds (element, sub, &stream->strf.auds,
+                &stream->extradata);
+            sub = NULL;
+            GST_DEBUG_OBJECT (element, "marking audio as VBR:%d, res %d",
+                stream->is_vbr, res);
+            break;
+          case GST_RIFF_FCC_iavs:
+            stream->is_vbr = TRUE;
+            res = gst_riff_parse_strf_iavs (element, sub,
+                &stream->strf.iavs, &stream->extradata);
+            sub = NULL;
+            GST_DEBUG_OBJECT (element, "marking iavs as VBR, res %d", res);
+            break;
+          case GST_RIFF_FCC_txts:
+            /* nothing to parse here */
+            stream->is_vbr = (stream->strh->samplesize == 0)
+                && (stream->strh->scale > 1);
+            res = TRUE;
+            break;
+          default:
+            GST_ERROR_OBJECT (avi,
+                "Don´t know how to handle stream type %" GST_FOURCC_FORMAT,
+                GST_FOURCC_ARGS (stream->strh->type));
+            break;
+        }
+        if (sub) {
+          gst_buffer_unref (sub);
+          sub = NULL;
+        }
+        if (!res)
+          goto fail;
+        got_strf = TRUE;
+        break;
+      }
+      case GST_RIFF_TAG_vprp:
+      {
+        if (got_vprp) {
+          GST_WARNING_OBJECT (avi, "Ignoring additional vprp chunk");
+          break;
+        }
+        if (!got_strh) {
+          GST_ERROR_OBJECT (avi, "Found vprp chunk before strh chunk");
+          goto fail;
+        }
+        if (!got_strf) {
+          GST_ERROR_OBJECT (avi, "Found vprp chunk before strf chunk");
+          goto fail;
+        }
+
+        if (!gst_avi_demux_riff_parse_vprp (element, sub, &vprp)) {
+          GST_WARNING_OBJECT (avi, "Failed to parse vprp chunk");
+          /* not considered fatal */
+          g_free (vprp);
+          vprp = NULL;
+        } else
+          got_vprp = TRUE;
+        sub = NULL;
+        break;
+      }
+      case GST_RIFF_TAG_strd:
+        if (stream->initdata)
+          gst_buffer_unref (stream->initdata);
+        stream->initdata = sub;
+        sub = NULL;
+        break;
+      case GST_RIFF_TAG_strn:
+        g_free (stream->name);
+        if (sub != NULL) {
+          stream->name =
+              g_strndup ((gchar *) GST_BUFFER_DATA (sub),
+              (gsize) GST_BUFFER_SIZE (sub));
+          gst_buffer_unref (sub);
+          sub = NULL;
+        } else {
+          stream->name = g_strdup ("");
+        }
+        GST_DEBUG_OBJECT (avi, "stream name: %s", stream->name);
+        break;
+      default:
+        if (tag == GST_MAKE_FOURCC ('i', 'n', 'd', 'x') ||
+            tag == GST_MAKE_FOURCC ('i', 'x', '0' + avi->num_streams / 10,
+                '0' + avi->num_streams % 10)) {
+          g_free (stream->indexes);
+          gst_avi_demux_parse_superindex (avi, sub, &stream->indexes);
+          stream->superindex = TRUE;
+          sub = NULL;
+          break;
+        }
+        GST_WARNING_OBJECT (avi,
+            "Unknown stream header tag %" GST_FOURCC_FORMAT ", ignoring",
+            GST_FOURCC_ARGS (tag));
+        /* fall-through */
+      case GST_RIFF_TAG_JUNK:
+        break;
+    }
+    if (sub != NULL) {
+      gst_buffer_unref (sub);
+      sub = NULL;
+    }
+  }
+
+  if (!got_strh) {
+    GST_WARNING_OBJECT (avi, "Failed to find strh chunk");
+    goto fail;
+  }
+
+  if (!got_strf) {
+    GST_WARNING_OBJECT (avi, "Failed to find strf chunk");
+    goto fail;
+  }
+
+  /* get class to figure out the template */
+  klass = GST_ELEMENT_GET_CLASS (avi);
+
+  /* we now have all info, let´s set up a pad and a caps and be done */
+  /* create stream name + pad */
+  switch (stream->strh->type) {
+    case GST_RIFF_FCC_vids:{
+      guint32 fourcc;
+
+      fourcc = (stream->strf.vids->compression) ?
+          stream->strf.vids->compression : stream->strh->fcc_handler;
+      padname = g_strdup_printf ("video_%02d", avi->num_v_streams);
+      templ = gst_element_class_get_pad_template (klass, "video_%02d");
+      caps = gst_riff_create_video_caps (fourcc, stream->strh,
+          stream->strf.vids, stream->extradata, stream->initdata, &codec_name);
+      if (!caps) {
+        caps = gst_caps_new_simple ("video/x-avi-unknown", "fourcc",
+            GST_TYPE_FOURCC, fourcc, NULL);
+      } else if (got_vprp && vprp) {
+        guint32 aspect_n, aspect_d;
+        gint n, d;
+
+        aspect_n = vprp->aspect >> 16;
+        aspect_d = vprp->aspect & 0xffff;
+        /* calculate the pixel aspect ratio using w/h and aspect ratio */
+        n = aspect_n * stream->strf.vids->height;
+        d = aspect_d * stream->strf.vids->width;
+        if (n && d)
+          gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
+              n, d, NULL);
+        /* very local, not needed elsewhere */
+        g_free (vprp);
+        vprp = NULL;
+      }
+      tag_name = GST_TAG_VIDEO_CODEC;
+      avi->num_v_streams++;
+      break;
+    }
+    case GST_RIFF_FCC_auds:{
+      padname = g_strdup_printf ("audio_%02d", avi->num_a_streams);
+      templ = gst_element_class_get_pad_template (klass, "audio_%02d");
+      caps = gst_riff_create_audio_caps (stream->strf.auds->format,
+          stream->strh, stream->strf.auds, stream->extradata,
+          stream->initdata, &codec_name);
+      if (!caps) {
+        caps = gst_caps_new_simple ("audio/x-avi-unknown", "codec_id",
+            G_TYPE_INT, stream->strf.auds->format, NULL);
+      }
+      tag_name = GST_TAG_AUDIO_CODEC;
+      avi->num_a_streams++;
+      break;
+    }
+    case GST_RIFF_FCC_iavs:{
+      guint32 fourcc = stream->strh->fcc_handler;
+
+      padname = g_strdup_printf ("video_%02d", avi->num_v_streams);
+      templ = gst_element_class_get_pad_template (klass, "video_%02d");
+      caps = gst_riff_create_iavs_caps (fourcc, stream->strh,
+          stream->strf.iavs, stream->extradata, stream->initdata, &codec_name);
+      if (!caps) {
+        caps = gst_caps_new_simple ("video/x-avi-unknown", "fourcc",
+            GST_TYPE_FOURCC, fourcc, NULL);
+      }
+      tag_name = GST_TAG_VIDEO_CODEC;
+      avi->num_v_streams++;
+      break;
+    }
+    case GST_RIFF_FCC_txts:{
+      padname = g_strdup_printf ("subtitle_%02d", avi->num_t_streams);
+      templ = gst_element_class_get_pad_template (klass, "subtitle_%02d");
+      caps = gst_caps_new_simple ("application/x-subtitle-avi", NULL);
+      tag_name = NULL;
+      avi->num_t_streams++;
+      break;
+    }
+    default:
+      g_assert_not_reached ();
+  }
+
+  /* no caps means no stream */
+  if (!caps) {
+    GST_ERROR_OBJECT (element, "Did not find caps for stream %s", padname);
+    goto fail;
+  }
+
+  GST_DEBUG_OBJECT (element, "codec-name=%s",
+      (codec_name ? codec_name : "NULL"));
+  GST_DEBUG_OBJECT (element, "caps=%" GST_PTR_FORMAT, caps);
+
+  /* set proper settings and add it */
+  if (stream->pad)
+    gst_object_unref (stream->pad);
+  pad = stream->pad = gst_pad_new_from_template (templ, padname);
+  stream->last_flow = GST_FLOW_OK;
+  stream->discont = TRUE;
+  g_free (padname);
+
+  gst_pad_use_fixed_caps (pad);
+#if 0
+  gst_pad_set_formats_function (pad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_get_src_formats));
+  gst_pad_set_event_mask_function (pad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_get_event_mask));
+#endif
+  gst_pad_set_event_function (pad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_handle_src_event));
+  gst_pad_set_query_type_function (pad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_get_src_query_types));
+  gst_pad_set_query_function (pad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_handle_src_query));
+#if 0
+  gst_pad_set_convert_function (pad,
+      GST_DEBUG_FUNCPTR (gst_avi_demux_src_convert));
+#endif
+
+  stream->num = avi->num_streams;
+  stream->total_bytes = 0;
+  stream->total_frames = 0;
+  stream->total_blocks = 0;
+  stream->current_frame = 0;
+  stream->current_byte = 0;
+  gst_pad_set_element_private (pad, stream);
+  avi->num_streams++;
+  gst_pad_set_caps (pad, caps);
+  gst_pad_set_active (pad, TRUE);
+  gst_element_add_pad (GST_ELEMENT (avi), pad);
+  GST_LOG_OBJECT (element, "Added pad %s with caps %" GST_PTR_FORMAT,
+      GST_PAD_NAME (pad), caps);
+  gst_caps_unref (caps);
+
+  /* make tags */
+  if (codec_name) {
+    if (!stream->taglist)
+      stream->taglist = gst_tag_list_new ();
+
+    avi->got_tags = TRUE;
+
+    gst_tag_list_add (stream->taglist, GST_TAG_MERGE_APPEND, tag_name,
+        codec_name, NULL);
+    g_free (codec_name);
+  }
+
+  gst_buffer_unref (buf);
+
+  return TRUE;
+
+  /* ERRORS */
+fail:
+  {
+    /* unref any mem that may be in use */
+    if (buf)
+      gst_buffer_unref (buf);
+    if (sub)
+      gst_buffer_unref (sub);
+    g_free (vprp);
+    g_free (codec_name);
+    g_free (stream->strh);
+    g_free (stream->strf.data);
+    g_free (stream->name);
+    g_free (stream->indexes);
+    if (stream->initdata)
+      gst_buffer_unref (stream->initdata);
+    if (stream->extradata)
+      gst_buffer_unref (stream->extradata);
+    memset (stream, 0, sizeof (avi_stream_context));
+    avi->num_streams++;
+    return FALSE;
+  }
+}
+
+/*
+ * gst_avi_demux_parse_odml:
+ * @avi: calling element (used for debug/error).
+ * @buf: input buffer to be used for parsing.
+ *
+ * Read an openDML-2.0 extension header. Fills in the frame number
+ * in the avi demuxer object when reading succeeds.
+ */
+static void
+gst_avi_demux_parse_odml (GstAviDemux * avi, GstBuffer * buf)
+{
+  guint32 tag = 0;
+  guint offset = 4;
+  GstBuffer *sub = NULL;
+
+  while (gst_riff_parse_chunk (GST_ELEMENT_CAST (avi), buf, &offset, &tag,
+          &sub)) {
+    switch (tag) {
+      case GST_RIFF_TAG_dmlh:{
+        gst_riff_dmlh dmlh, *_dmlh;
+        guint size;
+
+        /* sub == NULL is possible and means an empty buffer */
+        size = sub ? GST_BUFFER_SIZE (sub) : 0;
+
+        /* check size */
+        if (size < sizeof (gst_riff_dmlh)) {
+          GST_ERROR_OBJECT (avi,
+              "DMLH entry is too small (%d bytes, %d needed)",
+              size, (int) sizeof (gst_riff_dmlh));
+          goto next;
+        }
+        _dmlh = (gst_riff_dmlh *) GST_BUFFER_DATA (sub);
+        dmlh.totalframes = GST_READ_UINT32_LE (&_dmlh->totalframes);
+
+        GST_INFO_OBJECT (avi, "dmlh tag found:");
+        GST_INFO_OBJECT (avi, " totalframes: %u", dmlh.totalframes);
+
+        avi->avih->tot_frames = dmlh.totalframes;
+        goto next;
+      }
+
+      default:
+        GST_WARNING_OBJECT (avi,
+            "Unknown tag %" GST_FOURCC_FORMAT " in ODML header",
+            GST_FOURCC_ARGS (tag));
+        /* fall-through */
+      case GST_RIFF_TAG_JUNK:
+      next:
+        /* skip and move to next chunk */
+        if (sub) {
+          gst_buffer_unref (sub);
+          sub = NULL;
+        }
+        break;
+    }
+  }
+  if (buf)
+    gst_buffer_unref (buf);
+}
+
+/*
+ * Sort helper for index entries that sorts by index time.
+ * If times are equal we sort by stream number.
+ */
+static gint
+sort (gst_avi_index_entry * a, gst_avi_index_entry * b)
+{
+  if (a->ts > b->ts)
+    return 1;
+  else if (a->ts < b->ts)
+    return -1;
+  else
+    return a->stream_nr - b->stream_nr;
+}
+
+/*
+ * gst_avi_demux_parse_index:
+ * @avi: calling element (used for debugging/errors).
+ * @buf: buffer containing the full index.
+ * @entries_list: list (returned by this function) containing the index
+ *                entries parsed from the buffer. The first in the list
+ *                is also a pointer to the allocated data and should be
+ *                free'ed at some point.
+ *
+ * Read index entries from the provided buffer. Takes ownership of @buf.
+ */
+static void
+gst_avi_demux_parse_index (GstAviDemux * avi,
+    GstBuffer * buf, GList ** _entries_list)
+{
+  guint64 pos_before = avi->offset;
+  gst_avi_index_entry *entries = NULL;
+  guint8 *data;
+  GList *entries_list = NULL;
+  guint i, num, n;
+
+#ifndef GST_DISABLE_GST_DEBUG
+  gulong _nr_keyframes = 0;
+#endif
+
+  if (!buf || !GST_BUFFER_SIZE (buf)) {
+    *_entries_list = NULL;
+    GST_DEBUG ("empty index");
+    if (buf)
+      gst_buffer_unref (buf);
+    return;
+  }
+
+  data = GST_BUFFER_DATA (buf);
+  num = GST_BUFFER_SIZE (buf) / sizeof (gst_riff_index_entry);
+  if (!(entries = g_try_new (gst_avi_index_entry, num)))
+    goto out_of_mem;
+
+  GST_INFO ("Parsing index, nr_entries = %6d", num);
+
+  for (i = 0, n = 0; i < num; i++) {
+    gint64 next_ts;
+    gst_riff_index_entry entry, *_entry;
+    avi_stream_context *stream;
+    guint stream_nr;
+    gst_avi_index_entry *target;
+
+    _entry = &((gst_riff_index_entry *) data)[i];
+    entry.id = GST_READ_UINT32_LE (&_entry->id);
+    entry.offset = GST_READ_UINT32_LE (&_entry->offset);
+    entry.flags = GST_READ_UINT32_LE (&_entry->flags);
+    entry.size = GST_READ_UINT32_LE (&_entry->size);
+    target = &entries[n];
+
+    if (entry.id == GST_RIFF_rec || entry.id == 0 ||
+        (entry.offset == 0 && n > 0))
+      continue;
+
+    stream_nr = CHUNKID_TO_STREAMNR (entry.id);
+    if (stream_nr >= avi->num_streams) {
+      GST_WARNING_OBJECT (avi,
+          "Index entry %d has invalid stream nr %d", i, stream_nr);
+      continue;
+    }
+    target->stream_nr = stream_nr;
+    stream = &avi->stream[stream_nr];
+
+    if (!stream->strh) {
+      GST_WARNING_OBJECT (avi, "Unhandled stream %d, skipping", stream_nr);
+      continue;
+    }
+
+    target->index_nr = i;
+    target->flags =
+        (entry.flags & GST_RIFF_IF_KEYFRAME) ? GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME
+        : 0;
+    target->size = entry.size;
+    target->offset = entry.offset + 8;
+
+    /* figure out if the index is 0 based or relative to the MOVI start */
+    if (n == 0) {
+      if (target->offset < pos_before)
+        avi->index_offset = pos_before + 8;
+      else
+        avi->index_offset = 0;
+      GST_DEBUG ("index_offset = %" G_GUINT64_FORMAT, avi->index_offset);
+    }
+
+    if (stream->strh->type == GST_RIFF_FCC_auds) {
+      /* all audio frames are keyframes */
+      target->flags |= GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME;
+    }
+#ifndef GST_DISABLE_GST_DEBUG
+    if (target->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME)
+      _nr_keyframes++;
+#endif
+
+    /* stream duration unknown, now we can calculate it */
+    if (stream->idx_duration == -1)
+      stream->idx_duration = 0;
+
+    /* timestamps */
+    target->ts = stream->idx_duration;
+    if (stream->is_vbr) {
+      /* VBR stream next timestamp */
+      if (stream->strh->type == GST_RIFF_FCC_auds) {
+        next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
+            stream->total_blocks + 1);
+      } else {
+        next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
+            stream->total_frames + 1);
+      }
+    } else {
+      /* constant rate stream */
+      next_ts = avi_stream_convert_bytes_to_time_unchecked (stream,
+          stream->total_bytes + target->size);
+    }
+    /* duration is next - current */
+    target->dur = next_ts - target->ts;
+
+    /* stream position */
+    target->bytes_before = stream->total_bytes;
+    target->frames_before = stream->total_frames;
+
+    stream->total_bytes += target->size;
+    stream->total_frames++;
+    if (stream->strh->type == GST_RIFF_FCC_auds) {
+      if (stream->strf.auds->blockalign > 0)
+        stream->total_blocks +=
+            (target->size + stream->strf.auds->blockalign -
+            1) / stream->strf.auds->blockalign;
+      else
+        stream->total_blocks++;
+    }
+    stream->idx_duration = next_ts;
+
+    GST_LOG_OBJECT (avi,
+        "Adding index entry %d (%6u), flags %02x, stream %d, size %u "
+        ", offset %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT ", dur %"
+        GST_TIME_FORMAT,
+        target->index_nr, stream->total_frames - 1, target->flags,
+        target->stream_nr, target->size, target->offset,
+        GST_TIME_ARGS (target->ts), GST_TIME_ARGS (target->dur));
+    entries_list = g_list_prepend (entries_list, target);
+
+    n++;
+  }
+
+  GST_INFO ("Parsed index, %6d entries, %5ld keyframes, entry size = %2d, "
+      "total size = %10d", num, _nr_keyframes,
+      (gint) sizeof (gst_avi_index_entry),
+      (gint) (num * sizeof (gst_avi_index_entry)));
+
+  gst_buffer_unref (buf);
+
+  if (n > 0) {
+    *_entries_list = g_list_reverse (entries_list);
+  } else {
+    g_free (entries);
+  }
+  return;
+
+  /* ERRORS */
+out_of_mem:
+  {
+    GST_ELEMENT_ERROR (avi, RESOURCE, NO_SPACE_LEFT, (NULL),
+        ("Cannot allocate memory for %u*%u=%u bytes",
+            (guint) sizeof (gst_avi_index_entry), num,
+            (guint) sizeof (gst_avi_index_entry) * num));
+    gst_buffer_unref (buf);
+  }
+}
+
+/*
+ * gst_avi_demux_stream_index:
+ * @avi: avi demuxer object.
+ * @index: list of index entries, returned by this function.
+ * @alloc_list: list of allocated data, returned by this function.
+ *
+ * Seeks to index and reads it.
+ */
+static void
+gst_avi_demux_stream_index (GstAviDemux * avi,
+    GList ** index, GList ** alloc_list)
+{
+  GstFlowReturn res;
+  guint64 offset = avi->offset;
+  GstBuffer *buf;
+  guint32 tag;
+  guint32 size;
+  gint i;
+
+  GST_DEBUG ("demux stream index at offset %" G_GUINT64_FORMAT, offset);
+
+  *alloc_list = NULL;
+  *index = NULL;
+
+  /* get chunk information */
+  res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf);
+  if (res != GST_FLOW_OK)
+    goto pull_failed;
+  else if (GST_BUFFER_SIZE (buf) < 8)
+    goto too_small;
+
+  /* check tag first before blindy trying to read 'size' bytes */
+  tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
+  size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
+  if (tag == GST_RIFF_TAG_LIST) {
+    /* this is the movi tag */
+    GST_DEBUG_OBJECT (avi, "skip LIST chunk, size %" G_GUINT32_FORMAT,
+        (8 + ((size + 1) & ~1)));
+    offset += 8 + ((size + 1) & ~1);
+    gst_buffer_unref (buf);
+    res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf);
+    if (res != GST_FLOW_OK)
+      goto pull_failed;
+    else if (GST_BUFFER_SIZE (buf) < 8)
+      goto too_small;
+    tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
+    size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
+  }
+
+  if (tag != GST_RIFF_TAG_idx1)
+    goto no_index;
+  if (!size)
+    goto zero_index;
+
+  gst_buffer_unref (buf);
+
+  GST_DEBUG ("index found at offset %" G_GUINT64_FORMAT, offset);
+
+  /* read chunk, advance offset */
+  if (gst_riff_read_chunk (GST_ELEMENT_CAST (avi),
+          avi->sinkpad, &offset, &tag, &buf) != GST_FLOW_OK)
+    return;
+
+  GST_INFO ("will parse index chunk size %u for tag %"
+      GST_FOURCC_FORMAT, GST_BUFFER_SIZE (buf), GST_FOURCC_ARGS (tag));
+
+  gst_avi_demux_parse_index (avi, buf, index);
+  if (*index)
+    *alloc_list = g_list_append (*alloc_list, (*index)->data);
+
+  /* debug our indexes */
+  for (i = 0; i < avi->num_streams; i++) {
+    avi_stream_context *stream;
+
+    stream = &avi->stream[i];
+    GST_DEBUG_OBJECT (avi, "stream %u: %u frames, %" G_GINT64_FORMAT " bytes",
+        i, stream->total_frames, stream->total_bytes);
+  }
+  return;
+
+  /* ERRORS */
+pull_failed:
+  {
+    GST_DEBUG_OBJECT (avi,
+        "pull range failed: pos=%" G_GUINT64_FORMAT " size=8", offset);
+    return;
+  }
+too_small:
+  {
+    GST_DEBUG_OBJECT (avi, "Buffer is too small");
+    gst_buffer_unref (buf);
+    return;
+  }
+no_index:
+  {
+    GST_WARNING_OBJECT (avi,
+        "No index data (idx1) after movi chunk, but %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (tag));
+    gst_buffer_unref (buf);
+    return;
+  }
+zero_index:
+  {
+    GST_WARNING_OBJECT (avi, "Empty index data (idx1) after movi chunk");
+    gst_buffer_unref (buf);
+    return;
+  }
+}
+
+#if 0
+/*
+ * Sync to next data chunk.
+ */
+static gboolean
+gst_avi_demux_skip (GstAviDemux * avi, gboolean prevent_eos)
+{
+  GstRiffRead *riff = GST_RIFF_READ (avi);
+
+  if (prevent_eos) {
+    guint64 pos, length;
+    guint size;
+    guint8 *data;
+
+    pos = gst_bytestream_tell (riff->bs);
+    length = gst_bytestream_length (riff->bs);
+
+    if (pos + 8 > length)
+      return FALSE;
+
+    if (gst_bytestream_peek_bytes (riff->bs, &data, 8) != 8)
+      return FALSE;
+
+    size = GST_READ_UINT32_LE (&data[4]);
+    if (size & 1)
+      size++;
+
+    /* Note, we're going to skip which might involve seeks. Therefore,
+     * we need 1 byte more! */
+    if (pos + 8 + size >= length)
+      return FALSE;
+  }
+
+  return gst_riff_read_skip (riff);
+}
+
+static gboolean
+gst_avi_demux_sync (GstAviDemux * avi, guint32 * ret_tag, gboolean prevent_eos)
+{
+  GstRiffRead *riff = GST_RIFF_READ (avi);
+  guint32 tag;
+  guint64 length = gst_bytestream_length (riff->bs);
+
+  if (prevent_eos && gst_bytestream_tell (riff->bs) + 12 >= length)
+    return FALSE;
+
+  /* peek first (for the end of this 'list/movi' section) */
+  if (!(tag = gst_riff_peek_tag (riff, &avi->level_up)))
+    return FALSE;
+
+  /* if we're at top-level, we didn't read the 'movi'
+   * list tag yet. This can also be 'AVIX' in case of
+   * openDML-2.0 AVI files. Lastly, it might be idx1,
+   * in which case we skip it so we come at EOS. */
+  while (1) {
+    if (prevent_eos && gst_bytestream_tell (riff->bs) + 12 >= length)
+      return FALSE;
+
+    if (!(tag = gst_riff_peek_tag (riff, NULL)))
+      return FALSE;
+
+    switch (tag) {
+      case GST_RIFF_TAG_LIST:
+        if (!(tag = gst_riff_peek_list (riff)))
+          return FALSE;
+
+        switch (tag) {
+          case GST_RIFF_LIST_AVIX:
+            if (!gst_riff_read_list (riff, &tag))
+              return FALSE;
+            break;
+
+          case GST_RIFF_LIST_movi:
+            if (!gst_riff_read_list (riff, &tag))
+              return FALSE;
+            /* fall-through */
+
+          case GST_RIFF_rec:
+            goto done;
+
+          default:
+            GST_WARNING ("Unknown list %" GST_FOURCC_FORMAT " before AVI data",
+                GST_FOURCC_ARGS (tag));
+            /* fall-through */
+
+          case GST_RIFF_TAG_JUNK:
+            if (!gst_avi_demux_skip (avi, prevent_eos))
+              return FALSE;
+            break;
+        }
+        break;
+
+      default:
+        if ((tag & 0xff) >= '0' && (tag & 0xff) <= '9' &&
+            ((tag >> 8) & 0xff) >= '0' && ((tag >> 8) & 0xff) <= '9') {
+          goto done;
+        }
+        /* pass-through */
+
+      case GST_RIFF_TAG_idx1:
+      case GST_RIFF_TAG_JUNK:
+        if (!gst_avi_demux_skip (avi, prevent_eos)) {
+          return FALSE;
+        }
+        break;
+    }
+  }
+done:
+  /* And then, we get the data */
+  if (prevent_eos && gst_bytestream_tell (riff->bs) + 12 >= length)
+    return FALSE;
+
+  if (!(tag = gst_riff_peek_tag (riff, NULL)))
+    return FALSE;
+
+  /* Support for rec-list files */
+  switch (tag) {
+    case GST_RIFF_TAG_LIST:
+      if (!(tag = gst_riff_peek_list (riff)))
+        return FALSE;
+      if (tag == GST_RIFF_rec) {
+        /* Simply skip the list */
+        if (!gst_riff_read_list (riff, &tag))
+          return FALSE;
+        if (!(tag = gst_riff_peek_tag (riff, NULL)))
+          return FALSE;
+      }
+      break;
+
+    case GST_RIFF_TAG_JUNK:
+      gst_avi_demux_skip (avi, prevent_eos);
+      return FALSE;
+  }
+
+  if (ret_tag)
+    *ret_tag = tag;
+
+  return TRUE;
+}
+#endif
+
+/*
+ * gst_avi_demux_peek_tag:
+ *
+ * Returns the tag and size of the next chunk
+ */
+static GstFlowReturn
+gst_avi_demux_peek_tag (GstAviDemux * avi, guint64 offset, guint32 * tag,
+    guint * size)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+  GstBuffer *buf = NULL;
+  guint bufsize;
+
+  res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf);
+  if (res != GST_FLOW_OK)
+    goto pull_failed;
+
+  bufsize = GST_BUFFER_SIZE (buf);
+  if (bufsize != 8)
+    goto wrong_size;
+
+  *tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
+  *size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
+
+  GST_LOG_OBJECT (avi, "Tag[%" GST_FOURCC_FORMAT "] (size:%d) %"
+      G_GINT64_FORMAT " -- %" G_GINT64_FORMAT, GST_FOURCC_ARGS (*tag),
+      *size, offset + 8, offset + 8 + (gint64) * size);
+done:
+  gst_buffer_unref (buf);
+
+  return res;
+
+  /* ERRORS */
+pull_failed:
+  {
+    GST_DEBUG_OBJECT (avi, "pull_ranged returned %s", gst_flow_get_name (res));
+    return res;
+  }
+wrong_size:
+  {
+    GST_DEBUG_OBJECT (avi, "got %d bytes which is <> 8 bytes", bufsize);
+    res = GST_FLOW_ERROR;
+    goto done;
+  }
+}
+
+/*
+ * gst_avi_demux_next_data_buffer:
+ *
+ * Returns the offset and size of the next buffer
+ * Position is the position of the buffer (after tag and size)
+ */
+static GstFlowReturn
+gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset,
+    guint32 * tag, guint * size)
+{
+  guint64 off = *offset;
+  guint _size = 0;
+  GstFlowReturn res;
+
+  do {
+    res = gst_avi_demux_peek_tag (avi, off, tag, &_size);
+    if (res != GST_FLOW_OK)
+      break;
+    if (*tag == GST_RIFF_TAG_LIST || *tag == GST_RIFF_TAG_RIFF)
+      off += 8 + 4;             /* skip tag + size + subtag */
+    else {
+      *offset = off + 8;
+      *size = _size;
+      break;
+    }
+  } while (TRUE);
+
+  return res;
+}
+
+/*
+ * gst_avi_demux_stream_scan:
+ * @avi: calling element (used for debugging/errors).
+ * @index: list of index entries, returned by this function.
+ * @alloc_list: list of allocated data, returned by this function.
+ *
+ * Scan the file for all chunks to "create" a new index.
+ * Return value indicates if we can continue reading the stream. It
+ * does not say anything about whether we created an index.
+ *
+ * pull-range based
+ */
+static gboolean
+gst_avi_demux_stream_scan (GstAviDemux * avi,
+    GList ** index, GList ** alloc_list)
+{
+  GstFlowReturn res;
+  gst_avi_index_entry *entry, *entries = NULL;
+  avi_stream_context *stream;
+  GstFormat format;
+  guint64 pos = avi->offset;
+  guint64 length;
+  gint64 tmplength;
+  guint32 tag = 0;
+  GList *list = NULL;
+  guint index_size = 0;
+
+  /* FIXME:
+   * - implement non-seekable source support.
+   */
+  GST_DEBUG_OBJECT (avi,
+      "Creating index %s existing index, starting at offset %" G_GUINT64_FORMAT,
+      ((*index) ? "with" : "without"), pos);
+
+  format = GST_FORMAT_BYTES;
+  if (!gst_pad_query_peer_duration (avi->sinkpad, &format, &tmplength))
+    return FALSE;
+
+  length = tmplength;
+
+  if (*index) {
+    entry = g_list_last (*index)->data;
+    pos = entry->offset + avi->index_offset + entry->size;
+    if (entry->size & 1)
+      pos++;
+
+    if (pos >= length) {
+      GST_LOG_OBJECT (avi, "Complete index, we're done");
+      return TRUE;
+    }
+
+    GST_LOG_OBJECT (avi, "Incomplete index, seeking to last valid entry @ %"
+        G_GUINT64_FORMAT " of %" G_GUINT64_FORMAT " (%"
+        G_GUINT64_FORMAT "+%u)", pos, length, entry->offset, entry->size);
+  }
+
+  while (TRUE) {
+    guint stream_nr;
+    guint size = 0;
+
+    res = gst_avi_demux_next_data_buffer (avi, &pos, &tag, &size);
+    if (G_UNLIKELY (res != GST_FLOW_OK))
+      break;
+
+    /* check valid stream */
+    stream_nr = CHUNKID_TO_STREAMNR (tag);
+    if (G_UNLIKELY (stream_nr >= avi->num_streams)) {
+      GST_WARNING_OBJECT (avi,
+          "Index entry has invalid stream nr %d", stream_nr);
+      goto next;
+    }
+
+    stream = &avi->stream[stream_nr];
+    if (G_UNLIKELY (stream->pad == NULL)) {
+      GST_WARNING_OBJECT (avi,
+          "Stream %d does not have an output pad, can't create new index",
+          stream_nr);
+      goto next;
+    }
+
+    /* pre-allocate */
+    if (G_UNLIKELY (index_size % 1024 == 0)) {
+      entries = g_new (gst_avi_index_entry, 1024);
+      *alloc_list = g_list_prepend (*alloc_list, entries);
+    }
+    entry = &entries[index_size % 1024];
+
+    entry->index_nr = index_size++;
+    entry->stream_nr = stream_nr;
+    entry->flags = GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME;
+    entry->offset = pos - avi->index_offset;
+    entry->size = size;
+
+    /* timestamps, get timestamps of two consecutive frames to calculate
+     * timestamp and duration. */
+    format = GST_FORMAT_TIME;
+    if (stream->is_vbr) {
+      /* VBR stream */
+      entry->ts = avi_stream_convert_frames_to_time_unchecked (stream,
+          stream->total_frames);
+      entry->dur = avi_stream_convert_frames_to_time_unchecked (stream,
+          stream->total_frames + 1);
+    } else {
+      /* constant rate stream */
+      entry->ts = avi_stream_convert_bytes_to_time_unchecked (stream,
+          stream->total_bytes);
+      entry->dur = avi_stream_convert_bytes_to_time_unchecked (stream,
+          stream->total_bytes + entry->size);
+    }
+    entry->dur -= entry->ts;
+
+    /* stream position */
+    entry->bytes_before = stream->total_bytes;
+    stream->total_bytes += entry->size;
+    entry->frames_before = stream->total_frames;
+    stream->total_frames++;
+    stream->idx_duration = entry->ts + entry->dur;
+
+    list = g_list_prepend (list, entry);
+    GST_DEBUG_OBJECT (avi, "Added index entry %d (in stream: %d), offset %"
+        G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT " for stream %d",
+        index_size - 1, entry->frames_before, entry->offset,
+        GST_TIME_ARGS (entry->ts), entry->stream_nr);
+
+  next:
+    /* update position */
+    pos += GST_ROUND_UP_2 (size);
+    if (G_UNLIKELY (pos > length)) {
+      GST_WARNING_OBJECT (avi,
+          "Stopping index lookup since we are further than EOF");
+      break;
+    }
+  }
+
+  /* FIXME: why is this disabled */
+#if 0
+  while (gst_avi_demux_sync (avi, &tag, TRUE)) {
+    guint stream_nr = CHUNKID_TO_STREAMNR (tag);
+    guint8 *data;
+    GstFormat format = GST_FORMAT_TIME;
+
+    if (stream_nr >= avi->num_streams)
+      goto next;
+    stream = &avi->stream[stream_nr];
+
+    /* get chunk size */
+    if (gst_bytestream_peek_bytes (riff->bs, &data, 8) != 8)
+      goto next;
+
+    /* fill in */
+    entry->index_nr = index_size++;
+    entry->stream_nr = stream_nr;
+    entry->flags = GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME;
+    entry->offset = gst_bytestream_tell (riff->bs) + 8 - avi->index_offset;
+    entry->size = GST_READ_UINT32_LE (&data[4]);
+
+    /* timestamps */
+    if (stream->is_vbr) {
+      /* VBR stream */
+      entry->ts = avi_stream_convert_frames_to_time_unchecked (stream,
+          stream->total_frames);
+      entry->dur = avi_stream_convert_frames_to_time_unchecked (stream,
+          stream->total_frames + 1);
+    } else {
+      /* constant rate stream */
+      entry->ts = avi_stream_convert_bytes_to_time_unchecked (stream,
+          stream->total_bytes);
+      entry->dur = avi_stream_convert_bytes_to_time_unchecked (stream,
+          stream->total_bytes + entry->size);
+    }
+    entry->dur -= entry->ts;
+
+    /* stream position */
+    entry->bytes_before = stream->total_bytes;
+    stream->total_bytes += entry->size;
+    entry->frames_before = stream->total_frames;
+    stream->total_frames++;
+
+    list = g_list_prepend (list, entry);
+    GST_DEBUG_OBJECT (avi, "Added index entry %d (in stream: %d), offset %"
+        G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT " for stream %d",
+        index_size - 1, entry->frames_before, entry->offset,
+        GST_TIME_ARGS (entry->ts), entry->stream_nr);
+
+  next:
+    if (!gst_avi_demux_skip (avi, TRUE))
+      break;
+  }
+  /* seek back */
+  if (!(event = gst_riff_read_seek (riff, pos))) {
+    g_list_free (list);
+    return FALSE;
+  }
+  gst_event_unref (event);
+
+#endif
+
+  GST_DEBUG_OBJECT (avi, "index created, %d items", index_size);
+
+  *index = g_list_concat (*index, g_list_reverse (list));
+
+  return TRUE;
+}
+
+/*
+ * gst_avi_demux_massage_index:
+ * @avi: calling element (used for debugging/errors).
+ *
+ * We're going to go over each entry in the index and finetune
+ * some things we don't like about AVI. For example, a single
+ * chunk might be too long. Also, individual streams might be
+ * out-of-sync. In the first case, we cut the chunk in several
+ * smaller pieces. In the second case, we re-order chunk reading
+ * order. The end result should be a smoother playing AVI.
+ */
+static gboolean
+gst_avi_demux_massage_index (GstAviDemux * avi,
+    GList * list, GList * alloc_list)
+{
+  gst_avi_index_entry *entry;
+  avi_stream_context *stream;
+  guint i;
+  GList *node;
+  gint64 delay = G_GINT64_CONSTANT (0);
+
+  GST_LOG_OBJECT (avi, "Starting index massage, nr_entries = %d",
+      list ? g_list_length (list) : 0);
+
+  if (list) {
+#ifndef GST_DISABLE_GST_DEBUG
+    guint num_added_total = 0;
+    guint num_per_stream[GST_AVI_DEMUX_MAX_STREAMS] = { 0, };
+#endif
+    GST_LOG_OBJECT (avi,
+        "I'm now going to cut large chunks into smaller pieces");
+
+    /* cut chunks in small (seekable) pieces
+     * FIXME: this should be a property where a value of
+     * GST_CLOCK_TIME_NONE would disable the chunking
+     */
+#define MAX_DURATION (GST_SECOND / 2)
+    for (i = 0; i < avi->num_streams; i++) {
+      /* only chop streams that have exactly *one* chunk */
+      if (avi->stream[i].total_frames != 1)
+        continue;
+
+      for (node = list; node != NULL; node = node->next) {
+        entry = node->data;
+
+        if (entry->stream_nr != i)
+          continue;
+
+        /* check for max duration of a single buffer. I suppose that
+         * the allocation of index entries could be improved. */
+        stream = &avi->stream[entry->stream_nr];
+        if (entry->dur > MAX_DURATION
+            && stream->strh->type == GST_RIFF_FCC_auds) {
+          guint32 ideal_size;
+          gst_avi_index_entry *entries;
+          guint old_size, num_added;
+          GList *node2;
+
+          /* cut in 1/10th of a second */
+          ideal_size = stream->strf.auds->av_bps / 10;
+
+          /* ensure chunk size is multiple of blockalign */
+          if (stream->strf.auds->blockalign > 1)
+            ideal_size -= ideal_size % stream->strf.auds->blockalign;
+
+          /* copy index */
+          old_size = entry->size;
+          num_added = (entry->size - 1) / ideal_size;
+          avi->index_size += num_added;
+          entries = g_malloc (sizeof (gst_avi_index_entry) * num_added);
+          alloc_list = g_list_prepend (alloc_list, entries);
+          for (node2 = node->next; node2 != NULL; node2 = node2->next) {
+            gst_avi_index_entry *entry2 = node2->data;
+
+            entry2->index_nr += num_added;
+            if (entry2->stream_nr == entry->stream_nr)
+              entry2->frames_before += num_added;
+          }
+
+          /* new sized index chunks */
+          for (i = 0; i < num_added + 1; i++) {
+            gst_avi_index_entry *entry2;
+
+            if (i == 0) {
+              entry2 = entry;
+            } else {
+              entry2 = &entries[i - 1];
+              list = g_list_insert_before (list, node->next, entry2);
+              entry = node->data;
+              node = node->next;
+              memcpy (entry2, entry, sizeof (gst_avi_index_entry));
+            }
+
+            if (old_size >= ideal_size) {
+              entry2->size = ideal_size;
+              old_size -= ideal_size;
+            } else {
+              entry2->size = old_size;
+            }
+
+            entry2->dur = GST_SECOND * entry2->size / stream->strf.auds->av_bps;
+            if (i != 0) {
+              entry2->index_nr++;
+              entry2->ts += entry->dur;
+              entry2->offset += entry->size;
+              entry2->bytes_before += entry->size;
+              entry2->frames_before++;
+            }
+          }
+#ifndef GST_DISABLE_GST_DEBUG
+          num_added_total += num_added;
+#endif
+        }
+      }
+    }
+#ifndef GST_DISABLE_GST_DEBUG
+    if (num_added_total)
+      GST_LOG ("added %u new index entries", num_added_total);
+#endif
+
+    GST_LOG_OBJECT (avi, "I'm now going to reorder the index entries for time");
+
+    /* re-order for time */
+    list = g_list_sort (list, (GCompareFunc) sort);
+
+    /* make a continous array out of the list */
+    avi->index_size = g_list_length (list);
+    avi->index_entries = g_try_new (gst_avi_index_entry, avi->index_size);
+    if (!avi->index_entries)
+      goto out_of_mem;
+
+    entry = (gst_avi_index_entry *) (list->data);
+    delay = entry->ts;
+
+    GST_LOG_OBJECT (avi,
+        "Building index array, nr_entries = %d (time offset = %"
+        GST_TIME_FORMAT, avi->index_size, GST_TIME_ARGS (delay));
+
+    for (i = 0, node = list; node != NULL; node = node->next, i++) {
+      entry = node->data;
+      entry->index_nr = i;
+      entry->ts -= delay;
+      memcpy (&avi->index_entries[i], entry, sizeof (gst_avi_index_entry));
+#ifndef GST_DISABLE_GST_DEBUG
+      num_per_stream[entry->stream_nr]++;
+#endif
+
+      GST_LOG_OBJECT (avi, "Sorted index entry %3d for stream %d of size %6u"
+          " at offset %7" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT
+          " dur %" GST_TIME_FORMAT,
+          avi->index_entries[i].index_nr, entry->stream_nr, entry->size,
+          entry->offset, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur));
+    }
+    if (delay) {
+      for (i = 0; i < avi->num_streams; i++) {
+        stream = &avi->stream[i];
+        stream->idx_duration -= delay;
+      }
+    }
+#ifndef GST_DISABLE_GST_DEBUG
+    {
+      gchar str[GST_AVI_DEMUX_MAX_STREAMS * (1 + 6 + 2)];
+      gchar *pad_name;
+
+      for (i = 0; i < avi->num_streams; i++) {
+        if (!avi->stream[i].pad)
+          continue;
+        pad_name = GST_OBJECT_NAME (avi->stream[i].pad);
+        sprintf (&str[i * (1 + 6 + 2)], " %6u %c", num_per_stream[i],
+            pad_name[0]);
+      }
+      GST_LOG_OBJECT (avi, "indizies per stream:%20s", str);
+    }
+#endif
+
+    GST_LOG_OBJECT (avi, "Freeing original index list");
+    /* all the node->data in list point to alloc_list chunks */
+
+    g_list_free (list);
+  }
+  if (alloc_list) {
+    g_list_foreach (alloc_list, (GFunc) g_free, NULL);
+    g_list_free (alloc_list);
+  }
+#ifndef GST_DISABLE_GST_DEBUG
+  for (i = 0; i < avi->num_streams; i++) {
+    GST_LOG_OBJECT (avi, "Stream %d, %d frames, %8" G_GUINT64_FORMAT " bytes",
+        i, avi->stream[i].total_frames, avi->stream[i].total_bytes);
+  }
+#endif
+
+  GST_LOG_OBJECT (avi, "Index massaging done");
+  return TRUE;
+
+  /* ERRORS */
+out_of_mem:
+  GST_WARNING_OBJECT (avi, "Out of memory for %" G_GSIZE_FORMAT " bytes",
+      sizeof (gst_avi_index_entry) * avi->index_size);
+  return FALSE;
+}
+
+static void
+gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
+{
+  gint stream;
+  GstClockTime total;
+
+  total = GST_CLOCK_TIME_NONE;
+
+  /* all streams start at a timestamp 0 */
+  for (stream = 0; stream < avi->num_streams; stream++) {
+    GstClockTime duration, hduration;
+    avi_stream_context *streamc = &avi->stream[stream];
+    gst_riff_strh *strh = streamc->strh;
+
+    if (!strh)
+      continue;
+
+    /* get header duration for the stream */
+    hduration = streamc->hdr_duration;
+
+    /* index duration calculated during parsing, invariant under massage */
+    duration = streamc->idx_duration;
+
+    /* now pick a good duration */
+    if (GST_CLOCK_TIME_IS_VALID (duration)) {
+      /* index gave valid duration, use that */
+      GST_INFO ("Stream %d duration according to index: %" GST_TIME_FORMAT,
+          stream, GST_TIME_ARGS (duration));
+    } else {
+      /* fall back to header info to calculate a duration */
+      duration = hduration;
+    }
+    /* set duration for the stream */
+    streamc->duration = duration;
+
+    /* find total duration */
+    if (total == GST_CLOCK_TIME_NONE || duration > total)
+      total = duration;
+  }
+
+  if (GST_CLOCK_TIME_IS_VALID (total) && (total > 0)) {
+    /* now update the duration for those streams where we had none */
+    for (stream = 0; stream < avi->num_streams; stream++) {
+      avi_stream_context *streamc = &avi->stream[stream];
+
+      if (!GST_CLOCK_TIME_IS_VALID (streamc->duration)
+          || streamc->duration == 0) {
+        streamc->duration = total;
+
+        GST_INFO ("Stream %d duration according to total: %" GST_TIME_FORMAT,
+            stream, GST_TIME_ARGS (total));
+      }
+    }
+  }
+
+  /* and set the total duration in the segment. */
+  GST_INFO ("Setting total duration to: %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (total));
+
+  gst_segment_set_duration (&avi->segment, GST_FORMAT_TIME, total);
+}
+
+/* returns FALSE if there are no pads to deliver event to,
+ * otherwise TRUE (whatever the outcome of event sending) */
+static gboolean
+gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
+{
+  gboolean result = FALSE;
+  gint i;
+
+  GST_DEBUG_OBJECT (avi, "sending %s event to %d streams",
+      GST_EVENT_TYPE_NAME (event), avi->num_streams);
+
+  if (avi->num_streams) {
+    for (i = 0; i < avi->num_streams; i++) {
+      avi_stream_context *stream = &avi->stream[i];
+
+      if (stream->pad) {
+        result = TRUE;
+        gst_pad_push_event (stream->pad, gst_event_ref (event));
+      }
+    }
+  }
+  gst_event_unref (event);
+  return result;
+}
+
+/*
+ * Read AVI headers when streaming
+ */
+static GstFlowReturn
+gst_avi_demux_stream_header_push (GstAviDemux * avi)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  guint32 tag = 0;
+  guint32 ltag = 0;
+  guint32 size = 0;
+  const guint8 *data;
+  GstBuffer *buf = NULL, *sub = NULL;
+  guint offset = 4;
+  gint64 stop;
+
+  GST_DEBUG ("Reading and parsing avi headers: %d", avi->header_state);
+
+  switch (avi->header_state) {
+    case GST_AVI_DEMUX_HEADER_TAG_LIST:
+      if (gst_avi_demux_peek_chunk (avi, &tag, &size)) {
+        avi->offset += 8 + ((size + 1) & ~1);
+        if (tag != GST_RIFF_TAG_LIST)
+          goto header_no_list;
+
+        gst_adapter_flush (avi->adapter, 8);
+        /* Find the 'hdrl' LIST tag */
+        GST_DEBUG ("Reading %d bytes", size);
+        buf = gst_adapter_take_buffer (avi->adapter, size);
+
+        if (GST_READ_UINT32_LE (GST_BUFFER_DATA (buf)) != GST_RIFF_LIST_hdrl)
+          goto header_no_hdrl;
+
+        /* mind padding */
+        if (size & 1)
+          gst_adapter_flush (avi->adapter, 1);
+
+        GST_DEBUG ("'hdrl' LIST tag found. Parsing next chunk");
+
+        /* the hdrl starts with a 'avih' header */
+        if (!gst_riff_parse_chunk (GST_ELEMENT (avi), buf, &offset, &tag, &sub))
+          goto header_no_avih;
+
+        if (tag != GST_RIFF_TAG_avih)
+          goto header_no_avih;
+
+        if (!gst_avi_demux_parse_avih (GST_ELEMENT (avi), sub, &avi->avih))
+          goto header_wrong_avih;
+
+        GST_DEBUG_OBJECT (avi, "AVI header ok, reading elemnts from header");
+
+        /* now, read the elements from the header until the end */
+        while (gst_riff_parse_chunk (GST_ELEMENT (avi), buf, &offset, &tag,
+                &sub)) {
+          /* sub can be NULL on empty tags */
+          if (!sub)
+            continue;
+
+          switch (tag) {
+            case GST_RIFF_TAG_LIST:
+              if (GST_BUFFER_SIZE (sub) < 4)
+                goto next;
+
+              switch (GST_READ_UINT32_LE (GST_BUFFER_DATA (sub))) {
+                case GST_RIFF_LIST_strl:
+                  if (!(gst_avi_demux_parse_stream (avi, sub))) {
+                    sub = NULL;
+                    GST_ELEMENT_WARNING (avi, STREAM, DEMUX, (NULL),
+                        ("failed to parse stream, ignoring"));
+                    goto next;
+                  }
+                  sub = NULL;
+                  goto next;
+                case GST_RIFF_LIST_odml:
+                  gst_avi_demux_parse_odml (avi, sub);
+                  sub = NULL;
+                  break;
+                default:
+                  GST_WARNING_OBJECT (avi,
+                      "Unknown list %" GST_FOURCC_FORMAT " in AVI header",
+                      GST_FOURCC_ARGS (GST_READ_UINT32_LE (GST_BUFFER_DATA
+                              (sub))));
+                  /* fall-through */
+                case GST_RIFF_TAG_JUNK:
+                  goto next;
+              }
+              break;
+            default:
+              GST_WARNING_OBJECT (avi,
+                  "Unknown off %d tag %" GST_FOURCC_FORMAT " in AVI header",
+                  offset, GST_FOURCC_ARGS (tag));
+              /* fall-through */
+            case GST_RIFF_TAG_JUNK:
+            next:
+              /* move to next chunk */
+              if (sub)
+                gst_buffer_unref (sub);
+              sub = NULL;
+              break;
+          }
+        }
+        gst_buffer_unref (buf);
+        GST_DEBUG ("elements parsed");
+
+        /* check parsed streams */
+        if (avi->num_streams == 0) {
+          goto no_streams;
+        } else if (avi->num_streams != avi->avih->streams) {
+          GST_WARNING_OBJECT (avi,
+              "Stream header mentioned %d streams, but %d available",
+              avi->avih->streams, avi->num_streams);
+        }
+        GST_DEBUG ("Get junk and info next");
+        avi->header_state = GST_AVI_DEMUX_HEADER_INFO;
+      } else {
+        /* Need more data */
+        return ret;
+      }
+      /* fall-though */
+    case GST_AVI_DEMUX_HEADER_INFO:
+      GST_DEBUG_OBJECT (avi, "skipping junk between header and data ...");
+      while (TRUE) {
+        if (gst_adapter_available (avi->adapter) < 12)
+          return GST_FLOW_OK;
+
+        data = gst_adapter_peek (avi->adapter, 12);
+        tag = GST_READ_UINT32_LE (data);
+        size = GST_READ_UINT32_LE (data + 4);
+        ltag = GST_READ_UINT32_LE (data + 8);
+
+        if (tag == GST_RIFF_TAG_LIST) {
+          switch (ltag) {
+            case GST_RIFF_LIST_movi:
+              gst_adapter_flush (avi->adapter, 12);
+              avi->offset += 12;
+              goto skipping_done;
+            case GST_RIFF_LIST_INFO:
+              GST_DEBUG ("Found INFO chunk");
+              if (gst_avi_demux_peek_chunk (avi, &tag, &size)) {
+                GST_DEBUG ("got size %d", size);
+                avi->offset += 12;
+                gst_adapter_flush (avi->adapter, 12);
+                if (size > 4) {
+                  buf = gst_adapter_take_buffer (avi->adapter, size - 4);
+                  /* mind padding */
+                  if (size & 1)
+                    gst_adapter_flush (avi->adapter, 1);
+                  gst_riff_parse_info (GST_ELEMENT (avi), buf,
+                      &avi->globaltags);
+                  gst_buffer_unref (buf);
+
+                  avi->offset += ((size + 1) & ~1) - 4;
+                } else {
+                  GST_DEBUG ("skipping INFO LIST prefix");
+                }
+              } else {
+                /* Need more data */
+                return GST_FLOW_OK;
+              }
+              break;
+            default:
+              if (gst_avi_demux_peek_chunk (avi, &tag, &size)) {
+                avi->offset += 8 + ((size + 1) & ~1);
+                gst_adapter_flush (avi->adapter, 8 + ((size + 1) & ~1));
+                // ??? goto iterate; ???
+              } else {
+                /* Need more data */
+                return GST_FLOW_OK;
+              }
+              break;
+          }
+        } else {
+          if (gst_avi_demux_peek_chunk (avi, &tag, &size)) {
+            avi->offset += 8 + ((size + 1) & ~1);
+            gst_adapter_flush (avi->adapter, 8 + ((size + 1) & ~1));
+            //goto iterate;
+          } else {
+            /* Need more data */
+            return GST_FLOW_OK;
+          }
+        }
+      }
+      break;
+    default:
+      GST_WARNING ("unhandled header state: %d", avi->header_state);
+      break;
+  }
+skipping_done:
+
+  GST_DEBUG_OBJECT (avi, "skipping done ... (streams=%u, stream[0].indexes=%p)",
+      avi->num_streams, avi->stream[0].indexes);
+
+  GST_DEBUG ("Found movi chunk. Starting to stream data");
+  avi->state = GST_AVI_DEMUX_MOVI;
+
+#if 0
+  /*GList *index = NULL, *alloc = NULL; */
+
+  /* ######################## this need to be integrated with the state */
+  /* create or read stream index (for seeking) */
+  if (avi->stream[0].indexes != NULL) {
+    gst_avi_demux_read_subindexes_push (avi, &index, &alloc);
+  }
+  if (!index) {
+    if (avi->avih->flags & GST_RIFF_AVIH_HASINDEX) {
+      gst_avi_demux_stream_index (avi, &index, &alloc);
+    }
+    /* some indexes are incomplete, continue streaming from there */
+    if (!index)
+      gst_avi_demux_stream_scan (avi, &index, &alloc);
+  }
+
+  /* this is a fatal error */
+  if (!index)
+    goto no_index;
+
+  if (!gst_avi_demux_massage_index (avi, index, alloc))
+    goto no_index;
+
+  gst_avi_demux_calculate_durations_from_index (avi);
+  /* ######################## */
+#endif
+
+  /* create initial NEWSEGMENT event */
+  if ((stop = avi->segment.stop) == GST_CLOCK_TIME_NONE)
+    stop = avi->segment.duration;
+
+  GST_DEBUG_OBJECT (avi, "segment stop %" G_GINT64_FORMAT, stop);
+
+  if (avi->seek_event)
+    gst_event_unref (avi->seek_event);
+  avi->seek_event = gst_event_new_new_segment
+      (FALSE, avi->segment.rate, GST_FORMAT_TIME,
+      avi->segment.start, stop, avi->segment.start);
+
+  /* at this point we know all the streams and we can signal the no more
+   * pads signal */
+  GST_DEBUG_OBJECT (avi, "signaling no more pads");
+  gst_element_no_more_pads (GST_ELEMENT (avi));
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+no_streams:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("No streams found"));
+    return GST_FLOW_ERROR;
+  }
+header_no_list:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (no LIST at start): %"
+            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+    return GST_FLOW_ERROR;
+  }
+header_no_hdrl:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (no hdrl at start): %"
+            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+header_no_avih:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (no avih at start): %"
+            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+    if (sub)
+      gst_buffer_unref (sub);
+
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+header_wrong_avih:
+  {
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+}
+
+/*
+ * Read full AVI headers.
+ */
+static GstFlowReturn
+gst_avi_demux_stream_header_pull (GstAviDemux * avi)
+{
+  GstFlowReturn res;
+  GstBuffer *buf, *sub = NULL;
+  guint32 tag;
+  GList *index = NULL, *alloc = NULL;
+  guint offset = 4;
+  gint64 stop;
+  GstElement *element = GST_ELEMENT_CAST (avi);
+
+  /* the header consists of a 'hdrl' LIST tag */
+  res = gst_riff_read_chunk (element, avi->sinkpad, &avi->offset, &tag, &buf);
+  if (res != GST_FLOW_OK)
+    goto pull_range_failed;
+  else if (tag != GST_RIFF_TAG_LIST)
+    goto no_list;
+  else if (GST_BUFFER_SIZE (buf) < 4)
+    goto no_header;
+
+  GST_DEBUG_OBJECT (avi, "parsing headers");
+
+  /* Find the 'hdrl' LIST tag */
+  while (GST_READ_UINT32_LE (GST_BUFFER_DATA (buf)) != GST_RIFF_LIST_hdrl) {
+    GST_LOG_OBJECT (avi, "buffer contains %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (GST_READ_UINT32_LE (GST_BUFFER_DATA (buf))));
+
+    /* Eat up */
+    gst_buffer_unref (buf);
+
+    /* read new chunk */
+    res = gst_riff_read_chunk (element, avi->sinkpad, &avi->offset, &tag, &buf);
+    if (res != GST_FLOW_OK)
+      goto pull_range_failed;
+    else if (tag != GST_RIFF_TAG_LIST)
+      goto no_list;
+    else if (GST_BUFFER_SIZE (buf) < 4)
+      goto no_header;
+  }
+
+  GST_DEBUG_OBJECT (avi, "hdrl LIST tag found");
+
+  /* the hdrl starts with a 'avih' header */
+  if (!gst_riff_parse_chunk (element, buf, &offset, &tag, &sub))
+    goto no_avih;
+  else if (tag != GST_RIFF_TAG_avih)
+    goto no_avih;
+  else if (!gst_avi_demux_parse_avih (element, sub, &avi->avih))
+    goto invalid_avih;
+
+  GST_DEBUG_OBJECT (avi, "AVI header ok, reading elements from header");
+
+  /* now, read the elements from the header until the end */
+  while (gst_riff_parse_chunk (element, buf, &offset, &tag, &sub)) {
+    /* sub can be NULL on empty tags */
+    if (!sub)
+      continue;
+
+    switch (tag) {
+      case GST_RIFF_TAG_LIST:
+      {
+        guint8 *data;
+        guint32 fourcc;
+
+        if (GST_BUFFER_SIZE (sub) < 4)
+          goto next;
+
+        data = GST_BUFFER_DATA (sub);
+        fourcc = GST_READ_UINT32_LE (data);
+
+        switch (fourcc) {
+          case GST_RIFF_LIST_strl:
+            if (!(gst_avi_demux_parse_stream (avi, sub))) {
+              GST_ELEMENT_WARNING (avi, STREAM, DEMUX, (NULL),
+                  ("failed to parse stream, ignoring"));
+              sub = NULL;
+            }
+            sub = NULL;
+            goto next;
+          case GST_RIFF_LIST_odml:
+            gst_avi_demux_parse_odml (avi, sub);
+            sub = NULL;
+            break;
+          default:
+            GST_WARNING_OBJECT (avi,
+                "Unknown list %" GST_FOURCC_FORMAT " in AVI header",
+                GST_FOURCC_ARGS (fourcc));
+            GST_MEMDUMP_OBJECT (avi, "Unknown list", GST_BUFFER_DATA (sub),
+                GST_BUFFER_SIZE (sub));
+            /* fall-through */
+          case GST_RIFF_TAG_JUNK:
+            goto next;
+        }
+        break;
+      }
+      default:
+        GST_WARNING_OBJECT (avi,
+            "Unknown tag %" GST_FOURCC_FORMAT " in AVI header at off %d",
+            GST_FOURCC_ARGS (tag), offset);
+        GST_MEMDUMP_OBJECT (avi, "Unknown tag", GST_BUFFER_DATA (sub),
+            GST_BUFFER_SIZE (sub));
+        /* fall-through */
+      case GST_RIFF_TAG_JUNK:
+      next:
+        if (sub)
+          gst_buffer_unref (sub);
+        sub = NULL;
+        break;
+    }
+  }
+  gst_buffer_unref (buf);
+  GST_DEBUG ("elements parsed");
+
+  /* check parsed streams */
+  if (avi->num_streams == 0)
+    goto no_streams;
+  else if (avi->num_streams != avi->avih->streams) {
+    GST_WARNING_OBJECT (avi,
+        "Stream header mentioned %d streams, but %d available",
+        avi->avih->streams, avi->num_streams);
+  }
+
+  GST_DEBUG_OBJECT (avi, "skipping junk between header and data, offset=%"
+      G_GUINT64_FORMAT, avi->offset);
+
+  /* Now, find the data (i.e. skip all junk between header and data) */
+  do {
+    guint size;
+    guint32 tag, ltag;
+
+    res = gst_pad_pull_range (avi->sinkpad, avi->offset, 12, &buf);
+    if (res != GST_FLOW_OK) {
+      GST_DEBUG_OBJECT (avi, "pull_range failure while looking for tags");
+      goto pull_range_failed;
+    } else if (GST_BUFFER_SIZE (buf) < 12) {
+      GST_DEBUG_OBJECT (avi, "got %d bytes which is less than 12 bytes",
+          GST_BUFFER_SIZE (buf));
+      gst_buffer_unref (buf);
+      return GST_FLOW_ERROR;
+    }
+
+    tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
+    size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
+    ltag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 8);
+
+    GST_DEBUG ("tag %" GST_FOURCC_FORMAT ", size %u",
+        GST_FOURCC_ARGS (tag), size);
+    GST_MEMDUMP ("Tag content", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+    gst_buffer_unref (buf);
+
+    switch (tag) {
+      case GST_RIFF_TAG_LIST:{
+        switch (ltag) {
+          case GST_RIFF_LIST_movi:
+            GST_DEBUG_OBJECT (avi,
+                "Reached the 'movi' tag, we're done with skipping");
+            goto skipping_done;
+          case GST_RIFF_LIST_INFO:
+            res =
+                gst_riff_read_chunk (element, avi->sinkpad, &avi->offset, &tag,
+                &buf);
+            if (res != GST_FLOW_OK) {
+              GST_DEBUG_OBJECT (avi, "couldn't read INFO chunk");
+              goto pull_range_failed;
+            }
+            GST_DEBUG ("got size %u", GST_BUFFER_SIZE (buf));
+            if (size < 4) {
+              GST_DEBUG ("skipping INFO LIST prefix");
+              avi->offset += (4 - GST_ROUND_UP_2 (size));
+              gst_buffer_unref (buf);
+              continue;
+            }
+
+            sub = gst_buffer_create_sub (buf, 4, GST_BUFFER_SIZE (buf) - 4);
+            gst_riff_parse_info (element, sub, &avi->globaltags);
+            if (sub) {
+              gst_buffer_unref (sub);
+              sub = NULL;
+            }
+            gst_buffer_unref (buf);
+            /* gst_riff_read_chunk() has already advanced avi->offset */
+            break;
+          default:
+            GST_WARNING_OBJECT (avi,
+                "Skipping unknown list tag %" GST_FOURCC_FORMAT,
+                GST_FOURCC_ARGS (ltag));
+            avi->offset += 8 + ((size + 1) & ~1);
+            break;
+        }
+      }
+        break;
+      default:
+        GST_WARNING_OBJECT (avi, "Skipping unknown tag %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (tag));
+        /* Fall-through */
+      case GST_MAKE_FOURCC ('J', 'U', 'N', 'Q'):
+      case GST_MAKE_FOURCC ('J', 'U', 'N', 'K'):
+        avi->offset += 8 + ((size + 1) & ~1);
+        break;
+    }
+  } while (1);
+skipping_done:
+
+  GST_DEBUG_OBJECT (avi, "skipping done ... (streams=%u, stream[0].indexes=%p)",
+      avi->num_streams, avi->stream[0].indexes);
+
+  /* create or read stream index (for seeking) */
+  if (avi->stream[0].indexes != NULL) {
+    /* we read a super index already (gst_avi_demux_parse_superindex() ) */
+    gst_avi_demux_read_subindexes_pull (avi, &index, &alloc);
+  }
+  if (!index) {
+    if (avi->avih->flags & GST_RIFF_AVIH_HASINDEX) {
+      gst_avi_demux_stream_index (avi, &index, &alloc);
+    }
+    /* some indexes are incomplete, continue streaming from there */
+    if (!index)
+      gst_avi_demux_stream_scan (avi, &index, &alloc);
+  }
+
+  /* this is a fatal error */
+  if (!index)
+    goto no_index;
+
+  if (!gst_avi_demux_massage_index (avi, index, alloc))
+    goto no_index;
+
+  gst_avi_demux_calculate_durations_from_index (avi);
+
+  /* create initial NEWSEGMENT event */
+  if ((stop = avi->segment.stop) == GST_CLOCK_TIME_NONE)
+    stop = avi->segment.duration;
+
+  GST_DEBUG_OBJECT (avi, "segment stop %" G_GINT64_FORMAT, stop);
+
+  if (avi->seek_event)
+    gst_event_unref (avi->seek_event);
+  avi->seek_event = gst_event_new_new_segment
+      (FALSE, avi->segment.rate, GST_FORMAT_TIME,
+      avi->segment.start, stop, avi->segment.start);
+
+  /* at this point we know all the streams and we can signal the no more
+   * pads signal */
+  GST_DEBUG_OBJECT (avi, "signaling no more pads");
+  gst_element_no_more_pads (GST_ELEMENT_CAST (avi));
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+no_list:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (no LIST at start): %"
+            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+no_header:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (no hdrl at start): %"
+            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+no_avih:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (no avih at start): %"
+            GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+    if (sub)
+      gst_buffer_unref (sub);
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+invalid_avih:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Invalid AVI header (cannot parse avih at start)"));
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+no_streams:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("No streams found"));
+    return GST_FLOW_ERROR;
+  }
+no_index:
+  {
+    GST_WARNING ("file without or too big index");
+    g_list_free (index);
+    g_list_foreach (alloc, (GFunc) g_free, NULL);
+    g_list_free (alloc);
+
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("Could not get/create index"));
+    return GST_FLOW_ERROR;
+  }
+pull_range_failed:
+  {
+    GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
+        ("pull_range flow reading header: %s", gst_flow_get_name (res)));
+    return GST_FLOW_ERROR;
+  }
+}
+
+/*
+ * Do the actual seeking.
+ */
+static gboolean
+gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
+{
+  GstClockTime seek_time;
+  gboolean keyframe;
+  gst_avi_index_entry *entry, *kentry;
+  gint old_entry;
+
+  seek_time = segment->last_stop;
+  keyframe = !!(segment->flags & GST_SEEK_FLAG_KEY_UNIT);
+
+  /* FIXME: if we seek in an openDML file, we will have multiple
+   * primary levels. Seeking in between those will cause havoc. */
+
+  /* save old position so we can see if we must mark a discont. */
+  old_entry = avi->current_entry;
+
+  /* get the entry for the requested position, which is always in last_stop.
+   * we search the index entry for stream 0, since all entries are sorted by
+   * time and stream we automagically are positioned for the other streams as
+   * well. FIXME, this code assumes the main stream with keyframes is stream 0,
+   * which is mostly correct... */
+  if (!(entry = gst_avi_demux_index_entry_for_time (avi, 0, seek_time)))
+    goto no_entry;
+
+  GST_DEBUG_OBJECT (avi,
+      "Got requested entry %d [stream:%d / ts:%" GST_TIME_FORMAT
+      " / duration:%" GST_TIME_FORMAT "]", entry->index_nr,
+      entry->stream_nr, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur));
+
+  /* check if we are already on a keyframe */
+  if (!(entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME)) {
+    /* now go to the previous keyframe, this is where we should start
+     * decoding from. */
+    if (!(kentry = gst_avi_demux_index_prev (avi, 0, entry->index_nr,
+                GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME))) {
+      goto no_entry;
+    }
+  } else {
+    /* we were on a keyframe */
+    kentry = entry;
+  }
+
+  GST_DEBUG_OBJECT (avi,
+      "Got keyframe entry %d [stream:%d / ts:%" GST_TIME_FORMAT
+      " / duration:%" GST_TIME_FORMAT "]", kentry->index_nr,
+      entry->stream_nr, GST_TIME_ARGS (kentry->ts),
+      GST_TIME_ARGS (kentry->dur));
+
+  /* we must start decoding at the keyframe */
+  avi->current_entry = kentry->index_nr;
+
+  if (segment->rate < 0.0) {
+    gst_avi_index_entry *next_keyframe;
+
+    /* Because we don't know the frame order we need to push from the prev keyframe
+     * to the next keyframe. If there is a smart decoder downstream he will notice
+     * that there are too many encoded frames send and return UNEXPECTED when there
+     * are enough decoded frames to fill the segment.
+     */
+    next_keyframe =
+        gst_avi_demux_index_next (avi, 0, kentry->index_nr,
+        GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
+    if (!next_keyframe)
+      next_keyframe = gst_avi_demux_index_last (avi, 0);
+
+    avi->reverse_start_index = kentry->index_nr;
+    avi->reverse_stop_index = next_keyframe->index_nr;
+
+    GST_DEBUG_OBJECT (avi, "reverse seek: start idx (%d) and stop idx (%d)",
+        avi->reverse_start_index, avi->reverse_stop_index);
+  }
+
+  if (keyframe) {
+    /* when seeking to a keyframe, we update the result seek time
+     * to the time of the keyframe. */
+    seek_time = avi->index_entries[avi->current_entry].ts;
+  }
+
+next:
+  /* if we changed position, mark a DISCONT on all streams */
+  if (avi->current_entry != old_entry) {
+    gint i;
+
+    for (i = 0; i < avi->num_streams; i++) {
+      avi->stream[i].discont = TRUE;
+    }
+  }
+
+  GST_DEBUG_OBJECT (avi, "seek: %" GST_TIME_FORMAT
+      " keyframe seeking:%d", GST_TIME_ARGS (seek_time), keyframe);
+
+  /* the seek time is also the last_stop and stream time */
+  segment->last_stop = seek_time;
+  segment->time = seek_time;
+
+  return TRUE;
+
+no_entry:
+  {
+    /* we could not find an entry for the given time */
+    GST_WARNING_OBJECT (avi,
+        "Couldn't find AviIndexEntry for time:%" GST_TIME_FORMAT,
+        GST_TIME_ARGS (seek_time));
+    if (avi->current_entry >= avi->index_size && avi->index_size > 0)
+      avi->current_entry = avi->index_size - 1;
+
+    goto next;
+  }
+}
+
+/*
+ * Handle seek event.
+ */
+static gboolean
+gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
+{
+  gdouble rate;
+  GstFormat format;
+  GstSeekFlags flags;
+  GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
+  gint64 cur, stop;
+  gboolean flush;
+  gboolean update;
+  GstSegment seeksegment = { 0, };
+
+  if (event) {
+    GST_DEBUG_OBJECT (avi, "doing seek with event");
+
+    gst_event_parse_seek (event, &rate, &format, &flags,
+        &cur_type, &cur, &stop_type, &stop);
+
+    /* we have to have a format as the segment format. Try to convert
+     * if not. */
+    if (format != GST_FORMAT_TIME) {
+      GstFormat fmt = GST_FORMAT_TIME;
+      gboolean res = TRUE;
+
+      if (cur_type != GST_SEEK_TYPE_NONE)
+        res = gst_pad_query_convert (pad, format, cur, &fmt, &cur);
+      if (res && stop_type != GST_SEEK_TYPE_NONE)
+        res = gst_pad_query_convert (pad, format, stop, &fmt, &stop);
+      if (!res)
+        goto no_format;
+
+      format = fmt;
+    }
+    GST_DEBUG_OBJECT (avi,
+        "seek requested: rate %g cur %" GST_TIME_FORMAT " stop %"
+        GST_TIME_FORMAT, rate, GST_TIME_ARGS (cur), GST_TIME_ARGS (stop));
+    /* FIXME: can we do anything with rate!=1.0 */
+  } else {
+    GST_DEBUG_OBJECT (avi, "doing seek without event");
+    flags = 0;
+    rate = 1.0;
+  }
+
+  /* save flush flag */
+  flush = flags & GST_SEEK_FLAG_FLUSH;
+
+  if (flush) {
+    GstEvent *event = gst_event_new_flush_start ();
+
+    /* for a flushing seek, we send a flush_start on all pads. This will
+     * eventually stop streaming with a WRONG_STATE. We can thus eventually
+     * take the STREAM_LOCK. */
+    GST_DEBUG_OBJECT (avi, "sending flush start");
+    gst_avi_demux_push_event (avi, gst_event_ref (event));
+    gst_pad_push_event (avi->sinkpad, event);
+  } else {
+    /* a non-flushing seek, we PAUSE the task so that we can take the
+     * STREAM_LOCK */
+    GST_DEBUG_OBJECT (avi, "non flushing seek, pausing task");
+    gst_pad_pause_task (avi->sinkpad);
+  }
+
+  /* wait for streaming to stop */
+  GST_DEBUG_OBJECT (avi, "wait for streaming to stop");
+  GST_PAD_STREAM_LOCK (avi->sinkpad);
+
+  /* copy segment, we need this because we still need the old
+   * segment when we close the current segment. */
+  memcpy (&seeksegment, &avi->segment, sizeof (GstSegment));
+
+  if (event) {
+    GST_DEBUG_OBJECT (avi, "configuring seek");
+    gst_segment_set_seek (&seeksegment, rate, format, flags,
+        cur_type, cur, stop_type, stop, &update);
+  }
+
+  /* do the seek, seeksegment.last_stop contains the new position, this
+   * actually never fails. */
+  gst_avi_demux_do_seek (avi, &seeksegment);
+
+  if (flush) {
+    gint i;
+
+    GST_DEBUG_OBJECT (avi, "sending flush stop");
+    gst_avi_demux_push_event (avi, gst_event_new_flush_stop ());
+    gst_pad_push_event (avi->sinkpad, gst_event_new_flush_stop ());
+    /* reset the last flow and mark discont, FLUSH is always DISCONT */
+    for (i = 0; i < avi->num_streams; i++) {
+      avi->stream[i].last_flow = GST_FLOW_OK;
+      avi->stream[i].discont = TRUE;
+    }
+  } else if (avi->segment_running) {
+    GstEvent *seg;
+
+    /* we are running the current segment and doing a non-flushing seek,
+     * close the segment first based on the last_stop. */
+    GST_DEBUG_OBJECT (avi, "closing running segment %" G_GINT64_FORMAT
+        " to %" G_GINT64_FORMAT, avi->segment.start, avi->segment.last_stop);
+    seg = gst_event_new_new_segment (TRUE,
+        avi->segment.rate, avi->segment.format,
+        avi->segment.start, avi->segment.last_stop, avi->segment.time);
+    gst_avi_demux_push_event (avi, seg);
+  }
+
+  /* now update the real segment info */
+  memcpy (&avi->segment, &seeksegment, sizeof (GstSegment));
+
+  /* post the SEGMENT_START message when we do segmented playback */
+  if (avi->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+    gst_element_post_message (GST_ELEMENT (avi),
+        gst_message_new_segment_start (GST_OBJECT (avi),
+            avi->segment.format, avi->segment.last_stop));
+  }
+
+  /* prepare for streaming again */
+  if ((stop = avi->segment.stop) == GST_CLOCK_TIME_NONE)
+    stop = avi->segment.duration;
+
+  /* queue the segment event for the streaming thread. */
+  if (avi->seek_event)
+    gst_event_unref (avi->seek_event);
+  if (avi->segment.rate > 0.0) {
+    avi->seek_event = gst_event_new_new_segment (FALSE,
+        avi->segment.rate, avi->segment.format,
+        avi->segment.last_stop, stop, avi->segment.time);
+  } else {
+    avi->seek_event = gst_event_new_new_segment (FALSE,
+        avi->segment.rate, avi->segment.format,
+        avi->segment.start, avi->segment.last_stop, avi->segment.start);
+  }
+
+  if (!avi->streaming) {
+    avi->segment_running = TRUE;
+    gst_pad_start_task (avi->sinkpad, (GstTaskFunction) gst_avi_demux_loop,
+        avi->sinkpad);
+  }
+  GST_PAD_STREAM_UNLOCK (avi->sinkpad);
+
+  return TRUE;
+
+  /* ERRORS */
+no_format:
+  {
+    GST_DEBUG_OBJECT (avi, "unsupported format given, seek aborted.");
+    return FALSE;
+  }
+}
+
+/*
+ * Helper for gst_avi_demux_invert()
+ */
+static inline void
+swap_line (guint8 * d1, guint8 * d2, guint8 * tmp, gint bytes)
+{
+  memcpy (tmp, d1, bytes);
+  memcpy (d1, d2, bytes);
+  memcpy (d2, tmp, bytes);
+}
+
+
+#define gst_avi_demux_is_uncompressed(fourcc)		\
+  (fourcc == GST_RIFF_DIB ||				\
+   fourcc == GST_RIFF_rgb ||				\
+   fourcc == GST_RIFF_RGB || fourcc == GST_RIFF_RAW)
+
+/*
+ * Invert DIB buffers... Takes existing buffer and
+ * returns either the buffer or a new one (with old
+ * one dereferenced).
+ * FIXME: can't we preallocate tmp? and remember stride, bpp?
+ */
+static GstBuffer *
+gst_avi_demux_invert (avi_stream_context * stream, GstBuffer * buf)
+{
+  GstStructure *s;
+  gint y, w, h;
+  gint bpp, stride;
+  guint8 *tmp = NULL;
+
+  if (stream->strh->type != GST_RIFF_FCC_vids)
+    return buf;
+
+  if (!gst_avi_demux_is_uncompressed (stream->strh->fcc_handler)) {
+    return buf;                 /* Ignore non DIB buffers */
+  }
+
+  s = gst_caps_get_structure (GST_PAD_CAPS (stream->pad), 0);
+  if (!gst_structure_get_int (s, "bpp", &bpp)) {
+    GST_WARNING ("Failed to retrieve depth from caps");
+    return buf;
+  }
+
+  if (stream->strf.vids == NULL) {
+    GST_WARNING ("Failed to retrieve vids for stream");
+    return buf;
+  }
+
+  h = stream->strf.vids->height;
+  w = stream->strf.vids->width;
+  stride = w * (bpp / 8);
+
+  buf = gst_buffer_make_writable (buf);
+  if (GST_BUFFER_SIZE (buf) < (stride * h)) {
+    GST_WARNING ("Buffer is smaller than reported Width x Height x Depth");
+    return buf;
+  }
+
+  tmp = g_malloc (stride);
+
+  for (y = 0; y < h / 2; y++) {
+    swap_line (GST_BUFFER_DATA (buf) + stride * y,
+        GST_BUFFER_DATA (buf) + stride * (h - 1 - y), tmp, stride);
+  }
+
+  g_free (tmp);
+
+  return buf;
+}
+
+/*
+ * Returns the aggregated GstFlowReturn.
+ */
+static GstFlowReturn
+gst_avi_demux_combine_flows (GstAviDemux * avi, avi_stream_context * stream,
+    GstFlowReturn ret)
+{
+  guint i;
+
+  /* store the value */
+  stream->last_flow = ret;
+
+  /* any other error that is not-linked can be returned right away */
+  if (G_UNLIKELY (ret != GST_FLOW_NOT_LINKED))
+    goto done;
+
+  /* only return NOT_LINKED if all other pads returned NOT_LINKED */
+  for (i = 0; i < avi->num_streams; i++) {
+    avi_stream_context *ostream = &avi->stream[i];
+
+    ret = ostream->last_flow;
+    /* some other return value (must be SUCCESS but we can return
+     * other values as well) */
+    if (G_UNLIKELY (ret != GST_FLOW_NOT_LINKED))
+      goto done;
+  }
+  /* if we get here, all other pads were unlinked and we return
+   * NOT_LINKED then */
+done:
+  GST_LOG_OBJECT (avi, "combined return %s", gst_flow_get_name (ret));
+  return ret;
+}
+
+/*
+ * prepare the avi element for a reverse jump to a prev keyframe
+ * this function will return the start entry. if the function returns
+ * NULL there was no prev keyframe.
+ */
+static gst_avi_index_entry *
+gst_avi_demux_step_reverse (GstAviDemux * avi)
+{
+  gst_avi_index_entry *entry;
+  gint i;
+
+  avi->reverse_stop_index = avi->reverse_start_index;
+  entry =
+      gst_avi_demux_index_prev (avi, 0, avi->reverse_stop_index,
+      GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
+  if (!entry) {
+    GST_DEBUG_OBJECT (avi, "no valid index entry found index %d",
+        avi->reverse_stop_index);
+    return NULL;
+  }
+  avi->current_entry = avi->reverse_start_index = entry->index_nr;
+  GST_DEBUG_OBJECT (avi,
+      "reverse playback jump: start idx (%d) and stop idx (%d)",
+      avi->reverse_start_index, avi->reverse_stop_index);
+  gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, entry->ts);
+  for (i = 0; i < avi->num_streams; i++) {
+    avi->stream[i].last_flow = GST_FLOW_OK;
+    avi->stream[i].discont = TRUE;
+  }
+  return entry;
+}
+
+/*
+ * Read data from one index entry
+ */
+static GstFlowReturn
+gst_avi_demux_process_next_entry (GstAviDemux * avi)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+  gboolean processed = FALSE;
+  avi_stream_context *stream;
+  gst_avi_index_entry *entry;
+  GstBuffer *buf;
+
+  do {
+    /* see if we are at the end */
+    if ((avi->segment.rate > 0 && avi->current_entry >= avi->index_size))
+      goto eos;
+
+    /* get next entry, this will work as we checked for the index size above */
+    entry = &avi->index_entries[avi->current_entry++];
+
+    /* check for reverse playback */
+    if (avi->segment.rate < 0 && avi->current_entry > avi->reverse_stop_index) {
+      GST_LOG_OBJECT (avi, "stop_index %d reached", avi->reverse_stop_index);
+
+      /* check if we have pushed enough data for this segment */
+      if (avi->reverse_start_index == 0)
+        goto eos_reverse_zero;
+      if (avi->index_entries[avi->reverse_start_index].ts < avi->segment.start)
+        goto eos_reverse_segment;
+
+      if (!(entry = gst_avi_demux_step_reverse (avi)))
+        goto eos;
+
+      avi->current_entry++;
+    }
+
+    /* see if we have a valid stream, ignore if not
+     * FIXME: can't we check this when building the index?
+     *   we check it in _parse_index(), _stream_scan()
+     */
+    if (entry->stream_nr >= avi->num_streams) {
+      GST_WARNING_OBJECT (avi,
+          "Entry %d has non-existing stream nr %d",
+          avi->current_entry - 1, entry->stream_nr);
+      continue;
+    }
+
+    /* get stream now */
+    stream = &avi->stream[entry->stream_nr];
+
+    if (avi->segment.rate > 0.0) {
+      /* only check this for fowards playback for now */
+      if ((entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME)
+          && GST_CLOCK_TIME_IS_VALID (entry->ts)
+          && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
+          && (entry->ts > avi->segment.stop)) {
+        goto eos_stop;
+      }
+    }
+
+    /* skip empty entries */
+    if (entry->size == 0 || !stream->pad) {
+      GST_DEBUG_OBJECT (avi, "Skipping entry %d (%d, %p)",
+          avi->current_entry - 1, entry->size, stream->pad);
+      goto next;
+    }
+
+    GST_LOG ("reading buffer (size=%d) from stream %d at current pos %"
+        G_GUINT64_FORMAT " (%llx)", entry->size, entry->stream_nr,
+        avi->index_offset + entry->offset, avi->index_offset + entry->offset);
+
+    /* pull in the data */
+    res = gst_pad_pull_range (avi->sinkpad, entry->offset +
+        avi->index_offset, entry->size, &buf);
+    if (res != GST_FLOW_OK)
+      goto pull_failed;
+
+    /* check for short buffers, this is EOS as well */
+    if (GST_BUFFER_SIZE (buf) < entry->size)
+      goto short_buffer;
+
+    /* invert the picture if needed */
+    buf = gst_avi_demux_invert (stream, buf);
+
+    /* mark non-keyframes */
+    if (!(entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME))
+      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+
+    GST_BUFFER_TIMESTAMP (buf) = entry->ts;
+    GST_BUFFER_DURATION (buf) = entry->dur;
+    if (stream->strh->type == GST_RIFF_FCC_vids) {
+      if (stream->current_frame >= 0)
+        GST_BUFFER_OFFSET (buf) = stream->current_frame;
+      else {
+        gint64 framenum;
+        GstFormat fmt = GST_FORMAT_DEFAULT;
+
+        if (gst_pad_query_convert (stream->pad, GST_FORMAT_TIME, entry->ts,
+                &fmt, &framenum))
+          GST_BUFFER_OFFSET (buf) = framenum;
+        else
+          GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
+      }
+    } else
+      GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
+    GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
+    gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
+
+    GST_DEBUG_OBJECT (avi, "Pushing buffer of size %d, offset %"
+        G_GUINT64_FORMAT " and time %"
+        GST_TIME_FORMAT " on pad %s",
+        GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf),
+        GST_TIME_ARGS (entry->ts), GST_PAD_NAME (stream->pad));
+
+    /* update current position in the segment */
+    gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, entry->ts);
+
+    /* mark discont when pending */
+    if (stream->discont) {
+      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+      stream->discont = FALSE;
+    }
+
+    res = gst_pad_push (stream->pad, buf);
+
+    /* mark as processed, we increment the frame and byte counters then
+     * leave the while loop and return the GstFlowReturn */
+    processed = TRUE;
+    GST_DEBUG_OBJECT (avi, "Processed buffer %d: %s", entry->index_nr,
+        gst_flow_get_name (res));
+
+    if (avi->segment.rate < 0
+        && entry->ts > avi->segment.stop && res == GST_FLOW_UNEXPECTED) {
+      /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
+       * we are at the end of the segment, so we just need to jump
+       * back to the previous section.
+       */
+      GST_DEBUG_OBJECT (avi, "downstream has reached end of segment");
+
+      if (!(entry = gst_avi_demux_step_reverse (avi)))
+        goto eos;
+
+      res = GST_FLOW_OK;
+
+      stream->current_frame = entry->frames_before;
+      stream->current_byte = entry->bytes_before;
+
+      continue;
+    }
+
+    /* combine flows */
+    res = gst_avi_demux_combine_flows (avi, stream, res);
+
+  next:
+    stream->current_frame = entry->frames_before + 1;
+    stream->current_byte = entry->bytes_before + entry->size;
+  } while (!processed);
+
+beach:
+  GST_DEBUG_OBJECT (avi, "returning %s", gst_flow_get_name (res));
+
+  return res;
+
+  /* ERRORS */
+eos:
+  {
+    GST_LOG_OBJECT (avi, "Handled last index entry, setting EOS (%d > %d)",
+        avi->current_entry, avi->index_size);
+    /* we mark the first stream as EOS */
+    res = GST_FLOW_UNEXPECTED;
+    goto beach;
+  }
+eos_stop:
+  {
+    GST_LOG_OBJECT (avi, "Found keyframe after segment,"
+        " setting EOS (%" GST_TIME_FORMAT " > %" GST_TIME_FORMAT ")",
+        GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (avi->segment.stop));
+    res = GST_FLOW_UNEXPECTED;
+    goto beach;
+  }
+eos_reverse_zero:
+  {
+    GST_DEBUG_OBJECT (avi, "start_index was 0, setting EOS");
+    res = GST_FLOW_UNEXPECTED;
+    goto beach;
+  }
+eos_reverse_segment:
+  {
+    GST_DEBUG_OBJECT (avi, "full segment pushed, setting EOS");
+    res = GST_FLOW_UNEXPECTED;
+    goto beach;
+  }
+pull_failed:
+  {
+    GST_DEBUG_OBJECT (avi,
+        "pull range failed: pos=%" G_GUINT64_FORMAT " size=%d",
+        entry->offset + avi->index_offset, entry->size);
+    goto beach;
+  }
+short_buffer:
+  {
+    GST_WARNING_OBJECT (avi, "Short read at offset %" G_GUINT64_FORMAT
+        ", only got %d/%d bytes (truncated file?)", entry->offset +
+        avi->index_offset, GST_BUFFER_SIZE (buf), entry->size);
+    gst_buffer_unref (buf);
+    res = GST_FLOW_UNEXPECTED;
+    goto beach;
+  }
+}
+
+/*
+ * Read data. If we have an index it delegates to
+ * gst_avi_demux_process_next_entry().
+ */
+static GstFlowReturn
+gst_avi_demux_stream_data (GstAviDemux * avi)
+{
+  guint32 tag = 0;
+  guint32 size = 0;
+  gint stream_nr = 0;
+  GstFlowReturn res = GST_FLOW_OK;
+  GstFormat format = GST_FORMAT_TIME;
+
+  /* if we have a avi->index_entries[], we don't want to read
+   * the stream linearly, but seek to the next ts/index_entry. */
+  if (G_LIKELY (avi->index_entries != NULL))
+    return gst_avi_demux_process_next_entry (avi);
+
+  if (G_UNLIKELY (avi->have_eos)) {
+    /* Clean adapter, we're done */
+    gst_adapter_clear (avi->adapter);
+    return res;
+  }
+
+  /*
+     if (!gst_avi_demux_sync (avi, &tag, FALSE))
+     return FALSE;
+   */
+
+  /* Iterate until need more data, so adapter won't grow too much */
+  while (1) {
+    if (G_UNLIKELY (!gst_avi_demux_peek_chunk_info (avi, &tag, &size))) {
+      return GST_FLOW_OK;
+    }
+
+    GST_DEBUG ("Trying chunk (%" GST_FOURCC_FORMAT "), size %d",
+        GST_FOURCC_ARGS (tag), size);
+
+    if (G_LIKELY ((tag & 0xff) >= '0' && (tag & 0xff) <= '9' &&
+            ((tag >> 8) & 0xff) >= '0' && ((tag >> 8) & 0xff) <= '9')) {
+      GST_LOG ("Chunk ok");
+    } else if ((tag & 0xffff) == (('x' << 8) | 'i')) {
+      GST_DEBUG ("Found sub-index tag");
+      if (gst_avi_demux_peek_chunk (avi, &tag, &size)) {
+        if ((size > 0) && (size != -1)) {
+          GST_DEBUG ("  skipping %d bytes for now", size);
+          gst_adapter_flush (avi->adapter, 8 + GST_ROUND_UP_2 (size));
+        }
+      }
+      return GST_FLOW_OK;
+    } else if (tag == GST_RIFF_TAG_JUNK) {
+      GST_DEBUG ("JUNK chunk, skipping");
+    } else if (tag == GST_RIFF_TAG_idx1) {
+      GST_DEBUG ("Found index tag, stream done");
+      avi->have_eos = TRUE;
+      return GST_FLOW_UNEXPECTED;
+    } else if (tag == GST_RIFF_TAG_LIST) {
+      /* movi chunks might be grouped in rec list */
+      if (gst_adapter_available (avi->adapter) >= 12) {
+        GST_DEBUG ("Found LIST tag, skipping LIST header");
+        gst_adapter_flush (avi->adapter, 12);
+        continue;
+      }
+      return GST_FLOW_OK;
+    } else if (tag == GST_RIFF_TAG_JUNK) {
+      /* rec list might contain JUNK chunks */
+      GST_DEBUG ("Found JUNK tag");
+      if (gst_avi_demux_peek_chunk (avi, &tag, &size)) {
+        if ((size > 0) && (size != -1)) {
+          GST_DEBUG ("  skipping %d bytes for now", size);
+          gst_adapter_flush (avi->adapter, 8 + GST_ROUND_UP_2 (size));
+          continue;
+        }
+      }
+      return GST_FLOW_OK;
+    } else {
+      GST_DEBUG ("No more stream chunks, send EOS");
+      avi->have_eos = TRUE;
+      return GST_FLOW_UNEXPECTED;
+    }
+
+    if (G_UNLIKELY (!gst_avi_demux_peek_chunk (avi, &tag, &size))) {
+      if ((size == 0) || (size == -1))
+        gst_adapter_flush (avi->adapter, 8);
+      return GST_FLOW_OK;
+    }
+    GST_DEBUG ("chunk ID %" GST_FOURCC_FORMAT ", size %u",
+        GST_FOURCC_ARGS (tag), size);
+
+    stream_nr = CHUNKID_TO_STREAMNR (tag);
+
+    if (G_UNLIKELY (stream_nr < 0 || stream_nr >= avi->num_streams)) {
+      /* recoverable */
+      GST_WARNING ("Invalid stream ID %d (%" GST_FOURCC_FORMAT ")",
+          stream_nr, GST_FOURCC_ARGS (tag));
+      avi->offset += 8 + ((size + 1) & ~1);
+      gst_adapter_flush (avi->adapter, 8 + ((size + 1) & ~1));
+    } else {
+      avi_stream_context *stream;
+      GstClockTime next_ts = 0;
+      GstBuffer *buf;
+
+      gst_adapter_flush (avi->adapter, 8);
+
+      /* get buffer */
+      buf = gst_adapter_take_buffer (avi->adapter, ((size + 1) & ~1));
+      /* patch the size */
+      GST_BUFFER_SIZE (buf) = size;
+      avi->offset += 8 + ((size + 1) & ~1);
+
+      stream = &avi->stream[stream_nr];
+
+      /* set delay (if any)
+         if (stream->strh->init_frames == stream->current_frame &&
+         stream->delay == 0)
+         stream->delay = next_ts;
+       */
+
+      stream->current_frame++;
+      stream->current_byte += size;
+
+      /* parsing of corresponding header may have failed */
+      if (G_UNLIKELY (!stream->pad)) {
+        GST_WARNING_OBJECT (avi, "no pad for stream ID %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (tag));
+        gst_buffer_unref (buf);
+      } else {
+        GstClockTime dur_ts = 0;
+
+        /* get time of this buffer */
+        gst_pad_query_position (stream->pad, &format, (gint64 *) & next_ts);
+        if (G_UNLIKELY (format != GST_FORMAT_TIME))
+          goto wrong_format;
+
+        /* invert the picture if needed */
+        buf = gst_avi_demux_invert (stream, buf);
+
+        gst_pad_query_position (stream->pad, &format, (gint64 *) & dur_ts);
+        if (G_UNLIKELY (format != GST_FORMAT_TIME))
+          goto wrong_format;
+
+        GST_BUFFER_TIMESTAMP (buf) = next_ts;
+        GST_BUFFER_DURATION (buf) = dur_ts - next_ts;
+        if (stream->strh->type == GST_RIFF_FCC_vids)
+          GST_BUFFER_OFFSET (buf) = stream->current_frame - 1;
+        else
+          GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
+
+        gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
+        GST_DEBUG_OBJECT (avi,
+            "Pushing buffer with time=%" GST_TIME_FORMAT
+            ", offset %" G_GUINT64_FORMAT " and size %d over pad %s",
+            GST_TIME_ARGS (next_ts), GST_BUFFER_OFFSET (buf), size,
+            GST_PAD_NAME (stream->pad));
+
+        /* update current position in the segment */
+        gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, next_ts);
+
+        /* mark discont when pending */
+        if (G_UNLIKELY (stream->discont)) {
+          GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+          stream->discont = FALSE;
+        }
+        res = gst_pad_push (stream->pad, buf);
+
+        /* combine flows */
+        res = gst_avi_demux_combine_flows (avi, stream, res);
+        if (G_UNLIKELY (res != GST_FLOW_OK)) {
+          GST_DEBUG ("Push failed; %s", gst_flow_get_name (res));
+          return res;
+        }
+      }
+    }
+  }
+
+done:
+  return res;
+
+  /* ERRORS */
+wrong_format:
+  {
+    GST_DEBUG_OBJECT (avi, "format %s != GST_FORMAT_TIME",
+        gst_format_get_name (format));
+    res = GST_FLOW_ERROR;
+    goto done;
+  }
+}
+
+/*
+ * Send pending tags.
+ */
+static void
+push_tag_lists (GstAviDemux * avi)
+{
+  guint i;
+
+  if (!avi->got_tags)
+    return;
+
+  GST_DEBUG_OBJECT (avi, "Pushing pending tag lists");
+
+  for (i = 0; i < avi->num_streams; i++)
+    if (avi->stream[i].pad && avi->stream[i].taglist) {
+      GST_DEBUG_OBJECT (avi->stream[i].pad, "Tags: %" GST_PTR_FORMAT,
+          avi->stream[i].taglist);
+      gst_element_found_tags_for_pad (GST_ELEMENT (avi), avi->stream[i].pad,
+          avi->stream[i].taglist);
+      avi->stream[i].taglist = NULL;
+    }
+
+  if (avi->globaltags == NULL)
+    avi->globaltags = gst_tag_list_new ();
+
+  gst_tag_list_add (avi->globaltags, GST_TAG_MERGE_REPLACE,
+      GST_TAG_CONTAINER_FORMAT, "AVI", NULL);
+
+  GST_DEBUG_OBJECT (avi, "Global tags: %" GST_PTR_FORMAT, avi->globaltags);
+  gst_element_found_tags (GST_ELEMENT (avi), avi->globaltags);
+  avi->globaltags = NULL;
+  avi->got_tags = FALSE;
+}
+
+static void
+gst_avi_demux_loop (GstPad * pad)
+{
+  GstFlowReturn res;
+  GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad));
+
+  switch (avi->state) {
+    case GST_AVI_DEMUX_START:
+      if (G_UNLIKELY ((res =
+                  gst_avi_demux_stream_init_pull (avi)) != GST_FLOW_OK)) {
+        GST_WARNING ("stream_init flow: %s", gst_flow_get_name (res));
+        goto pause;
+      }
+      avi->state = GST_AVI_DEMUX_HEADER;
+      /* fall-through */
+    case GST_AVI_DEMUX_HEADER:
+      if (G_UNLIKELY ((res =
+                  gst_avi_demux_stream_header_pull (avi)) != GST_FLOW_OK)) {
+        GST_WARNING ("stream_header flow: %s", gst_flow_get_name (res));
+        goto pause;
+      }
+      avi->state = GST_AVI_DEMUX_MOVI;
+      break;
+    case GST_AVI_DEMUX_MOVI:
+      if (G_UNLIKELY (avi->seek_event)) {
+        gst_avi_demux_push_event (avi, avi->seek_event);
+        avi->seek_event = NULL;
+      }
+      if (G_UNLIKELY (avi->got_tags)) {
+        push_tag_lists (avi);
+      }
+      /* process each index entry in turn */
+      res = gst_avi_demux_stream_data (avi);
+
+      /* pause when error */
+      if (G_UNLIKELY (res != GST_FLOW_OK)) {
+        GST_INFO ("stream_movi flow: %s", gst_flow_get_name (res));
+        goto pause;
+      }
+      break;
+    default:
+      GST_ERROR_OBJECT (avi, "unknown state %d", avi->state);
+      res = GST_FLOW_ERROR;
+      goto pause;
+  }
+
+  GST_LOG_OBJECT (avi, "state: %d res:%s", avi->state, gst_flow_get_name (res));
+
+  return;
+
+  /* ERRORS */
+pause:
+  GST_LOG_OBJECT (avi, "pausing task, reason %s", gst_flow_get_name (res));
+  avi->segment_running = FALSE;
+  gst_pad_pause_task (avi->sinkpad);
+
+  if (GST_FLOW_IS_FATAL (res) || (res == GST_FLOW_NOT_LINKED)) {
+    gboolean push_eos = TRUE;
+
+    if (res == GST_FLOW_UNEXPECTED) {
+      /* handle end-of-stream/segment */
+      if (avi->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+        gint64 stop;
+
+        if ((stop = avi->segment.stop) == -1)
+          stop = avi->segment.duration;
+
+        GST_INFO_OBJECT (avi, "sending segment_done");
+
+        gst_element_post_message
+            (GST_ELEMENT (avi),
+            gst_message_new_segment_done (GST_OBJECT (avi), GST_FORMAT_TIME,
+                stop));
+        push_eos = FALSE;
+      }
+    } else {
+      /* for fatal errors we post an error message */
+      GST_ELEMENT_ERROR (avi, STREAM, FAILED,
+          (_("Internal data stream error.")),
+          ("streaming stopped, reason %s", gst_flow_get_name (res)));
+    }
+    if (push_eos) {
+      GST_INFO_OBJECT (avi, "sending eos");
+      if (!gst_avi_demux_push_event (avi, gst_event_new_eos ()) &&
+          (res == GST_FLOW_UNEXPECTED)) {
+        GST_ELEMENT_ERROR (avi, STREAM, DEMUX,
+            (NULL), ("got eos but no streams (yet)"));
+      }
+    }
+  }
+}
+
+
+static GstFlowReturn
+gst_avi_demux_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstFlowReturn res;
+  GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad));
+
+  GST_DEBUG ("Store %d bytes in adapter", GST_BUFFER_SIZE (buf));
+  gst_adapter_push (avi->adapter, buf);
+
+  switch (avi->state) {
+    case GST_AVI_DEMUX_START:
+      if ((res = gst_avi_demux_stream_init_push (avi)) != GST_FLOW_OK) {
+        GST_WARNING ("stream_init flow: %s", gst_flow_get_name (res));
+        break;
+      }
+      break;
+    case GST_AVI_DEMUX_HEADER:
+      if ((res = gst_avi_demux_stream_header_push (avi)) != GST_FLOW_OK) {
+        GST_WARNING ("stream_header flow: %s", gst_flow_get_name (res));
+        break;
+      }
+      break;
+    case GST_AVI_DEMUX_MOVI:
+      if (G_UNLIKELY (avi->seek_event)) {
+        gst_avi_demux_push_event (avi, avi->seek_event);
+        avi->seek_event = NULL;
+      }
+      if (G_UNLIKELY (avi->got_tags)) {
+        push_tag_lists (avi);
+      }
+      res = gst_avi_demux_stream_data (avi);
+      break;
+    default:
+      GST_ELEMENT_ERROR (avi, STREAM, FAILED, (NULL),
+          ("Illegal internal state"));
+      res = GST_FLOW_ERROR;
+      break;
+  }
+
+  GST_DEBUG_OBJECT (avi, "state: %d res:%s", avi->state,
+      gst_flow_get_name (res));
+
+  return res;
+}
+
+static gboolean
+gst_avi_demux_sink_activate (GstPad * sinkpad)
+{
+  if (gst_pad_check_pull_range (sinkpad)) {
+    GST_DEBUG ("going to pull mode");
+    return gst_pad_activate_pull (sinkpad, TRUE);
+  } else {
+    GST_DEBUG ("going to push (streaming) mode");
+    return gst_pad_activate_push (sinkpad, TRUE);
+  }
+}
+
+static gboolean
+gst_avi_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+  GstAviDemux *avi = GST_AVI_DEMUX (GST_OBJECT_PARENT (sinkpad));
+
+  if (active) {
+    avi->segment_running = TRUE;
+    avi->streaming = FALSE;
+    return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_avi_demux_loop,
+        sinkpad);
+  } else {
+    avi->segment_running = FALSE;
+    return gst_pad_stop_task (sinkpad);
+  }
+}
+
+static gboolean
+gst_avi_demux_activate_push (GstPad * pad, gboolean active)
+{
+  GstAviDemux *avi = GST_AVI_DEMUX (GST_OBJECT_PARENT (pad));
+
+  if (active) {
+    GST_DEBUG ("avi: activating push/chain function");
+    avi->streaming = TRUE;
+  } else {
+    GST_DEBUG ("avi: deactivating push/chain function");
+  }
+
+  return TRUE;
+}
+
+static GstStateChangeReturn
+gst_avi_demux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstAviDemux *avi = GST_AVI_DEMUX (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      avi->streaming = FALSE;
+      gst_segment_init (&avi->segment, GST_FORMAT_TIME);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    goto done;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_avi_demux_reset (avi);
+      break;
+    default:
+      break;
+  }
+
+done:
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavidemux.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,179 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2006> Nokia Corporation (contact <stefan.kost@nokia.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_AVI_DEMUX_H__
+#define __GST_AVI_DEMUX_H__
+
+#include <gst/gst.h>
+
+#include "avi-ids.h"
+#include "gst/riff/riff-ids.h"
+#include "gst/riff/riff-read.h"
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AVI_DEMUX \
+  (gst_avi_demux_get_type ())
+#define GST_AVI_DEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AVI_DEMUX, GstAviDemux))
+#define GST_AVI_DEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AVI_DEMUX, GstAviDemuxClass))
+#define GST_IS_AVI_DEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_AVI_DEMUX))
+#define GST_IS_AVI_DEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_AVI_DEMUX))
+
+#define GST_AVI_DEMUX_MAX_STREAMS       16
+
+#define CHUNKID_TO_STREAMNR(chunkid) \
+  ((((chunkid) & 0xff) - '0') * 10 + \
+   (((chunkid) >> 8) & 0xff) - '0')
+
+#define GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME 1
+
+/* 48 bytes */
+typedef struct {
+  guint          index_nr;      /* = (entry-index_entries)/sizeof(gst_avi_index_entry); */
+  guchar         stream_nr;
+  guchar         flags;
+  guint64        ts;
+  guint64        dur;           /* =entry[1].ts-entry->ts */
+  guint64        offset;
+  guint64        bytes_before;  /* calculated */
+  guint32        frames_before; /* calculated */
+  guint32        size;          /* could be read from the chunk (if we don't split) */
+} gst_avi_index_entry;
+
+typedef struct {
+  /* index of this streamcontext */
+  guint          num;
+
+  /* pad*/
+  GstPad        *pad;
+
+  /* stream info and headers */
+  gst_riff_strh *strh;
+  union {
+    gst_riff_strf_vids *vids;
+    gst_riff_strf_auds *auds;
+    gst_riff_strf_iavs *iavs;
+    gpointer     data;
+  } strf;
+  GstBuffer     *extradata, *initdata;
+  gchar         *name;
+
+  /* current position (byte, frame, time) and other status vars */
+  guint          current_frame;
+  guint64        current_byte;
+  GstFlowReturn  last_flow;
+  gboolean       discont;
+
+  /* stream length */
+  guint64        total_bytes;
+  guint32        total_frames;
+  guint32        total_blocks;
+  /* stream length according to index */
+  GstClockTime   idx_duration;
+  /* stream length according to header */
+  GstClockTime   hdr_duration;
+  /* stream length based on header/index */
+  GstClockTime   duration;
+
+  /* VBR indicator */
+  gboolean       is_vbr;
+
+  /* openDML support (for files >4GB) */
+  gboolean       superindex;
+  guint64       *indexes;
+
+  GstTagList	*taglist;
+} avi_stream_context;
+
+typedef enum {
+  GST_AVI_DEMUX_START,
+  GST_AVI_DEMUX_HEADER,
+  GST_AVI_DEMUX_MOVI,
+} GstAviDemuxState;
+
+typedef enum {
+  GST_AVI_DEMUX_HEADER_TAG_LIST,
+  GST_AVI_DEMUX_HEADER_AVIH,
+  GST_AVI_DEMUX_HEADER_ELEMENTS,
+  GST_AVI_DEMUX_HEADER_INFO,
+  GST_AVI_DEMUX_HEADER_JUNK,
+  GST_AVI_DEMUX_HEADER_DATA
+} GstAviDemuxHeaderState;
+
+typedef struct _GstAviDemux {
+  GstElement     parent;
+
+  /* pads */
+  GstPad        *sinkpad;
+
+  /* AVI decoding state */
+  GstAviDemuxState state;
+  GstAviDemuxHeaderState header_state;
+  guint64        offset;
+
+  /* index */
+  gst_avi_index_entry *index_entries;
+  guint          index_size;
+  guint64        index_offset;
+  guint          current_entry;
+  guint          reverse_start_index;
+  guint          reverse_stop_index;
+
+  /* streams */
+  guint          num_streams;
+  guint          num_v_streams;
+  guint          num_a_streams;
+  guint          num_t_streams;  /* subtitle text streams */
+
+  avi_stream_context stream[GST_AVI_DEMUX_MAX_STREAMS];
+
+  /* for streaming mode */
+  gboolean      streaming;
+  gboolean      have_eos;
+  GstAdapter    *adapter;
+
+  /* some stream info for length */
+  gst_riff_avih *avih;
+
+  /* segment in TIME */
+  GstSegment     segment;
+  gboolean       segment_running;
+
+  /* pending tags/events */
+  GstEvent      *seek_event;
+  GstTagList	*globaltags;
+  gboolean	got_tags;
+
+} GstAviDemux;
+
+typedef struct _GstAviDemuxClass {
+  GstElementClass parent_class;
+} GstAviDemuxClass;
+
+GType           gst_avi_demux_get_type          (void);
+
+G_END_DECLS
+
+#endif /* __GST_AVI_DEMUX_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavimux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1982 @@
+/* AVI muxer plugin for GStreamer
+ * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *           (C) 2006 Mark Nauwelaerts <manauw@skynet.be>
+ *
+ * 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.
+ */
+
+/* based on:
+ * - the old avimuxer (by Wim Taymans)
+ * - xawtv's aviwriter (by Gerd Knorr)
+ * - mjpegtools' avilib (by Rainer Johanni)
+ * - openDML large-AVI docs
+ */
+
+/**
+ * SECTION:element-avimux
+ *
+ * Muxes raw or compressed audio and/or video streams into an AVI file.
+ *
+ * <refsect2>
+ * <title>Example launch lines</title>
+ * <para>(write everything in one line, without the backslash characters)</para>
+ * |[
+ * gst-launch videotestsrc num-buffers=250 \
+ * ! 'video/x-raw-yuv,format=(fourcc)I420,width=320,height=240,framerate=(fraction)25/1' \
+ * ! queue ! mux. \
+ * audiotestsrc num-buffers=440 ! audioconvert \
+ * ! 'audio/x-raw-int,rate=44100,channels=2' ! queue ! mux. \
+ * avimux name=mux ! filesink location=test.avi
+ * ]| This will create an .AVI file containing an uncompressed video stream
+ * with a test picture and an uncompressed audio stream containing a 
+ * test sound.
+ * |[
+ * gst-launch videotestsrc num-buffers=250 \
+ * ! 'video/x-raw-yuv,format=(fourcc)I420,width=320,height=240,framerate=(fraction)25/1' \
+ * ! xvidenc ! queue ! mux. \
+ * audiotestsrc num-buffers=440 ! audioconvert ! 'audio/x-raw-int,rate=44100,channels=2' \
+ * ! lame ! queue ! mux. \
+ * avimux name=mux ! filesink location=test.avi
+ * ]| This will create an .AVI file containing the same test video and sound
+ * as above, only that both streams will be compressed this time. This will
+ * only work if you have the necessary encoder elements installed of course.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst/gst-i18n-plugin.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include <gst/video/video.h>
+
+#include "gstavimux.h"
+
+GST_DEBUG_CATEGORY_STATIC (avimux_debug);
+#define GST_CAT_DEFAULT avimux_debug
+
+enum
+{
+  ARG_0,
+  ARG_BIGFILE
+};
+
+#define DEFAULT_BIGFILE TRUE
+
+static const GstElementDetails gst_avi_mux_details =
+GST_ELEMENT_DETAILS ("Avi muxer",
+    "Codec/Muxer",
+    "Muxes audio and video into an avi stream",
+    "Ronald Bultje <rbultje@ronald.bitfreak.net>");
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-msvideo")
+    );
+
+static GstStaticPadTemplate video_sink_factory =
+    GST_STATIC_PAD_TEMPLATE ("video_%d",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS ("video/x-raw-yuv, "
+        "format = (fourcc) { YUY2, I420 }, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ]; "
+        "image/jpeg, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ]; "
+        "video/x-divx, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ], "
+        "divxversion = (int) [ 3, 5 ]; "
+        "video/x-xvid, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ]; "
+        "video/x-3ivx, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ]; "
+        "video/x-msmpeg, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ], "
+        "msmpegversion = (int) [ 41, 43 ]; "
+        "video/mpeg, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ], "
+        "mpegversion = (int) { 1, 2, 4}, "
+        "systemstream = (boolean) FALSE; "
+        "video/x-h263, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ]; "
+        "video/x-h264, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], "
+        "framerate = (fraction) [ 0, MAX ]; "
+        "video/x-dv, "
+        "width = (int) 720, "
+        "height = (int) { 576, 480 }, "
+        "framerate = (fraction) [ 0, MAX ], "
+        "systemstream = (boolean) FALSE; "
+        "video/x-huffyuv, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ];"
+        "video/x-dirac, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ];"
+        "video/x-wmv, "
+        "width = (int) [ 16, 4096 ], "
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ], "
+        "wmvversion = (int) [ 1, 3]")
+    );
+
+static GstStaticPadTemplate audio_sink_factory =
+    GST_STATIC_PAD_TEMPLATE ("audio_%d",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "endianness = (int) LITTLE_ENDIAN, "
+        "signed = (boolean) { TRUE, FALSE }, "
+        "width = (int) { 8, 16 }, "
+        "depth = (int) { 8, 16 }, "
+        "rate = (int) [ 1000, 96000 ], "
+        "channels = (int) [ 1, 2 ]; "
+        "audio/mpeg, "
+        "mpegversion = (int) 1, "
+        "layer = (int) [ 1, 3 ], "
+        "rate = (int) [ 1000, 96000 ], " "channels = (int) [ 1, 2 ]; "
+        "audio/mpeg, "
+        "mpegversion = (int) 4, "
+        "rate = (int) [ 1000, 96000 ], " "channels = (int) [ 1, 2 ]; "
+/*#if 0 VC6 doesn't support #if here ...
+        "audio/x-vorbis, "
+        "rate = (int) [ 1000, 96000 ], " "channels = (int) [ 1, 2 ]; "
+#endif*/
+        "audio/x-ac3, "
+        "rate = (int) [ 1000, 96000 ], " "channels = (int) [ 1, 2 ]; "
+        "audio/x-alaw, "
+        "rate = (int) [ 1000, 48000 ], " "channels = (int) [ 1, 2 ]; "
+        "audio/x-mulaw, "
+        "rate = (int) [ 1000, 48000 ], " "channels = (int) [ 1, 2 ]; "
+        "audio/x-wma, "
+        "rate = (int) [ 1000, 96000 ], " "channels = (int) [ 1, 2 ], "
+        "wmaversion = (int) [ 1, 2 ] ")
+    );
+
+static void gst_avi_mux_base_init (gpointer g_class);
+static void gst_avi_mux_class_init (GstAviMuxClass * klass);
+static void gst_avi_mux_init (GstAviMux * avimux);
+static void gst_avi_mux_pad_reset (GstAviPad * avipad, gboolean free);
+
+static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads * pads,
+    GstAviMux * avimux);
+static gboolean gst_avi_mux_handle_event (GstPad * pad, GstEvent * event);
+static GstPad *gst_avi_mux_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * name);
+static void gst_avi_mux_release_pad (GstElement * element, GstPad * pad);
+static void gst_avi_mux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_avi_mux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+static GstStateChangeReturn gst_avi_mux_change_state (GstElement * element,
+    GstStateChange transition);
+
+static GstElementClass *parent_class = NULL;
+
+GType
+gst_avi_mux_get_type (void)
+{
+  static GType avimux_type = 0;
+
+  if (!avimux_type) {
+    static const GTypeInfo avimux_info = {
+      sizeof (GstAviMuxClass),
+      gst_avi_mux_base_init,
+      NULL,
+      (GClassInitFunc) gst_avi_mux_class_init,
+      NULL,
+      NULL,
+      sizeof (GstAviMux),
+      0,
+      (GInstanceInitFunc) gst_avi_mux_init,
+    };
+    static const GInterfaceInfo tag_setter_info = {
+      NULL,
+      NULL,
+      NULL
+    };
+
+    avimux_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstAviMux", &avimux_info, 0);
+    g_type_add_interface_static (avimux_type, GST_TYPE_TAG_SETTER,
+        &tag_setter_info);
+  }
+  return avimux_type;
+}
+
+static void
+gst_avi_mux_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&audio_sink_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&video_sink_factory));
+
+  gst_element_class_set_details (element_class, &gst_avi_mux_details);
+
+  GST_DEBUG_CATEGORY_INIT (avimux_debug, "avimux", 0, "Muxer for AVI streams");
+}
+
+static void
+gst_avi_mux_finalize (GObject * object)
+{
+  GstAviMux *mux = GST_AVI_MUX (object);
+  GSList *node;
+
+  /* completely free each sinkpad */
+  node = mux->sinkpads;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+
+    node = node->next;
+
+    gst_avi_mux_pad_reset (avipad, TRUE);
+    g_free (avipad);
+  }
+  g_slist_free (mux->sinkpads);
+  mux->sinkpads = NULL;
+
+  g_free (mux->idx);
+  mux->idx = NULL;
+
+  gst_object_unref (mux->collect);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_avi_mux_class_init (GstAviMuxClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->get_property = gst_avi_mux_get_property;
+  gobject_class->set_property = gst_avi_mux_set_property;
+  gobject_class->finalize = gst_avi_mux_finalize;
+
+  g_object_class_install_property (gobject_class, ARG_BIGFILE,
+      g_param_spec_boolean ("bigfile", "Bigfile Support (>2GB)",
+          "Support for openDML-2.0 (big) AVI files", DEFAULT_BIGFILE,
+          G_PARAM_READWRITE));
+
+  gstelement_class->request_new_pad =
+      GST_DEBUG_FUNCPTR (gst_avi_mux_request_new_pad);
+  gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_avi_mux_release_pad);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_avi_mux_change_state);
+}
+
+/* reset pad to initial state
+ * free - if true, release all, not only stream related, data */
+static void
+gst_avi_mux_pad_reset (GstAviPad * avipad, gboolean free)
+{
+  /* generic part */
+  memset (&(avipad->hdr), 0, sizeof (gst_riff_strh));
+
+  memset (&(avipad->idx[0]), 0, sizeof (avipad->idx));
+
+  if (free) {
+    g_free (avipad->tag);
+    avipad->tag = NULL;
+    g_free (avipad->idx_tag);
+    avipad->idx_tag = NULL;
+  }
+
+  if (avipad->is_video) {
+    GstAviVideoPad *vidpad = (GstAviVideoPad *) avipad;
+
+    avipad->hdr.type = GST_MAKE_FOURCC ('v', 'i', 'd', 's');
+    if (vidpad->vids_codec_data) {
+      gst_buffer_unref (vidpad->vids_codec_data);
+      vidpad->vids_codec_data = NULL;
+    }
+
+    memset (&(vidpad->vids), 0, sizeof (gst_riff_strf_vids));
+    memset (&(vidpad->vprp), 0, sizeof (gst_riff_vprp));
+  } else {
+    GstAviAudioPad *audpad = (GstAviAudioPad *) avipad;
+
+    avipad->hdr.type = GST_MAKE_FOURCC ('a', 'u', 'd', 's');
+    if (audpad->auds_codec_data) {
+      gst_buffer_unref (audpad->auds_codec_data);
+      audpad->auds_codec_data = NULL;
+    }
+
+    memset (&(audpad->auds), 0, sizeof (gst_riff_strf_auds));
+  }
+}
+
+static void
+gst_avi_mux_reset (GstAviMux * avimux)
+{
+  GSList *node, *newlist = NULL;
+
+  /* free and reset each sinkpad */
+  node = avimux->sinkpads;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+
+    node = node->next;
+
+    gst_avi_mux_pad_reset (avipad, FALSE);
+    /* if this pad has collectdata, keep it, otherwise dump it completely */
+    if (avipad->collect)
+      newlist = g_slist_append (newlist, avipad);
+    else {
+      gst_avi_mux_pad_reset (avipad, TRUE);
+      g_free (avipad);
+    }
+  }
+
+  /* free the old list of sinkpads, only keep the real collecting ones */
+  g_slist_free (avimux->sinkpads);
+  avimux->sinkpads = newlist;
+
+  /* avi data */
+  avimux->num_frames = 0;
+  memset (&(avimux->avi_hdr), 0, sizeof (gst_riff_avih));
+  avimux->avi_hdr.max_bps = 10000000;
+  avimux->codec_data_size = 0;
+
+  if (avimux->tags_snap) {
+    gst_tag_list_free (avimux->tags_snap);
+    avimux->tags_snap = NULL;
+  }
+
+  g_free (avimux->idx);
+  avimux->idx = NULL;
+
+  /* state info */
+  avimux->write_header = TRUE;
+
+  /* tags */
+  gst_tag_setter_reset_tags (GST_TAG_SETTER (avimux));
+}
+
+static void
+gst_avi_mux_init (GstAviMux * avimux)
+{
+  avimux->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
+  gst_pad_use_fixed_caps (avimux->srcpad);
+  gst_element_add_pad (GST_ELEMENT (avimux), avimux->srcpad);
+
+  /* property */
+  avimux->enable_large_avi = DEFAULT_BIGFILE;
+
+  avimux->collect = gst_collect_pads_new ();
+  gst_collect_pads_set_function (avimux->collect,
+      (GstCollectPadsFunction) (GST_DEBUG_FUNCPTR (gst_avi_mux_collect_pads)),
+      avimux);
+
+  /* set to clean state */
+  gst_avi_mux_reset (avimux);
+}
+
+static gboolean
+gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
+{
+  GstAviMux *avimux;
+  GstAviVideoPad *avipad;
+  GstAviCollectData *collect_pad;
+  GstStructure *structure;
+  const gchar *mimetype;
+  const GValue *fps, *par;
+  const GValue *codec_data;
+  gint width, height;
+  gint par_n, par_d;
+
+  avimux = GST_AVI_MUX (gst_pad_get_parent (pad));
+
+  /* find stream data */
+  collect_pad = (GstAviCollectData *) gst_pad_get_element_private (pad);
+  g_assert (collect_pad);
+  avipad = (GstAviVideoPad *) collect_pad->avipad;
+  g_assert (avipad);
+  g_assert (avipad->parent.is_video);
+  g_assert (avipad->parent.hdr.type == GST_MAKE_FOURCC ('v', 'i', 'd', 's'));
+
+  GST_DEBUG_OBJECT (avimux, "%s:%s, caps=%" GST_PTR_FORMAT,
+      GST_DEBUG_PAD_NAME (pad), vscaps);
+
+  structure = gst_caps_get_structure (vscaps, 0);
+  mimetype = gst_structure_get_name (structure);
+
+  /* global */
+  avipad->vids.size = sizeof (gst_riff_strf_vids);
+  avipad->vids.planes = 1;
+  if (!gst_structure_get_int (structure, "width", &width) ||
+      !gst_structure_get_int (structure, "height", &height)) {
+    goto refuse_caps;
+  }
+
+  avipad->vids.width = width;
+  avipad->vids.height = height;
+
+  fps = gst_structure_get_value (structure, "framerate");
+  if (fps == NULL || !GST_VALUE_HOLDS_FRACTION (fps))
+    goto refuse_caps;
+
+  avipad->parent.hdr.rate = gst_value_get_fraction_numerator (fps);
+  avipad->parent.hdr.scale = gst_value_get_fraction_denominator (fps);
+
+  /* (pixel) aspect ratio data, if any */
+  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+  /* only use video properties header if there is non-trivial aspect info */
+  if (par && GST_VALUE_HOLDS_FRACTION (par) &&
+      ((par_n = gst_value_get_fraction_numerator (par)) !=
+          (par_d = gst_value_get_fraction_denominator (par)))) {
+    GValue to_ratio = { 0, };
+    guint ratio_n, ratio_d;
+
+    /* some fraction voodoo to obtain simplest possible ratio */
+    g_value_init (&to_ratio, GST_TYPE_FRACTION);
+    gst_value_set_fraction (&to_ratio, width * par_n, height * par_d);
+    ratio_n = gst_value_get_fraction_numerator (&to_ratio);
+    ratio_d = gst_value_get_fraction_denominator (&to_ratio);
+    GST_DEBUG_OBJECT (avimux, "generating vprp data with aspect ratio %d/%d",
+        ratio_n, ratio_d);
+    /* simply fill in */
+    avipad->vprp.vert_rate = avipad->parent.hdr.rate / avipad->parent.hdr.scale;
+    avipad->vprp.hor_t_total = width;
+    avipad->vprp.vert_lines = height;
+    avipad->vprp.aspect = (ratio_n) << 16 | (ratio_d & 0xffff);
+    avipad->vprp.width = width;
+    avipad->vprp.height = height;
+    avipad->vprp.fields = 1;
+    avipad->vprp.field_info[0].compressed_bm_height = height;
+    avipad->vprp.field_info[0].compressed_bm_width = width;
+    avipad->vprp.field_info[0].valid_bm_height = height;
+    avipad->vprp.field_info[0].valid_bm_width = width;
+  }
+
+  /* codec initialization data, if any */
+  codec_data = gst_structure_get_value (structure, "codec_data");
+  if (codec_data) {
+    avipad->vids_codec_data = gst_value_get_buffer (codec_data);
+    gst_buffer_ref (avipad->vids_codec_data);
+    /* keep global track of size */
+    avimux->codec_data_size += GST_BUFFER_SIZE (avipad->vids_codec_data);
+  }
+
+  if (!strcmp (mimetype, "video/x-raw-yuv")) {
+    guint32 format;
+
+    gst_structure_get_fourcc (structure, "format", &format);
+    avipad->vids.compression = format;
+    switch (format) {
+      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+        avipad->vids.bit_cnt = 16;
+        break;
+      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+        avipad->vids.bit_cnt = 12;
+        break;
+    }
+  } else {
+    avipad->vids.bit_cnt = 24;
+    avipad->vids.compression = 0;
+
+    /* find format */
+    if (!strcmp (mimetype, "video/x-huffyuv")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('H', 'F', 'Y', 'U');
+    } else if (!strcmp (mimetype, "image/jpeg")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
+    } else if (!strcmp (mimetype, "video/x-divx")) {
+      gint divxversion;
+
+      gst_structure_get_int (structure, "divxversion", &divxversion);
+      switch (divxversion) {
+        case 3:
+          avipad->vids.compression = GST_MAKE_FOURCC ('D', 'I', 'V', '3');
+          break;
+        case 4:
+          avipad->vids.compression = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
+          break;
+        case 5:
+          avipad->vids.compression = GST_MAKE_FOURCC ('D', 'X', '5', '0');
+          break;
+      }
+    } else if (!strcmp (mimetype, "video/x-xvid")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
+    } else if (!strcmp (mimetype, "video/x-3ivx")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('3', 'I', 'V', '2');
+    } else if (gst_structure_has_name (structure, "video/x-msmpeg")) {
+      gint msmpegversion;
+
+      gst_structure_get_int (structure, "msmpegversion", &msmpegversion);
+      switch (msmpegversion) {
+        case 41:
+          avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', 'G', '4');
+          break;
+        case 42:
+          avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', '4', '2');
+          break;
+        case 43:
+          avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', '4', '3');
+          break;
+        default:
+          GST_INFO ("unhandled msmpegversion : %d, fall back to fourcc=MPEG",
+              msmpegversion);
+          avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', 'E', 'G');
+          break;
+      }
+    } else if (!strcmp (mimetype, "video/x-dv")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('D', 'V', 'S', 'D');
+    } else if (!strcmp (mimetype, "video/x-h263")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('H', '2', '6', '3');
+    } else if (!strcmp (mimetype, "video/x-h264")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('H', '2', '6', '4');
+    } else if (!strcmp (mimetype, "video/mpeg")) {
+      gint mpegversion;
+
+      gst_structure_get_int (structure, "mpegversion", &mpegversion);
+
+      switch (mpegversion) {
+        case 2:
+          avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', 'G', '2');
+          break;
+        case 4:
+          /* mplayer/ffmpeg might not work with DIVX, but with FMP4 */
+          avipad->vids.compression = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
+          break;
+        default:
+          GST_INFO ("unhandled mpegversion : %d, fall back to fourcc=MPEG",
+              mpegversion);
+          avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', 'E', 'G');
+          break;
+      }
+    } else if (!strcmp (mimetype, "video/x-dirac")) {
+      avipad->vids.compression = GST_MAKE_FOURCC ('d', 'r', 'a', 'c');
+    } else if (!strcmp (mimetype, "video/x-wmv")) {
+      gint wmvversion;
+
+      if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
+        switch (wmvversion) {
+          case 1:
+            avipad->vids.compression = GST_MAKE_FOURCC ('W', 'M', 'V', '1');
+            break;
+          case 2:
+            avipad->vids.compression = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
+            break;
+          case 3:
+            avipad->vids.compression = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
+          default:
+            break;
+        }
+      }
+    }
+
+    if (!avipad->vids.compression)
+      goto refuse_caps;
+  }
+
+  avipad->parent.hdr.fcc_handler = avipad->vids.compression;
+  avipad->vids.image_size = avipad->vids.height * avipad->vids.width;
+  /* hm, maybe why avi only handles one stream well ... */
+  avimux->avi_hdr.width = avipad->vids.width;
+  avimux->avi_hdr.height = avipad->vids.height;
+  avimux->avi_hdr.us_frame = 1000000. * avipad->parent.hdr.scale /
+      avipad->parent.hdr.rate;
+
+  gst_object_unref (avimux);
+  return TRUE;
+
+refuse_caps:
+  {
+    GST_WARNING_OBJECT (avimux, "refused caps %" GST_PTR_FORMAT, vscaps);
+    gst_object_unref (avimux);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_avi_mux_audsink_set_caps (GstPad * pad, GstCaps * vscaps)
+{
+  GstAviMux *avimux;
+  GstAviAudioPad *avipad;
+  GstAviCollectData *collect_pad;
+  GstStructure *structure;
+  const gchar *mimetype;
+  const GValue *codec_data;
+  gint channels, rate;
+
+  avimux = GST_AVI_MUX (gst_pad_get_parent (pad));
+
+  /* find stream data */
+  collect_pad = (GstAviCollectData *) gst_pad_get_element_private (pad);
+  g_assert (collect_pad);
+  avipad = (GstAviAudioPad *) collect_pad->avipad;
+  g_assert (avipad);
+  g_assert (!avipad->parent.is_video);
+  g_assert (avipad->parent.hdr.type == GST_MAKE_FOURCC ('a', 'u', 'd', 's'));
+
+  GST_DEBUG_OBJECT (avimux, "%s:%s, caps=%" GST_PTR_FORMAT,
+      GST_DEBUG_PAD_NAME (pad), vscaps);
+
+  structure = gst_caps_get_structure (vscaps, 0);
+  mimetype = gst_structure_get_name (structure);
+
+  /* we want these for all */
+  if (!gst_structure_get_int (structure, "channels", &channels) ||
+      !gst_structure_get_int (structure, "rate", &rate)) {
+    goto refuse_caps;
+  }
+
+  avipad->auds.channels = channels;
+  avipad->auds.rate = rate;
+
+  /* codec initialization data, if any */
+  codec_data = gst_structure_get_value (structure, "codec_data");
+  if (codec_data) {
+    avipad->auds_codec_data = gst_value_get_buffer (codec_data);
+    gst_buffer_ref (avipad->auds_codec_data);
+    /* keep global track of size */
+    avimux->codec_data_size += GST_BUFFER_SIZE (avipad->auds_codec_data);
+  }
+
+  if (!strcmp (mimetype, "audio/x-raw-int")) {
+    gint width, depth;
+    gboolean signedness;
+
+    avipad->auds.format = GST_RIFF_WAVE_FORMAT_PCM;
+
+    if (!gst_structure_get_int (structure, "width", &width) ||
+        !gst_structure_get_int (structure, "depth", &depth) ||
+        !gst_structure_get_boolean (structure, "signed", &signedness)) {
+      GST_DEBUG_OBJECT (avimux,
+          "broken caps, width/depth/signed field missing");
+      goto refuse_caps;
+    }
+
+    /* no clear place to put different values for these while keeping to spec */
+    if (width != depth) {
+      GST_DEBUG_OBJECT (avimux, "width must be same as depth!");
+      goto refuse_caps;
+    }
+
+    /* because that's the way the caps will be recreated from riff data */
+    if ((width == 8 && signedness) || (width == 16 && !signedness)) {
+      GST_DEBUG_OBJECT (avimux,
+          "8-bit PCM must be unsigned, 16-bit PCM signed");
+      goto refuse_caps;
+    }
+
+    avipad->auds.blockalign = width;
+    avipad->auds.size = (width == 8) ? 8 : depth;
+
+    /* set some more info straight */
+    avipad->auds.blockalign /= 8;
+    avipad->auds.blockalign *= avipad->auds.channels;
+    avipad->auds.av_bps = avipad->auds.blockalign * avipad->auds.rate;
+  } else {
+    avipad->auds.format = 0;
+    /* set some defaults */
+    avipad->auds.blockalign = 1;
+    avipad->auds.av_bps = 0;
+    avipad->auds.size = 16;
+
+    if (!strcmp (mimetype, "audio/mpeg")) {
+      gint mpegversion;
+
+      gst_structure_get_int (structure, "mpegversion", &mpegversion);
+      switch (mpegversion) {
+        case 1:{
+          gint layer = 3;
+
+          gst_structure_get_int (structure, "layer", &layer);
+          switch (layer) {
+            case 3:
+              avipad->auds.format = GST_RIFF_WAVE_FORMAT_MPEGL3;
+              break;
+            case 1:
+            case 2:
+              avipad->auds.format = GST_RIFF_WAVE_FORMAT_MPEGL12;
+              break;
+          }
+          break;
+        }
+        case 4:
+          GST_WARNING ("AAC");
+          avipad->auds.format = GST_RIFF_WAVE_FORMAT_AAC;
+          break;
+      }
+    } else if (!strcmp (mimetype, "audio/x-vorbis")) {
+      avipad->auds.format = GST_RIFF_WAVE_FORMAT_VORBIS3;
+    } else if (!strcmp (mimetype, "audio/x-ac3")) {
+      avipad->auds.format = GST_RIFF_WAVE_FORMAT_A52;
+    } else if (!strcmp (mimetype, "audio/x-alaw")) {
+      avipad->auds.format = GST_RIFF_WAVE_FORMAT_ALAW;
+      avipad->auds.size = 8;
+      avipad->auds.blockalign = avipad->auds.channels;
+      avipad->auds.av_bps = avipad->auds.blockalign * avipad->auds.rate;
+    } else if (!strcmp (mimetype, "audio/x-mulaw")) {
+      avipad->auds.format = GST_RIFF_WAVE_FORMAT_MULAW;
+      avipad->auds.size = 8;
+      avipad->auds.blockalign = avipad->auds.channels;
+      avipad->auds.av_bps = avipad->auds.blockalign * avipad->auds.rate;
+    } else if (!strcmp (mimetype, "audio/x-wma")) {
+      gint version;
+      gint bitrate;
+      gint block_align;
+
+      if (gst_structure_get_int (structure, "wmaversion", &version)) {
+        switch (version) {
+          case 1:
+            avipad->auds.format = GST_RIFF_WAVE_FORMAT_WMAV1;
+            break;
+          case 2:
+            avipad->auds.format = GST_RIFF_WAVE_FORMAT_WMAV2;
+            break;
+          default:
+            break;
+        }
+      }
+
+      if (avipad->auds.format != 0) {
+        if (gst_structure_get_int (structure, "block_align", &block_align)) {
+          avipad->auds.blockalign = block_align;
+        }
+        if (gst_structure_get_int (structure, "bitrate", &bitrate)) {
+          avipad->auds.av_bps = bitrate / 8;
+        }
+      }
+    }
+  }
+
+  if (!avipad->auds.format)
+    goto refuse_caps;
+
+  /* by spec, hdr.rate is av_bps related, is calculated that way in stop_file,
+   * and reduces to sample rate in PCM like cases */
+  avipad->parent.hdr.rate = avipad->auds.av_bps / avipad->auds.blockalign;
+  avipad->parent.hdr.samplesize = avipad->auds.blockalign;
+  avipad->parent.hdr.scale = 1;
+
+  gst_object_unref (avimux);
+  return TRUE;
+
+refuse_caps:
+  {
+    GST_WARNING_OBJECT (avimux, "refused caps %" GST_PTR_FORMAT, vscaps);
+    gst_object_unref (avimux);
+    return FALSE;
+  }
+}
+
+
+static GstPad *
+gst_avi_mux_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * req_name)
+{
+  GstAviMux *avimux;
+  GstPad *newpad;
+  GstAviPad *avipad;
+  GstElementClass *klass;
+
+  g_return_val_if_fail (templ != NULL, NULL);
+
+  if (templ->direction != GST_PAD_SINK)
+    goto wrong_direction;
+
+  g_return_val_if_fail (GST_IS_AVI_MUX (element), NULL);
+  avimux = GST_AVI_MUX (element);
+
+  if (!avimux->write_header)
+    goto too_late;
+
+  klass = GST_ELEMENT_GET_CLASS (element);
+
+  if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
+    gchar *name;
+
+    /* setup pad */
+    name = g_strdup_printf ("audio_%02d", avimux->audio_pads);
+    GST_DEBUG_OBJECT (avimux, "adding new pad: %s", name);
+    newpad = gst_pad_new_from_template (templ, name);
+    g_free (name);
+    gst_pad_set_setcaps_function (newpad,
+        GST_DEBUG_FUNCPTR (gst_avi_mux_audsink_set_caps));
+
+    /* init pad specific data */
+    avipad = g_malloc0 (sizeof (GstAviAudioPad));
+    avipad->is_video = FALSE;
+    avipad->hdr.type = GST_MAKE_FOURCC ('a', 'u', 'd', 's');
+    avimux->audio_pads++;
+    /* audio goes last */
+    avimux->sinkpads = g_slist_append (avimux->sinkpads, avipad);
+  } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
+    /* though streams are pretty generic and relatively self-contained,
+     * some video info goes in a single avi header -and therefore mux struct-
+     * so video restricted to one stream */
+    if (avimux->video_pads > 0)
+      return NULL;
+    /* setup pad */
+    GST_DEBUG_OBJECT (avimux, "adding new pad: video_00");
+    newpad = gst_pad_new_from_template (templ, "video_00");
+    gst_pad_set_setcaps_function (newpad,
+        GST_DEBUG_FUNCPTR (gst_avi_mux_vidsink_set_caps));
+    avipad = g_malloc0 (sizeof (GstAviVideoPad));
+
+    /* init pad specific data */
+    avipad->is_video = TRUE;
+    avipad->hdr.type = GST_MAKE_FOURCC ('v', 'i', 'd', 's');
+    avimux->video_pads++;
+    /* video goes first */
+    avimux->sinkpads = g_slist_prepend (avimux->sinkpads, avipad);
+  } else
+    goto wrong_template;
+
+  avipad->collect = gst_collect_pads_add_pad (avimux->collect,
+      newpad, sizeof (GstAviCollectData));
+  ((GstAviCollectData *) (avipad->collect))->avipad = avipad;
+  /* FIXME: hacked way to override/extend the event function of
+   * GstCollectPads; because it sets its own event function giving the
+   * element no access to events */
+  avimux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
+  gst_pad_set_event_function (newpad,
+      GST_DEBUG_FUNCPTR (gst_avi_mux_handle_event));
+
+  gst_element_add_pad (element, newpad);
+
+  return newpad;
+
+  /* ERRORS */
+wrong_direction:
+  {
+    g_warning ("avimux: request pad that is not a SINK pad\n");
+    return NULL;
+  }
+too_late:
+  {
+    g_warning ("avimux: request pad cannot be added after streaming started\n");
+    return NULL;
+  }
+wrong_template:
+  {
+    g_warning ("avimuxx: this is not our template!\n");
+    return NULL;
+  }
+}
+
+static void
+gst_avi_mux_release_pad (GstElement * element, GstPad * pad)
+{
+  GstAviMux *avimux = GST_AVI_MUX (element);
+  GSList *node;
+
+  node = avimux->sinkpads;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+
+    if (avipad->collect->pad == pad) {
+      /* pad count should not be adjusted,
+       * as it also represent number of streams present */
+      avipad->collect = NULL;
+      GST_DEBUG_OBJECT (avimux, "removed pad '%s'", GST_PAD_NAME (pad));
+      gst_collect_pads_remove_pad (avimux->collect, pad);
+      gst_element_remove_pad (element, pad);
+      /* if not started yet, we can remove any sign this pad ever existed */
+      /* in this case _start will take care of the real pad count */
+      if (avimux->write_header) {
+        avimux->sinkpads = g_slist_remove (avimux->sinkpads, avipad);
+        gst_avi_mux_pad_reset (avipad, TRUE);
+        g_free (avipad);
+      }
+      return;
+    }
+
+    node = node->next;
+  }
+
+  g_warning ("Unknown pad %s", GST_PAD_NAME (pad));
+}
+
+/* maybe some of these functions should be moved to riff.h? */
+
+/* DISCLAIMER: this function is fairly ugly. So be it (i.e. it makes the rest easier)
+ * so is this struct */
+
+typedef struct _GstMarkedBuffer
+{
+  guint *highmark;
+  GstBuffer *buffer;
+} GstMarkedBuffer;
+
+static void
+gst_avi_mux_write_tag (const GstTagList * list, const gchar * tag,
+    gpointer data)
+{
+  const struct
+  {
+    guint32 fcc;
+    gchar *tag;
+  } rifftags[] = {
+    {
+    GST_RIFF_INFO_IARL, GST_TAG_LOCATION}, {
+    GST_RIFF_INFO_IART, GST_TAG_ARTIST}, {
+    GST_RIFF_INFO_ICMT, GST_TAG_COMMENT}, {
+    GST_RIFF_INFO_ICOP, GST_TAG_COPYRIGHT}, {
+    GST_RIFF_INFO_ICRD, GST_TAG_DATE}, {
+    GST_RIFF_INFO_IGNR, GST_TAG_GENRE}, {
+    GST_RIFF_INFO_IKEY, GST_TAG_KEYWORDS}, {
+    GST_RIFF_INFO_INAM, GST_TAG_TITLE}, {
+    GST_RIFF_INFO_ISFT, GST_TAG_ENCODER}, {
+    GST_RIFF_INFO_ISRC, GST_TAG_ISRC}, {
+    0, NULL}
+  };
+  gint n, len, plen;
+  GstBuffer *buf = ((GstMarkedBuffer *) data)->buffer;
+  guint *highmark = ((GstMarkedBuffer *) data)->highmark;
+  guint8 *buffdata = GST_BUFFER_DATA (buf) + *highmark;
+  gchar *str;
+
+  for (n = 0; rifftags[n].fcc != 0; n++) {
+    if (!strcmp (rifftags[n].tag, tag) &&
+        gst_tag_list_get_string (list, tag, &str) && str) {
+      len = strlen (str);
+      plen = len + 1;
+      if (plen & 1)
+        plen++;
+      if (GST_BUFFER_SIZE (buf) >= *highmark + 8 + plen) {
+        GST_WRITE_UINT32_LE (buffdata, rifftags[n].fcc);
+        GST_WRITE_UINT32_LE (buffdata + 4, len + 1);
+        memcpy (buffdata + 8, str, len);
+        buffdata[8 + len] = 0;
+        *highmark += 8 + plen;
+        GST_DEBUG ("writing tag in buffer %p, highmark at %d", buf, *highmark);
+      }
+      g_free (str);
+      break;
+    }
+  }
+}
+
+#define ODML_SUPERINDEX_SIZE    \
+    (32 + GST_AVI_SUPERINDEX_COUNT * sizeof (gst_avi_superindex_entry))
+
+static GstBuffer *
+gst_avi_mux_riff_get_avi_header (GstAviMux * avimux)
+{
+  const GstTagList *tags;
+  GstBuffer *buffer;
+  guint8 *buffdata;
+  guint size = 0;
+  guint highmark = 0;
+
+  /* pointer to list size field */
+  guint8 *riff_size, *hdrl_size;
+  GSList *node;
+
+  GST_DEBUG_OBJECT (avimux, "creating avi header, data_size %u, idx_size %u",
+      avimux->data_size, avimux->idx_size);
+
+  if (avimux->tags_snap)
+    tags = avimux->tags_snap;
+  else {
+    /* need to make snapshot of current state of tags to ensure the same set
+     * is used next time around during header rewrite at the end */
+    tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (avimux));
+    if (tags)
+      tags = avimux->tags_snap = gst_tag_list_copy (tags);
+  }
+  if (tags) {
+    /* that should be the strlen of all tags + header sizes
+     * not all of tags end up in a avi, still this is a good estimate
+     */
+    gchar *str = gst_structure_to_string (tags);
+    size += strlen (str) + 8 * gst_structure_n_fields (tags);
+    g_free (str);
+  }
+
+  /* allocate the buffer, starting with some wild/safe upper bound */
+  size += avimux->codec_data_size + 100 + sizeof (gst_riff_avih)
+      + (g_slist_length (avimux->sinkpads) * (100 + sizeof (gst_riff_strh_full)
+          + sizeof (gst_riff_strf_vids)
+          + sizeof (gst_riff_vprp)
+          + sizeof (gst_riff_vprp_video_field_desc) * 2
+          + sizeof (gst_riff_strf_auds) + 2 + ODML_SUPERINDEX_SIZE));
+  buffer = gst_buffer_new_and_alloc (size);
+  buffdata = GST_BUFFER_DATA (buffer);
+  highmark = 0;
+  GST_DEBUG_OBJECT (avimux, "creating buffer %p, size %d, highmark at 0",
+      buffer, GST_BUFFER_SIZE (buffer));
+
+  /* avi header metadata */
+  memcpy (buffdata + 0, "RIFF", 4);
+  /* fill in RIFF size later */
+  riff_size = buffdata + 4;
+  memcpy (buffdata + 8, "AVI ", 4);
+  memcpy (buffdata + 12, "LIST", 4);
+  /* fill in header size later */
+  hdrl_size = buffdata + 16;
+  memcpy (buffdata + 20, "hdrl", 4);
+  memcpy (buffdata + 24, "avih", 4);
+  GST_WRITE_UINT32_LE (buffdata + 28, sizeof (gst_riff_avih));
+  buffdata += 32;
+  highmark += 32;
+
+  /* the AVI header itself */
+  GST_WRITE_UINT32_LE (buffdata + 0, avimux->avi_hdr.us_frame);
+  GST_WRITE_UINT32_LE (buffdata + 4, avimux->avi_hdr.max_bps);
+  GST_WRITE_UINT32_LE (buffdata + 8, avimux->avi_hdr.pad_gran);
+  GST_WRITE_UINT32_LE (buffdata + 12, avimux->avi_hdr.flags);
+  GST_WRITE_UINT32_LE (buffdata + 16, avimux->avi_hdr.tot_frames);
+  GST_WRITE_UINT32_LE (buffdata + 20, avimux->avi_hdr.init_frames);
+  GST_WRITE_UINT32_LE (buffdata + 24, avimux->avi_hdr.streams);
+  GST_WRITE_UINT32_LE (buffdata + 28, avimux->avi_hdr.bufsize);
+  GST_WRITE_UINT32_LE (buffdata + 32, avimux->avi_hdr.width);
+  GST_WRITE_UINT32_LE (buffdata + 36, avimux->avi_hdr.height);
+  GST_WRITE_UINT32_LE (buffdata + 40, avimux->avi_hdr.scale);
+  GST_WRITE_UINT32_LE (buffdata + 44, avimux->avi_hdr.rate);
+  GST_WRITE_UINT32_LE (buffdata + 48, avimux->avi_hdr.start);
+  GST_WRITE_UINT32_LE (buffdata + 52, avimux->avi_hdr.length);
+  buffdata += 56;
+  highmark += 56;
+
+  /* stream data */
+  node = avimux->sinkpads;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+    GstAviVideoPad *vidpad = (GstAviVideoPad *) avipad;
+    GstAviAudioPad *audpad = (GstAviAudioPad *) avipad;
+    guint codec_size = 0, strl_size = 0, vprp_size = 0;
+
+    if (avipad->is_video) {
+      if (vidpad->vids_codec_data)
+        codec_size = GST_BUFFER_SIZE (vidpad->vids_codec_data);
+      strl_size = sizeof (gst_riff_strh_full) + sizeof (gst_riff_strf_vids)
+          + GST_ROUND_UP_2 (codec_size) + 4 * 5 + ODML_SUPERINDEX_SIZE;
+      if (vidpad->vprp.aspect) {
+        /* let's be on the safe side */
+        vidpad->vprp.fields = MIN (vidpad->vprp.fields,
+            GST_RIFF_VPRP_VIDEO_FIELDS);
+        vprp_size = G_STRUCT_OFFSET (gst_riff_vprp, field_info)
+            + (vidpad->vprp.fields * sizeof (gst_riff_vprp_video_field_desc));
+        strl_size += 4 * 2 + vprp_size;
+      }
+    } else {
+      if (audpad->auds_codec_data)
+        codec_size = GST_BUFFER_SIZE (audpad->auds_codec_data);
+      /* +2 is codec_size field, not part of gst_riff_strf_auds */
+      strl_size = sizeof (gst_riff_strh_full) + sizeof (gst_riff_strf_auds) + 2
+          + GST_ROUND_UP_2 (codec_size) + 4 * 5 + ODML_SUPERINDEX_SIZE;
+    }
+
+    /* stream list metadata */
+    memcpy (buffdata + 0, "LIST", 4);
+    GST_WRITE_UINT32_LE (buffdata + 4, strl_size);
+    memcpy (buffdata + 8, "strl", 4);
+    /* generic header */
+    memcpy (buffdata + 12, "strh", 4);
+    GST_WRITE_UINT32_LE (buffdata + 16, sizeof (gst_riff_strh_full));
+    /* the actual header */
+    GST_WRITE_UINT32_LE (buffdata + 20, avipad->hdr.type);
+    GST_WRITE_UINT32_LE (buffdata + 24, avipad->hdr.fcc_handler);
+    GST_WRITE_UINT32_LE (buffdata + 28, avipad->hdr.flags);
+    GST_WRITE_UINT32_LE (buffdata + 32, avipad->hdr.priority);
+    GST_WRITE_UINT32_LE (buffdata + 36, avipad->hdr.init_frames);
+    GST_WRITE_UINT32_LE (buffdata + 40, avipad->hdr.scale);
+    GST_WRITE_UINT32_LE (buffdata + 44, avipad->hdr.rate);
+    GST_WRITE_UINT32_LE (buffdata + 48, avipad->hdr.start);
+    GST_WRITE_UINT32_LE (buffdata + 52, avipad->hdr.length);
+    GST_WRITE_UINT32_LE (buffdata + 56, avipad->hdr.bufsize);
+    GST_WRITE_UINT32_LE (buffdata + 60, avipad->hdr.quality);
+    GST_WRITE_UINT32_LE (buffdata + 64, avipad->hdr.samplesize);
+    GST_WRITE_UINT16_LE (buffdata + 68, 0);
+    GST_WRITE_UINT16_LE (buffdata + 70, 0);
+    GST_WRITE_UINT16_LE (buffdata + 72, 0);
+    GST_WRITE_UINT16_LE (buffdata + 74, 0);
+    buffdata += 76;
+    highmark += 76;
+
+    if (avipad->is_video) {
+      /* the video header */
+      memcpy (buffdata + 0, "strf", 4);
+      GST_WRITE_UINT32_LE (buffdata + 4,
+          sizeof (gst_riff_strf_vids) + codec_size);
+      /* the actual header */
+      GST_WRITE_UINT32_LE (buffdata + 8, vidpad->vids.size + codec_size);
+      GST_WRITE_UINT32_LE (buffdata + 12, vidpad->vids.width);
+      GST_WRITE_UINT32_LE (buffdata + 16, vidpad->vids.height);
+      GST_WRITE_UINT16_LE (buffdata + 20, vidpad->vids.planes);
+      GST_WRITE_UINT16_LE (buffdata + 22, vidpad->vids.bit_cnt);
+      GST_WRITE_UINT32_LE (buffdata + 24, vidpad->vids.compression);
+      GST_WRITE_UINT32_LE (buffdata + 28, vidpad->vids.image_size);
+      GST_WRITE_UINT32_LE (buffdata + 32, vidpad->vids.xpels_meter);
+      GST_WRITE_UINT32_LE (buffdata + 36, vidpad->vids.ypels_meter);
+      GST_WRITE_UINT32_LE (buffdata + 40, vidpad->vids.num_colors);
+      GST_WRITE_UINT32_LE (buffdata + 44, vidpad->vids.imp_colors);
+      buffdata += 48;
+      highmark += 48;
+
+      /* include codec data, if any */
+      if (codec_size) {
+        memcpy (buffdata, GST_BUFFER_DATA (vidpad->vids_codec_data),
+            codec_size);
+
+        buffdata += codec_size;
+        highmark += codec_size;
+      }
+      /* padding */
+      if (highmark & 0x1) {
+        highmark++;
+        buffdata++;
+      }
+
+      /* add video property data, mainly for aspect ratio, if any */
+      if (vprp_size) {
+        gint f;
+
+        /* the vprp header */
+        memcpy (buffdata + 0, "vprp", 4);
+        GST_WRITE_UINT32_LE (buffdata + 4, vprp_size);
+        /* the actual data */
+        GST_WRITE_UINT32_LE (buffdata + 8, vidpad->vprp.format_token);
+        GST_WRITE_UINT32_LE (buffdata + 12, vidpad->vprp.standard);
+        GST_WRITE_UINT32_LE (buffdata + 16, vidpad->vprp.vert_rate);
+        GST_WRITE_UINT32_LE (buffdata + 20, vidpad->vprp.hor_t_total);
+        GST_WRITE_UINT32_LE (buffdata + 24, vidpad->vprp.vert_lines);
+        GST_WRITE_UINT32_LE (buffdata + 28, vidpad->vprp.aspect);
+        GST_WRITE_UINT32_LE (buffdata + 32, vidpad->vprp.width);
+        GST_WRITE_UINT32_LE (buffdata + 36, vidpad->vprp.height);
+        GST_WRITE_UINT32_LE (buffdata + 40, vidpad->vprp.fields);
+        buffdata += 44;
+        highmark += 44;
+        for (f = 0; f < vidpad->vprp.fields; ++f) {
+          gst_riff_vprp_video_field_desc *fd;
+
+          fd = &(vidpad->vprp.field_info[f]);
+          GST_WRITE_UINT32_LE (buffdata + 0, fd->compressed_bm_height);
+          GST_WRITE_UINT32_LE (buffdata + 4, fd->compressed_bm_width);
+          GST_WRITE_UINT32_LE (buffdata + 8, fd->valid_bm_height);
+          GST_WRITE_UINT32_LE (buffdata + 12, fd->valid_bm_width);
+          GST_WRITE_UINT32_LE (buffdata + 16, fd->valid_bm_x_offset);
+          GST_WRITE_UINT32_LE (buffdata + 20, fd->valid_bm_y_offset);
+          GST_WRITE_UINT32_LE (buffdata + 24, fd->video_x_t_offset);
+          GST_WRITE_UINT32_LE (buffdata + 28, fd->video_y_start);
+          buffdata += 32;
+          highmark += 32;
+        }
+      }
+    } else {
+      /* the audio header */
+      memcpy (buffdata + 0, "strf", 4);
+      GST_WRITE_UINT32_LE (buffdata + 4,
+          sizeof (gst_riff_strf_auds) + 2 + codec_size);
+      /* the actual header */
+      GST_WRITE_UINT16_LE (buffdata + 8, audpad->auds.format);
+      GST_WRITE_UINT16_LE (buffdata + 10, audpad->auds.channels);
+      GST_WRITE_UINT32_LE (buffdata + 12, audpad->auds.rate);
+      GST_WRITE_UINT32_LE (buffdata + 16, audpad->auds.av_bps);
+      GST_WRITE_UINT16_LE (buffdata + 20, audpad->auds.blockalign);
+      GST_WRITE_UINT16_LE (buffdata + 22, audpad->auds.size);
+      GST_WRITE_UINT16_LE (buffdata + 24, codec_size);
+      buffdata += 26;
+      highmark += 26;
+
+      /* include codec data, if any */
+      if (codec_size) {
+        memcpy (buffdata, GST_BUFFER_DATA (audpad->auds_codec_data),
+            codec_size);
+
+        buffdata += codec_size;
+        highmark += codec_size;
+      }
+      /* padding */
+      if (highmark & 0x1) {
+        highmark++;
+        buffdata++;
+      }
+    }
+
+    /* odml superindex chunk */
+    if (avipad->idx_index > 0)
+      memcpy (buffdata, "indx", 4);
+    else
+      memcpy (buffdata, "JUNK", 4);
+    GST_WRITE_UINT32_LE (buffdata + 4, ODML_SUPERINDEX_SIZE - 8);       /* chunk size */
+    GST_WRITE_UINT16_LE (buffdata + 8, 4);      /* bytes per entry */
+    buffdata[10] = 0;           /* index subtype */
+    buffdata[11] = GST_AVI_INDEX_OF_INDEXES;    /* index type */
+    GST_WRITE_UINT32_LE (buffdata + 12, avipad->idx_index);     /* entries in use */
+    memcpy (buffdata + 16, avipad->tag, 4);     /* stream id */
+    GST_WRITE_UINT32_LE (buffdata + 20, 0);     /* reserved */
+    GST_WRITE_UINT32_LE (buffdata + 24, 0);     /* reserved */
+    GST_WRITE_UINT32_LE (buffdata + 28, 0);     /* reserved */
+    memcpy (buffdata + 32, avipad->idx,
+        GST_AVI_SUPERINDEX_COUNT * sizeof (gst_avi_superindex_entry));
+    buffdata += ODML_SUPERINDEX_SIZE;
+    highmark += ODML_SUPERINDEX_SIZE;
+
+    node = node->next;
+  }
+
+  if (avimux->video_pads > 0) {
+    /* odml header */
+    memcpy (buffdata + 0, "LIST", 4);
+    GST_WRITE_UINT32_LE (buffdata + 4, sizeof (guint32) + 4 * 3);
+    memcpy (buffdata + 8, "odml", 4);
+    memcpy (buffdata + 12, "dmlh", 4);
+    GST_WRITE_UINT32_LE (buffdata + 16, sizeof (guint32));
+    GST_WRITE_UINT32_LE (buffdata + 20, avimux->total_frames);
+    buffdata += 24;
+    highmark += 24;
+  }
+
+  GST_WRITE_UINT32_LE (hdrl_size, (guint32) (buffdata - hdrl_size) - 4);
+
+  /* tags */
+  if (tags) {
+    guint8 *ptr;
+    guint startsize;
+    GstMarkedBuffer data ;
+    data.highmark = &highmark;
+    data.buffer = buffer;
+
+    memcpy (buffdata + 0, "LIST", 4);
+    ptr = buffdata + 4;         /* fill in later */
+    startsize = highmark + 4;
+    memcpy (buffdata + 8, "INFO", 4);
+    buffdata += 12;
+    highmark += 12;
+
+    /* 12 bytes is needed for data header */
+    GST_BUFFER_SIZE (buffer) -= 12;
+    gst_tag_list_foreach (tags, gst_avi_mux_write_tag, &data);
+    GST_BUFFER_SIZE (buffer) += 12;
+    buffdata = GST_BUFFER_DATA (buffer) + highmark;
+
+    /* update list size */
+    GST_WRITE_UINT32_LE (ptr, highmark - startsize - 4);
+  }
+
+  /* avi data header */
+  memcpy (buffdata + 0, "LIST", 4);
+  GST_WRITE_UINT32_LE (buffdata + 4, avimux->data_size);
+  memcpy (buffdata + 8, "movi", 4);
+  buffdata += 12;
+  highmark += 12;
+
+  /* finally we can fill in the RIFF size */
+  /* note that riff only counts the first avi chunk */
+  GST_WRITE_UINT32_LE (riff_size, (guint32) (buffdata - riff_size - 4)  /* header and movi tags */
+      +avimux->idx_size + avimux->data_size - 4);       /* movi data and index */
+
+  {                             /* only the part that is filled in actually makes up the header
+                                 *  unref the parent as we only need this part from now on */
+    GstBuffer *subbuffer = gst_buffer_create_sub (buffer, 0, highmark);
+
+    gst_buffer_unref (buffer);
+    return subbuffer;
+  }
+}
+
+static GstBuffer *
+gst_avi_mux_riff_get_avix_header (guint32 datax_size)
+{
+  GstBuffer *buffer;
+  guint8 *buffdata;
+
+  buffer = gst_buffer_new_and_alloc (24);
+  buffdata = GST_BUFFER_DATA (buffer);
+
+  memcpy (buffdata + 0, "RIFF", 4);
+  GST_WRITE_UINT32_LE (buffdata + 4, datax_size + 3 * 4);
+  memcpy (buffdata + 8, "AVIX", 4);
+  memcpy (buffdata + 12, "LIST", 4);
+  GST_WRITE_UINT32_LE (buffdata + 16, datax_size);
+  memcpy (buffdata + 20, "movi", 4);
+
+  return buffer;
+}
+
+static inline GstBuffer *
+gst_avi_mux_riff_get_header (GstAviPad * avipad, guint32 video_frame_size)
+{
+  GstBuffer *buffer;
+  guint8 *buffdata;
+
+  buffer = gst_buffer_new_and_alloc (8);
+  buffdata = GST_BUFFER_DATA (buffer);
+  memcpy (buffdata + 0, avipad->tag, 4);
+  GST_WRITE_UINT32_LE (buffdata + 4, video_frame_size);
+
+  return buffer;
+}
+
+/* write an odml index chunk in the movi list */
+static GstFlowReturn
+gst_avi_mux_write_avix_index (GstAviMux * avimux, gchar * code,
+    gchar * chunk, gst_avi_superindex_entry * super_index,
+    gint * super_index_count)
+{
+  GstFlowReturn res;
+  GstBuffer *buffer;
+  guint8 *buffdata, *data;
+  gst_riff_index_entry *entry;
+  gint i;
+  guint32 size, entry_count;
+
+  /* allocate the maximum possible */
+  buffer = gst_buffer_new_and_alloc (32 + 8 * avimux->idx_index);
+  buffdata = GST_BUFFER_DATA (buffer);
+
+  /* general index chunk info */
+  memcpy (buffdata + 0, chunk, 4);      /* chunk id */
+  GST_WRITE_UINT32_LE (buffdata + 4, 0);        /* chunk size; fill later */
+  GST_WRITE_UINT16_LE (buffdata + 8, 2);        /* index entry is 2 words */
+  buffdata[10] = 0;             /* index subtype */
+  buffdata[11] = GST_AVI_INDEX_OF_CHUNKS;       /* index type: AVI_INDEX_OF_CHUNKS */
+  GST_WRITE_UINT32_LE (buffdata + 12, 0);       /* entries in use; fill later */
+  memcpy (buffdata + 16, code, 4);      /* stream to which index refers */
+  GST_WRITE_UINT64_LE (buffdata + 20, avimux->avix_start);      /* base offset */
+  GST_WRITE_UINT32_LE (buffdata + 28, 0);       /* reserved */
+  buffdata += 32;
+
+  /* now the actual index entries */
+  i = avimux->idx_index;
+  entry = avimux->idx;
+  while (i > 0) {
+    if (memcmp (&entry->id, code, 4) == 0) {
+      /* enter relative offset to the data (!) */
+      GST_WRITE_UINT32_LE (buffdata, GUINT32_FROM_LE (entry->offset) + 8);
+      /* msb is set if not (!) keyframe */
+      GST_WRITE_UINT32_LE (buffdata + 4, GUINT32_FROM_LE (entry->size)
+          | (GUINT32_FROM_LE (entry->flags)
+              & GST_RIFF_IF_KEYFRAME ? 0 : 1U << 31));
+      buffdata += 8;
+    }
+    i--;
+    entry++;
+  }
+
+  /* ok, now we know the size and no of entries, fill in where needed */
+  data = GST_BUFFER_DATA (buffer);
+  GST_BUFFER_SIZE (buffer) = size = buffdata - data;
+  GST_WRITE_UINT32_LE (data + 4, size - 8);
+  entry_count = (size - 32) / 8;
+  GST_WRITE_UINT32_LE (data + 12, entry_count);
+
+  /* decorate and send */
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (avimux->srcpad));
+  if ((res = gst_pad_push (avimux->srcpad, buffer)) != GST_FLOW_OK)
+    return res;
+
+  /* keep track of this in superindex (if room) ... */
+  if (*super_index_count < GST_AVI_SUPERINDEX_COUNT) {
+    i = *super_index_count;
+    super_index[i].offset = GUINT64_TO_LE (avimux->total_data);
+    super_index[i].size = GUINT32_TO_LE (size);
+    super_index[i].duration = GUINT32_TO_LE (entry_count);
+    (*super_index_count)++;
+  } else
+    GST_WARNING_OBJECT (avimux, "No more room in superindex of stream %s",
+        code);
+
+  /* ... and in size */
+  avimux->total_data += size;
+  if (avimux->is_bigfile)
+    avimux->datax_size += size;
+  else
+    avimux->data_size += size;
+
+  return GST_FLOW_OK;
+}
+
+/* some other usable functions (thankyou xawtv ;-) ) */
+
+static void
+gst_avi_mux_add_index (GstAviMux * avimux, gchar * code, guint32 flags,
+    guint32 size)
+{
+  if (avimux->idx_index == avimux->idx_count) {
+    avimux->idx_count += 256;
+    avimux->idx =
+        g_realloc (avimux->idx,
+        avimux->idx_count * sizeof (gst_riff_index_entry));
+  }
+  memcpy (&(avimux->idx[avimux->idx_index].id), code, 4);
+  avimux->idx[avimux->idx_index].flags = GUINT32_TO_LE (flags);
+  avimux->idx[avimux->idx_index].offset = GUINT32_TO_LE (avimux->idx_offset);
+  avimux->idx[avimux->idx_index].size = GUINT32_TO_LE (size);
+  avimux->idx_index++;
+}
+
+static GstFlowReturn
+gst_avi_mux_write_index (GstAviMux * avimux)
+{
+  GstFlowReturn res;
+  GstBuffer *buffer;
+  guint8 *buffdata;
+
+  buffer = gst_buffer_new_and_alloc (8);
+  buffdata = GST_BUFFER_DATA (buffer);
+  memcpy (buffdata + 0, "idx1", 4);
+  GST_WRITE_UINT32_LE (buffdata + 4,
+      avimux->idx_index * sizeof (gst_riff_index_entry));
+
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (avimux->srcpad));
+  res = gst_pad_push (avimux->srcpad, buffer);
+  if (res != GST_FLOW_OK)
+    return res;
+
+  buffer = gst_buffer_new ();
+  GST_BUFFER_SIZE (buffer) = avimux->idx_index * sizeof (gst_riff_index_entry);
+  GST_BUFFER_DATA (buffer) = (guint8 *) avimux->idx;
+  GST_BUFFER_MALLOCDATA (buffer) = GST_BUFFER_DATA (buffer);
+  avimux->idx = NULL;           /* will be free()'ed by gst_buffer_unref() */
+  avimux->total_data += GST_BUFFER_SIZE (buffer) + 8;
+
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (avimux->srcpad));
+  res = gst_pad_push (avimux->srcpad, buffer);
+  if (res != GST_FLOW_OK)
+    return res;
+
+  avimux->idx_size += avimux->idx_index * sizeof (gst_riff_index_entry) + 8;
+
+  /* update header */
+  avimux->avi_hdr.flags |= GST_RIFF_AVIH_HASINDEX;
+  return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_avi_mux_bigfile (GstAviMux * avimux, gboolean last)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+  GstBuffer *header;
+  GstEvent *event;
+  GSList *node;
+
+  /* first some odml standard index chunks in the movi list */
+  node = avimux->sinkpads;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+
+    node = node->next;
+
+    res = gst_avi_mux_write_avix_index (avimux, avipad->tag,
+        avipad->idx_tag, avipad->idx, &avipad->idx_index);
+    if (res != GST_FLOW_OK)
+      return res;
+  }
+
+  if (avimux->is_bigfile) {
+    /* search back */
+    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+        avimux->avix_start, GST_CLOCK_TIME_NONE, avimux->avix_start);
+    /* if the event succeeds */
+    gst_pad_push_event (avimux->srcpad, event);
+
+    /* rewrite AVIX header */
+    header = gst_avi_mux_riff_get_avix_header (avimux->datax_size);
+    gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad));
+    res = gst_pad_push (avimux->srcpad, header);
+
+    /* go back to current location, at least try */
+    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+        avimux->total_data, GST_CLOCK_TIME_NONE, avimux->total_data);
+    gst_pad_push_event (avimux->srcpad, event);
+
+    if (res != GST_FLOW_OK)
+      return res;
+  } else {                      /* write a standard index in the first riff chunk */
+    res = gst_avi_mux_write_index (avimux);
+    /* the index data/buffer is freed by pushing it */
+    avimux->idx_count = 0;
+    if (res != GST_FLOW_OK)
+      return res;
+  }
+
+  avimux->avix_start = avimux->total_data;
+
+  if (last)
+    return res;
+
+  avimux->is_bigfile = TRUE;
+  avimux->numx_frames = 0;
+  avimux->datax_size = 4;       /* movi tag */
+  avimux->idx_index = 0;
+
+  header = gst_avi_mux_riff_get_avix_header (0);
+  avimux->total_data += GST_BUFFER_SIZE (header);
+  /* avix_start is used as base offset for the odml index chunk */
+  avimux->idx_offset = avimux->total_data - avimux->avix_start;
+  gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad));
+  return gst_pad_push (avimux->srcpad, header);
+}
+
+/* enough header blabla now, let's go on to actually writing the headers */
+
+static GstFlowReturn
+gst_avi_mux_start_file (GstAviMux * avimux)
+{
+  GstFlowReturn res;
+  GstBuffer *header;
+  GSList *node;
+
+  avimux->total_data = 0;
+  avimux->total_frames = 0;
+  avimux->data_size = 4;        /* movi tag */
+  avimux->datax_size = 0;
+  avimux->num_frames = 0;
+  avimux->numx_frames = 0;
+  avimux->avix_start = 0;
+
+  avimux->idx_index = 0;
+  avimux->idx_offset = 0;       /* see 10 lines below */
+  avimux->idx_size = 0;
+  avimux->idx_count = 0;
+  avimux->idx = NULL;
+
+  /* state */
+  avimux->write_header = FALSE;
+  avimux->restart = FALSE;
+
+  /* init streams, see what we've got */
+  node = avimux->sinkpads;
+  avimux->audio_pads = avimux->video_pads = 0;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+
+    node = node->next;
+
+    if (!avipad->is_video) {
+      /* audio stream numbers must start at 1 iff there is a video stream 0;
+       * request_pad inserts video pad at head of list, so this test suffices */
+      if (avimux->video_pads)
+        avimux->audio_pads++;
+      avipad->tag = g_strdup_printf ("%02uwb", avimux->audio_pads);
+      avipad->idx_tag = g_strdup_printf ("ix%02u", avimux->audio_pads);
+      if (!avimux->video_pads)
+        avimux->audio_pads++;
+    } else {
+      avipad->tag = g_strdup_printf ("%02udb", avimux->video_pads);
+      avipad->idx_tag = g_strdup_printf ("ix%02u", avimux->video_pads++);
+    }
+  }
+
+  /* let downstream know we think in BYTES and expect to do seeking later on */
+  gst_pad_push_event (avimux->srcpad,
+      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
+
+  /* header */
+  avimux->avi_hdr.streams = g_slist_length (avimux->sinkpads);
+  avimux->is_bigfile = FALSE;
+
+  header = gst_avi_mux_riff_get_avi_header (avimux);
+  avimux->total_data += GST_BUFFER_SIZE (header);
+
+  gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad));
+  res = gst_pad_push (avimux->srcpad, header);
+
+  avimux->idx_offset = avimux->total_data;
+
+  return res;
+}
+
+static GstFlowReturn
+gst_avi_mux_stop_file (GstAviMux * avimux)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+  GstEvent *event;
+  GstBuffer *header;
+  GSList *node;
+
+  /* if bigfile, rewrite header, else write indexes */
+  /* don't bail out at once if error, still try to re-write header */
+  if (avimux->video_pads > 0) {
+    if (avimux->is_bigfile) {
+      res = gst_avi_mux_bigfile (avimux, TRUE);
+    } else {
+      res = gst_avi_mux_write_index (avimux);
+    }
+  }
+
+  /* we do our best to make it interleaved at least ... */
+  if (avimux->audio_pads > 0 && avimux->video_pads > 0)
+    avimux->avi_hdr.flags |= GST_RIFF_AVIH_ISINTERLEAVED;
+
+  /* set rate and everything having to do with that */
+  avimux->avi_hdr.max_bps = 0;
+  node = avimux->sinkpads;
+  while (node) {
+    GstAviPad *avipad = (GstAviPad *) node->data;
+
+    node = node->next;
+
+    if (!avipad->is_video) {
+      GstAviAudioPad *audpad = (GstAviAudioPad *) avipad;
+
+      /* calculate bps if needed */
+      if (!audpad->auds.av_bps) {
+        if (audpad->audio_time) {
+          audpad->auds.av_bps =
+              (GST_SECOND * audpad->audio_size) / audpad->audio_time;
+          /* round bps to nearest multiple of 8;
+           * which is much more likely to be the (cbr) bitrate in use;
+           * which in turn results in better timestamp calculation on playback */
+          audpad->auds.av_bps = GST_ROUND_UP_8 (audpad->auds.av_bps - 4);
+        } else {
+          GST_ELEMENT_WARNING (avimux, STREAM, MUX,
+              (_("No or invalid input audio, AVI stream will be corrupt.")),
+              (NULL));
+          audpad->auds.av_bps = 0;
+        }
+        avipad->hdr.rate = audpad->auds.av_bps * avipad->hdr.scale;
+      }
+      avimux->avi_hdr.max_bps += audpad->auds.av_bps;
+      avipad->hdr.length = (audpad->audio_time * avipad->hdr.rate) / GST_SECOND;
+    } else {
+      GstAviVideoPad *vidpad = (GstAviVideoPad *) avipad;
+
+      avimux->avi_hdr.max_bps += ((vidpad->vids.bit_cnt + 7) / 8) *
+          (1000000. / avimux->avi_hdr.us_frame) * vidpad->vids.image_size;
+      avipad->hdr.length = avimux->total_frames;
+    }
+  }
+
+  /* statistics/total_frames/... */
+  avimux->avi_hdr.tot_frames = avimux->num_frames;
+
+  /* seek and rewrite the header */
+  header = gst_avi_mux_riff_get_avi_header (avimux);
+  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+      0, GST_CLOCK_TIME_NONE, 0);
+  gst_pad_push_event (avimux->srcpad, event);
+
+  gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad));
+  /* the first error survives */
+  if (res == GST_FLOW_OK)
+    res = gst_pad_push (avimux->srcpad, header);
+  else
+    gst_pad_push (avimux->srcpad, header);
+
+  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+      avimux->total_data, GST_CLOCK_TIME_NONE, avimux->total_data);
+  gst_pad_push_event (avimux->srcpad, event);
+
+  avimux->write_header = TRUE;
+
+  return res;
+}
+
+static GstFlowReturn
+gst_avi_mux_restart_file (GstAviMux * avimux)
+{
+  GstFlowReturn res;
+
+  if ((res = gst_avi_mux_stop_file (avimux)) != GST_FLOW_OK)
+    return res;
+
+  gst_pad_push_event (avimux->srcpad, gst_event_new_eos ());
+
+  return gst_avi_mux_start_file (avimux);
+}
+
+/* handle events (search) */
+static gboolean
+gst_avi_mux_handle_event (GstPad * pad, GstEvent * event)
+{
+  GstAviMux *avimux;
+  gboolean ret;
+
+  avimux = GST_AVI_MUX (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_TAG:{
+      GstTagList *list;
+      GstTagSetter *setter = GST_TAG_SETTER (avimux);
+      const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
+
+      gst_event_parse_tag (event, &list);
+      gst_tag_setter_merge_tags (setter, list, mode);
+      break;
+    }
+    default:
+      break;
+  }
+
+  /* now GstCollectPads can take care of the rest, e.g. EOS */
+  ret = avimux->collect_event (pad, event);
+
+  gst_object_unref (avimux);
+
+  return ret;
+}
+
+/* send extra 'padding' data */
+static GstFlowReturn
+gst_avi_mux_send_pad_data (GstAviMux * avimux, gulong num_bytes)
+{
+  GstBuffer *buffer;
+
+  buffer = gst_buffer_new_and_alloc (num_bytes);
+  memset (GST_BUFFER_DATA (buffer), 0, num_bytes);
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (avimux->srcpad));
+  return gst_pad_push (avimux->srcpad, buffer);
+}
+
+/* do buffer */
+static GstFlowReturn
+gst_avi_mux_do_buffer (GstAviMux * avimux, GstAviPad * avipad)
+{
+  GstFlowReturn res;
+  GstBuffer *data, *header;
+  gulong total_size, pad_bytes = 0;
+  guint flags;
+
+  data = gst_collect_pads_pop (avimux->collect, avipad->collect);
+
+  if (avimux->restart) {
+    if ((res = gst_avi_mux_restart_file (avimux)) != GST_FLOW_OK)
+      return res;
+  }
+
+  /* need to restart or start a next avix chunk ? */
+  if ((avimux->is_bigfile ? avimux->datax_size : avimux->data_size) +
+      GST_BUFFER_SIZE (data) > 1024 * 1024 * 2000) {
+    if (avimux->enable_large_avi) {
+      if ((res = gst_avi_mux_bigfile (avimux, FALSE)) != GST_FLOW_OK)
+        return res;
+    } else {
+      if ((res = gst_avi_mux_restart_file (avimux)) != GST_FLOW_OK)
+        return res;
+    }
+  }
+
+  /* get header and record some stats */
+  if (GST_BUFFER_SIZE (data) & 1) {
+    pad_bytes = 2 - (GST_BUFFER_SIZE (data) & 1);
+  }
+  header = gst_avi_mux_riff_get_header (avipad, GST_BUFFER_SIZE (data));
+  total_size = GST_BUFFER_SIZE (header) + GST_BUFFER_SIZE (data) + pad_bytes;
+
+  if (avimux->is_bigfile) {
+    avimux->datax_size += total_size;
+  } else {
+    avimux->data_size += total_size;
+  }
+
+  if (avipad->is_video) {
+    avimux->total_frames++;
+
+    if (avimux->is_bigfile) {
+      avimux->numx_frames++;
+    } else {
+      avimux->num_frames++;
+    }
+
+    flags = 0x02;
+    if (!GST_BUFFER_FLAG_IS_SET (data, GST_BUFFER_FLAG_DELTA_UNIT))
+      flags |= 0x10;
+  } else {
+    GstAviAudioPad *audpad = (GstAviAudioPad *) avipad;
+
+    flags = 0;
+    audpad->audio_size += GST_BUFFER_SIZE (data);
+    audpad->audio_time += GST_BUFFER_DURATION (data);
+  }
+
+  gst_avi_mux_add_index (avimux, avipad->tag, flags, GST_BUFFER_SIZE (data));
+
+  /* prepare buffers for sending */
+  gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad));
+  data = gst_buffer_make_metadata_writable (data);
+  gst_buffer_set_caps (data, GST_PAD_CAPS (avimux->srcpad));
+
+  GST_LOG_OBJECT (avimux, "pushing buffers: head, data");
+
+  if ((res = gst_pad_push (avimux->srcpad, header)) != GST_FLOW_OK)
+    return res;
+  if ((res = gst_pad_push (avimux->srcpad, data)) != GST_FLOW_OK)
+    return res;
+
+  if (pad_bytes) {
+    if ((res = gst_avi_mux_send_pad_data (avimux, pad_bytes)) != GST_FLOW_OK)
+      return res;
+  }
+
+  /* if any push above fails, we're in trouble with file consistency anyway */
+  avimux->total_data += total_size;
+  avimux->idx_offset += total_size;
+
+  return res;
+}
+
+/* pick the oldest buffer from the pads and push it */
+static GstFlowReturn
+gst_avi_mux_do_one_buffer (GstAviMux * avimux)
+{
+  GstAviPad *avipad, *best_pad;
+  GSList *node;
+  GstBuffer *buffer;
+  GstClockTime time, best_time;
+
+  node = avimux->sinkpads;
+  best_pad = NULL;
+  best_time = GST_CLOCK_TIME_NONE;
+  for (; node; node = node->next) {
+    avipad = (GstAviPad *) node->data;
+
+    if (!avipad->collect)
+      continue;
+
+    buffer = gst_collect_pads_peek (avimux->collect, avipad->collect);
+    if (!buffer)
+      continue;
+    time = GST_BUFFER_TIMESTAMP (buffer);
+    gst_buffer_unref (buffer);
+
+    /* invalid timestamp buffers pass first,
+     * these are probably initialization buffers */
+    if (best_pad == NULL || !GST_CLOCK_TIME_IS_VALID (time)
+        || (GST_CLOCK_TIME_IS_VALID (best_time) && time < best_time)) {
+      best_pad = avipad;
+      best_time = time;
+    }
+  }
+
+  if (best_pad) {
+    GST_LOG_OBJECT (avimux, "selected pad %s with time %" GST_TIME_FORMAT,
+        GST_PAD_NAME (best_pad->collect->pad), GST_TIME_ARGS (best_time));
+
+    return gst_avi_mux_do_buffer (avimux, best_pad);
+  } else {
+    /* simply finish off the file and send EOS */
+    gst_avi_mux_stop_file (avimux);
+    gst_pad_push_event (avimux->srcpad, gst_event_new_eos ());
+    return GST_FLOW_UNEXPECTED;
+  }
+}
+
+static GstFlowReturn
+gst_avi_mux_collect_pads (GstCollectPads * pads, GstAviMux * avimux)
+{
+  GstFlowReturn res;
+
+  if (G_UNLIKELY (avimux->write_header)) {
+    if ((res = gst_avi_mux_start_file (avimux)) != GST_FLOW_OK)
+      return res;
+  }
+
+  return gst_avi_mux_do_one_buffer (avimux);
+}
+
+
+static void
+gst_avi_mux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstAviMux *avimux;
+
+  avimux = GST_AVI_MUX (object);
+
+  switch (prop_id) {
+    case ARG_BIGFILE:
+      g_value_set_boolean (value, avimux->enable_large_avi);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_avi_mux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstAviMux *avimux;
+
+  avimux = GST_AVI_MUX (object);
+
+  switch (prop_id) {
+    case ARG_BIGFILE:
+      avimux->enable_large_avi = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstStateChangeReturn
+gst_avi_mux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstAviMux *avimux;
+  GstStateChangeReturn ret;
+
+  avimux = GST_AVI_MUX (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_collect_pads_start (avimux->collect);
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_collect_pads_stop (avimux->collect);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    goto done;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_avi_mux_reset (avimux);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+done:
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavimux.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,179 @@
+/* AVI muxer plugin for GStreamer
+ * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * 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_AVI_MUX_H__
+#define __GST_AVI_MUX_H__
+
+
+#include <gst/gst.h>
+#include <gst/base/gstcollectpads.h>
+#include <gst/riff/riff-ids.h>
+#include "avi-ids.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AVI_MUX \
+  (gst_avi_mux_get_type())
+#define GST_AVI_MUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVI_MUX,GstAviMux))
+#define GST_AVI_MUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVI_MUX,GstAviMuxClass))
+#define GST_IS_AVI_MUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVI_MUX))
+#define GST_IS_AVI_MUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVI_MUX))
+
+#define GST_AVI_INDEX_OF_INDEXES     0
+#define GST_AVI_INDEX_OF_CHUNKS      1
+
+/* this allows indexing up to 64GB avi file */
+#define GST_AVI_SUPERINDEX_COUNT    32
+
+typedef struct _gst_avi_superindex_entry {
+  guint64 offset;
+  guint32 size;
+  guint32 duration;
+} gst_avi_superindex_entry;
+
+typedef struct _gst_riff_strh_full {
+  gst_riff_strh  parent;
+  /* rcFrame, RECT structure (struct of 4 shorts) */
+  gint16  left;
+  gint16  top;
+  gint16  right;
+  gint16  bottom;
+} gst_riff_strh_full;
+
+typedef struct _GstAviPad {
+  /* do not extend, link to it */
+  /* is NULL if original sink request pad has been removed */
+  GstCollectData *collect;
+
+  /* type */
+  gboolean is_video;
+  gboolean connected;
+
+  /* chunk tag */
+  gchar *tag;
+
+  /* stream header */
+  gst_riff_strh hdr;
+
+  /* odml super indexes */
+  gst_avi_superindex_entry idx[GST_AVI_SUPERINDEX_COUNT];
+  gint idx_index;
+  gchar *idx_tag;
+} GstAviPad;
+
+typedef struct _GstAviVideoPad {
+  GstAviPad parent;
+
+  /* stream format */
+  gst_riff_strf_vids vids;
+  /* extra data */
+  GstBuffer *vids_codec_data;
+  /* ODML video properties */
+  gst_riff_vprp vprp;
+
+} GstAviVideoPad;
+
+typedef struct _GstAviAudioPad {
+  GstAviPad parent;
+
+  /* stream format */
+  gst_riff_strf_auds auds;
+  /* audio info for bps calculation */
+  guint32 audio_size;
+  guint64 audio_time;
+  /* extra data */
+  GstBuffer *auds_codec_data;
+} GstAviAudioPad;
+
+typedef struct _GstAviCollectData {
+  /* extend the CollectData */
+  GstCollectData collect;
+
+  GstAviPad      *avipad;
+} GstAviCollectData;
+
+typedef struct _GstAviMux GstAviMux;
+typedef struct _GstAviMuxClass GstAviMuxClass;
+
+struct _GstAviMux {
+  GstElement element;
+
+  /* pads */
+  GstPad              *srcpad;
+  /* sinkpads, video first */
+  GSList              *sinkpads;
+  /* video restricted to 1 pad */
+  guint               video_pads, audio_pads;
+  GstCollectPads      *collect;
+  GstPadEventFunction  collect_event;
+
+  /* the AVI header */
+  /* still some single stream video data in mux struct */
+  gst_riff_avih avi_hdr;
+  /* total number of (video) frames */
+  guint32 total_frames;
+  /* amount of total data (bytes) */
+  guint64 total_data;
+  /* amount of data (bytes) in the AVI/AVIX block;
+   * actually the movi list, so counted from and including the movi tag */
+  guint32 data_size, datax_size;
+  /* num (video) frames in the AVI/AVIX block */
+  guint32 num_frames, numx_frames;
+  /* size of hdrl list, including tag as usual */
+
+  /* total size of extra codec data */
+  guint32 codec_data_size;
+  /* state info */
+  gboolean write_header;
+  gboolean restart;
+
+  /* tags */
+  GstTagList *tags_snap;
+
+  /* information about the AVI index ('idx') */
+  gst_riff_index_entry *idx;
+  gint idx_index, idx_count;
+  /* offset of *chunk* (relative to a base offset); entered in the index */
+  guint32 idx_offset;
+  /* size of idx1 chunk (including! chunk header and size bytes) */
+  guint32 idx_size;
+
+  /* are we a big file already? */
+  gboolean is_bigfile;
+  guint64 avix_start;
+
+  /* whether to use "large AVI files" or just stick to small indexed files */
+  gboolean enable_large_avi;
+};
+
+struct _GstAviMuxClass {
+  GstElementClass parent_class;
+};
+
+GType gst_avi_mux_get_type(void);
+
+G_END_DECLS
+
+
+#endif /* __GST_AVI_MUX_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavisubtitle.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,376 @@
+/* GStreamer AVI GAB2 subtitle parser
+ * Copyright (C) <2007> Thijs Vermeir <thijsvermeir@gmail.com>
+ * Copyright (C) <2007> Tim-Philipp Müller <tim centricular net>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:element-avisubtitle
+ *
+ * <refsect2>
+ * <para>
+ * Parses the subtitle stream from an avi file.
+ * </para>
+ * <title>Example launch line</title>
+ * <para>
+ * <programlisting>
+ * gst-launch filesrc location=subtitle.avi ! avidemux name=demux ! queue ! avisubtitle ! subparse ! textoverlay name=overlay ! ffmpegcolorspace ! autovideosink demux. ! queue ! decodebin ! overlay.
+ * </programlisting>
+ * This plays an avi file with a video and subtitle stream.
+ * </para>
+ * </refsect2>
+ *
+ * Last reviewed on 2008-02-01
+ */
+
+/* example of a subtitle chunk in an avi file
+ * 00000000: 47 41 42 32 00 02 00 10 00 00 00 45 00 6e 00 67  GAB2.......E.n.g
+ * 00000010: 00 6c 00 69 00 73 00 68 00 00 00 04 00 8e 00 00  .l.i.s.h........
+ * 00000020: 00 ef bb bf 31 0d 0a 30 30 3a 30 30 3a 30 30 2c  ....1..00:00:00,
+ * 00000030: 31 30 30 20 2d 2d 3e 20 30 30 3a 30 30 3a 30 32  100 --> 00:00:02
+ * 00000040: 2c 30 30 30 0d 0a 3c 62 3e 41 6e 20 55 54 46 38  ,000..<b>An UTF8
+ * 00000050: 20 53 75 62 74 69 74 6c 65 20 77 69 74 68 20 42   Subtitle with B
+ * 00000060: 4f 4d 3c 2f 62 3e 0d 0a 0d 0a 32 0d 0a 30 30 3a  OM</b>....2..00:
+ * 00000070: 30 30 3a 30 32 2c 31 30 30 20 2d 2d 3e 20 30 30  00:02,100 --> 00
+ * 00000080: 3a 30 30 3a 30 34 2c 30 30 30 0d 0a 53 6f 6d 65  :00:04,000..Some
+ * 00000090: 74 68 69 6e 67 20 6e 6f 6e 41 53 43 49 49 20 2d  thing nonASCII -
+ * 000000a0: 20 c2 b5 c3 b6 c3 a4 c3 bc c3 9f 0d 0a 0d 0a      ..............
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstavisubtitle.h"
+
+GST_DEBUG_CATEGORY_STATIC (avisubtitle_debug);
+#define GST_CAT_DEFAULT avisubtitle_debug
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-subtitle-avi")
+    );
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-subtitle")
+    );
+
+static void gst_avi_subtitle_title_tag (GstAviSubtitle * sub, gchar * title);
+static GstFlowReturn gst_avi_subtitle_chain (GstPad * pad, GstBuffer * buffer);
+static GstStateChangeReturn gst_avi_subtitle_change_state (GstElement * element,
+    GstStateChange transition);
+static gboolean gst_avi_subtitle_send_event (GstElement * element,
+    GstEvent * event);
+
+GST_BOILERPLATE (GstAviSubtitle, gst_avi_subtitle, GstElement,
+    GST_TYPE_ELEMENT);
+
+#define IS_BOM_UTF8(data)     ((GST_READ_UINT32_BE(data) >> 8) == 0xEFBBBF)
+#define IS_BOM_UTF16_BE(data) (GST_READ_UINT16_BE(data) == 0xFEFF)
+#define IS_BOM_UTF16_LE(data) (GST_READ_UINT16_LE(data) == 0xFEFF)
+#define IS_BOM_UTF32_BE(data) (GST_READ_UINT32_BE(data) == 0xFEFF)
+#define IS_BOM_UTF32_LE(data) (GST_READ_UINT32_LE(data) == 0xFEFF)
+
+static GstBuffer *
+gst_avi_subtitle_extract_file (GstAviSubtitle * sub, GstBuffer * buffer,
+    guint offset, guint len)
+{
+  const gchar *input_enc = NULL;
+  GstBuffer *ret = NULL;
+  gchar *data;
+
+  data = (gchar *) GST_BUFFER_DATA (buffer) + offset;
+
+  if (len >= (3 + 1) && IS_BOM_UTF8 (data) &&
+      g_utf8_validate (data + 3, len - 3, NULL)) {
+    ret = gst_buffer_create_sub (buffer, offset + 3, len - 3);
+  } else if (len >= 2 && IS_BOM_UTF16_BE (data)) {
+    input_enc = "UTF-16BE";
+    data += 2;
+    len -= 2;
+  } else if (len >= 2 && IS_BOM_UTF16_LE (data)) {
+    input_enc = "UTF-16LE";
+    data += 2;
+    len -= 2;
+  } else if (len >= 4 && IS_BOM_UTF32_BE (data)) {
+    input_enc = "UTF-32BE";
+    data += 4;
+    len -= 4;
+  } else if (len >= 4 && IS_BOM_UTF32_LE (data)) {
+    input_enc = "UTF-32LE";
+    data += 4;
+    len -= 4;
+  } else if (g_utf8_validate (data, len, NULL)) {
+    /* not specified, check if it's UTF-8 */
+    ret = gst_buffer_create_sub (buffer, offset, len);
+  } else {
+    /* we could fall back to gst_tag_freeform_to_utf8() here */
+    GST_WARNING_OBJECT (sub, "unspecified encoding, and not UTF-8");
+    return NULL;
+  }
+
+  g_return_val_if_fail (ret != NULL || input_enc != NULL, NULL);
+
+  if (input_enc) {
+    GError *err = NULL;
+    gchar *utf8;
+
+    GST_DEBUG_OBJECT (sub, "converting subtitles from %s to UTF-8", input_enc);
+    utf8 = g_convert (data, len, "UTF-8", input_enc, NULL, NULL, &err);
+
+    if (err != NULL) {
+      GST_WARNING_OBJECT (sub, "conversion to UTF-8 failed : %s", err->message);
+      g_error_free (err);
+      return NULL;
+    }
+
+    ret = gst_buffer_new ();
+    GST_BUFFER_DATA (ret) = (guint8 *) utf8;
+    GST_BUFFER_MALLOCDATA (ret) = (guint8 *) utf8;
+    GST_BUFFER_SIZE (ret) = strlen (utf8);
+    GST_BUFFER_OFFSET (ret) = 0;
+  }
+
+  GST_BUFFER_CAPS (ret) = gst_caps_new_simple ("application/x-subtitle", NULL);
+  return ret;
+}
+
+/**
+ * gst_avi_subtitle_title_tag:
+ * @sub: subtitle element
+ * @title: the title of this subtitle stream
+ *
+ * Send an event to the srcpad of the @sub element with the title
+ * of the subtitle stream as a GST_TAG_TITLE
+ */
+static void
+gst_avi_subtitle_title_tag (GstAviSubtitle * sub, gchar * title)
+{
+  GstTagList *temp_list = gst_tag_list_new ();
+
+  gst_tag_list_add (temp_list, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, title,
+      NULL);
+  gst_pad_push_event (sub->src, gst_event_new_tag (temp_list));
+}
+
+static GstFlowReturn
+gst_avi_subtitle_parse_gab2_chunk (GstAviSubtitle * sub, GstBuffer * buf)
+{
+  const guint8 *data;
+  gchar *name_utf8;
+  guint name_length;
+  guint file_length;
+  guint size;
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  /* check the magic word "GAB2\0", and the next word must be 2 */
+  if (size < 12 || memcmp (data, "GAB2\0\2\0", 5 + 2) != 0)
+    goto wrong_magic_word;
+
+  /* read 'name' of subtitle */
+  name_length = GST_READ_UINT32_LE (data + 5 + 2);
+  GST_LOG_OBJECT (sub, "length of name: %u", name_length);
+  if (size <= 17 + name_length)
+    goto wrong_name_length;
+
+  name_utf8 = g_convert ((gchar *) data + 11, name_length, "UTF-8", "UTF-16LE",
+      NULL, NULL, NULL);
+
+  if (name_utf8) {
+    GST_LOG_OBJECT (sub, "subtitle name: %s", name_utf8);
+    gst_avi_subtitle_title_tag (sub, name_utf8);
+    g_free (name_utf8);
+  }
+
+  /* next word must be 4 */
+  if (GST_READ_UINT16_LE (data + 11 + name_length) != 0x4)
+    goto wrong_fixed_word_2;
+
+  file_length = GST_READ_UINT32_LE (data + 13 + name_length);
+  GST_LOG_OBJECT (sub, "length srt/ssa file: %u", file_length);
+
+  if (size < (17 + name_length + file_length))
+    goto wrong_total_length;
+
+  /* store this, so we can send it again after a seek; note that we shouldn't
+   * assume all the remaining data in the chunk is subtitle data, there may
+   * be padding at the end for some reason, so only parse file_length bytes */
+  sub->subfile =
+      gst_avi_subtitle_extract_file (sub, buf, 17 + name_length, file_length);
+
+  if (sub->subfile == NULL)
+    goto extract_failed;
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+wrong_magic_word:
+  {
+    GST_ELEMENT_ERROR (sub, STREAM, DECODE, (NULL), ("Wrong magic word"));
+    return GST_FLOW_ERROR;
+  }
+wrong_name_length:
+  {
+    GST_ELEMENT_ERROR (sub, STREAM, DECODE, (NULL),
+        ("name doesn't fit in buffer (%d < %d)", size, 17 + name_length));
+    return GST_FLOW_ERROR;
+  }
+wrong_fixed_word_2:
+  {
+    GST_ELEMENT_ERROR (sub, STREAM, DECODE, (NULL),
+        ("wrong fixed word: expected %u, got %u", 4,
+            GST_READ_UINT16_LE (data + 11 + name_length)));
+    return GST_FLOW_ERROR;
+  }
+wrong_total_length:
+  {
+    GST_ELEMENT_ERROR (sub, STREAM, DECODE, (NULL),
+        ("buffer size is wrong: need %d bytes, have %d bytes",
+            17 + name_length + file_length, size));
+    return GST_FLOW_ERROR;
+  }
+extract_failed:
+  {
+    GST_ELEMENT_ERROR (sub, STREAM, DECODE, (NULL),
+        ("could not extract subtitles"));
+    return GST_FLOW_ERROR;
+  }
+}
+
+static GstFlowReturn
+gst_avi_subtitle_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstAviSubtitle *sub = GST_AVI_SUBTITLE (GST_PAD_PARENT (pad));
+  GstFlowReturn ret;
+
+  if (sub->subfile != NULL) {
+    GST_WARNING_OBJECT (sub, "Got more buffers than expected, dropping");
+    ret = GST_FLOW_UNEXPECTED;
+    goto done;
+  }
+
+  /* we expect exactly one buffer with the whole srt/ssa file in it */
+  ret = gst_avi_subtitle_parse_gab2_chunk (sub, buffer);
+  if (ret != GST_FLOW_OK)
+    goto done;
+
+  /* now push the subtitle data downstream */
+  ret = gst_pad_push (sub->src, gst_buffer_ref (sub->subfile));
+
+done:
+
+  gst_buffer_unref (buffer);
+  return ret;
+}
+
+static gboolean
+gst_avi_subtitle_send_event (GstElement * element, GstEvent * event)
+{
+  GstAviSubtitle *avisubtitle = GST_AVI_SUBTITLE (element);
+  gboolean ret = FALSE;
+
+  if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
+    if (avisubtitle->subfile) {
+      if (gst_pad_push (avisubtitle->src,
+              gst_buffer_ref (avisubtitle->subfile)) == GST_FLOW_OK)
+        ret = TRUE;
+    }
+  }
+  gst_event_unref (event);
+  return ret;
+}
+
+static void
+gst_avi_subtitle_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  GST_DEBUG_CATEGORY_INIT (avisubtitle_debug, "avisubtitle", 0,
+      "parse avi subtitle stream");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+
+  gst_element_class_set_details_simple (element_class,
+      "Avi subtitle parser", "Codec/Parser/Subtitle",
+      "Parse avi subtitle stream", "Thijs Vermeir <thijsvermeir@gmail.com>");
+}
+
+static void
+gst_avi_subtitle_class_init (GstAviSubtitleClass * klass)
+{
+  GstElementClass *gstelement_class = (GstElementClass *) klass;
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_avi_subtitle_change_state);
+  gstelement_class->send_event =
+      GST_DEBUG_FUNCPTR (gst_avi_subtitle_send_event);
+}
+
+static void
+gst_avi_subtitle_init (GstAviSubtitle * self, GstAviSubtitleClass * klass)
+{
+  self->src = gst_pad_new_from_static_template (&src_template, "src");
+  gst_element_add_pad (GST_ELEMENT (self), self->src);
+
+  self->sink = gst_pad_new_from_static_template (&sink_template, "sink");
+  gst_pad_set_chain_function (self->sink,
+      GST_DEBUG_FUNCPTR (gst_avi_subtitle_chain));
+  gst_element_add_pad (GST_ELEMENT (self), self->sink);
+
+  self->subfile = NULL;
+}
+
+static GstStateChangeReturn
+gst_avi_subtitle_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstAviSubtitle *sub = GST_AVI_SUBTITLE (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      if (sub->subfile) {
+        gst_buffer_unref (sub->subfile);
+        sub->subfile = NULL;
+      }
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/avi/gstavisubtitle.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,39 @@
+
+#ifndef __GSTAVISUBTITLE_H__
+#define __GSTAVISUBTITLE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstAviSubtitle GstAviSubtitle;
+typedef struct _GstAviSubtitleClass GstAviSubtitleClass;
+
+#define GST_TYPE_AVI_SUBTITLE (gst_avi_subtitle_get_type ())
+#define GST_AVI_SUBTITLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AVI_SUBTITLE, GstAviSubtitle))
+#define GST_AVI_SUBTITLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AVI_SUBTITLE, GstAviSubtitleClass))
+#define GST_IS_AVI_SUBTITLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_AVI_SUBTITLE))
+#define GST_IS_AVI_SUBTITLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_AVI_SUBTITLE))
+#define GST_AVI_SUBTITLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AVI_SUBTITLE, GstAviSubtitleClass))
+
+GType gst_avi_subtitle_get_type (void);
+
+struct _GstAviSubtitle
+{
+  GstElement parent;
+
+  GstPad    *src;
+  GstPad    *sink;
+
+  GstBuffer *subfile;  /* the complete subtitle file in one buffer */
+};
+
+struct _GstAviSubtitleClass
+{
+  GstElementClass parent;
+};
+
+G_END_DECLS
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/alaw-decode.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,344 @@
+/* GStreamer A-Law to PCM conversion
+ * Copyright (C) 2000 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ * 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.1 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.
+ */
+/**
+ * SECTION:element-alawdec
+ *
+ * This element decodes alaw audio. Alaw coding is also known as G.711.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "alaw-decode.h"
+
+extern GstStaticPadTemplate alaw_dec_src_factory;
+extern GstStaticPadTemplate alaw_dec_sink_factory;
+
+GST_DEBUG_CATEGORY_STATIC (alaw_dec_debug);
+#define GST_CAT_DEFAULT alaw_dec_debug
+
+static GstStateChangeReturn
+gst_alaw_dec_change_state (GstElement * element, GstStateChange transition);
+static GstFlowReturn gst_alaw_dec_chain (GstPad * pad, GstBuffer * buffer);
+
+GST_BOILERPLATE (GstALawDec, gst_alaw_dec, GstElement, GST_TYPE_ELEMENT);
+
+/* some day we might have defines in gstconfig.h that tell us about the
+ * desired cpu/memory/binary size trade-offs */
+#define GST_ALAW_DEC_USE_TABLE
+
+#ifdef GST_ALAW_DEC_USE_TABLE
+
+static const gint alaw_to_s16_table[256] = {
+  -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
+  -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
+  -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
+  -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
+  -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
+  -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
+  -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
+  -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
+  -344, -328, -376, -360, -280, -264, -312, -296,
+  -472, -456, -504, -488, -408, -392, -440, -424,
+  -88, -72, -120, -104, -24, -8, -56, -40,
+  -216, -200, -248, -232, -152, -136, -184, -168,
+  -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
+  -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
+  -688, -656, -752, -720, -560, -528, -624, -592,
+  -944, -912, -1008, -976, -816, -784, -880, -848,
+  5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
+  7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
+  2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
+  3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
+  22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+  30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
+  11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
+  15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
+  344, 328, 376, 360, 280, 264, 312, 296,
+  472, 456, 504, 488, 408, 392, 440, 424,
+  88, 72, 120, 104, 24, 8, 56, 40,
+  216, 200, 248, 232, 152, 136, 184, 168,
+  1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
+  1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
+  688, 656, 752, 720, 560, 528, 624, 592,
+  944, 912, 1008, 976, 816, 784, 880, 848
+};
+
+static inline gint
+alaw_to_s16 (guint8 a_val)
+{
+  return alaw_to_s16_table[a_val];
+}
+
+#else /* GST_ALAW_DEC_USE_TABLE */
+
+static inline gint
+alaw_to_s16 (guint8 a_val)
+{
+  gint t;
+  gint seg;
+
+  a_val ^= 0x55;
+  t = a_val & 0x7f;
+  if (t < 16)
+    t = (t << 4) + 8;
+  else {
+    seg = (t >> 4) & 0x07;
+    t = ((t & 0x0f) << 4) + 0x108;
+    t <<= seg - 1;
+  }
+  return ((a_val & 0x80) ? t : -t);
+}
+
+#endif /* GST_ALAW_DEC_USE_TABLE */
+
+static gboolean
+gst_alaw_dec_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstALawDec *alawdec;
+  GstStructure *structure;
+  int rate, channels;
+  gboolean ret;
+  GstCaps *outcaps;
+
+  alawdec = GST_ALAW_DEC (GST_PAD_PARENT (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  ret = gst_structure_get_int (structure, "rate", &rate);
+  ret &= gst_structure_get_int (structure, "channels", &channels);
+  if (!ret)
+    return FALSE;
+
+  outcaps = gst_caps_new_simple ("audio/x-raw-int",
+      "width", G_TYPE_INT, 16,
+      "depth", G_TYPE_INT, 16,
+      "endianness", G_TYPE_INT, G_BYTE_ORDER,
+      "signed", G_TYPE_BOOLEAN, TRUE,
+      "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
+
+  ret = gst_pad_set_caps (alawdec->srcpad, outcaps);
+  gst_caps_unref (outcaps);
+
+  if (ret) {
+    GST_DEBUG_OBJECT (alawdec, "rate=%d, channels=%d", rate, channels);
+    alawdec->rate = rate;
+    alawdec->channels = channels;
+  }
+  return ret;
+}
+
+static GstCaps *
+gst_alaw_dec_getcaps (GstPad * pad)
+{
+  GstALawDec *alawdec;
+  GstPad *otherpad;
+  GstCaps *othercaps, *result;
+  const GstCaps *templ;
+  gchar *name;
+  gint i;
+
+  alawdec = GST_ALAW_DEC (GST_PAD_PARENT (pad));
+
+  /* figure out the name of the caps we are going to return */
+  if (pad == alawdec->srcpad) {
+    name = "audio/x-raw-int";
+    otherpad = alawdec->sinkpad;
+  } else {
+    name = "audio/x-alaw";
+    otherpad = alawdec->srcpad;
+  }
+  /* get caps from the peer, this can return NULL when there is no peer */
+  othercaps = gst_pad_peer_get_caps (otherpad);
+
+  /* get the template caps to make sure we return something acceptable */
+  templ = gst_pad_get_pad_template_caps (pad);
+
+  if (othercaps) {
+    /* there was a peer */
+    othercaps = gst_caps_make_writable (othercaps);
+
+    /* go through the caps and remove the fields we don't want */
+    for (i = 0; i < gst_caps_get_size (othercaps); i++) {
+      GstStructure *structure;
+
+      structure = gst_caps_get_structure (othercaps, i);
+
+      /* adjust the name */
+      gst_structure_set_name (structure, name);
+
+      if (pad == alawdec->sinkpad) {
+        /* remove the fields we don't want */
+        gst_structure_remove_fields (structure, "width", "depth", "endianness",
+            "signed", NULL);
+      } else {
+        /* add fixed fields */
+        gst_structure_set (structure, "width", G_TYPE_INT, 16,
+            "depth", G_TYPE_INT, 16,
+            "endianness", G_TYPE_INT, G_BYTE_ORDER,
+            "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      }
+    }
+    /* filter against the allowed caps of the pad to return our result */
+    result = gst_caps_intersect (othercaps, templ);
+    gst_caps_unref (othercaps);
+  } else {
+    /* there was no peer, return the template caps */
+    result = gst_caps_copy (templ);
+  }
+
+  return result;
+}
+
+static void
+gst_alaw_dec_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&alaw_dec_src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&alaw_dec_sink_factory));
+
+  gst_element_class_set_details_simple (element_class, "A Law audio decoder",
+      "Codec/Decoder/Audio", "Convert 8bit A law to 16bit PCM",
+      "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+
+  GST_DEBUG_CATEGORY_INIT (alaw_dec_debug, "alawdec", 0, "A Law audio decoder");
+}
+
+static void
+gst_alaw_dec_class_init (GstALawDecClass * klass)
+{
+  GstElementClass *element_class = (GstElementClass *) klass;
+
+  element_class->change_state = GST_DEBUG_FUNCPTR (gst_alaw_dec_change_state);
+}
+
+static void
+gst_alaw_dec_init (GstALawDec * alawdec, GstALawDecClass * klass)
+{
+  alawdec->sinkpad =
+      gst_pad_new_from_static_template (&alaw_dec_sink_factory, "sink");
+  gst_pad_set_setcaps_function (alawdec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_dec_sink_setcaps));
+  gst_pad_set_getcaps_function (alawdec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_dec_getcaps));
+  gst_pad_set_chain_function (alawdec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_dec_chain));
+  gst_element_add_pad (GST_ELEMENT (alawdec), alawdec->sinkpad);
+
+  alawdec->srcpad =
+      gst_pad_new_from_static_template (&alaw_dec_src_factory, "src");
+  gst_pad_use_fixed_caps (alawdec->srcpad);
+  gst_pad_set_getcaps_function (alawdec->srcpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_dec_getcaps));
+  gst_element_add_pad (GST_ELEMENT (alawdec), alawdec->srcpad);
+}
+
+static GstFlowReturn
+gst_alaw_dec_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstALawDec *alawdec;
+  gint16 *linear_data;
+  guint8 *alaw_data;
+  guint alaw_size;
+  GstBuffer *outbuf;
+  gint i;
+  GstFlowReturn ret;
+
+  alawdec = GST_ALAW_DEC (GST_PAD_PARENT (pad));
+
+  if (G_UNLIKELY (alawdec->rate == 0))
+    goto not_negotiated;
+
+  GST_LOG_OBJECT (alawdec, "buffer with ts=%" GST_TIME_FORMAT,
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
+
+  alaw_data = GST_BUFFER_DATA (buffer);
+  alaw_size = GST_BUFFER_SIZE (buffer);
+
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (alawdec->srcpad,
+      GST_BUFFER_OFFSET_NONE, alaw_size * 2, GST_PAD_CAPS (alawdec->srcpad),
+      &outbuf);
+  if (ret != GST_FLOW_OK)
+    goto alloc_failed;
+
+  linear_data = (gint16 *) GST_BUFFER_DATA (outbuf);
+
+  /* copy discont flag */
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+
+  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
+  GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (alawdec->srcpad));
+
+  for (i = 0; i < alaw_size; i++) {
+    linear_data[i] = alaw_to_s16 (alaw_data[i]);
+  }
+  gst_buffer_unref (buffer);
+
+  ret = gst_pad_push (alawdec->srcpad, outbuf);
+
+  return ret;
+
+not_negotiated:
+  {
+    gst_buffer_unref (buffer);
+    GST_WARNING_OBJECT (alawdec, "no input format set: not-negotiated");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+alloc_failed:
+  {
+    gst_buffer_unref (buffer);
+    GST_DEBUG_OBJECT (alawdec, "pad alloc failed, flow: %s",
+        gst_flow_get_name (ret));
+    return ret;
+  }
+}
+
+static GstStateChangeReturn
+gst_alaw_dec_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstALawDec *dec = GST_ALAW_DEC (element);
+
+  switch (transition) {
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret != GST_STATE_CHANGE_SUCCESS)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      dec->rate = 0;
+      dec->channels = 0;
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/alaw-decode.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,62 @@
+/* GStreamer A-Law to PCM conversion
+ * Copyright (C) 2000 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ * 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_ALAW_DECODE_H__
+#define __GST_ALAW_DECODE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_ALAW_DEC \
+  (gst_alaw_dec_get_type())
+#define GST_ALAW_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALAW_DEC,GstALawDec))
+#define GST_ALAW_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALAW_DEC,GstALawDecClass))
+#define GST_IS_ALAW_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALAW_DEC))
+#define GST_IS_ALAW_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALAW_DEC))
+
+typedef struct _GstALawDec GstALawDec;
+typedef struct _GstALawDecClass GstALawDecClass;
+
+struct _GstALawDec {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+  gint rate;
+  gint channels;
+};
+
+struct _GstALawDecClass {
+  GstElementClass parent_class;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_alaw_dec_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_ALAW_DECODE_H__ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/alaw-encode.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,524 @@
+/* GStreamer PCM to A-Law conversion
+ * Copyright (C) 2000 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ * 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.1 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.
+ */
+/**
+ * SECTION:element-alawenc
+ *
+ * This element encode alaw audio. Alaw coding is also known as G.711.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "alaw-encode.h"
+
+GST_DEBUG_CATEGORY_STATIC (alaw_enc_debug);
+#define GST_CAT_DEFAULT alaw_enc_debug
+
+extern GstStaticPadTemplate alaw_enc_src_factory;
+extern GstStaticPadTemplate alaw_enc_sink_factory;
+
+static GstFlowReturn gst_alaw_enc_chain (GstPad * pad, GstBuffer * buffer);
+
+GST_BOILERPLATE (GstALawEnc, gst_alaw_enc, GstElement, GST_TYPE_ELEMENT);
+
+/* some day we might have defines in gstconfig.h that tell us about the
+ * desired cpu/memory/binary size trade-offs */
+#define GST_ALAW_ENC_USE_TABLE
+
+#ifdef GST_ALAW_ENC_USE_TABLE
+
+static const guint8 alaw_encode[2048 + 1] = {
+  0xd5, 0xd4, 0xd7, 0xd6, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde,
+  0xd9, 0xd8, 0xdb, 0xda, 0xc5, 0xc4, 0xc7, 0xc6, 0xc1, 0xc0, 0xc3, 0xc2,
+  0xcd, 0xcc, 0xcf, 0xce, 0xc9, 0xc8, 0xcb, 0xca, 0xf5, 0xf5, 0xf4, 0xf4,
+  0xf7, 0xf7, 0xf6, 0xf6, 0xf1, 0xf1, 0xf0, 0xf0, 0xf3, 0xf3, 0xf2, 0xf2,
+  0xfd, 0xfd, 0xfc, 0xfc, 0xff, 0xff, 0xfe, 0xfe, 0xf9, 0xf9, 0xf8, 0xf8,
+  0xfb, 0xfb, 0xfa, 0xfa, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4,
+  0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1,
+  0xe0, 0xe0, 0xe0, 0xe0, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2,
+  0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef,
+  0xee, 0xee, 0xee, 0xee, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8,
+  0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+  0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96,
+  0x96, 0x96, 0x96, 0x96, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93,
+  0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+  0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c,
+  0x9c, 0x9c, 0x9c, 0x9c, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
+  0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99,
+  0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+  0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a,
+  0x9a, 0x9a, 0x9a, 0x9a, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+  0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
+  0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+  0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+  0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+  0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81,
+  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+  0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
+  0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
+  0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
+  0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
+  0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f,
+  0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
+  0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
+  0x8e, 0x8e, 0x8e, 0x8e, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+  0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
+  0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+  0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
+  0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
+  0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5,
+  0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
+  0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
+  0xb5, 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
+  0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
+  0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
+  0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+  0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+  0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
+  0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
+  0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
+  0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
+  0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
+  0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3,
+  0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
+  0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
+  0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+  0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+  0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+  0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+  0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+  0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc,
+  0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+  0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+  0xbc, 0xbc, 0xbc, 0xbc, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+  0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+  0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9,
+  0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
+  0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
+  0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+  0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+  0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+  0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+  0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+  0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba,
+  0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+  0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+  0xba, 0xba, 0xba, 0xba, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+  0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+  0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+  0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+  0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+  0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
+  0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
+  0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
+  0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
+  0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
+  0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1,
+  0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+  0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+  0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+  0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+  0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+  0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
+  0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
+  0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
+  0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
+  0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
+  0xa0, 0xa0, 0xa0, 0xa0, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
+  0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
+  0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
+  0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
+  0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
+  0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
+  0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
+  0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
+  0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
+  0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
+  0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
+  0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
+  0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
+  0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
+  0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
+  0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf,
+  0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+  0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+  0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+  0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+  0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+  0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
+  0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
+  0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
+  0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
+  0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
+  0xae, 0xae, 0xae, 0xae, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
+  0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
+  0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
+  0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
+  0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
+  0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
+  0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+  0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+  0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+  0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+  0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+  0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a
+};
+
+static inline guint8
+s16_to_alaw (gint16 pcm_val)
+{
+  if (pcm_val >= 0)
+    return alaw_encode[pcm_val / 16];
+  else
+    return (0x7F & alaw_encode[pcm_val / -16]);
+}
+
+#else /* GST_ALAW_ENC_USE_TABLE */
+
+/*
+ * s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
+ *
+ * s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data.
+ *
+ *              Linear Input Code       Compressed Code
+ *      ------------------------        ---------------
+ *      0000000wxyza                    000wxyz
+ *      0000001wxyza                    001wxyz
+ *      000001wxyzab                    010wxyz
+ *      00001wxyzabc                    011wxyz
+ *      0001wxyzabcd                    100wxyz
+ *      001wxyzabcde                    101wxyz
+ *      01wxyzabcdef                    110wxyz
+ *      1wxyzabcdefg                    111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+
+static inline gint
+val_seg (gint val)
+{
+  gint r = 1;
+
+  val >>= 8;
+  if (val & 0xf0) {
+    val >>= 4;
+    r += 4;
+  }
+  if (val & 0x0c) {
+    val >>= 2;
+    r += 2;
+  }
+  if (val & 0x02)
+    r += 1;
+  return r;
+}
+
+static inline guint8
+s16_to_alaw (gint pcm_val)
+{
+  gint seg;
+  guint8 mask;
+  guint8 aval;
+
+  if (pcm_val >= 0) {
+    mask = 0xD5;
+  } else {
+    mask = 0x55;
+    pcm_val = -pcm_val;
+    if (pcm_val > 0x7fff)
+      pcm_val = 0x7fff;
+  }
+
+  if (pcm_val < 256)
+    aval = pcm_val >> 4;
+  else {
+    /* Convert the scaled magnitude to segment number. */
+    seg = val_seg (pcm_val);
+    aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
+  }
+  return aval ^ mask;
+}
+
+#endif /* GST_ALAW_ENC_USE_TABLE */
+
+static GstCaps *
+gst_alaw_enc_getcaps (GstPad * pad)
+{
+  GstALawEnc *alawenc;
+  GstPad *otherpad;
+  GstCaps *othercaps, *result;
+  const GstCaps *templ;
+  gchar *name;
+  gint i;
+
+  alawenc = GST_ALAW_ENC (GST_PAD_PARENT (pad));
+
+  /* figure out the name of the caps we are going to return */
+  if (pad == alawenc->srcpad) {
+    name = "audio/x-alaw";
+    otherpad = alawenc->sinkpad;
+  } else {
+    name = "audio/x-raw-int";
+    otherpad = alawenc->srcpad;
+  }
+  /* get caps from the peer, this can return NULL when there is no peer */
+  othercaps = gst_pad_peer_get_caps (otherpad);
+
+  /* get the template caps to make sure we return something acceptable */
+  templ = gst_pad_get_pad_template_caps (pad);
+
+  if (othercaps) {
+    /* there was a peer */
+    othercaps = gst_caps_make_writable (othercaps);
+
+    /* go through the caps and remove the fields we don't want */
+    for (i = 0; i < gst_caps_get_size (othercaps); i++) {
+      GstStructure *structure;
+
+      structure = gst_caps_get_structure (othercaps, i);
+
+      /* adjust the name */
+      gst_structure_set_name (structure, name);
+
+      if (pad == alawenc->srcpad) {
+        /* remove the fields we don't want */
+        gst_structure_remove_fields (structure, "width", "depth", "endianness",
+            "signed", NULL);
+      } else {
+        /* add fixed fields */
+        gst_structure_set (structure, "width", G_TYPE_INT, 16,
+            "depth", G_TYPE_INT, 16,
+            "endianness", G_TYPE_INT, G_BYTE_ORDER,
+            "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      }
+    }
+    /* filter against the allowed caps of the pad to return our result */
+    result = gst_caps_intersect (othercaps, templ);
+    gst_caps_unref (othercaps);
+  } else {
+    /* there was no peer, return the template caps */
+    result = gst_caps_copy (templ);
+  }
+
+  return result;
+}
+
+static gboolean
+gst_alaw_enc_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstALawEnc *alawenc;
+  GstPad *otherpad;
+  GstStructure *structure;
+  gboolean ret;
+  GstCaps *base_caps;
+
+  alawenc = GST_ALAW_ENC (GST_PAD_PARENT (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+  gst_structure_get_int (structure, "channels", &alawenc->channels);
+  gst_structure_get_int (structure, "rate", &alawenc->rate);
+
+  if (pad == alawenc->sinkpad) {
+    otherpad = alawenc->srcpad;
+  } else {
+    otherpad = alawenc->sinkpad;
+  }
+
+  base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
+  structure = gst_caps_get_structure (base_caps, 0);
+  gst_structure_set (structure, "rate", G_TYPE_INT, alawenc->rate, NULL);
+  gst_structure_set (structure, "channels", G_TYPE_INT, alawenc->channels,
+      NULL);
+
+  GST_DEBUG_OBJECT (alawenc, "rate=%d, channels=%d", alawenc->rate,
+      alawenc->channels);
+
+  ret = gst_pad_set_caps (otherpad, base_caps);
+
+  gst_caps_unref (base_caps);
+
+  return ret;
+}
+
+static void
+gst_alaw_enc_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&alaw_enc_src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&alaw_enc_sink_factory));
+
+  gst_element_class_set_details_simple (element_class,
+      "A Law audio encoder", "Codec/Encoder/Audio",
+      "Convert 16bit PCM to 8bit A law",
+      "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+
+  GST_DEBUG_CATEGORY_INIT (alaw_enc_debug, "alawenc", 0, "A Law audio encoder");
+}
+
+static void
+gst_alaw_enc_class_init (GstALawEncClass * klass)
+{
+  /* nothing to do here for now */
+}
+
+static void
+gst_alaw_enc_init (GstALawEnc * alawenc, GstALawEncClass * klass)
+{
+  alawenc->sinkpad =
+      gst_pad_new_from_static_template (&alaw_enc_sink_factory, "sink");
+  gst_pad_set_setcaps_function (alawenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_enc_setcaps));
+  gst_pad_set_getcaps_function (alawenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_enc_getcaps));
+  gst_pad_set_chain_function (alawenc->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_enc_chain));
+  gst_element_add_pad (GST_ELEMENT (alawenc), alawenc->sinkpad);
+
+  alawenc->srcpad =
+      gst_pad_new_from_static_template (&alaw_enc_src_factory, "src");
+  gst_pad_set_setcaps_function (alawenc->srcpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_enc_setcaps));
+  gst_pad_set_getcaps_function (alawenc->srcpad,
+      GST_DEBUG_FUNCPTR (gst_alaw_enc_getcaps));
+  gst_pad_use_fixed_caps (alawenc->srcpad);
+  gst_element_add_pad (GST_ELEMENT (alawenc), alawenc->srcpad);
+
+  /* init rest */
+  alawenc->channels = 0;
+  alawenc->rate = 0;
+}
+
+static GstFlowReturn
+gst_alaw_enc_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstALawEnc *alawenc;
+  gint16 *linear_data;
+  guint linear_size;
+  guint8 *alaw_data;
+  guint alaw_size;
+  GstBuffer *outbuf;
+  gint i;
+  GstFlowReturn ret;
+  GstClockTime timestamp, duration;
+
+  alawenc = GST_ALAW_ENC (GST_PAD_PARENT (pad));
+
+  if (G_UNLIKELY (alawenc->rate == 0 || alawenc->channels == 0))
+    goto not_negotiated;
+
+  linear_data = (gint16 *) GST_BUFFER_DATA (buffer);
+  linear_size = GST_BUFFER_SIZE (buffer);
+
+  alaw_size = linear_size / 2;
+
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  duration = GST_BUFFER_DURATION (buffer);
+
+  GST_LOG_OBJECT (alawenc, "buffer with ts=%" GST_TIME_FORMAT,
+      GST_TIME_ARGS (timestamp));
+
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (alawenc->srcpad,
+      GST_BUFFER_OFFSET_NONE, alaw_size, GST_PAD_CAPS (alawenc->srcpad),
+      &outbuf);
+  if (ret != GST_FLOW_OK)
+    goto done;
+
+  if (duration == GST_CLOCK_TIME_NONE) {
+    duration = gst_util_uint64_scale_int (alaw_size,
+        GST_SECOND, alawenc->rate * alawenc->channels);
+  }
+
+  if (GST_BUFFER_SIZE (outbuf) < alaw_size) {
+    /* pad-alloc can return a smaller buffer */
+    gst_buffer_unref (outbuf);
+    outbuf = gst_buffer_new_and_alloc (alaw_size);
+  }
+
+  alaw_data = (guint8 *) GST_BUFFER_DATA (outbuf);
+
+  /* copy discont flag */
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+
+  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+  GST_BUFFER_DURATION (outbuf) = duration;
+
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (alawenc->srcpad));
+
+  for (i = 0; i < alaw_size; i++) {
+    alaw_data[i] = s16_to_alaw (linear_data[i]);
+  }
+
+  ret = gst_pad_push (alawenc->srcpad, outbuf);
+
+done:
+
+  gst_buffer_unref (buffer);
+
+  return ret;
+
+not_negotiated:
+  {
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    goto done;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/alaw-encode.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,62 @@
+/* GStreamer PCM to A-Law conversion
+ * Copyright (C) 2000 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ * 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_ALAW_ENCODE_H__
+#define __GST_ALAW_ENCODE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_ALAW_ENC \
+  (gst_alaw_enc_get_type())
+#define GST_ALAW_ENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALAW_ENC,GstALawEnc))
+#define GST_ALAW_ENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALAW_ENC,GstALawEncClass))
+#define GST_IS_ALAW_ENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALAW_ENC))
+#define GST_IS_ALAW_ENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALAW_ENC))
+
+typedef struct _GstALawEnc GstALawEnc;
+typedef struct _GstALawEncClass GstALawEncClass;
+
+struct _GstALawEnc {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  gint channels;
+  gint rate;
+};
+
+struct _GstALawEncClass {
+  GstElementClass parent_class;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_alaw_enc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_ALAW_ENCODE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/alaw.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,83 @@
+/* GStreamer PCM/A-Law conversions
+ *
+ * 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.1 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "alaw-encode.h"
+#include "alaw-decode.h"
+
+GstStaticPadTemplate alaw_dec_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "rate = (int) [ 8000, 192000 ], "
+        "channels = (int) [ 1, 2 ], "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) True")
+    );
+
+GstStaticPadTemplate alaw_dec_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-alaw, "
+        "rate = [ 8000 , 192000 ], " "channels = [ 1 , 2 ]")
+    );
+
+GstStaticPadTemplate alaw_enc_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "rate = (int) [ 8000, 192000 ], "
+        "channels = (int) [ 1, 2 ], "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) True")
+    );
+
+GstStaticPadTemplate alaw_enc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-alaw, "
+        "rate = [ 8000 , 192000 ], " "channels = [ 1 , 2 ]")
+    );
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "alawenc",
+          GST_RANK_NONE, GST_TYPE_ALAW_ENC) ||
+      !gst_element_register (plugin, "alawdec",
+          GST_RANK_PRIMARY, GST_TYPE_ALAW_DEC))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* FIXME 0.11: merge alaw and mulaw into one plugin? */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "alaw",
+    "ALaw audio conversion routines",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+    
+
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+	return &gst_plugin_desc;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw-conversion.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,116 @@
+/*
+ * This routine converts from linear to ulaw
+ * 29 September 1989
+ *
+ * Craig Reese: IDA/Supercomputing Research Center
+ * Joe Campbell: Department of Defense
+ *
+ * References:
+ * 1) CCITT Recommendation G.711  (very difficult to follow)
+ * 2) "A New Digital Technique for Implementation of Any 
+ *     Continuous PCM Companding Law," Villeret, Michel,
+ *     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
+ *     1973, pg. 11.12-11.17
+ * 3) MIL-STD-188-113,"Interoperability and Performance Standards
+ *     for Analog-to_Digital Conversion Techniques,"
+ *     17 February 1987
+ *
+ * Input: Signed 16 bit linear sample
+ * Output: 8 bit ulaw sample
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#undef ZEROTRAP                 /* turn on the trap as per the MIL-STD */
+#define BIAS 0x84               /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+
+void
+mulaw_encode (gint16 * in, guint8 * out, gint numsamples)
+{
+  static gint16 exp_lut[256] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+  };
+  gint16 sign, exponent, mantissa, i;
+  gint16 sample;
+  guint8 ulawbyte;
+
+  for (i = 0; i < numsamples; i++) {
+    sample = in[i];
+      /** get the sample into sign-magnitude **/
+    sign = (sample >> 8) & 0x80;        /* set aside the sign */
+    if (sign != 0) {
+      sample = -sample;         /* get magnitude */
+    }
+    /* sample can be zero because we can overflow in the inversion,
+     * checking against the unsigned version solves this */
+    if (((guint16) sample) > CLIP)
+      sample = CLIP;            /* clip the magnitude */
+
+      /** convert from 16 bit linear to ulaw **/
+    sample = sample + BIAS;
+    exponent = exp_lut[(sample >> 7) & 0xFF];
+    mantissa = (sample >> (exponent + 3)) & 0x0F;
+    ulawbyte = ~(sign | (exponent << 4) | mantissa);
+#ifdef ZEROTRAP
+    if (ulawbyte == 0)
+      ulawbyte = 0x02;          /* optional CCITT trap */
+#endif
+    out[i] = ulawbyte;
+  }
+}
+
+/*
+ * This routine converts from ulaw to 16 bit linear
+ * 29 September 1989
+ *
+ * Craig Reese: IDA/Supercomputing Research Center
+ *
+ * References:
+ * 1) CCITT Recommendation G.711  (very difficult to follow)
+ * 2) MIL-STD-188-113,"Interoperability and Performance Standards
+ *     for Analog-to_Digital Conversion Techniques,"
+ *     17 February 1987
+ *
+ * Input: 8 bit ulaw sample
+ * Output: signed 16 bit linear sample
+ */
+
+void
+mulaw_decode (guint8 * in, gint16 * out, gint numsamples)
+{
+  static gint16 exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
+  gint16 sign, exponent, mantissa;
+  guint8 ulawbyte;
+  gint16 linear, i;
+
+  for (i = 0; i < numsamples; i++) {
+    ulawbyte = in[i];
+    ulawbyte = ~ulawbyte;
+    sign = (ulawbyte & 0x80);
+    exponent = (ulawbyte >> 4) & 0x07;
+    mantissa = ulawbyte & 0x0F;
+    linear = exp_lut[exponent] + (mantissa << (exponent + 3));
+    if (sign != 0)
+      linear = -linear;
+    out[i] = linear;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw-conversion.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,12 @@
+#ifndef _GST_ULAW_CONVERSION_H
+#define _GST_ULAW_CONVERSION_H
+
+#include <glib.h>
+
+void
+mulaw_encode(gint16* in, guint8* out, gint numsamples);
+void
+mulaw_decode(guint8* in,gint16* out,gint numsamples);
+
+#endif /* _GST_ULAW_CONVERSION_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw-decode.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,309 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+/**
+ * SECTION:element-mulawdec
+ *
+ * This element decodes mulaw audio. Mulaw coding is also known as G.711.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gst/gst.h>
+#include "mulaw-decode.h"
+#include "mulaw-conversion.h"
+
+extern GstStaticPadTemplate mulaw_dec_src_factory;
+extern GstStaticPadTemplate mulaw_dec_sink_factory;
+
+/* Stereo signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0
+};
+
+static void gst_mulawdec_class_init (GstMuLawDecClass * klass);
+static void gst_mulawdec_base_init (GstMuLawDecClass * klass);
+static void gst_mulawdec_init (GstMuLawDec * mulawdec);
+static GstStateChangeReturn
+gst_mulawdec_change_state (GstElement * element, GstStateChange transition);
+
+static GstFlowReturn gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer);
+
+static GstElementClass *parent_class = NULL;
+
+static gboolean
+mulawdec_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstMuLawDec *mulawdec;
+  GstStructure *structure;
+  int rate, channels;
+  gboolean ret;
+  GstCaps *outcaps;
+
+  mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+  ret = gst_structure_get_int (structure, "rate", &rate);
+  ret = ret && gst_structure_get_int (structure, "channels", &channels);
+  if (!ret)
+    return FALSE;
+
+  outcaps = gst_caps_new_simple ("audio/x-raw-int",
+      "width", G_TYPE_INT, 16,
+      "depth", G_TYPE_INT, 16,
+      "endianness", G_TYPE_INT, G_BYTE_ORDER,
+      "signed", G_TYPE_BOOLEAN, TRUE,
+      "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
+  ret = gst_pad_set_caps (mulawdec->srcpad, outcaps);
+  gst_caps_unref (outcaps);
+
+  if (ret) {
+    GST_DEBUG_OBJECT (mulawdec, "rate=%d, channels=%d", rate, channels);
+    mulawdec->rate = rate;
+    mulawdec->channels = channels;
+  }
+  return ret;
+}
+
+static GstCaps *
+mulawdec_getcaps (GstPad * pad)
+{
+  GstMuLawDec *mulawdec;
+  GstPad *otherpad;
+  GstCaps *othercaps, *result;
+  const GstCaps *templ;
+  gchar *name;
+  gint i;
+
+  mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
+
+  /* figure out the name of the caps we are going to return */
+  if (pad == mulawdec->srcpad) {
+    name = "audio/x-raw-int";
+    otherpad = mulawdec->sinkpad;
+  } else {
+    name = "audio/x-mulaw";
+    otherpad = mulawdec->srcpad;
+  }
+  /* get caps from the peer, this can return NULL when there is no peer */
+  othercaps = gst_pad_peer_get_caps (otherpad);
+
+  /* get the template caps to make sure we return something acceptable */
+  templ = gst_pad_get_pad_template_caps (pad);
+
+  if (othercaps) {
+    /* there was a peer */
+    othercaps = gst_caps_make_writable (othercaps);
+
+    /* go through the caps and remove the fields we don't want */
+    for (i = 0; i < gst_caps_get_size (othercaps); i++) {
+      GstStructure *structure;
+
+      structure = gst_caps_get_structure (othercaps, i);
+
+      /* adjust the name */
+      gst_structure_set_name (structure, name);
+
+      if (pad == mulawdec->sinkpad) {
+        /* remove the fields we don't want */
+        gst_structure_remove_fields (structure, "width", "depth", "endianness",
+            "signed", NULL);
+      } else {
+        /* add fixed fields */
+        gst_structure_set (structure, "width", G_TYPE_INT, 16,
+            "depth", G_TYPE_INT, 16,
+            "endianness", G_TYPE_INT, G_BYTE_ORDER,
+            "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      }
+    }
+    /* filter against the allowed caps of the pad to return our result */
+    result = gst_caps_intersect (othercaps, templ);
+    gst_caps_unref (othercaps);
+  } else {
+    /* there was no peer, return the template caps */
+    result = gst_caps_copy (templ);
+  }
+  return result;
+}
+
+GType
+gst_mulawdec_get_type (void)
+{
+  static GType mulawdec_type = 0;
+
+  if (!mulawdec_type) {
+    static const GTypeInfo mulawdec_info = {
+      sizeof (GstMuLawDecClass),
+      (GBaseInitFunc) gst_mulawdec_base_init,
+      NULL,
+      (GClassInitFunc) gst_mulawdec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstMuLawDec),
+      0,
+      (GInstanceInitFunc) gst_mulawdec_init,
+    };
+
+    mulawdec_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawDec", &mulawdec_info,
+        0);
+  }
+  return mulawdec_type;
+}
+
+static void
+gst_mulawdec_base_init (GstMuLawDecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  const GstElementDetails mulawdec_details =
+      GST_ELEMENT_DETAILS ("Mu Law audio decoder",
+      "Codec/Decoder/Audio",
+      "Convert 8bit mu law to 16bit PCM",
+      "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mulaw_dec_src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mulaw_dec_sink_factory));
+  gst_element_class_set_details (element_class, &mulawdec_details);
+}
+
+static void
+gst_mulawdec_class_init (GstMuLawDecClass * klass)
+{
+  GstElementClass *element_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  element_class->change_state = GST_DEBUG_FUNCPTR (gst_mulawdec_change_state);
+}
+
+static void
+gst_mulawdec_init (GstMuLawDec * mulawdec)
+{
+  mulawdec->sinkpad =
+      gst_pad_new_from_static_template (&mulaw_dec_sink_factory, "sink");
+  gst_pad_set_setcaps_function (mulawdec->sinkpad, mulawdec_sink_setcaps);
+  gst_pad_set_getcaps_function (mulawdec->sinkpad, mulawdec_getcaps);
+  gst_pad_set_chain_function (mulawdec->sinkpad, gst_mulawdec_chain);
+  gst_element_add_pad (GST_ELEMENT (mulawdec), mulawdec->sinkpad);
+
+  mulawdec->srcpad =
+      gst_pad_new_from_static_template (&mulaw_dec_src_factory, "src");
+  gst_pad_use_fixed_caps (mulawdec->srcpad);
+  gst_pad_set_getcaps_function (mulawdec->srcpad, mulawdec_getcaps);
+  gst_element_add_pad (GST_ELEMENT (mulawdec), mulawdec->srcpad);
+}
+
+static GstFlowReturn
+gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstMuLawDec *mulawdec;
+  gint16 *linear_data;
+  guint8 *mulaw_data;
+  guint mulaw_size;
+  GstBuffer *outbuf;
+  GstFlowReturn ret;
+
+  mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
+
+  if (G_UNLIKELY (mulawdec->rate == 0))
+    goto not_negotiated;
+
+  mulaw_data = (guint8 *) GST_BUFFER_DATA (buffer);
+  mulaw_size = GST_BUFFER_SIZE (buffer);
+
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (mulawdec->srcpad,
+      GST_BUFFER_OFFSET_NONE, mulaw_size * 2, GST_PAD_CAPS (mulawdec->srcpad),
+      &outbuf);
+  if (ret != GST_FLOW_OK)
+    goto alloc_failed;
+
+  linear_data = (gint16 *) GST_BUFFER_DATA (outbuf);
+
+  /* copy discont flag */
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+
+  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
+  if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
+    GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (GST_SECOND,
+        mulaw_size * 2, 2 * mulawdec->rate * mulawdec->channels);
+  else
+    GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawdec->srcpad));
+
+  mulaw_decode (mulaw_data, linear_data, mulaw_size);
+
+  gst_buffer_unref (buffer);
+
+  ret = gst_pad_push (mulawdec->srcpad, outbuf);
+
+  return ret;
+
+  /* ERRORS */
+not_negotiated:
+  {
+    GST_WARNING_OBJECT (mulawdec, "no input format set: not-negotiated");
+    gst_buffer_unref (buffer);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+alloc_failed:
+  {
+    GST_DEBUG_OBJECT (mulawdec, "pad alloc failed, flow: %s",
+        gst_flow_get_name (ret));
+    gst_buffer_unref (buffer);
+    return ret;
+  }
+}
+
+static GstStateChangeReturn
+gst_mulawdec_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstMuLawDec *dec = GST_MULAWDEC (element);
+
+  switch (transition) {
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret != GST_STATE_CHANGE_SUCCESS)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      dec->rate = 0;
+      dec->channels = 0;
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw-decode.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,58 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_MULAWDECODE_H__
+#define __GST_MULAWDECODE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MULAWDEC \
+  (gst_mulawdec_get_type())
+#define GST_MULAWDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULAWDEC,GstMuLawDec))
+#define GST_MULAWDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULAWDEC,GstMuLawDecClass))
+#define GST_IS_MULAWDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULAWDEC))
+#define GST_IS_MULAWDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULAWDEC))
+
+typedef struct _GstMuLawDec GstMuLawDec;
+typedef struct _GstMuLawDecClass GstMuLawDecClass;
+
+struct _GstMuLawDec {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  gint rate;
+  gint channels;
+};
+
+struct _GstMuLawDecClass {
+  GstElementClass parent_class;
+};
+
+GType gst_mulawdec_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_STEREO_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw-encode.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,299 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+/**
+ * SECTION:element-mulawenc
+ *
+ * This element encode mulaw audio. Mulaw coding is also known as G.711.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gst/gst.h>
+#include "mulaw-encode.h"
+#include "mulaw-conversion.h"
+
+extern GstStaticPadTemplate mulaw_enc_src_factory;
+extern GstStaticPadTemplate mulaw_enc_sink_factory;
+
+/* Stereo signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0
+};
+
+static void gst_mulawenc_class_init (GstMuLawEncClass * klass);
+static void gst_mulawenc_base_init (GstMuLawEncClass * klass);
+static void gst_mulawenc_init (GstMuLawEnc * mulawenc);
+
+static GstFlowReturn gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer);
+
+static GstElementClass *parent_class = NULL;
+
+/*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
+
+static GstCaps *
+mulawenc_getcaps (GstPad * pad)
+{
+  GstMuLawEnc *mulawenc;
+  GstPad *otherpad;
+  GstCaps *othercaps, *result;
+  const GstCaps *templ;
+  gchar *name;
+  gint i;
+
+  mulawenc = GST_MULAWENC (GST_PAD_PARENT (pad));
+
+  /* figure out the name of the caps we are going to return */
+  if (pad == mulawenc->srcpad) {
+    name = "audio/x-mulaw";
+    otherpad = mulawenc->sinkpad;
+  } else {
+    name = "audio/x-raw-int";
+    otherpad = mulawenc->srcpad;
+  }
+  /* get caps from the peer, this can return NULL when there is no peer */
+  othercaps = gst_pad_peer_get_caps (otherpad);
+
+  /* get the template caps to make sure we return something acceptable */
+  templ = gst_pad_get_pad_template_caps (pad);
+
+  if (othercaps) {
+    /* there was a peer */
+    othercaps = gst_caps_make_writable (othercaps);
+
+    /* go through the caps and remove the fields we don't want */
+    for (i = 0; i < gst_caps_get_size (othercaps); i++) {
+      GstStructure *structure;
+
+      structure = gst_caps_get_structure (othercaps, i);
+
+      /* adjust the name */
+      gst_structure_set_name (structure, name);
+
+      if (pad == mulawenc->srcpad) {
+        /* remove the fields we don't want */
+        gst_structure_remove_fields (structure, "width", "depth", "endianness",
+            "signed", NULL);
+      } else {
+        /* add fixed fields */
+        gst_structure_set (structure, "width", G_TYPE_INT, 16,
+            "depth", G_TYPE_INT, 16,
+            "endianness", G_TYPE_INT, G_BYTE_ORDER,
+            "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      }
+    }
+    /* filter against the allowed caps of the pad to return our result */
+    result = gst_caps_intersect (othercaps, templ);
+    gst_caps_unref (othercaps);
+  } else {
+    /* there was no peer, return the template caps */
+    result = gst_caps_copy (templ);
+  }
+  return result;
+}
+
+static gboolean
+mulawenc_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstMuLawEnc *mulawenc;
+  GstPad *otherpad;
+  GstStructure *structure;
+  GstCaps *base_caps;
+
+  mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+  gst_structure_get_int (structure, "channels", &mulawenc->channels);
+  gst_structure_get_int (structure, "rate", &mulawenc->rate);
+
+  if (pad == mulawenc->sinkpad) {
+    otherpad = mulawenc->srcpad;
+  } else {
+    otherpad = mulawenc->sinkpad;
+  }
+  base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
+
+  structure = gst_caps_get_structure (base_caps, 0);
+  gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL);
+  gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels,
+      NULL);
+
+  gst_pad_set_caps (otherpad, base_caps);
+
+  gst_object_unref (mulawenc);
+  gst_caps_unref (base_caps);
+
+  return TRUE;
+}
+
+GType
+gst_mulawenc_get_type (void)
+{
+  static GType mulawenc_type = 0;
+
+  if (!mulawenc_type) {
+    static const GTypeInfo mulawenc_info = {
+      sizeof (GstMuLawEncClass),
+      (GBaseInitFunc) gst_mulawenc_base_init,
+      NULL,
+      (GClassInitFunc) gst_mulawenc_class_init,
+      NULL,
+      NULL,
+      sizeof (GstMuLawEnc),
+      0,
+      (GInstanceInitFunc) gst_mulawenc_init,
+    };
+
+    mulawenc_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawEnc", &mulawenc_info,
+        0);
+  }
+  return mulawenc_type;
+}
+
+static void
+gst_mulawenc_base_init (GstMuLawEncClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  const GstElementDetails mulawenc_details =
+      GST_ELEMENT_DETAILS ("Mu Law audio encoder",
+      "Codec/Encoder/Audio",
+      "Convert 16bit PCM to 8bit mu law",
+      "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mulaw_enc_src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mulaw_enc_sink_factory));
+  gst_element_class_set_details (element_class, &mulawenc_details);
+}
+
+static void
+gst_mulawenc_class_init (GstMuLawEncClass * klass)
+{
+  parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+gst_mulawenc_init (GstMuLawEnc * mulawenc)
+{
+  mulawenc->sinkpad =
+      gst_pad_new_from_static_template (&mulaw_enc_sink_factory, "sink");
+  gst_pad_set_setcaps_function (mulawenc->sinkpad, mulawenc_setcaps);
+  gst_pad_set_getcaps_function (mulawenc->sinkpad, mulawenc_getcaps);
+  gst_pad_set_chain_function (mulawenc->sinkpad, gst_mulawenc_chain);
+  gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->sinkpad);
+
+  mulawenc->srcpad =
+      gst_pad_new_from_static_template (&mulaw_enc_src_factory, "src");
+  gst_pad_set_setcaps_function (mulawenc->srcpad, mulawenc_setcaps);
+  gst_pad_set_getcaps_function (mulawenc->srcpad, mulawenc_getcaps);
+  gst_pad_use_fixed_caps (mulawenc->srcpad);
+  gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->srcpad);
+
+  /* init rest */
+  mulawenc->channels = 0;
+  mulawenc->rate = 0;
+}
+
+static GstFlowReturn
+gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstMuLawEnc *mulawenc;
+  gint16 *linear_data;
+  guint linear_size;
+  guint8 *mulaw_data;
+  guint mulaw_size;
+  GstBuffer *outbuf;
+  GstFlowReturn ret;
+  GstClockTime timestamp, duration;
+
+  mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
+
+  if (!mulawenc->rate || !mulawenc->channels)
+    goto not_negotiated;
+
+  linear_data = (gint16 *) GST_BUFFER_DATA (buffer);
+  linear_size = GST_BUFFER_SIZE (buffer);
+
+  mulaw_size = linear_size / 2;
+
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  duration = GST_BUFFER_DURATION (buffer);
+
+  ret = gst_pad_alloc_buffer_and_set_caps (mulawenc->srcpad,
+      GST_BUFFER_OFFSET_NONE, mulaw_size, GST_PAD_CAPS (mulawenc->srcpad),
+      &outbuf);
+  if (ret != GST_FLOW_OK)
+    goto alloc_failed;
+
+  if (duration == -1) {
+    duration = gst_util_uint64_scale_int (mulaw_size,
+        GST_SECOND, mulawenc->rate * mulawenc->channels);
+  }
+
+  if (GST_BUFFER_SIZE (outbuf) < mulaw_size) {
+    /* pad-alloc can suggest a smaller size */
+    gst_buffer_unref (outbuf);
+    outbuf = gst_buffer_new_and_alloc (mulaw_size);
+  }
+
+  mulaw_data = (guint8 *) GST_BUFFER_DATA (outbuf);
+
+  /* copy discont flag */
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+
+  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+  GST_BUFFER_DURATION (outbuf) = duration;
+
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawenc->srcpad));
+
+  mulaw_encode (linear_data, mulaw_data, mulaw_size);
+
+  gst_buffer_unref (buffer);
+
+  ret = gst_pad_push (mulawenc->srcpad, outbuf);
+
+done:
+  gst_object_unref (mulawenc);
+
+  return ret;
+
+not_negotiated:
+  {
+    GST_DEBUG_OBJECT (mulawenc, "no format negotiated");
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    gst_buffer_unref (buffer);
+    goto done;
+  }
+alloc_failed:
+  {
+    GST_DEBUG_OBJECT (mulawenc, "pad alloc failed");
+    gst_buffer_unref (buffer);
+    goto done;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw-encode.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,59 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_MULAWENCODE_H__
+#define __GST_MULAWENCODE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MULAWENC \
+  (gst_mulawenc_get_type())
+#define GST_MULAWENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULAWENC,GstMuLawEnc))
+#define GST_MULAWENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULAWENC,GstMuLawEncClass))
+#define GST_IS_MULAWENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULAWENC))
+#define GST_IS_MULAWENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULAWENC))
+
+typedef struct _GstMuLawEnc GstMuLawEnc;
+typedef struct _GstMuLawEncClass GstMuLawEncClass;
+
+struct _GstMuLawEnc {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  gint channels;
+  gint rate;
+};
+
+struct _GstMuLawEncClass {
+  GstElementClass parent_class;
+};
+
+GType gst_mulawenc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_STEREO_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/law/mulaw.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,81 @@
+/* GStreamer PCM/A-Law conversions
+ *
+ * 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.1 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "mulaw-encode.h"
+#include "mulaw-decode.h"
+
+GstStaticPadTemplate mulaw_dec_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "rate = (int) [ 8000, 192000 ], "
+        "channels = (int) [ 1, 2 ], "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) True")
+    );
+
+GstStaticPadTemplate mulaw_dec_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-mulaw, "
+        "rate = [ 8000 , 192000 ], " "channels = [ 1 , 2 ]")
+    );
+
+GstStaticPadTemplate mulaw_enc_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "rate = (int) [ 8000, 192000 ], "
+        "channels = (int) [ 1, 2 ], "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) True")
+    );
+
+GstStaticPadTemplate mulaw_enc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-mulaw, "
+        "rate = [ 8000 , 192000 ], " "channels = [ 1 , 2 ]")
+    );
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "mulawenc",
+          GST_RANK_NONE, GST_TYPE_MULAWENC) ||
+      !gst_element_register (plugin, "mulawdec",
+          GST_RANK_PRIMARY, GST_TYPE_MULAWDEC))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "mulaw",
+    "MuLaw audio conversion routines",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+	return &gst_plugin_desc;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/gstrtpxqtdepay.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,704 @@
+/* GStreamer
+ * Copyright (C) <2006> Wim Taymans <wim@fluendo.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.
+ */
+
+/*
+ * based on http://developer.apple.com/quicktime/icefloe/dispatch026.html
+ */
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <gst/rtp/gstrtpbuffer.h>
+
+#include <string.h>
+#include "gstrtpxqtdepay.h"
+
+#define MAKE_TLV(a,b)  (((a)<<8)|(b))
+
+#define TLV_sd	MAKE_TLV ('s','d')
+#define TLV_qt	MAKE_TLV ('q','t')
+#define TLV_ti	MAKE_TLV ('t','i')
+#define TLV_ly	MAKE_TLV ('l','y')
+#define TLV_vo	MAKE_TLV ('v','o')
+#define TLV_mx	MAKE_TLV ('m','x')
+#define TLV_tr	MAKE_TLV ('t','r')
+#define TLV_tw	MAKE_TLV ('t','w')
+#define TLV_th	MAKE_TLV ('t','h')
+#define TLV_la	MAKE_TLV ('l','a')
+#define TLV_rt	MAKE_TLV ('r','t')
+#define TLV_gm	MAKE_TLV ('g','m')
+#define TLV_oc	MAKE_TLV ('o','c')
+#define TLV_cr	MAKE_TLV ('c','r')
+#define TLV_du	MAKE_TLV ('d','u')
+#define TLV_po	MAKE_TLV ('p','o')
+
+#define QT_UINT32(a)  (GST_READ_UINT32_BE(a))
+#define QT_UINT24(a)  (GST_READ_UINT32_BE(a) >> 8)
+#define QT_UINT16(a)  (GST_READ_UINT16_BE(a))
+#define QT_UINT8(a)   (GST_READ_UINT8(a))
+#define QT_FP32(a)    ((GST_READ_UINT32_BE(a))/65536.0)
+#define QT_FP16(a)    ((GST_READ_UINT16_BE(a))/256.0)
+#define QT_FOURCC(a)  (GST_READ_UINT32_LE(a))
+#define QT_UINT64(a)  ((((guint64)QT_UINT32(a))<<32)|QT_UINT32(((guint8 *)a)+4))
+
+#define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
+#define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
+
+GST_DEBUG_CATEGORY_STATIC (rtpxqtdepay_debug);
+#define GST_CAT_DEFAULT (rtpxqtdepay_debug)
+
+/* elementfactory information */
+static const GstElementDetails gst_rtp_xqtdepay_details =
+GST_ELEMENT_DETAILS ("RTP packet depayloader",
+    "Codec/Depayloader/Network",
+    "Extracts Quicktime audio/video from RTP packets",
+    "Wim Taymans <wim@fluendo.com>");
+
+/* RtpXQTDepay signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0,
+};
+
+static GstStaticPadTemplate gst_rtp_xqt_depay_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate gst_rtp_xqt_depay_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-rtp, "
+        "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
+        "media = (string) { \"audio\", \"video\" }, clock-rate = (int) [1, MAX], "
+        "encoding-name = (string) { \"X-QT\", \"X-QUICKTIME\" }")
+    );
+
+GST_BOILERPLATE (GstRtpXQTDepay, gst_rtp_xqt_depay, GstBaseRTPDepayload,
+    GST_TYPE_BASE_RTP_DEPAYLOAD);
+
+static void gst_rtp_xqt_depay_finalize (GObject * object);
+
+static gboolean gst_rtp_xqt_depay_setcaps (GstBaseRTPDepayload * depayload,
+    GstCaps * caps);
+static GstBuffer *gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload,
+    GstBuffer * buf);
+
+static GstStateChangeReturn gst_rtp_xqt_depay_change_state (GstElement *
+    element, GstStateChange transition);
+
+static void
+gst_rtp_xqt_depay_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_rtp_xqt_depay_src_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_rtp_xqt_depay_sink_template));
+
+  gst_element_class_set_details (element_class, &gst_rtp_xqtdepay_details);
+}
+
+static void
+gst_rtp_xqt_depay_class_init (GstRtpXQTDepayClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+  gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_rtp_xqt_depay_finalize;
+
+  gstelement_class->change_state = gst_rtp_xqt_depay_change_state;
+
+  gstbasertpdepayload_class->set_caps = gst_rtp_xqt_depay_setcaps;
+  gstbasertpdepayload_class->process = gst_rtp_xqt_depay_process;
+
+  GST_DEBUG_CATEGORY_INIT (rtpxqtdepay_debug, "rtpxqtdepay", 0,
+      "QT Media RTP Depayloader");
+}
+
+static void
+gst_rtp_xqt_depay_init (GstRtpXQTDepay * rtpxqtdepay,
+    GstRtpXQTDepayClass * klass)
+{
+  rtpxqtdepay->adapter = gst_adapter_new ();
+}
+
+static void
+gst_rtp_xqt_depay_finalize (GObject * object)
+{
+  GstRtpXQTDepay *rtpxqtdepay;
+
+  rtpxqtdepay = GST_RTP_XQT_DEPAY (object);
+
+  g_object_unref (rtpxqtdepay->adapter);
+  rtpxqtdepay->adapter = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data,
+    guint data_len)
+{
+  gint len;
+  guint32 fourcc;
+
+  if (data_len < 8)
+    goto too_short;
+
+  len = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+  if (len > data_len)
+    goto too_short;
+
+  fourcc = QT_FOURCC (data + 4);
+
+  GST_DEBUG_OBJECT (rtpxqtdepay, "parsing %" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (fourcc));
+
+  switch (fourcc) {
+    case FOURCC_avc1:
+    {
+      guint32 chlen;
+
+      if (len < 0x56)
+        goto too_short;
+      len -= 0x56;
+      data += 0x56;
+
+      /* find avcC */
+      while (len >= 8) {
+        chlen = QT_UINT32 (data);
+        fourcc = QT_FOURCC (data + 4);
+        if (fourcc == FOURCC_avcC) {
+          GstBuffer *buf;
+          gint size;
+          GstCaps *caps;
+
+          GST_DEBUG_OBJECT (rtpxqtdepay, "found avcC codec_data in sd, %u",
+              chlen);
+
+          /* parse, if found */
+          if (chlen < len)
+            size = chlen - 8;
+          else
+            size = len - 8;
+
+          buf = gst_buffer_new_and_alloc (size);
+          memcpy (GST_BUFFER_DATA (buf), data + 8, size);
+          caps = gst_caps_new_simple ("video/x-h264",
+              "codec_data", GST_TYPE_BUFFER, buf, NULL);
+          gst_buffer_unref (buf);
+          gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD (rtpxqtdepay)->srcpad, caps);
+          gst_caps_unref (caps);
+          break;
+        }
+        len -= chlen;
+        data += chlen;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+  return TRUE;
+
+  /* ERRORS */
+too_short:
+  {
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_rtp_xqt_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
+{
+  GstStructure *structure;
+  gint clock_rate = 90000;      /* default */
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  gst_structure_get_int (structure, "clock-rate", &clock_rate);
+  depayload->clock_rate = clock_rate;
+
+  return TRUE;
+}
+
+static GstBuffer *
+gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
+{
+  GstRtpXQTDepay *rtpxqtdepay;
+  GstBuffer *outbuf;
+  gboolean m;
+
+  rtpxqtdepay = GST_RTP_XQT_DEPAY (depayload);
+
+  if (!gst_rtp_buffer_validate (buf))
+    goto bad_packet;
+
+  if (GST_BUFFER_IS_DISCONT (buf)) {
+    /* discont, clear adapter and try to find a new packet start */
+    gst_adapter_clear (rtpxqtdepay->adapter);
+    rtpxqtdepay->need_resync = TRUE;
+    GST_DEBUG_OBJECT (rtpxqtdepay, "we need resync");
+  }
+
+  m = gst_rtp_buffer_get_marker (buf);
+  GST_LOG_OBJECT (rtpxqtdepay, "marker: %d", m);
+
+  {
+    gint payload_len;
+    guint avail;
+    guint8 *payload;
+    guint32 timestamp;
+    guint8 ver, pck;
+    gboolean s, q, l, d;
+
+    payload_len = gst_rtp_buffer_get_payload_len (buf);
+    payload = gst_rtp_buffer_get_payload (buf);
+
+    /*                      1                   2                   3 
+     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     * | VER   |PCK|S|Q|L| RES         |D| QuickTime Payload ID        |
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     */
+    if (payload_len <= 4)
+      goto wrong_length;
+
+    ver = (payload[0] & 0xf0) >> 4;
+    if (ver > 1)
+      goto wrong_version;
+
+    pck = (payload[0] & 0x0c) >> 2;
+    if (pck == 0)
+      goto pck_reserved;
+
+    s = (payload[0] & 0x02) != 0;       /* contains sync sample */
+    q = (payload[0] & 0x01) != 0;       /* has payload description */
+    l = (payload[1] & 0x80) != 0;       /* has packet specific information description */
+    d = (payload[2] & 0x80) != 0;       /* don't cache info for payload id */
+    /* id used for caching info */
+    rtpxqtdepay->current_id = ((payload[2] & 0x7f) << 8) | payload[3];
+
+    GST_LOG_OBJECT (rtpxqtdepay,
+        "VER: %d, PCK: %d, S: %d, Q: %d, L: %d, D: %d, ID: %d", ver, pck, s, q,
+        l, d, rtpxqtdepay->current_id);
+
+    if (rtpxqtdepay->need_resync) {
+      /* we need to find the boundary of a new packet after a DISCONT */
+      if (pck != 3 || q) {
+        /* non-fragmented packet or payload description present, packet starts
+         * here. */
+        rtpxqtdepay->need_resync = FALSE;
+      } else {
+        /* fragmented packet without description */
+        if (m) {
+          /* marker bit set, next packet is start of new one */
+          rtpxqtdepay->need_resync = FALSE;
+        }
+        goto need_resync;
+      }
+    }
+
+    payload += 4;
+    payload_len -= 4;
+
+    if (q) {
+      gboolean k, f, a, z;
+      guint pdlen, pdpadded;
+      gint padding;
+      guint32 media_type, timescale;
+
+      /*                      1                   2                   3
+       *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * |K|F|A|Z| RES                   | QuickTime Payload Desc Length |
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * . QuickTime Payload Desc Data ... . 
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       */
+      if (payload_len <= 4)
+        goto wrong_length;
+
+      k = (payload[0] & 0x80) != 0;     /* keyframe */
+      f = (payload[0] & 0x40) != 0;     /* sparse */
+      a = (payload[0] & 0x20) != 0;     /* start of payload */
+      z = (payload[0] & 0x10) != 0;     /* end of payload */
+      pdlen = (payload[2] << 8) | payload[3];
+
+      if (pdlen < 12)
+        goto wrong_length;
+
+      /* calc padding */
+      pdpadded = pdlen + 3;
+      pdpadded -= pdpadded % 4;
+      if (payload_len < pdpadded)
+        goto wrong_length;
+
+      padding = pdpadded - pdlen;
+      GST_LOG_OBJECT (rtpxqtdepay,
+          "K: %d, F: %d, A: %d, Z: %d, len: %d, padding %d", k, f, a, z, pdlen,
+          padding);
+
+      payload += 4;
+      payload_len -= 4;
+      /*                      1                   2                   3
+       *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * | QuickTime Media Type                                          |
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * | Timescale                                                     |
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * . QuickTime TLVs ... .
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       */
+      media_type =
+          (payload[0] << 24) | (payload[1] << 16) | (payload[2] << 8) |
+          payload[3];
+      timescale =
+          (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) |
+          payload[7];
+
+      GST_LOG_OBJECT (rtpxqtdepay, "media_type: %c%c%c%c, timescale %u",
+          payload[0], payload[1], payload[2], payload[3], timescale);
+
+      payload += 8;
+      payload_len -= 8;
+      pdlen -= 12;
+
+      /* parse TLV (type-length-value triplets */
+      while (pdlen > 3) {
+        guint16 tlv_len, tlv_type;
+
+        /*                      1                   2                   3
+         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * | QuickTime TLV Length          | QuickTime TLV Type            |
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * . QuickTime TLV Value ... .
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         */
+        tlv_len = (payload[0] << 8) | payload[1];
+        tlv_type = (payload[2] << 8) | payload[3];
+        pdlen -= 4;
+        if (tlv_len > pdlen)
+          goto wrong_length;
+
+        GST_LOG_OBJECT (rtpxqtdepay, "TLV '%c%c', len %d", payload[2],
+            payload[3], tlv_len);
+
+        payload += 4;
+        payload_len -= 4;
+
+        switch (tlv_type) {
+          case TLV_sd:
+            /* Session description */
+            if (!gst_rtp_quicktime_parse_sd (rtpxqtdepay, payload, tlv_len))
+              goto unknown_format;
+            rtpxqtdepay->have_sd = TRUE;
+            break;
+          case TLV_qt:
+          case TLV_ti:
+          case TLV_ly:
+          case TLV_vo:
+          case TLV_mx:
+          case TLV_tr:
+          case TLV_tw:
+          case TLV_th:
+          case TLV_la:
+          case TLV_rt:
+          case TLV_gm:
+          case TLV_oc:
+          case TLV_cr:
+          case TLV_du:
+          case TLV_po:
+          default:
+            break;
+        }
+
+        pdlen -= tlv_len;
+        payload += tlv_len;
+        payload_len -= tlv_len;
+      }
+      payload += padding;
+      payload_len -= padding;
+    }
+
+    if (l) {
+      guint ssilen, ssipadded;
+      gint padding;
+
+      /*                      1                   2                   3
+       *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * | RES                           | Sample-Specific Info Length   |
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       * . QuickTime TLVs ... 
+       * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       */
+      if (payload_len <= 4)
+        goto wrong_length;
+
+      ssilen = (payload[2] << 8) | payload[3];
+      if (ssilen < 4)
+        goto wrong_length;
+
+      /* calc padding */
+      ssipadded = ssilen + 3;
+      ssipadded -= ssipadded % 4;
+      if (payload_len < ssipadded)
+        goto wrong_length;
+
+      padding = ssipadded - ssilen;
+      GST_LOG_OBJECT (rtpxqtdepay, "len: %d, padding %d", ssilen, padding);
+
+      payload += 4;
+      payload_len -= 4;
+      ssilen -= 4;
+
+      /* parse TLV (type-length-value triplets */
+      while (ssilen > 3) {
+        guint16 tlv_len, tlv_type;
+
+        /*                      1                   2                   3
+         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * | QuickTime TLV Length          | QuickTime TLV Type            |
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * . QuickTime TLV Value ... .
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         */
+        tlv_len = (payload[0] << 8) | payload[1];
+        tlv_type = (payload[2] << 8) | payload[3];
+        ssilen -= 4;
+        if (tlv_len > ssilen)
+          goto wrong_length;
+
+        GST_LOG_OBJECT (rtpxqtdepay, "TLV '%c%c', len %d", payload[2],
+            payload[3], tlv_len);
+
+        payload += 4;
+        payload_len -= 4;
+
+        switch (tlv_type) {
+          case TLV_sd:
+          case TLV_qt:
+          case TLV_ti:
+          case TLV_ly:
+          case TLV_vo:
+          case TLV_mx:
+          case TLV_tr:
+          case TLV_tw:
+          case TLV_th:
+          case TLV_la:
+          case TLV_rt:
+          case TLV_gm:
+          case TLV_oc:
+          case TLV_cr:
+          case TLV_du:
+          case TLV_po:
+          default:
+            break;
+        }
+
+        ssilen -= tlv_len;
+        payload += tlv_len;
+        payload_len -= tlv_len;
+      }
+      payload += padding;
+      payload_len -= padding;
+    }
+
+    timestamp = gst_rtp_buffer_get_timestamp (buf);
+    rtpxqtdepay->previous_id = rtpxqtdepay->current_id;
+
+    switch (pck) {
+      case 1:
+      {
+        /* multiple samples per packet. */
+        outbuf = gst_buffer_new_and_alloc (payload_len);
+        memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
+        return outbuf;
+      }
+      case 2:
+      {
+        guint slen, timestamp;
+
+        /* multiple samples per packet. 
+         *                      1                   2                   3
+         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * |S| Reserved                    | Sample Length                 |
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * | Sample Timestamp                                              |
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * . Sample Data ...                                               .
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * |S| Reserved                    | Sample Length                 |
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * | Sample Timestamp                                              |
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * . Sample Data ...                                               .
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * . ......                                                        .
+         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         */
+        while (payload_len > 8) {
+          s = (payload[0] & 0x80) != 0; /* contains sync sample */
+          slen = (payload[2] << 8) | payload[3];
+          timestamp =
+              (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) |
+              payload[7];
+
+          payload += 8;
+          payload_len -= 8;
+
+          if (slen > payload_len)
+            slen = payload_len;
+
+          outbuf = gst_buffer_new_and_alloc (slen);
+          memcpy (GST_BUFFER_DATA (outbuf), payload, slen);
+          if (!s)
+            GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+
+          gst_base_rtp_depayload_push (depayload, outbuf);
+
+          /* aligned on 32 bit boundary */
+          slen = GST_ROUND_UP_4 (slen);
+
+          payload += slen;
+          payload_len -= slen;
+        }
+        break;
+      }
+      case 3:
+      {
+        /* one sample per packet, use adapter to combine based on marker bit. */
+        outbuf = gst_buffer_new_and_alloc (payload_len);
+        memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
+
+        gst_adapter_push (rtpxqtdepay->adapter, outbuf);
+
+        if (!m)
+          goto done;
+
+        avail = gst_adapter_available (rtpxqtdepay->adapter);
+        outbuf = gst_adapter_take_buffer (rtpxqtdepay->adapter, avail);
+
+        GST_DEBUG_OBJECT (rtpxqtdepay,
+            "gst_rtp_xqt_depay_chain: pushing buffer of size %u", avail);
+
+        return outbuf;
+      }
+    }
+  }
+
+done:
+  return NULL;
+
+bad_packet:
+  {
+    GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
+        ("Packet did not validate."), (NULL));
+    return NULL;
+  }
+need_resync:
+  {
+    GST_DEBUG_OBJECT (rtpxqtdepay, "waiting for marker");
+    return NULL;
+  }
+wrong_version:
+  {
+    GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
+        ("Unknown payload version."), (NULL));
+    return NULL;
+  }
+pck_reserved:
+  {
+    GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
+        ("PCK reserved 0."), (NULL));
+    return NULL;
+  }
+wrong_length:
+  {
+    GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
+        ("Wrong payload length."), (NULL));
+    return NULL;
+  }
+unknown_format:
+  {
+    GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
+        ("Unknown payload format."), (NULL));
+    return NULL;
+  }
+}
+
+static GstStateChangeReturn
+gst_rtp_xqt_depay_change_state (GstElement * element, GstStateChange transition)
+{
+  GstRtpXQTDepay *rtpxqtdepay;
+  GstStateChangeReturn ret;
+
+  rtpxqtdepay = GST_RTP_XQT_DEPAY (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_adapter_clear (rtpxqtdepay->adapter);
+      rtpxqtdepay->previous_id = -1;
+      rtpxqtdepay->current_id = -1;
+      rtpxqtdepay->need_resync = TRUE;
+      rtpxqtdepay->have_sd = FALSE;
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_adapter_clear (rtpxqtdepay->adapter);
+    default:
+      break;
+  }
+  return ret;
+}
+
+gboolean
+gst_rtp_xqt_depay_plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "rtpxqtdepay",
+      GST_RANK_MARGINAL, GST_TYPE_RTP_XQT_DEPAY);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/gstrtpxqtdepay.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,64 @@
+/* GStreamer
+ * Copyright (C) <2005> Wim Taymans <wim@fluendo.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_RTP_XQT_DEPAY_H__
+#define __GST_RTP_XQT_DEPAY_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+#include <gst/rtp/gstbasertpdepayload.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_RTP_XQT_DEPAY \
+  (gst_rtp_xqt_depay_get_type())
+#define GST_RTP_XQT_DEPAY(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_XQT_DEPAY,GstRtpXQTDepay))
+#define GST_RTP_XQT_DEPAY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_XQT_DEPAY,GstRtpXQTDepayClass))
+#define GST_IS_RTP_XQT_DEPAY(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_XQT_DEPAY))
+#define GST_IS_RTP_XQT_DEPAY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_XQT_DEPAY))
+
+typedef struct _GstRtpXQTDepay GstRtpXQTDepay;
+typedef struct _GstRtpXQTDepayClass GstRtpXQTDepayClass;
+
+struct _GstRtpXQTDepay
+{
+  GstBaseRTPDepayload depayload;
+
+  GstAdapter *adapter;
+
+  gboolean need_resync;
+  guint16 previous_id;
+  guint16 current_id;
+  gboolean have_sd;
+};
+
+struct _GstRtpXQTDepayClass
+{
+  GstBaseRTPDepayloadClass parent_class;
+};
+
+GType gst_rtp_xqt_depay_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_RTP_XQT_DEPAY_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,6147 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
+ * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
+ * Copyright (C) <2007> Julien Moutte <julien@fluendo.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.
+ */
+
+/**
+ * SECTION:element-qtdemux
+ *
+ * Demuxes a .mov file into raw or compressed audio and/or video streams.
+ *
+ * This element supports both push and pull-based scheduling, depending on the
+ * capabilities of the upstream elements.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch filesrc location=test.mov ! qtdemux name=demux  demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
+ * ]| Play (parse and decode) a .mov file and try to output it to
+ * an automatically detected soundcard and videosink. If the MOV file contains
+ * compressed audio or video data, this will only work if you have the
+ * right decoder elements/plugins installed.
+ * </refsect2>
+ *
+ * Last reviewed on 2006-12-29 (0.10.5)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst/gst-i18n-plugin.h"
+
+#include <gst/tag/tag.h>
+
+#include "qtdemux_types.h"
+#include "qtdemux_dump.h"
+#include "qtdemux_fourcc.h"
+#include "qtdemux.h"
+#include "qtpalette.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ZLIB
+# include <zlib.h>
+#endif
+
+/* max. size considered 'sane' for non-mdat atoms */
+#define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
+
+GST_DEBUG_CATEGORY (qtdemux_debug);
+
+/*typedef struct _QtNode QtNode; */
+typedef struct _QtDemuxSegment QtDemuxSegment;
+typedef struct _QtDemuxSample QtDemuxSample;
+
+/*struct _QtNode
+{
+  guint32 type;
+  guint8 *data;
+  gint len;
+};*/
+
+struct _QtDemuxSample
+{
+  guint32 size;
+  guint64 offset;
+  GstClockTimeDiff pts_offset;  /* Add this value to timestamp to get the pts */
+  guint64 timestamp;            /* In GstClockTime */
+  guint64 duration;             /* in GstClockTime */
+  gboolean keyframe;            /* TRUE when this packet is a keyframe */
+};
+
+/*
+ * Quicktime has tracks and segments. A track is a continuous piece of
+ * multimedia content. The track is not always played from start to finish but
+ * instead, pieces of the track are 'cut out' and played in sequence. This is
+ * what the segments do.
+ *
+ * Inside the track we have keyframes (K) and delta frames. The track has its
+ * own timing, which starts from 0 and extends to end. The position in the track
+ * is called the media_time.
+ *
+ * The segments now describe the pieces that should be played from this track
+ * and are basically tupples of media_time/duration/rate entries. We can have
+ * multiple segments and they are all played after one another. An example:
+ *
+ * segment 1: media_time: 1 second, duration: 1 second, rate 1
+ * segment 2: media_time: 3 second, duration: 2 second, rate 2
+ *
+ * To correctly play back this track, one must play: 1 second of media starting
+ * from media_time 1 followed by 2 seconds of media starting from media_time 3
+ * at a rate of 2.
+ *
+ * Each of the segments will be played at a specific time, the first segment at
+ * time 0, the second one after the duration of the first one, etc.. Note that
+ * the time in resulting playback is not identical to the media_time of the
+ * track anymore.
+ *
+ * Visually, assuming the track has 4 second of media_time:
+ *
+ *                (a)                   (b)          (c)              (d)
+ *         .-----------------------------------------------------------.
+ * track:  | K.....K.........K........K.......K.......K...........K... |
+ *         '-----------------------------------------------------------'
+ *         0              1              2              3              4    
+ *           .------------^              ^   .----------^              ^
+ *          /              .-------------'  /       .------------------'
+ *         /              /          .-----'       /
+ *         .--------------.         .--------------.
+ *         | segment 1    |         | segment 2    |
+ *         '--------------'         '--------------'
+ *       
+ * The challenge here is to cut out the right pieces of the track for each of
+ * the playback segments. This fortunatly can easily be done with the SEGMENT
+ * events of gstreamer.
+ *
+ * For playback of segment 1, we need to provide the decoder with the keyframe
+ * (a), in the above figure, but we must instruct it only to output the decoded
+ * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
+ * position set to the time of the segment: 0.
+ *
+ * We then proceed to push data from keyframe (a) to frame (b). The decoder
+ * decodes but clips all before media_time 1.
+ * 
+ * After finishing a segment, we push out a new SEGMENT event with the clipping
+ * boundaries of the new data.
+ *
+ * This is a good usecase for the GStreamer accumulated SEGMENT events.
+ */
+
+struct _QtDemuxSegment
+{
+  /* global time and duration, all gst time */
+  guint64 time;
+  guint64 stop_time;
+  guint64 duration;
+  /* media time of trak, all gst time */
+  guint64 media_start;
+  guint64 media_stop;
+  gdouble rate;
+};
+
+struct _QtDemuxStream
+{
+  GstPad *pad;
+
+  /* stream type */
+  guint32 subtype;
+  GstCaps *caps;
+  guint32 fourcc;
+
+  /* duration/scale */
+  guint64 duration;             /* in timescale */
+  guint32 timescale;
+
+  /* our samples */
+  guint32 n_samples;
+  QtDemuxSample *samples;
+  gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
+  guint32 min_duration;         /* duration in timescale of first sample, used for figuring out
+                                   the framerate, in timescale units */
+
+  /* if we use chunks or samples */
+  gboolean sampled;
+  guint padding;
+
+  /* video info */
+  gint width;
+  gint height;
+  /* aspect ratio */
+  gint display_width;
+  gint display_height;
+  gint par_w;
+  gint par_h;
+  /* Numerator/denominator framerate */
+  gint fps_n;
+  gint fps_d;
+  guint16 bits_per_sample;
+  guint16 color_table_id;
+
+  /* audio info */
+  gdouble rate;
+  gint n_channels;
+  guint samples_per_packet;
+  guint samples_per_frame;
+  guint bytes_per_packet;
+  guint bytes_per_sample;
+  guint bytes_per_frame;
+  guint compression;
+
+  /* when a discontinuity is pending */
+  gboolean discont;
+
+  /* list of buffers to push first */
+  GSList *buffers;
+
+  /* if we need to clip this buffer. This is only needed for uncompressed
+   * data */
+  gboolean need_clip;
+
+  /* current position */
+  guint32 segment_index;
+  guint32 sample_index;
+  guint64 time_position;        /* in gst time */
+
+  /* the Gst segment we are processing out, used for clipping */
+  GstSegment segment;
+
+  /* last GstFlowReturn */
+  GstFlowReturn last_ret;
+
+  /* quicktime segments */
+  guint32 n_segments;
+  QtDemuxSegment *segments;
+  guint32 from_sample;
+  guint32 to_sample;
+
+  gboolean sent_eos;
+};
+
+enum QtDemuxState
+{
+  QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
+  QTDEMUX_STATE_HEADER,         /* Parsing the header */
+  QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
+  QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
+};
+
+static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
+static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
+
+static const GstElementDetails gst_qtdemux_details =
+GST_ELEMENT_DETAILS ("QuickTime demuxer",
+    "Codec/Demuxer",
+    "Demultiplex a QuickTime file into audio and video streams",
+    "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
+
+static GstStaticPadTemplate gst_qtdemux_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
+        "application/x-3gp")
+    );
+
+static GstStaticPadTemplate gst_qtdemux_videosrc_template =
+GST_STATIC_PAD_TEMPLATE ("video_%02d",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
+GST_STATIC_PAD_TEMPLATE ("audio_%02d",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate gst_qtdemux_subpsrc_template =
+GST_STATIC_PAD_TEMPLATE ("subp_%02d",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstElementClass *parent_class = NULL;
+
+static void gst_qtdemux_class_init (GstQTDemuxClass * klass);
+static void gst_qtdemux_base_init (GstQTDemuxClass * klass);
+static void gst_qtdemux_init (GstQTDemux * quicktime_demux);
+static void gst_qtdemux_dispose (GObject * object);
+
+static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
+    GstStateChange transition);
+static gboolean qtdemux_sink_activate (GstPad * sinkpad);
+static gboolean qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active);
+static gboolean qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active);
+
+static void gst_qtdemux_loop (GstPad * pad);
+static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf);
+static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstEvent * event);
+
+static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer,
+    int length);
+static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
+    const guint8 * buffer, int length);
+static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
+
+static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, GNode * esds, GstTagList * list);
+static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
+    gchar ** codec_name);
+static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
+    gchar ** codec_name);
+static GstCaps *qtdemux_subp_caps (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
+    gchar ** codec_name);
+
+GType
+gst_qtdemux_get_type (void)
+{
+  static GType qtdemux_type = 0;
+
+  if (G_UNLIKELY (!qtdemux_type)) {
+    static const GTypeInfo qtdemux_info = {
+      sizeof (GstQTDemuxClass),
+      (GBaseInitFunc) gst_qtdemux_base_init, NULL,
+      (GClassInitFunc) gst_qtdemux_class_init,
+      NULL, NULL, sizeof (GstQTDemux), 0,
+      (GInstanceInitFunc) gst_qtdemux_init,
+    };
+
+    qtdemux_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstQTDemux", &qtdemux_info,
+        0);
+  }
+  return qtdemux_type;
+}
+
+static void
+gst_qtdemux_base_init (GstQTDemuxClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_qtdemux_sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
+  gst_element_class_set_details (element_class, &gst_qtdemux_details);
+
+  GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
+}
+
+static void
+gst_qtdemux_class_init (GstQTDemuxClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->dispose = gst_qtdemux_dispose;
+
+  gstelement_class->change_state = gst_qtdemux_change_state;
+}
+
+static void
+gst_qtdemux_init (GstQTDemux * qtdemux)
+{
+  qtdemux->sinkpad =
+      gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
+  gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
+  gst_pad_set_activatepull_function (qtdemux->sinkpad,
+      qtdemux_sink_activate_pull);
+  gst_pad_set_activatepush_function (qtdemux->sinkpad,
+      qtdemux_sink_activate_push);
+  gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
+  gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
+  gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
+
+  qtdemux->state = QTDEMUX_STATE_INITIAL;
+  /* FIXME, use segment last_stop for this */
+  qtdemux->last_ts = GST_CLOCK_TIME_NONE;
+  qtdemux->pullbased = FALSE;
+  qtdemux->neededbytes = 16;
+  qtdemux->todrop = 0;
+  qtdemux->adapter = gst_adapter_new ();
+  qtdemux->offset = 0;
+  qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
+  qtdemux->mdatbuffer = NULL;
+  gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
+}
+
+static void
+gst_qtdemux_dispose (GObject * object)
+{
+  GstQTDemux *qtdemux = GST_QTDEMUX (object);
+
+  if (qtdemux->adapter) {
+    g_object_unref (G_OBJECT (qtdemux->adapter));
+    qtdemux->adapter = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static GstFlowReturn
+gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
+    GstBuffer ** buf)
+{
+  GstFlowReturn flow;
+
+  /* Sanity check: catch bogus sizes (fuzzed/broken files) */
+  if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+        (_("This file is invalid and cannot be played.")),
+        ("atom has bogus size %" G_GUINT64_FORMAT, size));
+    return GST_FLOW_ERROR;
+  }
+
+  flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
+
+  if (G_UNLIKELY (flow != GST_FLOW_OK))
+    return flow;
+
+  /* Catch short reads - we don't want any partial atoms */
+  if (G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size)) {
+    GST_WARNING_OBJECT (qtdemux, "short read: %u < %" G_GUINT64_FORMAT,
+        GST_BUFFER_SIZE (*buf), size);
+    gst_buffer_unref (*buf);
+    *buf = NULL;
+    return GST_FLOW_UNEXPECTED;
+  }
+
+  return flow;
+}
+
+#if 0
+static gboolean
+gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
+    GstFormat * dest_format, gint64 * dest_value)
+{
+  gboolean res = TRUE;
+  QtDemuxStream *stream = gst_pad_get_element_private (pad);
+
+  if (stream->subtype == GST_MAKE_FOURCC ('v', 'i', 'd', 'e') &&
+      (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
+    return FALSE;
+
+  switch (src_format) {
+    case GST_FORMAT_TIME:
+      switch (*dest_format) {
+        case GST_FORMAT_BYTES:
+          *dest_value = src_value * 1;  /* FIXME */
+          break;
+        case GST_FORMAT_DEFAULT:
+          *dest_value = src_value * 1;  /* FIXME */
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_BYTES:
+      switch (*dest_format) {
+        case GST_FORMAT_TIME:
+          *dest_value = src_value * 1;  /* FIXME */
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_DEFAULT:
+      switch (*dest_format) {
+        case GST_FORMAT_TIME:
+          *dest_value = src_value * 1;  /* FIXME */
+          break;
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    default:
+      res = FALSE;
+  }
+
+  return res;
+}
+#endif
+
+static const GstQueryType *
+gst_qtdemux_get_src_query_types (GstPad * pad)
+{
+  static const GstQueryType src_types[] = {
+    GST_QUERY_POSITION,
+    GST_QUERY_DURATION,
+    GST_QUERY_SEEKING,
+    0
+  };
+
+  return src_types;
+}
+
+static gboolean
+gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration)
+{
+  gboolean res = TRUE;
+
+  *duration = GST_CLOCK_TIME_NONE;
+
+  if (qtdemux->duration != 0) {
+    if (qtdemux->duration != G_MAXINT32 && qtdemux->timescale != 0) {
+      *duration = gst_util_uint64_scale (qtdemux->duration,
+          GST_SECOND, qtdemux->timescale);
+    }
+  }
+  return res;
+}
+
+static gboolean
+gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
+{
+  gboolean res = FALSE;
+  GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
+
+  GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+      if (GST_CLOCK_TIME_IS_VALID (qtdemux->segment.last_stop)) {
+        gst_query_set_position (query, GST_FORMAT_TIME,
+            qtdemux->segment.last_stop);
+        res = TRUE;
+      }
+      break;
+    case GST_QUERY_DURATION:{
+      GstFormat fmt;
+
+      gst_query_parse_duration (query, &fmt, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        gint64 duration = -1;
+
+        gst_qtdemux_get_duration (qtdemux, &duration);
+        if (duration > 0) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+          res = TRUE;
+        }
+      }
+      break;
+    }
+    case GST_QUERY_SEEKING:{
+      GstFormat fmt;
+      gboolean seekable;
+
+      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        gint64 duration = -1;
+
+        gst_qtdemux_get_duration (qtdemux, &duration);
+        seekable = TRUE;
+        if (!qtdemux->pullbased) {
+          GstQuery *q;
+
+          /* we might be able with help from upstream */
+          seekable = FALSE;
+          q = gst_query_new_seeking (GST_FORMAT_BYTES);
+          if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
+            gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
+            GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
+          }
+          gst_query_unref (q);
+        }
+        gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
+        res = TRUE;
+      }
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, query);
+      break;
+  }
+
+  gst_object_unref (qtdemux);
+
+  return res;
+}
+
+/* push event on all source pads; takes ownership of the event */
+static void
+gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
+{
+  guint n;
+
+  GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
+      GST_EVENT_TYPE_NAME (event));
+
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    GstPad *pad;
+
+    if ((pad = qtdemux->streams[n]->pad))
+      gst_pad_push_event (pad, gst_event_ref (event));
+  }
+  gst_event_unref (event);
+}
+
+/* push a pending newsegment event, if any from the streaming thread */
+static void
+gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
+{
+  if (qtdemux->pending_newsegment) {
+    gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
+    qtdemux->pending_newsegment = NULL;
+  }
+}
+
+typedef struct
+{
+  guint64 media_time;
+} FindData;
+
+static gint
+find_func (QtDemuxSample * s1, guint64 * media_time, gpointer user_data)
+{
+  if (s1->timestamp > *media_time)
+    return 1;
+
+  return -1;
+}
+
+/* find the index of the sample that includes the data for @media_time
+ *
+ * Returns the index of the sample.
+ */
+static guint32
+gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
+    guint64 media_time)
+{
+  QtDemuxSample *result;
+  guint32 index;
+
+  result = gst_util_array_binary_search (str->samples, str->n_samples,
+      sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
+      GST_SEARCH_MODE_BEFORE, &media_time, NULL);
+
+  if (G_LIKELY (result))
+    index = result - str->samples;
+  else
+    index = 0;
+
+  return index;
+}
+
+/* find the index of the keyframe needed to decode the sample at @index
+ * of stream @str.
+ *
+ * Returns the index of the keyframe.
+ */
+static guint32
+gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
+    guint32 index)
+{
+  guint32 new_index = index;
+
+  if (index >= str->n_samples) {
+    new_index = str->n_samples;
+    goto beach;
+  }
+
+  /* all keyframes, return index */
+  if (str->all_keyframe) {
+    new_index = index;
+    goto beach;
+  }
+
+  /* else go back until we have a keyframe */
+  while (TRUE) {
+    if (str->samples[new_index].keyframe)
+      break;
+
+    if (new_index == 0)
+      break;
+
+    new_index--;
+  }
+
+beach:
+  GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
+      "gave %u", index, new_index);
+
+  return new_index;
+}
+
+/* find the segment for @time_position for @stream
+ *
+ * Returns -1 if the segment cannot be found.
+ */
+static guint32
+gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    guint64 time_position)
+{
+  gint i;
+  guint32 seg_idx;
+
+  GST_LOG_OBJECT (qtdemux, "finding segment for %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (time_position));
+
+  /* find segment corresponding to time_position if we are looking
+   * for a segment. */
+  seg_idx = -1;
+  for (i = 0; i < stream->n_segments; i++) {
+    QtDemuxSegment *segment = &stream->segments[i];
+
+    GST_LOG_OBJECT (qtdemux,
+        "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
+        GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
+
+    /* For the last segment we include stop_time in the last segment */
+    if (i < stream->n_segments - 1) {
+      if (segment->time <= time_position && time_position < segment->stop_time) {
+        GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
+        seg_idx = i;
+        break;
+      }
+    } else {
+      if (segment->time <= time_position && time_position <= segment->stop_time) {
+        GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
+        seg_idx = i;
+        break;
+      }
+    }
+  }
+  return seg_idx;
+}
+
+/* move the stream @str to the sample position @index.
+ *
+ * Updates @str->sample_index and marks discontinuity if needed.
+ */
+static void
+gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
+    guint32 index)
+{
+  /* no change needed */
+  if (index == str->sample_index)
+    return;
+
+  GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
+      str->n_samples);
+
+  /* position changed, we have a discont */
+  str->sample_index = index;
+  /* Each time we move in the stream we store the position where we are 
+   * starting from */
+  str->from_sample = index;
+  str->discont = TRUE;
+}
+
+static void
+gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
+    gint64 * key_time, gint64 * key_offset)
+{
+  guint64 min_offset;
+  gint64 min_byte_offset = -1;
+  gint n;
+
+  min_offset = desired_time;
+
+  /* for each stream, find the index of the sample in the segment
+   * and move back to the previous keyframe. */
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    QtDemuxStream *str;
+    guint32 index, kindex;
+    guint32 seg_idx;
+    guint64 media_start;
+    guint64 media_time;
+    guint64 seg_time;
+    QtDemuxSegment *seg;
+
+    str = qtdemux->streams[n];
+
+    seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
+    GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
+
+    /* segment not found, continue with normal flow */
+    if (seg_idx == -1)
+      continue;
+
+    /* get segment and time in the segment */
+    seg = &str->segments[seg_idx];
+    seg_time = desired_time - seg->time;
+
+    /* get the media time in the segment */
+    media_start = seg->media_start + seg_time;
+
+    /* get the index of the sample with media time */
+    index = gst_qtdemux_find_index (qtdemux, str, media_start);
+    GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
+        GST_TIME_ARGS (media_start), index);
+
+    /* find previous keyframe */
+    kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
+
+    /* if the keyframe is at a different position, we need to update the
+     * requested seek time */
+    if (index != kindex) {
+      index = kindex;
+
+      /* get timestamp of keyframe */
+      media_time = str->samples[kindex].timestamp;
+      GST_DEBUG_OBJECT (qtdemux, "keyframe at %u with time %" GST_TIME_FORMAT,
+          kindex, GST_TIME_ARGS (media_time));
+
+      /* keyframes in the segment get a chance to change the
+       * desired_offset. keyframes out of the segment are
+       * ignored. */
+      if (media_time >= seg->media_start) {
+        guint64 seg_time;
+
+        /* this keyframe is inside the segment, convert back to
+         * segment time */
+        seg_time = (media_time - seg->media_start) + seg->time;
+        if (seg_time < min_offset)
+          min_offset = seg_time;
+      }
+    }
+
+    if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
+      min_byte_offset = str->samples[index].offset;
+  }
+
+  if (key_time)
+    *key_time = min_offset;
+  if (key_offset)
+    *key_offset = min_byte_offset;
+}
+
+static gboolean
+gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
+    GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
+{
+  gboolean res;
+  GstFormat fmt;
+
+  g_return_val_if_fail (format != NULL, FALSE);
+  g_return_val_if_fail (cur != NULL, FALSE);
+  g_return_val_if_fail (stop != NULL, FALSE);
+
+  if (*format == GST_FORMAT_TIME)
+    return TRUE;
+
+  fmt = GST_FORMAT_TIME;
+  res = TRUE;
+  if (cur_type != GST_SEEK_TYPE_NONE)
+    res = gst_pad_query_convert (pad, *format, *cur, &fmt, cur);
+  if (res && stop_type != GST_SEEK_TYPE_NONE)
+    res = gst_pad_query_convert (pad, *format, *stop, &fmt, stop);
+
+  if (res)
+    *format = GST_FORMAT_TIME;
+
+  return res;
+}
+
+/* perform seek in push based mode:
+   find BYTE position to move to based on time and delegate to upstream
+*/
+static gboolean
+gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
+{
+  gdouble rate;
+  GstFormat format;
+  GstSeekFlags flags;
+  GstSeekType cur_type, stop_type;
+  gint64 cur, stop;
+  gboolean res;
+  gint64 byte_cur;
+
+  GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
+
+  gst_event_parse_seek (event, &rate, &format, &flags,
+      &cur_type, &cur, &stop_type, &stop);
+
+  if (stop_type != GST_SEEK_TYPE_NONE)
+    goto unsupported_seek;
+  stop = -1;
+
+  /* only forward streaming and seeking is possible */
+  if (rate <= 0)
+    goto unsupported_seek;
+
+  /* convert to TIME if needed and possible */
+  if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
+          stop_type, &stop))
+    goto no_format;
+
+  /* find reasonable corresponding BYTE position,
+   * also try to mind about keyframes, since we can not go back a bit for them
+   * later on */
+  gst_qtdemux_adjust_seek (qtdemux, cur, NULL, &byte_cur);
+
+  if (byte_cur == -1)
+    goto abort_seek;
+
+  GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
+      "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
+      stop);
+  /* BYTE seek event */
+  event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
+      stop_type, stop);
+  res = gst_pad_push_event (qtdemux->sinkpad, event);
+
+  return res;
+
+  /* ERRORS */
+abort_seek:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
+        "seek aborted.");
+    return FALSE;
+  }
+unsupported_seek:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
+    return FALSE;
+  }
+no_format:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
+    return FALSE;
+  }
+}
+
+/* perform the seek.
+ *
+ * We set all segment_indexes in the streams to unknown and
+ * adjust the time_position to the desired position. this is enough
+ * to trigger a segment switch in the streaming thread to start
+ * streaming from the desired position.
+ *
+ * Keyframe seeking is a little more complicated when dealing with
+ * segments. Ideally we want to move to the previous keyframe in
+ * the segment but there might not be a keyframe in the segment. In
+ * fact, none of the segments could contain a keyframe. We take a
+ * practical approach: seek to the previous keyframe in the segment,
+ * if there is none, seek to the beginning of the segment.
+ *
+ * Called with STREAM_LOCK
+ */
+static gboolean
+gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
+{
+  gint64 desired_offset;
+  gint n;
+
+  desired_offset = segment->last_stop;
+
+  GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (desired_offset));
+
+  if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
+    gint64 min_offset;
+
+    gst_qtdemux_adjust_seek (qtdemux, desired_offset, &min_offset, NULL);
+    GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
+        GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
+    desired_offset = min_offset;
+  }
+
+  /* and set all streams to the final position */
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    QtDemuxStream *stream = qtdemux->streams[n];
+
+    stream->time_position = desired_offset;
+    stream->sample_index = -1;
+    stream->segment_index = -1;
+    stream->last_ret = GST_FLOW_OK;
+    stream->sent_eos = FALSE;
+  }
+  segment->last_stop = desired_offset;
+  segment->time = desired_offset;
+
+  /* we stop at the end */
+  if (segment->stop == -1)
+    segment->stop = segment->duration;
+
+  return TRUE;
+}
+
+/* do a seek in pull based mode */
+static gboolean
+gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
+{
+  gdouble rate;
+  GstFormat format;
+  GstSeekFlags flags;
+  GstSeekType cur_type, stop_type;
+  gint64 cur, stop;
+  gboolean flush;
+  gboolean update;
+  GstSegment seeksegment;
+  int i;
+
+  if (event) {
+    GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
+
+    gst_event_parse_seek (event, &rate, &format, &flags,
+        &cur_type, &cur, &stop_type, &stop);
+
+    /* we have to have a format as the segment format. Try to convert
+     * if not. */
+    if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
+            stop_type, &stop))
+      goto no_format;
+
+    GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
+  } else {
+    GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
+    flags = 0;
+  }
+
+  flush = flags & GST_SEEK_FLAG_FLUSH;
+
+  /* stop streaming, either by flushing or by pausing the task */
+  if (flush) {
+    /* unlock upstream pull_range */
+    gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_start ());
+    /* make sure out loop function exits */
+    gst_qtdemux_push_event (qtdemux, gst_event_new_flush_start ());
+  } else {
+    /* non flushing seek, pause the task */
+    gst_pad_pause_task (qtdemux->sinkpad);
+  }
+
+  /* wait for streaming to finish */
+  GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
+
+  /* copy segment, we need this because we still need the old
+   * segment when we close the current segment. */
+  memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
+
+  if (event) {
+    /* configure the segment with the seek variables */
+    GST_DEBUG_OBJECT (qtdemux, "configuring seek");
+    gst_segment_set_seek (&seeksegment, rate, format, flags,
+        cur_type, cur, stop_type, stop, &update);
+  }
+
+  /* now do the seek, this actually never returns FALSE */
+  gst_qtdemux_perform_seek (qtdemux, &seeksegment);
+
+  /* prepare for streaming again */
+  if (flush) {
+    gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_stop ());
+    gst_qtdemux_push_event (qtdemux, gst_event_new_flush_stop ());
+  } else if (qtdemux->segment_running) {
+    /* we are running the current segment and doing a non-flushing seek,
+     * close the segment first based on the last_stop. */
+    GST_DEBUG_OBJECT (qtdemux, "closing running segment %" G_GINT64_FORMAT
+        " to %" G_GINT64_FORMAT, qtdemux->segment.start,
+        qtdemux->segment.last_stop);
+
+    if (qtdemux->segment.rate >= 0) {
+      /* FIXME, rate is the product of the global rate and the (quicktime)
+       * segment rate. */
+      qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
+          qtdemux->segment.rate, qtdemux->segment.format,
+          qtdemux->segment.start, qtdemux->segment.last_stop,
+          qtdemux->segment.time);
+    } else {                    /* For Reverse Playback */
+      guint64 stop;
+
+      if ((stop = qtdemux->segment.stop) == -1)
+        stop = qtdemux->segment.duration;
+      /* for reverse playback, we played from stop to last_stop. */
+      qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
+          qtdemux->segment.rate, qtdemux->segment.format,
+          qtdemux->segment.last_stop, stop, qtdemux->segment.last_stop);
+    }
+  }
+
+  /* commit the new segment */
+  memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
+
+  if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+    gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
+        gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
+            qtdemux->segment.format, qtdemux->segment.last_stop));
+  }
+
+  /* restart streaming, NEWSEGMENT will be sent from the streaming
+   * thread. */
+  qtdemux->segment_running = TRUE;
+  for (i = 0; i < qtdemux->n_streams; i++)
+    qtdemux->streams[i]->last_ret = GST_FLOW_OK;
+
+  gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
+      qtdemux->sinkpad);
+
+  GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
+
+  return TRUE;
+
+  /* ERRORS */
+no_format:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res = TRUE;
+  GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+      if (qtdemux->pullbased) {
+        res = gst_qtdemux_do_seek (qtdemux, pad, event);
+      } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams) {
+        res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
+      } else {
+        GST_DEBUG_OBJECT (qtdemux,
+            "ignoring seek in push mode in current state");
+        res = FALSE;
+      }
+      gst_event_unref (event);
+      break;
+    case GST_EVENT_QOS:
+    case GST_EVENT_NAVIGATION:
+      res = FALSE;
+      gst_event_unref (event);
+      break;
+    default:
+      res = gst_pad_event_default (pad, event);
+      break;
+  }
+
+  gst_object_unref (qtdemux);
+
+  return res;
+}
+
+/* stream/index return sample that is min/max w.r.t. byte position,
+ * time is min/max w.r.t. time of samples,
+ * the latter need not be time of the former sample */
+static void
+gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
+    gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
+{
+  gint i, n, index;
+  gint64 time, min_time;
+  QtDemuxStream *stream;
+
+  min_time = -1;
+  stream = NULL;
+  index = -1;
+
+  for (n = 0; n < qtdemux->n_streams; ++n) {
+    QtDemuxStream *str;
+    gint inc;
+    gboolean set_sample;
+
+
+    str = qtdemux->streams[n];
+    set_sample = !set;
+
+    if (fw) {
+      i = 0;
+      inc = 1;
+    } else {
+      i = str->n_samples - 1;
+      inc = -1;
+    }
+    for (; (i >= 0) && (i < str->n_samples); i += inc) {
+      if (str->samples[i].size &&
+          ((fw && (str->samples[i].offset >= byte_pos)) ||
+              (!fw &&
+                  (str->samples[i].offset + str->samples[i].size <=
+                      byte_pos)))) {
+        /* move stream to first available sample */
+        if (set) {
+          gst_qtdemux_move_stream (qtdemux, str, i);
+          set_sample = TRUE;
+        }
+        /* determine min/max time */
+        time = str->samples[i].timestamp + str->samples[i].pts_offset;
+        if (min_time == -1 || (fw && min_time > time) ||
+            (!fw && min_time < time)) {
+          min_time = time;
+        }
+        /* determine stream with leading sample, to get its position */
+        /* only needed in fw case */
+        if (fw && (!stream ||
+                str->samples[i].offset < stream->samples[index].offset)) {
+          stream = str;
+          index = i;
+        }
+        break;
+      }
+    }
+    /* no sample for this stream, mark eos */
+    if (!set_sample)
+      gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
+  }
+
+  if (_time)
+    *_time = min_time;
+  if (_stream)
+    *_stream = stream;
+  if (_index)
+    *_index = index;
+}
+
+static gboolean
+gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
+{
+  GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
+  gboolean res;
+
+  GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+    {
+      GstFormat format;
+      gdouble rate, arate;
+      gint64 start, stop, time, offset = 0;
+      QtDemuxStream *stream;
+      gint idx;
+      gboolean update;
+      GstSegment segment;
+
+      /* some debug output */
+      gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+          &start, &stop, &time);
+      gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
+          start, stop, time);
+      GST_DEBUG_OBJECT (demux,
+          "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
+          &segment);
+
+      /* chain will send initial newsegment after pads have been added */
+      if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
+        GST_DEBUG_OBJECT (demux, "still starting, eating event");
+        goto exit;
+      }
+
+      /* we only expect a BYTE segment, e.g. following a seek */
+      if (format == GST_FORMAT_BYTES) {
+        if (start > 0) {
+          offset = start;
+          gst_qtdemux_find_sample (demux, start, TRUE, FALSE, NULL, NULL,
+              &start);
+          start = MAX (start, 0);
+        }
+        if (stop > 0) {
+          gst_qtdemux_find_sample (demux, stop, FALSE, FALSE, NULL, NULL,
+              &stop);
+          stop = MAX (stop, 0);
+        }
+      } else {
+        GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
+        goto exit;
+      }
+
+      /* accept upstream's notion of segment and distribute along */
+      gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,
+          GST_FORMAT_TIME, start, stop, start);
+      GST_DEBUG_OBJECT (demux, "Pushing newseg update %d, rate %g, "
+          "applied rate %g, format %d, start %" G_GINT64_FORMAT ", "
+          "stop %" G_GINT64_FORMAT, update, rate, arate, GST_FORMAT_TIME,
+          start, stop);
+      gst_qtdemux_push_event (demux,
+          gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME,
+              start, stop, start));
+
+      /* clear leftover in current segment, if any */
+      gst_adapter_clear (demux->adapter);
+      /* set up streaming thread */
+      gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx, NULL);
+      demux->offset = offset;
+      if (stream) {
+        demux->todrop = stream->samples[idx].offset - offset;
+        demux->neededbytes = demux->todrop + stream->samples[idx].size;
+      } else {
+        /* set up for EOS */
+        demux->neededbytes = -1;
+        demux->todrop = 0;
+      }
+    exit:
+      gst_event_unref (event);
+      res = TRUE;
+      goto drop;
+      break;
+    }
+    case GST_EVENT_FLUSH_STOP:
+    {
+      gint i;
+
+      /* clean up, force EOS if no more info follows */
+      gst_adapter_clear (demux->adapter);
+      demux->offset = 0;
+      demux->neededbytes = -1;
+      /* reset flow return, e.g. following seek */
+      for (i = 0; i < demux->n_streams; i++) {
+        demux->streams[i]->last_ret = GST_FLOW_OK;
+        demux->streams[i]->sent_eos = FALSE;
+      }
+      break;
+    }
+    case GST_EVENT_EOS:
+      /* If we are in push mode, and get an EOS before we've seen any streams,
+       * then error out - we have nowhere to send the EOS */
+      if (!demux->pullbased && demux->n_streams == 0) {
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE,
+            (_("This file contains no playable streams.")),
+            ("no known streams found"));
+      }
+      break;
+    default:
+      break;
+  }
+
+  res = gst_pad_event_default (demux->sinkpad, event);
+
+drop:
+  return res;
+}
+
+static GstStateChangeReturn
+gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstQTDemux *qtdemux = GST_QTDEMUX (element);
+  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      break;
+    default:
+      break;
+  }
+
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:{
+      gint n;
+
+      qtdemux->state = QTDEMUX_STATE_INITIAL;
+      qtdemux->last_ts = GST_CLOCK_TIME_NONE;
+      qtdemux->neededbytes = 16;
+      qtdemux->todrop = 0;
+      qtdemux->pullbased = FALSE;
+      qtdemux->offset = 0;
+      qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
+      if (qtdemux->mdatbuffer)
+        gst_buffer_unref (qtdemux->mdatbuffer);
+      qtdemux->mdatbuffer = NULL;
+      gst_adapter_clear (qtdemux->adapter);
+      for (n = 0; n < qtdemux->n_streams; n++) {
+        QtDemuxStream *stream = qtdemux->streams[n];
+
+        while (stream->buffers) {
+          gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
+          stream->buffers =
+              g_slist_delete_link (stream->buffers, stream->buffers);
+        }
+        if (stream->pad)
+          gst_element_remove_pad (element, stream->pad);
+        if (stream->samples)
+          g_free (stream->samples);
+        if (stream->caps)
+          gst_caps_unref (stream->caps);
+        if (stream->segments)
+          g_free (stream->segments);
+        g_free (stream);
+      }
+      qtdemux->major_brand = 0;
+      qtdemux->n_streams = 0;
+      qtdemux->n_video_streams = 0;
+      qtdemux->n_audio_streams = 0;
+      qtdemux->n_subp_streams = 0;
+      gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
+      break;
+    }
+    default:
+      break;
+  }
+
+  return result;
+}
+
+static void
+extract_initial_length_and_fourcc (const guint8 * data, guint64 * plength,
+    guint32 * pfourcc)
+{
+  guint64 length;
+  guint32 fourcc;
+
+  length = QT_UINT32 (data);
+  GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
+  fourcc = QT_FOURCC (data + 4);
+  GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
+
+  if (length == 0) {
+    length = G_MAXUINT32;
+  } else if (length == 1) {
+    /* this means we have an extended size, which is the 64 bit value of
+     * the next 8 bytes */
+    length = QT_UINT64 (data + 8);
+    GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
+  }
+
+  if (plength)
+    *plength = length;
+  if (pfourcc)
+    *pfourcc = fourcc;
+}
+
+static GstFlowReturn
+gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
+{
+  guint64 length = 0;
+  guint32 fourcc;
+  GstBuffer *buf = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+  guint64 cur_offset = qtdemux->offset;
+
+  ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto beach;
+  if (G_LIKELY (GST_BUFFER_SIZE (buf) == 16))
+    extract_initial_length_and_fourcc (GST_BUFFER_DATA (buf), &length, &fourcc);
+  gst_buffer_unref (buf);
+
+  if (G_UNLIKELY (length == 0)) {
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+        (_("This file is invalid and cannot be played.")),
+        ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
+            GST_FOURCC_ARGS (fourcc)));
+    ret = GST_FLOW_ERROR;
+    goto beach;
+  }
+
+  switch (fourcc) {
+    case FOURCC_mdat:
+    case FOURCC_free:
+    case FOURCC_wide:
+    case FOURCC_PICT:
+    case FOURCC_pnot:
+    {
+      GST_LOG_OBJECT (qtdemux,
+          "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
+          GST_FOURCC_ARGS (fourcc), cur_offset);
+      qtdemux->offset += length;
+      break;
+    }
+    case FOURCC_moov:
+    {
+      GstBuffer *moov;
+
+      ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
+      if (ret != GST_FLOW_OK)
+        goto beach;
+      if (length != GST_BUFFER_SIZE (moov)) {
+        /* Some files have a 'moov' atom at the end of the file which contains
+         * a terminal 'free' atom where the body of the atom is missing.
+         * Check for, and permit, this special case.
+         */
+        if (GST_BUFFER_SIZE (moov) >= 8) {
+          guint8 *final_data = GST_BUFFER_DATA (moov) +
+              (GST_BUFFER_SIZE (moov) - 8);
+          guint32 final_length = QT_UINT32 (final_data);
+          guint32 final_fourcc = QT_FOURCC (final_data + 4);
+          if (final_fourcc == FOURCC_free &&
+              GST_BUFFER_SIZE (moov) + final_length - 8 == length) {
+            /* Ok, we've found that special case. Allocate a new buffer with
+             * that free atom actually present. */
+            GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
+            gst_buffer_copy_metadata (newmoov, moov,
+                GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
+                GST_BUFFER_COPY_CAPS);
+            memcpy (GST_BUFFER_DATA (newmoov), GST_BUFFER_DATA (moov),
+                GST_BUFFER_SIZE (moov));
+            memset (GST_BUFFER_DATA (newmoov) + GST_BUFFER_SIZE (moov), 0,
+                final_length - 8);
+            gst_buffer_unref (moov);
+            moov = newmoov;
+          }
+        }
+      }
+
+      if (length != GST_BUFFER_SIZE (moov)) {
+        GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+            (_("This file is incomplete and cannot be played.")),
+            ("We got less than expected (received %u, wanted %u, offset %"
+                G_GUINT64_FORMAT ")",
+                GST_BUFFER_SIZE (moov), (guint) length, cur_offset));
+        ret = GST_FLOW_ERROR;
+        goto beach;
+      }
+      qtdemux->offset += length;
+
+      qtdemux_parse_moov (qtdemux, GST_BUFFER_DATA (moov), length);
+      qtdemux_node_dump (qtdemux, qtdemux->moov_node);
+
+      qtdemux_parse_tree (qtdemux);
+      g_node_destroy (qtdemux->moov_node);
+      gst_buffer_unref (moov);
+      qtdemux->moov_node = NULL;
+      qtdemux->state = QTDEMUX_STATE_MOVIE;
+      GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
+          qtdemux->state);
+      break;
+    }
+    case FOURCC_ftyp:
+    {
+      GstBuffer *ftyp;
+
+      /* extract major brand; might come in handy for ISO vs QT issues */
+      ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
+      if (ret != GST_FLOW_OK)
+        goto beach;
+      qtdemux->offset += length;
+      /* only consider at least a sufficiently complete ftyp atom */
+      if (length >= 20) {
+        qtdemux->major_brand = QT_FOURCC (GST_BUFFER_DATA (ftyp) + 8);
+        GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (qtdemux->major_brand));
+      }
+      gst_buffer_unref (ftyp);
+      break;
+    }
+    default:
+    {
+      GstBuffer *unknown;
+
+      GST_LOG_OBJECT (qtdemux,
+          "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
+          " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
+          cur_offset);
+      ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
+      if (ret != GST_FLOW_OK)
+        goto beach;
+      GST_MEMDUMP ("Unknown tag", GST_BUFFER_DATA (unknown),
+          GST_BUFFER_SIZE (unknown));
+      gst_buffer_unref (unknown);
+      qtdemux->offset += length;
+      break;
+    }
+  }
+
+beach:
+  return ret;
+}
+
+/* Seeks to the previous keyframe of the indexed stream and 
+ * aligns other streams with respect to the keyframe timestamp 
+ * of indexed stream. Only called in case of Reverse Playback
+ */
+static GstFlowReturn
+gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
+{
+  guint8 n = 0;
+  guint32 seg_idx = 0, k_index = 0;
+  guint64 k_pos = 0, last_stop = 0;
+  QtDemuxSegment *seg = NULL;
+  QtDemuxStream *ref_str = NULL;
+
+  /* Now we choose an arbitrary stream, get the previous keyframe timestamp
+   * and finally align all the other streams on that timestamp with their 
+   * respective keyframes */
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    QtDemuxStream *str = qtdemux->streams[n];
+
+    seg_idx = gst_qtdemux_find_segment (qtdemux, str,
+        qtdemux->segment.last_stop);
+
+    /* segment not found, continue with normal flow */
+    if (seg_idx == -1)
+      continue;
+
+    /* No candidate yet, take that one */
+    if (!ref_str) {
+      ref_str = str;
+      continue;
+    }
+
+    /* So that stream has a segment, we prefer video streams */
+    if (str->subtype == FOURCC_vide) {
+      ref_str = str;
+      break;
+    }
+  }
+
+  if (G_UNLIKELY (!ref_str)) {
+    GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
+    goto eos;
+  }
+
+  if (G_UNLIKELY (!ref_str->from_sample)) {
+    GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
+    goto eos;
+  }
+
+  /* So that stream has been playing from from_sample to to_sample. We will
+   * get the timestamp of the previous sample and search for a keyframe before
+   * that. For audio streams we do an arbitrary jump in the past (10 samples) */
+  if (ref_str->subtype == FOURCC_vide) {
+    k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
+        ref_str->from_sample - 1);
+  } else {
+    k_index = ref_str->from_sample - 10;
+  }
+
+  /* get current segment for that stream */
+  seg = &ref_str->segments[ref_str->segment_index];
+  /* Crawl back through segments to find the one containing this I frame */
+  while (ref_str->samples[k_index].timestamp < seg->media_start) {
+    GST_DEBUG_OBJECT (qtdemux, "keyframe position is out of segment %u",
+        ref_str->segment_index);
+    if (G_UNLIKELY (!ref_str->segment_index)) {
+      /* Reached first segment, let's consider it's EOS */
+      goto eos;
+    }
+    ref_str->segment_index--;
+    seg = &ref_str->segments[ref_str->segment_index];
+  }
+  /* Calculate time position of the keyframe and where we should stop */
+  k_pos = (ref_str->samples[k_index].timestamp - seg->media_start) + seg->time;
+  last_stop = ref_str->samples[ref_str->from_sample].timestamp;
+  last_stop = (last_stop - seg->media_start) + seg->time;
+
+  GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
+      "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
+      k_index, GST_TIME_ARGS (k_pos));
+
+  /* Set last_stop with the keyframe timestamp we pushed of that stream */
+  gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, last_stop);
+  GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (last_stop));
+
+  if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
+    GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
+    goto eos;
+  }
+
+  /* Align them all on this */
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    guint32 index = 0;
+    guint64 media_start = 0, seg_time = 0;
+    QtDemuxStream *str = qtdemux->streams[n];
+
+    seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
+    GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
+
+    /* segment not found, continue with normal flow */
+    if (seg_idx == -1)
+      continue;
+
+    /* get segment and time in the segment */
+    seg = &str->segments[seg_idx];
+    seg_time = k_pos - seg->time;
+
+    /* get the media time in the segment */
+    media_start = seg->media_start + seg_time;
+
+    /* get the index of the sample with media time */
+    index = gst_qtdemux_find_index (qtdemux, str, media_start);
+    GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
+        GST_TIME_ARGS (media_start), index);
+
+    /* find previous keyframe */
+    k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
+
+    /* Remember until where we want to go */
+    str->to_sample = str->from_sample - 1;
+    /* Define our time position */
+    str->time_position =
+        (str->samples[k_index].timestamp - seg->media_start) + seg->time;
+    /* Now seek back in time */
+    gst_qtdemux_move_stream (qtdemux, str, k_index);
+    GST_DEBUG_OBJECT (qtdemux, "keyframe at %u, time position %"
+        GST_TIME_FORMAT " playing from sample %u to %u", k_index,
+        GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
+  }
+
+  return GST_FLOW_OK;
+
+eos:
+  return GST_FLOW_UNEXPECTED;
+}
+
+/* activate the given segment number @seg_idx of @stream at time @offset.
+ * @offset is an absolute global position over all the segments.
+ *
+ * This will push out a NEWSEGMENT event with the right values and
+ * position the stream index to the first decodable sample before
+ * @offset.
+ */
+static gboolean
+gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    guint32 seg_idx, guint64 offset)
+{
+  GstEvent *event;
+  QtDemuxSegment *segment;
+  guint32 index, kf_index;
+  guint64 seg_time;
+  guint64 start, stop, time;
+  gdouble rate;
+
+  GST_LOG_OBJECT (qtdemux, "activate segment %d, offset %" G_GUINT64_FORMAT,
+      seg_idx, offset);
+
+  /* update the current segment */
+  stream->segment_index = seg_idx;
+
+  /* get the segment */
+  segment = &stream->segments[seg_idx];
+
+  if (G_UNLIKELY (offset < segment->time)) {
+    GST_WARNING_OBJECT (qtdemux, "offset < segment->time %" G_GUINT64_FORMAT,
+        segment->time);
+    return FALSE;
+  }
+
+  /* get time in this segment */
+  seg_time = offset - segment->time;
+
+  GST_LOG_OBJECT (qtdemux, "seg_time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (seg_time));
+
+  if (G_UNLIKELY (seg_time > segment->duration)) {
+    GST_LOG_OBJECT (qtdemux, "seg_time > segment->duration %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (segment->duration));
+    return FALSE;
+  }
+
+  /* qtdemux->segment.stop is in outside-time-realm, whereas
+   * segment->media_stop is in track-time-realm.
+   * 
+   * In order to compare the two, we need to bring segment.stop
+   * into the track-time-realm */
+
+  if (qtdemux->segment.stop == -1)
+    stop = segment->media_stop;
+  else
+    stop =
+        MIN (segment->media_stop,
+        qtdemux->segment.stop - segment->time + segment->media_start);
+
+  if (qtdemux->segment.rate >= 0) {
+    start = MIN (segment->media_start + seg_time, stop);
+    time = offset;
+  } else {
+    start = segment->media_start;
+    stop = MIN (segment->media_start + seg_time, stop);
+    time = segment->time;
+  }
+
+  GST_DEBUG_OBJECT (qtdemux, "newsegment %d from %" GST_TIME_FORMAT
+      " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
+      GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
+
+  /* combine global rate with that of the segment */
+  rate = segment->rate * qtdemux->segment.rate;
+
+  /* update the segment values used for clipping */
+  gst_segment_init (&stream->segment, GST_FORMAT_TIME);
+  gst_segment_set_newsegment (&stream->segment, FALSE, rate, GST_FORMAT_TIME,
+      start, stop, time);
+
+  /* now prepare and send the segment */
+  if (stream->pad) {
+    event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
+        start, stop, time);
+    gst_pad_push_event (stream->pad, event);
+    /* assume we can send more data now */
+    stream->last_ret = GST_FLOW_OK;
+  }
+
+  /* and move to the keyframe before the indicated media time of the
+   * segment */
+  if (qtdemux->segment.rate >= 0) {
+    index = gst_qtdemux_find_index (qtdemux, stream, start);
+    stream->to_sample = stream->n_samples;
+    GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
+        ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
+        GST_TIME_ARGS (stream->samples[index].timestamp));
+  } else {
+    index = gst_qtdemux_find_index (qtdemux, stream, stop);
+    stream->to_sample = index;
+    GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
+        ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
+        GST_TIME_ARGS (stream->samples[index].timestamp));
+  }
+
+  /* we're at the right spot */
+  if (index == stream->sample_index) {
+    GST_DEBUG_OBJECT (qtdemux, "we are at the right index");
+    return TRUE;
+  }
+
+  /* find keyframe of the target index */
+  kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
+
+  /* if we move forwards, we don't have to go back to the previous
+   * keyframe since we already sent that. We can also just jump to
+   * the keyframe right before the target index if there is one. */
+  if (index > stream->sample_index) {
+    /* moving forwards check if we move past a keyframe */
+    if (kf_index > stream->sample_index) {
+      GST_DEBUG_OBJECT (qtdemux, "moving forwards to keyframe at %u (pts %"
+          GST_TIME_FORMAT, kf_index,
+          GST_TIME_ARGS (stream->samples[kf_index].timestamp));
+      gst_qtdemux_move_stream (qtdemux, stream, kf_index);
+    } else {
+      GST_DEBUG_OBJECT (qtdemux, "moving forwards, keyframe at %u (pts %"
+          GST_TIME_FORMAT " already sent", kf_index,
+          GST_TIME_ARGS (stream->samples[kf_index].timestamp));
+    }
+  } else {
+    GST_DEBUG_OBJECT (qtdemux, "moving backwards to keyframe at %u (pts %"
+        GST_TIME_FORMAT, kf_index,
+        GST_TIME_ARGS (stream->samples[kf_index].timestamp));
+    gst_qtdemux_move_stream (qtdemux, stream, kf_index);
+  }
+
+  return TRUE;
+}
+
+/* prepare to get the current sample of @stream, getting essential values.
+ *
+ * This function will also prepare and send the segment when needed.
+ *
+ * Return FALSE if the stream is EOS.
+ */
+static gboolean
+gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, guint64 * offset, guint * size, guint64 * timestamp,
+    guint64 * duration, gboolean * keyframe)
+{
+  QtDemuxSample *sample;
+  guint64 time_position;
+  guint32 seg_idx;
+
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  time_position = stream->time_position;
+  if (G_UNLIKELY (time_position == -1))
+    goto eos;
+
+  seg_idx = stream->segment_index;
+  if (G_UNLIKELY (seg_idx == -1)) {
+    /* find segment corresponding to time_position if we are looking
+     * for a segment. */
+    seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
+
+    /* nothing found, we're really eos */
+    if (seg_idx == -1)
+      goto eos;
+  }
+
+  /* different segment, activate it, sample_index will be set. */
+  if (G_UNLIKELY (stream->segment_index != seg_idx))
+    gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
+
+  GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
+      stream->sample_index, stream->n_samples);
+
+  /* send out pending buffers */
+  while (stream->buffers) {
+    GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
+
+    if (G_UNLIKELY (stream->discont)) {
+      GST_LOG_OBJECT (qtdemux, "marking discont buffer");
+      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+      stream->discont = FALSE;
+    }
+    gst_buffer_set_caps (buffer, stream->caps);
+
+    gst_pad_push (stream->pad, buffer);
+
+    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
+  }
+
+  if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
+    goto eos;
+
+  /* now get the info for the sample we're at */
+  sample = &stream->samples[stream->sample_index];
+
+  *timestamp = sample->timestamp + sample->pts_offset;
+  *offset = sample->offset;
+  *size = sample->size;
+  *duration = sample->duration;
+  *keyframe = stream->all_keyframe || sample->keyframe;
+
+  /* add padding */
+  if (stream->padding) {
+    *offset += stream->padding;
+    *size -= stream->padding;
+  }
+
+  return TRUE;
+
+  /* special cases */
+eos:
+  {
+    stream->time_position = -1;
+    return FALSE;
+  }
+}
+
+/* move to the next sample in @stream.
+ *
+ * Moves to the next segment when needed.
+ */
+static void
+gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
+{
+  QtDemuxSample *sample;
+  QtDemuxSegment *segment;
+
+  if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
+    /* Mark the stream as EOS */
+    GST_DEBUG_OBJECT (qtdemux, "reached max allowed sample %u, mark EOS",
+        stream->to_sample);
+    stream->time_position = -1;
+    return;
+  }
+
+  /* move to next sample */
+  stream->sample_index++;
+
+  /* get current segment */
+  segment = &stream->segments[stream->segment_index];
+
+  /* reached the last sample, we need the next segment */
+  if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
+    goto next_segment;
+
+  /* get next sample */
+  sample = &stream->samples[stream->sample_index];
+
+  /* see if we are past the segment */
+  if (G_UNLIKELY (sample->timestamp >= segment->media_stop))
+    goto next_segment;
+
+  if (sample->timestamp >= segment->media_start) {
+    /* inside the segment, update time_position, looks very familiar to
+     * GStreamer segments, doesn't it? */
+    stream->time_position =
+        (sample->timestamp - segment->media_start) + segment->time;
+  } else {
+    /* not yet in segment, time does not yet increment. This means
+     * that we are still prerolling keyframes to the decoder so it can
+     * decode the first sample of the segment. */
+    stream->time_position = segment->time;
+  }
+  return;
+
+  /* move to the next segment */
+next_segment:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
+
+    if (stream->segment_index == stream->n_segments - 1) {
+      /* are we at the end of the last segment, we're EOS */
+      stream->time_position = -1;
+    } else {
+      /* else we're only at the end of the current segment */
+      stream->time_position = segment->stop_time;
+    }
+    /* make sure we select a new segment */
+    stream->segment_index = -1;
+  }
+}
+
+static void
+gst_qtdemux_sync_streams (GstQTDemux * demux)
+{
+  gint i;
+
+  if (demux->n_streams <= 1)
+    return;
+
+  for (i = 0; i < demux->n_streams; i++) {
+    QtDemuxStream *stream;
+    GstClockTime end_time;
+
+    stream = demux->streams[i];
+
+    if (!stream->pad)
+      continue;
+
+    /* TODO advance time on subtitle streams here, if any some day */
+
+    /* some clips/trailers may have unbalanced streams at the end,
+     * so send EOS on shorter stream to prevent stalling others */
+
+    /* do not mess with EOS if SEGMENT seeking */
+    if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
+      continue;
+
+    if (demux->pullbased) {
+      /* loop mode is sample time based */
+      if (stream->time_position != -1)
+        continue;
+    } else {
+      /* push mode is byte position based */
+      if (stream->samples[stream->n_samples - 1].offset >= demux->offset)
+        continue;
+    }
+
+    if (stream->sent_eos)
+      continue;
+
+    /* only act if some gap */
+    end_time = stream->segments[stream->n_segments - 1].stop_time;
+    GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
+        ", stream end: %" GST_TIME_FORMAT, GST_TIME_ARGS (end_time),
+        GST_TIME_ARGS (demux->segment.last_stop));
+    if (end_time + 2 * GST_SECOND < demux->segment.last_stop) {
+      GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
+          GST_PAD_NAME (stream->pad));
+      stream->sent_eos = TRUE;
+      gst_pad_push_event (stream->pad, gst_event_new_eos ());
+    }
+  }
+}
+
+/* UNEXPECTED and NOT_LINKED need to be combined. This means that we return:
+ *  
+ *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
+ *  GST_FLOW_UNEXPECTED: when all pads UNEXPECTED or NOT_LINKED.
+ */
+static GstFlowReturn
+gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
+    GstFlowReturn ret)
+{
+  gint i;
+  gboolean unexpected = FALSE, not_linked = TRUE;
+
+  GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
+
+  /* store the value */
+  stream->last_ret = ret;
+
+  for (i = 0; i < demux->n_streams; i++) {
+    QtDemuxStream *ostream = demux->streams[i];
+
+    ret = ostream->last_ret;
+
+    /* no unexpected or unlinked, return */
+    if (G_LIKELY (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_NOT_LINKED))
+      goto done;
+
+    /* we check to see if we have at least 1 unexpected or all unlinked */
+    unexpected |= (ret == GST_FLOW_UNEXPECTED);
+    not_linked &= (ret == GST_FLOW_NOT_LINKED);
+  }
+
+  /* when we get here, we all have unlinked or unexpected */
+  if (not_linked)
+    ret = GST_FLOW_NOT_LINKED;
+  else if (unexpected)
+    ret = GST_FLOW_UNEXPECTED;
+done:
+  GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
+  return ret;
+}
+
+/* the input buffer metadata must be writable. Returns NULL when the buffer is
+ * completely cliped */
+static GstBuffer *
+gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    GstBuffer * buf)
+{
+  gint64 start, stop, cstart, cstop, diff;
+  GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
+  guint8 *data;
+  guint size;
+  gint num_rate, denom_rate;
+  gint frame_size;
+  gboolean clip_data;
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  /* depending on the type, setup the clip parameters */
+  if (stream->subtype == FOURCC_soun) {
+    frame_size = stream->bytes_per_frame;
+    num_rate = GST_SECOND;
+    denom_rate = (gint) stream->rate;
+    clip_data = TRUE;
+  } else if (stream->subtype == FOURCC_vide) {
+    frame_size = size;
+    num_rate = stream->fps_n;
+    denom_rate = stream->fps_d;
+    clip_data = FALSE;
+  } else
+    goto wrong_type;
+
+  /* we can only clip if we have a valid timestamp */
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp)))
+    goto no_timestamp;
+
+  if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf))) {
+    duration = GST_BUFFER_DURATION (buf);
+  } else {
+    duration =
+        gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
+  }
+
+  start = timestamp;
+  stop = start + duration;
+
+  if (G_UNLIKELY (!gst_segment_clip (&stream->segment, GST_FORMAT_TIME,
+              start, stop, &cstart, &cstop)))
+    goto clipped;
+
+  /* see if some clipping happened */
+  diff = cstart - start;
+  if (diff > 0) {
+    timestamp = cstart;
+    duration -= diff;
+
+    if (clip_data) {
+      /* bring clipped time to samples and to bytes */
+      diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
+      diff *= frame_size;
+
+      GST_DEBUG_OBJECT (qtdemux, "clipping start to %" GST_TIME_FORMAT " %"
+          G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
+
+      data += diff;
+      size -= diff;
+    }
+  }
+  diff = stop - cstop;
+  if (diff > 0) {
+    duration -= diff;
+
+    if (clip_data) {
+      /* bring clipped time to samples and then to bytes */
+      diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
+      diff *= frame_size;
+
+      GST_DEBUG_OBJECT (qtdemux, "clipping stop to %" GST_TIME_FORMAT " %"
+          G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
+
+      size -= diff;
+    }
+  }
+
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;
+  GST_BUFFER_DURATION (buf) = duration;
+  GST_BUFFER_SIZE (buf) = size;
+  GST_BUFFER_DATA (buf) = data;
+
+  return buf;
+
+  /* dropped buffer */
+wrong_type:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
+    return buf;
+  }
+no_timestamp:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "no timestamp on buffer");
+    return buf;
+  }
+clipped:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
+    gst_buffer_unref (buf);
+    return NULL;
+  }
+}
+
+static GstFlowReturn
+gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstBuffer *buf = NULL;
+  QtDemuxStream *stream;
+  guint64 min_time;
+  guint64 offset = 0;
+  guint64 timestamp = GST_CLOCK_TIME_NONE;
+  guint64 duration = 0;
+  gboolean keyframe = FALSE;
+  guint size = 0;
+  gint index;
+  gint i;
+
+  gst_qtdemux_push_pending_newsegment (qtdemux);
+
+  /* Figure out the next stream sample to output, min_time is expressed in
+   * global time and runs over the edit list segments. */
+  min_time = G_MAXUINT64;
+  index = -1;
+  for (i = 0; i < qtdemux->n_streams; i++) {
+    guint64 position;
+
+    stream = qtdemux->streams[i];
+    position = stream->time_position;
+
+    /* position of -1 is EOS */
+    if (position != -1 && position < min_time) {
+      min_time = position;
+      index = i;
+    }
+  }
+  /* all are EOS */
+  if (G_UNLIKELY (index == -1)) {
+    GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
+    goto eos;
+  }
+
+  /* check for segment end */
+  if (G_UNLIKELY (qtdemux->segment.stop != -1
+          && qtdemux->segment.stop < min_time)) {
+    GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
+    goto eos;
+  }
+
+  stream = qtdemux->streams[index];
+
+  /* fetch info for the current sample of this stream */
+  if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &offset,
+              &size, &timestamp, &duration, &keyframe)))
+    goto eos_stream;
+
+  GST_LOG_OBJECT (qtdemux,
+      "pushing from stream %d, offset %" G_GUINT64_FORMAT
+      ", size %d, timestamp=%" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
+      index, offset, size, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
+
+  /* hmm, empty sample, skip and move to next sample */
+  if (G_UNLIKELY (size <= 0))
+    goto next;
+
+  /* last pushed sample was out of boundary, goto next sample */
+  if (G_UNLIKELY (stream->last_ret == GST_FLOW_UNEXPECTED))
+    goto next;
+
+  GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
+      offset);
+
+  ret = gst_qtdemux_pull_atom (qtdemux, offset, size, &buf);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto beach;
+
+  if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
+    GstMessage *m;
+    gchar *url;
+
+    url = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+    /* we have RTSP redirect now */
+    m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
+        gst_structure_new ("redirect",
+            "new-location", G_TYPE_STRING, url, NULL));
+    g_free (url);
+
+    gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
+  }
+
+  qtdemux->last_ts = min_time;
+  if (qtdemux->segment.rate >= 0) {
+    gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, min_time);
+    gst_qtdemux_sync_streams (qtdemux);
+  }
+  if (G_LIKELY (stream->pad)) {
+    /* we're going to modify the metadata */
+    buf = gst_buffer_make_metadata_writable (buf);
+
+    GST_BUFFER_TIMESTAMP (buf) = timestamp;
+    GST_BUFFER_DURATION (buf) = duration;
+    GST_BUFFER_OFFSET (buf) = -1;
+    GST_BUFFER_OFFSET_END (buf) = -1;
+
+    if (stream->need_clip)
+      buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
+
+    if (buf == NULL)
+      goto next;
+
+    if (stream->discont) {
+      GST_LOG_OBJECT (qtdemux, "marking discont buffer");
+      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+      stream->discont = FALSE;
+    }
+
+    if (!keyframe)
+      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+
+    gst_buffer_set_caps (buf, stream->caps);
+
+    GST_LOG_OBJECT (qtdemux,
+        "Pushing buffer with time %" GST_TIME_FORMAT ", duration %"
+        GST_TIME_FORMAT " on pad %s",
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
+
+    ret = gst_pad_push (stream->pad, buf);
+  } else {
+    GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
+    gst_buffer_unref (buf);
+    ret = GST_FLOW_OK;
+  }
+
+  /* combine flows */
+  ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
+  /* ignore unlinked, we will not push on the pad anymore and we will EOS when
+   * we have no more data for the pad to push */
+  if (ret == GST_FLOW_UNEXPECTED)
+    ret = GST_FLOW_OK;
+
+next:
+  gst_qtdemux_advance_sample (qtdemux, stream);
+
+beach:
+  return ret;
+
+  /* special cases */
+eos:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
+    ret = GST_FLOW_UNEXPECTED;
+    goto beach;
+  }
+eos_stream:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
+    /* EOS will be raised if all are EOS */
+    ret = GST_FLOW_OK;
+    goto beach;
+  }
+}
+
+static void
+gst_qtdemux_loop (GstPad * pad)
+{
+  GstQTDemux *qtdemux;
+  guint64 cur_offset;
+  GstFlowReturn ret;
+
+  qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
+
+  cur_offset = qtdemux->offset;
+  GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
+      cur_offset, qtdemux->state);
+
+  switch (qtdemux->state) {
+    case QTDEMUX_STATE_INITIAL:
+    case QTDEMUX_STATE_HEADER:
+      ret = gst_qtdemux_loop_state_header (qtdemux);
+      break;
+    case QTDEMUX_STATE_MOVIE:
+      ret = gst_qtdemux_loop_state_movie (qtdemux);
+      if (qtdemux->segment.rate < 0 && ret == GST_FLOW_UNEXPECTED) {
+        ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
+      }
+      break;
+    default:
+      /* ouch */
+      goto invalid_state;
+  }
+
+  /* if something went wrong, pause */
+  if (ret != GST_FLOW_OK)
+    goto pause;
+
+done:
+  gst_object_unref (qtdemux);
+  return;
+
+  /* ERRORS */
+invalid_state:
+  {
+    GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
+        (NULL), ("streaming stopped, invalid state"));
+    qtdemux->segment_running = FALSE;
+    gst_pad_pause_task (pad);
+    gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
+    goto done;
+  }
+pause:
+  {
+    const gchar *reason = gst_flow_get_name (ret);
+
+    GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
+
+    qtdemux->segment_running = FALSE;
+    gst_pad_pause_task (pad);
+
+    /* fatal errors need special actions */
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
+      /* check EOS */
+      if (ret == GST_FLOW_UNEXPECTED) {
+        if (qtdemux->n_streams == 0) {
+          /* we have no streams, post an error */
+          GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+              (_("This file contains no playable streams.")),
+              ("no known streams found"));
+        }
+        if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+          gint64 stop;
+
+          /* FIXME: I am not sure this is the right fix. If the sinks are
+           * supposed to detect the segment is complete and accumulate 
+           * automatically, it does not seem to work here. Need more work */
+          qtdemux->segment_running = TRUE;
+
+          if ((stop = qtdemux->segment.stop) == -1)
+            stop = qtdemux->segment.duration;
+
+          if (qtdemux->segment.rate >= 0) {
+            GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
+            gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
+                gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
+                    GST_FORMAT_TIME, stop));
+          } else {
+            /*  For Reverse Playback */
+            GST_LOG_OBJECT (qtdemux,
+                "Sending segment done, at start of segment");
+            gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
+                gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
+                    GST_FORMAT_TIME, qtdemux->segment.start));
+          }
+        } else {
+          GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
+          gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
+        }
+      } else {
+        GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
+            (NULL), ("streaming stopped, reason %s", reason));
+        gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
+      }
+    }
+    goto done;
+  }
+}
+
+/*
+ * next_entry_size
+ *
+ * Returns the size of the first entry at the current offset.
+ * If -1, there are none (which means EOS or empty file).
+ */
+static guint64
+next_entry_size (GstQTDemux * demux)
+{
+  QtDemuxStream *stream;
+  int i;
+  int smallidx = -1;
+  guint64 smalloffs = (guint64) - 1;
+
+  GST_LOG_OBJECT (demux, "Finding entry at offset %lld", demux->offset);
+
+  for (i = 0; i < demux->n_streams; i++) {
+    stream = demux->streams[i];
+
+    if (stream->sample_index == -1)
+      stream->sample_index = 0;
+
+    if (stream->sample_index >= stream->n_samples) {
+      GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
+      continue;
+    }
+
+    GST_LOG_OBJECT (demux,
+        "Checking Stream %d (sample_index:%d / offset:%lld / size:%d)",
+        i, stream->sample_index, stream->samples[stream->sample_index].offset,
+        stream->samples[stream->sample_index].size);
+
+    if (((smalloffs == -1)
+            || (stream->samples[stream->sample_index].offset < smalloffs))
+        && (stream->samples[stream->sample_index].size)) {
+      smallidx = i;
+      smalloffs = stream->samples[stream->sample_index].offset;
+    }
+  }
+
+  GST_LOG_OBJECT (demux, "stream %d offset %lld demux->offset :%lld",
+      smallidx, smalloffs, demux->offset);
+
+  if (smallidx == -1)
+    return -1;
+  stream = demux->streams[smallidx];
+
+  if (stream->samples[stream->sample_index].offset >= demux->offset) {
+    demux->todrop =
+        stream->samples[stream->sample_index].offset - demux->offset;
+    return stream->samples[stream->sample_index].size + demux->todrop;
+  }
+
+  GST_DEBUG_OBJECT (demux, "There wasn't any entry at offset %lld",
+      demux->offset);
+  return -1;
+}
+
+static void
+gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
+{
+  gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
+
+  gst_element_post_message (GST_ELEMENT_CAST (demux),
+      gst_message_new_element (GST_OBJECT_CAST (demux),
+          gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
+}
+
+/* FIXME, unverified after edit list updates */
+static GstFlowReturn
+gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
+{
+  GstQTDemux *demux;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  demux = GST_QTDEMUX (gst_pad_get_parent (sinkpad));
+
+  gst_adapter_push (demux->adapter, inbuf);
+
+  /* we never really mean to buffer that much */
+  if (demux->neededbytes == -1)
+    goto eos;
+
+  GST_DEBUG_OBJECT (demux, "pushing in inbuf %p, neededbytes:%u, available:%u",
+      inbuf, demux->neededbytes, gst_adapter_available (demux->adapter));
+
+  while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
+      (ret == GST_FLOW_OK)) {
+
+    GST_DEBUG_OBJECT (demux,
+        "state:%d , demux->neededbytes:%d, demux->offset:%lld", demux->state,
+        demux->neededbytes, demux->offset);
+
+    switch (demux->state) {
+      case QTDEMUX_STATE_INITIAL:{
+        const guint8 *data;
+        guint32 fourcc;
+        guint64 size;
+
+        data = gst_adapter_peek (demux->adapter, demux->neededbytes);
+
+        /* get fourcc/length, set neededbytes */
+        extract_initial_length_and_fourcc ((guint8 *) data, &size, &fourcc);
+        GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
+            "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
+        if (size == 0) {
+          GST_ELEMENT_ERROR (demux, STREAM, DECODE,
+              (_("This file is invalid and cannot be played.")),
+              ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
+                  GST_FOURCC_ARGS (fourcc)));
+          ret = GST_FLOW_ERROR;
+          break;
+        }
+        if (fourcc == FOURCC_mdat) {
+          if (demux->n_streams > 0) {
+            demux->state = QTDEMUX_STATE_MOVIE;
+            demux->neededbytes = next_entry_size (demux);
+          } else {
+            guint bs;
+
+          buffer_data:
+            /* there may be multiple mdat (or alike) buffers */
+            /* sanity check */
+            if (demux->mdatbuffer)
+              bs = GST_BUFFER_SIZE (demux->mdatbuffer);
+            else
+              bs = 0;
+            if (size + bs > 10 * (1 << 20))
+              goto no_moov;
+            demux->state = QTDEMUX_STATE_BUFFER_MDAT;
+            demux->neededbytes = size;
+            if (!demux->mdatbuffer)
+              demux->mdatoffset = demux->offset;
+          }
+        } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
+          GST_ELEMENT_ERROR (demux, STREAM, DECODE,
+              (_("This file is invalid and cannot be played.")),
+              ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
+                  GST_FOURCC_ARGS (fourcc), size));
+          ret = GST_FLOW_ERROR;
+          break;
+        } else {
+          /* this means we already started buffering and still no moov header,
+           * let's continue buffering everything till we get moov */
+          if (demux->mdatbuffer && (fourcc != FOURCC_moov))
+            goto buffer_data;
+          demux->neededbytes = size;
+          demux->state = QTDEMUX_STATE_HEADER;
+        }
+        break;
+      }
+      case QTDEMUX_STATE_HEADER:{
+        const guint8 *data;
+        guint32 fourcc;
+
+        GST_DEBUG_OBJECT (demux, "In header");
+
+        data = gst_adapter_peek (demux->adapter, demux->neededbytes);
+
+        /* parse the header */
+        extract_initial_length_and_fourcc (data, NULL, &fourcc);
+        if (fourcc == FOURCC_moov) {
+          GST_DEBUG_OBJECT (demux, "Parsing [moov]");
+
+          qtdemux_parse_moov (demux, data, demux->neededbytes);
+          qtdemux_node_dump (demux, demux->moov_node);
+          qtdemux_parse_tree (demux);
+
+          g_node_destroy (demux->moov_node);
+          demux->moov_node = NULL;
+          GST_DEBUG_OBJECT (demux, "Finished parsing the header");
+        } else {
+          GST_WARNING_OBJECT (demux,
+              "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
+              GST_FOURCC_ARGS (fourcc));
+          /* Let's jump that one and go back to initial state */
+        }
+
+        if (demux->mdatbuffer && demux->n_streams) {
+          GstBuffer *buf;
+
+          /* the mdat was before the header */
+          GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
+              demux->n_streams, demux->mdatbuffer);
+          /* restore our adapter/offset view of things with upstream;
+           * put preceding buffered data ahead of current moov data.
+           * This should also handle evil mdat, moov, mdat cases and alike */
+          buf = gst_adapter_take_buffer (demux->adapter,
+              gst_adapter_available (demux->adapter));
+          gst_adapter_clear (demux->adapter);
+          gst_adapter_push (demux->adapter, demux->mdatbuffer);
+          gst_adapter_push (demux->adapter, buf);
+          demux->mdatbuffer = NULL;
+          demux->offset = demux->mdatoffset;
+          demux->neededbytes = next_entry_size (demux);
+          demux->state = QTDEMUX_STATE_MOVIE;
+        } else {
+          GST_DEBUG_OBJECT (demux, "Carrying on normally");
+          gst_adapter_flush (demux->adapter, demux->neededbytes);
+          demux->offset += demux->neededbytes;
+          demux->neededbytes = 16;
+          demux->state = QTDEMUX_STATE_INITIAL;
+        }
+
+        break;
+      }
+      case QTDEMUX_STATE_BUFFER_MDAT:{
+        GstBuffer *buf;
+
+        GST_DEBUG_OBJECT (demux, "Got our buffer at offset %lld",
+            demux->offset);
+        buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
+        GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (QT_FOURCC (GST_BUFFER_DATA (buf) + 4)));
+        if (demux->mdatbuffer)
+          demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);
+        else
+          demux->mdatbuffer = buf;
+        demux->offset += demux->neededbytes;
+        demux->neededbytes = 16;
+        demux->state = QTDEMUX_STATE_INITIAL;
+        gst_qtdemux_post_progress (demux, 1, 1);
+
+        break;
+      }
+      case QTDEMUX_STATE_MOVIE:{
+        GstBuffer *outbuf;
+        QtDemuxStream *stream = NULL;
+        int i = -1;
+
+        GST_DEBUG_OBJECT (demux, "BEGIN // in MOVIE for offset %lld",
+            demux->offset);
+
+        if (demux->todrop) {
+          GST_LOG_OBJECT (demux, "Dropping %d bytes", demux->todrop);
+          gst_adapter_flush (demux->adapter, demux->todrop);
+          demux->neededbytes -= demux->todrop;
+          demux->offset += demux->todrop;
+        }
+
+        /* Figure out which stream this is packet belongs to */
+        for (i = 0; i < demux->n_streams; i++) {
+          stream = demux->streams[i];
+          if (stream->sample_index >= stream->n_samples)
+            continue;
+          GST_LOG_OBJECT (demux,
+              "Checking stream %d (sample_index:%d / offset:%lld / size:%d)",
+              i, stream->sample_index,
+              stream->samples[stream->sample_index].offset,
+              stream->samples[stream->sample_index].size);
+
+          if (stream->samples[stream->sample_index].offset == demux->offset)
+            break;
+        }
+
+        if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
+          goto unknown_stream;
+
+        /* first buffer? */
+        /* initial newsegment sent here after having added pads,
+         * possible others in sink_event */
+        if (G_UNLIKELY (demux->last_ts == GST_CLOCK_TIME_NONE)) {
+          gst_qtdemux_push_event (demux,
+              gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                  0, GST_CLOCK_TIME_NONE, 0));
+        }
+
+        /* Put data in a buffer, set timestamps, caps, ... */
+        outbuf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
+        GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (stream->fourcc));
+
+        g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
+
+        if (stream->samples[stream->sample_index].pts_offset) {
+          demux->last_ts = stream->samples[stream->sample_index].timestamp;
+          GST_BUFFER_TIMESTAMP (outbuf) = demux->last_ts +
+              stream->samples[stream->sample_index].pts_offset;
+        } else {
+          GST_BUFFER_TIMESTAMP (outbuf) =
+              stream->samples[stream->sample_index].timestamp;
+          demux->last_ts = GST_BUFFER_TIMESTAMP (outbuf);
+        }
+        GST_BUFFER_DURATION (outbuf) =
+            stream->samples[stream->sample_index].duration;
+        if (!stream->all_keyframe &&
+            !stream->samples[stream->sample_index].keyframe)
+          GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+
+        /* position reporting */
+        gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
+            demux->last_ts);
+        gst_qtdemux_sync_streams (demux);
+
+        /* send buffer */
+        if (stream->pad) {
+          GST_LOG_OBJECT (demux,
+              "Pushing buffer with time %" GST_TIME_FORMAT " on pad %p",
+              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), stream->pad);
+          gst_buffer_set_caps (outbuf, stream->caps);
+          ret = gst_pad_push (stream->pad, outbuf);
+        } else {
+          gst_buffer_unref (outbuf);
+          ret = GST_FLOW_OK;
+        }
+
+        /* combine flows */
+        ret = gst_qtdemux_combine_flows (demux, stream, ret);
+
+        stream->sample_index++;
+
+        /* update current offset and figure out size of next buffer */
+        GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
+            demux->offset, demux->neededbytes);
+        demux->offset += demux->neededbytes;
+        GST_LOG_OBJECT (demux, "offset is now %lld", demux->offset);
+
+        if ((demux->neededbytes = next_entry_size (demux)) == -1)
+          goto eos;
+        break;
+      }
+      default:
+        goto invalid_state;
+    }
+  }
+
+  /* when buffering movie data, at least show user something is happening */
+  if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
+      gst_adapter_available (demux->adapter) <= demux->neededbytes) {
+    gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
+        demux->neededbytes);
+  }
+done:
+  gst_object_unref (demux);
+
+  return ret;
+
+  /* ERRORS */
+unknown_stream:
+  {
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+eos:
+  {
+    GST_DEBUG_OBJECT (demux, "no next entry, EOS");
+    ret = GST_FLOW_UNEXPECTED;
+    goto done;
+  }
+invalid_state:
+  {
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+        (NULL), ("qtdemuxer invalid state %d", demux->state));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+no_moov:
+  {
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+        (NULL), ("no 'moov' atom withing first 10 MB"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+}
+
+static gboolean
+qtdemux_sink_activate (GstPad * sinkpad)
+{
+  if (gst_pad_check_pull_range (sinkpad))
+    return gst_pad_activate_pull (sinkpad, TRUE);
+  else
+    return gst_pad_activate_push (sinkpad, TRUE);
+}
+
+static gboolean
+qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+  GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
+
+  if (active) {
+    demux->pullbased = TRUE;
+    demux->segment_running = TRUE;
+    return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
+        sinkpad);
+  } else {
+    demux->segment_running = FALSE;
+    return gst_pad_stop_task (sinkpad);
+  }
+}
+
+static gboolean
+qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active)
+{
+  GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
+
+  demux->pullbased = FALSE;
+
+  return TRUE;
+}
+
+#ifdef HAVE_ZLIB
+static void *
+qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
+{
+  return g_malloc (items * size);
+}
+
+static void
+qtdemux_zfree (void *opaque, void *addr)
+{
+  g_free (addr);
+}
+
+static void *
+qtdemux_inflate (void *z_buffer, int z_length, int length)
+{
+  guint8 *buffer;
+  z_stream *z;
+  int ret;
+
+  z = g_new0 (z_stream, 1);
+  z->zalloc = qtdemux_zalloc;
+  z->zfree = qtdemux_zfree;
+  z->opaque = NULL;
+
+  z->next_in = z_buffer;
+  z->avail_in = z_length;
+
+  buffer = (guint8 *) g_malloc (length);
+  ret = inflateInit (z);
+  while (z->avail_in > 0) {
+    if (z->avail_out == 0) {
+      length += 1024;
+      buffer = (guint8 *) g_realloc (buffer, length);
+      z->next_out = buffer + z->total_out;
+      z->avail_out = 1024;
+    }
+    ret = inflate (z, Z_SYNC_FLUSH);
+    if (ret != Z_OK)
+      break;
+  }
+  if (ret != Z_STREAM_END) {
+    g_warning ("inflate() returned %d", ret);
+  }
+
+  g_free (z);
+  return buffer;
+}
+#endif /* HAVE_ZLIB */
+
+static gboolean
+qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, int length)
+{
+  GNode *cmov;
+
+  qtdemux->moov_node = g_node_new ((guint8 *) buffer);
+
+  GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
+  qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
+
+  cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
+  if (cmov) {
+    guint32 method;
+    GNode *dcom;
+    GNode *cmvd;
+
+    dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
+    cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
+    if (dcom == NULL || cmvd == NULL)
+      goto invalid_compression;
+
+    method = QT_FOURCC ((guint8 *) dcom->data + 8);
+    switch (method) {
+#ifdef HAVE_ZLIB
+      case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
+        int uncompressed_length;
+        int compressed_length;
+        guint8 *buf;
+
+        uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
+        compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
+        GST_LOG ("length = %d", uncompressed_length);
+
+        buf =
+            (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
+            compressed_length, uncompressed_length);
+
+        qtdemux->moov_node_compressed = qtdemux->moov_node;
+        qtdemux->moov_node = g_node_new (buf);
+
+        qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
+            uncompressed_length);
+        break;
+      }
+#endif /* HAVE_ZLIB */
+      default:
+        GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
+            "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
+        break;
+    }
+  }
+  return TRUE;
+
+  /* ERRORS */
+invalid_compression:
+  {
+    GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
+    return FALSE;
+  }
+}
+
+static gboolean
+qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
+    const guint8 * end)
+{
+  while (G_UNLIKELY (buf < end)) {
+    GNode *child;
+    guint32 len;
+
+    if (G_UNLIKELY (buf + 4 > end)) {
+      GST_LOG_OBJECT (qtdemux, "buffer overrun");
+      break;
+    }
+    len = QT_UINT32 (buf);
+    if (G_UNLIKELY (len == 0)) {
+      GST_LOG_OBJECT (qtdemux, "empty container");
+      break;
+    }
+    if (G_UNLIKELY (len < 8)) {
+      GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
+      break;
+    }
+    if (G_UNLIKELY (len > (end - buf))) {
+      GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len, end - buf);
+      break;
+    }
+
+    child = g_node_new ((guint8 *) buf);
+    g_node_append (node, child);
+    qtdemux_parse_node (qtdemux, child, buf, len);
+
+    buf += len;
+  }
+  return TRUE;
+}
+
+static gboolean
+qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    GNode * xdxt)
+{
+  int len = QT_UINT32 (xdxt->data);
+  guint8 *buf = xdxt->data;
+  guint8 *end = buf + len;
+  GstBuffer *buffer;
+
+  /* skip size and type */
+  buf += 8;
+  end -= 8;
+
+  while (buf < end) {
+    gint size;
+    guint32 type;
+
+    size = QT_UINT32 (buf);
+    type = QT_FOURCC (buf + 4);
+
+    GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
+
+    if (buf + size > end || size <= 0)
+      break;
+
+    buf += 8;
+    size -= 8;
+
+    GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (type));
+
+    switch (type) {
+      case FOURCC_tCtH:
+        buffer = gst_buffer_new_and_alloc (size);
+        memcpy (GST_BUFFER_DATA (buffer), buf, size);
+        stream->buffers = g_slist_append (stream->buffers, buffer);
+        GST_LOG_OBJECT (qtdemux, "parsing theora header");
+        break;
+      case FOURCC_tCt_:
+        buffer = gst_buffer_new_and_alloc (size);
+        memcpy (GST_BUFFER_DATA (buffer), buf, size);
+        stream->buffers = g_slist_append (stream->buffers, buffer);
+        GST_LOG_OBJECT (qtdemux, "parsing theora comment");
+        break;
+      case FOURCC_tCtC:
+        buffer = gst_buffer_new_and_alloc (size);
+        memcpy (GST_BUFFER_DATA (buffer), buf, size);
+        stream->buffers = g_slist_append (stream->buffers, buffer);
+        GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
+        break;
+      default:
+        GST_WARNING_OBJECT (qtdemux,
+            "unknown theora cookie %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (type));
+        break;
+    }
+    buf += size;
+  }
+  return TRUE;
+}
+
+static gboolean
+qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
+    int length)
+{
+  guint32 fourcc;
+  guint32 node_length;
+  const QtNodeType *type;
+  const guint8 *end;
+
+  GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %d", buffer, length);
+
+  node_length = QT_UINT32 (buffer);
+  fourcc = QT_FOURCC (buffer + 4);
+
+  /* ignore empty nodes */
+  if (G_UNLIKELY (fourcc == 0 || node_length == 8))
+    return TRUE;
+
+  type = qtdemux_type_get (fourcc);
+
+  end = buffer + length;
+
+  GST_LOG_OBJECT (qtdemux,
+      "parsing '%" GST_FOURCC_FORMAT "', length=%d, name '%s'",
+      GST_FOURCC_ARGS (fourcc), node_length, type->name);
+
+  if (type->flags & QT_FLAG_CONTAINER) {
+    qtdemux_parse_container (qtdemux, node, buffer + 8, end);
+  } else {
+    switch (fourcc) {
+      case FOURCC_stsd:
+      {
+        if (node_length < 20) {
+          GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
+          break;
+        }
+        GST_DEBUG_OBJECT (qtdemux,
+            "parsing stsd (sample table, sample description) atom");
+        qtdemux_parse_container (qtdemux, node, buffer + 16, end);
+        break;
+      }
+      case FOURCC_mp4a:
+      {
+        guint32 version;
+        guint32 offset;
+
+        if (length < 20) {
+          /* small boxes are also inside wave inside the mp4a box */
+          GST_LOG_OBJECT (qtdemux, "skipping small mp4a box");
+          break;
+        }
+        version = QT_UINT32 (buffer + 16);
+
+        GST_DEBUG_OBJECT (qtdemux, "mp4a version 0x%08x", version);
+
+        /* parse any esds descriptors */
+        switch (version) {
+          case 0x00000000:
+            offset = 0x24;
+            break;
+          case 0x00010000:
+            offset = 0x34;
+            break;
+          case 0x00020000:
+            offset = 0x58;
+            break;
+          default:
+            GST_WARNING_OBJECT (qtdemux, "unhandled mp4a version 0x%08x",
+                version);
+            offset = 0;
+            break;
+        }
+        if (offset)
+          qtdemux_parse_container (qtdemux, node, buffer + offset, end);
+        break;
+      }
+      case FOURCC_mp4v:
+      {
+        const guint8 *buf;
+        guint32 version;
+        int tlen;
+
+        GST_DEBUG_OBJECT (qtdemux, "parsing in mp4v");
+        version = QT_UINT32 (buffer + 16);
+        GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
+        if (1 || version == 0x00000000) {
+          buf = buffer + 0x32;
+
+          /* FIXME Quicktime uses PASCAL string while
+           * the iso format uses C strings. Check the file
+           * type before attempting to parse the string here. */
+          tlen = QT_UINT8 (buf);
+          GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
+          buf++;
+          GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
+          /* the string has a reserved space of 32 bytes so skip
+           * the remaining 31 */
+          buf += 31;
+          buf += 4;             /* and 4 bytes reserved */
+
+          GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
+
+          qtdemux_parse_container (qtdemux, node, buf, end);
+        }
+        break;
+      }
+      case FOURCC_mjp2:
+      {
+        qtdemux_parse_container (qtdemux, node, buffer + 86, end);
+        break;
+      }
+      case FOURCC_meta:
+      {
+        GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
+        qtdemux_parse_container (qtdemux, node, buffer + 12, end);
+        break;
+      }
+      case FOURCC_XiTh:
+      {
+        guint32 version;
+        guint32 offset;
+
+        version = QT_UINT32 (buffer + 12);
+        GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
+
+        switch (version) {
+          case 0x00000001:
+            offset = 0x62;
+            break;
+          default:
+            GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
+            offset = 0;
+            break;
+        }
+        if (offset)
+          qtdemux_parse_container (qtdemux, node, buffer + offset, end);
+        break;
+      }
+      case FOURCC_in24:
+      {
+        qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
+        break;
+      }
+      default:
+        if (!strcmp (type->name, "unknown"))
+          GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
+        break;
+    }
+  }
+  GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (fourcc));
+  return TRUE;
+}
+
+static GNode *
+qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
+{
+  GNode *child;
+  guint8 *buffer;
+  guint32 child_fourcc;
+
+  for (child = g_node_first_child (node); child;
+      child = g_node_next_sibling (child)) {
+    buffer = (guint8 *) child->data;
+
+    child_fourcc = QT_FOURCC (buffer + 4);
+
+    if (G_UNLIKELY (child_fourcc == fourcc)) {
+      return child;
+    }
+  }
+  return NULL;
+}
+
+static GNode *
+qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
+{
+  GNode *child;
+  guint8 *buffer;
+  guint32 child_fourcc;
+
+  for (child = g_node_next_sibling (node); child;
+      child = g_node_next_sibling (child)) {
+    buffer = (guint8 *) child->data;
+
+    child_fourcc = QT_FOURCC (buffer + 4);
+
+    if (child_fourcc == fourcc) {
+      return child;
+    }
+  }
+  return NULL;
+}
+
+static gboolean
+gst_qtdemux_add_stream (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, GstTagList * list)
+{
+  if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
+    goto too_many_streams;
+
+  if (stream->subtype == FOURCC_vide) {
+    gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
+
+    stream->pad =
+        gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
+    g_free (name);
+
+    /* fps is calculated base on the duration of the first frames since
+     * qt does not have a fixed framerate. */
+    if ((stream->n_samples == 1) && (stream->min_duration == 0)) {
+      /* still frame */
+      stream->fps_n = 0;
+      stream->fps_d = 1;
+    } else {
+      stream->fps_n = stream->timescale;
+      if (stream->min_duration == 0)
+        stream->fps_d = 1;
+      else
+        stream->fps_d = stream->min_duration;
+    }
+
+    if (stream->caps) {
+      gboolean gray;
+      gint depth, palette_count;
+      const guint32 *palette_data = NULL;
+
+      gst_caps_set_simple (stream->caps,
+          "width", G_TYPE_INT, stream->width,
+          "height", G_TYPE_INT, stream->height,
+          "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
+
+      /* iso files:
+       * calculate pixel-aspect-ratio using display width and height */
+      if (qtdemux->major_brand != FOURCC_qt__) {
+        GST_DEBUG_OBJECT (qtdemux,
+            "video size %dx%d, target display size %dx%d", stream->width,
+            stream->height, stream->display_width, stream->display_height);
+
+        if (stream->display_width > 0 && stream->display_height > 0 &&
+            stream->width > 0 && stream->height > 0) {
+          gint n, d;
+
+          /* calculate the pixel aspect ratio using the display and pixel w/h */
+          n = stream->display_width * stream->height;
+          d = stream->display_height * stream->width;
+          if (n != d) {
+            GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
+            gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
+                GST_TYPE_FRACTION, n, d, NULL);
+          }
+        }
+      }
+
+      /* qt file might have pasp atom */
+      if (stream->par_w > 0 && stream->par_h > 0) {
+        GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
+        gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
+            GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
+      }
+
+      depth = stream->bits_per_sample;
+
+      /* more than 32 bits means grayscale */
+      gray = (depth > 32);
+      /* low 32 bits specify the depth  */
+      depth &= 0x1F;
+
+      /* different number of palette entries is determined by depth. */
+      palette_count = 0;
+      if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
+        palette_count = (1 << depth);
+
+      switch (palette_count) {
+        case 0:
+          break;
+        case 2:
+          palette_data = ff_qt_default_palette_2;
+          break;
+        case 4:
+          palette_data = ff_qt_default_palette_4;
+          break;
+        case 16:
+          if (gray)
+            palette_data = ff_qt_grayscale_palette_16;
+          else
+            palette_data = ff_qt_default_palette_16;
+          break;
+        case 256:
+          if (gray)
+            palette_data = ff_qt_grayscale_palette_256;
+          else
+            palette_data = ff_qt_default_palette_256;
+          break;
+        default:
+          GST_ELEMENT_WARNING (qtdemux, STREAM, DECODE,
+              (_("The video in this file might not play correctly.")),
+              ("unsupported palette depth %d", depth));
+          break;
+      }
+      if (palette_data) {
+        GstBuffer *palette;
+
+        /* make sure it's not writable. We leave MALLOCDATA to NULL so that we
+         * don't free any of the buffer data. */
+        palette = gst_buffer_new ();
+        GST_BUFFER_FLAG_SET (palette, GST_BUFFER_FLAG_READONLY);
+        GST_BUFFER_DATA (palette) = (guint8 *) palette_data;
+        GST_BUFFER_SIZE (palette) = sizeof (guint32) * palette_count;
+
+        gst_caps_set_simple (stream->caps, "palette_data",
+            GST_TYPE_BUFFER, palette, NULL);
+        gst_buffer_unref (palette);
+      } else if (palette_count != 0) {
+        GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
+            (NULL), ("Unsupported palette depth %d. Ignoring stream.", depth));
+
+        gst_object_unref (stream->pad);
+        stream->pad = NULL;
+      }
+    }
+    qtdemux->n_video_streams++;
+  } else if (stream->subtype == FOURCC_soun) {
+    gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
+
+    stream->pad =
+        gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
+    g_free (name);
+    if (stream->caps) {
+      gst_caps_set_simple (stream->caps,
+          "rate", G_TYPE_INT, (int) stream->rate,
+          "channels", G_TYPE_INT, stream->n_channels, NULL);
+    }
+    qtdemux->n_audio_streams++;
+  } else if (stream->subtype == FOURCC_strm) {
+    GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
+  } else if (stream->subtype == FOURCC_subp) {
+    gchar *name = g_strdup_printf ("subp_%02d", qtdemux->n_subp_streams);
+
+    stream->pad =
+        gst_pad_new_from_static_template (&gst_qtdemux_subpsrc_template, name);
+    g_free (name);
+    qtdemux->n_subp_streams++;
+  } else {
+    GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
+    goto done;
+  }
+
+  qtdemux->streams[qtdemux->n_streams] = stream;
+  qtdemux->n_streams++;
+  GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
+
+  if (stream->pad) {
+    GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
+
+    gst_pad_use_fixed_caps (stream->pad);
+    gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
+    gst_pad_set_query_type_function (stream->pad,
+        gst_qtdemux_get_src_query_types);
+    gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
+
+    GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
+    gst_pad_set_caps (stream->pad, stream->caps);
+
+    GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
+        GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
+    gst_pad_set_active (stream->pad, TRUE);
+    gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
+    if (list)
+      gst_element_found_tags_for_pad (GST_ELEMENT_CAST (qtdemux), stream->pad,
+          list);
+  }
+done:
+  return TRUE;
+
+too_many_streams:
+  {
+    GST_ELEMENT_WARNING (qtdemux, STREAM, DECODE,
+        (_("This file contains too many streams. Only playing first %d"),
+            GST_QTDEMUX_MAX_STREAMS), (NULL));
+    return TRUE;
+  }
+}
+
+/* collect all samples for @stream by reading the info from @stbl
+ */
+static gboolean
+qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    GNode * stbl)
+{
+  GNode *stsc;
+  GNode *stsz;
+  GNode *stco;
+  GNode *co64;
+  GNode *stts;
+  GNode *stss;
+  GNode *stps;
+  GNode *ctts;
+  const guint8 *stsc_data, *stsz_data, *stco_data, *co64_data, *stts_data;
+  int sample_size;
+  int sample_index;
+  int n_samples;
+  int n_samples_per_chunk;
+  int n_sample_times;
+  QtDemuxSample *samples;
+  gint i, j, k;
+  int index;
+  guint64 timestamp, time;
+
+  /* sample to chunk */
+  if (!(stsc = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsc)))
+    goto corrupt_file;
+  stsc_data = (const guint8 *) stsc->data;
+
+  /* sample size */
+  if (!(stsz = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsz)))
+    goto corrupt_file;
+  stsz_data = (const guint8 *) stsz->data;
+
+  /* chunk offsets */
+  stco = qtdemux_tree_get_child_by_type (stbl, FOURCC_stco);
+  co64 = qtdemux_tree_get_child_by_type (stbl, FOURCC_co64);
+  if (stco) {
+    stco_data = (const guint8 *) stco->data;
+    co64_data = NULL;
+  } else {
+    stco_data = NULL;
+    if (co64 == NULL)
+      goto corrupt_file;
+    co64_data = (const guint8 *) co64->data;
+  }
+  /* sample time */
+  if (!(stts = qtdemux_tree_get_child_by_type (stbl, FOURCC_stts)))
+    goto corrupt_file;
+  stts_data = (const guint8 *) stts->data;
+
+  sample_size = QT_UINT32 (stsz_data + 12);
+  if (sample_size == 0 || stream->sampled) {
+    n_samples = QT_UINT32 (stsz_data + 16);
+
+    if (n_samples == 0)
+      goto no_samples;
+    else if (n_samples < 0)
+      goto corrupt_file;
+
+    GST_DEBUG_OBJECT (qtdemux, "stsz sample_size 0, allocating n_samples %d",
+        n_samples);
+
+    samples = g_try_new0 (QtDemuxSample, n_samples);
+    if (samples == NULL)
+      goto out_of_memory;
+
+    stream->n_samples = n_samples;
+    stream->samples = samples;
+
+    /* set the sample sizes */
+    if (sample_size == 0) {
+      const guint8 *stsz_p = stsz_data + 20;
+      /* different sizes for each sample */
+      for (i = 0; i < n_samples; i++) {
+        samples[i].size = QT_UINT32 (stsz_p);
+        GST_LOG_OBJECT (qtdemux, "sample %d has size %d", i, samples[i].size);
+        stsz_p += 4;
+      }
+    } else {
+      /* samples have the same size */
+      GST_LOG_OBJECT (qtdemux, "all samples have size %d", sample_size);
+      for (i = 0; i < n_samples; i++)
+        samples[i].size = sample_size;
+    }
+
+    /* set the sample offsets in the file */
+    n_samples_per_chunk = QT_UINT32 (stsc_data + 12);
+    index = 0;
+    for (i = 0; i < n_samples_per_chunk; i++) {
+      guint32 first_chunk, last_chunk;
+      guint32 samples_per_chunk;
+
+      first_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 0) - 1;
+      if (G_UNLIKELY (i == n_samples_per_chunk - 1)) {
+        last_chunk = G_MAXUINT32;
+      } else {
+        last_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 12) - 1;
+      }
+      samples_per_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 4);
+
+      for (j = first_chunk; j < last_chunk; j++) {
+        guint64 chunk_offset;
+
+        if (stco) {
+          chunk_offset = QT_UINT32 (stco_data + 16 + j * 4);
+        } else {
+          chunk_offset = QT_UINT64 (co64_data + 16 + j * 8);
+        }
+        for (k = 0; k < samples_per_chunk; k++) {
+          GST_LOG_OBJECT (qtdemux, "Creating entry %d with offset %lld",
+              index, chunk_offset);
+          samples[index].offset = chunk_offset;
+          chunk_offset += samples[index].size;
+          index++;
+          if (G_UNLIKELY (index >= n_samples))
+            goto done2;
+        }
+      }
+    }
+  done2:
+
+    n_sample_times = QT_UINT32 (stts_data + 12);
+    GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", n_sample_times);
+    timestamp = 0;
+    stream->min_duration = 0;
+    time = 0;
+    index = 0;
+    stts_data += 16;
+    for (i = 0; i < n_sample_times; i++) {
+      guint32 n;
+      guint32 duration;
+
+      n = QT_UINT32 (stts_data);
+      stts_data += 4;
+      duration = QT_UINT32 (stts_data);
+      stts_data += 4;
+      GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u ", i, n,
+          duration);
+
+      /* take first duration for fps */
+      if (G_UNLIKELY (stream->min_duration == 0))
+        stream->min_duration = duration;
+
+      for (j = 0; j < n; j++) {
+        GST_DEBUG_OBJECT (qtdemux,
+            "sample %d: index %d, timestamp %" GST_TIME_FORMAT, index, j,
+            GST_TIME_ARGS (timestamp));
+
+        samples[index].timestamp = timestamp;
+        /* add non-scaled values to avoid rounding errors */
+        time += duration;
+        timestamp = gst_util_uint64_scale (time, GST_SECOND, stream->timescale);
+        samples[index].duration = timestamp - samples[index].timestamp;
+
+        index++;
+        if (G_UNLIKELY (index >= n_samples))
+          goto done3;
+      }
+    }
+    /* fill up empty timestamps with the last timestamp, this can happen when
+     * the last samples do not decode and so we don't have timestamps for them.
+     * We however look at the last timestamp to estimate the track length so we
+     * need something in here. */
+    for (; index < n_samples; index++) {
+      GST_DEBUG_OBJECT (qtdemux, "fill sample %d: timestamp %" GST_TIME_FORMAT,
+          index, GST_TIME_ARGS (timestamp));
+      samples[index].timestamp = timestamp;
+      samples[index].duration = -1;
+    }
+  done3:
+
+    /* sample sync, can be NULL */
+    stss = qtdemux_tree_get_child_by_type (stbl, FOURCC_stss);
+
+    if (stss) {
+      /* mark keyframes */
+      guint32 n_sample_syncs;
+      const guint8 *stss_p = (guint8 *) stss->data;
+
+      stss_p += 12;
+      n_sample_syncs = QT_UINT32 (stss_p);
+      if (n_sample_syncs == 0) {
+        stream->all_keyframe = TRUE;
+      } else {
+        for (i = 0; i < n_sample_syncs; i++) {
+          stss_p += 4;
+          /* note that the first sample is index 1, not 0 */
+          index = QT_UINT32 (stss_p);
+          if (G_LIKELY (index > 0 && index <= n_samples))
+            samples[index - 1].keyframe = TRUE;
+        }
+      }
+      stps = qtdemux_tree_get_child_by_type (stbl, FOURCC_stps);
+      if (stps) {
+        /* stps marks partial sync frames like open GOP I-Frames */
+        guint32 n_sample_syncs;
+        const guint8 *stps_p = (guint8 *) stps->data;
+
+        stps_p += 12;
+        n_sample_syncs = QT_UINT32 (stps_p);
+        if (n_sample_syncs != 0) {
+          /* no entries, the stss table contains the real sync
+           * samples */
+        } else {
+          for (i = 0; i < n_sample_syncs; i++) {
+            stps_p += 4;
+            /* note that the first sample is index 1, not 0 */
+            index = QT_UINT32 (stps_p);
+            if (G_LIKELY (index > 0 && index <= n_samples))
+              samples[index - 1].keyframe = TRUE;
+          }
+        }
+      }
+    } else {
+      /* no stss, all samples are keyframes */
+      stream->all_keyframe = TRUE;
+    }
+  } else {
+    GST_DEBUG_OBJECT (qtdemux,
+        "stsz sample_size %d != 0, treating chunks as samples", sample_size);
+    /* treat chunks as samples */
+    if (stco) {
+      n_samples = QT_UINT32 (stco_data + 12);
+    } else {
+      n_samples = QT_UINT32 (co64_data + 12);
+    }
+
+    if (n_samples == 0)
+      goto no_samples;
+    else if (n_samples < 0)
+      goto corrupt_file;
+
+    GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %d", n_samples);
+
+    samples = g_try_new0 (QtDemuxSample, n_samples);
+    if (samples == NULL)
+      goto out_of_memory;
+
+    stream->n_samples = n_samples;
+    stream->samples = samples;
+
+    n_samples_per_chunk = QT_UINT32 (stsc_data + 12);
+    GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %d", n_samples_per_chunk);
+    sample_index = 0;
+    timestamp = 0;
+    for (i = 0; i < n_samples_per_chunk; i++) {
+      guint32 first_chunk, last_chunk;
+      guint32 samples_per_chunk;
+
+      first_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 0) - 1;
+      /* the last chunk of each entry is calculated by taking the first chunk
+       * of the next entry; except if there is no next, where we fake it with
+       * INT_MAX */
+      if (i == n_samples_per_chunk - 1) {
+        last_chunk = G_MAXUINT32;
+      } else {
+        last_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 12) - 1;
+      }
+      samples_per_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 4);
+
+      GST_LOG_OBJECT (qtdemux,
+          "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
+          first_chunk, last_chunk, samples_per_chunk);
+
+      for (j = first_chunk; j < last_chunk; j++) {
+        guint64 chunk_offset;
+
+        if (j >= n_samples)
+          goto done;
+
+        if (stco) {
+          chunk_offset = QT_UINT32 (stco_data + 16 + j * 4);
+        } else {
+          chunk_offset = QT_UINT64 (co64_data + 16 + j * 8);
+        }
+        GST_LOG_OBJECT (qtdemux,
+            "Creating entry %d with offset %" G_GUINT64_FORMAT, j,
+            chunk_offset);
+
+        samples[j].offset = chunk_offset;
+
+        if (stream->samples_per_frame * stream->bytes_per_frame) {
+          samples[j].size = (samples_per_chunk * stream->n_channels) /
+              stream->samples_per_frame * stream->bytes_per_frame;
+        } else {
+          samples[j].size = samples_per_chunk;
+        }
+
+        GST_DEBUG_OBJECT (qtdemux, "sample %d: timestamp %" GST_TIME_FORMAT
+            ", size %u", j, GST_TIME_ARGS (timestamp), samples[j].size);
+
+        samples[j].timestamp = timestamp;
+        sample_index += samples_per_chunk;
+
+        timestamp = gst_util_uint64_scale (sample_index,
+            GST_SECOND, stream->timescale);
+        samples[j].duration = timestamp - samples[j].timestamp;
+
+        samples[j].keyframe = TRUE;
+      }
+    }
+  }
+
+  /* composition time to sample */
+  if ((ctts = qtdemux_tree_get_child_by_type (stbl, FOURCC_ctts))) {
+    const guint8 *ctts_data, *ctts_p;
+    guint32 n_entries;
+    guint32 count;
+    gint32 soffset;
+
+    ctts_data = (const guint8 *) ctts->data;
+    n_entries = QT_UINT32 (ctts_data + 12);
+
+    /* Fill in the pts_offsets */
+    index = 0;
+    ctts_p = ctts_data + 16;
+    /* FIXME: make sure we don't read beyond the atom size/boundary */
+    for (i = 0; i < n_entries; i++) {
+      count = QT_UINT32 (ctts_p);
+      ctts_p += 4;
+      soffset = QT_UINT32 (ctts_p);
+      ctts_p += 4;
+      for (j = 0; j < count; j++) {
+        /* we operate with very small soffset values here, it shouldn't overflow */
+        samples[index].pts_offset = soffset * GST_SECOND / stream->timescale;
+        index++;
+        if (G_UNLIKELY (index >= n_samples))
+          goto done;
+      }
+    }
+  }
+done:
+  return TRUE;
+
+/* ERRORS */
+corrupt_file:
+  {
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+        (_("This file is corrupt and cannot be played.")), (NULL));
+    return FALSE;
+  }
+no_samples:
+  {
+    GST_WARNING_OBJECT (qtdemux, "stream has no samples");
+    return FALSE;
+  }
+out_of_memory:
+  {
+    GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples", n_samples);
+    return FALSE;
+  }
+}
+
+/* collect all segment info for @stream.
+ */
+static gboolean
+qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    GNode * trak)
+{
+  GNode *edts;
+
+  /* parse and prepare segment info from the edit list */
+  GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
+  stream->n_segments = 0;
+  stream->segments = NULL;
+  if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
+    GNode *elst;
+    gint n_segments;
+    gint i, count;
+    guint64 time, stime;
+    guint8 *buffer;
+
+    GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
+    if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
+      goto done;
+
+    buffer = elst->data;
+
+    n_segments = QT_UINT32 (buffer + 12);
+
+    /* we might allocate a bit too much, at least allocate 1 segment */
+    stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
+
+    /* segments always start from 0 */
+    time = 0;
+    stime = 0;
+    count = 0;
+    for (i = 0; i < n_segments; i++) {
+      guint64 duration;
+      guint64 media_time;
+      QtDemuxSegment *segment;
+      guint32 rate_int;
+
+      media_time = QT_UINT32 (buffer + 20 + i * 12);
+
+      /* -1 media time is an empty segment, just ignore it */
+      if (media_time == G_MAXUINT32)
+        continue;
+
+      duration = QT_UINT32 (buffer + 16 + i * 12);
+
+      segment = &stream->segments[count++];
+
+      /* time and duration expressed in global timescale */
+      segment->time = stime;
+      /* add non scaled values so we don't cause roundoff errors */
+      time += duration;
+      stime = gst_util_uint64_scale (time, GST_SECOND, qtdemux->timescale);
+      segment->stop_time = stime;
+      segment->duration = stime - segment->time;
+      /* media_time expressed in stream timescale */
+      segment->media_start =
+          gst_util_uint64_scale (media_time, GST_SECOND, stream->timescale);
+      segment->media_stop = segment->media_start + segment->duration;
+      rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
+
+      if (rate_int <= 1) {
+        /* 0 is not allowed, some programs write 1 instead of the floating point
+         * value */
+        GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
+            rate_int);
+        segment->rate = 1;
+      } else {
+        segment->rate = rate_int / 65536.0;
+      }
+
+      GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
+          ", duration %" GST_TIME_FORMAT ", media_time %" GST_TIME_FORMAT
+          ", rate %g, (%d)", i, GST_TIME_ARGS (segment->time),
+          GST_TIME_ARGS (segment->duration),
+          GST_TIME_ARGS (segment->media_start), segment->rate, rate_int);
+    }
+    GST_DEBUG_OBJECT (qtdemux, "found %d non-empty segments", count);
+    stream->n_segments = count;
+  }
+done:
+
+  /* push based does not handle segments, so act accordingly here,
+   * and warn if applicable */
+  if (!qtdemux->pullbased) {
+    GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
+    /* remove and use default one below, we stream like it anyway */
+    g_free (stream->segments);
+    stream->segments = NULL;
+    stream->n_segments = 0;
+  }
+
+  /* no segments, create one to play the complete trak */
+  if (stream->n_segments == 0) {
+    GstClockTime stream_duration = 0;
+
+    if (stream->segments == NULL)
+      stream->segments = g_new (QtDemuxSegment, 1);
+
+    /* samples know best */
+    if (stream->n_samples > 0) {
+      stream_duration =
+          stream->samples[stream->n_samples - 1].timestamp +
+          stream->samples[stream->n_samples - 1].pts_offset +
+          stream->samples[stream->n_samples - 1].duration;
+    }
+
+    stream->segments[0].time = 0;
+    stream->segments[0].stop_time = stream_duration;
+    stream->segments[0].duration = stream_duration;
+    stream->segments[0].media_start = 0;
+    stream->segments[0].media_stop = stream_duration;
+    stream->segments[0].rate = 1.0;
+
+    GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (stream_duration));
+    stream->n_segments = 1;
+  }
+  GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
+
+  return TRUE;
+}
+
+/* parse the traks.
+ * With each track we associate a new QtDemuxStream that contains all the info
+ * about the trak.
+ * traks that do not decode to something (like strm traks) will not have a pad.
+ */
+static gboolean
+qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
+{
+  int offset;
+  GNode *tkhd;
+  GNode *mdia;
+  GNode *mdhd;
+  GNode *hdlr;
+  GNode *minf;
+  GNode *stbl;
+  GNode *stsd;
+  GNode *mp4a;
+  GNode *mp4v;
+  GNode *wave;
+  GNode *esds;
+  GNode *pasp;
+  QtDemuxStream *stream;
+  GstTagList *list = NULL;
+  gchar *codec = NULL;
+  const guint8 *stsd_data;
+  guint32 version;
+
+  stream = g_new0 (QtDemuxStream, 1);
+  /* new streams always need a discont */
+  stream->discont = TRUE;
+  /* we enable clipping for raw audio/video streams */
+  stream->need_clip = FALSE;
+  stream->segment_index = -1;
+  stream->time_position = 0;
+  stream->sample_index = -1;
+  stream->last_ret = GST_FLOW_OK;
+
+  if (!(tkhd = qtdemux_tree_get_child_by_type (trak, FOURCC_tkhd)))
+    goto corrupt_file;
+
+  GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags: 0x%08x",
+      QT_UINT32 ((guint8 *) tkhd->data + 8));
+
+  if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
+    goto corrupt_file;
+
+  if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
+    /* be nice for some crooked mjp2 files that use mhdr for mdhd */
+    if (qtdemux->major_brand != FOURCC_mjp2 ||
+        !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
+      goto corrupt_file;
+  }
+
+  version = QT_UINT32 ((guint8 *) mdhd->data + 8);
+  GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
+  if (version == 0x01000000) {
+    stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
+    stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
+  } else {
+    stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
+    stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
+  }
+
+  GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
+      stream->timescale);
+  GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
+      stream->duration);
+
+  if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
+    goto corrupt_file;
+
+  if (qtdemux->duration != G_MAXINT32 && stream->duration != G_MAXINT32) {
+    guint64 tdur1, tdur2;
+
+    /* don't overflow */
+    tdur1 = stream->timescale * (guint64) qtdemux->duration;
+    tdur2 = qtdemux->timescale * (guint64) stream->duration;
+
+    /* HACK:
+     * some of those trailers, nowadays, have prologue images that are
+     * themselves vide tracks as well. I haven't really found a way to
+     * identify those yet, except for just looking at their duration. */
+    if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
+      GST_WARNING_OBJECT (qtdemux,
+          "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
+          " vs. %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
+          "found, assuming preview image or something; skipping track",
+          stream->duration, stream->timescale, qtdemux->duration,
+          qtdemux->timescale);
+      g_free (stream);
+      return TRUE;
+    }
+  }
+
+  if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
+    goto corrupt_file;
+
+  GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
+
+  stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
+  GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (stream->subtype));
+
+  if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
+    goto corrupt_file;
+
+  if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
+    goto corrupt_file;
+
+  /* parse stsd */
+  if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
+    goto corrupt_file;
+  stsd_data = (const guint8 *) stsd->data;
+
+  if (stream->subtype == FOURCC_vide) {
+    guint32 fourcc;
+    const guint8 *tkhd_data = (const guint8 *) tkhd->data;
+
+    stream->sampled = TRUE;
+
+    /* version 1 uses some 64-bit ints */
+    offset = (QT_UINT8 (tkhd_data + 8) == 1) ? 96 : 84;
+    stream->display_width = (guint) QT_FP32 (tkhd_data + offset);
+    stream->display_height = (guint) QT_FP32 (tkhd_data + offset + 4);
+
+    offset = 16;
+    stream->fourcc = fourcc = QT_FOURCC (stsd_data + offset + 4);
+    GST_LOG_OBJECT (qtdemux, "st type:          %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (fourcc));
+
+    stream->width = QT_UINT16 (stsd_data + offset + 32);
+    stream->height = QT_UINT16 (stsd_data + offset + 34);
+    stream->fps_n = 0;          /* this is filled in later */
+    stream->fps_d = 0;          /* this is filled in later */
+    stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
+    stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
+
+    GST_LOG_OBJECT (qtdemux, "frame count:   %u",
+        QT_UINT16 (stsd_data + offset + 48));
+
+    if (fourcc == FOURCC_drms)
+      goto error_encrypted;
+
+    stream->caps =
+        qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+    if (codec) {
+      list = gst_tag_list_new ();
+      gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+          GST_TAG_VIDEO_CODEC, codec, NULL);
+      g_free (codec);
+      codec = NULL;
+    }
+
+    esds = NULL;
+    pasp = NULL;
+    mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4v);
+    if (mp4v) {
+      esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
+      pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
+    }
+
+    if (pasp) {
+      const guint8 *pasp_data = (const guint8 *) pasp->data;
+
+      stream->par_w = QT_UINT32 (pasp_data + 8);
+      stream->par_h = QT_UINT32 (pasp_data + 12);
+    } else {
+      stream->par_w = 0;
+      stream->par_h = 0;
+    }
+
+    if (esds) {
+      gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
+    } else {
+      switch (fourcc) {
+        case FOURCC_avc1:
+        {
+          gint len = QT_UINT32 (stsd_data) - 0x66;
+          const guint8 *avc_data = stsd_data + 0x66;
+
+          /* find avcC */
+          while (len >= 0x8 &&
+              QT_FOURCC (avc_data + 0x4) != FOURCC_avcC &&
+              QT_UINT32 (avc_data) < len) {
+            len -= QT_UINT32 (avc_data);
+            avc_data += QT_UINT32 (avc_data);
+          }
+
+          /* parse, if found */
+          if (len > 0x8 && QT_FOURCC (avc_data + 0x4) == FOURCC_avcC) {
+            GstBuffer *buf;
+            gint size;
+
+            if (QT_UINT32 (avc_data) < len)
+              size = QT_UINT32 (avc_data) - 0x8;
+            else
+              size = len - 0x8;
+
+            GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
+
+            buf = gst_buffer_new_and_alloc (size);
+            memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
+            gst_caps_set_simple (stream->caps,
+                "codec_data", GST_TYPE_BUFFER, buf, NULL);
+            gst_buffer_unref (buf);
+          }
+          break;
+        }
+        case FOURCC_mjp2:
+        {
+          GNode *jp2h, *colr, *mjp2, *field, *prefix;
+          const guint8 *data;
+          guint32 fourcc = 0;
+
+          GST_DEBUG_OBJECT (qtdemux, "found mjp2");
+          /* some required atoms */
+          mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
+          if (!mjp2)
+            break;
+          jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
+          if (!jp2h)
+            break;
+          colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
+          if (!colr)
+            break;
+          GST_DEBUG_OBJECT (qtdemux, "found colr");
+          /* try to extract colour space info */
+          if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
+            switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
+              case 16:
+                fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
+                break;
+              case 17:
+                fourcc = GST_MAKE_FOURCC ('G', 'R', 'A', 'Y');
+                break;
+              case 18:
+                fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
+                break;
+              default:
+                break;
+            }
+          }
+
+          if (fourcc)
+            gst_caps_set_simple (stream->caps,
+                "fourcc", GST_TYPE_FOURCC, fourcc, NULL);
+
+          /* some optional atoms */
+          field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
+          prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
+
+          /* indicate possible fields in caps */
+          if (field) {
+            data = (guint8 *) field->data + 8;
+            if (*data != 1)
+              gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
+                  (gint) * data, NULL);
+          }
+          /* add codec_data if provided */
+          if (prefix) {
+            GstBuffer *buf;
+            gint len;
+
+            GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
+            data = prefix->data;
+            len = QT_UINT32 (data);
+            if (len > 0x8) {
+              len -= 0x8;
+              buf = gst_buffer_new_and_alloc (len);
+              memcpy (GST_BUFFER_DATA (buf), data + 8, len);
+              gst_caps_set_simple (stream->caps,
+                  "codec_data", GST_TYPE_BUFFER, buf, NULL);
+              gst_buffer_unref (buf);
+            }
+          }
+          break;
+        }
+        case FOURCC_SVQ3:
+        case FOURCC_VP31:
+        {
+          GstBuffer *buf;
+          gint len = QT_UINT32 (stsd_data);
+
+          GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
+
+          buf = gst_buffer_new_and_alloc (len);
+          memcpy (GST_BUFFER_DATA (buf), stsd_data, len);
+          gst_caps_set_simple (stream->caps,
+              "codec_data", GST_TYPE_BUFFER, buf, NULL);
+          gst_buffer_unref (buf);
+          break;
+        }
+        case FOURCC_rle_:
+        {
+          gst_caps_set_simple (stream->caps,
+              "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
+          break;
+        }
+        case FOURCC_XiTh:
+        {
+          GNode *xith, *xdxt;
+
+          GST_DEBUG_OBJECT (qtdemux, "found XiTh");
+          xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
+          if (!xith)
+            break;
+
+          xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
+          if (!xdxt)
+            break;
+
+          GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
+          /* collect the headers and store them in a stream list so that we can
+           * send them out first */
+          qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
+          break;
+        }
+        default:
+          break;
+      }
+    }
+
+    GST_INFO_OBJECT (qtdemux,
+        "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
+        GST_FOURCC_ARGS (fourcc), stream->caps);
+
+  } else if (stream->subtype == FOURCC_soun) {
+    int version, samplesize;
+    guint32 fourcc;
+    int len;
+    guint16 compression_id;
+
+    len = QT_UINT32 (stsd_data + 16);
+    GST_LOG_OBJECT (qtdemux, "stsd len:           %d", len);
+
+    stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
+    GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (stream->fourcc));
+
+    offset = 32;
+
+    version = QT_UINT32 (stsd_data + offset);
+    stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
+    samplesize = QT_UINT16 (stsd_data + offset + 10);
+    compression_id = QT_UINT16 (stsd_data + offset + 12);
+    stream->rate = QT_FP32 (stsd_data + offset + 16);
+
+    GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
+    GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
+        QT_UINT32 (stsd_data + offset + 4));
+    GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
+    GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
+    GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
+    GST_LOG_OBJECT (qtdemux, "packet size:      %d",
+        QT_UINT16 (stsd_data + offset + 14));
+    GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
+
+    if (compression_id == 0xfffe)
+      stream->sampled = TRUE;
+
+    /* first assume uncompressed audio */
+    stream->bytes_per_sample = samplesize / 8;
+    stream->samples_per_frame = stream->n_channels;
+    stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
+    stream->samples_per_packet = stream->samples_per_frame;
+    stream->bytes_per_packet = stream->bytes_per_sample;
+
+    offset = 52;
+    switch (fourcc) {
+        /* Yes, these have to be hard-coded */
+      case FOURCC_MAC6:
+      {
+        stream->samples_per_packet = 6;
+        stream->bytes_per_packet = 1;
+        stream->bytes_per_frame = 1 * stream->n_channels;
+        stream->bytes_per_sample = 1;
+        stream->samples_per_frame = 6 * stream->n_channels;
+        break;
+      }
+      case FOURCC_MAC3:
+      {
+        stream->samples_per_packet = 3;
+        stream->bytes_per_packet = 1;
+        stream->bytes_per_frame = 1 * stream->n_channels;
+        stream->bytes_per_sample = 1;
+        stream->samples_per_frame = 3 * stream->n_channels;
+        break;
+      }
+      case FOURCC_ima4:
+      {
+        stream->samples_per_packet = 64;
+        stream->bytes_per_packet = 34;
+        stream->bytes_per_frame = 34 * stream->n_channels;
+        stream->bytes_per_sample = 2;
+        stream->samples_per_frame = 64 * stream->n_channels;
+        break;
+      }
+      case FOURCC_ulaw:
+      case FOURCC_alaw:
+      {
+        stream->samples_per_packet = 1;
+        stream->bytes_per_packet = 1;
+        stream->bytes_per_frame = 1 * stream->n_channels;
+        stream->bytes_per_sample = 1;
+        stream->samples_per_frame = 1 * stream->n_channels;
+        break;
+      }
+      case FOURCC_agsm:
+      {
+        stream->samples_per_packet = 160;
+        stream->bytes_per_packet = 33;
+        stream->bytes_per_frame = 33 * stream->n_channels;
+        stream->bytes_per_sample = 2;
+        stream->samples_per_frame = 160 * stream->n_channels;
+        break;
+      }
+      default:
+        break;
+    }
+
+    if (version == 0x00010000) {
+      switch (fourcc) {
+        case FOURCC_twos:
+        case FOURCC_sowt:
+        case FOURCC_raw_:
+          break;
+        default:
+        {
+          /* only parse extra decoding config for non-pcm audio */
+          stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
+          stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
+          stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
+          stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
+
+          GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
+              stream->samples_per_packet);
+          GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
+              stream->bytes_per_packet);
+          GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
+              stream->bytes_per_frame);
+          GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
+              stream->bytes_per_sample);
+
+          if (!stream->sampled && stream->bytes_per_packet) {
+            stream->samples_per_frame = (stream->bytes_per_frame /
+                stream->bytes_per_packet) * stream->samples_per_packet;
+            GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
+                stream->samples_per_frame);
+          }
+          break;
+        }
+      }
+    } else if (version == 0x00020000) {
+      union
+      {
+        gdouble fp;
+        guint64 val;
+      } qtfp;
+
+      stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
+      qtfp.val = QT_UINT64 (stsd_data + offset + 4);
+      stream->rate = qtfp.fp;
+      stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
+
+      GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
+          stream->samples_per_packet);
+      GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
+      GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
+
+    } else {
+      GST_WARNING_OBJECT (qtdemux, "unknown version %08x", version);
+    }
+
+    if (fourcc == FOURCC_drms)
+      goto error_encrypted;
+
+    stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc, NULL, 0,
+        &codec);
+
+    switch (fourcc) {
+      case FOURCC_in24:
+      {
+        GNode *enda;
+        GNode *in24;
+
+        in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
+
+        enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
+        if (!enda) {
+          wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
+          if (wave)
+            enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
+        }
+        if (enda) {
+          gst_caps_set_simple (stream->caps,
+              "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
+        }
+        break;
+      }
+      default:
+        break;
+    }
+
+    if (codec) {
+      list = gst_tag_list_new ();
+      gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+          GST_TAG_AUDIO_CODEC, codec, NULL);
+      g_free (codec);
+      codec = NULL;
+    }
+
+    mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
+    wave = NULL;
+    esds = NULL;
+    if (mp4a) {
+      wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
+      if (wave)
+        esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
+      if (!esds)
+        esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
+    }
+
+    if (esds) {
+      gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
+    } else {
+      switch (fourcc) {
+#if 0
+          /* FIXME: what is in the chunk? */
+        case FOURCC_QDMC:
+        {
+          gint len = QT_UINT32 (stsd_data);
+
+          /* seems to be always = 116 = 0x74 */
+          break;
+        }
+#endif
+        case FOURCC_QDM2:
+        {
+          gint len = QT_UINT32 (stsd_data);
+
+          if (len > 0x4C) {
+            GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
+
+            memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x4C, len - 0x4C);
+            gst_caps_set_simple (stream->caps,
+                "codec_data", GST_TYPE_BUFFER, buf, NULL);
+            gst_buffer_unref (buf);
+          }
+          gst_caps_set_simple (stream->caps,
+              "samplesize", G_TYPE_INT, samplesize, NULL);
+          break;
+        }
+        case FOURCC_alac:
+        {
+          gint len = QT_UINT32 (stsd_data);
+
+          if (len > 0x34) {
+            GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
+
+            memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
+            gst_caps_set_simple (stream->caps,
+                "codec_data", GST_TYPE_BUFFER, buf, NULL);
+            gst_buffer_unref (buf);
+          }
+          gst_caps_set_simple (stream->caps,
+              "samplesize", G_TYPE_INT, samplesize, NULL);
+          break;
+        }
+        case FOURCC_samr:
+        {
+          gint len = QT_UINT32 (stsd_data);
+
+          if (len > 0x34) {
+            GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
+
+            memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
+
+            gst_caps_set_simple (stream->caps,
+                "codec_data", GST_TYPE_BUFFER, buf, NULL);
+            gst_buffer_unref (buf);
+          }
+          break;
+        }
+        default:
+          break;
+      }
+    }
+    GST_INFO_OBJECT (qtdemux,
+        "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
+        GST_FOURCC_ARGS (fourcc), stream->caps);
+
+  } else if (stream->subtype == FOURCC_strm) {
+    guint32 fourcc;
+
+    stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
+    GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (fourcc));
+
+    if (fourcc != FOURCC_rtsp) {
+      GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (fourcc));
+      goto unknown_stream;
+    }
+    stream->sampled = TRUE;
+  } else if (stream->subtype == FOURCC_subp) {
+    guint32 fourcc;
+
+    stream->sampled = TRUE;
+
+    offset = 16;
+    stream->fourcc = fourcc = QT_FOURCC (stsd_data + offset + 4);
+    GST_LOG_OBJECT (qtdemux, "st type:          %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (fourcc));
+
+    stream->caps =
+        qtdemux_subp_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+  } else {
+    goto unknown_stream;
+  }
+
+  /* promote to sampled format */
+  if (stream->fourcc == FOURCC_samr) {
+    /* force mono 8000 Hz for AMR */
+    stream->sampled = TRUE;
+    stream->n_channels = 1;
+    stream->rate = 8000;
+  } else if (stream->fourcc == FOURCC_sawb) {
+    /* force mono 16000 Hz for AMR-WB */
+    stream->sampled = TRUE;
+    stream->n_channels = 1;
+    stream->rate = 16000;
+  } else if (stream->fourcc == FOURCC_mp4a) {
+    stream->sampled = TRUE;
+  }
+
+  /* collect sample information */
+  if (!qtdemux_parse_samples (qtdemux, stream, stbl))
+    goto samples_failed;
+
+  /* configure segments */
+  if (!qtdemux_parse_segments (qtdemux, stream, trak))
+    goto segments_failed;
+
+  /* now we are ready to add the stream */
+  gst_qtdemux_add_stream (qtdemux, stream, list);
+
+  return TRUE;
+
+/* ERRORS */
+corrupt_file:
+  {
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+        (_("This file is corrupt and cannot be played.")), (NULL));
+    g_free (stream);
+    return FALSE;
+  }
+error_encrypted:
+  {
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
+    g_free (stream);
+    return FALSE;
+  }
+samples_failed:
+  {
+    /* we posted an error already */
+    g_free (stream);
+    return FALSE;
+  }
+segments_failed:
+  {
+    /* we posted an error already */
+    g_free (stream);
+    return FALSE;
+  }
+unknown_stream:
+  {
+    GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (stream->subtype));
+    g_free (stream);
+    return TRUE;
+  }
+}
+
+static inline gboolean
+qtdemux_is_string_3gp (GstQTDemux * qtdemux, guint32 fourcc)
+{
+  /* Detect if the tag must be handled as 3gpp - i18n metadata. The first
+   * check is for catching all the possible brands, e.g. 3gp4,3gp5,3gg6,.. and
+   * handling properly the tags present in more than one brand.*/
+  return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
+      GST_MAKE_FOURCC ('3', 'g', 0, 0)
+      && (fourcc == FOURCC_cprt || fourcc == FOURCC_gnre
+          || fourcc == FOURCC_kywd)) || fourcc == FOURCC_titl
+      || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
+      || fourcc == FOURCC_albm;
+}
+
+static void
+qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
+    const char *dummy, GNode * node)
+{
+  const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
+  int offset;
+  char *name;
+  gchar *data;
+  gdouble longitude, latitude, altitude;
+
+  data = node->data;
+  offset = 14;
+
+  /* TODO: language code skipped */
+
+  name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
+
+  if (!name) {
+    /* do not alarm in trivial case, but bail out otherwise */
+    if (*(data + offset) != 0) {
+      GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
+          "giving up", tag);
+    }
+  } else {
+    gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+        GST_TAG_GEO_LOCATION_NAME, name, NULL);
+    offset += strlen (name);
+    g_free (name);
+  }
+
+  /* +1 +1 = skip null-terminator and location role byte */
+  offset += 1 + 1;
+  longitude = QT_FP32 (data + offset);
+
+  offset += 4;
+  latitude = QT_FP32 (data + offset);
+
+  offset += 4;
+  altitude = QT_FP32 (data + offset);
+
+  /* one invalid means all are invalid */
+  if (longitude >= -180.0 && longitude <= 180.0 &&
+      latitude >= -90.0 && latitude <= 90.0) {
+    gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+        GST_TAG_GEO_LOCATION_LATITUDE, latitude,
+        GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
+        GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
+  }
+
+  /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
+}
+
+
+static void
+qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy,
+    GNode * node)
+{
+  guint16 y;
+  GDate *date;
+
+  y = QT_UINT16 ((guint8 *) node->data + 12);
+  GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
+
+  date = g_date_new_dmy (1, 1, y);
+  gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL);
+  g_date_free (date);
+}
+
+static void
+qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag,
+    const char *dummy, GNode * node)
+{
+  int offset;
+  char *tag_str = NULL;
+  guint8 *entity;
+  guint16 table;
+
+
+  offset = 12;
+  entity = (guint8 *) node->data + offset;
+
+  offset += 4;
+  table = QT_UINT16 ((guint8 *) node->data + offset);
+
+  /* Language code skipped */
+
+  offset += 4;
+
+  /* Tag format: "XXXX://Y[YYYY]/classification info string"
+   * XXXX: classification entity, fixed length 4 chars.
+   * Y[YYYY]: classification table, max 5 chars.
+   */
+  tag_str = g_strdup_printf ("----://%u/%s",
+      table, (char *) node->data + offset);
+
+  /* memcpy To be sure we're preserving byte order */
+  memcpy (tag_str, entity, 4);
+  GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
+
+  gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_APPEND, tag,
+      tag_str, NULL);
+
+  g_free (tag_str);
+}
+
+static void
+qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag, const char *dummy,
+    GNode * node)
+{
+  const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
+  GNode *data;
+  char *s;
+  int len;
+  guint32 type;
+  int offset;
+
+  data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
+  if (data) {
+    len = QT_UINT32 (data->data);
+    type = QT_UINT32 ((guint8 *) data->data + 8);
+    if (type == 0x00000001) {
+      s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
+          env_vars);
+      if (s) {
+        GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s,
+            NULL);
+        g_free (s);
+      } else {
+        GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
+      }
+    }
+  } else {
+    len = QT_UINT32 (node->data);
+    type = QT_UINT32 ((guint8 *) node->data + 4);
+    if ((type >> 24) == 0xa9) {
+      /* Type starts with the (C) symbol, so the next 32 bits are
+       * the language code, which we ignore */
+      offset = 12;
+      GST_DEBUG_OBJECT (qtdemux, "found international text tag");
+    } else if (qtdemux_is_string_3gp (qtdemux,
+            QT_FOURCC ((guint8 *) node->data + 4))) {
+      offset = 14;
+      /* 16-bit Language code is ignored here as well */
+      GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
+    } else {
+      offset = 8;
+      GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
+    }
+    s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
+        len - offset, env_vars);
+    if (s) {
+      GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
+      gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL);
+      g_free (s);
+    } else {
+      GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
+    }
+  }
+}
+
+static void
+qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
+    const char *dummy, GNode * node)
+{
+  const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
+  guint8 *data;
+  char *s, *t, *k = NULL;
+  int len;
+  int offset;
+  int count;
+
+  /* re-route to normal string tag if not 3GP */
+  if (!qtdemux_is_string_3gp (qtdemux, FOURCC_kywd))
+    return qtdemux_tag_add_str (qtdemux, tag, dummy, node);
+
+  GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
+
+  data = node->data;
+
+  len = QT_UINT32 (data);
+  if (len < 15)
+    goto short_read;
+
+  count = QT_UINT8 (data + 14);
+  offset = 15;
+  for (; count; count--) {
+    gint slen;
+
+    if (offset + 1 > len)
+      goto short_read;
+    slen = QT_UINT8 (data + offset);
+    offset += 1;
+    if (offset + slen > len)
+      goto short_read;
+    s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
+        slen, env_vars);
+    if (s) {
+      GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
+      if (k) {
+        t = g_strjoin (",", k, s, NULL);
+        g_free (s);
+        g_free (k);
+        k = t;
+      } else {
+        k = s;
+      }
+    } else {
+      GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
+    }
+    offset += slen;
+  }
+
+done:
+  if (k) {
+    GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
+    gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, k, NULL);
+  }
+  g_free (k);
+
+  return;
+
+  /* ERRORS */
+short_read:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
+    goto done;
+  }
+}
+
+static void
+qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
+    const char *tag2, GNode * node)
+{
+  GNode *data;
+  int len;
+  int type;
+  int n1, n2;
+
+  data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
+  if (data) {
+    len = QT_UINT32 (data->data);
+    type = QT_UINT32 ((guint8 *) data->data + 8);
+    if (type == 0x00000000 && len >= 22) {
+      n1 = QT_UINT16 ((guint8 *) data->data + 18);
+      n2 = QT_UINT16 ((guint8 *) data->data + 20);
+      if (n1 > 0) {
+        GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+            tag1, n1, NULL);
+      }
+      if (n2 > 0) {
+        GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+            tag2, n2, NULL);
+      }
+    }
+  }
+}
+
+static void
+qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
+    GNode * node)
+{
+  GNode *data;
+  int len;
+  int type;
+  int n1;
+
+  data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
+  if (data) {
+    len = QT_UINT32 (data->data);
+    type = QT_UINT32 ((guint8 *) data->data + 8);
+    GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
+    /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
+    if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
+      n1 = QT_UINT16 ((guint8 *) data->data + 16);
+      if (n1) {
+        /* do not add bpm=0 */
+        GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+            tag1, (gdouble) n1, NULL);
+      }
+    }
+  }
+}
+
+static void
+qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
+    GNode * node)
+{
+  GNode *data;
+  int len;
+  int type;
+  GstBuffer *buf;
+
+  data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
+  if (data) {
+    len = QT_UINT32 (data->data);
+    type = QT_UINT32 ((guint8 *) data->data + 8);
+    GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
+    if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
+      if ((buf = gst_tag_image_data_to_image_buffer ((guint8 *) data->data + 16,
+                  len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
+        GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+            tag1, buf, NULL);
+        gst_buffer_unref (buf);
+      }
+    }
+  }
+}
+
+static void
+qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
+    GNode * node)
+{
+  GNode *data;
+  char *s;
+  int len;
+  int type;
+
+  data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
+  if (data) {
+    len = QT_UINT32 (data->data);
+    type = QT_UINT32 ((guint8 *) data->data + 8);
+    if (type == 0x00000001) {
+      guint y, m = 1, d = 1;
+      gint ret;
+
+      s = g_strndup ((char *) data->data + 16, len - 16);
+      GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
+      ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
+      if (ret >= 1 && y > 1500 && y < 3000) {
+        GDate *date;
+
+        date = g_date_new_dmy (d, m, y);
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag,
+            date, NULL);
+        g_date_free (date);
+      } else {
+        GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
+      }
+      g_free (s);
+    }
+  }
+}
+
+static void
+qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
+    GNode * node)
+{
+  static const gchar *genres[] = {
+    "N/A", "Blues", "Classic Rock", "Country", "Dance", "Disco",
+    "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
+    "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
+    "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
+    "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
+    "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
+    "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
+    "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative",
+    "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic",
+    "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
+    "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
+    "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American",
+    "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes",
+    "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka",
+    "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
+    "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob",
+    "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
+    "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
+    "Symphonic Rock", "Slow Rock", "Big Band", "Chorus",
+    "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
+    "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
+    "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango",
+    "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul",
+    "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella",
+    "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club House",
+    "Hardcore", "Terror", "Indie", "BritPop", "NegerPunk",
+    "Polsk Punk", "Beat", "Christian Gangsta", "Heavy Metal",
+    "Black Metal", "Crossover", "Contemporary C", "Christian Rock",
+    "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "SynthPop"
+  };
+  GNode *data;
+  int len;
+  int type;
+  int n;
+
+  /* re-route to normal string tag if 3GP */
+  if (qtdemux_is_string_3gp (qtdemux, FOURCC_gnre))
+    return qtdemux_tag_add_str (qtdemux, tag, dummy, node);
+
+  data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
+  if (data) {
+    len = QT_UINT32 (data->data);
+    type = QT_UINT32 ((guint8 *) data->data + 8);
+    if (type == 0x00000000 && len >= 18) {
+      n = QT_UINT16 ((guint8 *) data->data + 16);
+      if (n > 0 && n < sizeof (genres) / sizeof (char *)) {
+        GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genres[n]);
+        gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
+            tag, genres[n], NULL);
+      }
+    }
+  }
+}
+
+typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
+    const char *tag, const char *tag_bis, GNode * node);
+
+static const struct
+{
+  guint32 fourcc;
+  const gchar *gst_tag;
+  const gchar *gst_tag_bis;
+  const GstQTDemuxAddTagFunc func;
+} add_funcs[] = {
+  {
+  FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
+  FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
+  FOURCC__grp, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
+  FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
+  FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
+  FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
+  FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
+  FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
+  FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
+  FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
+  FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
+  FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
+  FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
+  FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
+  FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
+  FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
+  FOURCC__too, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
+  FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
+  FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
+  FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
+        qtdemux_tag_add_num}, {
+  FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
+        qtdemux_tag_add_num}, {
+  FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
+  FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
+  FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
+  FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
+  FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
+  FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
+  FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
+  FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
+  FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
+        qtdemux_tag_add_classification}
+};
+
+static void
+qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
+{
+  gint len;
+  guint8 *data;
+  GstBuffer *buf;
+  gchar *media_type, *style;
+  GstCaps *caps;
+  guint i;
+  guint8 ndata[4];
+
+  data = node->data;
+  len = QT_UINT32 (data);
+  buf = gst_buffer_new_and_alloc (len);
+  memcpy (GST_BUFFER_DATA (buf), data, len);
+
+  /* heuristic to determine style of tag */
+  if (QT_FOURCC (data + 4) == FOURCC_____ ||
+      (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
+    style = "itunes";
+  else if (demux->major_brand == FOURCC_qt__)
+    style = "quicktime";
+  /* fall back to assuming iso/3gp tag style */
+  else
+    style = "iso";
+
+  /* santize the name for the caps. */
+  for (i = 0; i < 4; i++) {
+    guint8 d = data[4 + i];
+    if (g_ascii_isalnum (d))
+      ndata[i] = g_ascii_tolower (d);
+    else
+      ndata[i] = '_';
+  }
+
+  media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
+      ndata[0], ndata[1], ndata[2], ndata[3]);
+  GST_DEBUG_OBJECT (demux, "media type %s", media_type);
+
+  caps = gst_caps_new_simple (media_type, "style", G_TYPE_STRING, style, NULL);
+  gst_buffer_set_caps (buf, caps);
+  gst_caps_unref (caps);
+  g_free (media_type);
+
+  GST_DEBUG_OBJECT (demux, "adding private tag; size %d, caps %" GST_PTR_FORMAT,
+      GST_BUFFER_SIZE (buf), caps);
+
+  gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
+      GST_QT_DEMUX_PRIVATE_TAG, buf, NULL);
+  gst_buffer_unref (buf);
+}
+
+static void
+qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
+{
+  GNode *meta;
+  GNode *ilst;
+  GNode *node;
+  gint i;
+
+  meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
+  if (meta != NULL) {
+    ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
+    if (ilst == NULL) {
+      GST_LOG_OBJECT (qtdemux, "no ilst");
+      return;
+    }
+  } else {
+    ilst = udta;
+    GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
+  }
+
+  GST_DEBUG_OBJECT (qtdemux, "new tag list");
+  qtdemux->tag_list = gst_tag_list_new ();
+
+  for (i = 0; i < G_N_ELEMENTS (add_funcs); ++i) {
+    node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
+    if (node) {
+      add_funcs[i].func (qtdemux, add_funcs[i].gst_tag,
+          add_funcs[i].gst_tag_bis, node);
+      g_node_destroy (node);
+    }
+  }
+
+  /* parsed nodes have been removed, pass along remainder as blob */
+  g_node_children_foreach (ilst, G_TRAVERSE_ALL,
+      (GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux);
+
+}
+
+typedef struct
+{
+  GstStructure *structure;      /* helper for sort function */
+  gchar *location;
+  guint min_req_bitrate;
+  guint min_req_qt_version;
+} GstQtReference;
+
+static gint
+qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
+{
+  GstQtReference *ref_a = (GstQtReference *) a;
+  GstQtReference *ref_b = (GstQtReference *) b;
+
+  if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
+    return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
+
+  /* known bitrates go before unknown; higher bitrates go first */
+  return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
+}
+
+/* sort the redirects and post a message for the application.
+ */
+static void
+qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
+{
+  GstQtReference *best;
+  GstStructure *s;
+  GstMessage *msg;
+  GValue list_val = { 0, };
+  GList *l;
+
+  g_assert (references != NULL);
+
+  references = g_list_sort (references, qtdemux_redirects_sort_func);
+
+  best = (GstQtReference *) references->data;
+
+  g_value_init (&list_val, GST_TYPE_LIST);
+
+  for (l = references; l != NULL; l = l->next) {
+    GstQtReference *ref = (GstQtReference *) l->data;
+    GValue struct_val = { 0, };
+
+    ref->structure = gst_structure_new ("redirect",
+        "new-location", G_TYPE_STRING, ref->location, NULL);
+
+    if (ref->min_req_bitrate > 0) {
+      gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
+          ref->min_req_bitrate, NULL);
+    }
+
+    g_value_init (&struct_val, GST_TYPE_STRUCTURE);
+    g_value_set_boxed (&struct_val, ref->structure);
+    gst_value_list_append_value (&list_val, &struct_val);
+    g_value_unset (&struct_val);
+    /* don't free anything here yet, since we need best->structure below */
+  }
+
+  g_assert (best != NULL);
+  s = gst_structure_copy (best->structure);
+
+  if (g_list_length (references) > 1) {
+    gst_structure_set_value (s, "locations", &list_val);
+  }
+
+  g_value_unset (&list_val);
+
+  for (l = references; l != NULL; l = l->next) {
+    GstQtReference *ref = (GstQtReference *) l->data;
+
+    gst_structure_free (ref->structure);
+    g_free (ref->location);
+    g_free (ref);
+  }
+  g_list_free (references);
+
+  GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
+  msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
+  gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
+}
+
+/* look for redirect nodes, collect all redirect information and
+ * process it.
+ */
+static gboolean
+qtdemux_parse_redirects (GstQTDemux * qtdemux)
+{
+  GNode *rmra, *rmda, *rdrf;
+
+  rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
+  if (rmra) {
+    GList *redirects = NULL;
+
+    rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
+    while (rmda) {
+      GstQtReference ref = { NULL, NULL, 0, 0 };
+      GNode *rmdr, *rmvc;
+
+      if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
+        ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
+        GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
+            ref.min_req_bitrate);
+      }
+
+      if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
+        guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
+        guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
+
+#ifndef GST_DISABLE_GST_DEBUG
+        guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
+#endif
+        guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
+
+        GST_LOG_OBJECT (qtdemux,
+            "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
+            ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
+            bitmask, check_type);
+        if (package == FOURCC_qtim && check_type == 0) {
+          ref.min_req_qt_version = version;
+        }
+      }
+
+      rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
+      if (rdrf) {
+        guint32 ref_type;
+        guint8 *ref_data;
+
+        ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
+        ref_data = (guint8 *) rdrf->data + 20;
+        if (ref_type == FOURCC_alis) {
+          guint record_len, record_version, fn_len;
+
+          /* MacOSX alias record, google for alias-layout.txt */
+          record_len = QT_UINT16 (ref_data + 4);
+          record_version = QT_UINT16 (ref_data + 4 + 2);
+          fn_len = QT_UINT8 (ref_data + 50);
+          if (record_len > 50 && record_version == 2 && fn_len > 0) {
+            ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
+          }
+        } else if (ref_type == FOURCC_url_) {
+          ref.location = g_strdup ((gchar *) ref_data);
+        } else {
+          GST_DEBUG_OBJECT (qtdemux,
+              "unknown rdrf reference type %" GST_FOURCC_FORMAT,
+              GST_FOURCC_ARGS (ref_type));
+        }
+        if (ref.location != NULL) {
+          GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
+          redirects = g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
+        } else {
+          GST_WARNING_OBJECT (qtdemux,
+              "Failed to extract redirect location from rdrf atom");
+        }
+      }
+
+      /* look for others */
+      rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
+    }
+
+    if (redirects != NULL) {
+      qtdemux_process_redirects (qtdemux, redirects);
+    }
+  }
+  return TRUE;
+}
+
+static GstTagList *
+qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
+{
+  const gchar *fmt;
+
+  if (tags == NULL)
+    tags = gst_tag_list_new ();
+
+  if (qtdemux->major_brand == FOURCC_mjp2)
+    fmt = "Motion JPEG 2000";
+  else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
+    fmt = "3GP";
+  else if (qtdemux->major_brand == FOURCC_qt__)
+    fmt = "Quicktime";
+  else
+    fmt = "ISO MP4/M4A";
+
+  GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
+      GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
+
+  gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
+      fmt, NULL);
+
+  return tags;
+}
+
+/* we have read th complete moov node now.
+ * This function parses all of the relevant info, creates the traks and
+ * prepares all data structures for playback
+ */
+static gboolean
+qtdemux_parse_tree (GstQTDemux * qtdemux)
+{
+  GNode *mvhd;
+  GNode *trak;
+  GNode *udta;
+  gint64 duration;
+
+  mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
+  if (mvhd == NULL) {
+    GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
+    return qtdemux_parse_redirects (qtdemux);
+  }
+
+  qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
+  qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
+
+  GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
+  GST_INFO_OBJECT (qtdemux, "duration: %u", qtdemux->duration);
+
+  /* set duration in the segment info */
+  gst_qtdemux_get_duration (qtdemux, &duration);
+  gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
+
+  /* parse all traks */
+  trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
+  while (trak) {
+    qtdemux_parse_trak (qtdemux, trak);
+    /* iterate all siblings */
+    trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
+  }
+  gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
+
+  /* find and push tags, we do this after adding the pads so we can push the
+   * tags downstream as well. */
+  udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
+  if (udta) {
+    qtdemux_parse_udta (qtdemux, udta);
+  } else {
+    GST_LOG_OBJECT (qtdemux, "No udta node found.");
+  }
+
+  /* FIXME: tags must be pushed after the initial newsegment event */
+  qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
+  GST_INFO_OBJECT (qtdemux, "global tags: %" GST_PTR_FORMAT, qtdemux->tag_list);
+  gst_element_found_tags (GST_ELEMENT_CAST (qtdemux), qtdemux->tag_list);
+  qtdemux->tag_list = NULL;
+
+  return TRUE;
+}
+
+/* taken from ffmpeg */
+static unsigned int
+get_size (guint8 * ptr, guint8 ** end)
+{
+  int count = 4;
+  int len = 0;
+
+  while (count--) {
+    int c = *ptr;
+
+    ptr++;
+    len = (len << 7) | (c & 0x7f);
+    if (!(c & 0x80))
+      break;
+  }
+  if (end)
+    *end = ptr;
+  return len;
+}
+
+/* this can change the codec originally present in @list */
+static void
+gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    GNode * esds, GstTagList * list)
+{
+  int len = QT_UINT32 (esds->data);
+  guint8 *ptr = esds->data;
+  guint8 *end = ptr + len;
+  int tag;
+  guint8 *data_ptr = NULL;
+  int data_len = 0;
+  guint8 object_type_id = 0;
+  char *codec_name = NULL;
+  GstCaps *caps = NULL;
+
+  GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
+  ptr += 8;
+  GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
+  ptr += 4;
+  while (ptr < end) {
+    tag = QT_UINT8 (ptr);
+    GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
+    ptr++;
+    len = get_size (ptr, &ptr);
+    GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
+
+    switch (tag) {
+      case 0x03:
+        GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
+        GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
+        ptr += 3;
+        break;
+      case 0x04:
+        object_type_id = QT_UINT8 (ptr);
+        GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
+        GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
+        GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
+        GST_DEBUG_OBJECT (qtdemux, "max bitrate %d", QT_UINT32 (ptr + 5));
+        GST_DEBUG_OBJECT (qtdemux, "avg bitrate %d", QT_UINT32 (ptr + 9));
+        ptr += 13;
+        break;
+      case 0x05:
+        GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
+        data_ptr = ptr;
+        data_len = len;
+        ptr += len;
+        break;
+      case 0x06:
+        GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
+        ptr += 1;
+        break;
+      default:
+        GST_ERROR_OBJECT (qtdemux, "parse error");
+        break;
+    }
+  }
+
+  /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
+   * in use, and should also be used to override some other parameters for some
+   * codecs. */
+  switch (object_type_id) {
+    case 0x20:                 /* MPEG-4 */
+      break;                    /* Nothing special needed here */
+    case 0x21:                 /* H.264 */
+      codec_name = "H.264 / AVC";
+      caps = gst_caps_new_simple ("video/x-h264", NULL);
+      break;
+    case 0x40:                 /* AAC (any) */
+    case 0x66:                 /* AAC Main */
+    case 0x67:                 /* AAC LC */
+    case 0x68:                 /* AAC SSR */
+      /* Override channels and rate based on the codec_data, as it's often
+       * wrong. */
+      if (data_ptr && data_len >= 2) {
+        guint channels, rateindex;
+        int rates[] = { 96000, 88200, 64000, 48000, 44100, 32000,
+          24000, 22050, 16000, 12000, 11025, 8000
+        };
+
+        channels = (data_ptr[1] & 0x7f) >> 3;
+        if (channels <= 7) {
+          stream->n_channels = channels;
+        }
+
+        rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
+        if (rateindex < sizeof (rates) / sizeof (*rates)) {
+          stream->rate = rates[rateindex];
+        }
+      }
+      break;
+    case 0x60:                 /* MPEG-2, various profiles */
+    case 0x61:
+    case 0x62:
+    case 0x63:
+    case 0x64:
+    case 0x65:
+      codec_name = "MPEG-2 video";
+
+      gst_caps_unref (stream->caps);
+      stream->caps = gst_caps_new_simple ("video/mpeg",
+          "mpegversion", G_TYPE_INT, 2,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case 0x69:                 /* MP3 has two different values, accept either */
+    case 0x6B:
+      /* change to mpeg1 layer 3 audio */
+      gst_caps_set_simple (stream->caps, "layer", G_TYPE_INT, 3,
+          "mpegversion", G_TYPE_INT, 1, NULL);
+      codec_name = "MPEG-1 layer 3";
+      break;
+    case 0x6A:                 /* MPEG-1 */
+      codec_name = "MPEG-1 video";
+
+      gst_caps_unref (stream->caps);
+      stream->caps = gst_caps_new_simple ("video/mpeg",
+          "mpegversion", G_TYPE_INT, 1,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case 0x6C:                 /* MJPEG */
+      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      codec_name = "Motion-JPEG";
+      break;
+    case 0x6D:                 /* PNG */
+      caps = gst_caps_new_simple ("image/png", NULL);
+      codec_name = "PNG still images";
+      break;
+    case 0x6E:                 /* JPEG2000 */
+      codec_name = "JPEG-2000";
+      caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
+      break;
+    case 0xA4:                 /* Dirac */
+      codec_name = "Dirac";
+      caps = gst_caps_new_simple ("video/x-dirac", NULL);
+      break;
+    case 0xA5:                 /* AC3 */
+      codec_name = "AC-3 audio";
+      caps = gst_caps_new_simple ("audio/x-ac3", NULL);
+      break;
+    case 0xE1:                 /* QCELP */
+      /* QCELP, the codec_data is a riff tag (little endian) with
+       * more info (http://ftp.3gpp2.org/TSGC/Working/2003/2003-05-SanDiego/TSG-C-2003-05-San%20Diego/WG1/SWG12/C12-20030512-006%20=%20C12-20030217-015_Draft_Baseline%20Text%20of%20FFMS_R2.doc). */
+      caps = gst_caps_new_simple ("audio/qcelp", NULL);
+      codec_name = "QCELP";
+      break;
+    default:
+      break;
+  }
+
+  /* If we have a replacement caps, then change our caps for this stream */
+  if (caps) {
+    gst_caps_unref (stream->caps);
+    stream->caps = caps;
+  }
+
+  if (codec_name && list)
+    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+        GST_TAG_AUDIO_CODEC, codec_name, NULL);
+
+  /* Add the codec_data attribute to caps, if we have it */
+  if (data_ptr) {
+    GstBuffer *buffer;
+
+    buffer = gst_buffer_new_and_alloc (data_len);
+    memcpy (GST_BUFFER_DATA (buffer), data_ptr, data_len);
+
+    GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
+    GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
+
+    gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
+        buffer, NULL);
+    gst_buffer_unref (buffer);
+  }
+
+}
+
+#define _codec(name) \
+  do { \
+    if (codec_name) { \
+      *codec_name = g_strdup (name); \
+    } \
+  } while (0)
+
+static GstCaps *
+qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
+{
+  GstCaps *caps;
+  const GstStructure *s;
+  const gchar *name;
+
+  switch (fourcc) {
+    case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
+      _codec ("PNG still images");
+      caps = gst_caps_new_simple ("image/png", NULL);
+      break;
+    case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
+      _codec ("JPEG still images");
+      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
+    case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
+    case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
+      _codec ("Motion-JPEG");
+      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
+      _codec ("Motion-JPEG format B");
+      caps = gst_caps_new_simple ("video/x-mjpeg-b", NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
+      _codec ("JPEG-2000");
+      /* override to what it should be according to spec, avoid palette_data */
+      stream->bits_per_sample = 24;
+      caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
+      break;
+    case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
+      _codec ("Sorensen video v.3");
+      caps = gst_caps_new_simple ("video/x-svq",
+          "svqversion", G_TYPE_INT, 3, NULL);
+      break;
+    case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
+    case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
+      _codec ("Sorensen video v.1");
+      caps = gst_caps_new_simple ("video/x-svq",
+          "svqversion", G_TYPE_INT, 1, NULL);
+      break;
+    case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
+    {
+      guint16 bps;
+
+      _codec ("Raw RGB video");
+      bps = QT_UINT16 (stsd_data + 98);
+      /* set common stuff */
+      caps = gst_caps_new_simple ("video/x-raw-rgb",
+          "endianness", G_TYPE_INT, G_BYTE_ORDER, "depth", G_TYPE_INT, bps,
+          NULL);
+
+      switch (bps) {
+        case 15:
+          gst_caps_set_simple (caps,
+              "bpp", G_TYPE_INT, 16,
+              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+              "red_mask", G_TYPE_INT, 0x7c00,
+              "green_mask", G_TYPE_INT, 0x03e0,
+              "blue_mask", G_TYPE_INT, 0x001f, NULL);
+          break;
+        case 16:
+          gst_caps_set_simple (caps,
+              "bpp", G_TYPE_INT, 16,
+              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+              "red_mask", G_TYPE_INT, 0xf800,
+              "green_mask", G_TYPE_INT, 0x07e0,
+              "blue_mask", G_TYPE_INT, 0x001f, NULL);
+          break;
+        case 24:
+          gst_caps_set_simple (caps,
+              "bpp", G_TYPE_INT, 24,
+              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+              "red_mask", G_TYPE_INT, 0xff0000,
+              "green_mask", G_TYPE_INT, 0x00ff00,
+              "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
+          break;
+        case 32:
+          gst_caps_set_simple (caps,
+              "bpp", G_TYPE_INT, 32,
+              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+              "alpha_mask", G_TYPE_INT, 0xff000000,
+              "red_mask", G_TYPE_INT, 0x00ff0000,
+              "green_mask", G_TYPE_INT, 0x0000ff00,
+              "blue_mask", G_TYPE_INT, 0x000000ff, NULL);
+          break;
+        default:
+          /* unknown */
+          break;
+      }
+      break;
+    }
+    case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
+      _codec ("Raw planar YUV 4:2:0");
+      caps = gst_caps_new_simple ("video/x-raw-yuv",
+          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+          NULL);
+      break;
+    case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
+    case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
+      _codec ("Raw packed YUV 4:2:2");
+      caps = gst_caps_new_simple ("video/x-raw-yuv",
+          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
+          NULL);
+      break;
+    case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
+      _codec ("Raw packed YUV 4:2:0");
+      caps = gst_caps_new_simple ("video/x-raw-yuv",
+          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
+          NULL);
+      break;
+    case GST_MAKE_FOURCC ('v', '2', '1', '0'):
+      _codec ("Raw packed YUV 10-bit 4:2:2");
+      caps = gst_caps_new_simple ("video/x-raw-yuv",
+          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('v', '2', '1', '0'),
+          NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
+    case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
+      _codec ("MPEG-1 video");
+      caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): // HDV 720p30
+    case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): // HDV 1080i60
+    case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): // HDV 1080i50
+    case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): // HDV 720p25
+    case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): // HDV 1080i60
+    case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): // MPEG2 IMX NTSC 525/60 50mb/s produced by FCP
+    case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): // MPEG2 IMX PAL 625/60 50mb/s produced by FCP
+    case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): // MPEG2 IMX NTSC 525/60 40mb/s produced by FCP
+    case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): // MPEG2 IMX PAL 625/60 40mb/s produced by FCP
+    case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): // MPEG2 IMX NTSC 525/60 30mb/s produced by FCP
+    case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): // MPEG2 IMX PAL 625/50 30mb/s produced by FCP
+    case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): // XDCAM HD 1080i60
+    case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): // AVID IMX PAL
+    case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): // AVID IMX PAL
+      _codec ("MPEG-2 video");
+      caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
+      _codec ("GIF still images");
+      caps = gst_caps_new_simple ("image/gif", NULL);
+      break;
+    case GST_MAKE_FOURCC ('h', '2', '6', '3'):
+    case GST_MAKE_FOURCC ('H', '2', '6', '3'):
+    case GST_MAKE_FOURCC ('s', '2', '6', '3'):
+    case GST_MAKE_FOURCC ('U', '2', '6', '3'):
+      _codec ("H.263");
+      /* ffmpeg uses the height/width props, don't know why */
+      caps = gst_caps_new_simple ("video/x-h263", NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
+      _codec ("MPEG-4 video");
+      caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
+    case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
+      _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
+      caps = gst_caps_new_simple ("video/x-msmpeg",
+          "msmpegversion", G_TYPE_INT, 43, NULL);
+      break;
+    case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
+    case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
+      _codec ("3ivX video");
+      caps = gst_caps_new_simple ("video/x-3ivx", NULL);
+      break;
+    case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
+      _codec ("DivX 3");
+      caps = gst_caps_new_simple ("video/x-divx",
+          "divxversion", G_TYPE_INT, 3, NULL);
+      break;
+    case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
+    case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
+      _codec ("DivX 4");
+      caps = gst_caps_new_simple ("video/x-divx",
+          "divxversion", G_TYPE_INT, 4, NULL);
+      break;
+    case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
+      _codec ("DivX 5");
+      caps = gst_caps_new_simple ("video/x-divx",
+          "divxversion", G_TYPE_INT, 5, NULL);
+      break;
+    case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
+    case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
+      _codec ("XVID MPEG-4");
+      caps = gst_caps_new_simple ("video/x-xvid", NULL);
+      break;
+
+    case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
+    case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
+      caps = gst_caps_new_simple ("video/mpeg",
+          "mpegversion", G_TYPE_INT, 4, NULL);
+      if (codec_name)
+        *codec_name = g_strdup ("FFmpeg MPEG-4");
+      break;
+
+    case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
+      _codec ("Cinepak");
+      caps = gst_caps_new_simple ("video/x-cinepak", NULL);
+      break;
+    case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
+      _codec ("Apple QuickDraw");
+      caps = gst_caps_new_simple ("video/x-qdrw", NULL);
+      break;
+    case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
+      _codec ("Apple video");
+      caps = gst_caps_new_simple ("video/x-apple-video", NULL);
+      break;
+    case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
+      _codec ("H.264 / AVC");
+      caps = gst_caps_new_simple ("video/x-h264", NULL);
+      break;
+    case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
+      _codec ("Run-length encoding");
+      caps = gst_caps_new_simple ("video/x-rle",
+          "layout", G_TYPE_STRING, "quicktime", NULL);
+      break;
+    case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
+      _codec ("Indeo Video 3");
+      caps = gst_caps_new_simple ("video/x-indeo",
+          "indeoversion", G_TYPE_INT, 3, NULL);
+      break;
+    case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
+    case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
+      _codec ("Intel Video 4");
+      caps = gst_caps_new_simple ("video/x-indeo",
+          "indeoversion", G_TYPE_INT, 4, NULL);
+      break;
+    case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
+    case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
+    case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
+    case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
+    case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
+    case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
+    case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
+    case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
+      _codec ("DV Video");
+      caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): //DVCPRO50 NTSC
+    case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): //DVCPRO50 PAL
+      _codec ("DVCPro50 Video");
+      caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): //DVCPRO HD 50i produced by FCP
+    case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): //DVCPRO HD 60i produced by FCP
+      _codec ("DVCProHD Video");
+      caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
+          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
+      _codec ("Apple Graphics (SMC)");
+      caps = gst_caps_new_simple ("video/x-smc", NULL);
+      break;
+    case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
+      _codec ("VP3");
+      caps = gst_caps_new_simple ("video/x-vp3", NULL);
+      break;
+    case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
+      _codec ("Theora");
+      caps = gst_caps_new_simple ("video/x-theora", NULL);
+      /* theora uses one byte of padding in the data stream because it does not
+       * allow 0 sized packets while theora does */
+      stream->padding = 1;
+      break;
+    case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
+      _codec ("Dirac");
+      caps = gst_caps_new_simple ("video/x-dirac", NULL);
+      break;
+    case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
+      _codec ("TIFF still images");
+      caps = gst_caps_new_simple ("image/tiff", NULL);
+      break;
+    case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
+      _codec ("Apple Intermediate Codec");
+      caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
+      break;
+    case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
+      _codec ("AVID DNxHD");
+      caps = gst_caps_from_string ("video/x-dnxhd");
+      break;
+    case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
+    default:
+    {
+      char *s;
+
+      s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (fourcc));
+      caps = gst_caps_new_simple (s, NULL);
+      break;
+    }
+  }
+
+  /* enable clipping for raw video streams */
+  s = gst_caps_get_structure (caps, 0);
+  name = gst_structure_get_name (s);
+  if (g_str_has_prefix (name, "video/x-raw-")) {
+    stream->need_clip = TRUE;
+  }
+  return caps;
+}
+
+static GstCaps *
+qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
+{
+  GstCaps *caps;
+  const GstStructure *s;
+  const gchar *name;
+  gint endian = 0;
+
+  GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
+
+  switch (fourcc) {
+    case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
+    case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
+      _codec ("Raw 8-bit PCM audio");
+      caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 8,
+          "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
+      endian = G_BIG_ENDIAN;
+      /* fall-through */
+    case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
+    {
+      gchar *str;
+      gint depth;
+
+      if (!endian)
+        endian = G_LITTLE_ENDIAN;
+
+      depth = stream->bytes_per_packet * 8;
+      str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
+      _codec (str);
+      g_free (str);
+      caps = gst_caps_new_simple ("audio/x-raw-int",
+          "width", G_TYPE_INT, depth, "depth", G_TYPE_INT, depth,
+          "endianness", G_TYPE_INT, endian,
+          "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      break;
+    }
+    case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
+      _codec ("Raw 64-bit floating-point audio");
+      caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 64,
+          "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
+      break;
+    case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
+      _codec ("Raw 32-bit floating-point audio");
+      caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32,
+          "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
+      break;
+    case FOURCC_in24:
+      _codec ("Raw 24-bit PCM audio");
+      /* we assume BIG ENDIAN, an enda box will tell us to change this to little
+       * endian later */
+      caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 24,
+          "depth", G_TYPE_INT, 24,
+          "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+          "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
+      _codec ("Raw 32-bit PCM audio");
+      caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 32,
+          "depth", G_TYPE_INT, 32,
+          "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+          "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
+      _codec ("Mu-law audio");
+      caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
+      break;
+    case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
+      _codec ("A-law audio");
+      caps = gst_caps_new_simple ("audio/x-alaw", NULL);
+      break;
+    case 0x0200736d:
+    case 0x6d730002:
+      _codec ("Microsoft ADPCM");
+      /* Microsoft ADPCM-ACM code 2 */
+      caps = gst_caps_new_simple ("audio/x-adpcm",
+          "layout", G_TYPE_STRING, "microsoft", NULL);
+      break;
+    case 0x1100736d:
+    case 0x6d730011:
+      _codec ("IMA Loki SDL MJPEG ADPCM");
+      /* Loki ADPCM, See #550288 for a file that only decodes
+       * with the smjpeg variant of the ADPCM decoder. */
+      caps = gst_caps_new_simple ("audio/x-adpcm",
+          "layout", G_TYPE_STRING, "smjpeg", NULL);
+      break;
+    case 0x1700736d:
+    case 0x6d730017:
+      _codec ("DVI/Intel IMA ADPCM");
+      /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
+      caps = gst_caps_new_simple ("audio/x-adpcm",
+          "layout", G_TYPE_STRING, "quicktime", NULL);
+      break;
+    case 0x5500736d:
+    case 0x6d730055:
+      /* MPEG layer 3, CBR only (pre QT4.1) */
+    case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
+      _codec ("MPEG-1 layer 3");
+      /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
+      caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
+          "mpegversion", G_TYPE_INT, 1, NULL);
+      break;
+    case 0x20736d:
+    case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
+      _codec ("AC-3 audio");
+      caps = gst_caps_new_simple ("audio/x-ac3", NULL);
+      stream->sampled = TRUE;
+      break;
+    case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
+      _codec ("MACE-3");
+      caps = gst_caps_new_simple ("audio/x-mace",
+          "maceversion", G_TYPE_INT, 3, NULL);
+      break;
+    case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
+      _codec ("MACE-6");
+      caps = gst_caps_new_simple ("audio/x-mace",
+          "maceversion", G_TYPE_INT, 6, NULL);
+      break;
+    case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
+      /* ogg/vorbis */
+      caps = gst_caps_new_simple ("application/ogg", NULL);
+      break;
+    case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
+      _codec ("DV audio");
+      caps = gst_caps_new_simple ("audio/x-dv", NULL);
+      break;
+    case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
+      _codec ("MPEG-4 AAC audio");
+      caps = gst_caps_new_simple ("audio/mpeg",
+          "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE, NULL);
+      break;
+    case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
+      _codec ("QDesign Music");
+      caps = gst_caps_new_simple ("audio/x-qdm", NULL);
+      break;
+    case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
+      _codec ("QDesign Music v.2");
+      /* FIXME: QDesign music version 2 (no constant) */
+      if (data) {
+        caps = gst_caps_new_simple ("audio/x-qdm2",
+            "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
+            "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
+            "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
+      } else {
+        caps = gst_caps_new_simple ("audio/x-qdm2", NULL);
+      }
+      break;
+    case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
+      _codec ("GSM audio");
+      caps = gst_caps_new_simple ("audio/x-gsm", NULL);
+      break;
+    case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
+      _codec ("AMR audio");
+      caps = gst_caps_new_simple ("audio/AMR", NULL);
+      break;
+    case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
+      _codec ("AMR-WB audio");
+      caps = gst_caps_new_simple ("audio/AMR-WB", NULL);
+      break;
+    case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
+      _codec ("Quicktime IMA ADPCM");
+      caps = gst_caps_new_simple ("audio/x-adpcm",
+          "layout", G_TYPE_STRING, "quicktime", NULL);
+      break;
+    case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
+      _codec ("Apple lossless audio");
+      caps = gst_caps_new_simple ("audio/x-alac", NULL);
+      break;
+    case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
+      /* ? */
+    case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
+      /* QUALCOMM PureVoice */
+    default:
+    {
+      char *s;
+
+      s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (fourcc));
+      caps = gst_caps_new_simple (s, NULL);
+      break;
+    }
+  }
+
+  /* enable clipping for raw audio streams */
+  s = gst_caps_get_structure (caps, 0);
+  name = gst_structure_get_name (s);
+  if (g_str_has_prefix (name, "audio/x-raw-")) {
+    stream->need_clip = TRUE;
+  }
+  return caps;
+}
+
+static GstCaps *
+qtdemux_subp_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
+    guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
+{
+  GstCaps *caps;
+
+  GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
+
+  switch (fourcc) {
+    case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
+      _codec ("DVD subtitle");
+      caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
+      break;
+    default:
+    {
+      char *s;
+
+      s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (fourcc));
+      caps = gst_caps_new_simple (s, NULL);
+      break;
+    }
+  }
+  return caps;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,108 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_QTDEMUX_H__
+#define __GST_QTDEMUX_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+
+GST_DEBUG_CATEGORY_EXTERN (qtdemux_debug);
+#define GST_CAT_DEFAULT qtdemux_debug
+
+#define GST_TYPE_QTDEMUX \
+  (gst_qtdemux_get_type())
+#define GST_QTDEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QTDEMUX,GstQTDemux))
+#define GST_QTDEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QTDEMUX,GstQTDemuxClass))
+#define GST_IS_QTDEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QTDEMUX))
+#define GST_IS_QTDEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QTDEMUX))
+
+#define GST_QTDEMUX_CAST(obj) ((GstQTDemux *)(obj))
+
+/* qtdemux produces these for atoms it cannot parse */
+#define GST_QT_DEMUX_PRIVATE_TAG "private-qt-tag"
+#define GST_QT_DEMUX_CLASSIFICATION_TAG "classification"
+
+#define GST_QTDEMUX_MAX_STREAMS         8
+
+typedef struct _GstQTDemux GstQTDemux;
+typedef struct _GstQTDemuxClass GstQTDemuxClass;
+typedef struct _QtDemuxStream QtDemuxStream;
+
+struct _GstQTDemux {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad;
+
+  QtDemuxStream *streams[GST_QTDEMUX_MAX_STREAMS];
+  gint     n_streams;
+  gint     n_video_streams;
+  gint     n_audio_streams;
+  gint     n_subp_streams;
+
+  guint  major_brand;
+  GNode *moov_node;
+  GNode *moov_node_compressed;
+
+  guint32 timescale;
+  guint32 duration;
+
+  gint state;
+
+  gboolean pullbased;
+
+  /* push based variables */
+  guint neededbytes;
+  guint todrop;
+  GstAdapter *adapter;
+  GstBuffer *mdatbuffer;
+
+  /* offset of the media data (i.e.: Size of header) */
+  guint64 offset;
+  /* offset of the mdat atom */
+  guint64 mdatoffset;
+
+  GstTagList *tag_list;
+
+  /* track stuff */
+  guint64 last_ts;
+
+  /* configured playback region */
+  GstSegment segment;
+  gboolean segment_running;
+  GstEvent *pending_newsegment;
+};
+
+struct _GstQTDemuxClass {
+  GstElementClass parent_class;
+};
+
+GType gst_qtdemux_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_QTDEMUX_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux_dump.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,432 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 "qtdemux_types.h"
+#include "qtdemux_dump.h"
+
+void
+qtdemux_dump_mvhd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  creation time: %u", depth, "", QT_UINT32 (buffer + 12));
+  GST_LOG ("%*s  modify time:   %u", depth, "", QT_UINT32 (buffer + 16));
+  GST_LOG ("%*s  time scale:    1/%u sec", depth, "", QT_UINT32 (buffer + 20));
+  GST_LOG ("%*s  duration:      %u", depth, "", QT_UINT32 (buffer + 24));
+  GST_LOG ("%*s  pref. rate:    %g", depth, "", QT_FP32 (buffer + 28));
+  GST_LOG ("%*s  pref. volume:  %g", depth, "", QT_FP16 (buffer + 32));
+  GST_LOG ("%*s  preview time:  %u", depth, "", QT_UINT32 (buffer + 80));
+  GST_LOG ("%*s  preview dur.:  %u", depth, "", QT_UINT32 (buffer + 84));
+  GST_LOG ("%*s  poster time:   %u", depth, "", QT_UINT32 (buffer + 88));
+  GST_LOG ("%*s  select time:   %u", depth, "", QT_UINT32 (buffer + 92));
+  GST_LOG ("%*s  select dur.:   %u", depth, "", QT_UINT32 (buffer + 96));
+  GST_LOG ("%*s  current time:  %u", depth, "", QT_UINT32 (buffer + 100));
+  GST_LOG ("%*s  next track ID: %d", depth, "", QT_UINT32 (buffer + 104));
+}
+
+void
+qtdemux_dump_tkhd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  creation time: %u", depth, "", QT_UINT32 (buffer + 12));
+  GST_LOG ("%*s  modify time:   %u", depth, "", QT_UINT32 (buffer + 16));
+  GST_LOG ("%*s  track ID:      %u", depth, "", QT_UINT32 (buffer + 20));
+  GST_LOG ("%*s  duration:      %u", depth, "", QT_UINT32 (buffer + 28));
+  GST_LOG ("%*s  layer:         %u", depth, "", QT_UINT16 (buffer + 36));
+  GST_LOG ("%*s  alt group:     %u", depth, "", QT_UINT16 (buffer + 38));
+  GST_LOG ("%*s  volume:        %g", depth, "", QT_FP16 (buffer + 44));
+  GST_LOG ("%*s  track width:   %g", depth, "", QT_FP32 (buffer + 84));
+  GST_LOG ("%*s  track height:  %g", depth, "", QT_FP32 (buffer + 88));
+
+}
+
+void
+qtdemux_dump_elst (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %u", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    track dur:     %u", depth, "",
+        QT_UINT32 (buffer + 16 + i * 12));
+    GST_LOG ("%*s    media time:    %u", depth, "",
+        QT_UINT32 (buffer + 20 + i * 12));
+    GST_LOG ("%*s    media rate:    %g", depth, "",
+        QT_FP32 (buffer + 24 + i * 12));
+  }
+}
+
+void
+qtdemux_dump_mdhd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  guint32 version;
+  guint64 duration, ctime, mtime;
+  guint32 time_scale;
+  guint16 language, quality;
+
+  version = QT_UINT32 (buffer + 8);
+  GST_LOG ("%*s  version/flags: %08x", depth, "", version);
+
+  if (version == 0x01000000) {
+    ctime = QT_UINT64 (buffer + 12);
+    mtime = QT_UINT64 (buffer + 20);
+    time_scale = QT_UINT32 (buffer + 28);
+    duration = QT_UINT64 (buffer + 32);
+    language = QT_UINT16 (buffer + 40);
+    quality = QT_UINT16 (buffer + 42);
+  } else {
+    ctime = QT_UINT32 (buffer + 12);
+    mtime = QT_UINT32 (buffer + 16);
+    time_scale = QT_UINT32 (buffer + 20);
+    duration = QT_UINT32 (buffer + 24);
+    language = QT_UINT16 (buffer + 28);
+    quality = QT_UINT16 (buffer + 30);
+  }
+
+  GST_LOG ("%*s  creation time: %" G_GUINT64_FORMAT, depth, "", ctime);
+  GST_LOG ("%*s  modify time:   %" G_GUINT64_FORMAT, depth, "", mtime);
+  GST_LOG ("%*s  time scale:    1/%u sec", depth, "", time_scale);
+  GST_LOG ("%*s  duration:      %" G_GUINT64_FORMAT, depth, "", duration);
+  GST_LOG ("%*s  language:      %u", depth, "", language);
+  GST_LOG ("%*s  quality:       %u", depth, "", quality);
+}
+
+void
+qtdemux_dump_hdlr (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  type:          %" GST_FOURCC_FORMAT, depth, "",
+      GST_FOURCC_ARGS (QT_FOURCC (buffer + 12)));
+  GST_LOG ("%*s  subtype:       %" GST_FOURCC_FORMAT, depth, "",
+      GST_FOURCC_ARGS (QT_FOURCC (buffer + 16)));
+  GST_LOG ("%*s  manufacturer:  %" GST_FOURCC_FORMAT, depth, "",
+      GST_FOURCC_ARGS (QT_FOURCC (buffer + 20)));
+  GST_LOG ("%*s  flags:         %08x", depth, "", QT_UINT32 (buffer + 24));
+  GST_LOG ("%*s  flags mask:    %08x", depth, "", QT_UINT32 (buffer + 28));
+  GST_LOG ("%*s  name:          %*s", depth, "",
+      QT_UINT8 (buffer + 32), (char *) (buffer + 33));
+
+}
+
+void
+qtdemux_dump_vmhd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  mode/color:    %08x", depth, "", QT_UINT32 (buffer + 16));
+}
+
+void
+qtdemux_dump_dref (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int n;
+  int i;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %u", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    size:          %u", depth, "",
+        QT_UINT32 (buffer + offset));
+    GST_LOG ("%*s    type:          %" GST_FOURCC_FORMAT, depth, "",
+        GST_FOURCC_ARGS (QT_FOURCC (buffer + offset + 4)));
+    offset += QT_UINT32 (buffer + offset);
+  }
+}
+
+void
+qtdemux_dump_stsd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    size:          %u", depth, "",
+        QT_UINT32 (buffer + offset));
+    GST_LOG ("%*s    type:          %" GST_FOURCC_FORMAT, depth, "",
+        GST_FOURCC_ARGS (QT_FOURCC (buffer + offset + 4)));
+    GST_LOG ("%*s    data reference:%d", depth, "",
+        QT_UINT16 (buffer + offset + 14));
+
+    GST_LOG ("%*s    version/rev.:  %08x", depth, "",
+        QT_UINT32 (buffer + offset + 16));
+    GST_LOG ("%*s    vendor:        %" GST_FOURCC_FORMAT, depth, "",
+        GST_FOURCC_ARGS (QT_FOURCC (buffer + offset + 20)));
+    GST_LOG ("%*s    temporal qual: %u", depth, "",
+        QT_UINT32 (buffer + offset + 24));
+    GST_LOG ("%*s    spatial qual:  %u", depth, "",
+        QT_UINT32 (buffer + offset + 28));
+    GST_LOG ("%*s    width:         %u", depth, "",
+        QT_UINT16 (buffer + offset + 32));
+    GST_LOG ("%*s    height:        %u", depth, "",
+        QT_UINT16 (buffer + offset + 34));
+    GST_LOG ("%*s    horiz. resol:  %g", depth, "",
+        QT_FP32 (buffer + offset + 36));
+    GST_LOG ("%*s    vert. resol.:  %g", depth, "",
+        QT_FP32 (buffer + offset + 40));
+    GST_LOG ("%*s    data size:     %u", depth, "",
+        QT_UINT32 (buffer + offset + 44));
+    GST_LOG ("%*s    frame count:   %u", depth, "",
+        QT_UINT16 (buffer + offset + 48));
+    GST_LOG ("%*s    compressor:    %d %d %d", depth, "",
+        QT_UINT8 (buffer + offset + 49),
+        QT_UINT8 (buffer + offset + 50), QT_UINT8 (buffer + offset + 51));
+    //(char *) (buffer + offset + 51));
+    GST_LOG ("%*s    depth:         %u", depth, "",
+        QT_UINT16 (buffer + offset + 82));
+    GST_LOG ("%*s    color table ID:%u", depth, "",
+        QT_UINT16 (buffer + offset + 84));
+
+    offset += QT_UINT32 (buffer + offset);
+  }
+}
+
+void
+qtdemux_dump_stts (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    count:         %u", depth, "",
+        QT_UINT32 (buffer + offset));
+    GST_LOG ("%*s    duration:      %u", depth, "",
+        QT_UINT32 (buffer + offset + 4));
+
+    offset += 8;
+  }
+}
+
+void
+qtdemux_dump_stps (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    sample:        %u", depth, "",
+        QT_UINT32 (buffer + offset));
+
+    offset += 4;
+  }
+}
+
+void
+qtdemux_dump_stss (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    sample:        %u", depth, "",
+        QT_UINT32 (buffer + offset));
+
+    offset += 4;
+  }
+}
+
+void
+qtdemux_dump_stsc (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    first chunk:   %u", depth, "",
+        QT_UINT32 (buffer + offset));
+    GST_LOG ("%*s    sample per ch: %u", depth, "",
+        QT_UINT32 (buffer + offset + 4));
+    GST_LOG ("%*s    sample desc id:%08x", depth, "",
+        QT_UINT32 (buffer + offset + 8));
+
+    offset += 12;
+  }
+}
+
+void
+qtdemux_dump_stsz (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  //int i;
+  int n;
+  int offset;
+  int sample_size;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  sample_size = QT_UINT32 (buffer + 12);
+  GST_LOG ("%*s  sample size:   %d", depth, "", sample_size);
+  if (sample_size == 0) {
+    GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 16));
+    n = QT_UINT32 (buffer + 16);
+    offset = 20;
+#if 0
+    for (i = 0; i < n; i++) {
+      GST_LOG ("%*s    sample size:   %u", depth, "",
+          QT_UINT32 (buffer + offset));
+
+      offset += 4;
+    }
+#endif
+  }
+}
+
+void
+qtdemux_dump_stco (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  n = QT_UINT32 (buffer + 12);
+  GST_LOG ("%*s  n entries:     %d", depth, "", n);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    chunk offset:  %d", depth, "",
+        QT_UINT32 (buffer + offset));
+
+    offset += 4;
+  }
+}
+
+void
+qtdemux_dump_ctts (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  n = QT_UINT32 (buffer + 12);
+  GST_LOG ("%*s  n entries:     %d", depth, "", n);
+  offset = 16;
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    sample count :%8d offset: %8d",
+        depth, "", QT_UINT32 (buffer + offset),
+        QT_UINT32 (buffer + offset + 4));
+
+    offset += 8;
+  }
+}
+
+void
+qtdemux_dump_co64 (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  //int i;
+  int n;
+  int offset;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
+  GST_LOG ("%*s  n entries:     %d", depth, "", QT_UINT32 (buffer + 12));
+  n = QT_UINT32 (buffer + 12);
+  offset = 16;
+#if 0
+  for (i = 0; i < n; i++) {
+    GST_LOG ("%*s    chunk offset:  %" G_GUINT64_FORMAT, depth, "",
+        QTDEMUX_GUINT64_GET (buffer + offset));
+
+    offset += 8;
+  }
+#endif
+}
+
+void
+qtdemux_dump_dcom (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  GST_LOG ("%*s  compression type: %" GST_FOURCC_FORMAT, depth, "",
+      GST_FOURCC_ARGS (QT_FOURCC (buffer + 8)));
+}
+
+void
+qtdemux_dump_cmvd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  GST_LOG ("%*s  length: %d", depth, "", QT_UINT32 (buffer + 8));
+}
+
+void
+qtdemux_dump_unknown (GstQTDemux * qtdemux, guint8 * buffer, int depth)
+{
+  int len;
+
+  GST_LOG ("%*s  length: %d", depth, "", QT_UINT32 (buffer + 0));
+
+  len = QT_UINT32 (buffer + 0);
+  GST_MEMDUMP_OBJECT (qtdemux, "unknown atom data", buffer, len);
+}
+
+static gboolean
+qtdemux_node_dump_foreach (GNode * node, gpointer qtdemux)
+{
+  guint8 *buffer = (guint8 *) node->data;
+  guint32 node_length;
+  guint32 fourcc;
+  const QtNodeType *type;
+  int depth;
+
+  node_length = GST_READ_UINT32_BE (buffer);
+  fourcc = GST_READ_UINT32_LE (buffer + 4);
+
+  type = qtdemux_type_get (fourcc);
+
+  depth = (g_node_depth (node) - 1) * 2;
+  GST_LOG ("%*s'%" GST_FOURCC_FORMAT "', [%d], %s",
+      depth, "", GST_FOURCC_ARGS (fourcc), node_length, type->name);
+
+  if (type->dump)
+    type->dump (GST_QTDEMUX_CAST (qtdemux), buffer, depth);
+
+  return FALSE;
+}
+
+void
+qtdemux_node_dump (GstQTDemux * qtdemux, GNode * node)
+{
+  if (__gst_debug_min < GST_LEVEL_LOG)
+    return;
+
+  g_node_traverse (qtdemux->moov_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+      qtdemux_node_dump_foreach, qtdemux);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux_dump.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,52 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_QTDEMUX_DUMP_H__
+#define __GST_QTDEMUX_DUMP_H__
+
+#include <gst/gst.h>
+#include <qtdemux.h>
+
+G_BEGIN_DECLS
+
+void qtdemux_dump_mvhd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_tkhd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_elst (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_mdhd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_hdlr (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_vmhd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_dref (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stsd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stts (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stss (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stps (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stsc (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stsz (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_stco (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_co64 (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_dcom (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_cmvd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_ctts (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+void qtdemux_dump_unknown (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+
+void qtdemux_node_dump (GstQTDemux * qtdemux, GNode * node);
+
+G_END_DECLS
+
+#endif /* __GST_QTDEMUX_DUMP_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux_fourcc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,178 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_QTDEMUX_FOURCC_H__
+#define __GST_QTDEMUX_FOURCC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define FOURCC_ftyp     GST_MAKE_FOURCC('f','t','y','p')
+#define FOURCC_qt__     GST_MAKE_FOURCC('q','t',' ',' ')
+#define FOURCC_moov     GST_MAKE_FOURCC('m','o','o','v')
+#define FOURCC_mvhd     GST_MAKE_FOURCC('m','v','h','d')
+#define FOURCC_clip     GST_MAKE_FOURCC('c','l','i','p')
+#define FOURCC_trak     GST_MAKE_FOURCC('t','r','a','k')
+#define FOURCC_udta     GST_MAKE_FOURCC('u','d','t','a')
+#define FOURCC_ctab     GST_MAKE_FOURCC('c','t','a','b')
+#define FOURCC_tkhd     GST_MAKE_FOURCC('t','k','h','d')
+#define FOURCC_crgn     GST_MAKE_FOURCC('c','r','g','n')
+#define FOURCC_matt     GST_MAKE_FOURCC('m','a','t','t')
+#define FOURCC_kmat     GST_MAKE_FOURCC('k','m','a','t')
+#define FOURCC_edts     GST_MAKE_FOURCC('e','d','t','s')
+#define FOURCC_elst     GST_MAKE_FOURCC('e','l','s','t')
+#define FOURCC_load     GST_MAKE_FOURCC('l','o','a','d')
+#define FOURCC_tref     GST_MAKE_FOURCC('t','r','e','f')
+#define FOURCC_imap     GST_MAKE_FOURCC('i','m','a','p')
+#define FOURCC___in     GST_MAKE_FOURCC(' ',' ','i','n')
+#define FOURCC___ty     GST_MAKE_FOURCC(' ',' ','t','y')
+#define FOURCC_mdia     GST_MAKE_FOURCC('m','d','i','a')
+#define FOURCC_mdhd     GST_MAKE_FOURCC('m','d','h','d')
+#define FOURCC_hdlr     GST_MAKE_FOURCC('h','d','l','r')
+#define FOURCC_minf     GST_MAKE_FOURCC('m','i','n','f')
+#define FOURCC_vmhd     GST_MAKE_FOURCC('v','m','h','d')
+#define FOURCC_smhd     GST_MAKE_FOURCC('s','m','h','d')
+#define FOURCC_gmhd     GST_MAKE_FOURCC('g','m','h','d')
+#define FOURCC_gmin     GST_MAKE_FOURCC('g','m','i','n')
+#define FOURCC_dinf     GST_MAKE_FOURCC('d','i','n','f')
+#define FOURCC_dref     GST_MAKE_FOURCC('d','r','e','f')
+#define FOURCC_stbl     GST_MAKE_FOURCC('s','t','b','l')
+#define FOURCC_stsd     GST_MAKE_FOURCC('s','t','s','d')
+#define FOURCC_stts     GST_MAKE_FOURCC('s','t','t','s')
+#define FOURCC_stss     GST_MAKE_FOURCC('s','t','s','s')
+#define FOURCC_stps     GST_MAKE_FOURCC('s','t','p','s')
+#define FOURCC_stsc     GST_MAKE_FOURCC('s','t','s','c')
+#define FOURCC_stsz     GST_MAKE_FOURCC('s','t','s','z')
+#define FOURCC_stco     GST_MAKE_FOURCC('s','t','c','o')
+#define FOURCC_vide     GST_MAKE_FOURCC('v','i','d','e')
+#define FOURCC_soun     GST_MAKE_FOURCC('s','o','u','n')
+#define FOURCC_subp     GST_MAKE_FOURCC('s','u','b','p')
+#define FOURCC_strm     GST_MAKE_FOURCC('s','t','r','m')
+#define FOURCC_rtsp     GST_MAKE_FOURCC('r','t','s','p')
+#define FOURCC_co64     GST_MAKE_FOURCC('c','o','6','4')
+#define FOURCC_cmov     GST_MAKE_FOURCC('c','m','o','v')
+#define FOURCC_dcom     GST_MAKE_FOURCC('d','c','o','m')
+#define FOURCC_cmvd     GST_MAKE_FOURCC('c','m','v','d')
+#define FOURCC_hint     GST_MAKE_FOURCC('h','i','n','t')
+#define FOURCC_mp4a     GST_MAKE_FOURCC('m','p','4','a')
+#define FOURCC_mp4v     GST_MAKE_FOURCC('m','p','4','v')
+#define FOURCC_wave     GST_MAKE_FOURCC('w','a','v','e')
+#define FOURCC_appl     GST_MAKE_FOURCC('a','p','p','l')
+#define FOURCC_esds     GST_MAKE_FOURCC('e','s','d','s')
+#define FOURCC_pasp     GST_MAKE_FOURCC('p','a','s','p')
+#define FOURCC_hnti     GST_MAKE_FOURCC('h','n','t','i')
+#define FOURCC_rtp_     GST_MAKE_FOURCC('r','t','p',' ')
+#define FOURCC_sdp_     GST_MAKE_FOURCC('s','d','p',' ')
+#define FOURCC_meta     GST_MAKE_FOURCC('m','e','t','a')
+#define FOURCC_ilst     GST_MAKE_FOURCC('i','l','s','t')
+#define FOURCC__nam     GST_MAKE_FOURCC(0xa9,'n','a','m')
+#define FOURCC__cmt     GST_MAKE_FOURCC(0xa9,'c','m','t')
+#define FOURCC__des     GST_MAKE_FOURCC(0xa9,'d','e','s')
+#define FOURCC__cpy     GST_MAKE_FOURCC(0xa9,'c','p','y')
+#define FOURCC__ART     GST_MAKE_FOURCC(0xa9,'A','R','T')
+#define FOURCC__wrt     GST_MAKE_FOURCC(0xa9,'w','r','t')
+#define FOURCC__grp     GST_MAKE_FOURCC(0xa9,'g','r','p')
+#define FOURCC__alb     GST_MAKE_FOURCC(0xa9,'a','l','b')
+#define FOURCC__day     GST_MAKE_FOURCC(0xa9,'d','a','y')
+#define FOURCC__req     GST_MAKE_FOURCC(0xa9,'r','e','q')
+#define FOURCC__enc     GST_MAKE_FOURCC(0xa9,'e','n','c')
+#define FOURCC__inf     GST_MAKE_FOURCC(0xa9,'i','n','f')
+#define FOURCC_cprt     GST_MAKE_FOURCC('c','p','r','t')
+#define FOURCC_gnre     GST_MAKE_FOURCC('g','n','r','e')
+#define FOURCC_disc     GST_MAKE_FOURCC('d','i','s','c')
+#define FOURCC_disk     GST_MAKE_FOURCC('d','i','s','k')
+#define FOURCC_trkn     GST_MAKE_FOURCC('t','r','k','n')
+#define FOURCC_cpil     GST_MAKE_FOURCC('c','p','i','l')
+#define FOURCC_tmpo     GST_MAKE_FOURCC('t','m','p','o')
+#define FOURCC_covr     GST_MAKE_FOURCC('c','o','v','r')
+#define FOURCC__too     GST_MAKE_FOURCC(0xa9,'t','o','o')
+#define FOURCC_____     GST_MAKE_FOURCC('-','-','-','-')
+#define FOURCC_free     GST_MAKE_FOURCC('f','r','e','e')
+#define FOURCC_data     GST_MAKE_FOURCC('d','a','t','a')
+#define FOURCC_SVQ3     GST_MAKE_FOURCC('S','V','Q','3')
+#define FOURCC_rmra     GST_MAKE_FOURCC('r','m','r','a')
+#define FOURCC_rmda     GST_MAKE_FOURCC('r','m','d','a')
+#define FOURCC_rdrf     GST_MAKE_FOURCC('r','d','r','f')
+#define FOURCC__gen     GST_MAKE_FOURCC(0xa9, 'g', 'e', 'n')
+#define FOURCC_rmdr     GST_MAKE_FOURCC('r','m','d','r')
+#define FOURCC_rmvc     GST_MAKE_FOURCC('r','m','v','c')
+#define FOURCC_qtim     GST_MAKE_FOURCC('q','t','i','m')
+#define FOURCC_drms     GST_MAKE_FOURCC('d','r','m','s')
+#define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
+#define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
+#define FOURCC_VP31     GST_MAKE_FOURCC('V','P','3','1')
+#define FOURCC_rle_     GST_MAKE_FOURCC('r','l','e',' ')
+#define FOURCC_MAC6     GST_MAKE_FOURCC('M','A','C','6')
+#define FOURCC_MAC3     GST_MAKE_FOURCC('M','A','C','3')
+#define FOURCC_ima4     GST_MAKE_FOURCC('i','m','a','4')
+#define FOURCC_ulaw     GST_MAKE_FOURCC('u','l','a','w')
+#define FOURCC_alaw     GST_MAKE_FOURCC('a','l','a','w')
+#define FOURCC_twos     GST_MAKE_FOURCC('t','w','o','s')
+#define FOURCC_sowt     GST_MAKE_FOURCC('s','o','w','t')
+#define FOURCC_raw_     GST_MAKE_FOURCC('r','a','w',' ')
+#define FOURCC_in24     GST_MAKE_FOURCC('i','n','2','4')
+#define FOURCC_enda     GST_MAKE_FOURCC('e','n','d','a')
+#define FOURCC_QDM2     GST_MAKE_FOURCC('Q','D','M','2')
+#define FOURCC_alac     GST_MAKE_FOURCC('a','l','a','c')
+#define FOURCC_samr     GST_MAKE_FOURCC('s','a','m','r')
+#define FOURCC_sawb     GST_MAKE_FOURCC('s','a','w','b')
+#define FOURCC_mdat     GST_MAKE_FOURCC('m','d','a','t')
+#define FOURCC_wide     GST_MAKE_FOURCC('w','i','d','e')
+#define FOURCC_PICT     GST_MAKE_FOURCC('P','I','C','T')
+#define FOURCC_pnot     GST_MAKE_FOURCC('p','n','o','t')
+#define FOURCC_zlib     GST_MAKE_FOURCC('z','l','i','b')
+#define FOURCC_alis     GST_MAKE_FOURCC('a','l','i','s')
+#define FOURCC_url_     GST_MAKE_FOURCC('u','r','l',' ')
+#define FOURCC_frma     GST_MAKE_FOURCC('f','r','m','a')
+#define FOURCC_ctts     GST_MAKE_FOURCC('c','t','t','s')
+#define FOURCC_keyw     GST_MAKE_FOURCC('k','e','y','w')
+#define FOURCC_kywd     GST_MAKE_FOURCC('k','y','w','d')
+#define FOURCC_agsm     GST_MAKE_FOURCC('a','g','s','m')
+
+/* 3gpp asset meta data fourcc */
+#define FOURCC_titl     GST_MAKE_FOURCC('t','i','t','l')
+#define FOURCC_dscp     GST_MAKE_FOURCC('d','s','c','p')
+#define FOURCC_perf     GST_MAKE_FOURCC('p','e','r','f')
+#define FOURCC_auth     GST_MAKE_FOURCC('a','u','t','h')
+#define FOURCC_rtng     GST_MAKE_FOURCC('r','t','n','g')
+#define FOURCC_clsf     GST_MAKE_FOURCC('c','l','s','f')
+#define FOURCC_loci     GST_MAKE_FOURCC('l','o','c','i')
+#define FOURCC_albm     GST_MAKE_FOURCC('a','l','b','m')
+#define FOURCC_yrrc     GST_MAKE_FOURCC('y','r','r','c')
+
+/* ISO Motion JPEG 2000 fourcc */
+#define FOURCC_mjp2     GST_MAKE_FOURCC('m','j','p','2')
+#define FOURCC_jp2h     GST_MAKE_FOURCC('j','p','2','h')
+#define FOURCC_colr     GST_MAKE_FOURCC('c','o','l','r')
+#define FOURCC_fiel     GST_MAKE_FOURCC('f','i','e','l')
+#define FOURCC_jp2x     GST_MAKE_FOURCC('j','p','2','x')
+/* some buggy hardware's notion of mdhd */
+#define FOURCC_mhdr     GST_MAKE_FOURCC('m','h','d','r')
+
+/* Xiph fourcc */
+#define FOURCC_XiTh     GST_MAKE_FOURCC('X','i','T','h')
+#define FOURCC_XdxT     GST_MAKE_FOURCC('X','d','x','T')
+#define FOURCC_tCtH     GST_MAKE_FOURCC('t','C','t','H')
+#define FOURCC_tCt_     GST_MAKE_FOURCC('t','C','t','#')
+#define FOURCC_tCtC     GST_MAKE_FOURCC('t','C','t','C')
+
+G_END_DECLS
+
+#endif /* __GST_QTDEMUX_FOURCC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux_types.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,157 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 "qtdemux_types.h"
+#include "qtdemux_dump.h"
+#include "qtdemux_fourcc.h"
+
+static const QtNodeType qt_node_types[] = {
+  {FOURCC_moov, "movie", QT_FLAG_CONTAINER,},
+  {FOURCC_mvhd, "movie header", 0,
+      qtdemux_dump_mvhd},
+  {FOURCC_clip, "clipping", QT_FLAG_CONTAINER,},
+  {FOURCC_trak, "track", QT_FLAG_CONTAINER,},
+  {FOURCC_udta, "user data", QT_FLAG_CONTAINER,},       /* special container */
+  {FOURCC_ctab, "color table", 0,},
+  {FOURCC_tkhd, "track header", 0,
+      qtdemux_dump_tkhd},
+  {FOURCC_crgn, "clipping region", 0,},
+  {FOURCC_matt, "track matte", QT_FLAG_CONTAINER,},
+  {FOURCC_kmat, "compressed matte", 0,},
+  {FOURCC_edts, "edit", QT_FLAG_CONTAINER,},
+  {FOURCC_elst, "edit list", 0,
+      qtdemux_dump_elst},
+  {FOURCC_load, "track load settings", 0,},
+  {FOURCC_tref, "track reference", QT_FLAG_CONTAINER,},
+  {FOURCC_imap, "track input map", QT_FLAG_CONTAINER,},
+  {FOURCC___in, "track input", 0,},     /* special container */
+  {FOURCC___ty, "input type", 0,},
+  {FOURCC_mdia, "media", QT_FLAG_CONTAINER},
+  {FOURCC_mdhd, "media header", 0,
+      qtdemux_dump_mdhd},
+  {FOURCC_hdlr, "handler reference", 0,
+      qtdemux_dump_hdlr},
+  {FOURCC_minf, "media information", QT_FLAG_CONTAINER},
+  {FOURCC_vmhd, "video media information", 0,
+      qtdemux_dump_vmhd},
+  {FOURCC_smhd, "sound media information", 0},
+  {FOURCC_gmhd, "base media information header", 0},
+  {FOURCC_gmin, "base media info", 0},
+  {FOURCC_dinf, "data information", QT_FLAG_CONTAINER},
+  {FOURCC_dref, "data reference", 0,
+      qtdemux_dump_dref},
+  {FOURCC_stbl, "sample table", QT_FLAG_CONTAINER},
+  {FOURCC_stsd, "sample description", 0,
+      qtdemux_dump_stsd},
+  {FOURCC_stts, "time-to-sample", 0,
+      qtdemux_dump_stts},
+  {FOURCC_stps, "partial sync sample", 0,
+      qtdemux_dump_stps},
+  {FOURCC_stss, "sync sample", 0,
+      qtdemux_dump_stss},
+  {FOURCC_stsc, "sample-to-chunk", 0,
+      qtdemux_dump_stsc},
+  {FOURCC_stsz, "sample size", 0,
+      qtdemux_dump_stsz},
+  {FOURCC_stco, "chunk offset", 0,
+      qtdemux_dump_stco},
+  {FOURCC_co64, "64-bit chunk offset", 0,
+      qtdemux_dump_co64},
+  {FOURCC_vide, "video media", 0},
+  {FOURCC_cmov, "compressed movie", QT_FLAG_CONTAINER},
+  {FOURCC_dcom, "compressed data", 0, qtdemux_dump_dcom},
+  {FOURCC_cmvd, "compressed movie data", 0, qtdemux_dump_cmvd},
+  {FOURCC_hint, "hint", 0,},
+  {FOURCC_mp4a, "mp4a", 0,},
+  {FOURCC_mp4v, "mp4v", 0,},
+  {FOURCC_mjp2, "mjp2", 0,},
+  {FOURCC_mhdr, "mhdr", QT_FLAG_CONTAINER,},
+  {FOURCC_jp2h, "jp2h", QT_FLAG_CONTAINER,},
+  {FOURCC_colr, "colr", 0,},
+  {FOURCC_fiel, "fiel", 0,},
+  {FOURCC_jp2x, "jp2x", 0,},
+  {FOURCC_wave, "wave", QT_FLAG_CONTAINER},
+  {FOURCC_appl, "appl", QT_FLAG_CONTAINER},
+  {FOURCC_esds, "esds", 0},
+  {FOURCC_hnti, "hnti", QT_FLAG_CONTAINER},
+  {FOURCC_rtp_, "rtp ", 0, qtdemux_dump_unknown},
+  {FOURCC_sdp_, "sdp ", 0, qtdemux_dump_unknown},
+  {FOURCC_meta, "meta", 0, qtdemux_dump_unknown},
+  {FOURCC_ilst, "ilst", QT_FLAG_CONTAINER,},
+  {FOURCC__nam, "Name", QT_FLAG_CONTAINER,},
+  {FOURCC_titl, "Title", QT_FLAG_CONTAINER,},
+  {FOURCC__ART, "Artist", QT_FLAG_CONTAINER,},
+  {FOURCC_auth, "Author", QT_FLAG_CONTAINER,},
+  {FOURCC_perf, "Performer", QT_FLAG_CONTAINER,},
+  {FOURCC__wrt, "Writer", QT_FLAG_CONTAINER,},
+  {FOURCC__grp, "Group", QT_FLAG_CONTAINER,},
+  {FOURCC__alb, "Album", QT_FLAG_CONTAINER,},
+  {FOURCC_albm, "Album", QT_FLAG_CONTAINER,},
+  {FOURCC__day, "Date", QT_FLAG_CONTAINER,},
+  {FOURCC__cpy, "Copyright", QT_FLAG_CONTAINER,},
+  {FOURCC__cmt, "Comment", QT_FLAG_CONTAINER,},
+  {FOURCC__des, "Description", QT_FLAG_CONTAINER,},
+  {FOURCC_dscp, "Description", QT_FLAG_CONTAINER,},
+  {FOURCC__req, "Requirement", QT_FLAG_CONTAINER,},
+  {FOURCC__enc, "Encoder", QT_FLAG_CONTAINER,},
+  {FOURCC_gnre, "Genre", QT_FLAG_CONTAINER,},
+  {FOURCC_trkn, "Track Number", QT_FLAG_CONTAINER,},
+  {FOURCC_disc, "Disc Number", QT_FLAG_CONTAINER,},
+  {FOURCC_disk, "Disc Number", QT_FLAG_CONTAINER,},
+  {FOURCC_cprt, "Copyright", QT_FLAG_CONTAINER,},
+  {FOURCC_cpil, "cpil", QT_FLAG_CONTAINER,},
+  {FOURCC_tmpo, "Tempo", QT_FLAG_CONTAINER,},
+  {FOURCC_covr, "Cover", QT_FLAG_CONTAINER,},
+  {FOURCC_keyw, "Keywords", QT_FLAG_CONTAINER,},
+  {FOURCC_kywd, "Keywords", QT_FLAG_CONTAINER,},
+  {FOURCC__too, "too", QT_FLAG_CONTAINER,},
+  {FOURCC_____, "----", QT_FLAG_CONTAINER,},
+  {FOURCC_data, "data", 0, qtdemux_dump_unknown},
+  {FOURCC_free, "free", 0,},
+  {FOURCC_SVQ3, "SVQ3", 0,},
+  {FOURCC_rmra, "rmra", QT_FLAG_CONTAINER,},
+  {FOURCC_rmda, "rmda", QT_FLAG_CONTAINER,},
+  {FOURCC_rdrf, "rdrf", 0,},
+  {FOURCC__gen, "Custom Genre", QT_FLAG_CONTAINER,},
+  {FOURCC_ctts, "Composition time to sample", 0, qtdemux_dump_ctts},
+  {FOURCC_XiTh, "XiTh", 0},
+  {FOURCC_XdxT, "XdxT", 0},
+  {FOURCC_loci, "loci", 0},
+  {FOURCC_clsf, "clsf", 0},
+  {0, "unknown", 0,},
+};
+
+static const int n_qt_node_types =
+    sizeof (qt_node_types) / sizeof (qt_node_types[0]);
+
+const QtNodeType *
+qtdemux_type_get (guint32 fourcc)
+{
+  int i;
+
+  for (i = 0; i < n_qt_node_types; i++) {
+    if (G_UNLIKELY (qt_node_types[i].fourcc == fourcc))
+      return qt_node_types + i;
+  }
+
+  GST_WARNING ("unknown QuickTime node type %" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (fourcc));
+
+  return qt_node_types + n_qt_node_types - 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtdemux_types.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,58 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_QTDEMUX_TYPES_H__
+#define __GST_QTDEMUX_TYPES_H__
+
+#include <gst/gst.h>
+
+#include "qtdemux.h"
+
+G_BEGIN_DECLS
+
+typedef void (*QtDumpFunc) (GstQTDemux * qtdemux, guint8 * buffer, int depth);
+
+typedef struct _QtNodeType QtNodeType;
+
+#define QT_UINT32(a)  (GST_READ_UINT32_BE(a))
+#define QT_UINT24(a)  (GST_READ_UINT32_BE(a) >> 8)
+#define QT_UINT16(a)  (GST_READ_UINT16_BE(a))
+#define QT_UINT8(a)   (GST_READ_UINT8(a))
+#define QT_FP32(a)    ((GST_READ_UINT32_BE(a))/65536.0)
+#define QT_FP16(a)    ((GST_READ_UINT16_BE(a))/256.0)
+#define QT_FOURCC(a)  (GST_READ_UINT32_LE(a))
+#define QT_UINT64(a)  ((((guint64)QT_UINT32(a))<<32)|QT_UINT32(((guint8 *)a)+4))
+
+typedef enum {
+  QT_FLAG_NONE      = (0),
+  QT_FLAG_CONTAINER = (1 << 0) 
+} QtFlags;
+
+struct _QtNodeType {
+  guint32      fourcc;
+  const gchar *name;
+  QtFlags      flags;
+  QtDumpFunc   dump;
+};
+
+const QtNodeType *qtdemux_type_get (guint32 fourcc);
+
+G_END_DECLS
+
+#endif /* __GST_QTDEMUX_TYPES_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/qtpalette.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,137 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_QTPALLETE_H__
+#define __GST_QTPALLETE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+static const guint32 ff_qt_default_palette_2[2] = {
+  0xffffff, 0x000000
+};
+
+static const guint32 ff_qt_default_palette_4[4] = {
+  0x93655e, 0xffffff, 0xdfd0ab, 0x000000
+};
+
+static const guint32 ff_qt_default_palette_16[16] = {
+  0xfffbff, 0xefd9bb, 0xe8c9b1, 0x93655e,
+  0xfcdee8, 0x9d8891, 0xffffff, 0xffffff,
+  0xffffff, 0x474837, 0x7a5e55, 0xdfd0ab,
+  0xfffbf9, 0xe8cac5, 0x8a7c77, 0x000000
+};
+static const guint32 ff_qt_default_palette_256[256] = {
+  0xFFFFFF, 0xFFFFCC, 0xFFFF99, 0xFFFF66, 0xFFFF33, 0xFFFF00,
+  0xFFCCFF, 0xFFCCCC, 0xFFCC99, 0xFFCC66, 0xFFCC33, 0xFFCC00,
+  0xFF99FF, 0xFF99CC, 0xFF9999, 0xFF9966, 0xFF9933, 0xFF9900,
+  0xFF66FF, 0xFF66CC, 0xFF6699, 0xFF6666, 0xFF6633, 0xFF6600,
+  0xFF33FF, 0xFF33CC, 0xFF3399, 0xFF3366, 0xFF3333, 0xFF3300,
+  0xFF00FF, 0xFF00CC, 0xFF0099, 0xFF0066, 0xFF0033, 0xFF0000,
+  0xCCFFFF, 0xCCFFCC, 0xCCFF99, 0xCCFF66, 0xCCFF33, 0xCCFF00,
+  0xCCCCFF, 0xCCCCCC, 0xCCCC99, 0xCCCC66, 0xCCCC33, 0xCCCC00,
+  0xCC99FF, 0xCC99CC, 0xCC9999, 0xCC9966, 0xCC9933, 0xCC9900,
+  0xCC66FF, 0xCC66CC, 0xCC6699, 0xCC6666, 0xCC6633, 0xCC6600,
+  0xCC33FF, 0xCC33CC, 0xCC3399, 0xCC3366, 0xCC3333, 0xCC3300,
+  0xCC00FF, 0xCC00CC, 0xCC0099, 0xCC0066, 0xCC0033, 0xCC0000,
+  0x99FFFF, 0x99FFCC, 0x99FF99, 0x99FF66, 0x99FF33, 0x99FF00,
+  0x99CCFF, 0x99CCCC, 0x99CC99, 0x99CC66, 0x99CC33, 0x99CC00,
+  0x9999FF, 0x9999CC, 0x999999, 0x999966, 0x999933, 0x999900,
+  0x9966FF, 0x9966CC, 0x996699, 0x996666, 0x996633, 0x996600,
+  0x9933FF, 0x9933CC, 0x993399, 0x993366, 0x993333, 0x993300,
+  0x9900FF, 0x9900CC, 0x990099, 0x990066, 0x990033, 0x990000,
+  0x66FFFF, 0x66FFCC, 0x66FF99, 0x66FF66, 0x66FF33, 0x66FF00,
+  0x66CCFF, 0x66CCCC, 0x66CC99, 0x66CC66, 0x66CC33, 0x66CC00,
+  0x6699FF, 0x6699CC, 0x669999, 0x669966, 0x669933, 0x669900,
+  0x6666FF, 0x6666CC, 0x666699, 0x666666, 0x666633, 0x666600,
+  0x6633FF, 0x6633CC, 0x663399, 0x663366, 0x663333, 0x663300,
+  0x6600FF, 0x6600CC, 0x660099, 0x660066, 0x660033, 0x660000,
+  0x33FFFF, 0x33FFCC, 0x33FF99, 0x33FF66, 0x33FF33, 0x33FF00,
+  0x33CCFF, 0x33CCCC, 0x33CC99, 0x33CC66, 0x33CC33, 0x33CC00,
+  0x3399FF, 0x3399CC, 0x339999, 0x339966, 0x339933, 0x339900,
+  0x3366FF, 0x3366CC, 0x336699, 0x336666, 0x336633, 0x336600,
+  0x3333FF, 0x3333CC, 0x333399, 0x333366, 0x333333, 0x333300,
+  0x3300FF, 0x3300CC, 0x330099, 0x330066, 0x330033, 0x330000,
+  0x00FFFF, 0x00FFCC, 0x00FF99, 0x00FF66, 0x00FF33, 0x00FF00,
+  0x00CCFF, 0x00CCCC, 0x00CC99, 0x00CC66, 0x00CC33, 0x00CC00,
+  0x0099FF, 0x0099CC, 0x009999, 0x009966, 0x009933, 0x009900,
+  0x0066FF, 0x0066CC, 0x006699, 0x006666, 0x006633, 0x006600,
+  0x0033FF, 0x0033CC, 0x003399, 0x003366, 0x003333, 0x003300,
+  0x0000FF, 0x0000CC, 0x000099, 0x000066, 0x000033, 0xEE0000,
+  0xDD0000, 0xBB0000, 0xAA0000, 0x880000, 0x770000, 0x550000,
+  0x440000, 0x220000, 0x110000, 0x00EE00, 0x00DD00, 0x00BB00,
+  0x00AA00, 0x008800, 0x007700, 0x005500, 0x004400, 0x002200,
+  0x001100, 0x0000EE, 0x0000DD, 0x0000BB, 0x0000AA, 0x000088,
+  0x000077, 0x000055, 0x000044, 0x000022, 0x000011, 0xEEEEEE,
+  0xDDDDDD, 0xBBBBBB, 0xAAAAAA, 0x888888, 0x777777, 0x555555,
+  0x444444, 0x222222, 0x111111, 0x000000
+};
+
+static const guint32 ff_qt_grayscale_palette_16[16] = {
+  0xffffff, 0xeeeeee, 0xdddddd, 0xcccccc,
+  0xbbbbbb, 0xaaaaaa, 0x999999, 0x888888,
+  0x777777, 0x666666, 0x555555, 0x444444,
+  0x333333, 0x222222, 0x111111, 0x000000
+};
+
+static const guint32 ff_qt_grayscale_palette_256[256] = {
+  0xffffff, 0xfefefe, 0xfdfdfd, 0xfcfcfc, 0xfbfbfb, 0xfafafa, 0xf9f9f9,
+  0xf8f8f8, 0xf7f7f7, 0xf6f6f6, 0xf5f5f5, 0xf4f4f4, 0xf3f3f3, 0xf2f2f2,
+  0xf1f1f1, 0xf0f0f0, 0xefefef, 0xeeeeee, 0xededed, 0xececec, 0xebebeb,
+  0xeaeaea, 0xe9e9e9, 0xe8e8e8, 0xe7e7e7, 0xe6e6e6, 0xe5e5e5, 0xe4e4e4,
+  0xe3e3e3, 0xe2e2e2, 0xe1e1e1, 0xe0e0e0, 0xdfdfdf, 0xdedede, 0xdddddd,
+  0xdcdcdc, 0xdbdbdb, 0xdadada, 0xd9d9d9, 0xd8d8d8, 0xd7d7d7, 0xd6d6d6,
+  0xd5d5d5, 0xd4d4d4, 0xd3d3d3, 0xd2d2d2, 0xd1d1d1, 0xd0d0d0, 0xcfcfcf,
+  0xcecece, 0xcdcdcd, 0xcccccc, 0xcbcbcb, 0xcacaca, 0xc9c9c9, 0xc8c8c8,
+  0xc7c7c7, 0xc6c6c6, 0xc5c5c5, 0xc4c4c4, 0xc3c3c3, 0xc2c2c2, 0xc1c1c1,
+  0xc0c0c0, 0xbfbfbf, 0xbebebe, 0xbdbdbd, 0xbcbcbc, 0xbbbbbb, 0xbababa,
+  0xb9b9b9, 0xb8b8b8, 0xb7b7b7, 0xb6b6b6, 0xb5b5b5, 0xb4b4b4, 0xb3b3b3,
+  0xb2b2b2, 0xb1b1b1, 0xb0b0b0, 0xafafaf, 0xaeaeae, 0xadadad, 0xacacac,
+  0xababab, 0xaaaaaa, 0xa9a9a9, 0xa8a8a8, 0xa7a7a7, 0xa6a6a6, 0xa5a5a5,
+  0xa4a4a4, 0xa3a3a3, 0xa2a2a2, 0xa1a1a1, 0xa0a0a0, 0x9f9f9f, 0x9e9e9e,
+  0x9d9d9d, 0x9c9c9c, 0x9b9b9b, 0x9a9a9a, 0x999999, 0x989898, 0x979797,
+  0x969696, 0x959595, 0x949494, 0x939393, 0x929292, 0x919191, 0x909090,
+  0x8f8f8f, 0x8e8e8e, 0x8d8d8d, 0x8c8c8c, 0x8b8b8b, 0x8a8a8a, 0x898989,
+  0x888888, 0x878787, 0x868686, 0x858585, 0x848484, 0x838383, 0x828282,
+  0x818181, 0x808080, 0x7f7f7f, 0x7e7e7e, 0x7d7d7d, 0x7c7c7c, 0x7b7b7b,
+  0x7a7a7a, 0x797979, 0x787878, 0x777777, 0x767676, 0x757575, 0x747474,
+  0x737373, 0x727272, 0x717171, 0x707070, 0x6f6f6f, 0x6e6e6e, 0x6d6d6d,
+  0x6c6c6c, 0x6b6b6b, 0x6a6a6a, 0x696969, 0x686868, 0x676767, 0x666666,
+  0x656565, 0x646464, 0x636363, 0x626262, 0x616161, 0x606060, 0x5f5f5f,
+  0x5e5e5e, 0x5d5d5d, 0x5c5c5c, 0x5b5b5b, 0x5a5a5a, 0x595959, 0x585858,
+  0x575757, 0x565656, 0x555555, 0x545454, 0x535353, 0x525252, 0x515151,
+  0x505050, 0x4f4f4f, 0x4e4e4e, 0x4d4d4d, 0x4c4c4c, 0x4b4b4b, 0x4a4a4a,
+  0x494949, 0x484848, 0x474747, 0x464646, 0x454545, 0x444444, 0x434343,
+  0x424242, 0x414141, 0x404040, 0x3f3f3f, 0x3e3e3e, 0x3d3d3d, 0x3c3c3c,
+  0x3b3b3b, 0x3a3a3a, 0x393939, 0x383838, 0x373737, 0x363636, 0x353535,
+  0x343434, 0x333333, 0x323232, 0x313131, 0x303030, 0x2f2f2f, 0x2e2e2e,
+  0x2d2d2d, 0x2c2c2c, 0x2b2b2b, 0x2a2a2a, 0x292929, 0x282828, 0x272727,
+  0x262626, 0x252525, 0x242424, 0x232323, 0x222222, 0x212121, 0x202020,
+  0x1f1f1f, 0x1e1e1e, 0x1d1d1d, 0x1c1c1c, 0x1b1b1b, 0x1a1a1a, 0x191919,
+  0x181818, 0x171717, 0x161616, 0x151515, 0x141414, 0x131313, 0x121212,
+  0x111111, 0x101010, 0x0f0f0f, 0x0e0e0e, 0x0d0d0d, 0x0c0c0c, 0x0b0b0b,
+  0x0a0a0a, 0x090909, 0x080808, 0x070707, 0x060606, 0x050505, 0x040404,
+  0x030303, 0x020202, 0x010101, 0x000000
+};
+
+G_END_DECLS
+
+#endif /* __GST_QTPALETTE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtdemux/quicktime.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,71 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
+ * Copyright (C) <2006> Wim Taymans <wim@fluendo.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "gst/gst-i18n-plugin.h"
+
+#include "qtdemux.h"
+#include "gstrtpxqtdepay.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+#ifdef ENABLE_NLS
+  setlocale (LC_ALL, "");
+  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif /* ENABLE_NLS */
+
+  /* ensure private tag is registered */
+  gst_tag_register (GST_QT_DEMUX_PRIVATE_TAG, GST_TAG_FLAG_META,
+      GST_TYPE_BUFFER, "QT atom", "unparsed QT tag atom",
+      gst_tag_merge_use_first);
+
+  gst_tag_register (GST_QT_DEMUX_CLASSIFICATION_TAG, GST_TAG_FLAG_META,
+      G_TYPE_STRING, GST_QT_DEMUX_CLASSIFICATION_TAG, "content classification",
+      gst_tag_merge_use_first);
+
+  if (!gst_element_register (plugin, "qtdemux",
+          GST_RANK_PRIMARY, GST_TYPE_QTDEMUX))
+    return FALSE;
+
+  if (!gst_element_register (plugin, "rtpxqtdepay",
+          GST_RANK_MARGINAL, GST_TYPE_RTP_XQT_DEPAY))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "quicktime",
+    "Quicktime support",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
+
+#ifdef SYMBIAN
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+{
+    return &gst_plugin_desc;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/atoms.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3173 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "atoms.h"
+#include <string.h>
+#include <glib.h>
+
+/* only needed for gst_util_uint64_scale */
+#include <gst/gst.h>
+
+/**
+ * Creates a new AtomsContext for the given flavor.
+ */
+AtomsContext *
+atoms_context_new (AtomsTreeFlavor flavor)
+{
+  AtomsContext *context = g_new0 (AtomsContext, 1);
+  context->flavor = flavor;
+  return context;
+}
+
+/**
+ * Frees an AtomsContext and all memory associated with it
+ */
+void
+atoms_context_free (AtomsContext * context)
+{
+  g_free (context);
+}
+
+/* -- creation, initialization, clear and free functions -- */
+
+#define SECS_PER_DAY (24 * 60 * 60)
+#define LEAP_YEARS_FROM_1904_TO_1970 17
+
+static guint64
+get_current_qt_time ()
+{
+  GTimeVal timeval;
+
+  g_get_current_time (&timeval);
+  /* FIXME this should use UTC coordinated time */
+  return timeval.tv_sec + (((1970 - 1904) * (guint64) 365) +
+      LEAP_YEARS_FROM_1904_TO_1970) * SECS_PER_DAY;
+}
+
+static void
+common_time_info_init (TimeInfo * ti)
+{
+  ti->creation_time = ti->modification_time = get_current_qt_time ();
+  ti->timescale = 0;
+  ti->duration = 0;
+}
+
+static void
+atom_header_set (Atom * header, guint32 fourcc, gint32 size, gint64 ext_size)
+{
+  header->type = fourcc;
+  header->size = size;
+  header->extended_size = ext_size;
+}
+
+static void
+atom_clear (Atom * atom)
+{
+}
+
+static void
+atom_full_init (AtomFull * full, guint32 fourcc, gint32 size, gint64 ext_size,
+    guint8 version, guint8 flags[3])
+{
+  atom_header_set (&(full->header), fourcc, size, ext_size);
+  full->version = version;
+  full->flags[0] = flags[0];
+  full->flags[1] = flags[1];
+  full->flags[2] = flags[2];
+}
+
+static void
+atom_full_clear (AtomFull * full)
+{
+  atom_clear (&full->header);
+}
+
+static void
+atom_full_free (AtomFull * full)
+{
+  atom_full_clear (full);
+  g_free (full);
+}
+
+static AtomInfo *
+build_atom_info_wrapper (Atom * atom, gpointer copy_func, gpointer free_func)
+{
+  AtomInfo *info = NULL;
+
+  if (atom) {
+    info = g_new0 (AtomInfo, 1);
+
+    info->atom = atom;
+    info->copy_data_func = copy_func;
+    info->free_func = free_func;
+  }
+
+  return info;
+}
+
+static GList *
+atom_info_list_prepend_atom (GList * ai, Atom * atom,
+    AtomCopyDataFunc copy_func, AtomFreeFunc free_func)
+{
+  if (atom)
+    return g_list_prepend (ai,
+        build_atom_info_wrapper (atom, (gpointer)copy_func, (gpointer)free_func));
+  else
+    return ai;
+}
+
+static void
+atom_info_list_free (GList * ai)
+{
+  while (ai) {
+    AtomInfo *info = (AtomInfo *) ai->data;
+
+    info->free_func (info->atom);
+    g_free (info);
+    ai = g_list_delete_link (ai, ai);
+  }
+}
+
+static AtomData *
+atom_data_new (guint32 fourcc)
+{
+  AtomData *data = g_new0 (AtomData, 1);
+
+  atom_header_set (&data->header, fourcc, 0, 0);
+  return data;
+}
+
+static void
+atom_data_alloc_mem (AtomData * data, guint32 size)
+{
+  if (data->data) {
+    g_free (data->data);
+  }
+  data->data = g_new0 (guint8, size);
+  data->datalen = size;
+}
+
+static AtomData *
+atom_data_new_from_gst_buffer (guint32 fourcc, const GstBuffer * buf)
+{
+  AtomData *data = atom_data_new (fourcc);
+
+  atom_data_alloc_mem (data, GST_BUFFER_SIZE (buf));
+  g_memmove (data->data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+  return data;
+}
+
+static void
+atom_data_free (AtomData * data)
+{
+  atom_clear (&data->header);
+  g_free (data->data);
+  g_free (data);
+}
+
+static void
+atom_ftyp_init (AtomFTYP * ftyp, guint32 major, guint32 version, GList * brands)
+{
+  gint index;
+  GList *it = NULL;
+
+  atom_header_set (&ftyp->header, FOURCC_ftyp, 16, 0);
+  ftyp->major_brand = major;
+  ftyp->version = version;
+
+  /* always include major brand as compatible brand */
+  ftyp->compatible_brands_size = g_list_length (brands) + 1;
+  ftyp->compatible_brands = g_new (guint32, ftyp->compatible_brands_size);
+
+  ftyp->compatible_brands[0] = major;
+  index = 1;
+  for (it = brands; it != NULL; it = g_list_next (it)) {
+    ftyp->compatible_brands[index++] = GPOINTER_TO_UINT (it->data);
+  }
+}
+
+AtomFTYP *
+atom_ftyp_new (AtomsContext * context, guint32 major, guint32 version,
+    GList * brands)
+{
+  AtomFTYP *ftyp = g_new0 (AtomFTYP, 1);
+
+  atom_ftyp_init (ftyp, major, version, brands);
+  return ftyp;
+}
+
+void
+atom_ftyp_free (AtomFTYP * ftyp)
+{
+  atom_clear (&ftyp->header);
+  g_free (ftyp->compatible_brands);
+  ftyp->compatible_brands = NULL;
+  g_free (ftyp);
+}
+
+static void
+atom_esds_init (AtomESDS * esds)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&esds->header, FOURCC_esds, 0, 0, 0, flags);
+  desc_es_init (&esds->es);
+}
+
+static AtomESDS *
+atom_esds_new ()
+{
+  AtomESDS *esds = g_new0 (AtomESDS, 1);
+
+  atom_esds_init (esds);
+  return esds;
+}
+
+static void
+atom_esds_free (AtomESDS * esds)
+{
+  atom_full_clear (&esds->header);
+  desc_es_descriptor_clear (&esds->es);
+  g_free (esds);
+}
+
+static AtomFRMA *
+atom_frma_new ()
+{
+  AtomFRMA *frma = g_new0 (AtomFRMA, 1);
+
+  atom_header_set (&frma->header, FOURCC_frma, 0, 0);
+  return frma;
+}
+
+static void
+atom_frma_free (AtomFRMA * frma)
+{
+  atom_clear (&frma->header);
+  g_free (frma);
+}
+
+static AtomWAVE *
+atom_wave_new ()
+{
+  AtomWAVE *wave = g_new0 (AtomWAVE, 1);
+
+  atom_header_set (&wave->header, FOURCC_wave, 0, 0);
+  return wave;
+}
+
+static void
+atom_wave_free (AtomWAVE * wave)
+{
+  atom_clear (&wave->header);
+  atom_info_list_free (wave->extension_atoms);
+  g_free (wave);
+}
+
+static void
+atom_sample_entry_init (SampleTableEntry * se, guint32 type)
+{
+  atom_header_set (&se->header, type, 0, 0);
+
+  memset (se->reserved, 0, sizeof (guint8) * 6);
+  se->data_reference_index = 0;
+}
+
+static void
+atom_sample_entry_free (SampleTableEntry * se)
+{
+  atom_clear (&se->header);
+}
+
+static void
+sample_entry_mp4a_init (SampleTableEntryMP4A * mp4a)
+{
+  atom_sample_entry_init (&mp4a->se, FOURCC_mp4a);
+
+  mp4a->version = 0;
+  mp4a->revision_level = 0;
+  mp4a->vendor = 0;
+  mp4a->channels = 2;
+  mp4a->sample_size = 16;
+  mp4a->compression_id = 0;
+  mp4a->packet_size = 0;
+  mp4a->sample_rate = 0;
+  /* following only used if version is 1 */
+  mp4a->samples_per_packet = 0;
+  mp4a->bytes_per_packet = 0;
+  mp4a->bytes_per_frame = 0;
+  mp4a->bytes_per_sample = 0;
+
+  mp4a->extension_atoms = NULL;
+}
+
+static SampleTableEntryMP4A *
+sample_entry_mp4a_new ()
+{
+  SampleTableEntryMP4A *mp4a = g_new0 (SampleTableEntryMP4A, 1);
+
+  sample_entry_mp4a_init (mp4a);
+  return mp4a;
+}
+
+static void
+sample_entry_mp4a_free (SampleTableEntryMP4A * mp4a)
+{
+  atom_sample_entry_free (&mp4a->se);
+  atom_info_list_free (mp4a->extension_atoms);
+  g_free (mp4a);
+}
+
+static void
+sample_entry_mp4v_init (SampleTableEntryMP4V * mp4v, AtomsContext * context)
+{
+  atom_sample_entry_init (&mp4v->se, FOURCC_mp4v);
+
+  mp4v->version = 0;
+  mp4v->revision_level = 0;
+  mp4v->vendor = 0;
+
+  mp4v->temporal_quality = 0;
+  mp4v->spatial_quality = 0;
+
+  /* qt and ISO base media do not contradict, and examples agree */
+  mp4v->horizontal_resolution = 0x00480000;
+  mp4v->vertical_resolution = 0x00480000;
+
+  mp4v->datasize = 0;
+  mp4v->frame_count = 1;
+
+  memset (mp4v->compressor, 0, sizeof (guint8) * 32);
+
+  mp4v->depth = 0;
+  mp4v->color_table_id = 0;
+
+  mp4v->extension_atoms = NULL;
+}
+
+static void
+sample_entry_mp4v_free (SampleTableEntryMP4V * mp4v)
+{
+  atom_sample_entry_free (&mp4v->se);
+  atom_info_list_free (mp4v->extension_atoms);
+  g_free (mp4v);
+}
+
+static SampleTableEntryMP4V *
+sample_entry_mp4v_new (AtomsContext * context)
+{
+  SampleTableEntryMP4V *mp4v = g_new0 (SampleTableEntryMP4V, 1);
+
+  sample_entry_mp4v_init (mp4v, context);
+  return mp4v;
+}
+
+static void
+atom_stsd_init (AtomSTSD * stsd)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&stsd->header, FOURCC_stsd, 0, 0, 0, flags);
+  stsd->entries = NULL;
+}
+
+static void
+atom_stsd_clear (AtomSTSD * stsd)
+{
+  GList *walker;
+
+  atom_full_clear (&stsd->header);
+  walker = stsd->entries;
+  while (walker) {
+    GList *aux = walker;
+    SampleTableEntry *se = (SampleTableEntry *) aux->data;
+
+    walker = g_list_next (walker);
+    stsd->entries = g_list_remove_link (stsd->entries, aux);
+
+    switch (se->kind) {
+      case AUDIO:
+        sample_entry_mp4a_free ((SampleTableEntryMP4A *) se);
+        break;
+      case VIDEO:
+        sample_entry_mp4v_free ((SampleTableEntryMP4V *) se);
+        break;
+      default:
+        /* best possible cleanup */
+        atom_sample_entry_free (se);
+    }
+    g_list_free (aux);
+  }
+}
+
+static void
+atom_ctts_init (AtomCTTS * ctts)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&ctts->header, FOURCC_ctts, 0, 0, 0, flags);
+  ctts->entries = NULL;
+}
+
+static AtomCTTS *
+atom_ctts_new ()
+{
+  AtomCTTS *ctts = g_new0 (AtomCTTS, 1);
+
+  atom_ctts_init (ctts);
+  return ctts;
+}
+
+static void
+atom_ctts_free (AtomCTTS * ctts)
+{
+  GList *walker;
+
+  atom_full_clear (&ctts->header);
+  walker = ctts->entries;
+  while (walker) {
+    GList *aux = walker;
+
+    walker = g_list_next (walker);
+    ctts->entries = g_list_remove_link (ctts->entries, aux);
+    g_free ((CTTSEntry *) aux->data);
+    g_list_free (aux);
+  }
+  g_free (ctts);
+}
+
+static void
+atom_stts_init (AtomSTTS * stts)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&stts->header, FOURCC_stts, 0, 0, 0, flags);
+  stts->entries = NULL;
+}
+
+static void
+atom_stts_clear (AtomSTTS * stts)
+{
+  GList *walker;
+
+  atom_full_clear (&stts->header);
+  walker = stts->entries;
+  while (walker) {
+    GList *aux = walker;
+
+    walker = g_list_next (walker);
+    stts->entries = g_list_remove_link (stts->entries, aux);
+    g_free ((STTSEntry *) aux->data);
+    g_list_free (aux);
+  }
+  stts->n_entries = 0;
+}
+
+static void
+atom_stsz_init (AtomSTSZ * stsz)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&stsz->header, FOURCC_stsz, 0, 0, 0, flags);
+  stsz->sample_size = 0;
+  stsz->table_size = 0;
+  stsz->entries = NULL;
+}
+
+static void
+atom_stsz_clear (AtomSTSZ * stsz)
+{
+  atom_full_clear (&stsz->header);
+  g_list_free (stsz->entries);
+  stsz->entries = NULL;
+  stsz->table_size = 0;
+}
+
+static void
+atom_stsc_init (AtomSTSC * stsc)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&stsc->header, FOURCC_stsc, 0, 0, 0, flags);
+  stsc->entries = NULL;
+  stsc->n_entries = 0;
+}
+
+static void
+atom_stsc_clear (AtomSTSC * stsc)
+{
+  GList *walker;
+
+  atom_full_clear (&stsc->header);
+  walker = stsc->entries;
+  while (walker) {
+    GList *aux = walker;
+
+    walker = g_list_next (walker);
+    stsc->entries = g_list_remove_link (stsc->entries, aux);
+    g_free ((STSCEntry *) aux->data);
+    g_list_free (aux);
+  }
+  stsc->n_entries = 0;
+}
+
+static void
+atom_co64_init (AtomSTCO64 * co64)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&co64->header, FOURCC_co64, 0, 0, 0, flags);
+  co64->entries = NULL;
+  co64->n_entries = 0;
+}
+
+static void
+atom_stco64_clear (AtomSTCO64 * stco64)
+{
+  GList *walker;
+
+  atom_full_clear (&stco64->header);
+  walker = stco64->entries;
+  while (walker) {
+    GList *aux = walker;
+
+    walker = g_list_next (walker);
+    stco64->entries = g_list_remove_link (stco64->entries, aux);
+    g_free ((guint64 *) aux->data);
+    g_list_free (aux);
+  }
+  stco64->n_entries = 0;
+}
+
+static void
+atom_stss_init (AtomSTSS * stss)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&stss->header, FOURCC_stss, 0, 0, 0, flags);
+  stss->entries = NULL;
+  stss->n_entries = 0;
+}
+
+static void
+atom_stss_clear (AtomSTSS * stss)
+{
+  atom_full_clear (&stss->header);
+  g_list_free (stss->entries);
+  stss->entries = NULL;
+  stss->n_entries = 0;
+}
+
+static void
+atom_stbl_init (AtomSTBL * stbl)
+{
+  atom_header_set (&stbl->header, FOURCC_stbl, 0, 0);
+
+  atom_stts_init (&stbl->stts);
+  atom_stss_init (&stbl->stss);
+  atom_stsd_init (&stbl->stsd);
+  atom_stsz_init (&stbl->stsz);
+  atom_stsc_init (&stbl->stsc);
+  stbl->ctts = NULL;
+
+  atom_co64_init (&stbl->stco64);
+}
+
+static void
+atom_stbl_clear (AtomSTBL * stbl)
+{
+  atom_clear (&stbl->header);
+  atom_stsd_clear (&stbl->stsd);
+  atom_stts_clear (&stbl->stts);
+  atom_stss_clear (&stbl->stss);
+  atom_stsc_clear (&stbl->stsc);
+  atom_stsz_clear (&stbl->stsz);
+  if (stbl->ctts) {
+    atom_ctts_free (stbl->ctts);
+  }
+  atom_stco64_clear (&stbl->stco64);
+}
+
+static void
+atom_vmhd_init (AtomVMHD * vmhd, AtomsContext * context)
+{
+  guint8 flags[3] = { 0, 0, 1 };
+
+  atom_full_init (&vmhd->header, FOURCC_vmhd, 0, 0, 0, flags);
+  vmhd->graphics_mode = 0x0;
+  memset (vmhd->opcolor, 0, sizeof (guint16) * 3);
+
+  if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
+    vmhd->graphics_mode = 0x40;
+    vmhd->opcolor[0] = 32768;
+    vmhd->opcolor[1] = 32768;
+    vmhd->opcolor[2] = 32768;
+  }
+}
+
+static AtomVMHD *
+atom_vmhd_new (AtomsContext * context)
+{
+  AtomVMHD *vmhd = g_new0 (AtomVMHD, 1);
+
+  atom_vmhd_init (vmhd, context);
+  return vmhd;
+}
+
+static void
+atom_vmhd_free (AtomVMHD * vmhd)
+{
+  atom_full_clear (&vmhd->header);
+  g_free (vmhd);
+}
+
+static void
+atom_smhd_init (AtomSMHD * smhd)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&smhd->header, FOURCC_smhd, 0, 0, 0, flags);
+  smhd->balance = 0;
+  smhd->reserved = 0;
+}
+
+static AtomSMHD *
+atom_smhd_new ()
+{
+  AtomSMHD *smhd = g_new0 (AtomSMHD, 1);
+
+  atom_smhd_init (smhd);
+  return smhd;
+}
+
+static void
+atom_smhd_free (AtomSMHD * smhd)
+{
+  atom_full_clear (&smhd->header);
+  g_free (smhd);
+}
+
+static void
+atom_hmhd_free (AtomHMHD * hmhd)
+{
+  atom_full_clear (&hmhd->header);
+  g_free (hmhd);
+}
+
+static void
+atom_hdlr_init (AtomHDLR * hdlr)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&hdlr->header, FOURCC_hdlr, 0, 0, 0, flags);
+
+  hdlr->component_type = 0;
+  hdlr->handler_type = 0;
+  hdlr->manufacturer = 0;
+  hdlr->flags = 0;
+  hdlr->flags_mask = 0;
+  hdlr->name = g_strdup ("");
+}
+
+static AtomHDLR *
+atom_hdlr_new ()
+{
+  AtomHDLR *hdlr = g_new0 (AtomHDLR, 1);
+
+  atom_hdlr_init (hdlr);
+  return hdlr;
+}
+
+static void
+atom_hdlr_clear (AtomHDLR * hdlr)
+{
+  atom_full_clear (&hdlr->header);
+  if (hdlr->name) {
+    g_free (hdlr->name);
+    hdlr->name = NULL;
+  }
+}
+
+static void
+atom_hdlr_free (AtomHDLR * hdlr)
+{
+  atom_hdlr_clear (hdlr);
+  g_free (hdlr);
+}
+
+static void
+atom_url_init (AtomURL * url)
+{
+  guint8 flags[3] = { 0, 0, 1 };
+
+  atom_full_init (&url->header, FOURCC_url_, 0, 0, 0, flags);
+  url->location = NULL;
+}
+
+static void
+atom_url_free (AtomURL * url)
+{
+  atom_full_clear (&url->header);
+  if (url->location) {
+    g_free (url->location);
+    url->location = NULL;
+  }
+  g_free (url);
+}
+
+static AtomURL *
+atom_url_new ()
+{
+  AtomURL *url = g_new0 (AtomURL, 1);
+
+  atom_url_init (url);
+  return url;
+}
+
+static AtomFull *
+atom_alis_new ()
+{
+  guint8 flags[3] = { 0, 0, 1 };
+  AtomFull *alis = g_new0 (AtomFull, 1);
+
+  atom_full_init (alis, FOURCC_alis, 0, 0, 0, flags);
+  return alis;
+}
+
+static void
+atom_dref_init (AtomDREF * dref, AtomsContext * context)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&dref->header, FOURCC_dref, 0, 0, 0, flags);
+
+  /* in either case, alis or url init arranges to set self-contained flag */
+  if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
+    /* alis dref for qt */
+    AtomFull *alis = atom_alis_new ();
+    dref->entries = g_list_append (dref->entries, alis);
+  } else {
+    /* url for iso spec, as 'alis' not specified there */
+    AtomURL *url = atom_url_new ();
+    dref->entries = g_list_append (dref->entries, url);
+  }
+}
+
+static void
+atom_dref_clear (AtomDREF * dref)
+{
+  GList *walker;
+
+  atom_full_clear (&dref->header);
+  walker = dref->entries;
+  while (walker) {
+    GList *aux = walker;
+    Atom *atom = (Atom *) aux->data;
+
+    walker = g_list_next (walker);
+    dref->entries = g_list_remove_link (dref->entries, aux);
+    switch (atom->type) {
+      case FOURCC_alis:
+        atom_full_free ((AtomFull *) atom);
+        break;
+      case FOURCC_url_:
+        atom_url_free ((AtomURL *) atom);
+        break;
+      default:
+        /* we do nothing, better leak than crash */
+        break;
+    }
+    g_list_free (aux);
+  }
+}
+
+static void
+atom_dinf_init (AtomDINF * dinf, AtomsContext * context)
+{
+  atom_header_set (&dinf->header, FOURCC_dinf, 0, 0);
+  atom_dref_init (&dinf->dref, context);
+}
+
+static void
+atom_dinf_clear (AtomDINF * dinf)
+{
+  atom_clear (&dinf->header);
+  atom_dref_clear (&dinf->dref);
+}
+
+static void
+atom_minf_init (AtomMINF * minf, AtomsContext * context)
+{
+  atom_header_set (&minf->header, FOURCC_minf, 0, 0);
+
+  minf->vmhd = NULL;
+  minf->smhd = NULL;
+  minf->hmhd = NULL;
+
+  if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
+    minf->hdlr = atom_hdlr_new ();
+    minf->hdlr->component_type = FOURCC_dhlr;
+    minf->hdlr->handler_type = FOURCC_alis;
+  } else {
+    minf->hdlr = NULL;
+  }
+  atom_dinf_init (&minf->dinf, context);
+  atom_stbl_init (&minf->stbl);
+}
+
+static void
+atom_minf_clear_handlers (AtomMINF * minf)
+{
+  if (minf->vmhd) {
+    atom_vmhd_free (minf->vmhd);
+    minf->vmhd = NULL;
+  }
+  if (minf->smhd) {
+    atom_smhd_free (minf->smhd);
+    minf->smhd = NULL;
+  }
+  if (minf->hmhd) {
+    atom_hmhd_free (minf->hmhd);
+    minf->hmhd = NULL;
+  }
+}
+
+static void
+atom_minf_clear (AtomMINF * minf)
+{
+  atom_clear (&minf->header);
+  atom_minf_clear_handlers (minf);
+  if (minf->hdlr) {
+    atom_hdlr_free (minf->hdlr);
+  }
+  atom_dinf_clear (&minf->dinf);
+  atom_stbl_clear (&minf->stbl);
+}
+
+static void
+atom_mdhd_init (AtomMDHD * mdhd)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&mdhd->header, FOURCC_mdhd, 0, 0, 0, flags);
+  common_time_info_init (&mdhd->time_info);
+  mdhd->language_code = 0;
+  mdhd->quality = 0;
+}
+
+static void
+atom_mdhd_clear (AtomMDHD * mdhd)
+{
+  atom_full_clear (&mdhd->header);
+}
+
+static void
+atom_mdia_init (AtomMDIA * mdia, AtomsContext * context)
+{
+  atom_header_set (&mdia->header, FOURCC_mdia, 0, 0);
+
+  atom_mdhd_init (&mdia->mdhd);
+  atom_hdlr_init (&mdia->hdlr);
+  atom_minf_init (&mdia->minf, context);
+}
+
+static void
+atom_mdia_clear (AtomMDIA * mdia)
+{
+  atom_clear (&mdia->header);
+  atom_mdhd_clear (&mdia->mdhd);
+  atom_hdlr_clear (&mdia->hdlr);
+  atom_minf_clear (&mdia->minf);
+}
+
+static void
+atom_tkhd_init (AtomTKHD * tkhd, AtomsContext * context)
+{
+  /*
+   * flags info
+   * 1 -> track enabled
+   * 2 -> track in movie
+   * 4 -> track in preview
+   */
+  guint8 flags[3] = { 0, 0, 7 };
+
+  atom_full_init (&tkhd->header, FOURCC_tkhd, 0, 0, 0, flags);
+
+  tkhd->creation_time = tkhd->modification_time = get_current_qt_time ();
+  tkhd->duration = 0;
+  tkhd->track_ID = 0;
+  tkhd->reserved = 0;
+
+  tkhd->reserved2[0] = tkhd->reserved2[1] = 0;
+  tkhd->layer = 0;
+  tkhd->alternate_group = 0;
+  tkhd->volume = 0;
+  tkhd->reserved3 = 0;
+  memset (tkhd->matrix, 0, sizeof (guint32) * 9);
+  tkhd->matrix[0] = 1 << 16;
+  tkhd->matrix[4] = 1 << 16;
+  tkhd->matrix[8] = 16384 << 16;
+  tkhd->width = 0;
+  tkhd->height = 0;
+}
+
+static void
+atom_tkhd_clear (AtomTKHD * tkhd)
+{
+  atom_full_clear (&tkhd->header);
+}
+
+static void
+atom_trak_init (AtomTRAK * trak, AtomsContext * context)
+{
+  atom_header_set (&trak->header, FOURCC_trak, 0, 0);
+
+  atom_tkhd_init (&trak->tkhd, context);
+  atom_mdia_init (&trak->mdia, context);
+}
+
+AtomTRAK *
+atom_trak_new (AtomsContext * context)
+{
+  AtomTRAK *trak = g_new0 (AtomTRAK, 1);
+
+  atom_trak_init (trak, context);
+  return trak;
+}
+
+static void
+atom_trak_free (AtomTRAK * trak)
+{
+  atom_clear (&trak->header);
+  atom_tkhd_clear (&trak->tkhd);
+  atom_mdia_clear (&trak->mdia);
+  g_free (trak);
+}
+
+static void
+atom_ilst_init (AtomILST * ilst)
+{
+  atom_header_set (&ilst->header, FOURCC_ilst, 0, 0);
+  ilst->entries = NULL;
+}
+
+static AtomILST *
+atom_ilst_new ()
+{
+  AtomILST *ilst = g_new0 (AtomILST, 1);
+
+  atom_ilst_init (ilst);
+  return ilst;
+}
+
+static void
+atom_ilst_free (AtomILST * ilst)
+{
+  if (ilst->entries)
+    atom_info_list_free (ilst->entries);
+  atom_clear (&ilst->header);
+  g_free (ilst);
+}
+
+static void
+atom_meta_init (AtomMETA * meta)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&meta->header, FOURCC_meta, 0, 0, 0, flags);
+  atom_hdlr_init (&meta->hdlr);
+  /* FIXME (ISOM says this is always 0) */
+  meta->hdlr.component_type = FOURCC_mhlr;
+  meta->hdlr.handler_type = FOURCC_mdir;
+  meta->ilst = NULL;
+}
+
+static AtomMETA *
+atom_meta_new ()
+{
+  AtomMETA *meta = g_new0 (AtomMETA, 1);
+
+  atom_meta_init (meta);
+  return meta;
+}
+
+static void
+atom_meta_free (AtomMETA * meta)
+{
+  atom_full_clear (&meta->header);
+  atom_hdlr_clear (&meta->hdlr);
+  if (meta->ilst)
+    atom_ilst_free (meta->ilst);
+  meta->ilst = NULL;
+  g_free (meta);
+}
+
+static void
+atom_udta_init (AtomUDTA * udta)
+{
+  atom_header_set (&udta->header, FOURCC_udta, 0, 0);
+  udta->meta = NULL;
+}
+
+static AtomUDTA *
+atom_udta_new ()
+{
+  AtomUDTA *udta = g_new0 (AtomUDTA, 1);
+
+  atom_udta_init (udta);
+  return udta;
+}
+
+static void
+atom_udta_free (AtomUDTA * udta)
+{
+  atom_clear (&udta->header);
+  if (udta->meta)
+    atom_meta_free (udta->meta);
+  udta->meta = NULL;
+  if (udta->entries)
+    atom_info_list_free (udta->entries);
+  g_free (udta);
+}
+
+static void
+atom_tag_data_init (AtomTagData * data)
+{
+  guint8 flags[] = { 0, 0, 0 };
+
+  atom_full_init (&data->header, FOURCC_data, 0, 0, 0, flags);
+}
+
+static void
+atom_tag_data_clear (AtomTagData * data)
+{
+  atom_full_clear (&data->header);
+  g_free (data->data);
+  data->datalen = 0;
+}
+
+/*
+ * Fourcc is the tag fourcc
+ * flags will be truncated to 24bits
+ */
+static AtomTag *
+atom_tag_new (guint32 fourcc, guint32 flags_as_uint)
+{
+  AtomTag *tag = g_new0 (AtomTag, 1);
+
+  tag->header.type = fourcc;
+  atom_tag_data_init (&tag->data);
+  tag->data.header.flags[2] = flags_as_uint & 0xFF;
+  tag->data.header.flags[1] = (flags_as_uint & 0xFF00) >> 8;
+  tag->data.header.flags[0] = (flags_as_uint & 0xFF0000) >> 16;
+  return tag;
+}
+
+static void
+atom_tag_free (AtomTag * tag)
+{
+  atom_clear (&tag->header);
+  atom_tag_data_clear (&tag->data);
+  g_free (tag);
+}
+
+static void
+atom_mvhd_init (AtomMVHD * mvhd)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&(mvhd->header), FOURCC_mvhd, sizeof (AtomMVHD), 0, 0, flags);
+
+  common_time_info_init (&mvhd->time_info);
+
+  mvhd->prefered_rate = 1 << 16;
+  mvhd->volume = 1 << 8;
+  mvhd->reserved3 = 0;
+  memset (mvhd->reserved4, 0, sizeof (guint32[2]));
+
+  memset (mvhd->matrix, 0, sizeof (guint32[9]));
+  mvhd->matrix[0] = 1 << 16;
+  mvhd->matrix[4] = 1 << 16;
+  mvhd->matrix[8] = 16384 << 16;
+
+  mvhd->preview_time = 0;
+  mvhd->preview_duration = 0;
+  mvhd->poster_time = 0;
+  mvhd->selection_time = 0;
+  mvhd->selection_duration = 0;
+  mvhd->current_time = 0;
+
+  mvhd->next_track_id = 1;
+}
+
+static void
+atom_mvhd_clear (AtomMVHD * mvhd)
+{
+  atom_full_clear (&mvhd->header);
+}
+
+static void
+atom_moov_init (AtomMOOV * moov, AtomsContext * context)
+{
+  atom_header_set (&(moov->header), FOURCC_moov, 0, 0);
+  atom_mvhd_init (&(moov->mvhd));
+  moov->udta = NULL;
+  moov->traks = NULL;
+  moov->context = *context;
+}
+
+AtomMOOV *
+atom_moov_new (AtomsContext * context)
+{
+  AtomMOOV *moov = g_new0 (AtomMOOV, 1);
+
+  atom_moov_init (moov, context);
+  return moov;
+}
+
+void
+atom_moov_free (AtomMOOV * moov)
+{
+  GList *walker;
+
+  atom_clear (&moov->header);
+  atom_mvhd_clear (&moov->mvhd);
+
+  walker = moov->traks;
+  while (walker) {
+    atom_trak_free ((AtomTRAK *) walker->data);
+    walker = g_list_next (walker);
+  }
+  g_list_free (moov->traks);
+  moov->traks = NULL;
+
+  if (moov->udta) {
+    atom_udta_free (moov->udta);
+    moov->udta = NULL;
+  }
+
+  g_free (moov);
+}
+
+/* -- end of init / free -- */
+
+/* -- copy data functions -- */
+
+static guint8
+atom_full_get_version (AtomFull * full)
+{
+  return full->version;
+}
+
+static guint64
+common_time_info_copy_data (TimeInfo * ti, gboolean trunc_to_32,
+    guint8 ** buffer, guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (trunc_to_32) {
+    prop_copy_uint32 ((guint32) ti->creation_time, buffer, size, offset);
+    prop_copy_uint32 ((guint32) ti->modification_time, buffer, size, offset);
+    prop_copy_uint32 (ti->timescale, buffer, size, offset);
+    prop_copy_uint32 ((guint32) ti->duration, buffer, size, offset);
+  } else {
+    prop_copy_uint64 (ti->creation_time, buffer, size, offset);
+    prop_copy_uint64 (ti->modification_time, buffer, size, offset);
+    prop_copy_uint32 (ti->timescale, buffer, size, offset);
+    prop_copy_uint64 (ti->duration, buffer, size, offset);
+  }
+  return *offset - original_offset;
+}
+
+static void
+atom_write_size (guint8 ** buffer, guint64 * size, guint64 * offset,
+    guint64 atom_pos)
+{
+  /* this only works for non-extended atom size, which is OK
+   * (though it could be made to do mem_move, etc and write extended size) */
+  prop_copy_uint32 (*offset - atom_pos, buffer, size, &atom_pos);
+}
+
+guint64
+atom_copy_data (Atom * atom, guint8 ** buffer, guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  /* copies type and size */
+  prop_copy_uint32 (atom->size, buffer, size, offset);
+  prop_copy_fourcc (atom->type, buffer, size, offset);
+
+  /* extended size needed */
+  if (atom->size == 1) {
+    /* really should not happen other than with mdat atom;
+     * would be a problem for size (re)write code, not to mention memory */
+    g_return_val_if_fail (atom->type == FOURCC_mdat, 0);
+    prop_copy_uint64 (atom->extended_size, buffer, size, offset);
+  }
+
+  return *offset - original_offset;
+}
+
+static guint64
+atom_full_copy_data (AtomFull * atom, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&atom->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint8 (atom->version, buffer, size, offset);
+  prop_copy_uint8_array (atom->flags, 3, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_info_list_copy_data (GList * ai, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  while (ai) {
+    AtomInfo *info = (AtomInfo *) ai->data;
+
+    if (!info->copy_data_func (info->atom, buffer, size, offset)) {
+      return 0;
+    }
+    ai = g_list_next (ai);
+  }
+
+  return *offset - original_offset;
+}
+
+static guint64
+atom_data_copy_data (AtomData * data, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&data->header, buffer, size, offset)) {
+    return 0;
+  }
+  if (data->datalen)
+    prop_copy_uint8_array (data->data, data->datalen, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+guint64
+atom_ftyp_copy_data (AtomFTYP * ftyp, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&ftyp->header, buffer, size, offset)) {
+    return 0;
+  }
+  prop_copy_fourcc (ftyp->major_brand, buffer, size, offset);
+  prop_copy_uint32 (ftyp->version, buffer, size, offset);
+
+  prop_copy_fourcc_array (ftyp->compatible_brands, ftyp->compatible_brands_size,
+      buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_mvhd_copy_data (AtomMVHD * atom, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint8 version;
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&(atom->header), buffer, size, offset)) {
+    return 0;
+  }
+
+  version = atom_full_get_version (&(atom->header));
+  if (version == 0) {
+    common_time_info_copy_data (&atom->time_info, TRUE, buffer, size, offset);
+  } else if (version == 1) {
+    common_time_info_copy_data (&atom->time_info, FALSE, buffer, size, offset);
+  } else {
+    *offset = original_offset;
+    return 0;
+  }
+
+  prop_copy_uint32 (atom->prefered_rate, buffer, size, offset);
+  prop_copy_uint16 (atom->volume, buffer, size, offset);
+  prop_copy_uint16 (atom->reserved3, buffer, size, offset);
+  prop_copy_uint32_array (atom->reserved4, 2, buffer, size, offset);
+  prop_copy_uint32_array (atom->matrix, 9, buffer, size, offset);
+  prop_copy_uint32 (atom->preview_time, buffer, size, offset);
+  prop_copy_uint32 (atom->preview_duration, buffer, size, offset);
+  prop_copy_uint32 (atom->poster_time, buffer, size, offset);
+  prop_copy_uint32 (atom->selection_time, buffer, size, offset);
+  prop_copy_uint32 (atom->selection_duration, buffer, size, offset);
+  prop_copy_uint32 (atom->current_time, buffer, size, offset);
+
+  prop_copy_uint32 (atom->next_track_id, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_tkhd_copy_data (AtomTKHD * tkhd, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&tkhd->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (atom_full_get_version (&tkhd->header) == 0) {
+    prop_copy_uint32 ((guint32) tkhd->creation_time, buffer, size, offset);
+    prop_copy_uint32 ((guint32) tkhd->modification_time, buffer, size, offset);
+    prop_copy_uint32 (tkhd->track_ID, buffer, size, offset);
+    prop_copy_uint32 (tkhd->reserved, buffer, size, offset);
+    prop_copy_uint32 ((guint32) tkhd->duration, buffer, size, offset);
+  } else {
+    prop_copy_uint64 (tkhd->creation_time, buffer, size, offset);
+    prop_copy_uint64 (tkhd->modification_time, buffer, size, offset);
+    prop_copy_uint32 (tkhd->track_ID, buffer, size, offset);
+    prop_copy_uint32 (tkhd->reserved, buffer, size, offset);
+    prop_copy_uint64 (tkhd->duration, buffer, size, offset);
+  }
+
+  prop_copy_uint32_array (tkhd->reserved2, 2, buffer, size, offset);
+  prop_copy_uint16 (tkhd->layer, buffer, size, offset);
+  prop_copy_uint16 (tkhd->alternate_group, buffer, size, offset);
+  prop_copy_uint16 (tkhd->volume, buffer, size, offset);
+  prop_copy_uint16 (tkhd->reserved3, buffer, size, offset);
+  prop_copy_uint32_array (tkhd->matrix, 9, buffer, size, offset);
+
+  prop_copy_uint32 (tkhd->width, buffer, size, offset);
+  prop_copy_uint32 (tkhd->height, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_hdlr_copy_data (AtomHDLR * hdlr, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&hdlr->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_fourcc (hdlr->component_type, buffer, size, offset);
+  prop_copy_fourcc (hdlr->handler_type, buffer, size, offset);
+  prop_copy_fourcc (hdlr->manufacturer, buffer, size, offset);
+  prop_copy_uint32 (hdlr->flags, buffer, size, offset);
+  prop_copy_uint32 (hdlr->flags_mask, buffer, size, offset);
+
+  prop_copy_null_terminated_string (hdlr->name, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_vmhd_copy_data (AtomVMHD * vmhd, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&vmhd->header, buffer, size, offset)) {
+    return 0;
+  }
+  prop_copy_uint16 (vmhd->graphics_mode, buffer, size, offset);
+  prop_copy_uint16_array (vmhd->opcolor, 3, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return original_offset - *offset;
+}
+
+static guint64
+atom_smhd_copy_data (AtomSMHD * smhd, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&smhd->header, buffer, size, offset)) {
+    return 0;
+  }
+  prop_copy_uint16 (smhd->balance, buffer, size, offset);
+  prop_copy_uint16 (smhd->reserved, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return original_offset - *offset;
+}
+
+static guint64
+atom_hmhd_copy_data (AtomHMHD * hmhd, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&hmhd->header, buffer, size, offset)) {
+    return 0;
+  }
+  prop_copy_uint16 (hmhd->max_pdu_size, buffer, size, offset);
+  prop_copy_uint16 (hmhd->avg_pdu_size, buffer, size, offset);
+  prop_copy_uint32 (hmhd->max_bitrate, buffer, size, offset);
+  prop_copy_uint32 (hmhd->avg_bitrate, buffer, size, offset);
+  prop_copy_uint32 (hmhd->sliding_avg_bitrate, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return original_offset - *offset;
+}
+
+static gboolean
+atom_url_same_file_flag (AtomURL * url)
+{
+  return (url->header.flags[2] & 0x1) == 1;
+}
+
+static guint64
+atom_url_copy_data (AtomURL * url, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&url->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!atom_url_same_file_flag (url)) {
+    prop_copy_null_terminated_string (url->location, buffer, size, offset);
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return original_offset - *offset;
+}
+
+static guint64
+atom_stts_copy_data (AtomSTTS * stts, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_full_copy_data (&stts->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (stts->n_entries, buffer, size, offset);
+  /* minimize realloc */
+  prop_copy_ensure_buffer (buffer, size, offset, 8 * stts->n_entries);
+  for (walker = g_list_last (stts->entries); walker != NULL;
+      walker = g_list_previous (walker)) {
+    STTSEntry *entry = (STTSEntry *) walker->data;
+
+    prop_copy_uint32 (entry->sample_count, buffer, size, offset);
+    prop_copy_int32 (entry->sample_delta, buffer, size, offset);
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_sample_entry_copy_data (SampleTableEntry * se, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&se->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint8_array (se->reserved, 6, buffer, size, offset);
+  prop_copy_uint16 (se->data_reference_index, buffer, size, offset);
+
+  return *offset - original_offset;
+}
+
+static guint64
+atom_esds_copy_data (AtomESDS * esds, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&esds->header, buffer, size, offset)) {
+    return 0;
+  }
+  if (!desc_es_descriptor_copy_data (&esds->es, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_frma_copy_data (AtomFRMA * frma, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&(frma->header), buffer, size, offset))
+    return 0;
+
+  prop_copy_fourcc (frma->media_type, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_mp4s_copy_data (SampleTableEntryMP4S * mp4s, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_sample_entry_copy_data (&mp4s->se, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_esds_copy_data (&mp4s->es, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_hint_sample_entry_copy_data (AtomHintSampleEntry * hse, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_sample_entry_copy_data (&hse->se, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (hse->size, buffer, size, offset);
+  prop_copy_uint8_array (hse->data, hse->size, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+sample_entry_mp4a_copy_data (SampleTableEntryMP4A * mp4a, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_sample_entry_copy_data (&mp4a->se, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint16 (mp4a->version, buffer, size, offset);
+  prop_copy_uint16 (mp4a->revision_level, buffer, size, offset);
+  prop_copy_uint32 (mp4a->vendor, buffer, size, offset);
+  prop_copy_uint16 (mp4a->channels, buffer, size, offset);
+  prop_copy_uint16 (mp4a->sample_size, buffer, size, offset);
+  prop_copy_uint16 (mp4a->compression_id, buffer, size, offset);
+  prop_copy_uint16 (mp4a->packet_size, buffer, size, offset);
+  prop_copy_uint32 (mp4a->sample_rate, buffer, size, offset);
+
+  /* this should always be 0 for mp4 flavor */
+  if (mp4a->version == 1) {
+    prop_copy_uint32 (mp4a->samples_per_packet, buffer, size, offset);
+    prop_copy_uint32 (mp4a->bytes_per_packet, buffer, size, offset);
+    prop_copy_uint32 (mp4a->bytes_per_frame, buffer, size, offset);
+    prop_copy_uint32 (mp4a->bytes_per_sample, buffer, size, offset);
+  }
+
+  if (mp4a->extension_atoms) {
+    if (!atom_info_list_copy_data (mp4a->extension_atoms, buffer, size, offset))
+      return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+sample_entry_mp4v_copy_data (SampleTableEntryMP4V * mp4v, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_sample_entry_copy_data (&mp4v->se, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint16 (mp4v->version, buffer, size, offset);
+  prop_copy_uint16 (mp4v->revision_level, buffer, size, offset);
+  prop_copy_fourcc (mp4v->vendor, buffer, size, offset);
+  prop_copy_uint32 (mp4v->temporal_quality, buffer, size, offset);
+  prop_copy_uint32 (mp4v->spatial_quality, buffer, size, offset);
+
+  prop_copy_uint16 (mp4v->width, buffer, size, offset);
+  prop_copy_uint16 (mp4v->height, buffer, size, offset);
+
+  prop_copy_uint32 (mp4v->horizontal_resolution, buffer, size, offset);
+  prop_copy_uint32 (mp4v->vertical_resolution, buffer, size, offset);
+  prop_copy_uint32 (mp4v->datasize, buffer, size, offset);
+
+  prop_copy_uint16 (mp4v->frame_count, buffer, size, offset);
+
+  prop_copy_fixed_size_string ((guint8 *) mp4v->compressor, 32, buffer, size,
+      offset);
+
+  prop_copy_uint16 (mp4v->depth, buffer, size, offset);
+  prop_copy_uint16 (mp4v->color_table_id, buffer, size, offset);
+
+  /* extra atoms */
+  if (mp4v->extension_atoms &&
+      !atom_info_list_copy_data (mp4v->extension_atoms, buffer, size, offset))
+    return 0;
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_stsz_copy_data (AtomSTSZ * stsz, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_full_copy_data (&stsz->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (stsz->sample_size, buffer, size, offset);
+  prop_copy_uint32 (stsz->table_size, buffer, size, offset);
+  /* minimize realloc */
+  prop_copy_ensure_buffer (buffer, size, offset, 4 * stsz->table_size);
+  if (stsz->sample_size == 0) {
+    for (walker = g_list_last (stsz->entries); walker != NULL;
+        walker = g_list_previous (walker)) {
+      prop_copy_uint32 ((guint32) GPOINTER_TO_UINT (walker->data), buffer, size,
+          offset);
+    }
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_stsc_copy_data (AtomSTSC * stsc, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_full_copy_data (&stsc->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (stsc->n_entries, buffer, size, offset);
+  /* minimize realloc */
+  prop_copy_ensure_buffer (buffer, size, offset, 12 * stsc->n_entries);
+
+  for (walker = g_list_last (stsc->entries); walker != NULL;
+      walker = g_list_previous (walker)) {
+    STSCEntry *entry = (STSCEntry *) walker->data;
+
+    prop_copy_uint32 (entry->first_chunk, buffer, size, offset);
+    prop_copy_uint32 (entry->samples_per_chunk, buffer, size, offset);
+    prop_copy_uint32 (entry->sample_description_index, buffer, size, offset);
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_ctts_copy_data (AtomCTTS * ctts, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_full_copy_data (&ctts->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (ctts->n_entries, buffer, size, offset);
+  /* minimize realloc */
+  prop_copy_ensure_buffer (buffer, size, offset, 8 * ctts->n_entries);
+  for (walker = g_list_last (ctts->entries); walker != NULL;
+      walker = g_list_previous (walker)) {
+    CTTSEntry *entry = (CTTSEntry *) walker->data;
+
+    prop_copy_uint32 (entry->samplecount, buffer, size, offset);
+    prop_copy_uint32 (entry->sampleoffset, buffer, size, offset);
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_stco64_copy_data (AtomSTCO64 * stco64, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+  gboolean trunc_to_32 = stco64->header.header.type == FOURCC_stco;
+
+  if (!atom_full_copy_data (&stco64->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (stco64->n_entries, buffer, size, offset);
+
+  /* minimize realloc */
+  prop_copy_ensure_buffer (buffer, size, offset, 8 * stco64->n_entries);
+  for (walker = g_list_last (stco64->entries); walker != NULL;
+      walker = g_list_previous (walker)) {
+    guint64 *value = (guint64 *) walker->data;
+
+    if (trunc_to_32) {
+      prop_copy_uint32 ((guint32) * value, buffer, size, offset);
+    } else {
+      prop_copy_uint64 (*value, buffer, size, offset);
+    }
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_stss_copy_data (AtomSTSS * stss, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (stss->entries == NULL) {
+    /* FIXME not needing this atom might be confused with error while copying */
+    return 0;
+  }
+
+  if (!atom_full_copy_data (&stss->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (stss->n_entries, buffer, size, offset);
+  /* minimize realloc */
+  prop_copy_ensure_buffer (buffer, size, offset, 4 * stss->n_entries);
+  for (walker = g_list_last (stss->entries); walker != NULL;
+      walker = g_list_previous (walker)) {
+    prop_copy_uint32 ((guint32) GPOINTER_TO_UINT (walker->data), buffer, size,
+        offset);
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_stsd_copy_data (AtomSTSD * stsd, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_full_copy_data (&stsd->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (stsd->n_entries, buffer, size, offset);
+
+  for (walker = g_list_last (stsd->entries); walker != NULL;
+      walker = g_list_previous (walker)) {
+    SampleTableEntry *se = (SampleTableEntry *) walker->data;
+
+    switch (((Atom *) walker->data)->type) {
+      case FOURCC_mp4a:
+        if (!sample_entry_mp4a_copy_data ((SampleTableEntryMP4A *) walker->data,
+                buffer, size, offset)) {
+          return 0;
+        }
+        break;
+      case FOURCC_mp4s:
+        if (!atom_mp4s_copy_data ((SampleTableEntryMP4S *) walker->data,
+                buffer, size, offset)) {
+          return 0;
+        }
+        break;
+      case FOURCC_mp4v:
+        if (!sample_entry_mp4v_copy_data ((SampleTableEntryMP4V *) walker->data,
+                buffer, size, offset)) {
+          return 0;
+        }
+        break;
+      default:
+        if (se->kind == VIDEO) {
+          size += sample_entry_mp4v_copy_data ((SampleTableEntryMP4V *)
+              walker->data, buffer, size, offset);
+        } else if (se->kind == AUDIO) {
+          size += sample_entry_mp4a_copy_data ((SampleTableEntryMP4A *)
+              walker->data, buffer, size, offset);
+        } else {
+          if (!atom_hint_sample_entry_copy_data (
+                  (AtomHintSampleEntry *) walker->data, buffer, size, offset)) {
+            return 0;
+          }
+        }
+        break;
+    }
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_stbl_copy_data (AtomSTBL * stbl, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&stbl->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!atom_stsd_copy_data (&stbl->stsd, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_stts_copy_data (&stbl->stts, buffer, size, offset)) {
+    return 0;
+  }
+  /* this atom is optional, so let's check if we need it
+   * (to avoid false error) */
+  if (stbl->stss.entries) {
+    if (!atom_stss_copy_data (&stbl->stss, buffer, size, offset)) {
+      return 0;
+    }
+  }
+
+  if (!atom_stsc_copy_data (&stbl->stsc, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_stsz_copy_data (&stbl->stsz, buffer, size, offset)) {
+    return 0;
+  }
+  if (stbl->ctts) {
+    if (!atom_ctts_copy_data (stbl->ctts, buffer, size, offset)) {
+      return 0;
+    }
+  }
+  if (!atom_stco64_copy_data (&stbl->stco64, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return original_offset - *offset;
+}
+
+
+static guint64
+atom_dref_copy_data (AtomDREF * dref, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_full_copy_data (&dref->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (g_list_length (dref->entries), buffer, size, offset);
+
+  walker = dref->entries;
+  while (walker != NULL) {
+    Atom *atom = (Atom *) walker->data;
+
+    if (atom->type == FOURCC_url_) {
+      atom_url_copy_data ((AtomURL *) atom, buffer, size, offset);
+    } else if (atom->type == FOURCC_alis) {
+      atom_full_copy_data ((AtomFull *) atom, buffer, size, offset);
+    } else {
+      g_error ("Unsupported atom used inside dref atom");
+    }
+    walker = g_list_next (walker);
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_dinf_copy_data (AtomDINF * dinf, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&dinf->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!atom_dref_copy_data (&dinf->dref, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return original_offset - *offset;
+}
+
+static guint64
+atom_minf_copy_data (AtomMINF * minf, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&minf->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (minf->vmhd) {
+    if (!atom_vmhd_copy_data (minf->vmhd, buffer, size, offset)) {
+      return 0;
+    }
+  } else if (minf->smhd) {
+    if (!atom_smhd_copy_data (minf->smhd, buffer, size, offset)) {
+      return 0;
+    }
+  } else if (minf->hmhd) {
+    if (!atom_hmhd_copy_data (minf->hmhd, buffer, size, offset)) {
+      return 0;
+    }
+  }
+
+  if (minf->hdlr) {
+    if (!atom_hdlr_copy_data (minf->hdlr, buffer, size, offset)) {
+      return 0;
+    }
+  }
+
+  if (!atom_dinf_copy_data (&minf->dinf, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_stbl_copy_data (&minf->stbl, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_mdhd_copy_data (AtomMDHD * mdhd, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&mdhd->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!common_time_info_copy_data (&mdhd->time_info,
+          atom_full_get_version (&mdhd->header) == 0, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint16 (mdhd->language_code, buffer, size, offset);
+  prop_copy_uint16 (mdhd->quality, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_mdia_copy_data (AtomMDIA * mdia, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&mdia->header, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_mdhd_copy_data (&mdia->mdhd, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_hdlr_copy_data (&mdia->hdlr, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!atom_minf_copy_data (&mdia->minf, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_trak_copy_data (AtomTRAK * trak, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&trak->header, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_tkhd_copy_data (&trak->tkhd, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!atom_mdia_copy_data (&trak->mdia, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_tag_data_copy_data (AtomTagData * data, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&data->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint32 (data->reserved, buffer, size, offset);
+  prop_copy_uint8_array (data->data, data->datalen, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_tag_copy_data (AtomTag * tag, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&tag->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  if (!atom_tag_data_copy_data (&tag->data, buffer, size, offset)) {
+    return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_ilst_copy_data (AtomILST * ilst, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&ilst->header, buffer, size, offset)) {
+    return 0;
+  }
+  /* extra atoms */
+  if (ilst->entries &&
+      !atom_info_list_copy_data (ilst->entries, buffer, size, offset))
+    return 0;
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_meta_copy_data (AtomMETA * meta, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&meta->header, buffer, size, offset)) {
+    return 0;
+  }
+  if (!atom_hdlr_copy_data (&meta->hdlr, buffer, size, offset)) {
+    return 0;
+  }
+  if (meta->ilst) {
+    if (!atom_ilst_copy_data (meta->ilst, buffer, size, offset)) {
+      return 0;
+    }
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_udta_copy_data (AtomUDTA * udta, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&udta->header, buffer, size, offset)) {
+    return 0;
+  }
+  if (udta->meta) {
+    if (!atom_meta_copy_data (udta->meta, buffer, size, offset)) {
+      return 0;
+    }
+  } else if (udta->entries) {
+    /* extra atoms */
+    if (!atom_info_list_copy_data (udta->entries, buffer, size, offset))
+      return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+guint64
+atom_moov_copy_data (AtomMOOV * atom, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  GList *walker;
+
+  if (!atom_copy_data (&(atom->header), buffer, size, offset))
+    return 0;
+
+  if (!atom_mvhd_copy_data (&(atom->mvhd), buffer, size, offset))
+    return 0;
+
+  walker = g_list_first (atom->traks);
+  while (walker != NULL) {
+    if (!atom_trak_copy_data ((AtomTRAK *) walker->data, buffer, size, offset)) {
+      return 0;
+    }
+    walker = g_list_next (walker);
+  }
+
+  if (atom->udta) {
+    if (!atom_udta_copy_data (atom->udta, buffer, size, offset)) {
+      return 0;
+    }
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
+atom_wave_copy_data (AtomWAVE * wave, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_copy_data (&(wave->header), buffer, size, offset))
+    return 0;
+
+  if (wave->extension_atoms) {
+    if (!atom_info_list_copy_data (wave->extension_atoms, buffer, size, offset))
+      return 0;
+  }
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+/* -- end of copy data functions -- */
+
+/* -- general functions, API and support functions */
+
+/* add samples to tables */
+
+static STSCEntry *
+stsc_entry_new (guint32 first_chunk, guint32 samples, guint32 desc_index)
+{
+  STSCEntry *entry = g_new0 (STSCEntry, 1);
+
+  entry->first_chunk = first_chunk;
+  entry->samples_per_chunk = samples;
+  entry->sample_description_index = desc_index;
+  return entry;
+}
+
+static void
+atom_stsc_add_new_entry (AtomSTSC * stsc, guint32 first_chunk, guint32 nsamples)
+{
+  if (stsc->entries &&
+      ((STSCEntry *) stsc->entries->data)->samples_per_chunk == nsamples)
+    return;
+
+  stsc->entries =
+      g_list_prepend (stsc->entries, stsc_entry_new (first_chunk, nsamples, 1));
+  stsc->n_entries++;
+}
+
+static STTSEntry *
+stts_entry_new (guint32 sample_count, gint32 sample_delta)
+{
+  STTSEntry *entry = g_new0 (STTSEntry, 1);
+
+  entry->sample_count = sample_count;
+  entry->sample_delta = sample_delta;
+  return entry;
+}
+
+static void
+atom_stts_add_entry (AtomSTTS * stts, guint32 sample_count, gint32 sample_delta)
+{
+  STTSEntry *entry;
+
+  if (stts->entries == NULL) {
+    stts->entries =
+        g_list_prepend (stts->entries, stts_entry_new (sample_count,
+            sample_delta));
+    stts->n_entries++;
+    return;
+  }
+  entry = (STTSEntry *) g_list_first (stts->entries)->data;
+  if (entry->sample_delta == sample_delta) {
+    entry->sample_count += sample_count;
+  } else {
+    stts->entries =
+        g_list_prepend (stts->entries, stts_entry_new (sample_count,
+            sample_delta));
+    stts->n_entries++;
+  }
+}
+
+static void
+atom_stsz_add_entry (AtomSTSZ * stsz, guint32 nsamples, guint32 size)
+{
+  guint32 i;
+
+  stsz->table_size += nsamples;
+  if (stsz->sample_size != 0) {
+    /* it is constant size, we don't need entries */
+    return;
+  }
+  for (i = 0; i < nsamples; i++) {
+    stsz->entries = g_list_prepend (stsz->entries, GUINT_TO_POINTER (size));
+  }
+}
+
+static guint32
+atom_stco64_get_entry_count (AtomSTCO64 * stco64)
+{
+  return stco64->n_entries;
+}
+
+static void
+atom_stco64_add_entry (AtomSTCO64 * stco64, guint64 entry)
+{
+  guint64 *pont = g_new (guint64, 1);
+
+  *pont = entry;
+  stco64->entries = g_list_prepend (stco64->entries, pont);
+  stco64->n_entries++;
+}
+
+static void
+atom_stss_add_entry (AtomSTSS * stss, guint32 sample)
+{
+  stss->entries = g_list_prepend (stss->entries, GUINT_TO_POINTER (sample));
+  stss->n_entries++;
+}
+
+static void
+atom_stbl_add_stss_entry (AtomSTBL * stbl)
+{
+  guint32 sample_index = stbl->stsz.table_size;
+
+  atom_stss_add_entry (&stbl->stss, sample_index);
+}
+
+static void
+atom_ctts_add_entry (AtomCTTS * ctts, guint32 nsamples, guint32 offset)
+{
+  GList *walker;
+  CTTSEntry *entry;
+
+  walker = g_list_first (ctts->entries);
+  entry = (walker == NULL) ? NULL : (CTTSEntry *) walker->data;
+
+  if (entry == NULL || entry->sampleoffset != offset) {
+    CTTSEntry *entry = g_new0 (CTTSEntry, 1);
+
+    entry->samplecount = nsamples;
+    entry->sampleoffset = offset;
+    ctts->entries = g_list_prepend (ctts->entries, entry);
+    ctts->n_entries++;
+  } else {
+    entry->samplecount += nsamples;
+  }
+}
+
+static void
+atom_stbl_add_ctts_entry (AtomSTBL * stbl, guint32 nsamples, guint32 offset)
+{
+  if (stbl->ctts == NULL) {
+    stbl->ctts = atom_ctts_new ();
+  }
+  atom_ctts_add_entry (stbl->ctts, nsamples, offset);
+}
+
+void
+atom_trak_add_samples (AtomTRAK * trak, guint32 nsamples, guint32 delta,
+    guint32 size, guint64 chunk_offset, gboolean sync,
+    gboolean do_pts, gint64 pts_offset)
+{
+  AtomSTBL *stbl = &trak->mdia.minf.stbl;
+
+  atom_stts_add_entry (&stbl->stts, nsamples, delta);
+  atom_stsz_add_entry (&stbl->stsz, nsamples, size);
+  atom_stco64_add_entry (&stbl->stco64, chunk_offset);
+  atom_stsc_add_new_entry (&stbl->stsc,
+      atom_stco64_get_entry_count (&stbl->stco64), nsamples);
+  if (sync)
+    atom_stbl_add_stss_entry (stbl);
+  if (do_pts)
+    atom_stbl_add_ctts_entry (stbl, nsamples, pts_offset);
+}
+
+/* trak and moov molding */
+
+guint32
+atom_trak_get_timescale (AtomTRAK * trak)
+{
+  return trak->mdia.mdhd.time_info.timescale;
+}
+
+static void
+atom_trak_set_id (AtomTRAK * trak, guint32 id)
+{
+  trak->tkhd.track_ID = id;
+}
+
+void
+atom_moov_add_trak (AtomMOOV * moov, AtomTRAK * trak)
+{
+  atom_trak_set_id (trak, moov->mvhd.next_track_id++);
+  moov->traks = g_list_append (moov->traks, trak);
+}
+
+static guint64
+atom_trak_get_duration (AtomTRAK * trak)
+{
+  return trak->tkhd.duration;
+}
+
+static guint64
+atom_stts_get_total_duration (AtomSTTS * stts)
+{
+  GList *walker = stts->entries;
+  guint64 sum = 0;
+
+  while (walker) {
+    STTSEntry *entry = (STTSEntry *) walker->data;
+
+    sum += (guint64) (entry->sample_count) * entry->sample_delta;
+    walker = g_list_next (walker);
+  }
+  return sum;
+}
+
+static void
+atom_trak_update_duration (AtomTRAK * trak, guint64 moov_timescale)
+{
+  trak->mdia.mdhd.time_info.duration =
+      atom_stts_get_total_duration (&trak->mdia.minf.stbl.stts);
+  if (trak->mdia.mdhd.time_info.timescale != 0) {
+    trak->tkhd.duration =
+        gst_util_uint64_scale (trak->mdia.mdhd.time_info.duration,
+        moov_timescale, trak->mdia.mdhd.time_info.timescale);
+  } else {
+    trak->tkhd.duration = 0;
+  }
+}
+
+static guint32
+atom_moov_get_timescale (AtomMOOV * moov)
+{
+  return moov->mvhd.time_info.timescale;
+}
+
+void
+atom_moov_update_timescale (AtomMOOV * moov, guint32 timescale)
+{
+  moov->mvhd.time_info.timescale = timescale;
+}
+
+void
+atom_moov_update_duration (AtomMOOV * moov)
+{
+  GList *traks = moov->traks;
+  guint64 dur, duration = 0;
+
+  while (traks) {
+    AtomTRAK *trak = (AtomTRAK *) traks->data;
+
+    atom_trak_update_duration (trak, atom_moov_get_timescale (moov));
+    dur = atom_trak_get_duration (trak);
+    if (dur > duration)
+      duration = dur;
+    traks = g_list_next (traks);
+  }
+  moov->mvhd.time_info.duration = duration;
+}
+
+static void
+atom_set_type (Atom * atom, guint32 fourcc)
+{
+  atom->type = fourcc;
+}
+
+static void
+atom_stbl_set_64bits (AtomSTBL * stbl, gboolean use)
+{
+  if (use) {
+    atom_set_type (&stbl->stco64.header.header, FOURCC_co64);
+  } else {
+    atom_set_type (&stbl->stco64.header.header, FOURCC_stco);
+  }
+}
+
+static void
+atom_trak_set_64bits (AtomTRAK * trak, gboolean use)
+{
+  atom_stbl_set_64bits (&trak->mdia.minf.stbl, use);
+}
+
+void
+atom_moov_set_64bits (AtomMOOV * moov, gboolean large_file)
+{
+  GList *traks = moov->traks;
+
+  while (traks) {
+    AtomTRAK *trak = (AtomTRAK *) traks->data;
+
+    atom_trak_set_64bits (trak, large_file);
+    traks = g_list_next (traks);
+  }
+}
+
+static void
+atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset)
+{
+  GList *entries = stco64->entries;
+
+  while (entries) {
+    guint64 *value = (guint64 *) entries->data;
+
+    *value += offset;
+    entries = g_list_next (entries);
+  }
+}
+
+void
+atom_moov_chunks_add_offset (AtomMOOV * moov, guint32 offset)
+{
+  GList *traks = moov->traks;
+
+  while (traks) {
+    AtomTRAK *trak = (AtomTRAK *) traks->data;
+
+    atom_stco64_chunks_add_offset (&trak->mdia.minf.stbl.stco64, offset);
+    traks = g_list_next (traks);
+  }
+}
+
+/*
+ * Meta tags functions
+ */
+static void
+atom_moov_init_metatags (AtomMOOV * moov, AtomsContext * context)
+{
+  if (!moov->udta) {
+    moov->udta = atom_udta_new ();
+  }
+  if (context->flavor != ATOMS_TREE_FLAVOR_3GP) {
+    if (!moov->udta->meta) {
+      moov->udta->meta = atom_meta_new ();
+    }
+    if (!moov->udta->meta->ilst) {
+      moov->udta->meta->ilst = atom_ilst_new ();
+    }
+  }
+}
+
+static void
+atom_tag_data_alloc_data (AtomTagData * data, guint size)
+{
+  if (data->data != NULL) {
+    g_free (data->data);
+  }
+  data->data = g_new0 (guint8, size);
+  data->datalen = size;
+}
+
+static void
+atom_moov_append_tag (AtomMOOV * moov, AtomInfo * tag)
+{
+  GList **entries;
+
+  atom_moov_init_metatags (moov, &moov->context);
+  if (moov->udta->meta)
+    entries = &moov->udta->meta->ilst->entries;
+  else
+    entries = &moov->udta->entries;
+  *entries = g_list_append (*entries, tag);
+}
+
+void
+atom_moov_add_tag (AtomMOOV * moov, guint32 fourcc, guint32 flags,
+    const guint8 * data, guint size)
+{
+  AtomTag *tag;
+  AtomTagData *tdata;
+
+  tag = atom_tag_new (fourcc, flags);
+  tdata = &tag->data;
+  atom_tag_data_alloc_data (tdata, size);
+  g_memmove (tdata->data, data, size);
+
+  atom_moov_append_tag (moov,
+      build_atom_info_wrapper ((Atom *) tag, (gpointer)atom_tag_copy_data,
+              (gpointer)atom_tag_free));
+}
+
+void
+atom_moov_add_str_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value)
+{
+  gint len = strlen (value);
+
+  if (len > 0)
+    atom_moov_add_tag (moov, fourcc, METADATA_TEXT_FLAG, (guint8 *) value, len);
+}
+
+void
+atom_moov_add_uint_tag (AtomMOOV * moov, guint32 fourcc, guint32 flags,
+    guint32 value)
+{
+  guint8 data[8] = { 0, };
+
+  if (flags) {
+    GST_WRITE_UINT16_BE (data, value);
+    atom_moov_add_tag (moov, fourcc, flags, data, 2);
+  } else {
+    GST_WRITE_UINT32_BE (data + 2, value);
+    atom_moov_add_tag (moov, fourcc, flags, data, 8);
+  }
+}
+
+void
+atom_moov_add_blob_tag (AtomMOOV * moov, guint8 * data, guint size)
+{
+  AtomData *data_atom;
+  GstBuffer *buf;
+  guint len;
+  guint32 fourcc;
+
+  if (size < 8)
+    return;
+
+  /* blob is unparsed atom;
+   * extract size and fourcc, and wrap remainder in data atom */
+  len = GST_READ_UINT32_BE (data);
+  fourcc = GST_READ_UINT32_LE (data + 4);
+  if (len > size)
+    return;
+
+  buf = gst_buffer_new ();
+  GST_BUFFER_SIZE (buf) = len - 8;
+  GST_BUFFER_DATA (buf) = data + 8;
+
+  data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
+  gst_buffer_unref (buf);
+
+  atom_moov_append_tag (moov,
+      build_atom_info_wrapper ((Atom *) data_atom, (gpointer)atom_data_copy_data,
+              (gpointer)atom_data_free));
+}
+
+void
+atom_moov_add_3gp_tag (AtomMOOV * moov, guint32 fourcc, guint8 * data,
+    guint size)
+{
+  AtomData *data_atom;
+  GstBuffer *buf;
+  guint8 *bdata;
+
+  /* need full atom */
+  buf = gst_buffer_new_and_alloc (size + 4);
+  bdata = GST_BUFFER_DATA (buf);
+  /* full atom: version and flags */
+  GST_WRITE_UINT32_BE (bdata, 0);
+  memcpy (bdata + 4, data, size);
+
+  data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
+  gst_buffer_unref (buf);
+
+  atom_moov_append_tag (moov,
+      build_atom_info_wrapper ((Atom *) data_atom, (gpointer)atom_data_copy_data,
+              (gpointer)atom_data_free));
+}
+
+guint16
+language_code (const char *lang)
+{
+  g_return_val_if_fail (lang != NULL, 0);
+  g_return_val_if_fail (strlen (lang) == 3, 0);
+
+  return (((lang[0] - 0x60) & 0x1F) << 10) + (((lang[1] - 0x60) & 0x1F) << 5) +
+      ((lang[2] - 0x60) & 0x1F);
+}
+
+void
+atom_moov_add_3gp_str_int_tag (AtomMOOV * moov, guint32 fourcc,
+    const gchar * value, gint16 ivalue)
+{
+  gint len = 0, size = 0;
+  guint8 *data;
+
+  if (value) {
+    len = strlen (value);
+    size = len + 3;
+  }
+
+  if (ivalue >= 0)
+    size += 2;
+
+  data = g_malloc (size + 3);
+  /* language tag and null-terminated UTF-8 string */
+  if (value) {
+    GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
+    /* include 0 terminator */
+    memcpy (data + 2, value, len + 1);
+  }
+  /* 16-bit unsigned int if standalone, otherwise 8-bit */
+  if (ivalue >= 0) {
+    if (size == 2)
+      GST_WRITE_UINT16_BE (data + size - 2, ivalue);
+    else {
+      GST_WRITE_UINT8 (data + size - 2, ivalue & 0xFF);
+      size--;
+    }
+  }
+
+  atom_moov_add_3gp_tag (moov, fourcc, data, size);
+  g_free (data);
+}
+
+void
+atom_moov_add_3gp_str_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value)
+{
+  atom_moov_add_3gp_str_int_tag (moov, fourcc, value, -1);
+}
+
+void
+atom_moov_add_3gp_uint_tag (AtomMOOV * moov, guint32 fourcc, guint16 value)
+{
+  atom_moov_add_3gp_str_int_tag (moov, fourcc, NULL, value);
+}
+
+/*
+ * Functions for specifying media types
+ */
+
+static void
+atom_minf_set_audio (AtomMINF * minf)
+{
+  atom_minf_clear_handlers (minf);
+  minf->smhd = atom_smhd_new ();
+}
+
+static void
+atom_minf_set_video (AtomMINF * minf, AtomsContext * context)
+{
+  atom_minf_clear_handlers (minf);
+  minf->vmhd = atom_vmhd_new (context);
+}
+
+static void
+atom_hdlr_set_type (AtomHDLR * hdlr, AtomsContext * context, guint32 comp_type,
+    guint32 hdlr_type)
+{
+  if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
+    hdlr->component_type = comp_type;
+  }
+  hdlr->handler_type = hdlr_type;
+}
+
+static void
+atom_mdia_set_hdlr_type_audio (AtomMDIA * mdia, AtomsContext * context)
+{
+  atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_soun);
+}
+
+static void
+atom_mdia_set_hdlr_type_video (AtomMDIA * mdia, AtomsContext * context)
+{
+  atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_vide);
+}
+
+static void
+atom_mdia_set_audio (AtomMDIA * mdia, AtomsContext * context)
+{
+  atom_mdia_set_hdlr_type_audio (mdia, context);
+  atom_minf_set_audio (&mdia->minf);
+}
+
+static void
+atom_mdia_set_video (AtomMDIA * mdia, AtomsContext * context)
+{
+  atom_mdia_set_hdlr_type_video (mdia, context);
+  atom_minf_set_video (&mdia->minf, context);
+}
+
+static void
+atom_tkhd_set_audio (AtomTKHD * tkhd)
+{
+  tkhd->volume = 0x0100;
+  tkhd->width = tkhd->height = 0;
+}
+
+static void
+atom_tkhd_set_video (AtomTKHD * tkhd, AtomsContext * context, guint32 width,
+    guint32 height)
+{
+  tkhd->volume = 0;
+
+  /* qt and ISO base media do not contradict, and examples agree */
+  tkhd->width = width;
+  tkhd->height = height;
+}
+
+/* re-negotiation is prevented at top-level, so only 1 entry expected.
+ * Quite some more care here and elsewhere may be needed to
+ * support several entries */
+static SampleTableEntryMP4A *
+atom_trak_add_audio_entry (AtomTRAK * trak, AtomsContext * context,
+    guint32 type)
+{
+  AtomSTSD *stsd = &trak->mdia.minf.stbl.stsd;
+  SampleTableEntryMP4A *mp4a = sample_entry_mp4a_new ();
+
+  mp4a->se.header.type = type;
+  mp4a->se.kind = AUDIO;
+  mp4a->compression_id = -1;
+  mp4a->se.data_reference_index = 1;
+
+  stsd->entries = g_list_prepend (stsd->entries, mp4a);
+  stsd->n_entries++;
+  return mp4a;
+}
+
+static SampleTableEntryMP4V *
+atom_trak_add_video_entry (AtomTRAK * trak, AtomsContext * context,
+    guint32 type)
+{
+  SampleTableEntryMP4V *mp4v = sample_entry_mp4v_new (context);
+  AtomSTSD *stsd = &trak->mdia.minf.stbl.stsd;
+
+  mp4v->se.header.type = type;
+  mp4v->se.kind = VIDEO;
+  mp4v->se.data_reference_index = 1;
+  mp4v->horizontal_resolution = 72 << 16;
+  mp4v->vertical_resolution = 72 << 16;
+  if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
+    mp4v->spatial_quality = 512;
+    mp4v->temporal_quality = 512;
+  }
+
+  stsd->entries = g_list_prepend (stsd->entries, mp4v);
+  stsd->n_entries++;
+  return mp4v;
+}
+
+static void
+atom_trak_set_constant_size_samples (AtomTRAK * trak, guint32 sample_size)
+{
+  trak->mdia.minf.stbl.stsz.sample_size = sample_size;
+}
+
+static void
+atom_trak_set_audio (AtomTRAK * trak, AtomsContext * context)
+{
+  atom_tkhd_set_audio (&trak->tkhd);
+  atom_mdia_set_audio (&trak->mdia, context);
+}
+
+static void
+atom_trak_set_video (AtomTRAK * trak, AtomsContext * context, guint32 width,
+    guint32 height)
+{
+  atom_tkhd_set_video (&trak->tkhd, context, width, height);
+  atom_mdia_set_video (&trak->mdia, context);
+}
+
+static void
+atom_trak_set_audio_commons (AtomTRAK * trak, AtomsContext * context,
+    guint32 rate)
+{
+  atom_trak_set_audio (trak, context);
+  trak->mdia.mdhd.time_info.timescale = rate;
+}
+
+static void
+atom_trak_set_video_commons (AtomTRAK * trak, AtomsContext * context,
+    guint32 rate, guint32 width, guint32 height)
+{
+  atom_trak_set_video (trak, context, width, height);
+  trak->mdia.mdhd.time_info.timescale = rate;
+  trak->tkhd.width = width << 16;
+  trak->tkhd.height = height << 16;
+}
+
+void
+atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
+    AudioSampleEntry * entry, guint32 scale, AtomInfo * ext, gint sample_size)
+{
+  SampleTableEntryMP4A *ste;
+
+  atom_trak_set_audio_commons (trak, context, scale);
+  ste = atom_trak_add_audio_entry (trak, context, entry->fourcc);
+
+  trak->is_video = FALSE;
+  trak->is_h264 = FALSE;
+
+  ste->version = entry->version;
+  ste->compression_id = entry->compression_id;
+  ste->sample_size = entry->sample_size;
+  ste->sample_rate = entry->sample_rate << 16;
+  ste->channels = entry->channels;
+
+  ste->samples_per_packet = entry->samples_per_packet;
+  ste->bytes_per_sample = entry->bytes_per_sample;
+  ste->bytes_per_packet = entry->bytes_per_packet;
+  ste->bytes_per_frame = entry->bytes_per_frame;
+
+  if (ext)
+    ste->extension_atoms = g_list_prepend (ste->extension_atoms, ext);
+
+  /* 0 size means variable size */
+  atom_trak_set_constant_size_samples (trak, sample_size);
+}
+
+AtomInfo *
+build_pasp_extension (AtomTRAK * trak, gint par_width, gint par_height)
+{
+  AtomData *atom_data;
+  GstBuffer *buf;
+  guint8 *data;
+
+  buf = gst_buffer_new_and_alloc (8);
+  data = GST_BUFFER_DATA (buf);
+
+  /* ihdr = image header box */
+  GST_WRITE_UINT32_BE (data, par_width);
+  GST_WRITE_UINT32_BE (data + 4, par_height);
+
+  atom_data = atom_data_new_from_gst_buffer (FOURCC_pasp, buf);
+  gst_buffer_unref (buf);
+
+  return build_atom_info_wrapper ((Atom *) atom_data, (gpointer)atom_data_copy_data,
+          (gpointer)atom_data_free);
+}
+
+void
+atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
+    VisualSampleEntry * entry, guint32 scale, AtomInfo * ext)
+{
+  SampleTableEntryMP4V *ste;
+  gint dwidth, dheight;
+  gint par_n = 0, par_d = 0;
+
+  if ((entry->par_n != 1 || entry->par_d != 1) &&
+      (entry->par_n != entry->par_d)) {
+    par_n = entry->par_n;
+    par_d = entry->par_d;
+  }
+
+  dwidth = entry->width;
+  dheight = entry->height;
+  /* ISO file spec says track header w/h indicates track's visual presentation
+   * (so this together with pixels w/h implicitly defines PAR) */
+  if (par_n && (context->flavor != ATOMS_TREE_FLAVOR_MOV)) {
+    if (par_n > par_d) {
+      dwidth = entry->width * par_n / par_d;
+      dheight = entry->height;
+    } else {
+      dwidth = entry->width * par_n / par_d;
+      dheight = entry->height;
+    }
+  }
+
+  atom_trak_set_video_commons (trak, context, scale, dwidth, dheight);
+  ste = atom_trak_add_video_entry (trak, context, entry->fourcc);
+
+  trak->is_video = TRUE;
+  trak->is_h264 = (entry->fourcc == FOURCC_avc1);
+
+  ste->width = entry->width;
+  ste->height = entry->height;
+  ste->depth = entry->depth;
+  ste->color_table_id = entry->color_table_id;
+  ste->frame_count = entry->frame_count;
+
+  if (ext)
+    ste->extension_atoms = g_list_prepend (ste->extension_atoms, ext);
+
+  /* QT spec has a pasp extension atom in stsd that can hold PAR */
+  if (par_n && (context->flavor == ATOMS_TREE_FLAVOR_MOV)) {
+    ste->extension_atoms = g_list_append (ste->extension_atoms,
+        build_pasp_extension (trak, par_n, par_d));
+  }
+}
+
+/* some sample description construction helpers */
+
+AtomInfo *
+build_esds_extension (AtomTRAK * trak, guint8 object_type, guint8 stream_type,
+    const GstBuffer * codec_data)
+{
+  guint32 track_id;
+  AtomESDS *esds;
+
+  track_id = trak->tkhd.track_ID;
+
+  esds = atom_esds_new ();
+  esds->es.id = track_id & 0xFFFF;
+  esds->es.dec_conf_desc.object_type = object_type;
+  esds->es.dec_conf_desc.stream_type = stream_type << 2 | 0x01;
+
+  /* optional DecoderSpecificInfo */
+  if (codec_data) {
+    DecoderSpecificInfoDescriptor *desc;
+
+    esds->es.dec_conf_desc.dec_specific_info = desc =
+        desc_dec_specific_info_new ();
+    desc_dec_specific_info_alloc_data (desc, GST_BUFFER_SIZE (codec_data));
+
+    memcpy (desc->data, GST_BUFFER_DATA (codec_data),
+        GST_BUFFER_SIZE (codec_data));
+  }
+
+  return build_atom_info_wrapper ((Atom *) esds, (gpointer)atom_esds_copy_data,
+          (gpointer)atom_esds_free);
+}
+
+AtomInfo *
+build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data)
+{
+  AtomWAVE *wave;
+  AtomFRMA *frma;
+  Atom *ext_atom;
+  GstBuffer *buf;
+
+  /* Add WAVE atom to the MP4A sample table entry */
+  wave = atom_wave_new ();
+
+  /* Prepend Terminator atom to the WAVE list first, so it ends up last */
+  ext_atom = (Atom *) atom_data_new (FOURCC_null);
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) ext_atom,
+      (AtomCopyDataFunc) atom_data_copy_data, (AtomFreeFunc) atom_data_free);
+
+  /* Add ESDS atom to WAVE */
+  wave->extension_atoms = g_list_prepend (wave->extension_atoms,
+      build_esds_extension (trak, ESDS_OBJECT_TYPE_MPEG4_P3,
+          ESDS_STREAM_TYPE_AUDIO, codec_data));
+
+  /* Add MP4A atom to the WAVE:
+   * not really in spec, but makes offset based players happy */
+  buf = gst_buffer_new_and_alloc (4);
+  *((guint32 *) GST_BUFFER_DATA (buf)) = 0;
+  ext_atom = (Atom *) atom_data_new_from_gst_buffer (FOURCC_mp4a, buf);
+  gst_buffer_unref (buf);
+
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) ext_atom,
+      (AtomCopyDataFunc) atom_data_copy_data, (AtomFreeFunc) atom_data_free);
+
+  /* Add FRMA to the WAVE */
+  frma = atom_frma_new ();
+  frma->media_type = FOURCC_mp4a;
+
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) frma,
+      (AtomCopyDataFunc) atom_frma_copy_data, (AtomFreeFunc) atom_frma_free);
+
+  return build_atom_info_wrapper ((Atom *) wave, (gpointer)atom_wave_copy_data,
+          (gpointer)atom_wave_free);
+}
+
+AtomInfo *
+build_jp2h_extension (AtomTRAK * trak, gint width, gint height, guint32 fourcc)
+{
+  AtomData *atom_data;
+  GstBuffer *buf;
+  guint8 *data;
+  guint8 cenum;
+
+  if (fourcc == GST_MAKE_FOURCC ('s', 'R', 'G', 'B')) {
+    cenum = 0x10;
+  } else if (fourcc == GST_MAKE_FOURCC ('s', 'Y', 'U', 'V')) {
+    cenum = 0x12;
+  } else
+    return FALSE;
+
+  buf = gst_buffer_new_and_alloc (22 + 15);
+  data = GST_BUFFER_DATA (buf);
+
+  /* ihdr = image header box */
+  GST_WRITE_UINT32_BE (data, 22);
+  GST_WRITE_UINT32_LE (data + 4, GST_MAKE_FOURCC ('i', 'h', 'd', 'r'));
+  GST_WRITE_UINT32_BE (data + 8, height);
+  GST_WRITE_UINT32_BE (data + 12, width);
+  /* FIXME perhaps parse from stream,
+   * though exactly 3 in any respectable colourspace */
+  GST_WRITE_UINT16_BE (data + 16, 3);
+  /* 8 bits per component, unsigned */
+  GST_WRITE_UINT8 (data + 18, 0x7);
+  /* compression type; reserved */
+  GST_WRITE_UINT8 (data + 19, 0x7);
+  /* colour space (un)known */
+  GST_WRITE_UINT8 (data + 20, 0x0);
+  /* intellectual property right (box present) */
+  GST_WRITE_UINT8 (data + 21, 0x0);
+
+  /* colour specification box */
+  data += 22;
+  GST_WRITE_UINT32_BE (data, 15);
+  GST_WRITE_UINT32_LE (data + 4, GST_MAKE_FOURCC ('c', 'o', 'l', 'r'));
+  /* specification method: enumerated */
+  GST_WRITE_UINT8 (data + 8, 0x1);
+  /* precedence; reserved */
+  GST_WRITE_UINT8 (data + 9, 0x0);
+  /* approximation; reserved */
+  GST_WRITE_UINT8 (data + 10, 0x0);
+  /* enumerated colourspace */
+  GST_WRITE_UINT32_BE (data + 11, cenum);
+
+  atom_data = atom_data_new_from_gst_buffer (FOURCC_jp2h, buf);
+  gst_buffer_unref (buf);
+
+  return build_atom_info_wrapper ((Atom *) atom_data, (gpointer)atom_data_copy_data,
+          (gpointer)atom_data_free);
+}
+
+AtomInfo *
+build_codec_data_extension (guint32 fourcc, const GstBuffer * codec_data)
+{
+  AtomData *data;
+  AtomInfo *result = NULL;
+
+  if (codec_data) {
+    data = atom_data_new_from_gst_buffer (fourcc, codec_data);
+    result = build_atom_info_wrapper ((Atom *) data, (gpointer)atom_data_copy_data,
+            (gpointer)atom_data_free);
+  }
+
+  return result;
+}
+
+AtomInfo *
+build_amr_extension ()
+{
+  guint8 ext[9];
+  GstBuffer *buf;
+  AtomInfo *res;
+
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = ext;
+  GST_BUFFER_SIZE (buf) = sizeof (ext);
+
+  /* vendor */
+  GST_WRITE_UINT32_LE (ext, 0);
+  /* decoder version */
+  GST_WRITE_UINT8 (ext + 4, 0);
+  /* mode set (all modes) */
+  GST_WRITE_UINT16_BE (ext + 5, 0x81FF);
+  /* mode change period (no restriction) */
+  GST_WRITE_UINT8 (ext + 7, 0);
+  /* frames per sample */
+  GST_WRITE_UINT8 (ext + 8, 1);
+
+  res = build_codec_data_extension (GST_MAKE_FOURCC ('d', 'a', 'm', 'r'), buf);
+  gst_buffer_unref (buf);
+  return res;
+}
+
+AtomInfo *
+build_h263_extension ()
+{
+  guint8 ext[7];
+  GstBuffer *buf;
+  AtomInfo *res;
+
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = ext;
+  GST_BUFFER_SIZE (buf) = sizeof (ext);
+
+  /* vendor */
+  GST_WRITE_UINT32_LE (ext, 0);
+  /* decoder version */
+  GST_WRITE_UINT8 (ext + 4, 0);
+  /* level / profile */
+  /* FIXME ? maybe ? obtain somewhere; baseline for now */
+  GST_WRITE_UINT8 (ext + 5, 10);
+  GST_WRITE_UINT8 (ext + 6, 0);
+
+  res = build_codec_data_extension (GST_MAKE_FOURCC ('d', '2', '6', '3'), buf);
+  gst_buffer_unref (buf);
+  return res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/atoms.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,671 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __ATOMS_H__
+#define __ATOMS_H__
+
+#include <glib.h>
+#include <string.h>
+
+#include "descriptors.h"
+#include "properties.h"
+#include "fourcc.h"
+#include "ftypcc.h"
+
+/* light-weight context that may influence header atom tree construction */
+typedef enum _AtomsTreeFlavor
+{
+  ATOMS_TREE_FLAVOR_MOV,
+  ATOMS_TREE_FLAVOR_ISOM,
+  ATOMS_TREE_FLAVOR_3GP
+} AtomsTreeFlavor;
+
+typedef struct _AtomsContext
+{
+  AtomsTreeFlavor flavor;
+} AtomsContext;
+
+AtomsContext* atoms_context_new  (AtomsTreeFlavor flavor);
+void          atoms_context_free (AtomsContext *context);
+
+#define METADATA_DATA_FLAG 0x0
+#define METADATA_TEXT_FLAG 0x1
+
+/* atom defs and functions */
+
+/**
+ * Used for storing time related values for some atoms.
+ */
+typedef struct _TimeInfo
+{
+  guint64 creation_time;
+  guint64 modification_time;
+  guint32 timescale;
+  guint64 duration;
+} TimeInfo;
+
+typedef struct _Atom
+{
+  guint32 size;
+  guint32 type;
+  guint64 extended_size;
+} Atom;
+
+typedef struct _AtomFull
+{
+  Atom header;
+
+  guint8 version;
+  guint8 flags[3];
+} AtomFull;
+
+/*
+ * Generic extension atom
+ */
+typedef struct _AtomData
+{
+  Atom header;
+
+  /* not written */
+  guint32 datalen;
+  guint8 *data;
+} AtomData;
+
+typedef struct _AtomFTYP
+{
+  Atom header;
+  guint32 major_brand;
+  guint32 version;
+  guint32 *compatible_brands;
+
+  /* not written */
+  guint32 compatible_brands_size;
+} AtomFTYP;
+
+typedef struct _AtomMVHD
+{
+  AtomFull header;
+
+  /* version 0: 32 bits */
+  TimeInfo time_info;
+
+  guint32 prefered_rate;      /* ISO: 0x00010000 */
+  guint16 volume;             /* ISO: 0x0100 */
+  guint16 reserved3;          /* ISO: 0x0 */
+  guint32 reserved4[2];       /* ISO: 0, 0 */
+  /* ISO: identity matrix =
+   * { 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 } */
+  guint32 matrix[9];
+
+  /* ISO: all 0 */
+  guint32 preview_time;
+  guint32 preview_duration;
+  guint32 poster_time;
+  guint32 selection_time;
+  guint32 selection_duration;
+  guint32 current_time;
+
+  guint32 next_track_id;
+} AtomMVHD;
+
+typedef struct _AtomTKHD
+{
+  AtomFull header;
+
+  /* version 0: 32 bits */
+  /* like the TimeInfo struct, but it has this track_ID inside */
+  guint64 creation_time;
+  guint64 modification_time;
+  guint32 track_ID;
+  guint32 reserved;
+  guint64 duration;
+
+  guint32 reserved2[2];
+  guint16 layer;
+  guint16 alternate_group;
+  guint16 volume;
+  guint16 reserved3;
+
+  /* ISO: identity matrix =
+   * { 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 } */
+  guint32 matrix[9];
+  guint32 width;
+  guint32 height;
+} AtomTKHD;
+
+typedef struct _AtomMDHD
+{
+  AtomFull header;
+
+  /* version 0: 32 bits */
+  TimeInfo time_info;
+
+  /* ISO: packed ISO-639-2/T language code (first bit must be 0) */
+  guint16 language_code;
+  /* ISO: 0 */
+  guint16 quality;
+} AtomMDHD;
+
+typedef struct _AtomHDLR
+{
+  AtomFull header;
+
+  /* ISO: 0 */
+  guint32 component_type;
+  guint32 handler_type;
+  guint32 manufacturer;
+  guint32 flags;
+  guint32 flags_mask;
+  gchar *name;
+} AtomHDLR;
+
+typedef struct _AtomVMHD
+{
+  AtomFull header;          /* ISO: flags = 1 */
+
+  guint16 graphics_mode;
+  /* RGB */
+  guint16 opcolor[3];
+} AtomVMHD;
+
+typedef struct _AtomSMHD
+{
+  AtomFull header;
+
+  guint16 balance;
+  guint16 reserved;
+} AtomSMHD;
+
+typedef struct _AtomHMHD
+{
+  AtomFull header;
+
+  guint16 max_pdu_size;
+  guint16 avg_pdu_size;
+  guint32 max_bitrate;
+  guint32 avg_bitrate;
+  guint32 sliding_avg_bitrate;
+} AtomHMHD;
+
+typedef struct _AtomURL
+{
+  AtomFull header;
+
+  gchar *location;
+} AtomURL;
+
+typedef struct _AtomDREF
+{
+  AtomFull header;
+
+  GList *entries;
+} AtomDREF;
+
+typedef struct _AtomDINF
+{
+  Atom header;
+
+  AtomDREF dref;
+} AtomDINF;
+
+typedef struct _STTSEntry
+{
+  guint32 sample_count;
+  gint32 sample_delta;
+} STTSEntry;
+
+typedef struct _AtomSTTS
+{
+  AtomFull header;
+
+  guint n_entries;
+  /* list of STTSEntry */
+  GList *entries;
+} AtomSTTS;
+
+typedef struct _AtomSTSS
+{
+  AtomFull header;
+
+  guint n_entries;
+  /* list of sample indexes (guint32) */
+  GList *entries;
+} AtomSTSS;
+
+typedef struct _AtomESDS
+{
+  AtomFull header;
+
+  ESDescriptor es;
+} AtomESDS;
+
+typedef struct _AtomFRMA
+{
+  Atom header;
+
+  guint32 media_type;
+} AtomFRMA;
+
+typedef enum _SampleEntryKind
+{
+  UNKNOWN,
+  AUDIO,
+  VIDEO
+} SampleEntryKind;
+
+typedef struct _SampleTableEntry
+{
+  Atom header;
+
+  guint8 reserved[6];
+  guint16 data_reference_index;
+
+  /* sort of entry */
+  SampleEntryKind kind;
+} SampleTableEntry;
+
+typedef struct _AtomHintSampleEntry
+{
+  SampleTableEntry se;
+  guint32 size;
+  guint8 *data;
+} AtomHintSampleEntry;
+
+typedef struct _SampleTableEntryMP4V
+{
+  SampleTableEntry se;
+
+  guint16 version;
+  guint16 revision_level;
+
+  guint32 vendor;                 /* fourcc code */
+  guint32 temporal_quality;
+  guint32 spatial_quality;
+
+  guint16 width;
+  guint16 height;
+
+  guint32 horizontal_resolution;
+  guint32 vertical_resolution;
+  guint32 datasize;
+
+  guint16 frame_count;            /* usually 1 */
+
+  guint8 compressor[32];         /* pascal string, i.e. first byte = length */
+
+  guint16 depth;
+  guint16 color_table_id;
+
+  /* (optional) list of AtomInfo */
+  GList *extension_atoms;
+} SampleTableEntryMP4V;
+
+typedef struct _SampleTableEntryMP4A
+{
+  SampleTableEntry se;
+
+  guint16 version;
+  guint16 revision_level;
+  guint32 vendor;
+
+  guint16 channels;
+  guint16 sample_size;
+  guint16 compression_id;
+  guint16 packet_size;
+
+  guint32 sample_rate;            /* fixed point 16.16 */
+
+  guint32 samples_per_packet;
+  guint32 bytes_per_packet;
+  guint32 bytes_per_frame;
+  guint32 bytes_per_sample;
+
+  /* (optional) list of AtomInfo */
+  GList *extension_atoms;
+} SampleTableEntryMP4A;
+
+typedef struct _SampleTableEntryMP4S
+{
+  SampleTableEntry se;
+
+  AtomESDS es;
+} SampleTableEntryMP4S;
+
+typedef struct _AtomSTSD
+{
+  AtomFull header;
+
+  guint n_entries;
+  /* list of subclasses of SampleTableEntry */
+  GList *entries;
+} AtomSTSD;
+
+typedef struct _AtomSTSZ
+{
+  AtomFull header;
+
+  guint32 sample_size;
+
+  /* need the size here because when sample_size is constant,
+   * the list is empty */
+  guint32 table_size;
+  /* list of guint32 */
+  GList *entries;
+} AtomSTSZ;
+
+typedef struct _STSCEntry
+{
+  guint32 first_chunk;
+  guint32 samples_per_chunk;
+  guint32 sample_description_index;
+} STSCEntry;
+
+typedef struct _AtomSTSC
+{
+  AtomFull header;
+
+  guint n_entries;
+  /* list of STSCEntry */
+  GList *entries;
+} AtomSTSC;
+
+
+/*
+ * used for both STCO and CO64
+ * if used as STCO, entries should be truncated to use only 32bits
+ */
+typedef struct _AtomSTCO64
+{
+  AtomFull header;
+
+  guint n_entries;
+  /* list of guint64 */
+  GList *entries;
+} AtomSTCO64;
+
+typedef struct _CTTSEntry
+{
+  guint32 samplecount;
+  guint32 sampleoffset;
+} CTTSEntry;
+
+typedef struct _AtomCTTS
+{
+  AtomFull header;
+
+  /* also entry count here */
+  guint n_entries;
+  GList *entries;
+} AtomCTTS;
+
+typedef struct _AtomSTBL
+{
+  Atom header;
+
+  AtomSTSD stsd;
+  AtomSTTS stts;
+  AtomSTSS stss;
+  AtomSTSC stsc;
+  AtomSTSZ stsz;
+  /* NULL if not present */
+  AtomCTTS *ctts;
+
+  AtomSTCO64 stco64;
+} AtomSTBL;
+
+typedef struct _AtomMINF
+{
+  Atom header;
+
+  /* only (exactly) one of those must be present */
+  AtomVMHD *vmhd;
+  AtomSMHD *smhd;
+  AtomHMHD *hmhd;
+
+  AtomHDLR *hdlr;
+  AtomDINF dinf;
+  AtomSTBL stbl;
+} AtomMINF;
+
+typedef struct _AtomMDIA
+{
+  Atom header;
+
+  AtomMDHD mdhd;
+  AtomHDLR hdlr;
+  AtomMINF minf;
+} AtomMDIA;
+
+typedef struct _AtomILST
+{
+  Atom header;
+
+  /* list of AtomInfo */
+  GList* entries;
+} AtomILST;
+
+typedef struct _AtomTagData
+{
+  AtomFull header;
+  guint32 reserved;
+
+  guint32 datalen;
+  guint8* data;
+} AtomTagData;
+
+typedef struct _AtomTag
+{
+  Atom header;
+
+  AtomTagData data;
+} AtomTag;
+
+typedef struct _AtomMETA
+{
+  AtomFull header;
+  AtomHDLR hdlr;
+  AtomILST *ilst;
+} AtomMETA;
+
+typedef struct _AtomUDTA
+{
+  Atom header;
+
+  /* list of AtomInfo */
+  GList* entries;
+  /* or list is further down */
+  AtomMETA *meta;
+} AtomUDTA;
+
+typedef struct _AtomTRAK
+{
+  Atom header;
+
+  AtomTKHD tkhd;
+  AtomMDIA mdia;
+
+  /* some helper info for structural conformity checks */
+  gboolean is_video;
+  gboolean is_h264;
+} AtomTRAK;
+
+typedef struct _AtomMOOV
+{
+  /* style */
+  AtomsContext context;
+
+  Atom header;
+
+  AtomMVHD mvhd;
+
+  /* list of AtomTRAK */
+  GList *traks;
+  AtomUDTA *udta;
+} AtomMOOV;
+
+typedef struct _AtomWAVE
+{
+  Atom header;
+
+  /* list of AtomInfo */
+  GList *extension_atoms;
+} AtomWAVE;
+
+
+/*
+ * Function to serialize an atom
+ */
+typedef guint64 (*AtomCopyDataFunc) (Atom *atom, guint8 **buffer, guint64 *size, guint64 *offset);
+
+/*
+ * Releases memory allocated by an atom
+ */
+typedef guint64 (*AtomFreeFunc) (Atom *atom);
+
+/*
+ * Some atoms might have many optional different kinds of child atoms, so this
+ * is useful for enabling generic handling of any atom.
+ * All we need are the two functions (copying it to an array
+ * for serialization and the memory releasing function).
+ */
+typedef struct _AtomInfo
+{
+  Atom *atom;
+  AtomCopyDataFunc copy_data_func;
+  AtomFreeFunc free_func;
+} AtomInfo;
+
+
+guint64    atom_copy_data              (Atom *atom, guint8 **buffer,
+                                        guint64 *size, guint64* offset);
+
+AtomFTYP*  atom_ftyp_new               (AtomsContext *context, guint32 major,
+                                        guint32 version, GList *brands);
+guint64    atom_ftyp_copy_data         (AtomFTYP *ftyp, guint8 **buffer,
+                                        guint64 *size, guint64 *offset);
+void       atom_ftyp_free              (AtomFTYP *ftyp);
+
+AtomTRAK*  atom_trak_new               (AtomsContext *context);
+void       atom_trak_add_samples       (AtomTRAK * trak, guint32 nsamples, guint32 delta,
+                                        guint32 size, guint64 chunk_offset, gboolean sync,
+                                        gboolean do_pts, gint64 pts_offset);
+guint32    atom_trak_get_timescale     (AtomTRAK *trak);
+
+AtomMOOV*  atom_moov_new               (AtomsContext *context);
+void       atom_moov_free              (AtomMOOV *moov);
+guint64    atom_moov_copy_data         (AtomMOOV *atom, guint8 **buffer, guint64 *size, guint64* offset);
+void       atom_moov_update_timescale  (AtomMOOV *moov, guint32 timescale);
+void       atom_moov_update_duration   (AtomMOOV *moov);
+void       atom_moov_set_64bits        (AtomMOOV *moov, gboolean large_file);
+void       atom_moov_chunks_add_offset (AtomMOOV *moov, guint32 offset);
+void       atom_moov_add_trak          (AtomMOOV *moov, AtomTRAK *trak);
+
+/* media sample description related helpers */
+
+typedef struct
+{
+  guint32 fourcc;
+  guint width;
+  guint height;
+  guint depth;
+  guint frame_count;
+  gint color_table_id;
+  guint par_n;
+  guint par_d;
+
+  GstBuffer *codec_data;
+} VisualSampleEntry;
+
+typedef struct
+{
+  guint32 fourcc;
+  guint version;
+  gint compression_id;
+  guint sample_rate;
+  guint channels;
+  guint sample_size;
+  guint bytes_per_packet;
+  guint samples_per_packet;
+  guint bytes_per_sample;
+  guint bytes_per_frame;
+
+  GstBuffer *codec_data;
+} AudioSampleEntry;
+
+void atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
+                               AudioSampleEntry * entry, guint32 scale,
+                               AtomInfo * ext, gint sample_size);
+void atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
+                               VisualSampleEntry * entry, guint32 rate,
+                               AtomInfo * ext);
+
+AtomInfo *   build_codec_data_extension  (guint32 fourcc, const GstBuffer * codec_data);
+AtomInfo *   build_mov_aac_extension     (AtomTRAK * trak, const GstBuffer * codec_data);
+AtomInfo *   build_esds_extension        (AtomTRAK * trak, guint8 object_type,
+                                          guint8 stream_type, const GstBuffer * codec_data);
+AtomInfo *   build_jp2h_extension        (AtomTRAK * trak, gint width, gint height,
+                                          guint32 fourcc);
+AtomInfo *   build_amr_extension         ();
+AtomInfo *   build_h263_extension        ();
+
+
+/*
+ * Meta tags functions
+ */
+void atom_moov_add_str_tag    (AtomMOOV *moov, guint32 fourcc, const gchar *value);
+void atom_moov_add_uint_tag   (AtomMOOV *moov, guint32 fourcc, guint32 flags,
+                               guint32 value);
+void atom_moov_add_tag        (AtomMOOV *moov, guint32 fourcc, guint32 flags,
+                               const guint8 * data, guint size);
+void atom_moov_add_blob_tag   (AtomMOOV *moov, guint8 *data, guint size);
+
+void atom_moov_add_3gp_str_tag       (AtomMOOV * moov, guint32 fourcc, const gchar * value);
+void atom_moov_add_3gp_uint_tag      (AtomMOOV * moov, guint32 fourcc, guint16 value);
+void atom_moov_add_3gp_str_int_tag   (AtomMOOV * moov, guint32 fourcc, const gchar * value,
+                                      gint16 ivalue);
+void atom_moov_add_3gp_tag           (AtomMOOV * moov, guint32 fourcc, guint8 * data,
+                                      guint size);
+
+#define GST_QT_MUX_DEFAULT_TAG_LANGUAGE   "eng"
+guint16  language_code               (const char * lang);
+
+#endif /* __ATOMS_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/descriptors.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,465 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "descriptors.h"
+
+/**
+ * Some mp4 structures (descriptors) use a coding scheme for
+ * representing its size.
+ * It is grouped in bytes. The 1st bit set to 1 means we need another byte,
+ * 0 otherwise. The remaining 7 bits are the useful values.
+ *
+ * The next set of functions handle those values
+ */
+
+/**
+ * Gets an unsigned integer and packs it into a 'expandable size' format
+ * (as used by mp4 descriptors)
+ * @size: the integer to be parsed
+ * @ptr: the array to place the result
+ * @array_size: the size of ptr array
+ */
+static void
+expandable_size_parse (guint64 size, guint8 * ptr, guint32 array_size)
+{
+  int index = 0;
+
+  memset (ptr, 0, sizeof (array_size));
+  while (size > 0 && index < array_size) {
+    ptr[index++] = (size > 0x7F ? 0x80 : 0x0) | (size & 0x7F);
+    size = size >> 7;
+  }
+}
+
+/**
+ * Gets how many positions in an array holding an 'expandable size'
+ * are really used
+ *
+ * @ptr: the array with the 'expandable size'
+ * @array_size: the size of ptr array
+ *
+ * Returns: the number of really used positions
+ */
+static guint64
+expandable_size_get_length (guint8 * ptr, guint32 array_size)
+{
+  gboolean next = TRUE;
+  guint32 index = 0;
+
+  while (next && index < array_size) {
+    next = ((ptr[index] & 0x80) == 1);
+    index++;
+  }
+  return index;
+}
+
+/*
+ * Initializers below
+ */
+
+static void
+desc_base_descriptor_init (BaseDescriptor * bd, guint8 tag, guint32 size)
+{
+  bd->tag = tag;
+  expandable_size_parse (size, bd->size, 4);
+}
+
+static void
+desc_dec_specific_info_init (DecoderSpecificInfoDescriptor * dsid)
+{
+  desc_base_descriptor_init (&dsid->base, DECODER_SPECIFIC_INFO_TAG, 0);
+  dsid->length = 0;
+  dsid->data = NULL;
+}
+
+DecoderSpecificInfoDescriptor *
+desc_dec_specific_info_new ()
+{
+  DecoderSpecificInfoDescriptor *desc =
+      g_new0 (DecoderSpecificInfoDescriptor, 1);
+  desc_dec_specific_info_init (desc);
+  return desc;
+}
+
+static void
+desc_dec_conf_desc_init (DecoderConfigDescriptor * dcd)
+{
+  desc_base_descriptor_init (&dcd->base, DECODER_CONFIG_DESC_TAG, 0);
+  dcd->dec_specific_info = NULL;
+}
+
+static void
+desc_sl_conf_desc_init (SLConfigDescriptor * sl)
+{
+  desc_base_descriptor_init (&sl->base, SL_CONFIG_DESC_TAG, 0);
+  sl->predefined = 0x2;
+}
+
+void
+desc_es_init (ESDescriptor * es)
+{
+  desc_base_descriptor_init (&es->base, ES_DESCRIPTOR_TAG, 0);
+
+  es->id = 0;
+  es->flags = 0;
+  es->depends_on_es_id = 0;
+  es->ocr_es_id = 0;
+  es->url_length = 0;
+  es->url_string = NULL;
+
+  desc_dec_conf_desc_init (&es->dec_conf_desc);
+  desc_sl_conf_desc_init (&es->sl_conf_desc);
+}
+
+ESDescriptor *
+desc_es_descriptor_new ()
+{
+  ESDescriptor *es = g_new0 (ESDescriptor, 1);
+
+  desc_es_init (es);
+  return es;
+}
+
+/*
+ * Deinitializers/Destructors below
+ */
+
+static void
+desc_base_descriptor_clear (BaseDescriptor * base)
+{
+}
+
+void
+desc_dec_specific_info_free (DecoderSpecificInfoDescriptor * dsid)
+{
+  desc_base_descriptor_clear (&dsid->base);
+  if (dsid->data) {
+    g_free (dsid->data);
+    dsid->data = NULL;
+  }
+  g_free (dsid);
+}
+
+static void
+desc_dec_conf_desc_clear (DecoderConfigDescriptor * dec)
+{
+  desc_base_descriptor_clear (&dec->base);
+  if (dec->dec_specific_info) {
+    desc_dec_specific_info_free (dec->dec_specific_info);
+  }
+}
+
+static void
+desc_sl_config_descriptor_clear (SLConfigDescriptor * sl)
+{
+  desc_base_descriptor_clear (&sl->base);
+}
+
+void
+desc_es_descriptor_clear (ESDescriptor * es)
+{
+  desc_base_descriptor_clear (&es->base);
+  if (es->url_string) {
+    g_free (es->url_string);
+    es->url_string = NULL;
+  }
+  desc_dec_conf_desc_clear (&es->dec_conf_desc);
+  desc_sl_config_descriptor_clear (&es->sl_conf_desc);
+}
+
+void
+desc_es_descriptor_free (ESDescriptor * es)
+{
+  desc_es_descriptor_clear (es);
+  g_free (es);
+}
+
+/*
+ * Size handling functions below
+ */
+
+void
+desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor * dsid,
+    guint32 size)
+{
+  if (dsid->data) {
+    g_free (dsid->data);
+  }
+  dsid->data = g_new0 (guint8, size);
+  dsid->length = size;
+}
+
+static void
+desc_base_descriptor_set_size (BaseDescriptor * bd, guint32 size)
+{
+  expandable_size_parse (size, bd->size, 4);
+}
+
+static guint64
+desc_base_descriptor_get_size (BaseDescriptor * bd)
+{
+  guint64 size = 0;
+
+  size += sizeof (guint8);
+  size += expandable_size_get_length (bd->size, 4) * sizeof (guint8);
+  return size;
+}
+
+static guint64
+desc_sl_config_descriptor_get_size (SLConfigDescriptor * sl_desc)
+{
+  guint64 size = 0;
+  guint64 extra_size = 0;
+
+  size += desc_base_descriptor_get_size (&sl_desc->base);
+  /* predefined */
+  extra_size += sizeof (guint8);
+
+  desc_base_descriptor_set_size (&sl_desc->base, extra_size);
+
+  return size + extra_size;
+}
+
+static guint64
+desc_dec_specific_info_get_size (DecoderSpecificInfoDescriptor * dsid)
+{
+  guint64 size = 0;
+  guint64 extra_size = 0;
+
+  size += desc_base_descriptor_get_size (&dsid->base);
+  extra_size += sizeof (guint8) * dsid->length;
+  desc_base_descriptor_set_size (&dsid->base, extra_size);
+  return size + extra_size;
+}
+
+static guint64
+desc_dec_config_descriptor_get_size (DecoderConfigDescriptor * dec_desc)
+{
+  guint64 size = 0;
+  guint64 extra_size = 0;
+
+  size += desc_base_descriptor_get_size (&dec_desc->base);
+  /* object type */
+  extra_size += sizeof (guint8);
+  /* stream type */
+  extra_size += sizeof (guint8);
+  /* buffer size */
+  extra_size += sizeof (guint8) * 3;
+  /* max bitrate */
+  extra_size += sizeof (guint32);
+  /* avg bitrate */
+  extra_size += sizeof (guint32);
+  if (dec_desc->dec_specific_info) {
+    extra_size += desc_dec_specific_info_get_size (dec_desc->dec_specific_info);
+  }
+
+  desc_base_descriptor_set_size (&dec_desc->base, extra_size);
+  return size + extra_size;
+}
+
+static guint64
+desc_es_descriptor_get_size (ESDescriptor * es)
+{
+  guint64 size = 0;
+  guint64 extra_size = 0;
+
+  size += desc_base_descriptor_get_size (&es->base);
+  /* id */
+  extra_size += sizeof (guint16);
+  /* flags */
+  extra_size += sizeof (guint8);
+  /* depends_on_es_id */
+  if (es->flags & 0x80) {
+    extra_size += sizeof (guint16);
+  }
+  if (es->flags & 0x40) {
+    /* url_length */
+    extra_size += sizeof (guint8);
+    /* url */
+    extra_size += sizeof (gchar) * es->url_length;
+  }
+  if (es->flags & 0x20) {
+    /* ocr_es_id */
+    extra_size += sizeof (guint16);
+  }
+
+  extra_size += desc_dec_config_descriptor_get_size (&es->dec_conf_desc);
+  extra_size += desc_sl_config_descriptor_get_size (&es->sl_conf_desc);
+
+  desc_base_descriptor_set_size (&es->base, extra_size);
+
+  return size + extra_size;
+}
+
+static gboolean
+desc_es_descriptor_check_stream_dependency (ESDescriptor * es)
+{
+  return es->flags & 0x80;
+}
+
+static gboolean
+desc_es_descriptor_check_url_flag (ESDescriptor * es)
+{
+  return es->flags & 0x40;
+}
+
+static gboolean
+desc_es_descriptor_check_ocr (ESDescriptor * es)
+{
+  return es->flags & 0x20;
+}
+
+/* Copy/Serializations Functions below */
+
+static guint64
+desc_base_descriptor_copy_data (BaseDescriptor * desc, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  prop_copy_uint8 (desc->tag, buffer, size, offset);
+  prop_copy_uint8_array (desc->size, expandable_size_get_length (desc->size, 4),
+      buffer, size, offset);
+  return original_offset - *offset;
+}
+
+static guint64
+desc_sl_config_descriptor_copy_data (SLConfigDescriptor * desc,
+    guint8 ** buffer, guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
+    return 0;
+  }
+  /* predefined attribute */
+  prop_copy_uint8 (desc->predefined, buffer, size, offset);
+
+  return *offset - original_offset;
+}
+
+static guint64
+desc_dec_specific_info_copy_data (DecoderSpecificInfoDescriptor * desc,
+    guint8 ** buffer, guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
+    return 0;
+  }
+  prop_copy_uint8_array (desc->data, desc->length, buffer, size, offset);
+
+  return *offset - original_offset;
+}
+
+static guint64
+desc_dec_config_descriptor_copy_data (DecoderConfigDescriptor * desc,
+    guint8 ** buffer, guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
+    return 0;
+  }
+
+  prop_copy_uint8 (desc->object_type, buffer, size, offset);
+
+  prop_copy_uint8 (desc->stream_type, buffer, size, offset);
+  prop_copy_uint8_array (desc->buffer_size_DB, 3, buffer, size, offset);
+
+  prop_copy_uint32 (desc->max_bitrate, buffer, size, offset);
+  prop_copy_uint32 (desc->avg_bitrate, buffer, size, offset);
+
+  if (desc->dec_specific_info) {
+    if (!desc_dec_specific_info_copy_data (desc->dec_specific_info, buffer,
+            size, offset)) {
+      return 0;
+    }
+  }
+
+  return *offset - original_offset;
+}
+
+guint64
+desc_es_descriptor_copy_data (ESDescriptor * desc, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 desc_size;
+  guint64 original_offset = *offset;
+
+  /* must call this twice to have size fields of all contained descriptors set
+   * correctly, and to have the size of the size fields taken into account */
+  desc_size = desc_es_descriptor_get_size (desc);
+  desc_size = desc_es_descriptor_get_size (desc);
+
+  if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
+    return 0;
+  }
+  /* id and flags */
+  prop_copy_uint16 (desc->id, buffer, size, offset);
+  prop_copy_uint8 (desc->flags, buffer, size, offset);
+
+  if (desc_es_descriptor_check_stream_dependency (desc)) {
+    prop_copy_uint16 (desc->depends_on_es_id, buffer, size, offset);
+  }
+
+  if (desc_es_descriptor_check_url_flag (desc)) {
+    prop_copy_size_string (desc->url_string, desc->url_length, buffer, size,
+        offset);
+  }
+
+  if (desc_es_descriptor_check_ocr (desc)) {
+    prop_copy_uint16 (desc->ocr_es_id, buffer, size, offset);
+  }
+
+  if (!desc_dec_config_descriptor_copy_data (&desc->dec_conf_desc, buffer, size,
+          offset)) {
+    return 0;
+  }
+
+  if (!desc_sl_config_descriptor_copy_data (&desc->sl_conf_desc, buffer, size,
+          offset)) {
+    return 0;
+  }
+
+  return *offset - original_offset;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/descriptors.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,151 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __DESCRIPTORS_H__
+#define __DESCRIPTORS_H__
+
+#include <glib.h>
+#include <string.h>
+#include "properties.h"
+
+/*
+ * Tags for descriptor (each kind is represented by a number, instead of fourcc as in atoms)
+ */
+#define OBJECT_DESC_TAG            0x01
+#define INIT_OBJECT_DESC_TAG       0x02
+#define ES_DESCRIPTOR_TAG          0x03
+#define DECODER_CONFIG_DESC_TAG    0x04
+#define DECODER_SPECIFIC_INFO_TAG  0x05
+#define SL_CONFIG_DESC_TAG         0x06
+#define ES_ID_INC_TAG              0x0E
+#define MP4_INIT_OBJECT_DESC_TAG   0x10
+
+#define ESDS_OBJECT_TYPE_MPEG1_P3       0x6B
+#define ESDS_OBJECT_TYPE_MPEG2_P7_MAIN  0x66
+#define ESDS_OBJECT_TYPE_MPEG4_P7_LC    0x67
+#define ESDS_OBJECT_TYPE_MPEG4_P7_SSR   0x68
+#define ESDS_OBJECT_TYPE_MPEG4_P2       0x20
+#define ESDS_OBJECT_TYPE_MPEG4_P3       0x40
+
+#define ESDS_STREAM_TYPE_VISUAL         0x04
+#define ESDS_STREAM_TYPE_AUDIO          0x05
+
+
+typedef struct _BaseDescriptor
+{
+  guint8 tag;
+  /* the first bit of each byte indicates if the next byte should be used */
+  guint8 size[4];
+} BaseDescriptor;
+
+typedef struct _SLConfigDescriptor
+{
+  BaseDescriptor base;
+
+  guint8 predefined;              /* everything is supposed predefined */
+} SLConfigDescriptor;
+
+typedef struct _DecoderSpecificInfoDescriptor
+{
+  BaseDescriptor base;
+  guint32 length;
+  guint8 *data;
+} DecoderSpecificInfoDescriptor;
+
+typedef struct _DecoderConfigDescriptor {
+  BaseDescriptor base;
+
+  guint8 object_type;
+
+  /* following are condensed into streamType:
+   * bit(6) streamType;
+   * bit(1) upStream;
+   * const bit(1) reserved=1;
+  */
+  guint8 stream_type;
+
+  guint8 buffer_size_DB[3];
+  guint32 max_bitrate;
+  guint32 avg_bitrate;
+
+  DecoderSpecificInfoDescriptor *dec_specific_info;
+} DecoderConfigDescriptor;
+
+typedef struct _ESDescriptor
+{
+  BaseDescriptor base;
+
+  guint16 id;
+
+  /* flags contains the following:
+   * bit(1) streamDependenceFlag;
+   * bit(1) URL_Flag;
+   * bit(1) OCRstreamFlag;
+   * bit(5) streamPriority;
+   */
+  guint8 flags;
+
+  guint16 depends_on_es_id;
+  guint8 url_length;              /* only if URL_flag is set */
+  guint8 *url_string;             /* size is url_length */
+
+  guint16 ocr_es_id;              /* only if OCRstreamFlag is set */
+
+  DecoderConfigDescriptor dec_conf_desc;
+  SLConfigDescriptor sl_conf_desc;
+
+  /* optional remainder of ESDescriptor is not used */
+} ESDescriptor;
+
+/* --- FUNCTIONS --- */
+void    desc_es_init                               (ESDescriptor *es);
+ESDescriptor *desc_es_descriptor_new               ();
+guint64 desc_es_descriptor_copy_data               (ESDescriptor *es, guint8 **buffer,
+                                                    guint64 *size, guint64 *offset);
+void    desc_es_descriptor_clear                   (ESDescriptor *es);
+
+DecoderSpecificInfoDescriptor *desc_dec_specific_info_new();
+void    desc_dec_specific_info_free                (DecoderSpecificInfoDescriptor *dsid);
+void    desc_dec_specific_info_alloc_data          (DecoderSpecificInfoDescriptor *dsid,
+                                                    guint32 size);
+
+#endif /* __DESCRIPTORS_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/fourcc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,196 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+ /*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#ifndef __FOURCC_H__
+#define __FOURCC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define FOURCC_null     0x0
+
+#define FOURCC_moov     GST_MAKE_FOURCC('m','o','o','v')
+#define FOURCC_mvhd     GST_MAKE_FOURCC('m','v','h','d')
+#define FOURCC_clip     GST_MAKE_FOURCC('c','l','i','p')
+#define FOURCC_trak     GST_MAKE_FOURCC('t','r','a','k')
+#define FOURCC_udta     GST_MAKE_FOURCC('u','d','t','a')
+#define FOURCC_ctab     GST_MAKE_FOURCC('c','t','a','b')
+#define FOURCC_tkhd     GST_MAKE_FOURCC('t','k','h','d')
+#define FOURCC_crgn     GST_MAKE_FOURCC('c','r','g','n')
+#define FOURCC_matt     GST_MAKE_FOURCC('m','a','t','t')
+#define FOURCC_kmat     GST_MAKE_FOURCC('k','m','a','t')
+#define FOURCC_edts     GST_MAKE_FOURCC('e','d','t','s')
+#define FOURCC_elst     GST_MAKE_FOURCC('e','l','s','t')
+#define FOURCC_load     GST_MAKE_FOURCC('l','o','a','d')
+#define FOURCC_tref     GST_MAKE_FOURCC('t','r','e','f')
+#define FOURCC_imap     GST_MAKE_FOURCC('i','m','a','p')
+#define FOURCC___in     GST_MAKE_FOURCC(' ',' ','i','n')
+#define FOURCC___ty     GST_MAKE_FOURCC(' ',' ','t','y')
+#define FOURCC_mdia     GST_MAKE_FOURCC('m','d','i','a')
+#define FOURCC_mdhd     GST_MAKE_FOURCC('m','d','h','d')
+#define FOURCC_hdlr     GST_MAKE_FOURCC('h','d','l','r')
+#define FOURCC_dhlr     GST_MAKE_FOURCC('d','h','l','r')
+#define FOURCC_mhlr     GST_MAKE_FOURCC('m','h','l','r')
+#define FOURCC_minf     GST_MAKE_FOURCC('m','i','n','f')
+#define FOURCC_mdir     GST_MAKE_FOURCC('m','d','i','r')
+#define FOURCC_vmhd     GST_MAKE_FOURCC('v','m','h','d')
+#define FOURCC_smhd     GST_MAKE_FOURCC('s','m','h','d')
+#define FOURCC_gmhd     GST_MAKE_FOURCC('g','m','h','d')
+#define FOURCC_gmin     GST_MAKE_FOURCC('g','m','i','n')
+#define FOURCC_dinf     GST_MAKE_FOURCC('d','i','n','f')
+#define FOURCC_dref     GST_MAKE_FOURCC('d','r','e','f')
+#define FOURCC_stbl     GST_MAKE_FOURCC('s','t','b','l')
+#define FOURCC_stsd     GST_MAKE_FOURCC('s','t','s','d')
+#define FOURCC_stts     GST_MAKE_FOURCC('s','t','t','s')
+#define FOURCC_stss     GST_MAKE_FOURCC('s','t','s','s')
+#define FOURCC_stsc     GST_MAKE_FOURCC('s','t','s','c')
+#define FOURCC_stsz     GST_MAKE_FOURCC('s','t','s','z')
+#define FOURCC_stco     GST_MAKE_FOURCC('s','t','c','o')
+#define FOURCC_vide     GST_MAKE_FOURCC('v','i','d','e')
+#define FOURCC_soun     GST_MAKE_FOURCC('s','o','u','n')
+#define FOURCC_strm     GST_MAKE_FOURCC('s','t','r','m')
+#define FOURCC_rtsp     GST_MAKE_FOURCC('r','t','s','p')
+#define FOURCC_co64     GST_MAKE_FOURCC('c','o','6','4')
+#define FOURCC_cmov     GST_MAKE_FOURCC('c','m','o','v')
+#define FOURCC_dcom     GST_MAKE_FOURCC('d','c','o','m')
+#define FOURCC_cmvd     GST_MAKE_FOURCC('c','m','v','d')
+#define FOURCC_hint     GST_MAKE_FOURCC('h','i','n','t')
+#define FOURCC_mp4a     GST_MAKE_FOURCC('m','p','4','a')
+#define FOURCC__mp3     GST_MAKE_FOURCC('.','m','p','3')
+#define FOURCC_mp4s	GST_MAKE_FOURCC('m','p','4','s')
+#define FOURCC_mp4v     GST_MAKE_FOURCC('m','p','4','v')
+#define FOURCC_2vuy     GST_MAKE_FOURCC('2','v','u','y')
+#define FOURCC_wave     GST_MAKE_FOURCC('w','a','v','e')
+#define FOURCC_appl     GST_MAKE_FOURCC('a','p','p','l')
+#define FOURCC_esds     GST_MAKE_FOURCC('e','s','d','s')
+#define FOURCC_pasp     GST_MAKE_FOURCC('p','a','s','p')
+#define FOURCC_hnti     GST_MAKE_FOURCC('h','n','t','i')
+#define FOURCC_rtp_     GST_MAKE_FOURCC('r','t','p',' ')
+#define FOURCC_sdp_     GST_MAKE_FOURCC('s','d','p',' ')
+#define FOURCC_meta     GST_MAKE_FOURCC('m','e','t','a')
+#define FOURCC_ilst     GST_MAKE_FOURCC('i','l','s','t')
+#define FOURCC__nam     GST_MAKE_FOURCC(0xa9,'n','a','m')
+#define FOURCC__ART     GST_MAKE_FOURCC(0xa9,'A','R','T')
+#define FOURCC__wrt     GST_MAKE_FOURCC(0xa9,'w','r','t')
+#define FOURCC__grp     GST_MAKE_FOURCC(0xa9,'g','r','p')
+#define FOURCC__alb     GST_MAKE_FOURCC(0xa9,'a','l','b')
+#define FOURCC__day     GST_MAKE_FOURCC(0xa9,'d','a','y')
+#define FOURCC__des     GST_MAKE_FOURCC(0xa9,'d','e','s')
+#define FOURCC_gnre     GST_MAKE_FOURCC('g','n','r','e')
+#define FOURCC_disc     GST_MAKE_FOURCC('d','i','s','c')
+#define FOURCC_disk     GST_MAKE_FOURCC('d','i','s','k')
+#define FOURCC_trkn     GST_MAKE_FOURCC('t','r','k','n')
+#define FOURCC_cprt     GST_MAKE_FOURCC('c','p','r','t')
+#define FOURCC_covr     GST_MAKE_FOURCC('c','o','v','r')
+#define FOURCC_cpil     GST_MAKE_FOURCC('c','p','i','l')
+#define FOURCC_tmpo     GST_MAKE_FOURCC('t','m','p','o')
+#define FOURCC__too     GST_MAKE_FOURCC(0xa9,'t','o','o')
+#define FOURCC_keyw     GST_MAKE_FOURCC('k','e','y','w')
+#define FOURCC_____     GST_MAKE_FOURCC('-','-','-','-')
+#define FOURCC_free     GST_MAKE_FOURCC('f','r','e','e')
+#define FOURCC_data     GST_MAKE_FOURCC('d','a','t','a')
+#define FOURCC_SVQ3     GST_MAKE_FOURCC('S','V','Q','3')
+#define FOURCC_rmra     GST_MAKE_FOURCC('r','m','r','a')
+#define FOURCC_rmda     GST_MAKE_FOURCC('r','m','d','a')
+#define FOURCC_rdrf     GST_MAKE_FOURCC('r','d','r','f')
+#define FOURCC__gen     GST_MAKE_FOURCC(0xa9, 'g', 'e', 'n')
+#define FOURCC_rmdr     GST_MAKE_FOURCC('r','m','d','r')
+#define FOURCC_rmvc     GST_MAKE_FOURCC('r','m','v','c')
+#define FOURCC_qtim     GST_MAKE_FOURCC('q','t','i','m')
+#define FOURCC_drms     GST_MAKE_FOURCC('d','r','m','s')
+#define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
+#define FOURCC_h263     GST_MAKE_FOURCC('h','2','6','3')
+#define FOURCC_s263     GST_MAKE_FOURCC('s','2','6','3')
+#define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
+#define FOURCC_VP31     GST_MAKE_FOURCC('V','P','3','1')
+#define FOURCC_rle_     GST_MAKE_FOURCC('r','l','e',' ')
+#define FOURCC_MAC6     GST_MAKE_FOURCC('M','A','C','6')
+#define FOURCC_MAC3     GST_MAKE_FOURCC('M','A','C','3')
+#define FOURCC_ima4     GST_MAKE_FOURCC('i','m','a','4')
+#define FOURCC_ulaw     GST_MAKE_FOURCC('u','l','a','w')
+#define FOURCC_alaw     GST_MAKE_FOURCC('a','l','a','w')
+#define FOURCC_twos     GST_MAKE_FOURCC('t','w','o','s')
+#define FOURCC_sowt     GST_MAKE_FOURCC('s','o','w','t')
+#define FOURCC_raw_     GST_MAKE_FOURCC('r','a','w',' ')
+#define FOURCC_QDM2     GST_MAKE_FOURCC('Q','D','M','2')
+#define FOURCC_alac     GST_MAKE_FOURCC('a','l','a','c')
+#define FOURCC_samr     GST_MAKE_FOURCC('s','a','m','r')
+#define FOURCC_sawb     GST_MAKE_FOURCC('s','a','w','b')
+#define FOURCC_mdat     GST_MAKE_FOURCC('m','d','a','t')
+#define FOURCC_wide     GST_MAKE_FOURCC('w','i','d','e')
+#define FOURCC_PICT     GST_MAKE_FOURCC('P','I','C','T')
+#define FOURCC_pnot     GST_MAKE_FOURCC('p','n','o','t')
+#define FOURCC_zlib     GST_MAKE_FOURCC('z','l','i','b')
+#define FOURCC_alis     GST_MAKE_FOURCC('a','l','i','s')
+#define FOURCC_url_     GST_MAKE_FOURCC('u','r','l',' ')
+#define FOURCC_frma     GST_MAKE_FOURCC('f','r','m','a')
+#define FOURCC_ctts     GST_MAKE_FOURCC('c','t','t','s')
+#define FOURCC_drac     GST_MAKE_FOURCC('d','r','a','c')
+#define FOURCC_jpeg     GST_MAKE_FOURCC('j','p','e','g')
+#define FOURCC_mjp2     GST_MAKE_FOURCC('m','j','p','2')
+#define FOURCC_jp2h     GST_MAKE_FOURCC('j','p','2','h')
+
+/* Xiph fourcc */
+#define FOURCC_XiTh     GST_MAKE_FOURCC('X','i','T','h')
+#define FOURCC_XdxT     GST_MAKE_FOURCC('X','d','x','T')
+#define FOURCC_tCtH     GST_MAKE_FOURCC('t','C','t','H')
+#define FOURCC_tCt_     GST_MAKE_FOURCC('t','C','t','#')
+#define FOURCC_tCtC     GST_MAKE_FOURCC('t','C','t','C')
+
+/* ilst metatags */
+#define FOURCC_titl     GST_MAKE_FOURCC('t','i','t','l')
+#define FOURCC__cmt     GST_MAKE_FOURCC(0xa9, 'c','m','t')
+
+/* 3gp tags */
+#define FOURCC_dscp     GST_MAKE_FOURCC('d','s','c','p')
+#define FOURCC_perf     GST_MAKE_FOURCC('p','e','r','f')
+#define FOURCC_auth     GST_MAKE_FOURCC('a','u','t','h')
+#define FOURCC_yrrc     GST_MAKE_FOURCC('y','r','r','c')
+#define FOURCC_albm     GST_MAKE_FOURCC('a','l','b','m')
+#define FOURCC_loci     GST_MAKE_FOURCC('l','o','c','i')
+#define FOURCC_kywd     GST_MAKE_FOURCC('k','y','w','d')
+
+G_END_DECLS
+
+#endif /* __FOURCC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/ftypcc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,66 @@
+/* GStreamer
+ * Copyright (C) <2008> Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FTYP_CC_H__
+#define __FTYP_CC_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define FOURCC_ftyp	GST_MAKE_FOURCC('f','t','y','p')
+#define FOURCC_isom     GST_MAKE_FOURCC('i','s','o','m')
+#define FOURCC_iso2     GST_MAKE_FOURCC('i','s','o','2')
+#define FOURCC_mp41     GST_MAKE_FOURCC('m','p','4','1')
+#define FOURCC_mp42     GST_MAKE_FOURCC('m','p','4','2')
+#define FOURCC_mjp2     GST_MAKE_FOURCC('m','j','p','2')
+#define FOURCC_3gp4     GST_MAKE_FOURCC('3','g','p','4')
+#define FOURCC_3gp6     GST_MAKE_FOURCC('3','g','p','6')
+#define FOURCC_3gg6     GST_MAKE_FOURCC('3','g','g','6')
+#define FOURCC_3gr6     GST_MAKE_FOURCC('3','g','r','6')
+#define FOURCC_3gg7     GST_MAKE_FOURCC('3','g','g','7')
+#define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
+#define FOURCC_qt__     GST_MAKE_FOURCC('q','t',' ',' ')
+
+G_END_DECLS
+
+#endif /* __FTYP_CC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/gstqtmux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,2236 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+/**
+ * SECTION:gstqtmux
+ * @short_description: Muxer for quicktime(.mov) files
+ *
+ * <refsect2>
+ * <para>
+ * This element merges streams (audio and video) into qt(.mov) files.
+ * </para>
+ * <title>Example pipelines</title>
+ * <para>
+ * <programlisting>
+ * gst-launch v4l2src num-buffers=500 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! qtmux ! filesink location=video.mov
+ * </programlisting>
+ * Records a video stream captured from a v4l2 device and muxes it into a qt file.
+ * </para>
+ * </refsect2>
+ *
+ * Last reviewed on 2008-08-27
+ */
+
+/*
+ * Based on avimux
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gstdio.h>
+
+#include <gst/gst.h>
+#include <gst/base/gstcollectpads.h>
+
+#include <sys/types.h>
+#ifdef G_OS_WIN32
+#include <io.h>                 /* lseek, open, close, read */
+#undef lseek
+#define lseek _lseeki64
+#undef off_t
+#define off_t guint64
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#include "gstqtmux.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_qt_mux_debug);
+#define GST_CAT_DEFAULT gst_qt_mux_debug
+
+/* QTMux signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_LARGE_FILE,
+  PROP_MOVIE_TIMESCALE,
+  PROP_DO_CTTS,
+  PROP_FLAVOR,
+  PROP_FAST_START,
+  PROP_FAST_START_TEMP_FILE
+};
+
+/* some spare for header size as well */
+#define MDAT_LARGE_FILE_LIMIT           ((guint64) 1024 * 1024 * 1024 * 2)
+
+#define DEFAULT_LARGE_FILE              FALSE
+#define DEFAULT_MOVIE_TIMESCALE         1000
+#define DEFAULT_DO_CTTS                 FALSE
+#define DEFAULT_FAST_START              FALSE
+#define DEFAULT_FAST_START_TEMP_FILE    NULL
+
+static void gst_qt_mux_finalize (GObject * object);
+
+static GstStateChangeReturn gst_qt_mux_change_state (GstElement * element,
+    GstStateChange transition);
+
+/* property functions */
+static void gst_qt_mux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_qt_mux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
+/* pad functions */
+static GstPad *gst_qt_mux_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * name);
+static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad);
+
+/* event */
+static gboolean gst_qt_mux_sink_event (GstPad * pad, GstEvent * event);
+
+static GstFlowReturn gst_qt_mux_collected (GstCollectPads * pads,
+    gpointer user_data);
+static GstFlowReturn gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
+    GstBuffer * buf);
+
+static GstElementClass *parent_class = NULL;
+
+static void
+gst_qt_mux_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  GstQTMuxClass *klass = (GstQTMuxClass *) g_class;
+  GstQTMuxClassParams *params;
+  GstElementDetails details;
+  GstPadTemplate *videosinktempl, *audiosinktempl, *srctempl;
+
+  params =
+      (GstQTMuxClassParams *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (g_class),
+      GST_QT_MUX_PARAMS_QDATA);
+  g_assert (params != NULL);
+
+  /* construct the element details struct */
+  details.longname = g_strdup_printf ("%s Muxer", params->prop->long_name);
+  details.klass = g_strdup ("Codec/Muxer");
+  details.description =
+      g_strdup_printf ("Multiplex audio and video into a %s file",
+      params->prop->long_name);
+  details.author = "Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>";
+  gst_element_class_set_details (element_class, &details);
+  g_free (details.longname);
+  g_free (details.klass);
+  g_free (details.description);
+
+  /* pad templates */
+  srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
+      GST_PAD_ALWAYS, params->src_caps);
+  gst_element_class_add_pad_template (element_class, srctempl);
+
+  if (params->audio_sink_caps) {
+    audiosinktempl = gst_pad_template_new ("audio_%d",
+        GST_PAD_SINK, GST_PAD_REQUEST, params->audio_sink_caps);
+    gst_element_class_add_pad_template (element_class, audiosinktempl);
+  }
+
+  if (params->video_sink_caps) {
+    videosinktempl = gst_pad_template_new ("video_%d",
+        GST_PAD_SINK, GST_PAD_REQUEST, params->video_sink_caps);
+    gst_element_class_add_pad_template (element_class, videosinktempl);
+  }
+
+  klass->format = params->prop->format;
+}
+
+static void
+gst_qt_mux_class_init (GstQTMuxClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_qt_mux_finalize;
+  gobject_class->get_property = gst_qt_mux_get_property;
+  gobject_class->set_property = gst_qt_mux_set_property;
+
+  g_object_class_install_property (gobject_class, PROP_LARGE_FILE,
+      g_param_spec_boolean ("large-file", "Support for large files",
+          "Uses 64bits to some fields instead of 32bits, "
+          "providing support for large files",
+          DEFAULT_LARGE_FILE, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_MOVIE_TIMESCALE,
+      g_param_spec_uint ("movie-timescale", "Movie timescale",
+          "Timescale to use in the movie (units per second)",
+          1, G_MAXUINT32, DEFAULT_MOVIE_TIMESCALE,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (gobject_class, PROP_DO_CTTS,
+      g_param_spec_boolean ("presentation-time",
+          "Include presentation-time info",
+          "Calculate and include presentation/composition time (in addition to decoding time)"
+          " (use with caution)", DEFAULT_DO_CTTS,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (gobject_class, PROP_FAST_START,
+      g_param_spec_boolean ("faststart", "Format file to faststart",
+          "If the file should be formated for faststart (headers first). ",
+          DEFAULT_FAST_START, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_FAST_START_TEMP_FILE,
+      g_param_spec_string ("faststart-file", "File to use for storing buffers",
+          "File that will be used temporarily to store data from the stream when "
+          "creating a faststart file. If null a filepath will be created automatically",
+          DEFAULT_FAST_START_TEMP_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+  gstelement_class->request_new_pad =
+      GST_DEBUG_FUNCPTR (gst_qt_mux_request_new_pad);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qt_mux_change_state);
+  gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_qt_mux_release_pad);
+}
+
+static void
+gst_qt_mux_pad_reset (GstQTPad * qtpad)
+{
+  qtpad->fourcc = 0;
+  qtpad->is_out_of_order = FALSE;
+  qtpad->have_dts = FALSE;
+  qtpad->sample_size = 0;
+  qtpad->sync = FALSE;
+  qtpad->last_dts = 0;
+
+  if (qtpad->last_buf)
+    gst_buffer_replace (&qtpad->last_buf, NULL);
+
+  /* reference owned elsewhere */
+  qtpad->trak = NULL;
+}
+
+/*
+ * Takes GstQTMux back to its initial state
+ */
+static void
+gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc)
+{
+  GSList *walk;
+
+  qtmux->state = GST_QT_MUX_STATE_NONE;
+  qtmux->header_size = 0;
+  qtmux->mdat_size = 0;
+  qtmux->mdat_pos = 0;
+  qtmux->longest_chunk = GST_CLOCK_TIME_NONE;
+
+  if (qtmux->ftyp) {
+    atom_ftyp_free (qtmux->ftyp);
+    qtmux->ftyp = NULL;
+  }
+  if (qtmux->moov) {
+    atom_moov_free (qtmux->moov);
+    qtmux->moov = NULL;
+  }
+  if (qtmux->fast_start_file) {
+    fclose (qtmux->fast_start_file);
+    qtmux->fast_start_file = NULL;
+  }
+  gst_tag_setter_reset_tags (GST_TAG_SETTER (qtmux));
+
+  /* reset pad data */
+  for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
+    GstQTPad *qtpad = (GstQTPad *) walk->data;
+    gst_qt_mux_pad_reset (qtpad);
+
+    /* hm, moov_free above yanked the traks away from us,
+     * so do not free, but do clear */
+    qtpad->trak = NULL;
+  }
+
+  if (alloc) {
+    qtmux->moov = atom_moov_new (qtmux->context);
+    /* ensure all is as nice and fresh as request_new_pad would provide it */
+    for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
+      GstQTPad *qtpad = (GstQTPad *) walk->data;
+
+      qtpad->trak = atom_trak_new (qtmux->context);
+      atom_moov_add_trak (qtmux->moov, qtpad->trak);
+    }
+  }
+}
+
+static void
+gst_qt_mux_init (GstQTMux * qtmux, GstQTMuxClass * qtmux_klass)
+{
+  GstElementClass *klass = GST_ELEMENT_CLASS (qtmux_klass);
+  GstPadTemplate *templ;
+  GstCaps *caps;
+
+  templ = gst_element_class_get_pad_template (klass, "src");
+  qtmux->srcpad = gst_pad_new_from_template (templ, "src");
+  caps = gst_caps_copy (gst_pad_get_pad_template_caps (qtmux->srcpad));
+  gst_pad_set_caps (qtmux->srcpad, caps);
+  gst_caps_unref (caps);
+  gst_pad_use_fixed_caps (qtmux->srcpad);
+  gst_element_add_pad (GST_ELEMENT (qtmux), qtmux->srcpad);
+
+  qtmux->collect = gst_collect_pads_new ();
+  gst_collect_pads_set_function (qtmux->collect,
+      (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_qt_mux_collected), qtmux);
+
+  /* properties set to default upon construction */
+
+  /* always need this */
+  qtmux->context =
+      atoms_context_new (gst_qt_mux_map_format_to_flavor (qtmux_klass->format));
+
+  /* internals to initial state */
+  gst_qt_mux_reset (qtmux, TRUE);
+}
+
+
+static void
+gst_qt_mux_finalize (GObject * object)
+{
+  GstQTMux *qtmux = GST_QT_MUX_CAST (object);
+
+  gst_qt_mux_reset (qtmux, FALSE);
+
+  if (qtmux->fast_start_file_path)
+    g_free (qtmux->fast_start_file_path);
+
+  atoms_context_free (qtmux->context);
+  gst_object_unref (qtmux->collect);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_qt_mux_add_mp4_tag (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  switch (gst_tag_get_type (tag)) {
+      /* strings */
+    case G_TYPE_STRING:
+    {
+      gchar *str = NULL;
+
+      if (!gst_tag_list_get_string (list, tag, &str) || !str)
+        break;
+      GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
+          GST_FOURCC_ARGS (fourcc), str);
+      atom_moov_add_str_tag (qtmux->moov, fourcc, str);
+      g_free (str);
+      break;
+    }
+      /* double */
+    case G_TYPE_DOUBLE:
+    {
+      gdouble value;
+
+      if (!gst_tag_list_get_double (list, tag, &value))
+        break;
+      GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %u",
+          GST_FOURCC_ARGS (fourcc), (gint) value);
+      atom_moov_add_uint_tag (qtmux->moov, fourcc, 21, (gint) value);
+      break;
+    }
+      /* paired unsigned integers */
+    case G_TYPE_UINT:
+    {
+      guint value;
+      guint count;
+
+      if (!gst_tag_list_get_uint (list, tag, &value) ||
+          !gst_tag_list_get_uint (list, tag2, &count))
+        break;
+      GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %u/%u",
+          GST_FOURCC_ARGS (fourcc), value, count);
+      atom_moov_add_uint_tag (qtmux->moov, fourcc, 0,
+          value << 16 | (count & 0xFFFF));
+      break;
+    }
+    default:
+      g_assert_not_reached ();
+      break;
+  }
+}
+
+static void
+gst_qt_mux_add_mp4_date (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  GDate *date = NULL;
+  GDateYear year;
+  GDateMonth month;
+  GDateDay day;
+  gchar *str;
+
+  g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_DATE);
+
+  if (!gst_tag_list_get_date (list, tag, &date) || !date)
+    return;
+
+  year = g_date_get_year (date);
+  month = g_date_get_month (date);
+  day = g_date_get_day (date);
+
+  if (year == G_DATE_BAD_YEAR && month == G_DATE_BAD_MONTH &&
+      day == G_DATE_BAD_DAY) {
+    GST_WARNING_OBJECT (qtmux, "invalid date in tag");
+    return;
+  }
+
+  str = g_strdup_printf ("%u-%u-%u", year, month, day);
+  GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
+      GST_FOURCC_ARGS (fourcc), str);
+  atom_moov_add_str_tag (qtmux->moov, fourcc, str);
+}
+
+static void
+gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  GValue value = { 0, };
+  GstBuffer *buf;
+  GstCaps *caps;
+  GstStructure *structure;
+  gint flags = 0;
+
+  g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_BUFFER);
+
+  if (!gst_tag_list_copy_value (&value, list, tag))
+    return;
+
+  buf = gst_value_get_buffer (&value);
+  if (!buf)
+    goto done;
+
+  caps = gst_buffer_get_caps (buf);
+  if (!caps) {
+    GST_WARNING_OBJECT (qtmux, "preview image without caps");
+    goto done;
+  }
+
+  GST_DEBUG_OBJECT (qtmux, "preview image caps %" GST_PTR_FORMAT, caps);
+
+  structure = gst_caps_get_structure (caps, 0);
+  if (gst_structure_has_name (structure, "image/jpeg"))
+    flags = 13;
+  else if (gst_structure_has_name (structure, "image/png"))
+    flags = 14;
+  gst_caps_unref (caps);
+
+  if (!flags) {
+    GST_WARNING_OBJECT (qtmux, "preview image format not supported");
+    goto done;
+  }
+
+  GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT
+      " -> image size %d", GST_FOURCC_ARGS (fourcc), GST_BUFFER_SIZE (buf));
+  atom_moov_add_tag (qtmux->moov, fourcc, flags, GST_BUFFER_DATA (buf),
+      GST_BUFFER_SIZE (buf));
+done:
+  g_value_unset (&value);
+}
+
+static void
+gst_qt_mux_add_3gp_str (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  gchar *str = NULL;
+  guint number;
+
+  g_return_if_fail (gst_tag_get_type (tag) == G_TYPE_STRING);
+  g_return_if_fail (!tag2 || gst_tag_get_type (tag2) == G_TYPE_UINT);
+
+  if (!gst_tag_list_get_string (list, tag, &str) || !str)
+    return;
+
+  if (tag2)
+    if (!gst_tag_list_get_uint (list, tag2, &number))
+      tag2 = NULL;
+
+  if (!tag2) {
+    GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
+        GST_FOURCC_ARGS (fourcc), str);
+    atom_moov_add_3gp_str_tag (qtmux->moov, fourcc, str);
+  } else {
+    GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s/%d",
+        GST_FOURCC_ARGS (fourcc), str, number);
+    atom_moov_add_3gp_str_int_tag (qtmux->moov, fourcc, str, number);
+  }
+
+  g_free (str);
+}
+
+static void
+gst_qt_mux_add_3gp_date (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  GDate *date = NULL;
+  GDateYear year;
+
+  g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_DATE);
+
+  if (!gst_tag_list_get_date (list, tag, &date) || !date)
+    return;
+
+  year = g_date_get_year (date);
+
+  if (year == G_DATE_BAD_YEAR) {
+    GST_WARNING_OBJECT (qtmux, "invalid date in tag");
+    return;
+  }
+
+  GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %d",
+      GST_FOURCC_ARGS (fourcc), year);
+  atom_moov_add_3gp_uint_tag (qtmux->moov, fourcc, year);
+}
+
+static void
+gst_qt_mux_add_3gp_location (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  gdouble latitude = -360, longitude = -360, altitude = 0;
+  gchar *location = NULL;
+  guint8 *data, *ddata;
+  gint size = 0, len = 0;
+  gboolean ret = FALSE;
+
+  g_return_if_fail (strcmp (tag, GST_TAG_GEO_LOCATION_NAME) == 0);
+
+  ret = gst_tag_list_get_string (list, tag, &location);
+  ret |= gst_tag_list_get_double (list, GST_TAG_GEO_LOCATION_LONGITUDE,
+      &longitude);
+  ret |= gst_tag_list_get_double (list, GST_TAG_GEO_LOCATION_LATITUDE,
+      &latitude);
+  ret |= gst_tag_list_get_double (list, GST_TAG_GEO_LOCATION_ELEVATION,
+      &altitude);
+
+  if (!ret)
+    return;
+
+  if (location)
+    len = strlen (location);
+  size += len + 1 + 2;
+
+  /* role + (long, lat, alt) + body + notes */
+  size += 1 + 3 * 4 + 1 + 1;
+
+  data = ddata = g_malloc (size);
+
+  /* language tag */
+  GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
+  /* location */
+  if (location)
+    memcpy (data + 2, location, len);
+  GST_WRITE_UINT8 (data + 2 + len, 0);
+  data += len + 1 + 2;
+  /* role */
+  GST_WRITE_UINT8 (data, 0);
+  /* long, lat, alt */
+  GST_WRITE_UINT32_BE (data + 1, (guint32) (longitude * 65536.0));
+  GST_WRITE_UINT32_BE (data + 5, (guint32) (latitude * 65536.0));
+  GST_WRITE_UINT32_BE (data + 9, (guint32) (altitude * 65536.0));
+  /* neither astronomical body nor notes */
+  GST_WRITE_UINT16_BE (data + 13, 0);
+
+  GST_DEBUG_OBJECT (qtmux, "Adding tag 'loci'");
+  atom_moov_add_3gp_tag (qtmux->moov, fourcc, ddata, size);
+  g_free (ddata);
+}
+
+static void
+gst_qt_mux_add_3gp_keywords (GstQTMux * qtmux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc)
+{
+  gchar *keywords = NULL;
+  guint8 *data, *ddata;
+  gint size = 0, i;
+  gchar **kwds;
+
+  g_return_if_fail (strcmp (tag, GST_TAG_KEYWORDS) == 0);
+
+  if (!gst_tag_list_get_string (list, tag, &keywords) || !keywords)
+    return;
+
+  kwds = g_strsplit (keywords, ",", 0);
+
+  size = 0;
+  for (i = 0; kwds[i]; i++) {
+    /* size byte + null-terminator */
+    size += strlen (kwds[i]) + 1 + 1;
+  }
+
+  /* language tag + count + keywords */
+  size += 2 + 1;
+
+  data = ddata = g_malloc (size);
+
+  /* language tag */
+  GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
+  /* count */
+  GST_WRITE_UINT8 (data + 2, i);
+  data += 3;
+  /* keywords */
+  for (i = 0; kwds[i]; ++i) {
+    gint len = strlen (kwds[i]);
+
+    GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
+        GST_FOURCC_ARGS (fourcc), kwds[i]);
+    /* size */
+    GST_WRITE_UINT8 (data, len + 1);
+    memcpy (data + 1, kwds[i], len + 1);
+    data += len + 2;
+  }
+
+  g_strfreev (kwds);
+
+  atom_moov_add_3gp_tag (qtmux->moov, fourcc, ddata, size);
+  g_free (ddata);
+}
+
+
+typedef void (*GstQTMuxAddTagFunc) (GstQTMux * mux, const GstTagList * list,
+    const char *tag, const char *tag2, guint32 fourcc);
+
+/*
+ * Struct to record mappings from gstreamer tags to fourcc codes
+ */
+typedef struct _GstTagToFourcc
+{
+  guint32 fourcc;
+  const gchar *gsttag;
+  const gchar *gsttag2;
+  const GstQTMuxAddTagFunc func;
+} GstTagToFourcc;
+
+/* tag list tags to fourcc matching */
+static const GstTagToFourcc tag_matches_mp4[] = {
+  {FOURCC__alb, GST_TAG_ALBUM, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__ART, GST_TAG_ARTIST, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__cmt, GST_TAG_COMMENT, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__wrt, GST_TAG_COMPOSER, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__gen, GST_TAG_GENRE, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__nam, GST_TAG_TITLE, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__des, GST_TAG_DESCRIPTION, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__too, GST_TAG_ENCODER, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC_keyw, GST_TAG_KEYWORDS, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC__day, GST_TAG_DATE, NULL, gst_qt_mux_add_mp4_date},
+  {FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, gst_qt_mux_add_mp4_tag},
+  {FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT,
+      gst_qt_mux_add_mp4_tag},
+  {FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
+      gst_qt_mux_add_mp4_tag},
+  {FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, gst_qt_mux_add_mp4_cover},
+  {0, NULL,}
+};
+
+static const GstTagToFourcc tag_matches_3gp[] = {
+  {FOURCC_titl, GST_TAG_TITLE, NULL, gst_qt_mux_add_3gp_str},
+  {FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, gst_qt_mux_add_3gp_str},
+  {FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, gst_qt_mux_add_3gp_str},
+  {FOURCC_perf, GST_TAG_ARTIST, NULL, gst_qt_mux_add_3gp_str},
+  {FOURCC_auth, GST_TAG_COMPOSER, NULL, gst_qt_mux_add_3gp_str},
+  {FOURCC_gnre, GST_TAG_GENRE, NULL, gst_qt_mux_add_3gp_str},
+  {FOURCC_kywd, GST_TAG_KEYWORDS, NULL, gst_qt_mux_add_3gp_keywords},
+  {FOURCC_yrrc, GST_TAG_DATE, NULL, gst_qt_mux_add_3gp_date},
+  {FOURCC_albm, GST_TAG_ALBUM, GST_TAG_TRACK_NUMBER, gst_qt_mux_add_3gp_str},
+  {FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, gst_qt_mux_add_3gp_location},
+  {0, NULL,}
+};
+
+/* qtdemux produces these for atoms it cannot parse */
+#define GST_QT_DEMUX_PRIVATE_TAG "private-qt-tag"
+
+static void
+gst_qt_mux_add_metadata_tags (GstQTMux * qtmux, const GstTagList * list)
+{
+  GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
+  guint32 fourcc;
+  gint i;
+  const gchar *tag, *tag2;
+  const GstTagToFourcc *tag_matches;
+
+  switch (qtmux_klass->format) {
+    case GST_QT_MUX_FORMAT_3GP:
+      tag_matches = tag_matches_3gp;
+      break;
+    case GST_QT_MUX_FORMAT_MJ2:
+      tag_matches = NULL;
+      break;
+    default:
+      /* sort of iTunes style for mp4 and QT (?) */
+      tag_matches = tag_matches_mp4;
+      break;
+  }
+
+  if (!tag_matches)
+    return;
+
+  for (i = 0; tag_matches[i].fourcc; i++) {
+    fourcc = tag_matches[i].fourcc;
+    tag = tag_matches[i].gsttag;
+    tag2 = tag_matches[i].gsttag2;
+
+    g_assert (tag_matches[i].func);
+    tag_matches[i].func (qtmux, list, tag, tag2, fourcc);
+  }
+
+  /* add unparsed blobs if present */
+  if (gst_tag_exists (GST_QT_DEMUX_PRIVATE_TAG)) {
+    guint num_tags;
+
+    num_tags = gst_tag_list_get_tag_size (list, GST_QT_DEMUX_PRIVATE_TAG);
+    for (i = 0; i < num_tags; ++i) {
+      const GValue *val;
+      GstBuffer *buf;
+      GstCaps *caps = NULL;
+
+      val = gst_tag_list_get_value_index (list, GST_QT_DEMUX_PRIVATE_TAG, i);
+      buf = (GstBuffer *) gst_value_get_mini_object (val);
+
+      if (buf && (caps = gst_buffer_get_caps (buf))) {
+        GstStructure *s;
+        const gchar *style = NULL;
+
+        GST_DEBUG_OBJECT (qtmux, "Found private tag %d/%d; size %d, caps %"
+            GST_PTR_FORMAT, i, num_tags, GST_BUFFER_SIZE (buf), caps);
+        s = gst_caps_get_structure (caps, 0);
+        if (s && (style = gst_structure_get_string (s, "style"))) {
+          /* try to prevent some style tag ending up into another variant
+           * (todo: make into a list if more cases) */
+          if ((strcmp (style, "itunes") == 0 &&
+                  qtmux_klass->format == GST_QT_MUX_FORMAT_MP4) ||
+              (strcmp (style, "iso") == 0 &&
+                  qtmux_klass->format == GST_QT_MUX_FORMAT_3GP)) {
+            GST_DEBUG_OBJECT (qtmux, "Adding private tag");
+            atom_moov_add_blob_tag (qtmux->moov, GST_BUFFER_DATA (buf),
+                GST_BUFFER_SIZE (buf));
+          }
+        }
+        gst_caps_unref (caps);
+      }
+    }
+  }
+
+  return;
+}
+
+/*
+ * Gets the tagsetter iface taglist and puts the known tags
+ * into the output stream
+ */
+static void
+gst_qt_mux_setup_metadata (GstQTMux * qtmux)
+{
+  const GstTagList *tags;
+
+  tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (qtmux));
+
+  GST_LOG_OBJECT (qtmux, "tags: %" GST_PTR_FORMAT, tags);
+
+  if (tags && !gst_tag_list_is_empty (tags)) {
+    GST_DEBUG_OBJECT (qtmux, "Formatting tags");
+    gst_qt_mux_add_metadata_tags (qtmux, tags);
+  } else {
+    GST_DEBUG_OBJECT (qtmux, "No tags received");
+  }
+}
+
+static GstFlowReturn
+gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset,
+    gboolean mind_fast)
+{
+  GstFlowReturn res;
+  guint8 *data;
+  guint size;
+
+  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  GST_LOG_OBJECT (qtmux, "sending buffer size %d", size);
+
+  if (mind_fast && qtmux->fast_start_file) {
+    gint ret;
+
+    GST_LOG_OBJECT (qtmux, "to temporary file");
+    ret = fwrite (data, sizeof (guint8), size, qtmux->fast_start_file);
+    gst_buffer_unref (buf);
+    if (ret != size)
+      goto write_error;
+    else
+      res = GST_FLOW_OK;
+  } else {
+    GST_LOG_OBJECT (qtmux, "downstream");
+
+    gst_buffer_set_caps (buf, GST_PAD_CAPS (qtmux->srcpad));
+    res = gst_pad_push (qtmux->srcpad, buf);
+  }
+
+  if (G_LIKELY (offset))
+    *offset += size;
+
+  return res;
+
+  /* ERRORS */
+write_error:
+  {
+    GST_ELEMENT_ERROR (qtmux, RESOURCE, WRITE,
+        ("Failed to write to temporary file"), GST_ERROR_SYSTEM);
+    return GST_FLOW_ERROR;
+  }
+}
+
+static GstFlowReturn
+gst_qt_mux_send_buffered_data (GstQTMux * qtmux, guint64 * offset)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstBuffer *buf = NULL;
+
+  if (fflush (qtmux->fast_start_file))
+    goto flush_failed;
+
+#ifdef HAVE_FSEEKO
+  if (fseeko (qtmux->fast_start_file, (off_t) 0, SEEK_SET) != 0)
+    goto seek_failed;
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
+  if (lseek (fileno (qtmux->fast_start_file), (off_t) 0,
+          SEEK_SET) == (off_t) - 1)
+    goto seek_failed;
+#else
+  if (fseek (qtmux->fast_start_file, (long) 0, SEEK_SET) != 0)
+    goto seek_failed;
+#endif
+
+  /* hm, this could all take a really really long time,
+   * but there may not be another way to get moov atom first
+   * (somehow optimize copy?) */
+  GST_DEBUG_OBJECT (qtmux, "Sending buffered data");
+  while (ret == GST_FLOW_OK) {
+    gint r;
+    const int bufsize = 4096;
+
+    buf = gst_buffer_new_and_alloc (bufsize);
+    r = fread (GST_BUFFER_DATA (buf), sizeof (guint8), bufsize,
+        qtmux->fast_start_file);
+    if (r == 0)
+      break;
+    GST_BUFFER_SIZE (buf) = r;
+    GST_LOG_OBJECT (qtmux, "Pushing buffered buffer of size %d", r);
+    ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
+    buf = NULL;
+  }
+  if (buf)
+    gst_buffer_unref (buf);
+
+exit:
+  /* best cleaning up effort, eat possible error */
+  fclose (qtmux->fast_start_file);
+  qtmux->fast_start_file = NULL;
+
+  /* FIXME maybe delete temporary file, or let the system handle that ? */
+
+  return ret;
+
+  /* ERRORS */
+flush_failed:
+  {
+    GST_ELEMENT_ERROR (qtmux, RESOURCE, WRITE,
+        ("Failed to flush temporary file"), GST_ERROR_SYSTEM);
+    ret = GST_FLOW_ERROR;
+    goto exit;
+  }
+seek_failed:
+  {
+    GST_ELEMENT_ERROR (qtmux, RESOURCE, SEEK,
+        ("Failed to seek temporary file"), GST_ERROR_SYSTEM);
+    ret = GST_FLOW_ERROR;
+    goto exit;
+  }
+}
+
+/*
+ * Sends the initial mdat atom fields (size fields and fourcc type),
+ * the subsequent buffers are considered part of it's data.
+ * As we can't predict the amount of data that we are going to place in mdat
+ * we need to record the position of the size field in the stream so we can
+ * seek back to it later and update when the streams have finished.
+ */
+static GstFlowReturn
+gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size,
+    gboolean extended)
+{
+  Atom *node_header;
+  GstBuffer *buf;
+  guint8 *data = NULL;
+  guint64 offset = 0;
+
+  GST_DEBUG_OBJECT (qtmux, "Sending mdat's atom header, "
+      "size %" G_GUINT64_FORMAT, size);
+
+  node_header = g_malloc0 (sizeof (Atom));
+  node_header->type = FOURCC_mdat;
+  if (extended) {
+    /* use extended size */
+    node_header->size = 1;
+    node_header->extended_size = 0;
+    if (size)
+      node_header->extended_size = size + 16;
+  } else {
+    node_header->size = size + 8;
+  }
+
+  size = offset = 0;
+  if (atom_copy_data (node_header, &data, &size, &offset) == 0)
+    goto serialize_error;
+
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;
+  GST_BUFFER_SIZE (buf) = offset;
+
+  g_free (node_header);
+
+  GST_LOG_OBJECT (qtmux, "Pushing mdat start");
+  return gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
+
+  /* ERRORS */
+serialize_error:
+  {
+    GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+        ("Failed to serialize ftyp"));
+    return GST_FLOW_ERROR;
+  }
+}
+
+/*
+ * We get the position of the mdat size field, seek back to it
+ * and overwrite with the real value
+ */
+static GstFlowReturn
+gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
+    guint64 mdat_size, guint64 * offset)
+{
+  GstEvent *event;
+  GstBuffer *buf;
+  gboolean large_file;
+
+  large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT);
+
+  if (large_file)
+    mdat_pos += 8;
+
+  /* seek and rewrite the header */
+  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+      mdat_pos, GST_CLOCK_TIME_NONE, 0);
+  gst_pad_push_event (qtmux->srcpad, event);
+
+  if (large_file) {
+    buf = gst_buffer_new_and_alloc (sizeof (guint64));
+    GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size + 16);
+  } else {
+    guint8 *data;
+
+    buf = gst_buffer_new_and_alloc (16);
+    data = GST_BUFFER_DATA (buf);
+    GST_WRITE_UINT32_BE (data, 8);
+    GST_WRITE_UINT32_LE (data + 4, FOURCC_free);
+    GST_WRITE_UINT32_BE (data + 8, mdat_size + 8);
+    GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat);
+  }
+
+  return gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
+}
+
+static GstFlowReturn
+gst_qt_mux_send_ftyp (GstQTMux * qtmux, guint64 * off)
+{
+  GstBuffer *buf;
+  guint64 size = 0, offset = 0;
+  guint8 *data = NULL;
+
+  GST_DEBUG_OBJECT (qtmux, "Sending ftyp atom");
+
+  if (!atom_ftyp_copy_data (qtmux->ftyp, &data, &size, &offset))
+    goto serialize_error;
+
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;
+  GST_BUFFER_SIZE (buf) = offset;
+
+  GST_LOG_OBJECT (qtmux, "Pushing ftyp");
+  return gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
+
+  /* ERRORS */
+serialize_error:
+  {
+    GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+        ("Failed to serialize ftyp"));
+    return GST_FLOW_ERROR;
+  }
+}
+
+static GstFlowReturn
+gst_qt_mux_prepare_and_send_ftyp (GstQTMux * qtmux)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
+  guint32 major, version;
+  GList *comp;
+  GstBuffer *prefix;
+
+  GST_DEBUG_OBJECT (qtmux, "Preparing to send ftyp atom");
+
+  /* init and send context and ftyp based on current property state */
+  if (qtmux->ftyp)
+    atom_ftyp_free (qtmux->ftyp);
+  gst_qt_mux_map_format_to_header (qtmux_klass->format, &prefix, &major,
+      &version, &comp, qtmux->moov, qtmux->longest_chunk,
+      qtmux->fast_start_file != NULL);
+  qtmux->ftyp = atom_ftyp_new (qtmux->context, major, version, comp);
+  if (comp)
+    g_list_free (comp);
+  if (prefix) {
+    ret = gst_qt_mux_send_buffer (qtmux, prefix, &qtmux->header_size, FALSE);
+    if (ret != GST_FLOW_OK)
+      return ret;
+  }
+  return gst_qt_mux_send_ftyp (qtmux, &qtmux->header_size);
+}
+
+static GstFlowReturn
+gst_qt_mux_start_file (GstQTMux * qtmux)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  GST_DEBUG_OBJECT (qtmux, "starting file");
+
+  /* let downstream know we think in BYTES and expect to do seeking later on */
+  gst_pad_push_event (qtmux->srcpad,
+      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
+
+  /* 
+   * send mdat header if already needed, and mark position for later update.
+   * We don't send ftyp now if we are on fast start mode, because we can
+   * better fine tune using the information we gather to create the whole moov
+   * atom.
+   */
+  if (qtmux->fast_start) {
+    GST_OBJECT_LOCK (qtmux);
+    qtmux->fast_start_file = g_fopen (qtmux->fast_start_file_path, "wb+");
+    if (!qtmux->fast_start_file)
+      goto open_failed;
+    GST_OBJECT_UNLOCK (qtmux);
+
+    /* send a dummy buffer for preroll */
+    ret = gst_qt_mux_send_buffer (qtmux, gst_buffer_new (), NULL, FALSE);
+    if (ret != GST_FLOW_OK)
+      goto exit;
+
+  } else {
+    ret = gst_qt_mux_prepare_and_send_ftyp (qtmux);
+    if (ret != GST_FLOW_OK) {
+      goto exit;
+    }
+
+    /* extended to ensure some spare space */
+    qtmux->mdat_pos = qtmux->header_size;
+    ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
+  }
+
+exit:
+  return ret;
+
+  /* ERRORS */
+open_failed:
+  {
+    GST_ELEMENT_ERROR (qtmux, RESOURCE, OPEN_READ_WRITE,
+        (("Could not open temporary file \"%s\""), qtmux->fast_start_file_path),
+        GST_ERROR_SYSTEM);
+    GST_OBJECT_UNLOCK (qtmux);
+    return GST_FLOW_ERROR;
+  }
+}
+
+static GstFlowReturn
+gst_qt_mux_stop_file (GstQTMux * qtmux)
+{
+  gboolean ret = GST_FLOW_OK;
+  GstBuffer *buffer = NULL;
+  guint64 offset = 0, size = 0;
+  guint8 *data;
+  GSList *walk;
+  gboolean large_file;
+  guint32 timescale;
+
+  GST_DEBUG_OBJECT (qtmux, "Updating remaining values and sending last data");
+
+  /* pushing last buffers for each pad */
+  for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
+    GstCollectData *cdata = (GstCollectData *) walk->data;
+    GstQTPad *qtpad = (GstQTPad *) cdata;
+
+    /* send last buffer */
+    GST_DEBUG_OBJECT (qtmux, "Sending the last buffer for pad %s",
+        GST_PAD_NAME (qtpad->collect.pad));
+    ret = gst_qt_mux_add_buffer (qtmux, qtpad, NULL);
+    if (ret != GST_FLOW_OK)
+      GST_WARNING_OBJECT (qtmux, "Failed to send last buffer for %s, "
+          "flow return: %s", GST_PAD_NAME (qtpad->collect.pad),
+          gst_flow_get_name (ret));
+  }
+
+  GST_OBJECT_LOCK (qtmux);
+  timescale = qtmux->timescale;
+  large_file = qtmux->large_file;
+  GST_OBJECT_UNLOCK (qtmux);
+
+  /* inform lower layers of our property wishes, and determine duration.
+   * Let moov take care of this using its list of traks;
+   * so that released pads are also included */
+  GST_DEBUG_OBJECT (qtmux, "Large file support: %d", large_file);
+  GST_DEBUG_OBJECT (qtmux, "Updating timescale to %" G_GUINT32_FORMAT,
+      timescale);
+  atom_moov_update_timescale (qtmux->moov, timescale);
+  atom_moov_set_64bits (qtmux->moov, large_file);
+  atom_moov_update_duration (qtmux->moov);
+
+  /* tags into file metadata */
+  gst_qt_mux_setup_metadata (qtmux);
+
+  large_file = (qtmux->mdat_size > MDAT_LARGE_FILE_LIMIT);
+  /* if faststart, update the offset of the atoms in the movie with the offset
+   * that the movie headers before mdat will cause.
+   * Also, send the ftyp */
+  if (qtmux->fast_start_file) {
+    GstFlowReturn flow_ret;
+    offset = size = 0;
+
+    flow_ret = gst_qt_mux_prepare_and_send_ftyp (qtmux);
+    if (flow_ret != GST_FLOW_OK) {
+      goto ftyp_error;
+    }
+    /* copy into NULL to obtain size */
+    if (!atom_moov_copy_data (qtmux->moov, NULL, &size, &offset))
+      goto serialize_error;
+    GST_DEBUG_OBJECT (qtmux, "calculated moov atom size %" G_GUINT64_FORMAT,
+        size);
+    offset += qtmux->header_size + (large_file ? 16 : 8);
+  } else
+    offset = qtmux->header_size;
+  atom_moov_chunks_add_offset (qtmux->moov, offset);
+
+  /* serialize moov */
+  offset = size = 0;
+  data = NULL;
+  GST_LOG_OBJECT (qtmux, "Copying movie header into buffer");
+  ret = atom_moov_copy_data (qtmux->moov, &data, &size, &offset);
+  if (!ret)
+    goto serialize_error;
+
+  buffer = gst_buffer_new ();
+  GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer) = data;
+  GST_BUFFER_SIZE (buffer) = offset;
+  /* note: as of this point, we no longer care about tracking written data size,
+   * since there is no more use for it anyway */
+  GST_DEBUG_OBJECT (qtmux, "Pushing movie atoms");
+  gst_qt_mux_send_buffer (qtmux, buffer, NULL, FALSE);
+
+  /* if needed, send mdat atom and move buffered data into it */
+  if (qtmux->fast_start_file) {
+    /* mdat size = accumulated (buffered data) + mdat atom header */
+    ret = gst_qt_mux_send_mdat_header (qtmux, NULL, qtmux->mdat_size,
+        large_file);
+    if (ret != GST_FLOW_OK)
+      return ret;
+    ret = gst_qt_mux_send_buffered_data (qtmux, NULL);
+    if (ret != GST_FLOW_OK)
+      return ret;
+  } else {
+    /* mdata needs update iff not using faststart */
+    GST_DEBUG_OBJECT (qtmux, "updating mdata size");
+    ret = gst_qt_mux_update_mdat_size (qtmux, qtmux->mdat_pos,
+        qtmux->mdat_size, NULL);
+    /* note; no seeking back to the end of file is done,
+     * since we longer write anything anyway */
+  }
+
+  return ret;
+
+  /* ERRORS */
+serialize_error:
+  {
+    gst_buffer_unref (buffer);
+    GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+        ("Failed to serialize moov"));
+    return GST_FLOW_ERROR;
+  }
+ftyp_error:
+  {
+    GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL), ("Failed to send ftyp"));
+    return GST_FLOW_ERROR;
+  }
+}
+
+/*
+ * Here we push the buffer and update the tables in the track atoms
+ */
+static GstFlowReturn
+gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
+{
+  GstBuffer *last_buf = NULL;
+  GstClockTime duration;
+  guint nsamples, sample_size;
+  guint64 scaled_duration, chunk_offset;
+  gint64 last_dts;
+  gint64 pts_offset = 0;
+  gboolean sync = FALSE, do_pts = FALSE;
+
+  if (!pad->fourcc)
+    goto not_negotiated;
+
+  last_buf = pad->last_buf;
+  if (last_buf == NULL) {
+#ifndef GST_DISABLE_GST_DEBUG
+    if (buf == NULL) {
+      GST_DEBUG_OBJECT (qtmux, "Pad %s has no previous buffer stored and "
+          "received NULL buffer, doing nothing",
+          GST_PAD_NAME (pad->collect.pad));
+    } else {
+      GST_LOG_OBJECT (qtmux,
+          "Pad %s has no previous buffer stored, storing now",
+          GST_PAD_NAME (pad->collect.pad));
+    }
+#endif
+    pad->last_buf = buf;
+    return GST_FLOW_OK;
+  } else
+    gst_buffer_ref (last_buf);
+
+  /* fall back to duration if:
+   * - last bufer
+   * - this format has out of order buffers (e.g. MPEG-4),
+   * - lack of valid time forces fall back */
+  if (buf == NULL || pad->is_out_of_order ||
+      !GST_BUFFER_TIMESTAMP_IS_VALID (last_buf) ||
+      !GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+    if (!GST_BUFFER_DURATION_IS_VALID (last_buf)) {
+      /* be forgiving for some possibly last upstream flushed buffer */
+      if (buf)
+        goto no_time;
+      GST_WARNING_OBJECT (qtmux, "no duration for last buffer");
+      /* iso spec recommends some small value, try 0 */
+      duration = 0;
+    } else {
+      duration = GST_BUFFER_DURATION (last_buf);
+    }
+  } else {
+    duration = GST_BUFFER_TIMESTAMP (buf) - GST_BUFFER_TIMESTAMP (last_buf);
+  }
+
+  gst_buffer_replace (&pad->last_buf, buf);
+
+  last_dts = gst_util_uint64_scale (pad->last_dts,
+      atom_trak_get_timescale (pad->trak), GST_SECOND);
+
+  /* raw audio has many samples per buffer (= chunk) */
+  if (pad->sample_size) {
+    sample_size = pad->sample_size;
+    if (GST_BUFFER_SIZE (last_buf) % sample_size != 0)
+      goto fragmented_sample;
+    /* note: qt raw audio storage warps it implicitly into a timewise
+     * perfect stream, discarding buffer times */
+    nsamples = GST_BUFFER_SIZE (last_buf) / sample_size;
+    duration = GST_BUFFER_DURATION (last_buf) / nsamples;
+    /* timescale = samplerate */
+    scaled_duration = 1;
+    pad->last_dts += duration * nsamples;
+  } else {
+    nsamples = 1;
+    sample_size = GST_BUFFER_SIZE (last_buf);
+    if (pad->have_dts) {
+      gint64 scaled_dts;
+      pad->last_dts = GST_BUFFER_OFFSET_END (last_buf);
+      if ((gint64) (pad->last_dts) < 0) {
+        scaled_dts = -gst_util_uint64_scale (-pad->last_dts,
+            atom_trak_get_timescale (pad->trak), GST_SECOND);
+      } else {
+        scaled_dts = gst_util_uint64_scale (pad->last_dts,
+            atom_trak_get_timescale (pad->trak), GST_SECOND);
+      }
+      scaled_duration = scaled_dts - last_dts;
+      last_dts = scaled_dts;
+    } else {
+      /* first convert intended timestamp (in GstClockTime resolution) to
+       * trak timescale, then derive delta;
+       * this ensures sums of (scale)delta add up to converted timestamp,
+       * which only deviates at most 1/scale from timestamp itself */
+      scaled_duration = gst_util_uint64_scale (pad->last_dts + duration,
+          atom_trak_get_timescale (pad->trak), GST_SECOND) - last_dts;
+      pad->last_dts += duration;
+    }
+  }
+  chunk_offset = qtmux->mdat_size;
+
+  GST_LOG_OBJECT (qtmux,
+      "Pad (%s) dts updated to %" GST_TIME_FORMAT,
+      GST_PAD_NAME (pad->collect.pad), GST_TIME_ARGS (pad->last_dts));
+  GST_LOG_OBJECT (qtmux,
+      "Adding %d samples to track, duration: %" G_GUINT64_FORMAT
+      " size: %" G_GUINT32_FORMAT " chunk offset: %" G_GUINT64_FORMAT,
+      nsamples, scaled_duration, sample_size, chunk_offset);
+
+  /* might be a sync sample */
+  if (pad->sync &&
+      !GST_BUFFER_FLAG_IS_SET (last_buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
+    GST_LOG_OBJECT (qtmux, "Adding new sync sample entry for track of pad %s",
+        GST_PAD_NAME (pad->collect.pad));
+    sync = TRUE;
+  }
+
+  /* optionally calculate ctts entry values
+   * (if composition-time expected different from decoding-time) */
+  /* really not recommended:
+   * - decoder typically takes care of dts/pts issues
+   * - in case of out-of-order, dts may only be determined as above
+   *   (e.g. sum of duration), which may be totally different from
+   *   buffer timestamps in case of multiple segment, non-perfect streams
+   *  (and just perhaps maybe with some luck segment_to_running_time
+   *   or segment_to_media_time might get near to it) */
+  if ((pad->have_dts || qtmux->guess_pts) && pad->is_out_of_order) {
+    guint64 pts;
+
+    pts = gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (last_buf),
+        atom_trak_get_timescale (pad->trak), GST_SECOND);
+    pts_offset = (gint64) (pts - last_dts);
+    do_pts = TRUE;
+    GST_LOG_OBJECT (qtmux, "Adding ctts entry for pad %s: %" G_GINT64_FORMAT,
+        GST_PAD_NAME (pad->collect.pad), pts_offset);
+  }
+
+  /*
+   * Each buffer starts a new chunk, so we can assume the buffer
+   * duration is the chunk duration
+   */
+  if (GST_CLOCK_TIME_IS_VALID (duration) && (duration > qtmux->longest_chunk ||
+          !GST_CLOCK_TIME_IS_VALID (qtmux->longest_chunk))) {
+    GST_DEBUG_OBJECT (qtmux, "New longest chunk found: %" GST_TIME_FORMAT
+        ", pad %s", GST_TIME_ARGS (duration), GST_PAD_NAME (pad->collect.pad));
+    qtmux->longest_chunk = duration;
+  }
+
+  /* now we go and register this buffer/sample all over */
+  /* note that a new chunk is started each time (not fancy but works) */
+  atom_trak_add_samples (pad->trak, nsamples, scaled_duration, sample_size,
+      chunk_offset, sync, do_pts, pts_offset);
+
+  if (buf)
+    gst_buffer_unref (buf);
+
+  return gst_qt_mux_send_buffer (qtmux, last_buf, &qtmux->mdat_size, TRUE);
+
+  /* ERRORS */
+bail:
+  {
+    if (buf)
+      gst_buffer_unref (buf);
+    gst_buffer_unref (last_buf);
+    return GST_FLOW_ERROR;
+  }
+no_time:
+  {
+    GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+        ("Received buffer without timestamp/duration."));
+    goto bail;
+  }
+fragmented_sample:
+  {
+    GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
+        ("Audio buffer contains fragmented sample."));
+    goto bail;
+  }
+not_negotiated:
+  {
+    GST_ELEMENT_ERROR (qtmux, CORE, NEGOTIATION, (NULL),
+        ("format wasn't negotiated before buffer flow on pad %s",
+            GST_PAD_NAME (pad->collect.pad)));
+    if (buf)
+      gst_buffer_unref (buf);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+}
+
+static GstFlowReturn
+gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstQTMux *qtmux = GST_QT_MUX_CAST (user_data);
+  GSList *walk;
+  GstQTPad *best_pad = NULL;
+  GstClockTime time, best_time = GST_CLOCK_TIME_NONE;
+  GstBuffer *buf;
+
+  if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_STARTED)) {
+    if ((ret = gst_qt_mux_start_file (qtmux)) != GST_FLOW_OK)
+      return ret;
+    else
+      qtmux->state = GST_QT_MUX_STATE_DATA;
+  }
+
+  if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_EOS))
+    return GST_FLOW_UNEXPECTED;
+
+  /* select the best buffer */
+  walk = qtmux->collect->data;
+  while (walk) {
+    GstQTPad *pad;
+    GstCollectData *data;
+
+    data = (GstCollectData *) walk->data;
+    pad = (GstQTPad *) data;
+
+    walk = g_slist_next (walk);
+
+    buf = gst_collect_pads_peek (pads, data);
+    if (buf == NULL) {
+      GST_LOG_OBJECT (qtmux, "Pad %s has no buffers",
+          GST_PAD_NAME (pad->collect.pad));
+      continue;
+    }
+    time = GST_BUFFER_TIMESTAMP (buf);
+    gst_buffer_unref (buf);
+
+    if (best_pad == NULL || !GST_CLOCK_TIME_IS_VALID (time) ||
+        (GST_CLOCK_TIME_IS_VALID (best_time) && time < best_time)) {
+      best_pad = pad;
+      best_time = time;
+    }
+  }
+
+  if (best_pad != NULL) {
+    GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
+        GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
+    buf = gst_collect_pads_pop (pads, &best_pad->collect);
+    ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
+  } else {
+    ret = gst_qt_mux_stop_file (qtmux);
+    if (ret == GST_FLOW_OK) {
+      gst_pad_push_event (qtmux->srcpad, gst_event_new_eos ());
+      ret = GST_FLOW_UNEXPECTED;
+    }
+    qtmux->state = GST_QT_MUX_STATE_EOS;
+  }
+
+  return ret;
+}
+
+static gboolean
+gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
+{
+  GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
+  GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
+  GstQTPad *qtpad = NULL;
+  GstStructure *structure;
+  const gchar *mimetype;
+  gint rate, channels;
+  const GValue *value = NULL;
+  const GstBuffer *codec_data = NULL;
+  GstQTMuxFormat format;
+  AudioSampleEntry entry = { 0, };
+  AtomInfo *ext_atom = NULL;
+  gint constant_size = 0;
+
+  /* find stream data */
+  qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
+  g_assert (qtpad);
+
+  /* does not go well to renegotiate stream mid-way */
+  if (qtpad->fourcc)
+    goto refuse_renegotiation;
+
+  GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
+      GST_DEBUG_PAD_NAME (pad), caps);
+
+  format = qtmux_klass->format;
+  structure = gst_caps_get_structure (caps, 0);
+  mimetype = gst_structure_get_name (structure);
+
+  /* common info */
+  if (!gst_structure_get_int (structure, "channels", &channels) ||
+      !gst_structure_get_int (structure, "rate", &rate)) {
+    goto refuse_caps;
+  }
+
+  /* optional */
+  value = gst_structure_get_value (structure, "codec_data");
+  if (value != NULL)
+    codec_data = gst_value_get_buffer (value);
+
+  qtpad->is_out_of_order = FALSE;
+  qtpad->have_dts = FALSE;
+
+  /* set common properties */
+  entry.sample_rate = rate;
+  entry.channels = channels;
+  /* default */
+  entry.sample_size = 16;
+  /* this is the typical compressed case */
+  if (format == GST_QT_MUX_FORMAT_QT) {
+    entry.version = 1;
+    entry.compression_id = -2;
+  }
+
+  /* now map onto a fourcc, and some extra properties */
+  if (strcmp (mimetype, "audio/mpeg") == 0) {
+    gint mpegversion = 0;
+    gint layer = -1;
+
+    gst_structure_get_int (structure, "mpegversion", &mpegversion);
+    switch (mpegversion) {
+      case 1:
+        gst_structure_get_int (structure, "layer", &layer);
+        switch (layer) {
+          case 3:
+            /* mp3 */
+            /* note: QuickTime player does not like mp3 either way in iso/mp4 */
+            if (format == GST_QT_MUX_FORMAT_QT)
+              entry.fourcc = FOURCC__mp3;
+            else {
+              entry.fourcc = FOURCC_mp4a;
+              ext_atom =
+                  build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG1_P3,
+                  ESDS_STREAM_TYPE_AUDIO, codec_data);
+            }
+            entry.samples_per_packet = 1152;
+            entry.bytes_per_sample = 2;
+            break;
+        }
+        break;
+      case 4:
+        /* AAC */
+        entry.fourcc = FOURCC_mp4a;
+        if (!codec_data || GST_BUFFER_SIZE (codec_data) < 2)
+          GST_WARNING_OBJECT (qtmux, "no (valid) codec_data for AAC audio");
+        else {
+          guint8 profile = GST_READ_UINT8 (GST_BUFFER_DATA (codec_data));
+
+          /* warn if not Low Complexity profile */
+          profile >>= 3;
+          if (profile != 2)
+            GST_WARNING_OBJECT (qtmux,
+                "non-LC AAC may not run well on (Apple) QuickTime/iTunes");
+        }
+        if (format == GST_QT_MUX_FORMAT_QT)
+          ext_atom = build_mov_aac_extension (qtpad->trak, codec_data);
+        else
+          ext_atom =
+              build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG4_P3,
+              ESDS_STREAM_TYPE_AUDIO, codec_data);
+        break;
+      default:
+        break;
+    }
+  } else if (strcmp (mimetype, "audio/AMR") == 0) {
+    entry.fourcc = FOURCC_samr;
+    entry.sample_size = 16;
+    entry.samples_per_packet = 160;
+    entry.bytes_per_sample = 2;
+    ext_atom = build_amr_extension ();
+  } else if (strcmp (mimetype, "audio/AMR-WB") == 0) {
+    entry.fourcc = FOURCC_sawb;
+    entry.sample_size = 16;
+    entry.samples_per_packet = 320;
+    entry.bytes_per_sample = 2;
+    ext_atom = build_amr_extension ();
+  } else if (strcmp (mimetype, "audio/x-raw-int") == 0) {
+    gint width;
+    gint depth;
+    gint endianness;
+    gboolean sign;
+
+    if (!gst_structure_get_int (structure, "width", &width) ||
+        !gst_structure_get_int (structure, "depth", &depth) ||
+        !gst_structure_get_boolean (structure, "signed", &sign)) {
+      GST_DEBUG_OBJECT (qtmux, "broken caps, width/depth/signed field missing");
+      goto refuse_caps;
+    }
+
+    if (depth <= 8) {
+      endianness = G_BYTE_ORDER;
+    } else if (!gst_structure_get_boolean (structure,
+            "endianness", &endianness)) {
+      GST_DEBUG_OBJECT (qtmux, "broken caps, endianness field missing");
+      goto refuse_caps;
+    }
+
+    /* spec has no place for a distinction in these */
+    if (width != depth) {
+      GST_DEBUG_OBJECT (qtmux, "width must be same as depth!");
+      goto refuse_caps;
+    }
+
+    if (sign) {
+      if (endianness == G_LITTLE_ENDIAN)
+        entry.fourcc = FOURCC_sowt;
+      else if (endianness == G_BIG_ENDIAN)
+        entry.fourcc = FOURCC_twos;
+      /* maximum backward compatibility; only new version for > 16 bit */
+      if (depth <= 16)
+        entry.version = 0;
+      /* not compressed in any case */
+      entry.compression_id = 0;
+      /* QT spec says: max at 16 bit even if sample size were actually larger,
+       * however, most players (e.g. QuickTime!) seem to disagree, so ... */
+      entry.sample_size = depth;
+      entry.bytes_per_sample = depth / 8;
+      entry.samples_per_packet = 1;
+      entry.bytes_per_packet = depth / 8;
+      entry.bytes_per_frame = entry.bytes_per_packet * channels;
+    } else {
+      if (width == 8 && depth == 8) {
+        /* fall back to old 8-bit version */
+        entry.fourcc = FOURCC_raw_;
+        entry.version = 0;
+        entry.compression_id = 0;
+        entry.sample_size = 8;
+      } else {
+        GST_DEBUG_OBJECT (qtmux, "non 8-bit PCM must be signed");
+        goto refuse_caps;
+      }
+    }
+    constant_size = (depth / 8) * channels;
+  } else if (strcmp (mimetype, "audio/x-alaw") == 0) {
+    entry.fourcc = FOURCC_alaw;
+    entry.samples_per_packet = 1023;
+    entry.bytes_per_sample = 2;
+  } else if (strcmp (mimetype, "audio/x-mulaw") == 0) {
+    entry.fourcc = FOURCC_ulaw;
+    entry.samples_per_packet = 1023;
+    entry.bytes_per_sample = 2;
+  }
+
+  if (!entry.fourcc)
+    goto refuse_caps;
+
+  /* ok, set the pad info accordingly */
+  qtpad->fourcc = entry.fourcc;
+  qtpad->sample_size = constant_size;
+  atom_trak_set_audio_type (qtpad->trak, qtmux->context, &entry,
+      entry.sample_rate, ext_atom, constant_size);
+
+  gst_object_unref (qtmux);
+  return TRUE;
+
+  /* ERRORS */
+refuse_caps:
+  {
+    GST_WARNING_OBJECT (qtmux, "pad %s refused caps %" GST_PTR_FORMAT,
+        GST_PAD_NAME (pad), caps);
+    gst_object_unref (qtmux);
+    return FALSE;
+  }
+refuse_renegotiation:
+  {
+    GST_WARNING_OBJECT (qtmux,
+        "pad %s refused renegotiation to %" GST_PTR_FORMAT,
+        GST_PAD_NAME (pad), caps);
+    gst_object_unref (qtmux);
+    return FALSE;
+  }
+}
+
+/* scale rate up or down by factor of 10 to fit into [1000,10000] interval */
+static guint32
+adjust_rate (guint64 rate)
+{
+  while (rate >= 10000)
+    rate /= 10;
+
+  while (rate < 1000)
+    rate *= 10;
+
+  return (guint32) rate;
+}
+
+static gboolean
+gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
+{
+  GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
+  GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
+  GstQTPad *qtpad = NULL;
+  GstStructure *structure;
+  const gchar *mimetype;
+  gint width, height, depth = -1;
+  gint framerate_num, framerate_den;
+  guint32 rate;
+  const GValue *value = NULL;
+  const GstBuffer *codec_data = NULL;
+  VisualSampleEntry entry = { 0, };
+  GstQTMuxFormat format;
+  AtomInfo *ext_atom = NULL;
+  gboolean sync = FALSE;
+  int par_num, par_den;
+
+  /* find stream data */
+  qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
+  g_assert (qtpad);
+
+  /* does not go well to renegotiate stream mid-way */
+  if (qtpad->fourcc)
+    goto refuse_renegotiation;
+
+  GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
+      GST_DEBUG_PAD_NAME (pad), caps);
+
+  format = qtmux_klass->format;
+  structure = gst_caps_get_structure (caps, 0);
+  mimetype = gst_structure_get_name (structure);
+
+  /* required parts */
+  if (!gst_structure_get_int (structure, "width", &width) ||
+      !gst_structure_get_int (structure, "height", &height))
+    goto refuse_caps;
+
+  /* optional */
+  depth = -1;
+  /* works as a default timebase */
+  framerate_num = 10000;
+  framerate_den = 1;
+  gst_structure_get_fraction (structure, "framerate", &framerate_num,
+      &framerate_den);
+  gst_structure_get_int (structure, "depth", &depth);
+  value = gst_structure_get_value (structure, "codec_data");
+  if (value != NULL)
+    codec_data = gst_value_get_buffer (value);
+
+  par_num = 1;
+  par_den = 1;
+  gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_num,
+      &par_den);
+
+  qtpad->is_out_of_order = FALSE;
+
+  /* bring frame numerator into a range that ensures both reasonable resolution
+   * as well as a fair duration */
+  rate = adjust_rate (framerate_num);
+  GST_DEBUG_OBJECT (qtmux, "Rate of video track selected: %" G_GUINT32_FORMAT,
+      rate);
+
+  /* set common properties */
+  entry.width = width;
+  entry.height = height;
+  entry.par_n = par_num;
+  entry.par_d = par_den;
+  /* should be OK according to qt and iso spec, override if really needed */
+  entry.color_table_id = -1;
+  entry.frame_count = 1;
+  entry.depth = 24;
+
+  /* sync entries by default */
+  sync = TRUE;
+
+  /* now map onto a fourcc, and some extra properties */
+  if (strcmp (mimetype, "video/x-raw-rgb") == 0) {
+    gint bpp;
+
+    entry.fourcc = FOURCC_raw_;
+    gst_structure_get_int (structure, "bpp", &bpp);
+    entry.depth = bpp;
+    sync = FALSE;
+  } else if (strcmp (mimetype, "video/x-raw-yuv") == 0) {
+    guint32 format = 0;
+
+    sync = FALSE;
+    gst_structure_get_fourcc (structure, "format", &format);
+    switch (format) {
+      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+        if (depth == -1)
+          depth = 24;
+        entry.fourcc = FOURCC_2vuy;
+        entry.depth = depth;
+        break;
+    }
+  } else if (strcmp (mimetype, "video/x-h263") == 0) {
+    if (format == GST_QT_MUX_FORMAT_QT)
+      entry.fourcc = FOURCC_h263;
+    else
+      entry.fourcc = FOURCC_s263;
+    ext_atom = build_h263_extension ();
+  } else if (strcmp (mimetype, "video/x-divx") == 0 ||
+      strcmp (mimetype, "video/mpeg") == 0) {
+    gint version = 0;
+
+    if (strcmp (mimetype, "video/x-divx") == 0) {
+      gst_structure_get_int (structure, "divxversion", &version);
+      version = version == 5 ? 1 : 0;
+    } else {
+      gst_structure_get_int (structure, "mpegversion", &version);
+      version = version == 4 ? 1 : 0;
+    }
+    if (version) {
+      entry.fourcc = FOURCC_mp4v;
+      ext_atom =
+          build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG4_P2,
+          ESDS_STREAM_TYPE_VISUAL, codec_data);
+      if (!codec_data)
+        GST_WARNING_OBJECT (qtmux, "no codec_data for MPEG4 video; "
+            "output might not play in Apple QuickTime (try global-headers?)");
+    }
+  } else if (strcmp (mimetype, "video/x-h264") == 0) {
+    entry.fourcc = FOURCC_avc1;
+    qtpad->is_out_of_order = TRUE;
+    if (!codec_data)
+      GST_WARNING_OBJECT (qtmux, "no codec_data in h264 caps");
+    ext_atom = build_codec_data_extension (FOURCC_avcC, codec_data);
+  } else if (strcmp (mimetype, "video/x-dv") == 0) {
+    gint version = 0;
+    gboolean pal = TRUE;
+
+    sync = FALSE;
+    if (framerate_num != 25 || framerate_den != 1)
+      pal = FALSE;
+    gst_structure_get_int (structure, "dvversion", &version);
+    /* fall back to typical one */
+    if (!version)
+      version = 25;
+    switch (version) {
+      case 25:
+        if (pal)
+          entry.fourcc = GST_MAKE_FOURCC ('d', 'v', 'c', 'p');
+        else
+          entry.fourcc = GST_MAKE_FOURCC ('d', 'v', 'c', ' ');
+        break;
+      case 50:
+        if (pal)
+          entry.fourcc = GST_MAKE_FOURCC ('d', 'v', '5', 'p');
+        else
+          entry.fourcc = GST_MAKE_FOURCC ('d', 'v', '5', 'n');
+        break;
+      default:
+        GST_WARNING_OBJECT (qtmux, "unrecognized dv version");
+        break;
+    }
+  } else if (strcmp (mimetype, "image/jpeg") == 0) {
+    entry.fourcc = FOURCC_jpeg;
+    sync = FALSE;
+  } else if (strcmp (mimetype, "image/x-j2c") == 0) {
+    guint32 fourcc;
+
+    entry.fourcc = FOURCC_mjp2;
+    sync = FALSE;
+    if (!gst_structure_get_fourcc (structure, "fourcc", &fourcc) ||
+        !(ext_atom =
+            build_jp2h_extension (qtpad->trak, width, height, fourcc))) {
+      GST_DEBUG_OBJECT (qtmux, "missing or invalid fourcc in jp2 caps");
+      goto refuse_caps;
+    }
+  } else if (strcmp (mimetype, "video/x-qt-part") == 0) {
+    guint32 fourcc;
+
+    gst_structure_get_fourcc (structure, "format", &fourcc);
+    entry.fourcc = fourcc;
+    qtpad->is_out_of_order = TRUE;
+    qtpad->have_dts = TRUE;
+  } else if (strcmp (mimetype, "video/x-mp4-part") == 0) {
+    guint32 fourcc;
+
+    gst_structure_get_fourcc (structure, "format", &fourcc);
+    entry.fourcc = fourcc;
+    qtpad->is_out_of_order = TRUE;
+    qtpad->have_dts = TRUE;
+  }
+
+  if (!entry.fourcc)
+    goto refuse_caps;
+
+  /* ok, set the pad info accordingly */
+  qtpad->fourcc = entry.fourcc;
+  qtpad->sync = sync;
+  atom_trak_set_video_type (qtpad->trak, qtmux->context, &entry, rate,
+      ext_atom);
+
+  gst_object_unref (qtmux);
+  return TRUE;
+
+  /* ERRORS */
+refuse_caps:
+  {
+    GST_WARNING_OBJECT (qtmux, "pad %s refused caps %" GST_PTR_FORMAT,
+        GST_PAD_NAME (pad), caps);
+    gst_object_unref (qtmux);
+    return FALSE;
+  }
+refuse_renegotiation:
+  {
+    GST_WARNING_OBJECT (qtmux,
+        "pad %s refused renegotiation to %" GST_PTR_FORMAT " from %"
+        GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+    gst_object_unref (qtmux);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_qt_mux_sink_event (GstPad * pad, GstEvent * event)
+{
+  gboolean ret;
+  GstQTMux *qtmux;
+
+  qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_TAG:{
+      GstTagList *list;
+      GstTagSetter *setter = GST_TAG_SETTER (qtmux);
+      const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
+
+      GST_DEBUG_OBJECT (qtmux, "received tag event");
+      gst_event_parse_tag (event, &list);
+      gst_tag_setter_merge_tags (setter, list, mode);
+      break;
+    }
+    default:
+      break;
+  }
+
+  ret = qtmux->collect_event (pad, event);
+  gst_object_unref (qtmux);
+
+  return ret;
+}
+
+static void
+gst_qt_mux_release_pad (GstElement * element, GstPad * pad)
+{
+  GstQTMux *mux = GST_QT_MUX_CAST (element);
+
+  /* let GstCollectPads complain if it is some unknown pad */
+  if (gst_collect_pads_remove_pad (mux->collect, pad))
+    gst_element_remove_pad (element, pad);
+}
+
+static GstPad *
+gst_qt_mux_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * req_name)
+{
+  GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
+  GstQTMux *qtmux = GST_QT_MUX_CAST (element);
+  GstQTPad *collect_pad;
+  GstPad *newpad;
+  gboolean audio;
+  gchar *name;
+
+  if (templ->direction != GST_PAD_SINK)
+    goto wrong_direction;
+
+//  if (qtmux->state != GST_QT_MUX_STATE_NONE)
+//    goto too_late;
+
+  if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
+    audio = TRUE;
+    name = g_strdup_printf ("audio_%02d", qtmux->audio_pads++);
+  } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
+    audio = FALSE;
+    name = g_strdup_printf ("video_%02d", qtmux->video_pads++);
+  } else
+    goto wrong_template;
+
+  GST_DEBUG_OBJECT (qtmux, "Requested pad: %s", name);
+
+  /* create pad and add to collections */
+  newpad = gst_pad_new_from_template (templ, name);
+  g_free (name);
+  collect_pad = (GstQTPad *)
+      gst_collect_pads_add_pad_full (qtmux->collect, newpad, sizeof (GstQTPad),
+      (GstCollectDataDestroyNotify) (gst_qt_mux_pad_reset));
+  /* set up pad */
+  gst_qt_mux_pad_reset (collect_pad);
+  collect_pad->trak = atom_trak_new (qtmux->context);
+  atom_moov_add_trak (qtmux->moov, collect_pad->trak);
+
+  /* set up pad functions */
+  if (audio)
+    gst_pad_set_setcaps_function (newpad,
+        GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps));
+  else
+    gst_pad_set_setcaps_function (newpad,
+        GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps));
+
+  /* FIXME: hacked way to override/extend the event function of
+   * GstCollectPads; because it sets its own event function giving the
+   * element no access to events.
+   */
+  qtmux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
+  gst_pad_set_event_function (newpad,
+      GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event));
+
+  gst_pad_set_active (newpad, TRUE);
+  gst_element_add_pad (element, newpad);
+
+  return newpad;
+
+  /* ERRORS */
+wrong_direction:
+  {
+    GST_WARNING_OBJECT (qtmux, "Request pad that is not a SINK pad.");
+    return NULL;
+  }
+too_late:
+  {
+    GST_WARNING_OBJECT (qtmux, "Not providing request pad after stream start.");
+    return NULL;
+  }
+wrong_template:
+  {
+    GST_WARNING_OBJECT (qtmux, "This is not our template!");
+    return NULL;
+  }
+}
+
+static void
+gst_qt_mux_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstQTMux *qtmux = GST_QT_MUX_CAST (object);
+
+  GST_OBJECT_LOCK (qtmux);
+  switch (prop_id) {
+    case PROP_LARGE_FILE:
+      g_value_set_boolean (value, qtmux->large_file);
+      break;
+    case PROP_MOVIE_TIMESCALE:
+      g_value_set_uint (value, qtmux->timescale);
+      break;
+    case PROP_DO_CTTS:
+      g_value_set_boolean (value, qtmux->guess_pts);
+      break;
+    case PROP_FAST_START:
+      g_value_set_boolean (value, qtmux->fast_start);
+      break;
+    case PROP_FAST_START_TEMP_FILE:
+      g_value_set_string (value, qtmux->fast_start_file_path);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (qtmux);
+}
+
+static void
+gst_qt_mux_generate_fast_start_file_path (GstQTMux * qtmux)
+{
+  gchar *tmp;
+
+  if (qtmux->fast_start_file_path) {
+    g_free (qtmux->fast_start_file_path);
+    qtmux->fast_start_file_path = NULL;
+  }
+
+  tmp = g_strdup_printf ("%s%d", "qtmux", g_random_int ());
+  qtmux->fast_start_file_path = g_build_filename (g_get_tmp_dir (), tmp, NULL);
+  g_free (tmp);
+}
+
+static void
+gst_qt_mux_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstQTMux *qtmux = GST_QT_MUX_CAST (object);
+
+  GST_OBJECT_LOCK (qtmux);
+  switch (prop_id) {
+    case PROP_LARGE_FILE:
+      qtmux->large_file = g_value_get_boolean (value);
+      break;
+    case PROP_MOVIE_TIMESCALE:
+      qtmux->timescale = g_value_get_uint (value);
+      break;
+    case PROP_DO_CTTS:
+      qtmux->guess_pts = g_value_get_boolean (value);
+      break;
+    case PROP_FAST_START:
+      qtmux->fast_start = g_value_get_boolean (value);
+      break;
+    case PROP_FAST_START_TEMP_FILE:
+      if (qtmux->fast_start_file_path) {
+        g_free (qtmux->fast_start_file_path);
+      }
+      qtmux->fast_start_file_path = g_value_dup_string (value);
+      /* NULL means to generate a random one */
+      if (!qtmux->fast_start_file_path) {
+        gst_qt_mux_generate_fast_start_file_path (qtmux);
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (qtmux);
+}
+
+static GstStateChangeReturn
+gst_qt_mux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstQTMux *qtmux = GST_QT_MUX_CAST (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_collect_pads_start (qtmux->collect);
+      qtmux->state = GST_QT_MUX_STATE_STARTED;
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_collect_pads_stop (qtmux->collect);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      gst_qt_mux_reset (qtmux, TRUE);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+
+gboolean
+gst_qt_mux_register (GstPlugin * plugin)
+{
+  GTypeInfo typeinfo = {
+    sizeof (GstQTMuxClass),
+    (GBaseInitFunc) gst_qt_mux_base_init,
+    NULL,
+    (GClassInitFunc) gst_qt_mux_class_init,
+    NULL,
+    NULL,
+    sizeof (GstQTMux),
+    0,
+    (GInstanceInitFunc) gst_qt_mux_init,
+  };
+  static const GInterfaceInfo tag_setter_info = {
+    NULL, NULL, NULL
+  };
+  GType type;
+  GstQTMuxFormat format;
+  GstQTMuxClassParams *params;
+  guint i = 0;
+
+  GST_LOG ("Registering muxers");
+
+  while (TRUE) {
+    GstQTMuxFormatProp *prop;
+
+    prop = &gst_qt_mux_format_list[i];
+    format = prop->format;
+    if (format == GST_QT_MUX_FORMAT_NONE)
+      break;
+
+    /* create a cache for these properties */
+    params = g_new0 (GstQTMuxClassParams, 1);
+    params->prop = prop;
+    params->src_caps = gst_static_caps_get (&prop->src_caps);
+    params->video_sink_caps = gst_static_caps_get (&prop->video_sink_caps);
+    params->audio_sink_caps = gst_static_caps_get (&prop->audio_sink_caps);
+
+    /* create the type now */
+    type = g_type_register_static (GST_TYPE_ELEMENT, prop->type_name, &typeinfo,
+        0);
+    g_type_set_qdata (type, GST_QT_MUX_PARAMS_QDATA, (gpointer) params);
+    g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, &tag_setter_info);
+
+    if (!gst_element_register (plugin, prop->name, GST_RANK_PRIMARY, type))
+      return FALSE;
+
+    i++;
+  }
+
+  GST_LOG ("Finished registering muxers");
+
+  return TRUE;
+}
+
+gboolean
+gst_qt_mux_plugin_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (gst_qt_mux_debug, "qtmux", 0, "QT Muxer");
+
+  return gst_qt_mux_register (plugin);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "qtmux",
+    "Quicktime Muxer plugin",
+    gst_qt_mux_plugin_init, VERSION, "LGPL", "gsoc2008 package",
+    "embedded.ufcg.edu.br")
+
+EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
+       {
+          return &gst_plugin_desc;
+       }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/gstqtmux.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,163 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __GST_QT_MUX_H__
+#define __GST_QT_MUX_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstcollectpads.h>
+
+#include "fourcc.h"
+#include "atoms.h"
+#include "gstqtmuxmap.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_QT_MUX (gst_qt_mux_get_type())
+#define GST_QT_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QT_MUX, GstQTMux))
+#define GST_QT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QT_MUX, GstQTMux))
+#define GST_IS_QT_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QT_MUX))
+#define GST_IS_QT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QT_MUX))
+#define GST_QT_MUX_CAST(obj) ((GstQTMux*)(obj))
+
+
+typedef struct _GstQTMux GstQTMux;
+typedef struct _GstQTMuxClass GstQTMuxClass;
+
+typedef struct _GstQTPad
+{
+  GstCollectData collect;       /* we extend the CollectData */
+
+  /* fourcc id of stream */
+  guint32 fourcc;
+  /* whether using format that have out of order buffers */
+  gboolean is_out_of_order;
+  /* whether upstream provides valid PTS data */
+  gboolean have_dts;
+  /* if not 0, track with constant sized samples, e.g. raw audio */
+  guint sample_size;
+  /* make sync table entry */
+  gboolean sync;
+
+  GstBuffer *last_buf;
+  /* dts of last_buf */
+  GstClockTime last_dts;
+
+  /* all the atom and chunk book-keeping is delegated here
+   * unowned/uncounted reference, parent MOOV owns */
+  AtomTRAK *trak;
+} GstQTPad;
+
+typedef enum _GstQTMuxState
+{
+  GST_QT_MUX_STATE_NONE,
+  GST_QT_MUX_STATE_STARTED,
+  GST_QT_MUX_STATE_DATA,
+  GST_QT_MUX_STATE_EOS
+} GstQTMuxState;
+
+struct _GstQTMux
+{
+  GstElement element;
+
+  GstPad *srcpad;
+  GstCollectPads *collect;
+
+  /* state */
+  GstQTMuxState state;
+
+  /* size of header (prefix, atoms (ftyp, mdat)) */
+  guint64 header_size;
+  /* accumulated size of raw media data (a priori not including mdat header) */
+  guint64 mdat_size;
+  /* position of mdat atom (for later updating) */
+  guint64 mdat_pos;
+
+  /* keep track of the largest chunk to fine-tune brands */
+  GstClockTime longest_chunk;
+
+  /* atom helper objects */
+  AtomsContext *context;
+  AtomFTYP *ftyp;
+  AtomMOOV *moov;
+
+  /* fast start */
+  FILE *fast_start_file;
+
+  /* properties */
+  guint32 timescale;
+  AtomsTreeFlavor flavor;
+  gboolean fast_start;
+  gboolean large_file;
+  gboolean guess_pts;
+  gchar *fast_start_file_path;
+
+  /* for collect pads event handling function */
+  GstPadEventFunction collect_event;
+
+  /* for request pad naming */
+  guint video_pads, audio_pads;
+};
+
+struct _GstQTMuxClass
+{
+  GstElementClass parent_class;
+
+  GstQTMuxFormat format;
+};
+
+/* type register helper struct */
+typedef struct _GstQTMuxClassParams
+{
+  GstQTMuxFormatProp *prop;
+  GstCaps *src_caps;
+  GstCaps *video_sink_caps;
+  GstCaps *audio_sink_caps;
+} GstQTMuxClassParams;
+
+#define GST_QT_MUX_PARAMS_QDATA g_quark_from_static_string("qt-mux-params")
+
+GType gst_qt_mux_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_QT_MUX_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/gstqtmuxmap.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,327 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "gstqtmuxmap.h"
+#include "fourcc.h"
+#include "ftypcc.h"
+
+/* static info related to various format */
+
+#define COMMON_VIDEO_CAPS \
+  "width = (int) [ 16, 4096 ], " \
+  "height = (int) [ 16, 4096 ], " \
+  "framerate = (fraction) [ 0, MAX ]"
+
+#define COMMON_VIDEO_CAPS_NO_FRAMERATE \
+  "width = (int) [ 16, 4096 ], " \
+  "height = (int) [ 16, 4096 ] "
+
+#define H263_CAPS \
+  "video/x-h263, " \
+  COMMON_VIDEO_CAPS
+
+#define H264_CAPS \
+  "video/x-h264, " \
+  COMMON_VIDEO_CAPS
+
+#define MPEG4V_CAPS \
+  "video/mpeg, " \
+  "mpegversion = (int) 4, "\
+  "systemstream = (boolean) false, " \
+  COMMON_VIDEO_CAPS "; " \
+  "video/x-divx, " \
+  "divxversion = (int) 5, "\
+  COMMON_VIDEO_CAPS
+
+#define COMMON_AUDIO_CAPS(c, r) \
+  "channels = (int) [ 1, " G_STRINGIFY (c) " ], " \
+  "rate = (int) [ 1, " G_STRINGIFY (r) " ]"
+
+#define PCM_CAPS \
+  "audio/x-raw-int, " \
+  "width = (int) 8, " \
+  "depth = (int) 8, " \
+  COMMON_AUDIO_CAPS (2, MAX) ", " \
+  "signed = (boolean) { true, false }; " \
+  "audio/x-raw-int, " \
+  "width = (int) 16, " \
+  "depth = (int) 16, " \
+  "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
+  COMMON_AUDIO_CAPS (2, MAX) ", " \
+  "signed = (boolean) true " \
+
+#define PCM_CAPS_FULL \
+  PCM_CAPS "; " \
+  "audio/x-raw-int, " \
+  "width = (int) 24, " \
+  "depth = (int) 24, " \
+  "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
+  COMMON_AUDIO_CAPS (2, MAX) ", " \
+  "signed = (boolean) true; " \
+  "audio/x-raw-int, " \
+  "width = (int) 32, " \
+  "depth = (int) 32, " \
+  "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
+  COMMON_AUDIO_CAPS (2, MAX) ", " \
+  "signed = (boolean) true "
+
+#define MP3_CAPS \
+  "audio/mpeg, " \
+  "mpegversion = (int) 1, " \
+  "layer = (int) 3, " \
+  COMMON_AUDIO_CAPS (2, MAX)
+
+#define AAC_CAPS \
+  "audio/mpeg, " \
+  "mpegversion = (int) 4, " \
+  COMMON_AUDIO_CAPS (8, MAX)
+
+#define AMR_CAPS \
+  "audio/AMR, " \
+  "rate = (int) 8000, " \
+  "channels = [ 1, 2 ]; " \
+  "audio/AMR-WB, " \
+  "rate = (int) 16000, " \
+  "channels = [ 1, 2 ] "
+
+/* FIXME 0.11 - take a look at bugs #580005 and #340375 */
+GstQTMuxFormatProp gst_qt_mux_format_list[] = {
+  /* original QuickTime format; see Apple site (e.g. qtff.pdf) */
+  {
+        GST_QT_MUX_FORMAT_QT,
+        "qtmux",
+        "QuickTime",
+        "GstQTMux",
+        GST_STATIC_CAPS ("video/quicktime, variant = (string) apple"),
+        GST_STATIC_CAPS ("video/x-raw-rgb, "
+            COMMON_VIDEO_CAPS "; "
+            "video/x-raw-yuv, "
+            "format = (fourcc) UYVY, "
+            COMMON_VIDEO_CAPS "; "
+            MPEG4V_CAPS "; "
+            H263_CAPS "; "
+            H264_CAPS "; "
+            "video/x-dv, "
+            "systemstream = (boolean) false, "
+            COMMON_VIDEO_CAPS "; "
+            "image/jpeg, "
+            COMMON_VIDEO_CAPS_NO_FRAMERATE "; "
+            "video/x-qt-part, " COMMON_VIDEO_CAPS),
+        GST_STATIC_CAPS (PCM_CAPS_FULL "; "
+            MP3_CAPS " ; "
+            AAC_CAPS " ; "
+            "audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; " AMR_CAPS)
+      }
+  ,
+  /* ISO 14496-14: mp42 as ISO base media extension
+   * (supersedes original ISO 144996-1 mp41) */
+  {
+        GST_QT_MUX_FORMAT_MP4,
+        "mp4mux",
+        "MP4",
+        "GstMP4Mux",
+        GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
+        GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
+            "video/x-mp4-part," COMMON_VIDEO_CAPS),
+        GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS)
+      }
+  ,
+  /* 3GPP Technical Specification 26.244 V7.3.0
+   * (extended in 3GPP2 File Formats for Multimedia Services) */
+  {
+        GST_QT_MUX_FORMAT_3GP,
+        "gppmux",
+        "3GPP",
+        "GstGPPMux",
+        GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
+        GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
+        GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS)
+      }
+  ,
+  /* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
+  {
+        GST_QT_MUX_FORMAT_MJ2,
+        "mj2mux",
+        "MJ2",
+        "GstMJ2Mux",
+        GST_STATIC_CAPS ("video/mj2"),
+        GST_STATIC_CAPS ("image/x-j2c, " COMMON_VIDEO_CAPS),
+        GST_STATIC_CAPS (PCM_CAPS)
+      }
+  ,
+  {
+        GST_QT_MUX_FORMAT_NONE,
+      }
+  ,
+};
+
+/* pretty static, but may turn out needed a few times */
+AtomsTreeFlavor
+gst_qt_mux_map_format_to_flavor (GstQTMuxFormat format)
+{
+  if (format == GST_QT_MUX_FORMAT_QT)
+    return ATOMS_TREE_FLAVOR_MOV;
+  else if (format == GST_QT_MUX_FORMAT_3GP)
+    return ATOMS_TREE_FLAVOR_3GP;
+  else
+    return ATOMS_TREE_FLAVOR_ISOM;
+}
+
+static void
+gst_qt_mux_map_check_tracks (AtomMOOV * moov, gint * _video, gint * _audio,
+    gboolean * _has_h264)
+{
+  GList *it;
+  gint video = 0, audio = 0;
+  gboolean has_h264 = FALSE;
+
+  for (it = moov->traks; it != NULL; it = g_list_next (it)) {
+    AtomTRAK *track = it->data;
+
+    if (track->is_video) {
+      video++;
+      if (track->is_h264)
+        has_h264 = TRUE;
+    } else
+      audio++;
+  }
+
+  if (_video)
+    *_video = video;
+  if (_audio)
+    *_audio = audio;
+  if (_has_h264)
+    *_has_h264 = has_h264;
+}
+
+/* pretty static, but possibly dynamic format info */
+
+/* notes:
+ * - avc1 brand is not used, since the specific extensions indicated by it
+ *   are not used (e.g. sample groupings, etc)
+ * - TODO: maybe even more 3GPP brand fine-tuning ??
+ *   (but that might need ftyp rewriting at the end) */
+void
+gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
+    guint32 * _major, guint32 * _version, GList ** _compatible, AtomMOOV * moov,
+    GstClockTime longest_chunk, gboolean faststart)
+{
+  static guint32 qt_brands[] = { 0 };
+  static guint32 mp4_brands[] = { FOURCC_mp41, FOURCC_isom, FOURCC_iso2, 0 };
+  static guint32 gpp_brands[] = { FOURCC_isom, FOURCC_iso2, 0 };
+  static guint32 mjp2_brands[] = { FOURCC_isom, FOURCC_iso2, 0 };
+  static guint8 mjp2_prefix[] =
+      { 0, 0, 0, 12, 'j', 'P', ' ', ' ', 0x0D, 0x0A, 0x87, 0x0A };
+  guint32 *comp = NULL;
+  guint32 major = 0, version = 0;
+  GstBuffer *prefix = NULL;
+  GList *result = NULL;
+
+  g_return_if_fail (_prefix != NULL);
+  g_return_if_fail (_major != NULL);
+  g_return_if_fail (_version != NULL);
+  g_return_if_fail (_compatible != NULL);
+
+  switch (format) {
+    case GST_QT_MUX_FORMAT_QT:
+      major = FOURCC_qt__;
+      comp = qt_brands;
+      version = 0x20050300;
+      break;
+    case GST_QT_MUX_FORMAT_MP4:
+      major = FOURCC_mp42;
+      comp = mp4_brands;
+      break;
+    case GST_QT_MUX_FORMAT_3GP:
+    {
+      gint video, audio;
+      gboolean has_h264;
+
+      gst_qt_mux_map_check_tracks (moov, &video, &audio, &has_h264);
+      /* only track restriction really matters for Basic Profile */
+      if (video <= 1 && audio <= 1) {
+        /* it seems only newer spec knows about H264 */
+        major = has_h264 ? FOURCC_3gp6 : FOURCC_3gp4;
+        version = has_h264 ? 0x100 : 0x200;
+      } else {
+        major = FOURCC_3gg6;
+        version = 0x100;
+      }
+      comp = gpp_brands;
+
+      /*
+       * We assume that we have chunks in dts order
+       */
+      if (faststart && longest_chunk <= GST_SECOND) {
+        /* add progressive download profile */
+        result = g_list_append (result, GUINT_TO_POINTER (FOURCC_3gr6));
+      }
+      break;
+    }
+    case GST_QT_MUX_FORMAT_MJ2:
+      major = FOURCC_mjp2;
+      comp = mjp2_brands;
+      version = 0;
+      prefix = gst_buffer_new_and_alloc (sizeof (mjp2_prefix));
+      memcpy (GST_BUFFER_DATA (prefix), mjp2_prefix, GST_BUFFER_SIZE (prefix));
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+  }
+
+  /* convert list to list, hm */
+  while (comp && *comp != 0) {
+    /* order matters over efficiency */
+    result = g_list_append (result, GUINT_TO_POINTER (*comp));
+    comp++;
+  }
+
+  *_major = major;
+  *_version = version;
+  *_prefix = prefix;
+  *_compatible = result;
+
+  /* TODO 3GPP may include mp42 as compatible if applicable */
+  /* TODO 3GPP major brand 3gp7 if at most 1 video and audio track */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/gstqtmuxmap.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,82 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __GST_QT_MUX_MAP_H__
+#define __GST_QT_MUX_MAP_H__
+
+#include "atoms.h"
+
+#include <glib.h>
+#include <gst/gst.h>
+
+typedef enum _GstQTMuxFormat
+{
+  GST_QT_MUX_FORMAT_NONE = 0,
+  GST_QT_MUX_FORMAT_QT,
+  GST_QT_MUX_FORMAT_MP4,
+  GST_QT_MUX_FORMAT_3GP,
+  GST_QT_MUX_FORMAT_MJ2
+} GstQTMuxFormat;
+
+typedef struct _GstQTMuxFormatProp
+{
+  GstQTMuxFormat format;
+  gchar *name;
+  gchar *long_name;
+  gchar *type_name;
+  GstStaticCaps src_caps;
+  GstStaticCaps video_sink_caps;
+  GstStaticCaps audio_sink_caps;
+} GstQTMuxFormatProp;
+
+extern GstQTMuxFormatProp gst_qt_mux_format_list[];
+
+void            gst_qt_mux_map_format_to_header      (GstQTMuxFormat format, GstBuffer ** _prefix,
+                                                      guint32 * _major, guint32 * verson,
+                                                      GList ** _compatible, AtomMOOV * moov,
+                                                      GstClockTime longest_chunk,
+                                                      gboolean faststart);
+
+AtomsTreeFlavor gst_qt_mux_map_format_to_flavor      (GstQTMuxFormat format);
+
+#endif /* __GST_QT_MUX_MAP_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/properties.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,206 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "properties.h"
+
+/* if needed, re-allocate buffer to ensure size bytes can be written into it
+ * at offset */
+void
+prop_copy_ensure_buffer (guint8 ** buffer, guint64 * bsize, guint64 * offset,
+    guint64 size)
+{
+  if (buffer && *bsize - *offset < size) {
+    *bsize += size + 10 * 1024;
+    *buffer = g_realloc (*buffer, *bsize);
+  }
+}
+
+static guint64
+copy_func (void *prop, guint size, guint8 ** buffer, guint64 * bsize,
+    guint64 * offset)
+{
+  if (buffer) {
+    prop_copy_ensure_buffer (buffer, bsize, offset, size);
+    memcpy (*buffer + *offset, prop, size);
+  }
+  *offset += size;
+  return size;
+}
+
+#define INT_ARRAY_COPY_FUNC_FAST(name, datatype) 			\
+guint64 prop_copy_ ## name ## _array (datatype *prop, guint size,	\
+    guint8 ** buffer, guint64 * bsize, guint64 * offset) { 		\
+  return copy_func (prop, sizeof (datatype) * size, buffer, bsize, offset);\
+}
+
+#define INT_ARRAY_COPY_FUNC(name, datatype) 				\
+guint64 prop_copy_ ## name ## _array (datatype *prop, guint size,	\
+    guint8 ** buffer, guint64 * bsize, guint64 * offset) { 		\
+  guint i;								\
+									\
+  for (i = 0; i < size; i++) {						\
+    prop_copy_ ## name (prop[i], buffer, bsize, offset);		\
+  }									\
+  return sizeof (datatype) * size;					\
+}
+
+/* INTEGERS */
+guint64
+prop_copy_uint8 (guint8 prop, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  return copy_func (&prop, sizeof (guint8), buffer, size, offset);
+}
+
+guint64
+prop_copy_uint16 (guint16 prop, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  prop = GUINT16_TO_BE (prop);
+  return copy_func (&prop, sizeof (guint16), buffer, size, offset);
+}
+
+guint64
+prop_copy_uint32 (guint32 prop, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  prop = GUINT32_TO_BE (prop);
+  return copy_func (&prop, sizeof (guint32), buffer, size, offset);
+}
+
+guint64
+prop_copy_uint64 (guint64 prop, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  prop = GUINT64_TO_BE (prop);
+  return copy_func (&prop, sizeof (guint64), buffer, size, offset);
+}
+
+guint64
+prop_copy_int32 (gint32 prop, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  prop = GINT32_TO_BE (prop);
+  return copy_func (&prop, sizeof (guint32), buffer, size, offset);
+}
+
+/* uint8 can use direct copy in any case, and may be used for large quantity */
+INT_ARRAY_COPY_FUNC_FAST (uint8, guint8);
+/* not used in large quantity anyway */
+INT_ARRAY_COPY_FUNC (uint16, guint16);
+INT_ARRAY_COPY_FUNC (uint32, guint32);
+INT_ARRAY_COPY_FUNC (uint64, guint64);
+
+/* FOURCC */
+guint64
+prop_copy_fourcc (guint32 prop, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  prop = GINT32_TO_LE (prop);
+  return copy_func (&prop, sizeof (guint32), buffer, size, offset);
+}
+
+INT_ARRAY_COPY_FUNC (fourcc, guint32);
+
+/**
+ * Copies a string of bytes without placing its size at the beginning.
+ *
+ * @string: the string to be copied
+ * @str_size: size of the string
+ * @buffer: the array to copy the string to
+ * @offset: the position in the buffer array.
+ * This value is updated to the point right after the copied string.
+ *
+ * Returns: the number of bytes copied
+ */
+guint64
+prop_copy_fixed_size_string (guint8 * string, guint str_size, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  return copy_func (string, str_size * sizeof (guint8), buffer, size, offset);
+}
+
+/**
+ * Copies a string and its size to an array. Example:
+ * string = 'abc\0'
+ * result in the array: [3][a][b][c]  (each [x] represents a position)
+ *
+ * @string: the string to be copied
+ * @str_size: size of the string
+ * @buffer: the array to copy the string to
+ * @offset: the position in the buffer array.
+ * This value is updated to the point right after the copied string.
+ *
+ * Returns: the number of bytes copied
+ */
+guint64
+prop_copy_size_string (guint8 * string, guint str_size, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  prop_copy_uint8 (str_size, buffer, size, offset);
+  prop_copy_fixed_size_string (string, str_size, buffer, size, offset);
+  return *offset - original_offset;
+}
+
+/**
+ * Copies a string including its null terminating char to an array.
+ *
+ * @string: the string to be copied
+ * @buffer: the array to copy the string to
+ * @offset: the position in the buffer array.
+ * This value is updated to the point right after the copied string.
+ *
+ * Returns: the number of bytes copied
+ */
+guint64
+prop_copy_null_terminated_string (gchar * string, guint8 ** buffer,
+    guint64 * size, guint64 * offset)
+{
+  guint64 original_offset = *offset;
+  guint len = strlen (string);
+
+  prop_copy_fixed_size_string ((guint8 *) string, len, buffer, size, offset);
+  prop_copy_uint8 ('\0', buffer, size, offset);
+  return *offset - original_offset;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_good/gst/qtmux/properties.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,87 @@
+/* Quicktime muxer plugin for GStreamer
+ * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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.
+ */
+/*
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __PROPERTIES_H__
+#define __PROPERTIES_H__
+
+#include <glib.h>
+#include <string.h>
+
+/**
+ * Functions for copying atoms properties.
+ *
+ * All of them receive, as the input, the property to be copied, the destination
+ * buffer, and a pointer to an offset in the destination buffer to copy to the right place.
+ * This offset will be updated to the new value (offset + copied_size)
+ * The functions return the size of the property that has been copied or 0
+ * if it couldn't copy.
+ */
+
+void    prop_copy_ensure_buffer          (guint8 ** buffer, guint64 * bsize, guint64 * offset, guint64 size);
+
+guint64 prop_copy_uint8                  (guint8 prop, guint8 **buffer, guint64 *size, guint64 *offset);
+guint64 prop_copy_uint16                 (guint16 prop, guint8 **buffer, guint64 *size, guint64 *offset);
+guint64 prop_copy_uint32                 (guint32 prop, guint8 **buffer, guint64 *size, guint64 *offset);
+guint64 prop_copy_uint64                 (guint64 prop, guint8 **buffer, guint64 *size, guint64 *offset);
+
+guint64 prop_copy_int32                  (gint32 prop, guint8 **buffer, guint64 *size, guint64 *offset);
+
+guint64 prop_copy_uint8_array            (guint8 *prop, guint size,
+                                          guint8 **buffer, guint64 *bsize, guint64 *offset);
+guint64 prop_copy_uint16_array           (guint16 *prop, guint size,
+                                          guint8 **buffer, guint64 *bsize, guint64 *offset);
+guint64 prop_copy_uint32_array           (guint32 *prop, guint size,
+                                          guint8 **buffer, guint64 *bsize, guint64 *offset);
+guint64 prop_copy_uint64_array           (guint64 *prop, guint size,
+                                          guint8 **buffer, guint64 *bsize, guint64 *offset);
+
+guint64 prop_copy_fourcc                 (guint32 prop, guint8 **buffer, guint64 *size, guint64 *offset);
+guint64 prop_copy_fourcc_array           (guint32 *prop, guint size,
+                                          guint8 **buffer, guint64 *bsize, guint64 *offset);
+guint64 prop_copy_fixed_size_string      (guint8 *string, guint str_size,
+                                          guint8 **buffer, guint64 *size, guint64 *offset);
+guint64 prop_copy_size_string            (guint8 *string, guint str_size,
+                                          guint8 **buffer, guint64 *size, guint64 *offset);
+guint64 prop_copy_null_terminated_string (gchar *string,
+                                          guint8 **buffer, guint64 *size, guint64 *offset);
+
+#endif /* __PROPERTIES_H__ */
--- a/gst_plugins_good/gst/wavenc/gstwavenc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/wavenc/gstwavenc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,24 +24,17 @@
 #include "config.h"
 #endif
 
-
-
 #include <string.h>
 #include "gstwavenc.h"
-//#include "riff.h" rj
+#include "riff.h"
 
-#include "gst/riff/riff-ids.h"
-#include "gst/riff/riff-media.h"
-#include <gst/gst-i18n-plugin.h>
 
 #ifdef __SYMBIAN32__
 #include<gst/gstinfo.h>
 #endif
 
 GST_DEBUG_CATEGORY_STATIC (wavenc_debug);
-#define GST_CAT_DEFAULT (wavenc_debug) //rj
-
-#define WAVE_FORMAT_PCM 0x0001
+#define GST_CAT_DEFAULT wavenc_debug
 
 struct riff_struct
 {
@@ -88,6 +81,22 @@
     "rate = (int) [ 1, MAX ], "          \
     "channels = (int) [ 1, 2 ], "        \
     "endianness = (int) LITTLE_ENDIAN, " \
+    "width = (int) 32, "                 \
+    "depth = (int) 32, "                 \
+    "signed = (boolean) true"            \
+    "; "                                 \
+    "audio/x-raw-int, "                  \
+    "rate = (int) [ 1, MAX ], "          \
+    "channels = (int) [ 1, 2 ], "        \
+    "endianness = (int) LITTLE_ENDIAN, " \
+    "width = (int) 24, "                 \
+    "depth = (int) 24, "                 \
+    "signed = (boolean) true"            \
+    "; "                                 \
+    "audio/x-raw-int, "                  \
+    "rate = (int) [ 1, MAX ], "          \
+    "channels = (int) [ 1, 2 ], "        \
+    "endianness = (int) LITTLE_ENDIAN, " \
     "width = (int) 16, "                 \
     "depth = (int) 16, "                 \
     "signed = (boolean) true"            \
@@ -96,6 +105,25 @@
     "rate = (int) [ 1, MAX ], "          \
     "channels = (int) [ 1, 2 ], "        \
     "width = (int) 8, "                  \
+    "depth = (int) 8, "                  \
+    "signed = (boolean) false"           \
+    "; "                                 \
+    "audio/x-raw-float, "                \
+    "rate = (int) [ 1, MAX ], "          \
+    "channels = (int) [ 1, 2 ], "        \
+    "endianness = (int) LITTLE_ENDIAN, " \
+    "width = (int) { 32, 64 }; "         \
+    "audio/x-alaw, "                     \
+    "rate = (int) [ 8000, 192000 ], "    \
+    "channels = (int) [ 1, 2 ], "        \
+    "width = (int) 8, "                  \
+    "depth = (int) 8, "                  \
+    "signed = (boolean) false; "         \
+    "audio/x-mulaw, "                    \
+    "rate = (int) [ 8000, 192000 ], "    \
+    "channels = (int) [ 1, 2 ], "        \
+    "width = (int) 8, "                  \
+    "depth = (int) 8, "                  \
     "signed = (boolean) false"
 
 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
@@ -110,16 +138,7 @@
     GST_STATIC_CAPS ("audio/x-wav")
     );
 
-#ifndef __SYMBIAN32__  //rj
 GST_BOILERPLATE (GstWavEnc, gst_wavenc, GstElement, GST_TYPE_ELEMENT);
-#endif
-
-//rj
-static void gst_wavenc_base_init (gpointer g_class);
-static void gst_wavenc_class_init (GstWavEncClass * klass);
-static void gst_wavenc_init (GstWavEnc * wavenc, GstWavEncClass * klass);
-static GstElementClass *parent_class = NULL;
-//rj
 
 static GstFlowReturn gst_wavenc_chain (GstPad * pad, GstBuffer * buf);
 static gboolean gst_wavenc_event (GstPad * pad, GstEvent * event);
@@ -127,34 +146,6 @@
     GstStateChange transition);
 static gboolean gst_wavenc_sink_setcaps (GstPad * pad, GstCaps * caps);
 
-
-
-
-GType gst_wavenc_get_type (void)
-{
-  static GType wavenc_type = 0;
-
-  if (!wavenc_type) {
-    static const GTypeInfo wavenc_info = {
-      sizeof (GstWavEncClass),
-      gst_wavenc_base_init,
-      NULL,
-      (GClassInitFunc) gst_wavenc_class_init,
-      NULL,
-      NULL,
-      sizeof (GstWavEnc),
-      0,
-      (GInstanceInitFunc) gst_wavenc_init,
-    };
-
-    wavenc_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstWavEnc",
-        &wavenc_info, 0);
-  }
-  return wavenc_type;
-}
-
-
 static void
 gst_wavenc_base_init (gpointer g_class)
 {
@@ -176,8 +167,6 @@
   GstElementClass *element_class;
 
   element_class = (GstElementClass *) klass;
-  
-  parent_class = g_type_class_peek_parent (klass);//rj
 
   element_class->change_state = GST_DEBUG_FUNCPTR (gst_wavenc_change_state);
 }
@@ -203,7 +192,6 @@
 
 #define WAV_HEADER_LEN 44
 
-/* FIXME: we are probably not handling depth != width correctly here */
 static GstBuffer *
 gst_wavenc_create_header_buf (GstWavEnc * wavenc, guint audio_data_size)
 {
@@ -216,23 +204,23 @@
   memset (header, 0, WAV_HEADER_LEN);
 
   wave.common.wChannels = wavenc->channels;
-  wave.common.wBitsPerSample = wavenc->depth;
+  wave.common.wBitsPerSample = wavenc->width;
   wave.common.dwSamplesPerSec = wavenc->rate;
 
   /* Fill out our wav-header with some information */
   memcpy (wave.riff.id, "RIFF", 4);
+  //g_printf("before wave.riff.len %d \n" ,wave.riff.len);
   wave.riff.len = audio_data_size + WAV_HEADER_LEN - 8;
+  //g_printf("after wave.riff.len %d \n" ,wave.riff.len);
   memcpy (wave.riff.wav_id, "WAVE", 4);
 
   memcpy (wave.format.id, "fmt ", 4);
   wave.format.len = 16;
 
-  wave.common.wFormatTag = WAVE_FORMAT_PCM;
+  wave.common.wFormatTag = wavenc->format;
+  wave.common.wBlockAlign = (wavenc->width / 8) * wave.common.wChannels;
   wave.common.dwAvgBytesPerSec =
-      wave.common.wChannels * wave.common.dwSamplesPerSec *
-      (wave.common.wBitsPerSample >> 3);
-  wave.common.wBlockAlign =
-      wave.common.wChannels * (wave.common.wBitsPerSample >> 3);
+      wave.common.wBlockAlign * wave.common.dwSamplesPerSec;
 
   memcpy (wave.data.id, "data", 4);
   wave.data.len = audio_data_size;
@@ -287,7 +275,8 @@
 {
   GstWavEnc *wavenc;
   GstStructure *structure;
-  gint chans, rate, width, depth;
+  const gchar *name;
+  gint chans, rate, width;
 
   wavenc = GST_WAVENC (gst_pad_get_parent (pad));
 
@@ -299,21 +288,45 @@
   GST_DEBUG_OBJECT (wavenc, "got caps: %" GST_PTR_FORMAT, caps);
 
   structure = gst_caps_get_structure (caps, 0);
+  name = gst_structure_get_name (structure);
+
   if (!gst_structure_get_int (structure, "channels", &chans) ||
-      !gst_structure_get_int (structure, "rate", &rate) ||
-      !gst_structure_get_int (structure, "width", &width) ||
-      (width != 8 && !gst_structure_get_int (structure, "depth", &depth))) {
+      !gst_structure_get_int (structure, "rate", &rate)) {
     GST_WARNING_OBJECT (wavenc, "caps incomplete");
     goto fail;
   }
 
+  if (strcmp (name, "audio/x-raw-int") == 0) {
+    if (!gst_structure_get_int (structure, "width", &width)) {
+      GST_WARNING_OBJECT (wavenc, "caps incomplete");
+      goto fail;
+    }
+    wavenc->format = GST_RIFF_WAVE_FORMAT_PCM;
+    wavenc->width = width;
+  } else if (strcmp (name, "audio/x-raw-float") == 0) {
+    if (!gst_structure_get_int (structure, "width", &width)) {
+      GST_WARNING_OBJECT (wavenc, "caps incomplete");
+      goto fail;
+    }
+    wavenc->format = GST_RIFF_WAVE_FORMAT_FLOAT;
+    wavenc->width = width;
+  } else if (strcmp (name, "audio/x-alaw") == 0) {
+    wavenc->format = GST_RIFF_WAVE_FORMAT_ALAW;
+    wavenc->width = 8;
+  } else if (strcmp (name, "audio/x-mulaw") == 0) {
+    wavenc->format = GST_RIFF_WAVE_FORMAT_MULAW;
+    wavenc->width = 8;
+  } else {
+    GST_WARNING_OBJECT (wavenc, "Unsupported format %s", name);
+    goto fail;
+  }
+
   wavenc->channels = chans;
-  wavenc->width = width;
-  wavenc->depth = (width == 8) ? 8 : depth;
   wavenc->rate = rate;
 
-  GST_LOG_OBJECT (wavenc, "accepted caps: chans=%u width=%u depth=%u rate=%u",
-      wavenc->channels, wavenc->width, wavenc->depth, wavenc->rate);
+  GST_LOG_OBJECT (wavenc,
+      "accepted caps: format=0x%04x chans=%u width=%u rate=%u",
+      wavenc->format, wavenc->channels, wavenc->width, wavenc->rate);
 
   gst_object_unref (wavenc);
   return TRUE;
@@ -625,6 +638,9 @@
       /* write header with correct length values */
       gst_wavenc_push_header (wavenc, wavenc->length);
 
+      /* we're done with this file */
+      wavenc->finished_properly = TRUE;
+
       /* and forward the EOS event */
       res = gst_pad_event_default (pad, event);
       break;
@@ -656,6 +672,9 @@
      * header when we get EOS and know the exact length */
     flow = gst_wavenc_push_header (wavenc, 0x7FFF0000);
 
+    /* starting a file, means we have to finish it properly */
+    wavenc->finished_properly = FALSE;
+
     if (flow != GST_FLOW_OK)
       return flow;
 
@@ -663,8 +682,6 @@
     wavenc->sent_header = TRUE;
   }
 
-  wavenc->length += GST_BUFFER_SIZE (buf);
-
   GST_LOG_OBJECT (wavenc, "pushing %u bytes raw audio, ts=%" GST_TIME_FORMAT,
       GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
 
@@ -673,6 +690,8 @@
   GST_BUFFER_OFFSET (buf) = WAV_HEADER_LEN + wavenc->length;
   GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
 
+  wavenc->length += GST_BUFFER_SIZE (buf);
+
   flow = gst_pad_push (wavenc->srcpad, buf);
 
   return flow;
@@ -686,12 +705,14 @@
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
+      wavenc->format = 0;
       wavenc->channels = 0;
       wavenc->width = 0;
-      wavenc->depth = 0;
       wavenc->rate = 0;
       wavenc->length = 0;
       wavenc->sent_header = FALSE;
+      /* its true because we haven't writen anything */
+      wavenc->finished_properly = TRUE;
       break;
     default:
       break;
@@ -701,13 +722,26 @@
   if (ret != GST_STATE_CHANGE_SUCCESS)
     return ret;
 
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      if (!wavenc->finished_properly) {
+        GST_ELEMENT_WARNING (wavenc, STREAM, MUX,
+            ("Wav stream not finished properly"),
+            ("Wav stream not finished properly, no EOS received "
+                "before shutdown"));
+      }
+      break;
+    default:
+      break;
+  }
+
   return ret;
 }
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  return gst_element_register (plugin, "wavenc", GST_RANK_NONE,
+  return gst_element_register (plugin, "wavenc", GST_RANK_PRIMARY,
       GST_TYPE_WAVENC);
 }
 
--- a/gst_plugins_good/gst/wavenc/gstwavenc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/wavenc/gstwavenc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -47,20 +47,20 @@
   GstPad    *srcpad;
 
   /* useful audio data */
-  guint      depth;
+  guint16    format;
   guint      width;
   guint      rate;
   guint      channels;
   guint32    length;
 
   gboolean   sent_header;
+  gboolean   finished_properly;
 };
 
 struct _GstWavEncClass {
   GstElementClass parent_class;
 };
 
-GType gst_wavenc_get_type(void);
 G_END_DECLS
 
 #endif /* __GST_WAV_ENC_H__ */
--- a/gst_plugins_good/gst/wavenc/riff.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/wavenc/riff.h	Fri Apr 16 15:15:52 2010 +0300
@@ -300,6 +300,7 @@
 #define GST_RIFF_WAVE_FORMAT_UNKNOWN        (0x0000)
 #define GST_RIFF_WAVE_FORMAT_PCM            (0x0001)
 #define GST_RIFF_WAVE_FORMAT_ADPCM          (0x0002)
+#define GST_RIFF_WAVE_FORMAT_FLOAT          (0x0003)
 #define GST_RIFF_WAVE_FORMAT_IBM_CVSD       (0x0005)
 #define GST_RIFF_WAVE_FORMAT_ALAW           (0x0006)
 #define GST_RIFF_WAVE_FORMAT_MULAW          (0x0007)
--- a/gst_plugins_good/gst/wavparse/gstwavparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/wavparse/gstwavparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,62 +22,44 @@
 /**
  * SECTION:element-wavparse
  *
+ * Parse a .wav file into raw or compressed audio.
+ *
+ * Wavparse supports both push and pull mode operations, making it possible to
+ * stream from a network source.
+ *
  * <refsect2>
- * <para>
- * Parse a .wav file into raw or compressed audio.
- * </para>
- * <para>
- * This element currently only supports pull based scheduling.
- * </para>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch filesrc location=sine.wav ! wavparse ! audioconvert ! alsasink
- * </programlisting>
- * Read a wav file and output to the soundcard using the ALSA element. The
+ * ]| Read a wav file and output to the soundcard using the ALSA element. The
  * wav file is assumed to contain raw uncompressed samples.
- * </para>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch gnomevfssrc location=http://www.example.org/sine.wav ! queue ! wavparse ! audioconvert ! alsasink
- * </programlisting>
- * Stream data from
- * </para>
+ * ]| Stream data from a network url.
  * </refsect2>
  *
- * Last reviewed on 2006-03-03 (0.10.3)
+ * Last reviewed on 2007-02-14 (0.10.6)
+ */
+
+/*
+ * TODO:
+ * http://replaygain.hydrogenaudio.org/file_format_wav.html
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+#include <string.h>
+#include <math.h>
 
-#include "string.h"
 #include "gstwavparse.h"
-#include <gst/riff/riff-ids.h>
-#include <gst/riff/riff-media.h>
-#include <gst/riff/riff-read.h>
-
-#ifndef __SYMBIAN32__
+#include "gst/riff/riff-ids.h"
+#include "gst/riff/riff-media.h"
 #include <gst/gst-i18n-plugin.h>
-#else
-#include "gst/gst-i18n-plugin.h"
-#endif
-
-#ifdef __SYMBIAN32__
-#include <gst/gstinfo.h>
-#endif
-
-#ifndef G_MAXUINT32
-#define G_MAXUINT32 0xffffffff
-#endif
 
 GST_DEBUG_CATEGORY_STATIC (wavparse_debug);
 #define GST_CAT_DEFAULT (wavparse_debug)
 
-static void gst_wavparse_base_init (gpointer g_class);
-static void gst_wavparse_class_init (GstWavParseClass * klass);
-static void gst_wavparse_init (GstWavParse * wavparse);
 static void gst_wavparse_dispose (GObject * object);
 
 static gboolean gst_wavparse_sink_activate (GstPad * sinkpad);
@@ -85,20 +67,19 @@
     gboolean active);
 static gboolean gst_wavparse_send_event (GstElement * element,
     GstEvent * event);
-static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstBuffer * buf);
 static GstStateChangeReturn gst_wavparse_change_state (GstElement * element,
     GstStateChange transition);
 
+static const GstQueryType *gst_wavparse_get_query_types (GstPad * pad);
 static gboolean gst_wavparse_pad_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *gst_wavparse_get_query_types (GstPad * pad);
 static gboolean gst_wavparse_pad_convert (GstPad * pad,
     GstFormat src_format,
     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
 
+static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_wavparse_sink_event (GstPad * pad, GstEvent * event);
 static void gst_wavparse_loop (GstPad * pad);
 static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event);
-static void gst_wavparse_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
 
 static const GstElementDetails gst_wavparse_details =
 GST_ELEMENT_DETAILS ("WAV audio demuxer",
@@ -107,91 +88,33 @@
     "Erik Walthinsen <omega@cse.ogi.edu>");
 
 static GstStaticPadTemplate sink_template_factory =
-//GST_STATIC_PAD_TEMPLATE ("wavparse_sink",
-GST_STATIC_PAD_TEMPLATE ("sink", 
+GST_STATIC_PAD_TEMPLATE ("wavparse_sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("audio/x-wav")
     );
 
-/* the pad is marked a sometimes and is added to the element when the
- * exact type is known. This makes it much easier for a static autoplugger
- * to connect the right decoder when needed.
- */
-static GstStaticPadTemplate src_template_factory =
- //   GST_STATIC_PAD_TEMPLATE ("wavparse_src",
-    GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_SOMETIMES,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) little_endian, "
-        "signed = (boolean) { true, false }, "
-        "width = (int) { 8, 16, 24, 32 }, "
-        "depth = (int) { 8, 16, 24, 32 }, "
-        "rate = (int) [ 8000, 96000 ], "
-        "channels = (int) [ 1, 8 ]; "
-        "audio/mpeg, "
-        "mpegversion = (int) 1, "
-        "layer = (int) [ 1, 3 ], "
-        "rate = (int) [ 8000, 48000 ], "
-        "channels = (int) [ 1, 2 ]; "
-        "audio/x-alaw, "
-        "rate = (int) [ 8000, 48000 ], "
-        "channels = (int) [ 1, 2 ]; "
-        "audio/x-mulaw, "
-        "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ];"
-        "audio/x-adpcm, "
-        "layout = (string) microsoft, "
-        "block_align = (int) [ 1, 8192 ], "
-        "rate = (int) [ 8000, 48000 ], "
-        "channels = (int) [ 1, 2 ]; "
-        "audio/x-adpcm, "
-        "layout = (string) dvi, "
-        "block_align = (int) [ 1, 8192 ], "
-        "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ];"
-        "audio/x-vnd.sony.atrac3;"
-        "audio/x-dts;" "audio/x-wma, " "wmaversion = (int) [ 1, 2 ]")
-    );
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
 
-
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_wavparse_get_type (void)
-{
-  static GType wavparse_type = 0;
-
-  if (!wavparse_type) {
-    static const GTypeInfo wavparse_info = {
-      sizeof (GstWavParseClass),
-      gst_wavparse_base_init,
-      NULL,
-      (GClassInitFunc) gst_wavparse_class_init,
-      NULL,
-      NULL,
-      sizeof (GstWavParse),
-      0,
-      (GInstanceInitFunc) gst_wavparse_init,
-    };
-
-    wavparse_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstWavParse",
-        &wavparse_info, 0);
-  }
-  return wavparse_type;
-}
-
+GST_BOILERPLATE_FULL (GstWavParse, gst_wavparse, GstElement,
+    GST_TYPE_ELEMENT, DEBUG_INIT);
 
 static void
 gst_wavparse_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  GstPadTemplate *src_template;
 
-  /* register src pads */
+  /* register pads */
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&sink_template_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_template_factory));
+
+  src_template = gst_pad_template_new ("wavparse_src", GST_PAD_SRC,
+      GST_PAD_SOMETIMES, gst_riff_create_audio_template_caps ());
+  gst_element_class_add_pad_template (element_class, src_template);
+  gst_object_unref (src_template);
+
   gst_element_class_set_details (element_class, &gst_wavparse_details);
 }
 
@@ -206,64 +129,60 @@
 
   parent_class = g_type_class_peek_parent (klass);
 
-  object_class->get_property = gst_wavparse_get_property;
   object_class->dispose = gst_wavparse_dispose;
 
   gstelement_class->change_state = gst_wavparse_change_state;
   gstelement_class->send_event = gst_wavparse_send_event;
 }
 
+static void
+gst_wavparse_reset (GstWavParse * wav)
+{
+  wav->state = GST_WAVPARSE_START;
+
+  /* These will all be set correctly in the fmt chunk */
+  wav->depth = 0;
+  wav->rate = 0;
+  wav->width = 0;
+  wav->channels = 0;
+  wav->blockalign = 0;
+  wav->bps = 0;
+  wav->fact = 0;
+  wav->offset = 0;
+  wav->end_offset = 0;
+  wav->dataleft = 0;
+  wav->datasize = 0;
+  wav->datastart = 0;
+  wav->duration = 0;
+  wav->got_fmt = FALSE;
+  wav->first = TRUE;
+
+  if (wav->seek_event)
+    gst_event_unref (wav->seek_event);
+  wav->seek_event = NULL;
+  if (wav->adapter) {
+    gst_adapter_clear (wav->adapter);
+    g_object_unref (wav->adapter);
+    wav->adapter = NULL;
+  }
+  if (wav->tags)
+    gst_tag_list_free (wav->tags);
+  wav->tags = NULL;
+}
 
 static void
 gst_wavparse_dispose (GObject * object)
 {
-	#ifndef __SYMBIAN32__
-  GST_DEBUG("WAV: Dispose\n");
-  #endif
   GstWavParse *wav = GST_WAVPARSE (object);
-  #ifdef __SYMBIAN32__
-  GST_DEBUG("WAV: Dispose\n");
-	#endif
 
-  if (wav->adapter) {
-    g_object_unref (wav->adapter);
-    wav->adapter = NULL;
-  }
+  GST_DEBUG_OBJECT (wav, "WAV: Dispose");
+  gst_wavparse_reset (wav);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
-
 static void
-gst_wavparse_reset (GstWavParse * wavparse)
-{
-  wavparse->state = GST_WAVPARSE_START;
-
-  /* These will all be set correctly in the fmt chunk */
-  wavparse->depth = 0;
-  wavparse->rate = 0;
-  wavparse->width = 0;
-  wavparse->channels = 0;
-  wavparse->blockalign = 0;
-  wavparse->bps = 0;
-  wavparse->offset = 0;
-  wavparse->end_offset = 0;
-  wavparse->dataleft = 0;
-  wavparse->datasize = 0;
-  wavparse->datastart = 0;
-  wavparse->got_fmt = FALSE;
-  wavparse->first = TRUE;
-
-  if (wavparse->seek_event)
-    gst_event_unref (wavparse->seek_event);
-  wavparse->seek_event = NULL;
-
-  /* we keep the segment info in time */
-  gst_segment_init (&wavparse->segment, GST_FORMAT_TIME);
-}
-
-static void
-gst_wavparse_init (GstWavParse * wavparse)
+gst_wavparse_init (GstWavParse * wavparse, GstWavParseClass * g_class)
 {
   gst_wavparse_reset (wavparse);
 
@@ -276,7 +195,9 @@
       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate_pull));
   gst_pad_set_chain_function (wavparse->sinkpad,
       GST_DEBUG_FUNCPTR (gst_wavparse_chain));
-  gst_element_add_pad (GST_ELEMENT (wavparse), wavparse->sinkpad);
+  gst_pad_set_event_function (wavparse->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_wavparse_sink_event));
+  gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->sinkpad);
 
   /* src, will be created later */
   wavparse->srcpad = NULL;
@@ -286,7 +207,7 @@
 gst_wavparse_destroy_sourcepad (GstWavParse * wavparse)
 {
   if (wavparse->srcpad) {
-    gst_element_remove_pad (GST_ELEMENT (wavparse), wavparse->srcpad);
+    gst_element_remove_pad (GST_ELEMENT_CAST (wavparse), wavparse->srcpad);
     wavparse->srcpad = NULL;
   }
 }
@@ -294,12 +215,15 @@
 static void
 gst_wavparse_create_sourcepad (GstWavParse * wavparse)
 {
+  GstElementClass *klass = GST_ELEMENT_GET_CLASS (wavparse);
+  GstPadTemplate *src_template;
+
   /* destroy previous one */
   gst_wavparse_destroy_sourcepad (wavparse);
 
   /* source */
-  wavparse->srcpad =
-      gst_pad_new_from_static_template (&src_template_factory, "src");
+  src_template = gst_element_class_get_pad_template (klass, "wavparse_src");
+  wavparse->srcpad = gst_pad_new_from_template (src_template, "src");
   gst_pad_use_fixed_caps (wavparse->srcpad);
   gst_pad_set_query_type_function (wavparse->srcpad,
       GST_DEBUG_FUNCPTR (gst_wavparse_get_query_types));
@@ -311,22 +235,38 @@
   GST_DEBUG_OBJECT (wavparse, "srcpad created");
 }
 
-static void
-gst_wavparse_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
+/* Compute (value * nom) % denom, avoiding overflow.  This can be used
+ * to perform ceiling or rounding division together with
+ * gst_util_uint64_scale[_int]. */
+#define uint64_scale_modulo(val, nom, denom) \
+  ((val % denom) * (nom % denom) % denom)
+
+/* Like gst_util_uint64_scale, but performs ceiling division. */
+static guint64
+uint64_ceiling_scale_int (guint64 val, gint num, gint denom)
 {
-  GstWavParse *wavparse;
+  guint64 result = gst_util_uint64_scale_int (val, num, denom);
 
-  wavparse = GST_WAVPARSE (object);
+  if (uint64_scale_modulo (val, num, denom) == 0)
+    return result;
+  else
+    return result + 1;
+}
 
-  switch (prop_id) {
-    default:
-      break;
-  }
+/* Like gst_util_uint64_scale, but performs ceiling division. */
+static guint64
+uint64_ceiling_scale (guint64 val, guint64 num, guint64 denom)
+{
+  guint64 result = gst_util_uint64_scale (val, num, denom);
+
+  if (uint64_scale_modulo (val, num, denom) == 0)
+    return result;
+  else
+    return result + 1;
 }
 
 
-
+/* FIXME: why is that not in use? */
 #if 0
 static void
 gst_wavparse_parse_adtl (GstWavParse * wavparse, int len)
@@ -581,52 +521,68 @@
   gst_riff_strf_auds *header = NULL;
   GstCaps *caps;
 
-  if (!gst_riff_read_strf_auds (wav, &header)) {
-    g_warning ("Not fmt");
-    return FALSE;
-  }
+  if (!gst_riff_read_strf_auds (wav, &header))
+    goto no_fmt;
 
   wav->format = header->format;
   wav->rate = header->rate;
   wav->channels = header->channels;
-  if (wav->channels == 0) {
+  if (wav->channels == 0)
+    goto no_channels;
+
+  wav->blockalign = header->blockalign;
+  wav->width = (header->blockalign * 8) / header->channels;
+  wav->depth = header->size;
+  wav->bps = header->av_bps;
+  if (wav->bps <= 0)
+    goto no_bps;
+
+  /* Note: gst_riff_create_audio_caps might need to fix values in
+   * the header header depending on the format, so call it first */
+  caps = gst_riff_create_audio_caps (header->format, NULL, header, NULL);
+  g_free (header);
+
+  if (caps == NULL)
+    goto no_caps;
+
+  gst_wavparse_create_sourcepad (wav);
+  gst_pad_use_fixed_caps (wav->srcpad);
+  gst_pad_set_active (wav->srcpad, TRUE);
+  gst_pad_set_caps (wav->srcpad, caps);
+  gst_caps_free (caps);
+  gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
+  gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
+
+  GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
+
+  return TRUE;
+
+  /* ERRORS */
+no_fmt:
+  {
+    GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
+        ("No FMT tag found"));
+    return FALSE;
+  }
+no_channels:
+  {
     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
         ("Stream claims to contain zero channels - invalid data"));
     g_free (header);
     return FALSE;
   }
-  wav->blockalign = header->blockalign;
-  wav->width = (header->blockalign * 8) / header->channels;
-  wav->depth = header->size;
-  wav->bps = header->av_bps;
-  if (wav->bps <= 0) {
+no_bps:
+  {
     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
         ("Stream claims to bitrate of <= zero - invalid data"));
     g_free (header);
     return FALSE;
   }
-
-  /* Note: gst_riff_create_audio_caps might nedd to fix values in
-   * the header header depending on the format, so call it first */
-  caps = gst_riff_create_audio_caps (header->format, NULL, header, NULL);
-
-  g_free (header);
-
-  if (caps) {
-    gst_wavparse_create_sourcepad (wav);
-    gst_pad_use_fixed_caps (wav->srcpad);
-    gst_pad_set_active (wav->srcpad, TRUE);
-    gst_pad_set_caps (wav->srcpad, caps);
-    gst_caps_free (caps);
-    gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad);
-    gst_element_no_more_pads (GST_ELEMENT (wav));
-    GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
-  } else {
+no_caps:
+  {
     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
     return FALSE;
   }
-
-  return TRUE;
 }
 
 static gboolean
@@ -711,7 +667,8 @@
         }
       }
       wav->datasize = (guint64) length;
-      break;
+      GST_DEBUG_OBJECT (wav, "datasize = %ld", length)
+          break;
 
     case GST_RIFF_TAG_cue:
       if (!gst_riff_read_skip (wav)) {
@@ -732,14 +689,13 @@
 #endif
 
 
-
 static gboolean
 gst_wavparse_parse_file_header (GstElement * element, GstBuffer * buf)
 {
   guint32 doctype;
-  
+
   if (!gst_riff_parse_file_header (element, buf, &doctype))
-   return FALSE;
+    return FALSE;
 
   if (doctype != GST_RIFF_RIFF_WAVE)
     goto not_wav;
@@ -748,10 +704,9 @@
 
   /* ERRORS */
 not_wav:
-
   {
     GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
-        ("File is not an WAVE file: %" GST_FOURCC_FORMAT,
+        ("File is not a WAVE file: %" GST_FOURCC_FORMAT,
             GST_FOURCC_ARGS (doctype)));
     return FALSE;
   }
@@ -763,14 +718,10 @@
   GstFlowReturn res;
   GstBuffer *buf = NULL;
 
-  
   if ((res = gst_pad_pull_range (wav->sinkpad,
               wav->offset, 12, &buf)) != GST_FLOW_OK)
-      {
- 
     return res;
-      }
-  else if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), buf))
+  else if (!gst_wavparse_parse_file_header (GST_ELEMENT_CAST (wav), buf))
     return GST_FLOW_ERROR;
 
   wav->offset += 12;
@@ -778,8 +729,35 @@
   return GST_FLOW_OK;
 }
 
-/* This function is used to perform seeks on the element in 
- * pull mode.
+static gboolean
+gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos)
+{
+  /* -1 always maps to -1 */
+  if (ts == -1) {
+    *bytepos = -1;
+    return TRUE;
+  }
+
+  /* 0 always maps to 0 */
+  if (ts == 0) {
+    *bytepos = 0;
+    return TRUE;
+  }
+
+  if (wav->bps > 0) {
+    *bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND);
+    return TRUE;
+  } else if (wav->fact) {
+    guint64 bps =
+        gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
+    *bytepos = uint64_ceiling_scale (ts, bps, GST_SECOND);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/* This function is used to perform seeks on the element.
  *
  * It also works when event is NULL, in which case it will just
  * start from the last configured segment. This technique is
@@ -791,14 +769,14 @@
 {
   gboolean res;
   gdouble rate;
-  GstEvent *newsegment;
-  GstFormat format;
+  GstFormat format, bformat;
   GstSeekFlags flags;
-  GstSeekType cur_type, stop_type;
-  gint64 cur, stop;
+  GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
+  gint64 cur, stop, upstream_size;
   gboolean flush;
   gboolean update;
-  GstSegment seeksegment;
+  GstSegment seeksegment = { 0, };
+  gint64 last_stop;
 
   if (event) {
     GST_DEBUG_OBJECT (wav, "doing seek with event");
@@ -806,116 +784,221 @@
     gst_event_parse_seek (event, &rate, &format, &flags,
         &cur_type, &cur, &stop_type, &stop);
 
-    /* we have to have a format as the segment format. Try to convert
-     * if not. */
-    if (format != GST_FORMAT_TIME) {
-      GstFormat fmt;
+    /* no negative rates yet */
+    if (rate < 0.0)
+      goto negative_rate;
 
-      fmt = GST_FORMAT_TIME;
+    if (format != wav->segment.format) {
+      GST_INFO_OBJECT (wav, "converting seek-event from %s to %s",
+          gst_format_get_name (format),
+          gst_format_get_name (wav->segment.format));
       res = TRUE;
       if (cur_type != GST_SEEK_TYPE_NONE)
-        res = gst_pad_query_convert (wav->srcpad, format, cur, &fmt, &cur);
+        res =
+            gst_pad_query_convert (wav->srcpad, format, cur,
+            &wav->segment.format, &cur);
       if (res && stop_type != GST_SEEK_TYPE_NONE)
-        res = gst_pad_query_convert (wav->srcpad, format, stop, &fmt, &stop);
+        res =
+            gst_pad_query_convert (wav->srcpad, format, stop,
+            &wav->segment.format, &stop);
       if (!res)
         goto no_format;
 
-      format = fmt;
+      format = wav->segment.format;
     }
   } else {
     GST_DEBUG_OBJECT (wav, "doing seek without event");
     flags = 0;
+    rate = 1.0;
+    cur_type = GST_SEEK_TYPE_SET;
+    stop_type = GST_SEEK_TYPE_SET;
   }
 
+  /* in push mode, we must delegate to upstream */
+  if (wav->streaming) {
+    gboolean res = FALSE;
+
+    /* if streaming not yet started; only prepare initial newsegment */
+    if (!event || wav->state != GST_WAVPARSE_DATA) {
+      if (wav->start_segment)
+        gst_event_unref (wav->start_segment);
+      wav->start_segment =
+          gst_event_new_new_segment (FALSE, wav->segment.rate,
+          wav->segment.format, wav->segment.last_stop, wav->segment.duration,
+          wav->segment.last_stop);
+      res = TRUE;
+    } else {
+      /* convert seek positions to byte positions in data sections */
+      if (format == GST_FORMAT_TIME) {
+        /* should not fail */
+        if (!gst_wavparse_time_to_bytepos (wav, cur, &cur))
+          goto no_position;
+        if (!gst_wavparse_time_to_bytepos (wav, stop, &stop))
+          goto no_position;
+      }
+      /* mind sample boundary and header */
+      if (cur >= 0) {
+        cur -= (cur % wav->bytes_per_sample);
+        cur += wav->datastart;
+      }
+      if (stop >= 0) {
+        stop -= (stop % wav->bytes_per_sample);
+        stop += wav->datastart;
+      }
+      GST_DEBUG_OBJECT (wav, "Pushing BYTE seek rate %g, "
+          "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur,
+          stop);
+      /* BYTE seek event */
+      event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
+          stop_type, stop);
+      res = gst_pad_push_event (wav->sinkpad, event);
+    }
+    return res;
+  }
+
+  /* get flush flag */
   flush = flags & GST_SEEK_FLAG_FLUSH;
 
-  if (flush && wav->srcpad) {
-    GST_DEBUG_OBJECT (wav, "sending flush start");
-    gst_pad_push_event (wav->srcpad, gst_event_new_flush_start ());
+  /* now we need to make sure the streaming thread is stopped. We do this by
+   * either sending a FLUSH_START event downstream which will cause the
+   * streaming thread to stop with a WRONG_STATE.
+   * For a non-flushing seek we simply pause the task, which will happen as soon
+   * as it completes one iteration (and thus might block when the sink is
+   * blocking in preroll). */
+  if (flush) {
+    if (wav->srcpad) {
+      GST_DEBUG_OBJECT (wav, "sending flush start");
+      gst_pad_push_event (wav->srcpad, gst_event_new_flush_start ());
+    }
   } else {
     gst_pad_pause_task (wav->sinkpad);
   }
 
+  /* we should now be able to grab the streaming thread because we stopped it
+   * with the above flush/pause code */
   GST_PAD_STREAM_LOCK (wav->sinkpad);
 
+  /* save current position */
+  last_stop = wav->segment.last_stop;
+
+  GST_DEBUG_OBJECT (wav, "stopped streaming at %" G_GINT64_FORMAT, last_stop);
+
   /* copy segment, we need this because we still need the old
    * segment when we close the current segment. */
   memcpy (&seeksegment, &wav->segment, sizeof (GstSegment));
 
+  /* configure the seek parameters in the seeksegment. We will then have the
+   * right values in the segment to perform the seek */
   if (event) {
     GST_DEBUG_OBJECT (wav, "configuring seek");
     gst_segment_set_seek (&seeksegment, rate, format, flags,
         cur_type, cur, stop_type, stop, &update);
   }
 
+  /* figure out the last position we need to play. If it's configured (stop !=
+   * -1), use that, else we play until the total duration of the file */
   if ((stop = seeksegment.stop) == -1)
     stop = seeksegment.duration;
 
-  if (cur_type != GST_SEEK_TYPE_NONE) {
-    wav->offset =
-        gst_util_uint64_scale_int (seeksegment.last_stop, wav->bps, GST_SECOND);
-    wav->offset -= wav->offset % wav->bytes_per_sample;
+  GST_DEBUG_OBJECT (wav, "cur_type =%d", cur_type);
+  if ((cur_type != GST_SEEK_TYPE_NONE)) {
+    /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
+     * we can just copy the last_stop. If not, we use the bps to convert TIME to
+     * bytes. */
+    if (!gst_wavparse_time_to_bytepos (wav, seeksegment.last_stop,
+            (gint64 *) & wav->offset))
+      wav->offset = seeksegment.last_stop;
+    GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
+    wav->offset -= (wav->offset % wav->bytes_per_sample);
+    GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
     wav->offset += wav->datastart;
+    GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
+  } else {
+    GST_LOG_OBJECT (wav, "continue from offset=%" G_GUINT64_FORMAT,
+        wav->offset);
   }
 
-  if (stop != -1) {
-    wav->end_offset = gst_util_uint64_scale_int (stop, wav->bps, GST_SECOND);
-    wav->end_offset +=
-        wav->bytes_per_sample - (wav->end_offset % wav->bytes_per_sample);
+  if (stop_type != GST_SEEK_TYPE_NONE) {
+    if (!gst_wavparse_time_to_bytepos (wav, stop, (gint64 *) & wav->end_offset))
+      wav->end_offset = stop;
+    GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
+    wav->end_offset -= (wav->end_offset % wav->bytes_per_sample);
+    GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
     wav->end_offset += wav->datastart;
+    GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
   } else {
-    wav->end_offset = wav->datasize + wav->datastart;
+    GST_LOG_OBJECT (wav, "continue to end_offset=%" G_GUINT64_FORMAT,
+        wav->end_offset);
   }
+
+  /* make sure filesize is not exceeded due to rounding errors or so,
+   * same precaution as in _stream_headers */
+  bformat = GST_FORMAT_BYTES;
+  if (gst_pad_query_peer_duration (wav->sinkpad, &bformat, &upstream_size))
+    wav->end_offset = MIN (wav->end_offset, upstream_size);
+
+  /* this is the range of bytes we will use for playback */
   wav->offset = MIN (wav->offset, wav->end_offset);
   wav->dataleft = wav->end_offset - wav->offset;
 
   GST_DEBUG_OBJECT (wav,
-      "seek: offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT ", segment %"
-      GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, wav->offset, wav->end_offset,
-      GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (stop));
+      "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
+      ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, wav->offset,
+      wav->end_offset, GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (stop));
 
   /* prepare for streaming again */
   if (wav->srcpad) {
     if (flush) {
+      /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
       GST_DEBUG_OBJECT (wav, "sending flush stop");
       gst_pad_push_event (wav->srcpad, gst_event_new_flush_stop ());
     } else if (wav->segment_running) {
       /* we are running the current segment and doing a non-flushing seek,
-       * close the segment first based on the last_stop. */
+       * close the segment first based on the previous last_stop. */
       GST_DEBUG_OBJECT (wav, "closing running segment %" G_GINT64_FORMAT
-          " to %" G_GINT64_FORMAT, wav->segment.start, wav->segment.last_stop);
+          " to %" G_GINT64_FORMAT, wav->segment.accum, wav->segment.last_stop);
 
-      gst_pad_push_event (wav->srcpad,
-          gst_event_new_new_segment (TRUE,
-              wav->segment.rate, wav->segment.format,
-              wav->segment.start, wav->segment.last_stop, wav->segment.time));
+      /* queue the segment for sending in the stream thread */
+      if (wav->close_segment)
+        gst_event_unref (wav->close_segment);
+      wav->close_segment = gst_event_new_new_segment (TRUE,
+          wav->segment.rate, wav->segment.format,
+          wav->segment.accum, wav->segment.last_stop, wav->segment.accum);
+
+      /* keep track of our last_stop */
+      seeksegment.accum = wav->segment.last_stop;
     }
   }
 
+  /* now we did the seek and can activate the new segment values */
   memcpy (&wav->segment, &seeksegment, sizeof (GstSegment));
 
+  /* if we're doing a segment seek, post a SEGMENT_START message */
   if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
-    gst_element_post_message (GST_ELEMENT (wav),
-        gst_message_new_segment_start (GST_OBJECT (wav),
+    gst_element_post_message (GST_ELEMENT_CAST (wav),
+        gst_message_new_segment_start (GST_OBJECT_CAST (wav),
             wav->segment.format, wav->segment.last_stop));
   }
 
-  /* now send the newsegment */
-  GST_DEBUG_OBJECT (wav, "Sending newsegment from %" G_GINT64_FORMAT
-      " to %" G_GINT64_FORMAT, wav->segment.start, stop);
+  /* now create the newsegment */
+  GST_DEBUG_OBJECT (wav, "Creating newsegment from %" G_GINT64_FORMAT
+      " to %" G_GINT64_FORMAT, wav->segment.last_stop, stop);
 
-  newsegment =
+  /* store the newsegment event so it can be sent from the streaming thread. */
+  if (wav->start_segment)
+    gst_event_unref (wav->start_segment);
+  wav->start_segment =
       gst_event_new_new_segment (FALSE, wav->segment.rate,
-      wav->segment.format, wav->segment.last_stop, stop, wav->segment.time);
+      wav->segment.format, wav->segment.last_stop, stop,
+      wav->segment.last_stop);
 
-  if (wav->srcpad) {
-    gst_pad_push_event (wav->srcpad, newsegment);
-  } else {
-    /* send later when we actually create the source pad */
-    g_assert (wav->newsegment == NULL);
-    wav->newsegment = newsegment;
+  /* mark discont if we are going to stream from another position. */
+  if (last_stop != wav->segment.last_stop) {
+    GST_DEBUG_OBJECT (wav, "mark DISCONT, we did a seek to another position");
+    wav->discont = TRUE;
   }
 
+  /* and start the streaming task again */
   wav->segment_running = TRUE;
   if (!wav->streaming) {
     gst_pad_start_task (wav->sinkpad, (GstTaskFunction) gst_wavparse_loop,
@@ -927,11 +1010,22 @@
   return TRUE;
 
   /* ERRORS */
+negative_rate:
+  {
+    GST_DEBUG_OBJECT (wav, "negative playback rates are not supported yet.");
+    return FALSE;
+  }
 no_format:
   {
     GST_DEBUG_OBJECT (wav, "unsupported format given, seek aborted.");
     return FALSE;
   }
+no_position:
+  {
+    GST_DEBUG_OBJECT (wav,
+        "Could not determine byte position for desired time");
+    return FALSE;
+  }
 }
 
 /*
@@ -939,25 +1033,26 @@
  * @wav Wavparse object
  * @tag holder for tag
  * @size holder for tag size
- *                         
- * Peek next chunk info (tag and size)                         
  *
- * Returns: %TRUE when one chunk info has been got from the adapter
+ * Peek next chunk info (tag and size)
+ *
+ * Returns: %TRUE when the chunk info (header) is available
  */
 static gboolean
 gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
 {
   const guint8 *data = NULL;
 
-  if (gst_adapter_available (wav->adapter) < 8) {
+  if (gst_adapter_available (wav->adapter) < 8)
     return FALSE;
-  }
 
-  GST_DEBUG ("Next chunk size is %d bytes", *size);
   data = gst_adapter_peek (wav->adapter, 8);
   *tag = GST_READ_UINT32_LE (data);
   *size = GST_READ_UINT32_LE (data + 4);
 
+  GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
+      GST_FOURCC_ARGS (*tag));
+
   return TRUE;
 }
 
@@ -969,37 +1064,79 @@
  *
  * Peek enough data for one full chunk
  *
- * Returns: %TRUE when one chunk has been got
+ * Returns: %TRUE when the full chunk is available
  */
 static gboolean
 gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
 {
   guint32 peek_size = 0;
+  guint available;
 
-  gst_wavparse_peek_chunk_info (wav, tag, size);
+  if (!gst_wavparse_peek_chunk_info (wav, tag, size))
+    return FALSE;
+
   GST_DEBUG ("Need to peek chunk of %d bytes", *size);
   peek_size = (*size + 1) & ~1;
 
-  if (gst_adapter_available (wav->adapter) >= (8 + peek_size)) {
+  available = gst_adapter_available (wav->adapter);
+  if (available >= (8 + peek_size)) {
     return TRUE;
   } else {
+    GST_LOG ("but only %u bytes available now", available);
     return FALSE;
   }
 }
 
+/*
+ * gst_wavparse_calculate_duration:
+ * @wav: wavparse object
+ *
+ * Calculate duration on demand and store in @wav. Prefer bps, but use fact as a
+ * fallback.
+ *
+ * Returns: %TRUE if duration is available.
+ */
 static gboolean
-gst_wavparse_get_upstream_size (GstWavParse * wav, gint64 * len)
+gst_wavparse_calculate_duration (GstWavParse * wav)
 {
-  gboolean res = FALSE;
-  GstFormat fmt = GST_FORMAT_BYTES;
-  GstPad *peer;
+  if (wav->duration > 0)
+    return TRUE;
 
-  if ((peer = gst_pad_get_peer (wav->sinkpad))) {
-    res = gst_pad_query_duration (peer, &fmt, len);
-    gst_object_unref (peer);
+  if (wav->bps > 0) {
+    GST_INFO_OBJECT (wav, "Got datasize %" G_GUINT64_FORMAT, wav->datasize);
+    wav->duration =
+        uint64_ceiling_scale (wav->datasize, GST_SECOND, (guint64) wav->bps);
+    GST_INFO_OBJECT (wav, "Got duration (bps) %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (wav->duration));
+    return TRUE;
+  } else if (wav->fact) {
+    wav->duration = uint64_ceiling_scale_int (GST_SECOND, wav->fact, wav->rate);
+    GST_INFO_OBJECT (wav, "Got duration (fact) %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (wav->duration));
+    return TRUE;
   }
+  return FALSE;
+}
 
-  return res;
+static void
+gst_waveparse_ignore_chunk (GstWavParse * wav, GstBuffer * buf, guint32 tag,
+    guint32 size)
+{
+  guint flush;
+
+  if (wav->streaming) {
+    if (!gst_wavparse_peek_chunk (wav, &tag, &size))
+      return;
+  }
+  GST_DEBUG_OBJECT (wav, "Ignoring tag %" GST_FOURCC_FORMAT,
+      GST_FOURCC_ARGS (tag));
+  flush = 8 + ((size + 1) & ~1);
+  wav->offset += flush;
+  if (wav->streaming) {
+    gst_adapter_flush (wav->adapter, flush);
+  } else {
+    gst_buffer_unref (buf);
+  }
 }
 
 static GstFlowReturn
@@ -1011,84 +1148,126 @@
   guint32 tag, size;
   gboolean gotdata = FALSE;
   GstCaps *caps;
-  gint64 duration;
   gchar *codec_name = NULL;
   GstEvent **event_p;
+  GstFormat bformat;
+  gint64 upstream_size = 0;
 
-  
-  if (!wav->got_fmt) {
+  /* search for "_fmt" chunk, which should be first */
+  while (!wav->got_fmt) {
     GstBuffer *extra;
 
-    /* The header start with a 'fmt ' tag */
-
+    /* The header starts with a 'fmt ' tag */
     if (wav->streaming) {
       if (!gst_wavparse_peek_chunk (wav, &tag, &size))
         return GST_FLOW_OK;
 
-      buf = gst_buffer_new ();
-      gst_buffer_ref (buf);
       gst_adapter_flush (wav->adapter, 8);
       wav->offset += 8;
-      GST_BUFFER_DATA (buf) = (guint8 *) gst_adapter_peek (wav->adapter, size);
-      GST_BUFFER_SIZE (buf) = size;
 
+      buf = gst_adapter_take_buffer (wav->adapter, size);
     } else {
-      if ((res = gst_riff_read_chunk (GST_ELEMENT (wav), wav->sinkpad,
+      if ((res = gst_riff_read_chunk (GST_ELEMENT_CAST (wav), wav->sinkpad,
                   &wav->offset, &tag, &buf)) != GST_FLOW_OK)
         return res;
     }
 
+    if (tag == GST_RIFF_TAG_JUNK || tag == GST_RIFF_TAG_bext ||
+        tag == GST_RIFF_TAG_BEXT || tag == GST_RIFF_TAG_LIST) {
+      GST_DEBUG_OBJECT (wav, "skipping %" GST_FOURCC_FORMAT " chunk",
+          GST_FOURCC_ARGS (tag));
+      gst_buffer_unref (buf);
+      buf = NULL;
+      continue;
+    }
+
     if (tag != GST_RIFF_TAG_fmt)
       goto invalid_wav;
 
-    if (!(gst_riff_parse_strf_auds (GST_ELEMENT (wav), buf, &header, &extra)))
+    if (!(gst_riff_parse_strf_auds (GST_ELEMENT_CAST (wav), buf, &header,
+                &extra)))
       goto parse_header_error;
 
-    if (wav->streaming) {
-      gst_adapter_flush (wav->adapter, size);
-      wav->offset += size;
-      GST_BUFFER_DATA (buf) = NULL;
-      gst_buffer_unref (buf);
-    }
+    buf = NULL;                 /* parse_strf_auds() took ownership of buffer */
 
-    /* Note: gst_riff_create_audio_caps might nedd to fix values in
+    /* do sanity checks of header fields */
+    if (header->channels == 0)
+      goto no_channels;
+    if (header->rate == 0)
+      goto no_rate;
+
+    GST_DEBUG_OBJECT (wav, "creating the caps");
+
+    /* Note: gst_riff_create_audio_caps might need to fix values in
      * the header header depending on the format, so call it first */
-    caps =
-        gst_riff_create_audio_caps (header->format, NULL, header, extra,
+    caps = gst_riff_create_audio_caps (header->format, NULL, header, extra,
         NULL, &codec_name);
 
     if (extra)
       gst_buffer_unref (extra);
 
+    if (!caps)
+      goto unknown_format;
+
+    /* do more sanity checks of header fields
+     * (these can be sanitized by gst_riff_create_audio_caps()
+     */
     wav->format = header->format;
     wav->rate = header->rate;
     wav->channels = header->channels;
-
-    if (wav->channels == 0)
-      goto no_channels;
-
     wav->blockalign = header->blockalign;
-    wav->width = (header->blockalign * 8) / header->channels;
     wav->depth = header->size;
-    wav->bps = header->av_bps;
+    wav->av_bps = header->av_bps;
+    wav->vbr = FALSE;
+
+    g_free (header);
+    header = NULL;
 
-    if (wav->bps <= 0)
-      goto no_bitrate;
+    /* do format specific handling */
+    switch (wav->format) {
+      case GST_RIFF_WAVE_FORMAT_MPEGL12:
+      case GST_RIFF_WAVE_FORMAT_MPEGL3:
+      {
+        /* Note: workaround for mp2/mp3 embedded in wav, that relies on the
+         * bitrate inside the mpeg stream */
+        GST_INFO ("resetting bps from %d to 0 for mp2/3", wav->av_bps);
+        wav->bps = 0;
+        break;
+      }
+      case GST_RIFF_WAVE_FORMAT_PCM:
+        if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0))
+          goto invalid_blockalign;
+        /* fall through */
+      default:
+        if (wav->av_bps > wav->blockalign * wav->rate)
+          goto invalid_bps;
+        /* use the configured bps */
+        wav->bps = wav->av_bps;
+        break;
+    }
 
+    wav->width = (wav->blockalign * 8) / wav->channels;
     wav->bytes_per_sample = wav->channels * wav->width / 8;
+
     if (wav->bytes_per_sample <= 0)
       goto no_bytes_per_sample;
 
-    g_free (header);
-
-    if (!caps)
-      goto unknown_format;
-
     GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
     GST_DEBUG_OBJECT (wav, "width      = %u", (guint) wav->width);
     GST_DEBUG_OBJECT (wav, "depth      = %u", (guint) wav->depth);
+    GST_DEBUG_OBJECT (wav, "av_bps     = %u", (guint) wav->av_bps);
+    GST_DEBUG_OBJECT (wav, "frequency  = %u", (guint) wav->rate);
+    GST_DEBUG_OBJECT (wav, "channels   = %u", (guint) wav->channels);
+    GST_DEBUG_OBJECT (wav, "bytes_per_sample = %u", wav->bytes_per_sample);
+
+    /* bps can be 0 when we don't have a valid bitrate (mostly for compressed
+     * formats). This will make the element output a BYTE format segment and
+     * will not timestamp the outgoing buffers.
+     */
     GST_DEBUG_OBJECT (wav, "bps        = %u", (guint) wav->bps);
 
+    GST_DEBUG_OBJECT (wav, "caps = %" GST_PTR_FORMAT, caps);
+
     /* create pad later so we can sniff the first few bytes
      * of the real data and correct our caps if necessary */
     gst_caps_replace (&wav->caps, caps);
@@ -1106,10 +1285,12 @@
       codec_name = NULL;
     }
 
-    GST_DEBUG_OBJECT (wav, "frequency %d, channels %d", wav->rate,
-        wav->channels);
   }
 
+  bformat = GST_FORMAT_BYTES;
+  gst_pad_query_peer_duration (wav->sinkpad, &bformat, &upstream_size);
+  GST_DEBUG_OBJECT (wav, "upstream size %" G_GUINT64_FORMAT, upstream_size);
+
   /* loop headers until we get data */
   while (!gotdata) {
     if (wav->streaming) {
@@ -1124,56 +1305,208 @@
       size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
     }
 
-    /*
-       wav is a st00pid format, we don't know for sure where data starts.
-       So we have to go bit by bit until we find the 'data' header
+    GST_INFO_OBJECT (wav,
+        "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
+        GST_FOURCC_ARGS (tag), wav->offset);
+
+    /* wav is a st00pid format, we don't know for sure where data starts.
+     * So we have to go bit by bit until we find the 'data' header
      */
-
     switch (tag) {
-        /* TODO : Implement the various cases */
       case GST_RIFF_TAG_data:{
-        gint64 upstream_size;
-
         GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
-        gotdata = TRUE;
         if (wav->streaming) {
           gst_adapter_flush (wav->adapter, 8);
+          gotdata = TRUE;
         } else {
           gst_buffer_unref (buf);
         }
         wav->offset += 8;
         wav->datastart = wav->offset;
         /* file might be truncated */
-        if (gst_wavparse_get_upstream_size (wav, &upstream_size)) {
+        if (upstream_size) {
           size = MIN (size, (upstream_size - wav->datastart));
         }
-        wav->datasize = size;
-        wav->dataleft = size;
+        wav->datasize = (guint64) size;
+        wav->dataleft = (guint64) size;
         wav->end_offset = size + wav->datastart;
+        if (!wav->streaming) {
+          /* We will continue parsing tags 'till end */
+          wav->offset += size;
+        }
+        GST_DEBUG_OBJECT (wav, "datasize = %d", size);
+        break;
+      }
+      case GST_RIFF_TAG_fact:{
+        if (wav->format != GST_RIFF_WAVE_FORMAT_MPEGL12 &&
+            wav->format != GST_RIFF_WAVE_FORMAT_MPEGL3) {
+          const guint data_size = 4;
+
+          /* number of samples (for compressed formats) */
+          if (wav->streaming) {
+            const guint8 *data = NULL;
+
+            if (gst_adapter_available (wav->adapter) < 8 + data_size) {
+              return GST_FLOW_OK;
+            }
+            gst_adapter_flush (wav->adapter, 8);
+            data = gst_adapter_peek (wav->adapter, data_size);
+            wav->fact = GST_READ_UINT32_LE (data);
+            gst_adapter_flush (wav->adapter, data_size);
+          } else {
+            gst_buffer_unref (buf);
+            if ((res =
+                    gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
+                        data_size, &buf)) != GST_FLOW_OK)
+              goto header_read_error;
+            wav->fact = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
+            gst_buffer_unref (buf);
+          }
+          GST_DEBUG_OBJECT (wav, "have fact %u", wav->fact);
+          wav->offset += 8 + data_size;
+          break;
+        } else {
+          gst_waveparse_ignore_chunk (wav, buf, tag, size);
+        }
+        break;
+      }
+      case GST_RIFF_TAG_acid:{
+        const gst_riff_acid *acid = NULL;
+        const guint data_size = sizeof (gst_riff_acid);
+
+        if (wav->streaming) {
+          if (gst_adapter_available (wav->adapter) < 8 + data_size) {
+            return GST_FLOW_OK;
+          }
+          gst_adapter_flush (wav->adapter, 8);
+          acid = (const gst_riff_acid *) gst_adapter_peek (wav->adapter,
+              data_size);
+        } else {
+          gst_buffer_unref (buf);
+          if ((res =
+                  gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
+                      data_size, &buf)) != GST_FLOW_OK)
+            goto header_read_error;
+          acid = (const gst_riff_acid *) GST_BUFFER_DATA (buf);
+        }
+        GST_INFO_OBJECT (wav, "Have acid chunk");
+        /* send data as tags */
+        if (!wav->tags)
+          wav->tags = gst_tag_list_new ();
+        gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
+            GST_TAG_BEATS_PER_MINUTE, acid->tempo, NULL);
+
+        if (wav->streaming) {
+          gst_adapter_flush (wav->adapter, data_size);
+        } else {
+          gst_buffer_unref (buf);
+          wav->offset += 8 + data_size;
+        }
+        break;
+      }
+        /* FIXME: all list tags after data are ignored in streaming mode */
+      case GST_RIFF_TAG_LIST:{
+        guint32 ltag;
+
+        if (wav->streaming) {
+          const guint8 *data = NULL;
+
+          if (gst_adapter_available (wav->adapter) < 12) {
+            return GST_FLOW_OK;
+          }
+          data = gst_adapter_peek (wav->adapter, 12);
+          ltag = GST_READ_UINT32_LE (data + 8);
+        } else {
+          gst_buffer_unref (buf);
+          if ((res =
+                  gst_pad_pull_range (wav->sinkpad, wav->offset, 12,
+                      &buf)) != GST_FLOW_OK)
+            goto header_read_error;
+          ltag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 8);
+        }
+        switch (ltag) {
+          case GST_RIFF_LIST_INFO:{
+            const guint data_size = size - 4;
+            GstTagList *new;
+
+            GST_INFO_OBJECT (wav, "Have LIST chunk INFO size %u", data_size);
+            if (wav->streaming) {
+              gst_adapter_flush (wav->adapter, 12);
+              if (gst_adapter_available (wav->adapter) < data_size) {
+                return GST_FLOW_OK;
+              }
+              gst_buffer_unref (buf);
+              if (data_size > 0)
+                buf = gst_adapter_take_buffer (wav->adapter, data_size);
+            } else {
+              wav->offset += 12;
+              gst_buffer_unref (buf);
+              if (data_size > 0) {
+                if ((res =
+                        gst_pad_pull_range (wav->sinkpad, wav->offset,
+                            data_size, &buf)) != GST_FLOW_OK)
+                  goto header_read_error;
+              }
+            }
+            if (data_size > 0) {
+              /* parse tags */
+              gst_riff_parse_info (GST_ELEMENT (wav), buf, &new);
+              if (new) {
+                GstTagList *old = wav->tags;
+                wav->tags =
+                    gst_tag_list_merge (old, new, GST_TAG_MERGE_REPLACE);
+                if (old)
+                  gst_tag_list_free (old);
+                gst_tag_list_free (new);
+              }
+              if (wav->streaming) {
+                gst_adapter_flush (wav->adapter, data_size);
+              } else {
+                gst_buffer_unref (buf);
+                wav->offset += data_size;
+              }
+            }
+            break;
+          }
+          default:
+            GST_INFO_OBJECT (wav, "Ignoring LIST chunk %" GST_FOURCC_FORMAT,
+                GST_FOURCC_ARGS (ltag));
+            gst_waveparse_ignore_chunk (wav, buf, tag, size);
+            break;
+        }
         break;
       }
       default:
-        if (wav->streaming) {
-          if (!gst_wavparse_peek_chunk (wav, &tag, &size))
-            return GST_FLOW_OK;
-        }
-        GST_DEBUG_OBJECT (wav, "Ignoring tag %" GST_FOURCC_FORMAT,
-            GST_FOURCC_ARGS (tag));
-        wav->offset += 8 + ((size + 1) & ~1);
-        if (wav->streaming) {
-          gst_adapter_flush (wav->adapter, 8 + ((size + 1) & ~1));
-        } else {
-          gst_buffer_unref (buf);
-        }
+        gst_waveparse_ignore_chunk (wav, buf, tag, size);
+    }
+
+    if (upstream_size && (wav->offset >= upstream_size)) {
+      /* Now we are gone through the whole file */
+      gotdata = TRUE;
     }
   }
 
   GST_DEBUG_OBJECT (wav, "Finished parsing headers");
 
-  duration = gst_util_uint64_scale_int (wav->datasize, GST_SECOND, wav->bps);
-  GST_DEBUG_OBJECT (wav, "Got duration %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (duration));
-  gst_segment_set_duration (&wav->segment, GST_FORMAT_TIME, duration);
+  if (wav->bps <= 0 && wav->fact) {
+#if 0
+    /* not a good idea, as for embedded mp2/mp3 we set bps to 0 earlier */
+    wav->bps =
+        (guint32) gst_util_uint64_scale ((guint64) wav->rate, wav->datasize,
+        (guint64) wav->fact);
+    GST_INFO_OBJECT (wav, "calculated bps : %d, enabling VBR", wav->bps);
+#endif
+    wav->vbr = TRUE;
+  }
+
+  if (gst_wavparse_calculate_duration (wav)) {
+    gst_segment_init (&wav->segment, GST_FORMAT_TIME);
+    gst_segment_set_duration (&wav->segment, GST_FORMAT_TIME, wav->duration);
+  } else {
+    /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
+    gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
+    gst_segment_set_duration (&wav->segment, GST_FORMAT_BYTES, wav->datasize);
+  }
 
   /* now we have all the info to perform a pending seek if any, if no
    * event, this will still do the right thing and it will also send
@@ -1183,6 +1516,9 @@
   event_p = &wav->seek_event;
   gst_event_replace (event_p, NULL);
 
+  /* we just started, we are discont */
+  wav->discont = TRUE;
+
   wav->state = GST_WAVPARSE_DATA;
 
   return GST_FLOW_OK;
@@ -1190,20 +1526,17 @@
   /* ERROR */
 invalid_wav:
   {
-    GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
+    GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
         ("Invalid WAV header (no fmt at start): %"
             GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
     g_free (codec_name);
-
     return GST_FLOW_ERROR;
   }
 parse_header_error:
   {
     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
         ("Couldn't parse audio header"));
-    gst_buffer_unref (buf);
     g_free (codec_name);
- 
     return GST_FLOW_ERROR;
   }
 no_channels:
@@ -1214,19 +1547,34 @@
     g_free (codec_name);
     return GST_FLOW_ERROR;
   }
-no_bitrate:
+no_rate:
+  {
+    GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
+        ("Stream with sample_rate == 0 - invalid data"));
+    g_free (header);
+    g_free (codec_name);
+    return GST_FLOW_ERROR;
+  }
+invalid_blockalign:
   {
     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
-        ("Stream claims to have a bitrate of <= zero - invalid data"));
-    g_free (header);
+        ("Stream claims blockalign = %u, which is more than %u - invalid data",
+            wav->blockalign, wav->channels * (guint) ceil (wav->depth / 8.0)));
+    g_free (codec_name);
+    return GST_FLOW_ERROR;
+  }
+invalid_bps:
+  {
+    GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
+        ("Stream claims av_bsp = %u, which is more than %u - invalid data",
+            wav->av_bps, wav->blockalign * wav->rate));
     g_free (codec_name);
     return GST_FLOW_ERROR;
   }
 no_bytes_per_sample:
   {
     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
-        ("could not caluclate bytes per sample - invalid data"));
-    g_free (header);
+        ("Could not caluclate bytes per sample - invalid data"));
     g_free (codec_name);
     return GST_FLOW_ERROR;
   }
@@ -1235,35 +1583,34 @@
     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
         ("No caps found for format 0x%x, %d channels, %d Hz",
             wav->format, wav->channels, wav->rate));
+    g_free (header);
     g_free (codec_name);
     return GST_FLOW_ERROR;
   }
 header_read_error:
   {
-    GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL), ("Couldn't read in header"));
+    GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
+        ("Couldn't read in header %d (%s)", res, gst_flow_get_name (res)));
     g_free (codec_name);
     return GST_FLOW_ERROR;
   }
 }
 
-
-/*                       
+/*
  * Read WAV file tag when streaming
  */
 static GstFlowReturn
 gst_wavparse_parse_stream_init (GstWavParse * wav)
 {
   if (gst_adapter_available (wav->adapter) >= 12) {
-    GstBuffer *tmp = gst_buffer_new ();
+    GstBuffer *tmp;
 
     /* _take flushes the data */
-    GST_BUFFER_DATA (tmp) = gst_adapter_take (wav->adapter, 12);
-    GST_BUFFER_SIZE (tmp) = 12;
+    tmp = gst_adapter_take_buffer (wav->adapter, 12);
 
     GST_DEBUG ("Parsing wav header");
-    if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), tmp)) {
+    if (!gst_wavparse_parse_file_header (GST_ELEMENT_CAST (wav), tmp))
       return GST_FLOW_ERROR;
-    }
 
     wav->offset += 12;
     /* Go to next state */
@@ -1322,19 +1669,21 @@
   GstStructure *s;
   const guint8 dts_marker[] = { 0xFF, 0x1F, 0x00, 0xE8, 0xF1, 0x07 };
 
-  
-  s = gst_caps_get_structure (wav->caps, 0);
-  if (gst_structure_has_name (s, "audio/x-raw-int") &&
-      GST_BUFFER_SIZE (buf) > 6 &&
-      memcmp (GST_BUFFER_DATA (buf), dts_marker, 6) == 0) {
+  GST_DEBUG_OBJECT (wav, "adding src pad");
+
+  if (wav->caps) {
+    s = gst_caps_get_structure (wav->caps, 0);
+    if (s && gst_structure_has_name (s, "audio/x-raw-int") && buf &&
+        GST_BUFFER_SIZE (buf) > 6 &&
+        memcmp (GST_BUFFER_DATA (buf), dts_marker, 6) == 0) {
 
-    GST_WARNING_OBJECT (wav, "Found DTS marker in file marked as raw PCM");
-    gst_caps_unref (wav->caps);
-    wav->caps = gst_caps_from_string ("audio/x-dts");
+      GST_WARNING_OBJECT (wav, "Found DTS marker in file marked as raw PCM");
+      gst_caps_unref (wav->caps);
+      wav->caps = gst_caps_from_string ("audio/x-dts");
 
-    gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
-        GST_TAG_AUDIO_CODEC, "dts", NULL);
-  
+      gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
+          GST_TAG_AUDIO_CODEC, "dts", NULL);
+    }
   }
 
   gst_wavparse_create_sourcepad (wav);
@@ -1342,21 +1691,25 @@
   gst_pad_set_caps (wav->srcpad, wav->caps);
   gst_caps_replace (&wav->caps, NULL);
 
-  gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad);
-   
-
-  gst_element_no_more_pads (GST_ELEMENT (wav));
+  gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
+  gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
 
-  GST_DEBUG_OBJECT (wav, "Send newsegment event on newpad");
-  gst_pad_push_event (wav->srcpad, wav->newsegment);
-  wav->newsegment = NULL;
+  if (wav->close_segment) {
+    GST_DEBUG_OBJECT (wav, "Send close segment event on newpad");
+    gst_pad_push_event (wav->srcpad, wav->close_segment);
+    wav->close_segment = NULL;
+  }
+  if (wav->start_segment) {
+    GST_DEBUG_OBJECT (wav, "Send start segment event on newpad");
+    gst_pad_push_event (wav->srcpad, wav->start_segment);
+    wav->start_segment = NULL;
+  }
 
-  
   if (wav->tags) {
-    gst_element_found_tags_for_pad (GST_ELEMENT (wav), wav->srcpad, wav->tags);
+    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (wav), wav->srcpad,
+        wav->tags);
     wav->tags = NULL;
   }
-
 }
 
 #define MAX_BUFFER_SIZE 4096
@@ -1367,10 +1720,9 @@
   GstBuffer *buf = NULL;
   GstFlowReturn res = GST_FLOW_OK;
   guint64 desired, obtained;
-  GstClockTime timestamp, next_timestamp;
+  GstClockTime timestamp, next_timestamp, duration;
   guint64 pos, nextpos;
 
- 
 iterate_adapter:
   GST_LOG_OBJECT (wav,
       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
@@ -1384,49 +1736,76 @@
    * amounts of data regardless of the playback rate */
   desired =
       MIN (gst_guint64_to_gdouble (wav->dataleft),
-      MAX_BUFFER_SIZE * ABS (wav->segment.rate));
+      MAX_BUFFER_SIZE * wav->segment.abs_rate);
+
   if (desired >= wav->blockalign && wav->blockalign > 0)
     desired -= (desired % wav->blockalign);
 
-  
   GST_LOG_OBJECT (wav, "Fetching %" G_GINT64_FORMAT " bytes of data "
       "from the sinkpad", desired);
 
   if (wav->streaming) {
     guint avail = gst_adapter_available (wav->adapter);
-     
+    guint extra;
+
+    /* flush some bytes if evil upstream sends segment that starts
+     * before data or does is not send sample aligned segment */
+    if (G_LIKELY (wav->offset >= wav->datastart)) {
+      extra = (wav->offset - wav->datastart) % wav->bytes_per_sample;
+    } else {
+      extra = wav->datastart - wav->offset;
+    }
+
+    if (G_UNLIKELY (extra)) {
+      extra = wav->bytes_per_sample - extra;
+      if (extra <= avail) {
+        GST_DEBUG_OBJECT (wav, "flushing %d bytes to sample boundary", extra);
+        gst_adapter_flush (wav->adapter, extra);
+        wav->offset += extra;
+        wav->dataleft -= extra;
+        goto iterate_adapter;
+      } else {
+        GST_DEBUG_OBJECT (wav, "flushing %d bytes", avail);
+        gst_adapter_clear (wav->adapter);
+        wav->offset += avail;
+        wav->dataleft -= avail;
+        return GST_FLOW_OK;
+      }
+    }
+
     if (avail < desired) {
-   
       GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
       return GST_FLOW_OK;
     }
 
-    buf = gst_buffer_new ();
-    GST_BUFFER_DATA (buf) = gst_adapter_take (wav->adapter, desired);
-    GST_BUFFER_SIZE (buf) = desired;
-
-    
+    buf = gst_adapter_take_buffer (wav->adapter, desired);
   } else {
     if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset,
                 desired, &buf)) != GST_FLOW_OK)
-        {
-   
       goto pull_error;
-        }
-
   }
 
   /* first chunk of data? create the source pad. We do this only here so
    * we can detect broken .wav files with dts disguised as raw PCM (sigh) */
   if (G_UNLIKELY (wav->first)) {
     wav->first = FALSE;
-
+    /* this will also push the segment events */
     gst_wavparse_add_src_pad (wav, buf);
+  } else {
+    /* If we have a pending close/start segment, send it now. */
+    if (G_UNLIKELY (wav->close_segment != NULL)) {
+      gst_pad_push_event (wav->srcpad, wav->close_segment);
+      wav->close_segment = NULL;
+    }
+    if (G_UNLIKELY (wav->start_segment != NULL)) {
+      gst_pad_push_event (wav->srcpad, wav->start_segment);
+      wav->start_segment = NULL;
+    }
   }
 
   obtained = GST_BUFFER_SIZE (buf);
 
-  /* our positions */
+  /* our positions in bytes */
   pos = wav->offset - wav->datastart;
   nextpos = pos + obtained;
 
@@ -1434,83 +1813,98 @@
   GST_BUFFER_OFFSET (buf) = pos / wav->bytes_per_sample;
   GST_BUFFER_OFFSET_END (buf) = nextpos / wav->bytes_per_sample;
 
-  /* and timestamps, be carefull for overflows */
-  timestamp = gst_util_uint64_scale_int (pos, GST_SECOND, wav->bps);
-  next_timestamp = gst_util_uint64_scale_int (nextpos, GST_SECOND, wav->bps);
+  if (wav->bps > 0) {
+    /* and timestamps if we have a bitrate, be careful for overflows */
+    timestamp = uint64_ceiling_scale (pos, GST_SECOND, (guint64) wav->bps);
+    next_timestamp =
+        uint64_ceiling_scale (nextpos, GST_SECOND, (guint64) wav->bps);
+    duration = next_timestamp - timestamp;
+
+    /* update current running segment position */
+    gst_segment_set_last_stop (&wav->segment, GST_FORMAT_TIME, next_timestamp);
+  } else if (wav->fact) {
+    guint64 bps =
+        gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
+    /* and timestamps if we have a bitrate, be careful for overflows */
+    timestamp = uint64_ceiling_scale (pos, GST_SECOND, bps);
+    next_timestamp = uint64_ceiling_scale (nextpos, GST_SECOND, bps);
+    duration = next_timestamp - timestamp;
+  } else {
+    /* no bitrate, all we know is that the first sample has timestamp 0, all
+     * other positions and durations have unknown timestamp. */
+    if (pos == 0)
+      timestamp = 0;
+    else
+      timestamp = GST_CLOCK_TIME_NONE;
+    duration = GST_CLOCK_TIME_NONE;
+    /* update current running segment position with byte offset */
+    gst_segment_set_last_stop (&wav->segment, GST_FORMAT_BYTES, nextpos);
+  }
+  if ((pos > 0) && wav->vbr) {
+    /* don't set timestamps for VBR files if it's not the first buffer */
+    timestamp = GST_CLOCK_TIME_NONE;
+    duration = GST_CLOCK_TIME_NONE;
+  }
+  if (wav->discont) {
+    GST_DEBUG_OBJECT (wav, "marking DISCONT");
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+    wav->discont = FALSE;
+  }
 
   GST_BUFFER_TIMESTAMP (buf) = timestamp;
-  GST_BUFFER_DURATION (buf) = next_timestamp - timestamp;
-
-  /* update current running segment position */
-  gst_segment_set_last_stop (&wav->segment, GST_FORMAT_TIME, next_timestamp);
+  GST_BUFFER_DURATION (buf) = duration;
 
   /* don't forget to set the caps on the buffer */
   gst_buffer_set_caps (buf, GST_PAD_CAPS (wav->srcpad));
 
   GST_LOG_OBJECT (wav,
       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
-      ", size:%u", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
-      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf));
-  
-     
+      ", size:%u", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration),
+      GST_BUFFER_SIZE (buf));
+
   if ((res = gst_pad_push (wav->srcpad, buf)) != GST_FLOW_OK)
-      {
+    goto push_error;
 
-    goto push_error;
-      }
- 
-    
   if (obtained < wav->dataleft) {
+    wav->offset += obtained;
     wav->dataleft -= obtained;
   } else {
+    wav->offset += wav->dataleft;
     wav->dataleft = 0;
   }
-  wav->offset += obtained;
+
   /* Iterate until need more data, so adapter size won't grow */
   if (wav->streaming) {
     GST_LOG_OBJECT (wav,
         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, wav->offset,
         wav->end_offset);
-    
     goto iterate_adapter;
   }
-
   return res;
 
   /* ERROR */
 found_eos:
   {
-
     GST_DEBUG_OBJECT (wav, "found EOS");
-    /* we completed the segment */
-    wav->segment_running = FALSE;
-    if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
-      GstClockTime stop;
-
-      if ((stop = wav->segment.stop) == -1)
-        stop = wav->segment.duration;
-
-      gst_element_post_message (GST_ELEMENT (wav),
-          gst_message_new_segment_done (GST_OBJECT (wav), GST_FORMAT_TIME,
-              stop));
-
-    } else {
-      gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
- 
-    }
-    return GST_FLOW_WRONG_STATE;
+    return GST_FLOW_UNEXPECTED;
   }
 pull_error:
   {
-     
-    GST_DEBUG_OBJECT (wav, "Error getting %" G_GINT64_FORMAT " bytes from the "
+    /* check if we got EOS */
+    if (res == GST_FLOW_UNEXPECTED)
+      goto found_eos;
+
+    GST_WARNING_OBJECT (wav,
+        "Error getting %" G_GINT64_FORMAT " bytes from the "
         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, wav->dataleft);
     return res;
   }
 push_error:
   {
-      
-    GST_DEBUG_OBJECT (wav, "Error pushing on srcpad");
+    GST_INFO_OBJECT (wav,
+        "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
+        GST_DEBUG_PAD_NAME (wav->srcpad), gst_flow_get_name (res),
+        gst_pad_is_linked (wav->srcpad));
     return res;
   }
 }
@@ -1525,52 +1919,73 @@
 
   switch (wav->state) {
     case GST_WAVPARSE_START:
-      GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_START");
+      GST_INFO_OBJECT (wav, "GST_WAVPARSE_START");
       if ((ret = gst_wavparse_stream_init (wav)) != GST_FLOW_OK)
         goto pause;
-      
+
       wav->state = GST_WAVPARSE_HEADER;
       /* fall-through */
 
     case GST_WAVPARSE_HEADER:
-      GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_HEADER");
+      GST_INFO_OBJECT (wav, "GST_WAVPARSE_HEADER");
       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
         goto pause;
 
       wav->state = GST_WAVPARSE_DATA;
+      GST_INFO_OBJECT (wav, "GST_WAVPARSE_DATA");
       /* fall-through */
 
     case GST_WAVPARSE_DATA:
       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
-          {
-
         goto pause;
-          }
- 
-        break;
+      break;
     default:
       g_assert_not_reached ();
   }
- 
   return;
 
   /* ERRORS */
 pause:
-  GST_LOG_OBJECT (wav, "pausing task %d", ret);
-  gst_pad_pause_task (wav->sinkpad);
-  if (GST_FLOW_IS_FATAL (ret)) {
+  {
+    const gchar *reason = gst_flow_get_name (ret);
+
+    GST_DEBUG_OBJECT (wav, "pausing task, reason %s", reason);
+    wav->segment_running = FALSE;
+    gst_pad_pause_task (pad);
+
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
+      if (ret == GST_FLOW_UNEXPECTED) {
+        /* add pad before we perform EOS */
+        if (G_UNLIKELY (wav->first)) {
+          wav->first = FALSE;
+          gst_wavparse_add_src_pad (wav, NULL);
+        }
+        /* perform EOS logic */
+        if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+          GstClockTime stop;
 
-     
-    /* for fatal errors we post an error message */
-    GST_ELEMENT_ERROR (wav, STREAM, FAILED,
-        (_("Internal data stream error.")),
-        ("streaming stopped, reason %s", gst_flow_get_name (ret)));
-    if (wav->srcpad != NULL)
-        {
-      gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
-           }
+          if ((stop = wav->segment.stop) == -1)
+            stop = wav->segment.duration;
+
+          gst_element_post_message (GST_ELEMENT_CAST (wav),
+              gst_message_new_segment_done (GST_OBJECT_CAST (wav),
+                  wav->segment.format, stop));
+        } else {
+          if (wav->srcpad != NULL)
+            gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
+        }
+      } else {
+        /* for fatal errors we post an error message, post the error
+         * first so the app knows about the error first. */
+        GST_ELEMENT_ERROR (wav, STREAM, FAILED,
+            (_("Internal data flow error.")),
+            ("streaming task paused, reason %s (%d)", reason, ret));
+        if (wav->srcpad != NULL)
+          gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
+      }
+    }
+    return;
   }
-  
 }
 
 static GstFlowReturn
@@ -1578,60 +1993,167 @@
 {
   GstFlowReturn ret;
   GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
-   GST_LOG_OBJECT (wav, "adapter_push %" G_GINT64_FORMAT " bytes",
-      GST_BUFFER_SIZE (buf));
+
+  GST_LOG_OBJECT (wav, "adapter_push %u bytes", GST_BUFFER_SIZE (buf));
 
   gst_adapter_push (wav->adapter, buf);
+
   switch (wav->state) {
     case GST_WAVPARSE_START:
-      GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_START");
-      if ((ret = gst_wavparse_parse_stream_init (wav)) != GST_FLOW_OK) 
-      {
-   
-        goto pause;
-			}
-			
-      wav->state = GST_WAVPARSE_HEADER;
-      /* fall-through */
+      GST_INFO_OBJECT (wav, "GST_WAVPARSE_START");
+      if ((ret = gst_wavparse_parse_stream_init (wav)) != GST_FLOW_OK)
+        goto done;
 
+      if (wav->state != GST_WAVPARSE_HEADER)
+        break;
+
+      /* otherwise fall-through */
     case GST_WAVPARSE_HEADER:
-      GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_HEADER");
+      GST_INFO_OBJECT (wav, "GST_WAVPARSE_HEADER");
       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
-        goto pause;
-		
+        goto done;
+
+      if (!wav->got_fmt || wav->datastart == 0)
+        break;
+
       wav->state = GST_WAVPARSE_DATA;
+      GST_INFO_OBJECT (wav, "GST_WAVPARSE_DATA");
+
       /* fall-through */
-
     case GST_WAVPARSE_DATA:
+      if (buf && GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))
+        wav->discont = TRUE;
       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
-      {
- 
-        goto pause;
+        goto done;
+      break;
+    default:
+      g_return_val_if_reached (GST_FLOW_ERROR);
+  }
+done:
+  return ret;
+}
+
+static GstFlowReturn
+gst_wavparse_flush_data (GstWavParse * wav)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  guint av;
+
+  if ((av = gst_adapter_available (wav->adapter)) > 0) {
+    wav->dataleft = av;
+    wav->end_offset = wav->offset + av;
+    ret = gst_wavparse_stream_data (wav);
+  }
+
+  return ret;
+}
+
+static gboolean
+gst_wavparse_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
+  gboolean ret = TRUE;
+
+  GST_LOG_OBJECT (wav, "handling %s event", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+    {
+      GstFormat format;
+      gdouble rate, arate;
+      gint64 start, stop, time, offset = 0, end_offset = -1;
+      gboolean update;
+      GstSegment segment;
+
+      /* some debug output */
+      gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+          &start, &stop, &time);
+      gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
+          start, stop, time);
+      GST_DEBUG_OBJECT (wav,
+          "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
+          &segment);
+
+      if (wav->state != GST_WAVPARSE_DATA) {
+        GST_DEBUG_OBJECT (wav, "still starting, eating event");
+        goto exit;
       }
 
-      break;
+      /* now we are either committed to TIME or BYTE format,
+       * and we only expect a BYTE segment, e.g. following a seek */
+      if (format == GST_FORMAT_BYTES) {
+        if (start > 0) {
+          offset = start;
+          start -= wav->datastart;
+          start = MAX (start, 0);
+        }
+        if (stop > 0) {
+          end_offset = stop;
+          stop -= wav->datastart;
+          stop = MAX (stop, 0);
+        }
+        if (wav->segment.format == GST_FORMAT_TIME) {
+          guint64 bps = wav->bps;
 
-    default:
-      g_assert_not_reached ();
-  }
-	
-  return ret;
-
-pause:
+          /* operating in format TIME, so we can convert */
+          if (!bps && wav->fact)
+            bps =
+                gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
+          if (bps) {
+            if (start >= 0)
+              start =
+                  uint64_ceiling_scale (start, GST_SECOND, (guint64) wav->bps);
+            if (stop >= 0)
+              stop =
+                  uint64_ceiling_scale (stop, GST_SECOND, (guint64) wav->bps);
+          }
+        }
+      } else {
+        GST_DEBUG_OBJECT (wav, "unsupported segment format, ignoring");
+        goto exit;
+      }
 
-  GST_LOG_OBJECT (wav, "pausing task %d", ret);
-  gst_pad_pause_task (wav->sinkpad);
-  if (GST_FLOW_IS_FATAL (ret)) {
-    /* for fatal errors we post an error message */
- 
-    GST_ELEMENT_ERROR (wav, STREAM, FAILED,
-        (_("Internal data stream error.")),
-        ("streaming stopped, reason %s", gst_flow_get_name (ret)));
-    if (wav->srcpad != NULL)
-    {
-      gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
-  	
-  	}
+      /* accept upstream's notion of segment and distribute along */
+      gst_segment_set_newsegment_full (&wav->segment, update, rate, arate,
+          wav->segment.format, start, stop, start);
+      /* also store the newsegment event for the streaming thread */
+      if (wav->start_segment)
+        gst_event_unref (wav->start_segment);
+      wav->start_segment =
+          gst_event_new_new_segment_full (update, rate, arate,
+          wav->segment.format, start, stop, start);
+      GST_DEBUG_OBJECT (wav, "Pushing newseg update %d, rate %g, "
+          "applied rate %g, format %d, start %" G_GINT64_FORMAT ", "
+          "stop %" G_GINT64_FORMAT, update, rate, arate, wav->segment.format,
+          start, stop);
+
+      /* stream leftover data in current segment */
+      gst_wavparse_flush_data (wav);
+      /* and set up streaming thread for next one */
+      wav->offset = offset;
+      wav->end_offset = end_offset;
+      if (wav->end_offset > 0) {
+        wav->dataleft = wav->end_offset - wav->offset;
+      } else {
+        /* infinity; upstream will EOS when done */
+        wav->dataleft = G_MAXUINT64;
+      }
+    exit:
+      gst_event_unref (event);
+      break;
+    }
+    case GST_EVENT_EOS:
+      /* stream leftover data in current segment */
+      gst_wavparse_flush_data (wav);
+      /* fall-through */
+    case GST_EVENT_FLUSH_STOP:
+      gst_adapter_clear (wav->adapter);
+      wav->discont = TRUE;
+      /* fall-through */
+    default:
+      ret = gst_pad_event_default (wav->sinkpad, event);
+      break;
   }
 
   return ret;
@@ -1661,29 +2183,48 @@
   GstWavParse *wavparse;
   gboolean res = TRUE;
 
-  wavparse = GST_WAVPARSE (gst_pad_get_parent (pad));
+  wavparse = GST_WAVPARSE (GST_PAD_PARENT (pad));
 
-  if (wavparse->bytes_per_sample == 0)
-    goto no_bytes_per_sample;
+  if (*dest_format == src_format) {
+    *dest_value = src_value;
+    return TRUE;
+  }
 
-  if (wavparse->bps == 0)
-    goto no_bps;
+  if ((wavparse->bps == 0) && !wavparse->fact)
+    goto no_bps_fact;
+
+  GST_INFO_OBJECT (wavparse, "converting value from %s to %s",
+      gst_format_get_name (src_format), gst_format_get_name (*dest_format));
 
   switch (src_format) {
     case GST_FORMAT_BYTES:
       switch (*dest_format) {
         case GST_FORMAT_DEFAULT:
           *dest_value = src_value / wavparse->bytes_per_sample;
+          /* make sure we end up on a sample boundary */
+          *dest_value -= *dest_value % wavparse->bytes_per_sample;
           break;
         case GST_FORMAT_TIME:
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, GST_SECOND, wavparse->bps);
+          /* src_value + datastart = offset */
+          GST_INFO_OBJECT (wavparse,
+              "src=%" G_GINT64_FORMAT ", offset=%" G_GINT64_FORMAT, src_value,
+              wavparse->offset);
+          if (wavparse->bps > 0)
+            *dest_value = uint64_ceiling_scale (src_value, GST_SECOND,
+                (guint64) wavparse->bps);
+          else if (wavparse->fact) {
+            guint64 bps = uint64_ceiling_scale_int (wavparse->datasize,
+                wavparse->rate, wavparse->fact);
+
+            *dest_value = uint64_ceiling_scale_int (src_value, GST_SECOND, bps);
+          } else {
+            res = FALSE;
+          }
           break;
         default:
           res = FALSE;
           goto done;
       }
-      *dest_value -= *dest_value % wavparse->bytes_per_sample;
       break;
 
     case GST_FORMAT_DEFAULT:
@@ -1692,8 +2233,8 @@
           *dest_value = src_value * wavparse->bytes_per_sample;
           break;
         case GST_FORMAT_TIME:
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, GST_SECOND, wavparse->rate);
+          *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
+              (guint64) wavparse->rate);
           break;
         default:
           res = FALSE;
@@ -1704,14 +2245,21 @@
     case GST_FORMAT_TIME:
       switch (*dest_format) {
         case GST_FORMAT_BYTES:
+          if (wavparse->bps > 0)
+            *dest_value = gst_util_uint64_scale (src_value,
+                (guint64) wavparse->bps, GST_SECOND);
+          else {
+            guint64 bps = gst_util_uint64_scale_int (wavparse->datasize,
+                wavparse->rate, wavparse->fact);
+
+            *dest_value = gst_util_uint64_scale (src_value, bps, GST_SECOND);
+          }
           /* make sure we end up on a sample boundary */
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, wavparse->bps, GST_SECOND);
           *dest_value -= *dest_value % wavparse->blockalign;
           break;
         case GST_FORMAT_DEFAULT:
-          *dest_value =
-              gst_util_uint64_scale_int (src_value, wavparse->rate, GST_SECOND);
+          *dest_value = gst_util_uint64_scale (src_value,
+              (guint64) wavparse->rate, GST_SECOND);
           break;
         default:
           res = FALSE;
@@ -1725,22 +2273,12 @@
   }
 
 done:
-  gst_object_unref (wavparse);
-
   return res;
 
   /* ERRORS */
-no_bytes_per_sample:
+no_bps_fact:
   {
-    GST_DEBUG_OBJECT (wavparse,
-        "bytes_per_sample 0, probably an mp3 - channels %d, width %d",
-        wavparse->channels, wavparse->width);
-    res = FALSE;
-    goto done;
-  }
-no_bps:
-  {
-    GST_DEBUG_OBJECT (wavparse, "bps 0, cannot convert");
+    GST_DEBUG_OBJECT (wavparse, "bps 0 or no fact chunk, cannot convert");
     res = FALSE;
     goto done;
   }
@@ -1753,6 +2291,7 @@
     GST_QUERY_POSITION,
     GST_QUERY_DURATION,
     GST_QUERY_CONVERT,
+    GST_QUERY_SEEKING,
     0
   };
 
@@ -1764,11 +2303,15 @@
 gst_wavparse_pad_query (GstPad * pad, GstQuery * query)
 {
   gboolean res = TRUE;
-  GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
+  GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (pad));
 
   /* only if we know */
-  if (wav->state != GST_WAVPARSE_DATA)
+  if (wav->state != GST_WAVPARSE_DATA) {
+    gst_object_unref (wav);
     return FALSE;
+  }
+
+  GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
@@ -1776,15 +2319,15 @@
       gint64 curb;
       gint64 cur;
       GstFormat format;
-      gboolean res = TRUE;
 
+      /* this is not very precise, as we have pushed severla buffer upstream for prerolling */
       curb = wav->offset - wav->datastart;
       gst_query_parse_position (query, &format, NULL);
+      GST_INFO_OBJECT (wav, "pos query at %" G_GINT64_FORMAT, curb);
 
       switch (format) {
         case GST_FORMAT_TIME:
-          res &=
-              gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, curb,
+          res = gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, curb,
               &format, &cur);
           break;
         default:
@@ -1798,27 +2341,24 @@
     }
     case GST_QUERY_DURATION:
     {
-      gint64 endb;
-      gint64 end;
+      gint64 duration = 0;
       GstFormat format;
-      gboolean res = TRUE;
 
-      endb = wav->datasize;
       gst_query_parse_duration (query, &format, NULL);
 
       switch (format) {
-        case GST_FORMAT_TIME:
-          res &=
-              gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, endb,
-              &format, &end);
+        case GST_FORMAT_TIME:{
+          if ((res = gst_wavparse_calculate_duration (wav))) {
+            duration = wav->duration;
+          }
           break;
+        }
         default:
           format = GST_FORMAT_BYTES;
-          end = endb;
+          duration = wav->datasize;
           break;
       }
-      if (res)
-        gst_query_set_duration (query, format, end);
+      gst_query_set_duration (query, format, duration);
       break;
     }
     case GST_QUERY_CONVERT:
@@ -1828,46 +2368,69 @@
 
       gst_query_parse_convert (query, &srcformat, &srcvalue,
           &dstformat, &dstvalue);
-      res &=
-          gst_wavparse_pad_convert (pad, srcformat, srcvalue,
+      res = gst_wavparse_pad_convert (pad, srcformat, srcvalue,
           &dstformat, &dstvalue);
       if (res)
         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
       break;
     }
+    case GST_QUERY_SEEKING:{
+      GstFormat fmt;
+      gboolean seekable = FALSE;
+
+      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+      if (fmt == wav->segment.format) {
+        if (wav->streaming) {
+          GstQuery *q;
+
+          q = gst_query_new_seeking (GST_FORMAT_BYTES);
+          if ((res = gst_pad_peer_query (wav->sinkpad, q))) {
+            gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
+            GST_LOG_OBJECT (wav, "upstream BYTE seekable %d", seekable);
+          }
+          gst_query_unref (q);
+        } else {
+          GST_LOG_OBJECT (wav, "looping => seekable");
+          seekable = TRUE;
+          res = TRUE;
+        }
+      } else if (fmt == GST_FORMAT_TIME) {
+        res = TRUE;
+      }
+      if (res) {
+        gst_query_set_seeking (query, fmt, seekable, 0, wav->segment.duration);
+      }
+      break;
+    }
     default:
       res = gst_pad_query_default (pad, query);
       break;
   }
+  gst_object_unref (wav);
   return res;
 }
 
 static gboolean
 gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event)
 {
-  GstWavParse *wavparse = GST_WAVPARSE (GST_PAD_PARENT (pad));
-  gboolean res = TRUE;
+  GstWavParse *wavparse = GST_WAVPARSE (gst_pad_get_parent (pad));
+  gboolean res = FALSE;
 
-  GST_DEBUG_OBJECT (wavparse, "event %d, %s", GST_EVENT_TYPE (event),
-      GST_EVENT_TYPE_NAME (event));
-
-  /* can only handle events when we are in the data state */
-  if (wavparse->state != GST_WAVPARSE_DATA)
-    return FALSE;
+  GST_DEBUG_OBJECT (wavparse, "%s event", GST_EVENT_TYPE_NAME (event));
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
-    {
-      res = gst_wavparse_perform_seek (wavparse, event);
+      /* can only handle events when we are in the data state */
+      if (wavparse->state == GST_WAVPARSE_DATA) {
+        res = gst_wavparse_perform_seek (wavparse, event);
+      }
+      gst_event_unref (event);
       break;
-    }
     default:
-      res = FALSE;
+      res = gst_pad_push_event (wavparse->sinkpad, event);
       break;
   }
-
-  gst_event_unref (event);
-
+  gst_object_unref (wavparse);
   return res;
 }
 
@@ -1877,15 +2440,23 @@
   GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
   gboolean res;
 
+  if (wav->adapter)
+    gst_object_unref (wav->adapter);
+
   if (gst_pad_check_pull_range (sinkpad)) {
     GST_DEBUG ("going to pull mode");
     wav->streaming = FALSE;
+    if (wav->adapter) {
+      gst_adapter_clear (wav->adapter);
+      g_object_unref (wav->adapter);
+    }
     wav->adapter = NULL;
     res = gst_pad_activate_pull (sinkpad, TRUE);
   } else {
     GST_DEBUG ("going to push (streaming) mode");
     wav->streaming = TRUE;
-    wav->adapter = gst_adapter_new ();
+    if (wav->adapter == NULL)
+      wav->adapter = gst_adapter_new ();
     res = gst_pad_activate_push (sinkpad, TRUE);
   }
   gst_object_unref (wav);
@@ -1896,21 +2467,18 @@
 static gboolean
 gst_wavparse_sink_activate_pull (GstPad * sinkpad, gboolean active)
 {
-  GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
-
-  GST_DEBUG_OBJECT (wav, "activating pull");
+  GstWavParse *wav = GST_WAVPARSE (GST_OBJECT_PARENT (sinkpad));
 
   if (active) {
     /* if we have a scheduler we can start the task */
     wav->segment_running = TRUE;
-    gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop, sinkpad);
+    return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop,
+        sinkpad);
   } else {
-    gst_pad_stop_task (sinkpad);
+    wav->segment_running = FALSE;
+    return gst_pad_stop_task (sinkpad);
   }
-  gst_object_unref (wav);
-
-  return TRUE;
-}
+};
 
 static GstStateChangeReturn
 gst_wavparse_change_state (GstElement * element, GstStateChange transition)
@@ -1918,10 +2486,6 @@
   GstStateChangeReturn ret;
   GstWavParse *wav = GST_WAVPARSE (element);
 
-  GST_DEBUG_OBJECT (wav, "changing state %s - %s",
-      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
-      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
-
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       break;
@@ -1939,17 +2503,10 @@
   switch (transition) {
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:{
-      GstEvent **event_p = &wav->seek_event;
-
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
       gst_wavparse_destroy_sourcepad (wav);
-      gst_event_replace (event_p, NULL);
       gst_wavparse_reset (wav);
-      if (wav->adapter) {
-        gst_adapter_clear (wav->adapter);
-      }
       break;
-    }
     case GST_STATE_CHANGE_READY_TO_NULL:
       break;
     default:
@@ -1963,8 +2520,6 @@
 {
   gst_riff_init ();
 
-  GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
-
   return gst_element_register (plugin, "wavparse", GST_RANK_PRIMARY,
       GST_TYPE_WAVPARSE);
 }
@@ -1974,10 +2529,9 @@
     "wavparse",
     "Parse a .wav file into raw audio",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
-
-
+	
+	
 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
 {
 	return &gst_plugin_desc;
-}
-
+}
\ No newline at end of file
--- a/gst_plugins_good/gst/wavparse/gstwavparse.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_good/gst/wavparse/gstwavparse.h	Fri Apr 16 15:15:52 2010 +0300
@@ -24,11 +24,8 @@
 
 
 #include <gst/gst.h>
-#include <gst/gst_global.h>
-#include <gst/riff/riff-read.h>
-#include <gst/riff/riff-ids.h>
-#include <gst/riff/riff-media.h>
-
+#include "gst/riff/riff-ids.h"
+#include "gst/riff/riff-read.h"
 #include <gst/base/gstadapter.h>
 
 G_BEGIN_DECLS
@@ -47,7 +44,7 @@
 typedef enum {
   GST_WAVPARSE_START,
   GST_WAVPARSE_HEADER,
-  GST_WAVPARSE_DATA,
+  GST_WAVPARSE_DATA
 } GstWavParseState;
 
 typedef struct _GstWavParse GstWavParse;
@@ -69,7 +66,8 @@
    * the format for sure */
   GstCaps     *caps;
   GstTagList  *tags;
-  GstEvent    *newsegment;
+  GstEvent    *close_segment;
+  GstEvent    *start_segment;
 
   /* WAVE decoding state */
   GstWavParseState state;
@@ -79,11 +77,16 @@
 
   /* useful audio data */
   guint16 depth;
-  gint rate;
+  guint32 rate;
   guint16 channels;
   guint16 blockalign;
   guint16 width;
+  guint32 av_bps;
+  guint32 fact;
+
+  /* real bps used or 0 when no bitrate is known */
   guint32 bps;
+  gboolean vbr;
 
   guint bytes_per_sample;
 
@@ -94,7 +97,9 @@
   /* offset/length of data part */
   guint64 	datastart;
   guint64 	datasize;
-  
+  /* duration in time */
+  guint64 	duration;
+
   /* pending seek */
   GstEvent *seek_event;
 
@@ -106,9 +111,11 @@
   /* configured segment, start/stop expressed in time */
   GstSegment segment;
   gboolean segment_running;
-  
+
   /* for late pad configuration */
   gboolean first;
+  /* discont after seek */
+  gboolean discont;
 };
 
 struct _GstWavParseClass {
--- a/gst_plugins_symbian/config.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_symbian/config.h	Fri Apr 16 15:15:52 2010 +0300
@@ -29,7 +29,7 @@
 
 
 /* gettext package name */
-#define GETTEXT_PACKAGE "gst-plugins-base-0.10"
+#define GETTEXT_PACKAGE "gst-plugins-symbian-0.10"
 
 /* macro to use to show function name */
 #define GST_FUNCTION __PRETTY_FUNCTION__
@@ -44,7 +44,7 @@
 #define GST_LICENSE "LGPL"
 
 /* package name in plugins */
-#define GST_PACKAGE_NAME "GStreamer Base Plug-ins source release"
+#define GST_PACKAGE_NAME "GStreamer Symbian Plug-ins source release"
 
 /* package origin */
 #define GST_PACKAGE_ORIGIN "Unknown package origin"
@@ -217,25 +217,25 @@
 #define HAVE_XVIDEO 
 
 /* gettext locale dir */
-#define LOCALEDIR "/home/datha/gst-plugins-base-0.10.8/share/locale"
+#define LOCALEDIR "/home/datha/gst-plugins-symbian-0.10.1/share/locale"
 
 /* Name of package */
-#define PACKAGE "gst-plugins-base"
+#define PACKAGE "gst-plugins-Symbian"
 
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer"
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME "GStreamer Base Plug-ins"
+#define PACKAGE_NAME "GStreamer symbian Plug-ins"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer Base Plug-ins 0.10.8"
+#define PACKAGE_STRING "GStreamer symbian Plug-ins 0.10.1"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gst-plugins-base"
+#define PACKAGE_TARNAME "gst-plugins-symbian"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.8"
+#define PACKAGE_VERSION "0.10.1"
 
 /* directory where plugins are located */
 #ifdef __SYMBIAN32__
@@ -271,7 +271,7 @@
 #define STDC_HEADERS 1
 
 /* Version number of package */
-#define VERSION "0.10.8"
+#define VERSION "0.10.1"
 
 /* Define to 1 if your processor stores words with the most significant byte
    first (like Motorola and SPARC, unlike Intel and VAX). */
--- a/gst_plugins_symbian/tsrc/gstreamertestmodule/conf/GStreamerTestClass.cfg	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/conf/GStreamerTestClass.cfg	Fri Apr 16 15:15:52 2010 +0300
@@ -27,6 +27,7 @@
 //		    ECONVERTER      9,
 //		    EDEVSOUNDSRC    10,
 //		    EDEVSOUNDSINK   11
+//        NOKIAAACENCODER 12
 
   //GST_STATE_VOID_PENDING        = 0,
   //GST_STATE_NULL                = 1,
@@ -54,7 +55,7 @@
 gst SetElementProperties 10 gain 5
 gst GetElementProperties 10 gain
 gst GetElementProperties 10 samplesrecorded
-gst GetElementProperties 10 rate
+gst GetElementProperties 10 rates
 gst GetElementProperties 10 channels
 gst SetElementProperties 10 leftbalance 80
 gst SetElementProperties 10 rightbalance 20
@@ -64,7 +65,424 @@
 [Endtest]
 
 [Test]
-title 2. Create WAV Record Pipeline 
+title 2. Create WAV Record Pipeline for balance
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestbalance.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 9000
+gst SetElementProperties 10 leftbalance 80
+gst SetElementProperties 10 rightbalance 20
+pause 1000
+gst StopRecording
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 3. Create WAV Record Pipeline for ten sec
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 10000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 4. Create WAV Record Pipeline for pause resume
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestpause.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 3
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 5. Create WAV Play Pipeline 
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 1
+gst CreateElement 5
+gst CreateElement 9
+gst CreateElement 8
+gst CreateElement 11
+gst InitPipeLine
+gst SetElementProperties 1 c:\data\RecordTest.wav
+gst AddElementToPipeline 1
+gst AddElementToPipeline 5
+gst AddElementToPipeline 9
+gst AddElementToPipeline 8
+gst AddElementToPipeline 11
+gst LinkElementsInPipeline 1 5
+gst SetPipelineState 4
+pause 3000
+gst GetElementProperties 11 volume
+gst SetElementProperties 11 volume 5000
+gst SetElementProperties 11 leftbalance 80
+gst SetElementProperties 11 rightbalance 20
+gst GetElementProperties 11 samplesplayed
+gst GetElementProperties 11 rate
+gst GetElementProperties 11 channels
+pause 3000
+gst SetElementProperties 11 volume 10000
+waittestclass gst
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 6. Create RAW Play Pipeline 
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 1
+gst CreateElement 11
+gst InitPipeLine
+gst SetElementProperties 1 c:\data\RecordTest.raw
+gst AddElementToPipeline 1
+gst AddElementToPipeline 11
+gst LinkElementsInPipeline 1 11
+gst SetElementProperties 11 priority 0
+gst SetElementProperties 11 preference 0
+gst SetElementProperties 11 channels 1
+gst SetElementProperties 11 rate 16000
+gst SetElementProperties 11 mimetype audio/x-raw-int
+gst SetElementProperties 11 fourcc 909201440
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 11 volume
+gst GetElementProperties 11 maxvolume
+waittestclass gst
+gst SetPipelineState 4
+waittestclass gst
+delete gst
+[Endtest]
+
+
+/*
+[Test]
+title 7. Create WAV Record Pipeline1
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest1.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 8. Create WAV Record Pipeline2
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest2.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 gain 5
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+pause 1000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst SetPipelineState 3
+pause 4000
+gst SetElementProperties 10 gain 64
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 9. Create WAV Record Pipeline3 
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest3.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 gain 24
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 2
+pause 1000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst SetPipelineState 3
+pause 4000
+gst SetElementProperties 10 gain 64
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 10. Create WAV Record Pipeline4
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest4.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 10000
+gst SetElementProperties 10 priority 1
+gst SetElementProperties 10 gain 50
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+pause 1000
+gst SetPipelineState 4
+pause 5000
+gst SetElementProperties 10 rate 20000
+pause 3000
+gst SetPipelineState 3
+pause 4000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 11. Create WAV Record Pipeline5
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest5.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 gain 80
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+pause 1000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 4000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 4000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 4000
+pause 5000
+gst SetPipelineState 4
+pause 4000
+gst SetElementProperties 10 gain 90
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 12. Create WAV Record Pipeline6
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest6.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 10000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 10000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 13. Create WAV Record Pipeline7
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 gain 12
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+pause 1000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst SetPipelineState 3
+pause 4000
+gst SetElementProperties 10 gain 64
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 14. Create WAV Record Pipeline8
 create GStreamerTestClass gst
 gst InitGStreamer
 gst CreatePipeLine
@@ -81,6 +499,521 @@
 gst LinkElementsInPipeline 7 2
 gst SetElementProperties 10 rate 16000
 gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 gain 12
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+pause 1000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst SetPipelineState 3
+pause 4000
+gst SetElementProperties 10 gain 64
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+[Endtest]
+
+[Test]
+title 15. Create WAV Record Pipeline 9
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest9.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 gain 12
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+pause 1000
+gst SetPipelineState 4
+pause 10000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+gst SetPipelineState 3
+pause 360000
+gst SetElementProperties 10 gain 64
+gst SetPipelineState 4
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 16. Create WAV Record Pipeline GstReliabilitytestPlaypause
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestpause.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst GstReliabilitytestPlaypause 30
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 17. Create WAV Record Pipeline GstReliabilitytestRecording
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 7
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestpause.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 7
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 7
+gst LinkElementsInPipeline 7 2
+gst GstReliabilitytestRecording 30
+gst GetElementProperties 10 samplesrecorded
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 18. Create WAV Play1 Pipeline 
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 1
+gst CreateElement 5
+gst CreateElement 9
+gst CreateElement 8
+gst CreateElement 11
+gst InitPipeLine
+gst SetElementProperties 1 c:\data\RecordTest.wav
+gst AddElementToPipeline 1
+gst AddElementToPipeline 5
+gst AddElementToPipeline 9
+gst AddElementToPipeline 8
+gst AddElementToPipeline 11
+gst SetElementProperties 5 volume 5000
+gst LinkElementsInPipeline 1 5
+gst SetPipelineState 4
+pause 20000
+waittestclass gst
+delete gst
+[Endtest]
+
+
+[Test]
+title 19. Create AAC Record Pipeline 
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 12
+gst CreateElement 13
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest.mp4
+gst AddElementToPipeline 10
+gst AddElementToPipeline 12
+gst AddElementToPipeline 13
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 12
+gst LinkElementsInPipeline 12 13
+gst LinkElementsInPipeline 13 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 5000
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+[Test]
+title 20. Create AAC Record Pipeline for pause
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 12
+gst CreateElement 13
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestpause.mp4
+gst AddElementToPipeline 10
+gst AddElementToPipeline 12
+gst AddElementToPipeline 13
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 12
+gst LinkElementsInPipeline 12 13
+gst LinkElementsInPipeline 13 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 3
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 21. Create AAC Record Pipeline1
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 12
+gst CreateElement 13
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest1.mp4
+gst AddElementToPipeline 10
+gst AddElementToPipeline 12
+gst AddElementToPipeline 13
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 12
+gst LinkElementsInPipeline 12 13
+gst LinkElementsInPipeline 13 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 22. Create AAC Record Pipeline reliabilityplaypause
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 12
+gst CreateElement 13
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestpause.mp4
+gst AddElementToPipeline 10
+gst AddElementToPipeline 12
+gst AddElementToPipeline 13
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 12
+gst LinkElementsInPipeline 12 13
+gst LinkElementsInPipeline 13 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst GstReliabilitytestPlaypause 30
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 23. Create AAC Record Pipeline reliabilityrecording
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 12
+gst CreateElement 13
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest.mp4
+gst AddElementToPipeline 10
+gst AddElementToPipeline 12
+gst AddElementToPipeline 13
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 12
+gst LinkElementsInPipeline 12 13
+gst LinkElementsInPipeline 13 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
+gst SetElementProperties 10 preference 0
+gst SetElementProperties 10 channels 1
+gst GstReliabilitytestRecording 30
+gst GetElementProperties 10 samplesrecorded
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+
+
+[Test]
+title 24. Create AMR Record Pipeline  with amrmux
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 14
+gst SetElementProperties 14 1
+gst GetElementProperties 14 1
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest.amr
+gst AddElementToPipeline 10
+gst AddElementToPipeline 14
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/amr
+gst GetElementsCustomIntfc 10 7
+gst CustomIntfcProp 7 2 1
+gst CustomIntfcProp 7 4 16000
+gst LinkElementsInPipeline 10 14
+gst LinkElementsInPipeline 14 2
+gst SetPipelineState 4
+pause 5000
+gst CustomIntfcProp 7 3
+gst CustomIntfcProp 7 5
+pause 5000
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+[Test]
+title 25. Create AMR Record Pipeline for pause resume
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 14
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestpause.amr
+gst AddElementToPipeline 10
+gst AddElementToPipeline 14
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/amr
+gst GetElementsCustomIntfc 10 7
+gst CustomIntfcProp 7 2 1
+gst CustomIntfcProp 7 4 16000
+gst LinkElementsInPipeline 10 14
+gst LinkElementsInPipeline 14 2
+gst SetPipelineState 4
+pause 5000
+gst SetPipelineState 3
+pause 5000
+gst SetPipelineState 4
+pause 5000
+gst CustomIntfcProp 7 3
+gst CustomIntfcProp 7 5
+pause 5000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 26. Create AMR Record Pipeline balance
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 14
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTestbalance.amr
+gst AddElementToPipeline 10
+gst AddElementToPipeline 14
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/amr
+gst GetElementsCustomIntfc 10 7
+gst CustomIntfcProp 7 2 1
+gst CustomIntfcProp 7 4 16000
+gst LinkElementsInPipeline 10 14
+gst LinkElementsInPipeline 14 2
+gst SetPipelineState 4
+pause 5000
+gst CustomIntfcProp 7 3
+gst CustomIntfcProp 7 5
+pause 5000
+gst SetElementProperties 10 leftbalance 80
+gst SetElementProperties 10 rightbalance 20
+pause 1000
+gst StopRecording
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 27. Create AMR Record Pipeline  GstReliabilitytestPlaypause
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 14
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordReliabilityplaypause.amr
+gst AddElementToPipeline 10
+gst AddElementToPipeline 14
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/amr
+gst GetElementsCustomIntfc 10 7
+gst CustomIntfcProp 7 2 1
+gst CustomIntfcProp 7 4 16000
+gst LinkElementsInPipeline 10 14
+gst LinkElementsInPipeline 14 2
+gst GstReliabilitytestPlaypause 30
+gst SetPipelineState 4
+pause 5000
+gst GetElementProperties 10 gain
+gst GetElementProperties 10 samplesrecorded
+pause 2000
+gst CustomIntfcProp 7 3
+gst CustomIntfcProp 7 5
+pause 2000
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+
+
+
+[Test]
+title 28. Create AMR Record Pipeline reliabilityrecording
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 14
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordReliabilityRecording.amr
+gst AddElementToPipeline 10
+gst AddElementToPipeline 14
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/amr
+gst GetElementsCustomIntfc 10 7
+gst CustomIntfcProp 7 2 1
+gst CustomIntfcProp 7 4 16000
+gst LinkElementsInPipeline 10 14
+gst LinkElementsInPipeline 14 2
+gst GstReliabilitytestRecording 30
+gst GetElementProperties 10 samplesrecorded
+gst StopRecording
+waittestclass gst
+gst SetPipelineState 1
+delete gst
+[Endtest]
+*/
+
+
+
+
+
+/*[Test]
+title 2. Create AAC Record Pipeline 
+create GStreamerTestClass gst
+gst InitGStreamer
+gst CreatePipeLine
+gst CreateElement 10
+gst CreateElement 12
+gst CreateElement 2
+gst InitPipeLine
+gst SetElementProperties 2 c:\data\RecordTest.wav
+gst AddElementToPipeline 10
+gst AddElementToPipeline 12
+gst AddElementToPipeline 2
+gst SetCapsInPipeLine audio/x-raw-int 16 16
+gst LinkElementsInPipeline 10 12
+gst LinkElementsInPipeline 12 2
+gst SetElementProperties 10 rate 16000
+gst SetElementProperties 10 priority 0
 gst SetElementProperties 10 preference 0
 gst SetElementProperties 10 channels 1
 gst SetPipelineState 4
@@ -367,4 +1300,4 @@
 gst SetPipelineState 4
 waittestclass gst
 delete gst
-[Endtest]
\ No newline at end of file
+[Endtest] */
\ No newline at end of file
--- a/gst_plugins_symbian/tsrc/gstreamertestmodule/group/GStreamerTestClass.pkg	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/group/GStreamerTestClass.pkg	Fri Apr 16 15:15:52 2010 +0300
@@ -36,6 +36,53 @@
 ;*"rd-key.pem","rd.cer"
 
 ;Files to install
+
+"\epoc32\release\armv5\udeb\libgstadder.dll"-"!:\sys\bin\libgstadder.dll"
+"\epoc32\release\armv5\udeb\libgstaudio.dll"-"!:\sys\bin\libgstaudio.dll"
+"\epoc32\release\armv5\udeb\libgstbase.dll"-"!:\sys\bin\libgstbase.dll"
+"\epoc32\release\armv5\udeb\libgstcdda.dll"-"!:\sys\bin\libgstcdda.dll"
+"\epoc32\release\armv5\udeb\libgstcontroller.dll"-"!:\sys\bin\libgstcontroller.dll"
+"\epoc32\release\armv5\udeb\libgstdataprotocol.dll"-"!:\sys\bin\libgstdataprotocol.dll"
+"\epoc32\release\armv5\udeb\libgstdevsoundext.dll"-"!:\sys\bin\libgstdevsoundext.dll"
+;"\epoc32\release\armv5\udeb\libgstffmpegcolorspace.dll"-"!:\sys\bin\libgstffmpegcolorspace.dll"
+"\epoc32\release\armv5\udeb\libgstfft.dll"-"!:\sys\bin\libgstfft.dll"
+"\epoc32\release\armv5\udeb\libgstgdp.dll"-"!:\sys\bin\libgstgdp.dll"
+
+"\epoc32\release\armv5\udeb\libgstinterfaces.dll"-"!:\sys\bin\libgstinterfaces.dll"
+"\epoc32\release\armv5\udeb\libgstnet.dll"-"!:\sys\bin\libgstnet.dll"
+"\epoc32\release\armv5\udeb\libgstnetbuffer.dll"-"!:\sys\bin\libgstnetbuffer.dll"
+"\epoc32\release\armv5\udeb\libgstpbutils.dll"-"!:\sys\bin\libgstpbutils.dll"
+"\epoc32\release\armv5\udeb\libgstreamer.dll"-"!:\sys\bin\libgstreamer.dll"
+"\epoc32\release\armv5\udeb\libgstriff.dll"-"!:\sys\bin\libgstriff.dll"
+;"\epoc32\release\armv5\udeb\libgstrtp.dll"-"!:\sys\bin\libgstrtp.dll"
+"\epoc32\release\armv5\udeb\libgstsubparse.dll"-"!:\sys\bin\libgstsubparse.dll"
+"\epoc32\release\armv5\udeb\libgsttag.dll"-"!:\sys\bin\libgsttag.dll"
+"\epoc32\release\armv5\udeb\libgsttcp.dll"-"!:\sys\bin\libgsttcp.dll"
+
+;"\epoc32\release\armv5\udeb\libgstvideo.dll"-"!:\sys\bin\libgstvideo.dll"
+;"\epoc32\release\armv5\udeb\libgstvideorate.dll"-"!:\sys\bin\libgstvideorate.dll"
+;"\epoc32\release\armv5\udeb\libgstvideoscale.dll"-"!:\sys\bin\libgstvideoscale.dll"
+;"\epoc32\release\armv5\udeb\libgstvideotestsrc.dll"-"!:\sys\bin\libgstvideotestsrc.dll"
+;"\epoc32\release\armv5\udeb\libgstvolume.dll"-"!:\sys\bin\libgstvolume.dll"
+
+
+"\epoc32\release\armv5\udeb\libgstaudiorate.dll"-"!:\sys\bin\libgstaudiorate.dll"
+"\epoc32\release\armv5\udeb\libgstaudioresample.dll"-"!:\sys\bin\libgstaudioresample.dll"
+"\epoc32\release\armv5\udeb\libgstaudiotestsrc.dll"-"!:\sys\bin\libgstaudiotestsrc.dll"
+"\epoc32\release\armv5\udeb\libgstcoreelements.dll"-"!:\sys\bin\libgstcoreelements.dll"
+"\epoc32\release\armv5\udeb\libgstcoreindexers.dll"-"!:\sys\bin\libgstcoreindexers.dll"
+"\epoc32\release\armv5\udeb\libgstdecodebin.dll"-"!:\sys\bin\libgstdecodebin.dll"
+"\epoc32\release\armv5\udeb\libgstdecodebin2.dll"-"!:\sys\bin\libgstdecodebin2.dll"
+"\epoc32\release\armv5\udeb\libgstdevsoundsink.dll"-"!:\sys\bin\libgstdevsoundsink.dll"
+"\epoc32\release\armv5\udeb\libgstdevsoundsrc.dll"-"!:\sys\bin\libgstdevsoundsrc.dll"
+"\epoc32\release\armv5\udeb\libgstplaybin.dll"-"!:\sys\bin\libgstplaybin.dll"
+"\epoc32\release\armv5\udeb\libgsttypefindfunctions.dll"-"!:\sys\bin\libgsttypefindfunctions.dll"
+"\epoc32\release\armv5\udeb\libgstwavparse.dll"-"!:\sys\bin\libgstwavparse.dll"
+"\epoc32\release\armv5\udeb\libgstwavenc.dll"-"!:\sys\bin\libgstwavenc.dll"
+"\epoc32\release\armv5\udeb\libgstaudioconvert.dll"-"!:\sys\bin\libgstaudioconvert.dll"
+"\epoc32\release\armv5\udeb\libgstqueue2.dll"-"!:\sys\bin\libgstqueue2.dll"
+"\epoc32\release\armv5\udeb\libgstautodetect.dll"-"!:\sys\bin\libgstautodetect.dll"
+
 "\epoc32\release\armv5\urel\GStreamerTestClass.dll"-"c:\sys\bin\GStreamerTestClass.dll"
 "..\Conf\GStreamerTestClass.cfg"-"c:\TestFramework\GStreamerTestClass.cfg"
 "..\init\GStreamerTestClass.ini"-"c:\TestFramework\GStreamerTestClass.ini"
--- a/gst_plugins_symbian/tsrc/gstreamertestmodule/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -26,13 +26,29 @@
 DEFAULT
 
 PRJ_TESTEXPORTS
-#ifdef FF_GSTREAMER
-../data/16khzstereo.mp3 /epoc32/winscw/c/data/16khzstereo.mp3
-#endif
+/epoc32/release/winscw/udeb/libgstcoreelements.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstcoreelements.dll
+/epoc32/release/winscw/udeb/libgstcoreindexers.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstcoreindexers.dll
+/epoc32/release/winscw/udeb/libgstwavparse.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstwavparse.dll
+/epoc32/release/winscw/udeb/libgstwavenc.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstwavenc.dll
+/epoc32/release/winscw/udeb/libgstdevsoundsink.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstdevsoundsink.dll
+/epoc32/release/winscw/udeb/libgstdevsoundsrc.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstdevsoundsrc.dll
+/epoc32/release/winscw/udeb/libgstaudioconvert.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstaudioconvert.dll
+/epoc32/release/winscw/udeb/libgstaudioresample.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstaudioresample.dll
+/epoc32/release/winscw/udeb/libgstaudiotestsrc.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstaudiotestsrc.dll
+/epoc32/release/winscw/udeb/libgstdecodebin.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstdecodebin.dll
+/epoc32/release/winscw/udeb/libgstdecodebin2.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstdecodebin2.dll
+/epoc32/release/winscw/udeb/libgstplaybin.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstplaybin.dll
+/epoc32/release/winscw/udeb/libgsttypefindfunctions.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgsttypefindfunctions.dll
+/epoc32/release/winscw/udeb/libgstqueue2.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstlibgstqueue2.dll
+/epoc32/release/winscw/udeb/libgstaudiorate.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstaudiorate.dll
+/epoc32/release/winscw/udeb/libgstautodetect.dll	/epoc32/release/winscw/udeb/z/sys/bin/plugins/libgstautodetect.dll
+
+../conf/GStreamerTestClass.cfg   /epoc32/winscw/c/TestFramework/GStreamerTestClass.cfg
+../init/GStreamerTestClass.ini   /epoc32/winscw/c/TestFramework/GStreamerTestClass.ini
+
 
 PRJ_TESTMMPFILES
-#ifdef FF_GSTREAMER
 GStreamerTestClass.mmp
-#endif
+
 
 //  End of File
\ No newline at end of file
--- a/gst_plugins_symbian/tsrc/gstreamertestmodule/inc/GStreamerTestClass.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/inc/GStreamerTestClass.h	Fri Apr 16 15:15:52 2010 +0300
@@ -85,6 +85,7 @@
 _LIT( KTagVolumeRampProperty,"volumeramp");
 _LIT( KTagPriorityProperty,"priority");
 _LIT( KTagPereferenceProperty,"preference");
+_LIT( KTagNumBuffersProperty,"num-buffers");
 _LIT( KTagFourCCProperty,"fourcc");
 _LIT( KTagMimeTypeProperty,"mimetype");
 
@@ -101,7 +102,7 @@
 #ifdef __WINSCW__
 _LIT( KGStreamerTestClassLogPath, "\\logs\\testframework\\" ); 
 #else
-_LIT( KGStreamerTestClassLogPath, "e:\\testing\\Log\\" );
+_LIT( KGStreamerTestClassLogPath, "c:\\logs\\" );
 #endif
 
 // Log file
@@ -154,6 +155,9 @@
     GstElement *iFakesink;
     GstElement *iFilesink;
     GstElement *iEncoder;
+    GstElement *iAACEncoder;
+    GstElement *iQtMux;
+    GstElement *iAmrMux;
     GstElement *iFilter;
     GstElement *iWavenc;
     GstBus* iBus;
@@ -213,7 +217,10 @@
 		    ERESAMPLER,
 		    ECONVERTER,
 		    EDEVSOUNDSRC,
-		    EDEVSOUNDSINK
+		    EDEVSOUNDSINK,
+		    ENOKIAAACENCODER,
+		    ENOKIAQTMUX,
+		    ENOKIAAMRMUX,
 		    };
 		
       enum TElementCustomInterfaces
@@ -453,7 +460,11 @@
 		TInt CustomIntfcProp( CStifItemParser& aItem );
 		
 		TInt SetCapsInPipeLine( CStifItemParser& aItem );
-		
+		TInt StopRecording( CStifItemParser& aItem );
+		TInt GstReliabilitytestRecording( CStifItemParser& aItem );
+		TInt GstReliabilitytestPlaypause( CStifItemParser& aItem );
+		TInt SeekElement( CStifItemParser& aItem );
+		TInt CheckProperties ( CStifItemParser& aItem );
 		TInt SetMainLoopRun( CStifItemParser& aItem );
 		TInt GetConfigureData();
 		TInt SetConfigureData();
--- a/gst_plugins_symbian/tsrc/gstreamertestmodule/src/GStreamerTestClassBlocks.cpp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/src/GStreamerTestClassBlocks.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -30,6 +30,7 @@
 #include "debug.h"
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 
 _LIT8(defaultMedia,"audio/x-raw-int");
@@ -113,6 +114,9 @@
     iFakesink = NULL;
     iFilesink = NULL;
     iEncoder = NULL;
+    iAACEncoder = NULL;
+    iQtMux = NULL;
+    iAmrMux = NULL;
     iFilter = NULL;
     iWavenc = NULL;
     iBus = NULL;
@@ -184,6 +188,14 @@
       g_error_free (err);
       break;
     }
+    case GST_MESSAGE_STATE_CHANGED:
+        {
+        GstState*  state = NULL;
+        GstState * pending = NULL;
+        gst_element_get_state(GST_ELEMENT (objects->iPipeline),state,pending,-1 );
+        //int x = 10;
+        }
+        break;
     default:
       break;
   }
@@ -264,7 +276,11 @@
         ENTRY( "SetExpectedEvents", CGStreamerTestClass::SetExpectedEvents ),
         ENTRY( "SetMainLoopRun", CGStreamerTestClass::SetMainLoopRun ),
         ENTRY( "SetCapsInPipeLine", CGStreamerTestClass::SetCapsInPipeLine ),
-		
+        ENTRY( "StopRecording", CGStreamerTestClass::StopRecording ),
+        ENTRY( "SeekElement", CGStreamerTestClass::SeekElement ),
+        ENTRY( "CheckProperties", CGStreamerTestClass::CheckProperties ),
+        ENTRY( "GstReliabilitytestPlaypause", CGStreamerTestClass::GstReliabilitytestPlaypause ),
+        ENTRY( "GstReliabilitytestRecording", CGStreamerTestClass::GstReliabilitytestRecording ),
         };
 
     const TInt count = sizeof( KFunctions ) / 
@@ -594,6 +610,8 @@
     iLog->Log(_L("<<CGStreamerTestClass::InitPipeLine"));   
     return KErrNone;
     }
+	
+
 
 TInt CGStreamerTestClass::SetMainLoopRun( CStifItemParser& /*aItem*/ )
     {
@@ -740,6 +758,48 @@
                 }
             break;
             }
+        case   ENOKIAAACENCODER:	        
+            {
+            if(iObjects->iAACEncoder)
+                {
+                error = KErrAlreadyExists;
+                }
+            else
+                {
+                iObjects->iAACEncoder = gst_element_factory_make("nokiaaacenc", "nokiaaacenc");     
+                if( iObjects->iAACEncoder == NULL )
+                    iLog->Log(_L(" iObjects->iAACEncoder == NULL"));
+                }
+            break;
+            }
+        case   ENOKIAQTMUX:            
+            {
+            if(iObjects->iQtMux)
+                {
+                error = KErrAlreadyExists;
+                }
+            else
+                {
+                iObjects->iQtMux = gst_element_factory_make("mp4mux", "mp4mux");     
+                if( iObjects->iQtMux == NULL )
+                    iLog->Log(_L(" iObjects->iQtMux == NULL"));
+                }
+            break;
+            }       
+        case   ENOKIAAMRMUX:            
+            {
+            if(iObjects->iAmrMux)
+                {
+                error = KErrAlreadyExists;
+                }
+            else
+                {
+                iObjects->iAmrMux = gst_element_factory_make("amrmux", "amrmux");     
+                if( iObjects->iAmrMux == NULL )
+                    iLog->Log(_L(" iObjects->iAmrMux == NULL"));
+                }
+            break;
+            }            
 	    case   ERESAMPLER:
             {
             if(iObjects->iResampler)
@@ -890,6 +950,42 @@
                 }
             break;
             }
+        case   ENOKIAAACENCODER:
+            {
+            if(!iObjects->iAACEncoder)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                }
+            break;
+            }            
+        case   ENOKIAQTMUX:
+            {
+            if(!iObjects->iQtMux)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                }
+            break;
+            }              
+        case   ENOKIAAMRMUX:
+            {
+            if(!iObjects->iAmrMux)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                    gboolean header;
+                    g_object_get (G_OBJECT (iObjects->iAmrMux), "header", &header, NULL); 
+
+                }
+            break;
+            }             
         case   ERESAMPLER:
             {
             if(!iObjects->iResampler)
@@ -956,6 +1052,17 @@
                     FTRACE(FPrint(_L("CGStreamerTestClass::GetElementProperties SamplesRecorded[%d]"),value));
                     iLog->Log(_L("CGStreamerTestClass::GetElementProperties SamplesRecorded[%d]"),value);
                     }
+				else if(!property.Compare(KTagLeftBalanceProperty()))
+                    {                  
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+                     }             
+          
+                else if(!property.Compare(KTagRightBalanceProperty()))
+                    {
+                    
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+
+                        }	
                 delete prop;
                 }
             break;
@@ -1119,6 +1226,42 @@
                 }
             break;
             }
+        case   ENOKIAAACENCODER:
+            {
+            if(!iObjects->iAACEncoder)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                }
+            break;
+            }            
+        case   ENOKIAQTMUX:
+            {
+            if(!iObjects->iQtMux)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                }
+            break;
+            }               
+        case   ENOKIAAMRMUX:
+            {
+            if(!iObjects->iAmrMux)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                    TInt value;
+                    aItem.GetNextInt(value);
+                    g_object_set (G_OBJECT (iObjects->iAmrMux), "header", (gboolean)value, NULL);                     
+                }
+            break;
+            }              
         case   ERESAMPLER:
             {
             if(!iObjects->iResampler)
@@ -1239,6 +1382,18 @@
                         error = KErrNotFound;
                         }
                     }
+                else if(!property.Compare(KTagNumBuffersProperty()))
+                    {
+                    TInt value;
+                    if(!aItem.GetNextInt(value))
+                        {
+                        g_object_set (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), value, NULL); 
+                        }
+                    else
+                        {
+                        error = KErrNotFound;
+                        }
+                    }
                 delete prop;
                 }
             break;
@@ -1492,6 +1647,45 @@
                 }
             break;
             }
+        case   ENOKIAAACENCODER:
+            {
+            iLog->Log(_L("<<CGStreamerTestClass::AddElementToPipeline ENOKIAAACENCODER"));
+            if(!iObjects->iAACEncoder)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                gst_bin_add_many(GST_BIN (iObjects->iPipeline),iObjects->iAACEncoder, NULL);
+                }
+            break;
+            }            
+        case   ENOKIAQTMUX:
+            {
+            
+            if(!iObjects->iQtMux)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                gst_bin_add_many(GST_BIN (iObjects->iPipeline),iObjects->iQtMux, NULL);
+                }
+            break;
+            }     
+        case   ENOKIAAMRMUX:
+            {
+            
+            if(!iObjects->iAmrMux)
+                {
+                error = KErrNotFound;
+                }
+            else
+                {
+                gst_bin_add_many(GST_BIN (iObjects->iPipeline),iObjects->iAmrMux, NULL);
+                }
+            break;
+            }             
         case   ERESAMPLER:
             {
             if(!iObjects->iResampler)
@@ -1566,6 +1760,8 @@
     return error;
     }
 
+
+
 TInt CGStreamerTestClass::SetCapsInPipeLine( CStifItemParser& aItem )
     {
     TInt error(KErrNone);
@@ -2249,6 +2445,42 @@
                     }
                 break;
                 }
+            case   ENOKIAAACENCODER:
+                {
+                if(!iObjects->iAACEncoder)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    array.Append(iObjects->iAACEncoder);
+                    }
+                break;
+                }                
+            case   ENOKIAQTMUX:
+                {
+                if(!iObjects->iQtMux)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    array.Append(iObjects->iQtMux);
+                    }
+                break;
+                }                  
+            case   ENOKIAAMRMUX:
+                {
+                if(!iObjects->iAmrMux)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    array.Append(iObjects->iAmrMux);
+                    }
+                break;
+                }                 
             case   ERESAMPLER:
                 {
                 if(!iObjects->iResampler)
@@ -2326,7 +2558,31 @@
                 }
             else
                 {
-                linkOK = gst_element_link(array[i-1],array[i]);
+                    if( array[i] == iObjects->iQtMux)
+                    {
+                        iLog->Log(_L("array[i] == iObjects->iQtMux"));
+                        GstPad* qtsinkpad  = gst_element_get_request_pad( array[i], "audio_%d");
+                        if( !qtsinkpad )
+                            {
+                                iLog->Log(_L("qtsinkpad failed"));
+                            }
+                        GstPad* aacencsrcpad  = gst_element_get_pad( array[i-1], "src");
+                        if( !aacencsrcpad )
+                            {
+                                iLog->Log(_L("aacencsrcpad failed"));
+                            }
+                        
+                        //linkOK = gst_pad_link (aacencsrcpad,qtsinkpad);
+                        if( gst_pad_link (aacencsrcpad,qtsinkpad) != GST_PAD_LINK_OK )
+                            {
+                        iLog->Log(_L("gst_pad_link (aacencsrcpad,qtsinkpad) failed"));
+                        linkOK = 0;
+                            }
+                    }
+                    else
+                    {    
+                        linkOK = gst_element_link(array[i-1],array[i]);
+                    }
                 }
             }        
         }
@@ -2337,4 +2593,420 @@
     }
 
 
+
+
+
+
+
+
+
+
+
+
+
+TInt CGStreamerTestClass::StopRecording( CStifItemParser& /*aItem*/ )
+    {   
+    FTRACE(FPrint(_L("CGStreamerTestClass::StopRecording")));
+    iLog->Log(_L(">>CGStreamerTestClass::StopRecording"));   
+    gst_element_send_event (iObjects->iPipeline, gst_event_new_eos ());
+    iLog->Log(_L("<<CGStreamerTestClass::StopRecording"));   
+    return KErrNone;
+    }
+
+TInt CGStreamerTestClass::GstReliabilitytestRecording( CStifItemParser& aItem )
+    {   
+    FTRACE(FPrint(_L("CGStreamerTestClass::GstReliabilitytestRecording")));
+    iLog->Log(_L(">>CGStreamerTestClass::GstReliabilitytestRecording"));   
+    TInt i=0;
+    aItem.GetNextInt(i);
+    while(--i)
+        {
+         gst_element_set_state (iObjects->iPipeline, GST_STATE_PLAYING );
+         sleep (60);
+        }
+    iLog->Log(_L("<<CGStreamerTestClass::GstReliabilitytestRecording"));   
+    return KErrNone;
+    }
+
+
+TInt CGStreamerTestClass::GstReliabilitytestPlaypause( CStifItemParser& aItem )
+    {   
+    FTRACE(FPrint(_L("CGStreamerTestClass::GstReliabilitytestPlaypause")));
+    iLog->Log(_L(">>CGStreamerTestClass::GstReliabilitytestPlaypause"));   
+    TInt i=0;
+    aItem.GetNextInt(i);
+    //aItem.GetNextInt(element);
+    while( --i )
+        {
+        gst_element_set_state (iObjects->iPipeline, GST_STATE_PLAYING );
+        sleep(10);
+        gst_element_set_state (iObjects->iPipeline, GST_STATE_PAUSED );
+        sleep(2);
+        }
+    iLog->Log(_L("<<CGStreamerTestClass::GstReliabilitytestPlaypause"));   
+    return KErrNone;
+    }
+
+static gint convert_devsound_rate(gint devsound_rate)
+    {
+    gint result;
+
+    switch (devsound_rate)
+        {
+        case 1:
+            result=8000;
+            break;
+        case 2:
+            result=11025;
+            break;
+        case 4:
+            result=16000;
+            break;
+        case 8:
+            result=22050;
+            break;
+        case 16:
+            result=32000;
+            break;
+        case 32:
+            result=44100;
+            break;
+        case 64:
+            result=48000;
+            break;
+        case 128:
+            result=88200;
+            break;
+        case 256:
+            result=96000;
+            break;
+        case 512:
+            result=12000;
+            break;
+        case 1024:
+            result=24000;
+            break;
+        case 2048:
+            result=64000;
+            break;
+        default:
+            result=8000;
+            break;
+
+        }
+    return result;
+
+    }
+
+TInt CGStreamerTestClass::CheckProperties( CStifItemParser& aItem )
+    {   
+    FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties")));
+    iLog->Log(_L(">>CGStreamerTestClass::CheckProperties"));   
+    TInt error = KErrNone;
+    TInt element;
+    TInt ValueExpected(0);
+    aItem.GetNextInt(element);
+        switch(element)
+            {
+            case   EFILESOURCE:
+                {
+                if(!iObjects->iSource)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EFILESINK:
+                {
+                if(!iObjects->iSink)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EFAKESOURCE:
+                {
+                if(!iObjects->iSource)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EFAKESINK:
+                {
+                if(!iObjects->iSink)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EWAVPARSE:
+                {
+                if(!iObjects->iWavparse)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EMP3DECODER:
+                {
+                if(!iObjects->iDecoder)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EWAVEENCODER:
+                {
+                if(!iObjects->iEncoder)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   ENOKIAAACENCODER:
+                {
+                if(!iObjects->iAACEncoder)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   ENOKIAQTMUX:
+                {
+                if(!iObjects->iQtMux)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   ENOKIAAMRMUX:
+                {
+                if(!iObjects->iAmrMux)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }                
+            case   ERESAMPLER:
+                {
+                if(!iObjects->iResampler)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   ECONVERTER:
+                {
+                if(!iObjects->iConverter)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    }
+                break;
+                }
+            case   EDEVSOUNDSRC:
+                {
+                if(!iObjects->iSource)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    TPtrC property;
+                    TInt value(0);
+                    aItem.GetNextString(property);
+                    aItem.GetNextInt(ValueExpected);
+                    HBufC8* prop = HBufC8::NewL(property.Length()+ 1);
+                    TPtr8 des = prop->Des();
+                    des.Copy(property);
+                    if(!property.Compare(KTagGainProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties GetGain[%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties GetGain[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagRateProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL);
+                        value = convert_devsound_rate(value);
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties GetRate[%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties GetRate[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagChannelsProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties Channels[%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties channels[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagMaxGainProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties MaxGain[%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties Max Gain[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagSamplesRecordedProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties SamplesRecorded[%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties SamplesRecorded[%d]"),value);
+                        }
+
+                    else if(!property.Compare(KTagLeftBalanceProperty()))
+                        {                  
+                            g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+                         }             
+              
+                    else if(!property.Compare(KTagRightBalanceProperty()))
+                        {
+                        
+                            g_object_get (G_OBJECT (iObjects->iSource),(const char *)(des.PtrZ()), &value, NULL); 
+
+                            }
+                   
+                    if(value == ValueExpected)
+                        {
+                    FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties EDEVSOUNDSRC OK")));
+                    iLog->Log(_L("CGStreamerTestClass::CheckProperties EDEVSOUNDSRC OK " ));
+                        }
+                    else
+                        {
+                    FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties EDEVSOUNDSRC Error ValueExpected [%d]"),ValueExpected));
+                    iLog->Log(_L("CGStreamerTestClass::CheckProperties EDEVSOUNDSRC ValueExpected [%d]"),ValueExpected);
+                        error = KErrGeneral;
+                        gst_element_set_state (iObjects->iPipeline,GST_STATE_NULL);
+                        }
+                    delete prop;
+                    }
+                break;
+                }            
+            case   EDEVSOUNDSINK:
+                {
+                if(!iObjects->iSink)
+                    {
+                    error = KErrNotFound;
+                    }
+                else
+                    {
+                    TPtrC property;
+                    TInt value(0);
+                    aItem.GetNextString(property);
+                    HBufC8* prop = HBufC8::NewL(property.Length()+ 1);
+                    TPtr8 des = prop->Des();
+                    des.Copy(property);
+                    if(!property.Compare(KTagVolumeProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSink),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties Volume[%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties Volume[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagRateProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSink),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties rate [%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties rate[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagChannelsProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSink),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties channels [%d]"),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties channels[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagMaxVolumeProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSink),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties max vol[%d] "),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties max vol[%d]"),value);
+                        }
+                    else if(!property.Compare(KTagSamplesPlayedProperty()))
+                        {
+                        g_object_get (G_OBJECT (iObjects->iSink),(const char *)(des.PtrZ()), &value, NULL); 
+                        FTRACE(FPrint(_L("CGStreamerTestClass::CheckProperties samples played[%d] "),value));
+                        iLog->Log(_L("CGStreamerTestClass::CheckProperties samples played[%d]"),value);
+                        }
+                    delete prop;
+                    }
+                break;
+                }
+            default:
+                error = KErrNotFound;
+                break;
+            }
+        iLog->Log(_L(">>CGStreamerTestClass::CheckProperties Error[%d]"),error);
+        return error;
+    iLog->Log(_L("<<CGStreamerTestClass::CheckProperties"));   
+    return KErrNone;
+    }
+
+TInt CGStreamerTestClass::SeekElement( CStifItemParser& aItem )
+    {   
+    FTRACE(FPrint(_L("CGStreamerTestClass::SeekElement")));
+    iLog->Log(_L(">>CGStreamerTestClass::SeekElement"));   
+    //
+    TInt time;
+    GstFormat fmt = GST_FORMAT_TIME;
+    gint64 pos1, len1 , pos2 , len2;
+
+    aItem.GetNextInt(time);
+    if (gst_element_query_position (iObjects->iPipeline, &fmt, &pos1)
+      && gst_element_query_duration (iObjects->iPipeline, &fmt, &len1)) {
+    iLog->Log(_L("CGStreamerTestClass:: before seek query position and duration error"));
+    }
+    pos1 = (pos1 / GST_SECOND ) ;
+    len1 = (len1 / GST_SECOND ) ;
+    time = pos1 + (time);
+    if (!gst_element_seek (iObjects->iPipeline, 1.0 , GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE,
+                             GST_SEEK_TYPE_SET, time*GST_SECOND ,
+                             GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+    iLog->Log(_L("<<CGStreamerTestClass::SeekElement Failed"));
+      }
+
+    if (gst_element_query_position (iObjects->iPipeline, &fmt, &pos2)
+      && gst_element_query_duration (iObjects->iPipeline, &fmt, &len2)) {
+    iLog->Log(_L("CGStreamerTestClass:: after seek query position and duration error"));
+    }
+    pos2 = (pos2 / GST_SECOND ) ;
+    len2 = (len2 / GST_SECOND ) ;
+    iLog->Log(_L("<<CGStreamerTestClass::SeekElement"));   
+    return KErrNone;
+    }
+
+
+
+
 //  End of File
--- a/gstreamer_core/bwins/libgstbaseu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/bwins/libgstbaseu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,80 +1,175 @@
-EXPORTS
-	gst_adapter_available @ 1 NONAME
+EXPORTS	gst_adapter_available @ 1 NONAME
 	gst_adapter_available_fast @ 2 NONAME
 	gst_adapter_clear @ 3 NONAME
 	gst_adapter_copy @ 4 NONAME
 	gst_adapter_flush @ 5 NONAME
 	gst_adapter_get_type @ 6 NONAME
-	gst_adapter_new @ 7 NONAME
-	gst_adapter_peek @ 8 NONAME
-	gst_adapter_push @ 9 NONAME
-	gst_adapter_take @ 10 NONAME
-	gst_adapter_take_buffer @ 11 NONAME
-	gst_base_sink_get_last_buffer @ 12 NONAME
-	gst_base_sink_get_latency @ 13 NONAME
-	gst_base_sink_get_max_lateness @ 14 NONAME
-	gst_base_sink_get_sync @ 15 NONAME
-	gst_base_sink_get_ts_offset @ 16 NONAME
-	gst_base_sink_get_type @ 17 NONAME
-	gst_base_sink_is_async_enabled @ 18 NONAME
-	gst_base_sink_is_qos_enabled @ 19 NONAME
-	gst_base_sink_query_latency @ 20 NONAME
-	gst_base_sink_set_async_enabled @ 21 NONAME
-	gst_base_sink_set_max_lateness @ 22 NONAME
-	gst_base_sink_set_qos_enabled @ 23 NONAME
-	gst_base_sink_set_sync @ 24 NONAME
-	gst_base_sink_set_ts_offset @ 25 NONAME
-	gst_base_sink_wait_eos @ 26 NONAME
-	gst_base_sink_wait_preroll @ 27 NONAME
-	gst_base_src_get_do_timestamp @ 28 NONAME
-	gst_base_src_get_type @ 29 NONAME
-	gst_base_src_is_live @ 30 NONAME
-	gst_base_src_query_latency @ 31 NONAME
-	gst_base_src_set_do_timestamp @ 32 NONAME
-	gst_base_src_set_format @ 33 NONAME
-	gst_base_src_set_live @ 34 NONAME
-	gst_base_src_wait_playing @ 35 NONAME
-	gst_base_transform_get_type @ 36 NONAME
-	gst_base_transform_is_in_place @ 37 NONAME
-	gst_base_transform_is_passthrough @ 38 NONAME
-	gst_base_transform_is_qos_enabled @ 39 NONAME
-	gst_base_transform_set_gap_aware @ 40 NONAME
-	gst_base_transform_set_in_place @ 41 NONAME
-	gst_base_transform_set_passthrough @ 42 NONAME
-	gst_base_transform_set_qos_enabled @ 43 NONAME
-	gst_base_transform_update_qos @ 44 NONAME
-	gst_collect_pads_add_pad @ 45 NONAME
-	gst_collect_pads_add_pad_full @ 46 NONAME
-	gst_collect_pads_available @ 47 NONAME
-	gst_collect_pads_collect @ 48 NONAME
-	gst_collect_pads_collect_range @ 49 NONAME
-	gst_collect_pads_flush @ 50 NONAME
-	gst_collect_pads_get_type @ 51 NONAME
-	gst_collect_pads_is_active @ 52 NONAME
-	gst_collect_pads_new @ 53 NONAME
-	gst_collect_pads_peek @ 54 NONAME
-	gst_collect_pads_pop @ 55 NONAME
-	gst_collect_pads_read @ 56 NONAME
-	gst_collect_pads_read_buffer @ 57 NONAME
-	gst_collect_pads_remove_pad @ 58 NONAME
-	gst_collect_pads_set_flushing @ 59 NONAME
-	gst_collect_pads_set_function @ 60 NONAME
-	gst_collect_pads_start @ 61 NONAME
-	gst_collect_pads_stop @ 62 NONAME
-	gst_collect_pads_take_buffer @ 63 NONAME
-	gst_data_queue_drop_head @ 64 NONAME
-	gst_data_queue_flush @ 65 NONAME
-	gst_data_queue_get_level @ 66 NONAME
-	gst_data_queue_get_type @ 67 NONAME
-	gst_data_queue_is_empty @ 68 NONAME
-	gst_data_queue_is_full @ 69 NONAME
-	gst_data_queue_limits_changed @ 70 NONAME
-	gst_data_queue_new @ 71 NONAME
-	gst_data_queue_pop @ 72 NONAME
-	gst_data_queue_push @ 73 NONAME
-	gst_data_queue_set_flushing @ 74 NONAME
-	gst_push_src_get_type @ 75 NONAME
-	gst_type_find_helper @ 76 NONAME
-	gst_type_find_helper_for_buffer @ 77 NONAME
-	gst_type_find_helper_get_range @ 78 NONAME
+	gst_adapter_masked_scan_uint32 @ 7 NONAME
+	gst_adapter_new @ 8 NONAME
+	gst_adapter_peek @ 9 NONAME
+	gst_adapter_prev_timestamp @ 10 NONAME
+	gst_adapter_push @ 11 NONAME
+	gst_adapter_take @ 12 NONAME
+	gst_adapter_take_buffer @ 13 NONAME
+	gst_base_sink_do_preroll @ 14 NONAME
+	gst_base_sink_get_blocksize @ 15 NONAME
+	gst_base_sink_get_last_buffer @ 16 NONAME
+	gst_base_sink_get_latency @ 17 NONAME
+	gst_base_sink_get_max_lateness @ 18 NONAME
+	gst_base_sink_get_render_delay @ 19 NONAME
+	gst_base_sink_get_sync @ 20 NONAME
+	gst_base_sink_get_ts_offset @ 21 NONAME
+	gst_base_sink_get_type @ 22 NONAME
+	gst_base_sink_is_async_enabled @ 23 NONAME
+	gst_base_sink_is_qos_enabled @ 24 NONAME
+	gst_base_sink_query_latency @ 25 NONAME
+	gst_base_sink_set_async_enabled @ 26 NONAME
+	gst_base_sink_set_blocksize @ 27 NONAME
+	gst_base_sink_set_max_lateness @ 28 NONAME
+	gst_base_sink_set_qos_enabled @ 29 NONAME
+	gst_base_sink_set_render_delay @ 30 NONAME
+	gst_base_sink_set_sync @ 31 NONAME
+	gst_base_sink_set_ts_offset @ 32 NONAME
+	gst_base_sink_wait_clock @ 33 NONAME
+	gst_base_sink_wait_eos @ 34 NONAME
+	gst_base_sink_wait_preroll @ 35 NONAME
+	gst_base_src_get_blocksize @ 36 NONAME
+	gst_base_src_get_do_timestamp @ 37 NONAME
+	gst_base_src_get_type @ 38 NONAME
+	gst_base_src_is_live @ 39 NONAME
+	gst_base_src_query_latency @ 40 NONAME
+	gst_base_src_set_blocksize @ 41 NONAME
+	gst_base_src_set_do_timestamp @ 42 NONAME
+	gst_base_src_set_format @ 43 NONAME
+	gst_base_src_set_live @ 44 NONAME
+	gst_base_src_wait_playing @ 45 NONAME
+	gst_base_transform_get_type @ 46 NONAME
+	gst_base_transform_is_in_place @ 47 NONAME
+	gst_base_transform_is_passthrough @ 48 NONAME
+	gst_base_transform_is_qos_enabled @ 49 NONAME
+	gst_base_transform_reconfigure @ 50 NONAME
+	gst_base_transform_set_gap_aware @ 51 NONAME
+	gst_base_transform_set_in_place @ 52 NONAME
+	gst_base_transform_set_passthrough @ 53 NONAME
+	gst_base_transform_set_qos_enabled @ 54 NONAME
+	gst_base_transform_suggest @ 55 NONAME
+	gst_base_transform_update_qos @ 56 NONAME
+	gst_bit_reader_free @ 57 NONAME
+	gst_bit_reader_get_bits_uint16 @ 58 NONAME
+	gst_bit_reader_get_bits_uint32 @ 59 NONAME
+	gst_bit_reader_get_bits_uint64 @ 60 NONAME
+	gst_bit_reader_get_bits_uint8 @ 61 NONAME
+	gst_bit_reader_get_pos @ 62 NONAME
+	gst_bit_reader_get_remaining @ 63 NONAME
+	gst_bit_reader_init @ 64 NONAME
+	gst_bit_reader_init_from_buffer @ 65 NONAME
+	gst_bit_reader_new @ 66 NONAME
+	gst_bit_reader_new_from_buffer @ 67 NONAME
+	gst_bit_reader_peek_bits_uint16 @ 68 NONAME
+	gst_bit_reader_peek_bits_uint32 @ 69 NONAME
+	gst_bit_reader_peek_bits_uint64 @ 70 NONAME
+	gst_bit_reader_peek_bits_uint8 @ 71 NONAME
+	gst_bit_reader_set_pos @ 72 NONAME
+	gst_bit_reader_skip @ 73 NONAME
+	gst_bit_reader_skip_to_byte @ 74 NONAME
+	gst_byte_reader_dup_data @ 75 NONAME
+	gst_byte_reader_dup_string_utf16 @ 76 NONAME
+	gst_byte_reader_dup_string_utf32 @ 77 NONAME
+	gst_byte_reader_dup_string_utf8 @ 78 NONAME
+	gst_byte_reader_free @ 79 NONAME
+	gst_byte_reader_get_data @ 80 NONAME
+	gst_byte_reader_get_float32_be @ 81 NONAME
+	gst_byte_reader_get_float32_le @ 82 NONAME
+	gst_byte_reader_get_float64_be @ 83 NONAME
+	gst_byte_reader_get_float64_le @ 84 NONAME
+	gst_byte_reader_get_int16_be @ 85 NONAME
+	gst_byte_reader_get_int16_le @ 86 NONAME
+	gst_byte_reader_get_int24_be @ 87 NONAME
+	gst_byte_reader_get_int24_le @ 88 NONAME
+	gst_byte_reader_get_int32_be @ 89 NONAME
+	gst_byte_reader_get_int32_le @ 90 NONAME
+	gst_byte_reader_get_int64_be @ 91 NONAME
+	gst_byte_reader_get_int64_le @ 92 NONAME
+	gst_byte_reader_get_int8 @ 93 NONAME
+	gst_byte_reader_get_pos @ 94 NONAME
+	gst_byte_reader_get_remaining @ 95 NONAME
+	gst_byte_reader_get_string_utf8 @ 96 NONAME
+	gst_byte_reader_get_uint16_be @ 97 NONAME
+	gst_byte_reader_get_uint16_le @ 98 NONAME
+	gst_byte_reader_get_uint24_be @ 99 NONAME
+	gst_byte_reader_get_uint24_le @ 100 NONAME
+	gst_byte_reader_get_uint32_be @ 101 NONAME
+	gst_byte_reader_get_uint32_le @ 102 NONAME
+	gst_byte_reader_get_uint64_be @ 103 NONAME
+	gst_byte_reader_get_uint64_le @ 104 NONAME
+	gst_byte_reader_get_uint8 @ 105 NONAME
+	gst_byte_reader_init @ 106 NONAME
+	gst_byte_reader_init_from_buffer @ 107 NONAME
+	gst_byte_reader_masked_scan_uint32 @ 108 NONAME
+	gst_byte_reader_new @ 109 NONAME
+	gst_byte_reader_new_from_buffer @ 110 NONAME
+	gst_byte_reader_peek_data @ 111 NONAME
+	gst_byte_reader_peek_float32_be @ 112 NONAME
+	gst_byte_reader_peek_float32_le @ 113 NONAME
+	gst_byte_reader_peek_float64_be @ 114 NONAME
+	gst_byte_reader_peek_float64_le @ 115 NONAME
+	gst_byte_reader_peek_int16_be @ 116 NONAME
+	gst_byte_reader_peek_int16_le @ 117 NONAME
+	gst_byte_reader_peek_int24_be @ 118 NONAME
+	gst_byte_reader_peek_int24_le @ 119 NONAME
+	gst_byte_reader_peek_int32_be @ 120 NONAME
+	gst_byte_reader_peek_int32_le @ 121 NONAME
+	gst_byte_reader_peek_int64_be @ 122 NONAME
+	gst_byte_reader_peek_int64_le @ 123 NONAME
+	gst_byte_reader_peek_int8 @ 124 NONAME
+	gst_byte_reader_peek_string_utf8 @ 125 NONAME
+	gst_byte_reader_peek_uint16_be @ 126 NONAME
+	gst_byte_reader_peek_uint16_le @ 127 NONAME
+	gst_byte_reader_peek_uint24_be @ 128 NONAME
+	gst_byte_reader_peek_uint24_le @ 129 NONAME
+	gst_byte_reader_peek_uint32_be @ 130 NONAME
+	gst_byte_reader_peek_uint32_le @ 131 NONAME
+	gst_byte_reader_peek_uint64_be @ 132 NONAME
+	gst_byte_reader_peek_uint64_le @ 133 NONAME
+	gst_byte_reader_peek_uint8 @ 134 NONAME
+	gst_byte_reader_set_pos @ 135 NONAME
+	gst_byte_reader_skip @ 136 NONAME
+	gst_byte_reader_skip_string_utf16 @ 137 NONAME
+	gst_byte_reader_skip_string_utf32 @ 138 NONAME
+	gst_byte_reader_skip_string_utf8 @ 139 NONAME
+	gst_collect_pads_add_pad @ 140 NONAME
+	gst_collect_pads_add_pad_full @ 141 NONAME
+	gst_collect_pads_available @ 142 NONAME
+	gst_collect_pads_collect @ 143 NONAME
+	gst_collect_pads_collect_range @ 144 NONAME
+	gst_collect_pads_flush @ 145 NONAME
+	gst_collect_pads_get_type @ 146 NONAME
+	gst_collect_pads_is_active @ 147 NONAME
+	gst_collect_pads_new @ 148 NONAME
+	gst_collect_pads_peek @ 149 NONAME
+	gst_collect_pads_pop @ 150 NONAME
+	gst_collect_pads_read @ 151 NONAME
+	gst_collect_pads_read_buffer @ 152 NONAME
+	gst_collect_pads_remove_pad @ 153 NONAME
+	gst_collect_pads_set_flushing @ 154 NONAME
+	gst_collect_pads_set_function @ 155 NONAME
+	gst_collect_pads_start @ 156 NONAME
+	gst_collect_pads_stop @ 157 NONAME
+	gst_collect_pads_take_buffer @ 158 NONAME
+	gst_data_queue_drop_head @ 159 NONAME
+	gst_data_queue_flush @ 160 NONAME
+	gst_data_queue_get_level @ 161 NONAME
+	gst_data_queue_get_type @ 162 NONAME
+	gst_data_queue_is_empty @ 163 NONAME
+	gst_data_queue_is_full @ 164 NONAME
+	gst_data_queue_limits_changed @ 165 NONAME
+	gst_data_queue_new @ 166 NONAME
+	gst_data_queue_pop @ 167 NONAME
+	gst_data_queue_push @ 168 NONAME
+	gst_data_queue_set_flushing @ 169 NONAME
+	gst_push_src_get_type @ 170 NONAME
+	gst_type_find_helper @ 171 NONAME
+	gst_type_find_helper_for_buffer @ 172 NONAME
+	gst_type_find_helper_for_extension @ 173 NONAME
+	gst_type_find_helper_get_range @ 174 NONAME
 
--- a/gstreamer_core/bwins/libgstcoreelementsu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/bwins/libgstcoreelementsu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -12,4 +12,5 @@
 	gst_queue_get_type @ 11 NONAME
 	gst_tee_get_type @ 12 NONAME
 	gst_type_find_element_get_type @ 13 NONAME
+	gst_open @ 14 NONAME
 
--- a/gstreamer_core/bwins/libgstreameru.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/bwins/libgstreameru.def	Fri Apr 16 15:15:52 2010 +0300
@@ -984,4 +984,181 @@
 	send_failure_info @ 983 NONAME
 	std_log @ 984 NONAME
 	testResultXml @ 985 NONAME
+	_gst_debug_dump_mem @ 986 NONAME
+	_priv_plugin_deps_env_vars_changed @ 987 NONAME
+	_priv_plugin_deps_files_changed @ 988 NONAME
+	gst_bin_find_unlinked_pad @ 989 NONAME
+	gst_bin_recalculate_latency @ 990 NONAME
+	gst_buffering_mode_get_type @ 991 NONAME
+	gst_check_setup_sink_pad_by_name @ 992 NONAME
+	gst_check_setup_src_pad_by_name @ 993 NONAME
+	gst_check_teardown_pad_by_name @ 994 NONAME
+	gst_clock_type_get_type @ 995 NONAME
+	gst_debug_construct_win_color @ 996 NONAME
+	gst_event_get_seqnum @ 997 NONAME
+	gst_event_has_name @ 998 NONAME
+	gst_event_set_seqnum @ 999 NONAME
+	gst_ghost_pad_construct @ 1000 NONAME
+	gst_message_get_seqnum @ 1001 NONAME
+	gst_message_new_request_state @ 1002 NONAME
+	gst_message_new_structure_change @ 1003 NONAME
+	gst_message_parse_buffering_stats @ 1004 NONAME
+	gst_message_parse_request_state @ 1005 NONAME
+	gst_message_parse_structure_change @ 1006 NONAME
+	gst_message_set_buffering_stats @ 1007 NONAME
+	gst_message_set_seqnum @ 1008 NONAME
+	gst_pad_add_buffer_probe_full @ 1009 NONAME
+	gst_pad_add_data_probe_full @ 1010 NONAME
+	gst_pad_add_event_probe_full @ 1011 NONAME
+	gst_pad_iterate_internal_links @ 1012 NONAME
+	gst_pad_iterate_internal_links_default @ 1013 NONAME
+	gst_pad_set_blocked_async_full @ 1014 NONAME
+	gst_pad_set_iterate_internal_links_function @ 1015 NONAME
+	gst_param_spec_mini_object_get_type @ 1016 NONAME
+	gst_parse_bin_from_description_full @ 1017 NONAME
+	gst_parse_context_free @ 1018 NONAME
+	gst_parse_context_get_missing_elements @ 1019 NONAME
+	gst_parse_context_new @ 1020 NONAME
+	gst_parse_flags_get_type @ 1021 NONAME
+	gst_parse_launch_full @ 1022 NONAME
+	gst_parse_launchv_full @ 1023 NONAME
+	gst_plugin_add_dependency @ 1024 NONAME
+	gst_plugin_add_dependency_simple @ 1025 NONAME
+	gst_plugin_dependency_flags_get_type @ 1026 NONAME
+	gst_poll_new_timer @ 1027 NONAME
+	gst_poll_read_control @ 1028 NONAME
+	gst_poll_write_control @ 1029 NONAME
+	gst_preset_delete_preset @ 1030 NONAME
+	gst_preset_get_meta @ 1031 NONAME
+	gst_preset_get_preset_names @ 1032 NONAME
+	gst_preset_get_property_names @ 1033 NONAME
+	gst_preset_get_type @ 1034 NONAME
+	gst_preset_load_preset @ 1035 NONAME
+	gst_preset_rename_preset @ 1036 NONAME
+	gst_preset_save_preset @ 1037 NONAME
+	gst_preset_set_meta @ 1038 NONAME
+	gst_query_new_buffering @ 1039 NONAME
+	gst_query_new_uri @ 1040 NONAME
+	gst_query_parse_buffering_percent @ 1041 NONAME
+	gst_query_parse_buffering_range @ 1042 NONAME
+	gst_query_parse_buffering_stats @ 1043 NONAME
+	gst_query_parse_uri @ 1044 NONAME
+	gst_query_set_buffering_percent @ 1045 NONAME
+	gst_query_set_buffering_range @ 1046 NONAME
+	gst_query_set_buffering_stats @ 1047 NONAME
+	gst_query_set_uri @ 1048 NONAME
+	gst_search_mode_get_type @ 1049 NONAME
+	gst_segment_copy @ 1050 NONAME
+	gst_signal_object_get_type @ 1051 NONAME
+	gst_structure_change_type_get_type @ 1052 NONAME
+	gst_subbuffer_get_type @ 1053 NONAME
+	gst_tag_list_get_buffer @ 1054 NONAME
+	gst_tag_list_get_buffer_index @ 1055 NONAME
+	gst_tag_setter_reset_tags @ 1056 NONAME
+	gst_type_find_suggest_simple @ 1057 NONAME
+	gst_util_array_binary_search @ 1058 NONAME
+	gst_util_seqnum_compare @ 1059 NONAME
+	gst_util_seqnum_next @ 1060 NONAME
+	gst_value_dup_mini_object @ 1061 NONAME
+	GST_CAT_AUTOPLUG @ 1062 NONAME
+	GST_CAT_AUTOPLUG_ATTEMPT @ 1063 NONAME
+	GST_CAT_BUFFER @ 1064 NONAME
+	GST_CAT_BUS @ 1065 NONAME
+	GST_CAT_CALL_TRACE @ 1066 NONAME
+	GST_CAT_CAPS @ 1067 NONAME
+	GST_CAT_CLOCK @ 1068 NONAME
+	GST_CAT_ELEMENT_PADS @ 1069 NONAME
+	GST_CAT_ERROR_SYSTEM @ 1070 NONAME
+	GST_CAT_GST_INIT @ 1071 NONAME
+	GST_CAT_MESSAGE @ 1072 NONAME
+	GST_CAT_NEGOTIATION @ 1073 NONAME
+	GST_CAT_PADS @ 1074 NONAME
+	GST_CAT_PARAMS @ 1075 NONAME
+	GST_CAT_PARENTAGE @ 1076 NONAME
+	GST_CAT_PIPELINE @ 1077 NONAME
+	GST_CAT_PLUGIN_INFO @ 1078 NONAME
+	GST_CAT_PLUGIN_LOADING @ 1079 NONAME
+	GST_CAT_PROBE @ 1080 NONAME
+	GST_CAT_PROPERTIES @ 1081 NONAME
+	GST_CAT_REFCOUNTING @ 1082 NONAME
+	GST_CAT_REGISTRY @ 1083 NONAME
+	GST_CAT_SCHEDULING @ 1084 NONAME
+	GST_CAT_SIGNAL @ 1085 NONAME
+	GST_CAT_STATES @ 1086 NONAME
+	GST_CAT_TYPES @ 1087 NONAME
+	GST_CAT_XML @ 1088 NONAME
+	__gst_debug_min @ 1089 NONAME
+	GST_CAT_BUFFER_LIST @ 1090 NONAME
+	GST_CAT_PERFORMANCE @ 1091 NONAME
+	_gst_buffer_list_initialize @ 1092 NONAME
+	_gst_debug_get_category @ 1093 NONAME
+	gst_buffer_list_foreach @ 1094 NONAME
+	gst_buffer_list_get @ 1095 NONAME
+	gst_buffer_list_get_type @ 1096 NONAME
+	gst_buffer_list_item_get_type @ 1097 NONAME
+	gst_buffer_list_iterate @ 1098 NONAME
+	gst_buffer_list_iterator_add @ 1099 NONAME
+	gst_buffer_list_iterator_add_group @ 1100 NONAME
+	gst_buffer_list_iterator_do @ 1101 NONAME
+	gst_buffer_list_iterator_free @ 1102 NONAME
+	gst_buffer_list_iterator_merge_group @ 1103 NONAME
+	gst_buffer_list_iterator_n_buffers @ 1104 NONAME
+	gst_buffer_list_iterator_next @ 1105 NONAME
+	gst_buffer_list_iterator_next_group @ 1106 NONAME
+	gst_buffer_list_iterator_remove @ 1107 NONAME
+	gst_buffer_list_iterator_steal @ 1108 NONAME
+	gst_buffer_list_iterator_take @ 1109 NONAME
+	gst_buffer_list_n_groups @ 1110 NONAME
+	gst_buffer_list_new @ 1111 NONAME
+	gst_debug_print_stack_trace @ 1112 NONAME
+	gst_element_get_start_time @ 1113 NONAME
+	gst_element_lost_state_full @ 1114 NONAME
+	gst_element_set_start_time @ 1115 NONAME
+	gst_event_new_step @ 1116 NONAME
+	gst_event_parse_step @ 1117 NONAME
+	gst_message_get_stream_status_object @ 1118 NONAME
+	gst_message_new_step_done @ 1119 NONAME
+	gst_message_new_step_start @ 1120 NONAME
+	gst_message_new_stream_status @ 1121 NONAME
+	gst_message_new_tag_full @ 1122 NONAME
+	gst_message_parse_step_done @ 1123 NONAME
+	gst_message_parse_step_start @ 1124 NONAME
+	gst_message_parse_stream_status @ 1125 NONAME
+	gst_message_parse_tag_full @ 1126 NONAME
+	gst_message_set_stream_status_object @ 1127 NONAME
+	gst_object_ref_sink @ 1128 NONAME
+	gst_pad_chain_list @ 1129 NONAME
+	gst_pad_push_list @ 1130 NONAME
+	gst_pad_set_chain_list_function @ 1131 NONAME
+	gst_plugin_get_cache_data @ 1132 NONAME
+	gst_plugin_register_static_full @ 1133 NONAME
+	gst_plugin_set_cache_data @ 1134 NONAME
+	gst_segment_set_running_time @ 1135 NONAME
+	gst_segment_to_position @ 1136 NONAME
+	gst_stream_status_type_get_type @ 1137 NONAME
+	gst_structure_get @ 1138 NONAME
+	gst_structure_get_valist @ 1139 NONAME
+	gst_structure_id_get @ 1140 NONAME
+	gst_structure_id_get_valist @ 1141 NONAME
+	gst_structure_id_new @ 1142 NONAME
+	gst_tag_list_add_value @ 1143 NONAME
+	gst_tag_list_new_full @ 1144 NONAME
+	gst_tag_list_new_full_valist @ 1145 NONAME
+	gst_tag_setter_add_tag_value @ 1146 NONAME
+	gst_task_get_pool @ 1147 NONAME
+	gst_task_pool_cleanup @ 1148 NONAME
+	gst_task_pool_get_type @ 1149 NONAME
+	gst_task_pool_join @ 1150 NONAME
+	gst_task_pool_new @ 1151 NONAME
+	gst_task_pool_prepare @ 1152 NONAME
+	gst_task_pool_push @ 1153 NONAME
+	gst_task_set_pool @ 1154 NONAME
+	gst_task_set_priority @ 1155 NONAME
+	gst_task_set_state @ 1156 NONAME
+	gst_task_set_thread_callbacks @ 1157 NONAME
+	GST_CAT_DEFAULT @ 1158 NONAME
+	GST_CAT_EVENT @ 1159 NONAME
+	GST_CAT_QOS @ 1160 NONAME
+	gst_debug_min @ 1161 NONAME
+	_check_debug @ 1162 NONAME
 
--- a/gstreamer_core/config.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/config.h	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,9 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 	 #undef ENABLE_NLS 
@@ -8,8 +11,14 @@
 /* gettext package name */
 #define GETTEXT_PACKAGE "gstreamer-0.10"
 
+/* data dir */
+#define GST_DATADIR "/usr/local/share"
+//#define GST_DISABLE_GST_DEBUG 1
 /* Define if pipeline parsing code is disabled */
-//#define GST_DISABLE_PARSE 1 
+/* #undef GST_DISABLE_PARSE */
+
+/* Extra platform specific plugin suffix */
+/* #undef GST_EXTRA_MODULE_SUFFIX */
 
 /* macro to use to show function name */
 #define GST_FUNCTION __PRETTY_FUNCTION__
@@ -17,6 +26,9 @@
 /* Defined if gcov is enabled to force a rebuild due to config.h changing */
 /* #undef GST_GCOV_ENABLED */
 
+/* Defined when registry scanning through fork is unsafe */
+/* #undef GST_HAVE_UNSAFE_FORK */
+
 /* Default errorlevel to use */
 #ifdef DEBUG_ENABLE
 #define GST_LEVEL_DEFAULT GST_LEVEL_DEBUG
@@ -36,6 +48,14 @@
 /* package origin */
 #define GST_PACKAGE_ORIGIN "Unknown package origin"
 
+/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
 /* Define to 1 if you have the `clock_gettime' function. */
 #define HAVE_CLOCK_GETTIME 1
 
@@ -159,7 +179,7 @@
 #define HAVE_MMAP 1
 
 /* Have a monotonic clock */
-#define HAVE_MONOTONIC_CLOCK 1
+//#define HAVE_MONOTONIC_CLOCK 1
 
 /* Define to 1 if you have the `poll' function. */
 #ifndef __SYMBIAN32__
@@ -272,20 +292,20 @@
 #define PACKAGE_NAME "GStreamer"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer 0.10.19"
+#define PACKAGE_STRING "GStreamer 0.10.24"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "gstreamer"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.19"
+#define PACKAGE_VERSION "0.10.24"
 
-#define PLUGIN_LIST "c:\\gstreamer\\plugins_list"
-#define PLUGIN_LIST_IN_ROM "z:\\gstreamer\\plugins_list"
-#define GSTREAMER_REGISTERY_PATH "c:\\gstreamer"
-#define GSTREAMER_REGISTERY_PATH_IN_ROM "z:\\gstreamer"
+/// needed for audiofx
+#ifndef G_PARAM_STATIC_STRINGS
+#define	G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
+#endif
 
-#define GST_REGISTRY_GENERATOR "GSTRegistryGenerator.exe"
+
 /* directory where plugins are located */
 #ifdef __SYMBIAN32__
 #if defined(__WINSCW__) || defined(__WINS__)
@@ -312,11 +332,19 @@
 /* #undef USE_POISONING */
 
 /* Version number of package */
-#define VERSION "0.10.19"
+#define VERSION "0.10.24"
 
-/* Define to 1 if your processor stores words with the most significant byte
-   first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
 
 /* Number of bits in a file offset, on hosts where this is settable. */
 #define _FILE_OFFSET_BITS 64
@@ -327,8 +355,23 @@
 /* Define for large files, on AIX-style hosts. */
 /* #undef _LARGE_FILES */
 
+/* We need at least WinXP SP2 for __stat64 */
+/* #undef __MSVCRT_VERSION__ */
+
 /* Define to `__inline__' or `__inline' if that's what the C compiler
    calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus
 /* #undef inline */
+#else
+#ifdef __WINSCW__ 
+_LIT(KResFileNamePath,"\\sys\\bin\\plugins\\");
+#else
+_LIT(KResFileNamePath,"\\sys\\bin\\");
 #endif
+#endif
+
+#define PLUGIN_LIST_TXT_FILE_PATH "c:\\gstreamer\\plugins_list"
+#define PLUGIN_LIST_TXT_FILE_PATH_IN_ROM "z:\\gstreamer\\plugins_list"
+#define GSTREAMER_REGISTERY_PATH "c:\\gstreamer"
+#define GSTREAMER_REGISTERY_PATH_IN_ROM "z:\\gstreamer"
+#define GSTREAMER_TXT_FILE_SUFFIX "txt"
--- a/gstreamer_core/eabi/libgstbaseu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/eabi/libgstbaseu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -77,4 +77,100 @@
 	gst_type_find_helper @ 76 NONAME
 	gst_type_find_helper_for_buffer @ 77 NONAME
 	gst_type_find_helper_get_range @ 78 NONAME
+	gst_base_sink_do_preroll @ 79 NONAME
+	gst_base_sink_get_blocksize @ 80 NONAME
+	gst_base_sink_get_render_delay @ 81 NONAME
+	gst_base_sink_set_blocksize @ 82 NONAME
+	gst_base_sink_set_render_delay @ 83 NONAME
+	gst_base_sink_wait_clock @ 84 NONAME
+	gst_base_src_get_blocksize @ 85 NONAME
+	gst_base_src_set_blocksize @ 86 NONAME
+	gst_base_transform_reconfigure @ 87 NONAME
+	gst_base_transform_suggest @ 88 NONAME
+	gst_bit_reader_free @ 89 NONAME
+	gst_bit_reader_get_pos @ 90 NONAME
+	gst_bit_reader_get_remaining @ 91 NONAME
+	gst_bit_reader_init @ 92 NONAME
+	gst_bit_reader_init_from_buffer @ 93 NONAME
+	gst_bit_reader_new @ 94 NONAME
+	gst_bit_reader_new_from_buffer @ 95 NONAME
+	gst_bit_reader_set_pos @ 96 NONAME
+	gst_bit_reader_skip @ 97 NONAME
+	gst_bit_reader_skip_to_byte @ 98 NONAME
+	gst_byte_reader_free @ 99 NONAME
+	gst_byte_reader_get_data @ 100 NONAME
+	gst_byte_reader_get_int24_be @ 101 NONAME
+	gst_byte_reader_get_int24_le @ 102 NONAME
+	gst_byte_reader_get_int8 @ 103 NONAME
+	gst_byte_reader_get_pos @ 104 NONAME
+	gst_byte_reader_get_remaining @ 105 NONAME
+	gst_byte_reader_get_uint24_be @ 106 NONAME
+	gst_byte_reader_get_uint24_le @ 107 NONAME
+	gst_byte_reader_get_uint8 @ 108 NONAME
+	gst_byte_reader_init @ 109 NONAME
+	gst_byte_reader_init_from_buffer @ 110 NONAME
+	gst_byte_reader_new @ 111 NONAME
+	gst_byte_reader_new_from_buffer @ 112 NONAME
+	gst_byte_reader_peek_data @ 113 NONAME
+	gst_byte_reader_peek_int24_be @ 114 NONAME
+	gst_byte_reader_peek_int24_le @ 115 NONAME
+	gst_byte_reader_peek_int8 @ 116 NONAME
+	gst_byte_reader_peek_uint24_be @ 117 NONAME
+	gst_byte_reader_peek_uint24_le @ 118 NONAME
+	gst_byte_reader_peek_uint8 @ 119 NONAME
+	gst_byte_reader_set_pos @ 120 NONAME
+	gst_byte_reader_skip @ 121 NONAME
+	gst_type_find_helper_for_extension @ 122 NONAME
+	gst_adapter_masked_scan_uint32 @ 123 NONAME
+	gst_adapter_prev_timestamp @ 124 NONAME
+	gst_bit_reader_get_bits_uint16 @ 125 NONAME
+	gst_bit_reader_get_bits_uint32 @ 126 NONAME
+	gst_bit_reader_get_bits_uint64 @ 127 NONAME
+	gst_bit_reader_get_bits_uint8 @ 128 NONAME
+	gst_bit_reader_peek_bits_uint16 @ 129 NONAME
+	gst_bit_reader_peek_bits_uint32 @ 130 NONAME
+	gst_bit_reader_peek_bits_uint64 @ 131 NONAME
+	gst_bit_reader_peek_bits_uint8 @ 132 NONAME
+	gst_byte_reader_dup_data @ 133 NONAME
+	gst_byte_reader_dup_string_utf16 @ 134 NONAME
+	gst_byte_reader_dup_string_utf32 @ 135 NONAME
+	gst_byte_reader_dup_string_utf8 @ 136 NONAME
+	gst_byte_reader_get_float32_be @ 137 NONAME
+	gst_byte_reader_get_float32_le @ 138 NONAME
+	gst_byte_reader_get_float64_be @ 139 NONAME
+	gst_byte_reader_get_float64_le @ 140 NONAME
+	gst_byte_reader_get_int16_be @ 141 NONAME
+	gst_byte_reader_get_int16_le @ 142 NONAME
+	gst_byte_reader_get_int32_be @ 143 NONAME
+	gst_byte_reader_get_int32_le @ 144 NONAME
+	gst_byte_reader_get_int64_be @ 145 NONAME
+	gst_byte_reader_get_int64_le @ 146 NONAME
+	gst_byte_reader_get_string_utf8 @ 147 NONAME
+	gst_byte_reader_get_uint16_be @ 148 NONAME
+	gst_byte_reader_get_uint16_le @ 149 NONAME
+	gst_byte_reader_get_uint32_be @ 150 NONAME
+	gst_byte_reader_get_uint32_le @ 151 NONAME
+	gst_byte_reader_get_uint64_be @ 152 NONAME
+	gst_byte_reader_get_uint64_le @ 153 NONAME
+	gst_byte_reader_masked_scan_uint32 @ 154 NONAME
+	gst_byte_reader_peek_float32_be @ 155 NONAME
+	gst_byte_reader_peek_float32_le @ 156 NONAME
+	gst_byte_reader_peek_float64_be @ 157 NONAME
+	gst_byte_reader_peek_float64_le @ 158 NONAME
+	gst_byte_reader_peek_int16_be @ 159 NONAME
+	gst_byte_reader_peek_int16_le @ 160 NONAME
+	gst_byte_reader_peek_int32_be @ 161 NONAME
+	gst_byte_reader_peek_int32_le @ 162 NONAME
+	gst_byte_reader_peek_int64_be @ 163 NONAME
+	gst_byte_reader_peek_int64_le @ 164 NONAME
+	gst_byte_reader_peek_string_utf8 @ 165 NONAME
+	gst_byte_reader_peek_uint16_be @ 166 NONAME
+	gst_byte_reader_peek_uint16_le @ 167 NONAME
+	gst_byte_reader_peek_uint32_be @ 168 NONAME
+	gst_byte_reader_peek_uint32_le @ 169 NONAME
+	gst_byte_reader_peek_uint64_be @ 170 NONAME
+	gst_byte_reader_peek_uint64_le @ 171 NONAME
+	gst_byte_reader_skip_string_utf16 @ 172 NONAME
+	gst_byte_reader_skip_string_utf32 @ 173 NONAME
+	gst_byte_reader_skip_string_utf8 @ 174 NONAME
 
--- a/gstreamer_core/eabi/libgstcoreelementsu.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/eabi/libgstcoreelementsu.def	Fri Apr 16 15:15:52 2010 +0300
@@ -12,4 +12,5 @@
 	gst_queue_get_type @ 11 NONAME
 	gst_tee_get_type @ 12 NONAME
 	gst_type_find_element_get_type @ 13 NONAME
+	gst_open @ 14 NONAME
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/eabi/libgstcoreelementsu_old.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,15 @@
+EXPORTS
+	_GST_PLUGIN_DESC @ 1 NONAME
+	gst_capsfilter_get_type @ 2 NONAME
+	gst_fake_sink_get_type @ 3 NONAME
+	gst_fake_src_get_type @ 4 NONAME
+	gst_fd_sink_get_type @ 5 NONAME
+	gst_fd_src_get_type @ 6 NONAME
+	gst_file_sink_get_type @ 7 NONAME
+	gst_file_src_get_type @ 8 NONAME
+	gst_identity_get_type @ 9 NONAME
+	gst_multi_queue_get_type @ 10 NONAME
+	gst_queue_get_type @ 11 NONAME
+	gst_tee_get_type @ 12 NONAME
+	gst_type_find_element_get_type @ 13 NONAME
+
--- a/gstreamer_core/eabi/libgstreameru.def	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/eabi/libgstreameru.def	Fri Apr 16 15:15:52 2010 +0300
@@ -1,1001 +1,1177 @@
 EXPORTS
-	_GST_CAT_DEFAULT @ 1 NONAME
-	_GST_CAT_EVENT @ 2 NONAME
-	_GST_CAT_QOS @ 3 NONAME
-	__gst_element_details_clear @ 4 NONAME
-	__gst_element_details_copy @ 5 NONAME
-	__gst_element_details_set @ 6 NONAME
-	__gst_element_factory_add_interface @ 7 NONAME
-	__gst_element_factory_add_static_pad_template @ 8 NONAME
-	_fail_unless @ 9 NONAME
-	_gst_alloc_trace_register @ 10 NONAME
-	_gst_buffer_initialize @ 11 NONAME
-	_gst_check_debug @ 12 NONAME DATA 4
-	_gst_check_expecting_log @ 13 NONAME DATA 4
-	_gst_check_raised_critical @ 14 NONAME DATA 4
-	_gst_check_raised_warning @ 15 NONAME DATA 4
-	_gst_check_run_test_func @ 16 NONAME
-	_gst_check_threads_running @ 17 NONAME DATA 4
-	_gst_debug_bin_to_dot_file @ 18 NONAME
-	_gst_debug_bin_to_dot_file_with_ts @ 19 NONAME
-	_gst_debug_category_new @ 20 NONAME
-	_gst_debug_init @ 21 NONAME
-	_gst_debug_nameof_funcptr @ 22 NONAME
-	_gst_debug_register_funcptr @ 23 NONAME
-	_gst_element_error_printf @ 24 NONAME
-	_gst_event_initialize @ 25 NONAME
-	_gst_format_initialize @ 26 NONAME
-	_gst_message_initialize @ 27 NONAME
-	_gst_plugin_initialize @ 28 NONAME
-	_gst_plugin_register_static @ 29 NONAME
-	_gst_query_initialize @ 30 NONAME
-	_gst_tag_initialize @ 31 NONAME
-	_gst_trace_add_entry @ 32 NONAME
-	_gst_value_initialize @ 33 NONAME
-	_priv_gst_in_valgrind @ 34 NONAME
-	_priv_gst_quarks_initialize @ 35 NONAME
-	_priv_gst_registry_cleanup @ 36 NONAME
-	_priv_gst_registry_remove_cache_plugins @ 37 NONAME
-	buffers @ 38 NONAME DATA 4
-	check_cond @ 39 NONAME DATA 4
-	check_mutex @ 40 NONAME DATA 4
-	close_log_file @ 41 NONAME
-	failed @ 42 NONAME DATA 4
-	fp_std_log_t @ 43 NONAME DATA 4
-	get_assert_failed @ 44 NONAME
-	get_fp_std_log @ 45 NONAME
-	get_xmlfile @ 46 NONAME
-	gnutest @ 47 NONAME DATA 4
-	gst_activate_mode_get_type @ 48 NONAME
-	gst_alloc_trace_available @ 49 NONAME
-	gst_alloc_trace_flags_get_type @ 50 NONAME
-	gst_alloc_trace_get @ 51 NONAME
-	gst_alloc_trace_list @ 52 NONAME
-	gst_alloc_trace_live_all @ 53 NONAME
-	gst_alloc_trace_print @ 54 NONAME
-	gst_alloc_trace_print_all @ 55 NONAME
-	gst_alloc_trace_print_live @ 56 NONAME
-	gst_alloc_trace_set_flags @ 57 NONAME
-	gst_alloc_trace_set_flags_all @ 58 NONAME
-	gst_assoc_flags_get_type @ 59 NONAME
-	gst_atomic_int_set @ 60 NONAME
-	gst_bin_add @ 61 NONAME
-	gst_bin_add_many @ 62 NONAME
-	gst_bin_child_proxy_get_children_count @ 63 NONAME
-	gst_bin_find_unconnected_pad @ 64 NONAME
-	gst_bin_flags_get_type @ 65 NONAME
-	gst_bin_get_by_interface @ 66 NONAME
-	gst_bin_get_by_name @ 67 NONAME
-	gst_bin_get_by_name_recurse_up @ 68 NONAME
-	gst_bin_get_type @ 69 NONAME
-	gst_bin_iterate_all_by_interface @ 70 NONAME
-	gst_bin_iterate_elements @ 71 NONAME
-	gst_bin_iterate_recurse @ 72 NONAME
-	gst_bin_iterate_sinks @ 73 NONAME
-	gst_bin_iterate_sorted @ 74 NONAME
-	gst_bin_iterate_sources @ 75 NONAME
-	gst_bin_new @ 76 NONAME
-	gst_bin_remove @ 77 NONAME
-	gst_bin_remove_many @ 78 NONAME
-	gst_buffer_copy_flags_get_type @ 79 NONAME
-	gst_buffer_copy_metadata @ 80 NONAME
-	gst_buffer_create_sub @ 81 NONAME
-	gst_buffer_flag_get_type @ 82 NONAME
-	gst_buffer_get_caps @ 83 NONAME
-	gst_buffer_get_type @ 84 NONAME
-	gst_buffer_is_metadata_writable @ 85 NONAME
-	gst_buffer_is_span_fast @ 86 NONAME
-	gst_buffer_join @ 87 NONAME
-	gst_buffer_make_metadata_writable @ 88 NONAME
-	gst_buffer_merge @ 89 NONAME
-	gst_buffer_new @ 90 NONAME
-	gst_buffer_new_and_alloc @ 91 NONAME
-	gst_buffer_set_caps @ 92 NONAME
-	gst_buffer_span @ 93 NONAME
-	gst_buffer_stamp @ 94 NONAME
-	gst_buffer_straw_get_buffer @ 95 NONAME
-	gst_buffer_straw_start_pipeline @ 96 NONAME
-	gst_buffer_straw_stop_pipeline @ 97 NONAME
-	gst_buffer_try_new_and_alloc @ 98 NONAME
-	gst_bus_add_signal_watch @ 99 NONAME
-	gst_bus_add_signal_watch_full @ 100 NONAME
-	gst_bus_add_watch @ 101 NONAME
-	gst_bus_add_watch_full @ 102 NONAME
-	gst_bus_async_signal_func @ 103 NONAME
-	gst_bus_create_watch @ 104 NONAME
-	gst_bus_disable_sync_message_emission @ 105 NONAME
-	gst_bus_enable_sync_message_emission @ 106 NONAME
-	gst_bus_flags_get_type @ 107 NONAME
-	gst_bus_get_type @ 108 NONAME
-	gst_bus_have_pending @ 109 NONAME
-	gst_bus_new @ 110 NONAME
-	gst_bus_peek @ 111 NONAME
-	gst_bus_poll @ 112 NONAME
-	gst_bus_pop @ 113 NONAME
-	gst_bus_pop_filtered @ 114 NONAME
-	gst_bus_post @ 115 NONAME
-	gst_bus_remove_signal_watch @ 116 NONAME
-	gst_bus_set_flushing @ 117 NONAME
-	gst_bus_set_sync_handler @ 118 NONAME
-	gst_bus_sync_reply_get_type @ 119 NONAME
-	gst_bus_sync_signal_handler @ 120 NONAME
-	gst_bus_timed_pop @ 121 NONAME
-	gst_bus_timed_pop_filtered @ 122 NONAME
-	gst_caps_append @ 123 NONAME
-	gst_caps_append_structure @ 124 NONAME
-	gst_caps_copy @ 125 NONAME
-	gst_caps_copy_nth @ 126 NONAME
-	gst_caps_do_simplify @ 127 NONAME
-	gst_caps_flags_get_type @ 128 NONAME
-	gst_caps_from_string @ 129 NONAME
-	gst_caps_get_size @ 130 NONAME
-	gst_caps_get_structure @ 131 NONAME
-	gst_caps_get_type @ 132 NONAME
-	gst_caps_intersect @ 133 NONAME
-	gst_caps_is_always_compatible @ 134 NONAME
-	gst_caps_is_any @ 135 NONAME
-	gst_caps_is_empty @ 136 NONAME
-	gst_caps_is_equal @ 137 NONAME
-	gst_caps_is_equal_fixed @ 138 NONAME
-	gst_caps_is_fixed @ 139 NONAME
-	gst_caps_is_subset @ 140 NONAME
-	gst_caps_make_writable @ 141 NONAME
-	gst_caps_merge @ 142 NONAME
-	gst_caps_merge_structure @ 143 NONAME
-	gst_caps_new_any @ 144 NONAME
-	gst_caps_new_empty @ 145 NONAME
-	gst_caps_new_full @ 146 NONAME
-	gst_caps_new_full_valist @ 147 NONAME
-	gst_caps_new_simple @ 148 NONAME
-	gst_caps_normalize @ 149 NONAME
-	gst_caps_ref @ 150 NONAME
-	gst_caps_remove_structure @ 151 NONAME
-	gst_caps_replace @ 152 NONAME
-	gst_caps_set_simple @ 153 NONAME
-	gst_caps_set_simple_valist @ 154 NONAME
-	gst_caps_subtract @ 155 NONAME
-	gst_caps_to_string @ 156 NONAME
-	gst_caps_truncate @ 157 NONAME
-	gst_caps_union @ 158 NONAME
-	gst_caps_unref @ 159 NONAME
-	gst_check_abi_list @ 160 NONAME
-	gst_check_caps_equal @ 161 NONAME
-	gst_check_chain_func @ 162 NONAME
-	gst_check_drop_buffers @ 163 NONAME
-	gst_check_element_push_buffer @ 164 NONAME
-	gst_check_element_push_buffer_list @ 165 NONAME
-	gst_check_init @ 166 NONAME
-	gst_check_message_error @ 167 NONAME
-	gst_check_setup_element @ 168 NONAME
-	gst_check_setup_sink_pad @ 169 NONAME
-	gst_check_setup_src_pad @ 170 NONAME
-	gst_check_teardown_element @ 171 NONAME
-	gst_check_teardown_sink_pad @ 172 NONAME
-	gst_check_teardown_src_pad @ 173 NONAME
-	gst_child_proxy_child_added @ 174 NONAME
-	gst_child_proxy_child_removed @ 175 NONAME
-	gst_child_proxy_get @ 176 NONAME
-	gst_child_proxy_get_child_by_index @ 177 NONAME
-	gst_child_proxy_get_child_by_name @ 178 NONAME
-	gst_child_proxy_get_children_count @ 179 NONAME
-	gst_child_proxy_get_property @ 180 NONAME
-	gst_child_proxy_get_type @ 181 NONAME
-	gst_child_proxy_get_valist @ 182 NONAME
-	gst_child_proxy_lookup @ 183 NONAME
-	gst_child_proxy_set @ 184 NONAME
-	gst_child_proxy_set_property @ 185 NONAME
-	gst_child_proxy_set_valist @ 186 NONAME
-	gst_class_signal_connect @ 187 NONAME
-	gst_clock_add_observation @ 188 NONAME
-	gst_clock_adjust_unlocked @ 189 NONAME
-	gst_clock_entry_type_get_type @ 190 NONAME
-	gst_clock_flags_get_type @ 191 NONAME
-	gst_clock_get_calibration @ 192 NONAME
-	gst_clock_get_internal_time @ 193 NONAME
-	gst_clock_get_master @ 194 NONAME
-	gst_clock_get_resolution @ 195 NONAME
-	gst_clock_get_time @ 196 NONAME
-	gst_clock_get_type @ 197 NONAME
-	gst_clock_id_compare_func @ 198 NONAME
-	gst_clock_id_get_time @ 199 NONAME
-	gst_clock_id_ref @ 200 NONAME
-	gst_clock_id_unref @ 201 NONAME
-	gst_clock_id_unschedule @ 202 NONAME
-	gst_clock_id_wait @ 203 NONAME
-	gst_clock_id_wait_async @ 204 NONAME
-	gst_clock_new_periodic_id @ 205 NONAME
-	gst_clock_new_single_shot_id @ 206 NONAME
-	gst_clock_return_get_type @ 207 NONAME
-	gst_clock_set_calibration @ 208 NONAME
-	gst_clock_set_master @ 209 NONAME
-	gst_clock_set_resolution @ 210 NONAME
-	gst_clock_unadjust_unlocked @ 211 NONAME
-	gst_core_error_get_type @ 212 NONAME
-	gst_core_error_quark @ 213 NONAME
-	gst_date_get_type @ 214 NONAME
-	gst_debug_add_log_function @ 215 NONAME
-	gst_debug_category_free @ 216 NONAME
-	gst_debug_category_get_color @ 217 NONAME
-	gst_debug_category_get_description @ 218 NONAME
-	gst_debug_category_get_name @ 219 NONAME
-	gst_debug_category_get_threshold @ 220 NONAME
-	gst_debug_category_reset_threshold @ 221 NONAME
-	gst_debug_category_set_threshold @ 222 NONAME
-	gst_debug_color_flags_get_type @ 223 NONAME
-	gst_debug_construct_term_color @ 224 NONAME
-	gst_debug_enabled @ 225 NONAME
-	gst_debug_get_all_categories @ 226 NONAME
-	gst_debug_get_default_threshold @ 227 NONAME
-	gst_debug_graph_details_get_type @ 228 NONAME
-	gst_debug_is_active @ 229 NONAME
-	gst_debug_is_colored @ 230 NONAME
-	gst_debug_level_get_name @ 231 NONAME
-	gst_debug_level_get_type @ 232 NONAME
-	gst_debug_log @ 233 NONAME
-	gst_debug_log_default @ 234 NONAME
-	gst_debug_log_valist @ 235 NONAME
-	gst_debug_message_get @ 236 NONAME
-	gst_debug_remove_log_function @ 237 NONAME
-	gst_debug_remove_log_function_by_data @ 238 NONAME
-	gst_debug_set_active @ 239 NONAME
-	gst_debug_set_colored @ 240 NONAME
-	gst_debug_set_default_threshold @ 241 NONAME
-	gst_debug_set_threshold_for_name @ 242 NONAME
-	gst_debug_unset_threshold_for_name @ 243 NONAME
-	gst_default_registry_check_feature_version @ 244 NONAME
-	gst_deinit @ 245 NONAME
-	gst_double_range_get_type @ 246 NONAME
-	gst_element_abort_state @ 247 NONAME
-	gst_element_add_pad @ 248 NONAME
-	gst_element_change_state @ 249 NONAME
-	gst_element_class_add_pad_template @ 250 NONAME
-	gst_element_class_get_pad_template @ 251 NONAME
-	gst_element_class_get_pad_template_list @ 252 NONAME
-	gst_element_class_install_std_props @ 253 NONAME
-	gst_element_class_set_details @ 254 NONAME
-	gst_element_class_set_details_simple @ 255 NONAME
-	gst_element_continue_state @ 256 NONAME
-	gst_element_create_all_pads @ 257 NONAME
-	gst_element_default_error @ 258 NONAME
-	gst_element_factory_can_sink_caps @ 259 NONAME
-	gst_element_factory_can_src_caps @ 260 NONAME
-	gst_element_factory_create @ 261 NONAME
-	gst_element_factory_find @ 262 NONAME
-	gst_element_factory_get_author @ 263 NONAME
-	gst_element_factory_get_description @ 264 NONAME
-	gst_element_factory_get_element_type @ 265 NONAME
-	gst_element_factory_get_klass @ 266 NONAME
-	gst_element_factory_get_longname @ 267 NONAME
-	gst_element_factory_get_num_pad_templates @ 268 NONAME
-	gst_element_factory_get_static_pad_templates @ 269 NONAME
-	gst_element_factory_get_type @ 270 NONAME
-	gst_element_factory_get_uri_protocols @ 271 NONAME
-	gst_element_factory_get_uri_type @ 272 NONAME
-	gst_element_factory_has_interface @ 273 NONAME
-	gst_element_factory_make @ 274 NONAME
-	gst_element_flags_get_type @ 275 NONAME
-	gst_element_found_tags @ 276 NONAME
-	gst_element_found_tags_for_pad @ 277 NONAME
-	gst_element_get_base_time @ 278 NONAME
-	gst_element_get_bus @ 279 NONAME
-	gst_element_get_clock @ 280 NONAME
-	gst_element_get_compatible_pad @ 281 NONAME
-	gst_element_get_compatible_pad_template @ 282 NONAME
-	gst_element_get_factory @ 283 NONAME
-	gst_element_get_index @ 284 NONAME
-	gst_element_get_pad @ 285 NONAME
-	gst_element_get_query_types @ 286 NONAME
-	gst_element_get_request_pad @ 287 NONAME
-	gst_element_get_state @ 288 NONAME
-	gst_element_get_static_pad @ 289 NONAME
-	gst_element_get_type @ 290 NONAME
-	gst_element_implements_interface @ 291 NONAME
-	gst_element_is_indexable @ 292 NONAME
-	gst_element_is_locked_state @ 293 NONAME
-	gst_element_iterate_pads @ 294 NONAME
-	gst_element_iterate_sink_pads @ 295 NONAME
-	gst_element_iterate_src_pads @ 296 NONAME
-	gst_element_link @ 297 NONAME
-	gst_element_link_filtered @ 298 NONAME
-	gst_element_link_many @ 299 NONAME
-	gst_element_link_pads @ 300 NONAME
-	gst_element_link_pads_filtered @ 301 NONAME
-	gst_element_lost_state @ 302 NONAME
-	gst_element_make_from_uri @ 303 NONAME
-	gst_element_message_full @ 304 NONAME
-	gst_element_no_more_pads @ 305 NONAME
-	gst_element_post_message @ 306 NONAME
-	gst_element_provide_clock @ 307 NONAME
-	gst_element_provides_clock @ 308 NONAME
-	gst_element_query @ 309 NONAME
-	gst_element_query_convert @ 310 NONAME
-	gst_element_query_duration @ 311 NONAME
-	gst_element_query_position @ 312 NONAME
-	gst_element_register @ 313 NONAME
-	gst_element_release_request_pad @ 314 NONAME
-	gst_element_remove_pad @ 315 NONAME
-	gst_element_request_compatible_pad @ 316 NONAME
-	gst_element_requires_clock @ 317 NONAME
-	gst_element_seek @ 318 NONAME
-	gst_element_seek_simple @ 319 NONAME
-	gst_element_send_event @ 320 NONAME
-	gst_element_set_base_time @ 321 NONAME
-	gst_element_set_bus @ 322 NONAME
-	gst_element_set_clock @ 323 NONAME
-	gst_element_set_index @ 324 NONAME
-	gst_element_set_locked_state @ 325 NONAME
-	gst_element_set_state @ 326 NONAME
-	gst_element_state_change_return_get_name @ 327 NONAME
-	gst_element_state_get_name @ 328 NONAME
-	gst_element_sync_state_with_parent @ 329 NONAME
-	gst_element_unlink @ 330 NONAME
-	gst_element_unlink_many @ 331 NONAME
-	gst_element_unlink_pads @ 332 NONAME
-	gst_error_get_message @ 333 NONAME
-	gst_event_get_structure @ 334 NONAME
-	gst_event_get_type @ 335 NONAME
-	gst_event_new_buffer_size @ 336 NONAME
-	gst_event_new_custom @ 337 NONAME
-	gst_event_new_eos @ 338 NONAME
-	gst_event_new_flush_start @ 339 NONAME
-	gst_event_new_flush_stop @ 340 NONAME
-	gst_event_new_latency @ 341 NONAME
-	gst_event_new_navigation @ 342 NONAME
-	gst_event_new_new_segment @ 343 NONAME
-	gst_event_new_new_segment_full @ 344 NONAME
-	gst_event_new_qos @ 345 NONAME
-	gst_event_new_seek @ 346 NONAME
-	gst_event_new_tag @ 347 NONAME
-	gst_event_parse_buffer_size @ 348 NONAME
-	gst_event_parse_latency @ 349 NONAME
-	gst_event_parse_new_segment @ 350 NONAME
-	gst_event_parse_new_segment_full @ 351 NONAME
-	gst_event_parse_qos @ 352 NONAME
-	gst_event_parse_seek @ 353 NONAME
-	gst_event_parse_tag @ 354 NONAME
-	gst_event_type_flags_get_type @ 355 NONAME
-	gst_event_type_get_flags @ 356 NONAME
-	gst_event_type_get_name @ 357 NONAME
-	gst_event_type_get_type @ 358 NONAME
-	gst_event_type_to_quark @ 359 NONAME
-	gst_filter_run @ 360 NONAME
-	gst_flow_get_name @ 361 NONAME
-	gst_flow_return_get_type @ 362 NONAME
-	gst_flow_to_quark @ 363 NONAME
-	gst_format_get_by_nick @ 364 NONAME
-	gst_format_get_details @ 365 NONAME
-	gst_format_get_name @ 366 NONAME
-	gst_format_get_type @ 367 NONAME
-	gst_format_iterate_definitions @ 368 NONAME
-	gst_format_register @ 369 NONAME
-	gst_format_to_quark @ 370 NONAME
-	gst_formats_contains @ 371 NONAME
-	gst_fourcc_get_type @ 372 NONAME
-	gst_fraction_get_type @ 373 NONAME
-	gst_fraction_range_get_type @ 374 NONAME
-	gst_g_error_get_type @ 375 NONAME
-	gst_ghost_pad_get_target @ 376 NONAME
-	gst_ghost_pad_get_type @ 377 NONAME
-	gst_ghost_pad_new @ 378 NONAME
-	gst_ghost_pad_new_from_template @ 379 NONAME
-	gst_ghost_pad_new_no_target @ 380 NONAME
-	gst_ghost_pad_new_no_target_from_template @ 381 NONAME
-	gst_ghost_pad_set_target @ 382 NONAME
-	gst_implements_interface_cast @ 383 NONAME
-	gst_implements_interface_check @ 384 NONAME
-	gst_implements_interface_get_type @ 385 NONAME
-	gst_index_add_association @ 386 NONAME
-	gst_index_add_associationv @ 387 NONAME
-	gst_index_add_format @ 388 NONAME
-	gst_index_add_id @ 389 NONAME
-	gst_index_add_object @ 390 NONAME
-	gst_index_certainty_get_type @ 391 NONAME
-	gst_index_commit @ 392 NONAME
-	gst_index_entry_assoc_map @ 393 NONAME
-	gst_index_entry_copy @ 394 NONAME
-	gst_index_entry_free @ 395 NONAME
-	gst_index_entry_get_type @ 396 NONAME
-	gst_index_entry_type_get_type @ 397 NONAME
-	gst_index_factory_create @ 398 NONAME
-	gst_index_factory_destroy @ 399 NONAME
-	gst_index_factory_find @ 400 NONAME
-	gst_index_factory_get_type @ 401 NONAME
-	gst_index_factory_make @ 402 NONAME
-	gst_index_factory_new @ 403 NONAME
-	gst_index_flags_get_type @ 404 NONAME
-	gst_index_get_assoc_entry @ 405 NONAME
-	gst_index_get_assoc_entry_full @ 406 NONAME
-	gst_index_get_certainty @ 407 NONAME
-	gst_index_get_group @ 408 NONAME
-	gst_index_get_type @ 409 NONAME
-	gst_index_get_writer_id @ 410 NONAME
-	gst_index_lookup_method_get_type @ 411 NONAME
-	gst_index_new @ 412 NONAME
-	gst_index_new_group @ 413 NONAME
-	gst_index_resolver_method_get_type @ 414 NONAME
-	gst_index_set_certainty @ 415 NONAME
-	gst_index_set_filter @ 416 NONAME
-	gst_index_set_filter_full @ 417 NONAME
-	gst_index_set_group @ 418 NONAME
-	gst_index_set_resolver @ 419 NONAME
-	gst_index_set_resolver_full @ 420 NONAME
-	gst_init @ 421 NONAME
-	gst_init_check @ 422 NONAME
-	gst_init_get_option_group @ 423 NONAME
-	gst_int_range_get_type @ 424 NONAME
-	gst_is_tag_list @ 425 NONAME
-	gst_iterator_filter @ 426 NONAME
-	gst_iterator_find_custom @ 427 NONAME
-	gst_iterator_fold @ 428 NONAME
-	gst_iterator_foreach @ 429 NONAME
-	gst_iterator_free @ 430 NONAME
-	gst_iterator_item_get_type @ 431 NONAME
-	gst_iterator_new @ 432 NONAME
-	gst_iterator_new_list @ 433 NONAME
-	gst_iterator_next @ 434 NONAME
-	gst_iterator_push @ 435 NONAME
-	gst_iterator_result_get_type @ 436 NONAME
-	gst_iterator_resync @ 437 NONAME
-	gst_library_error_get_type @ 438 NONAME
-	gst_library_error_quark @ 439 NONAME
-	gst_marshal_BOOLEAN__POINTER @ 440 NONAME
-	gst_marshal_BOOLEAN__VOID @ 441 NONAME
-	gst_marshal_BOXED__BOXED @ 442 NONAME
-	gst_marshal_POINTER__POINTER @ 443 NONAME
-	gst_marshal_VOID__BOXED_OBJECT @ 444 NONAME
-	gst_marshal_VOID__INT64 @ 445 NONAME
-	gst_marshal_VOID__INT_INT @ 446 NONAME
-	gst_marshal_VOID__OBJECT_BOXED @ 447 NONAME
-	gst_marshal_VOID__OBJECT_BOXED_STRING @ 448 NONAME
-	gst_marshal_VOID__OBJECT_OBJECT @ 449 NONAME
-	gst_marshal_VOID__OBJECT_OBJECT_STRING @ 450 NONAME
-	gst_marshal_VOID__OBJECT_PARAM @ 451 NONAME
-	gst_marshal_VOID__OBJECT_POINTER @ 452 NONAME
-	gst_marshal_VOID__OBJECT_STRING @ 453 NONAME
-	gst_marshal_VOID__POINTER_OBJECT @ 454 NONAME
-	gst_marshal_VOID__UINT_BOXED @ 455 NONAME
-	gst_message_get_structure @ 456 NONAME
-	gst_message_get_type @ 457 NONAME
-	gst_message_new_application @ 458 NONAME
-	gst_message_new_async_done @ 459 NONAME
-	gst_message_new_async_start @ 460 NONAME
-	gst_message_new_buffering @ 461 NONAME
-	gst_message_new_clock_lost @ 462 NONAME
-	gst_message_new_clock_provide @ 463 NONAME
-	gst_message_new_custom @ 464 NONAME
-	gst_message_new_duration @ 465 NONAME
-	gst_message_new_element @ 466 NONAME
-	gst_message_new_eos @ 467 NONAME
-	gst_message_new_error @ 468 NONAME
-	gst_message_new_info @ 469 NONAME
-	gst_message_new_latency @ 470 NONAME
-	gst_message_new_new_clock @ 471 NONAME
-	gst_message_new_segment_done @ 472 NONAME
-	gst_message_new_segment_start @ 473 NONAME
-	gst_message_new_state_changed @ 474 NONAME
-	gst_message_new_state_dirty @ 475 NONAME
-	gst_message_new_tag @ 476 NONAME
-	gst_message_new_warning @ 477 NONAME
-	gst_message_parse_async_start @ 478 NONAME
-	gst_message_parse_buffering @ 479 NONAME
-	gst_message_parse_clock_lost @ 480 NONAME
-	gst_message_parse_clock_provide @ 481 NONAME
-	gst_message_parse_duration @ 482 NONAME
-	gst_message_parse_error @ 483 NONAME
-	gst_message_parse_info @ 484 NONAME
-	gst_message_parse_new_clock @ 485 NONAME
-	gst_message_parse_segment_done @ 486 NONAME
-	gst_message_parse_segment_start @ 487 NONAME
-	gst_message_parse_state_changed @ 488 NONAME
-	gst_message_parse_tag @ 489 NONAME
-	gst_message_parse_warning @ 490 NONAME
-	gst_message_type_get_name @ 491 NONAME
-	gst_message_type_get_type @ 492 NONAME
-	gst_message_type_to_quark @ 493 NONAME
-	gst_mini_object_copy @ 494 NONAME
-	gst_mini_object_flags_get_type @ 495 NONAME
-	gst_mini_object_get_type @ 496 NONAME
-	gst_mini_object_is_writable @ 497 NONAME
-	gst_mini_object_make_writable @ 498 NONAME
-	gst_mini_object_new @ 499 NONAME
-	gst_mini_object_ref @ 500 NONAME
-	gst_mini_object_replace @ 501 NONAME
-	gst_mini_object_unref @ 502 NONAME
-	gst_object_check_uniqueness @ 503 NONAME
-	gst_object_default_deep_notify @ 504 NONAME
-	gst_object_default_error @ 505 NONAME
-	gst_object_flags_get_type @ 506 NONAME
-	gst_object_get_name @ 507 NONAME
-	gst_object_get_name_prefix @ 508 NONAME
-	gst_object_get_parent @ 509 NONAME
-	gst_object_get_path_string @ 510 NONAME
-	gst_object_get_type @ 511 NONAME
-	gst_object_has_ancestor @ 512 NONAME
-	gst_object_ref @ 513 NONAME
-	gst_object_replace @ 514 NONAME
-	gst_object_set_name @ 515 NONAME
-	gst_object_set_name_prefix @ 516 NONAME
-	gst_object_set_parent @ 517 NONAME
-	gst_object_sink @ 518 NONAME
-	gst_object_unparent @ 519 NONAME
-	gst_object_unref @ 520 NONAME
-	gst_pad_accept_caps @ 521 NONAME
-	gst_pad_activate_pull @ 522 NONAME
-	gst_pad_activate_push @ 523 NONAME
-	gst_pad_add_buffer_probe @ 524 NONAME
-	gst_pad_add_data_probe @ 525 NONAME
-	gst_pad_add_event_probe @ 526 NONAME
-	gst_pad_alloc_buffer @ 527 NONAME
-	gst_pad_alloc_buffer_and_set_caps @ 528 NONAME
-	gst_pad_can_link @ 529 NONAME
-	gst_pad_chain @ 530 NONAME
-	gst_pad_check_pull_range @ 531 NONAME
-	gst_pad_direction_get_type @ 532 NONAME
-	gst_pad_dispatcher @ 533 NONAME
-	gst_pad_event_default @ 534 NONAME
-	gst_pad_fixate_caps @ 535 NONAME
-	gst_pad_flags_get_type @ 536 NONAME
-	gst_pad_get_allowed_caps @ 537 NONAME
-	gst_pad_get_caps @ 538 NONAME
-	gst_pad_get_direction @ 539 NONAME
-	gst_pad_get_element_private @ 540 NONAME
-	gst_pad_get_fixed_caps_func @ 541 NONAME
-	gst_pad_get_internal_links @ 542 NONAME
-	gst_pad_get_internal_links_default @ 543 NONAME
-	gst_pad_get_negotiated_caps @ 544 NONAME
-	gst_pad_get_pad_template @ 545 NONAME
-	gst_pad_get_pad_template_caps @ 546 NONAME
-	gst_pad_get_parent_element @ 547 NONAME
-	gst_pad_get_peer @ 548 NONAME
-	gst_pad_get_query_types @ 549 NONAME
-	gst_pad_get_query_types_default @ 550 NONAME
-	gst_pad_get_range @ 551 NONAME
-	gst_pad_get_type @ 552 NONAME
-	gst_pad_is_active @ 553 NONAME
-	gst_pad_is_blocked @ 554 NONAME
-	gst_pad_is_blocking @ 555 NONAME
-	gst_pad_is_linked @ 556 NONAME
-	gst_pad_link @ 557 NONAME
-	gst_pad_link_return_get_type @ 558 NONAME
-	gst_pad_new @ 559 NONAME
-	gst_pad_new_from_static_template @ 560 NONAME
-	gst_pad_new_from_template @ 561 NONAME
-	gst_pad_pause_task @ 562 NONAME
-	gst_pad_peer_accept_caps @ 563 NONAME
-	gst_pad_peer_get_caps @ 564 NONAME
-	gst_pad_peer_query @ 565 NONAME
-	gst_pad_presence_get_type @ 566 NONAME
-	gst_pad_proxy_getcaps @ 567 NONAME
-	gst_pad_proxy_setcaps @ 568 NONAME
-	gst_pad_pull_range @ 569 NONAME
-	gst_pad_push @ 570 NONAME
-	gst_pad_push_event @ 571 NONAME
-	gst_pad_query @ 572 NONAME
-	gst_pad_query_convert @ 573 NONAME
-	gst_pad_query_default @ 574 NONAME
-	gst_pad_query_duration @ 575 NONAME
-	gst_pad_query_peer_convert @ 576 NONAME
-	gst_pad_query_peer_duration @ 577 NONAME
-	gst_pad_query_peer_position @ 578 NONAME
-	gst_pad_query_position @ 579 NONAME
-	gst_pad_remove_buffer_probe @ 580 NONAME
-	gst_pad_remove_data_probe @ 581 NONAME
-	gst_pad_remove_event_probe @ 582 NONAME
-	gst_pad_send_event @ 583 NONAME
-	gst_pad_set_acceptcaps_function @ 584 NONAME
-	gst_pad_set_activate_function @ 585 NONAME
-	gst_pad_set_activatepull_function @ 586 NONAME
-	gst_pad_set_activatepush_function @ 587 NONAME
-	gst_pad_set_active @ 588 NONAME
-	gst_pad_set_blocked @ 589 NONAME
-	gst_pad_set_blocked_async @ 590 NONAME
-	gst_pad_set_bufferalloc_function @ 591 NONAME
-	gst_pad_set_caps @ 592 NONAME
-	gst_pad_set_chain_function @ 593 NONAME
-	gst_pad_set_checkgetrange_function @ 594 NONAME
-	gst_pad_set_element_private @ 595 NONAME
-	gst_pad_set_event_function @ 596 NONAME
-	gst_pad_set_fixatecaps_function @ 597 NONAME
-	gst_pad_set_getcaps_function @ 598 NONAME
-	gst_pad_set_getrange_function @ 599 NONAME
-	gst_pad_set_internal_link_function @ 600 NONAME
-	gst_pad_set_link_function @ 601 NONAME
-	gst_pad_set_query_function @ 602 NONAME
-	gst_pad_set_query_type_function @ 603 NONAME
-	gst_pad_set_setcaps_function @ 604 NONAME
-	gst_pad_set_unlink_function @ 605 NONAME
-	gst_pad_start_task @ 606 NONAME
-	gst_pad_stop_task @ 607 NONAME
-	gst_pad_template_flags_get_type @ 608 NONAME
-	gst_pad_template_get_caps @ 609 NONAME
-	gst_pad_template_get_type @ 610 NONAME
-	gst_pad_template_new @ 611 NONAME
-	gst_pad_template_pad_created @ 612 NONAME
-	gst_pad_unlink @ 613 NONAME
-	gst_pad_use_fixed_caps @ 614 NONAME
-	gst_param_spec_fraction @ 615 NONAME
-	gst_param_spec_fraction_get_type @ 616 NONAME
-	gst_param_spec_mini_object @ 617 NONAME
-	gst_parse_bin_from_description @ 618 NONAME
-	gst_parse_error_get_type @ 619 NONAME
-	gst_parse_error_quark @ 620 NONAME
-	gst_parse_launch @ 621 NONAME
-	gst_parse_launchv @ 622 NONAME
-	gst_pipeline_auto_clock @ 623 NONAME
-	gst_pipeline_flags_get_type @ 624 NONAME
-	gst_pipeline_get_auto_flush_bus @ 625 NONAME
-	gst_pipeline_get_bus @ 626 NONAME
-	gst_pipeline_get_clock @ 627 NONAME
-	gst_pipeline_get_delay @ 628 NONAME
-	gst_pipeline_get_last_stream_time @ 629 NONAME
-	gst_pipeline_get_type @ 630 NONAME
-	gst_pipeline_new @ 631 NONAME
-	gst_pipeline_set_auto_flush_bus @ 632 NONAME
-	gst_pipeline_set_clock @ 633 NONAME
-	gst_pipeline_set_delay @ 634 NONAME
-	gst_pipeline_set_new_stream_time @ 635 NONAME
-	gst_pipeline_use_clock @ 636 NONAME
-	gst_plugin_error_get_type @ 637 NONAME
-	gst_plugin_error_quark @ 638 NONAME
-	gst_plugin_feature_check_version @ 639 NONAME
-	gst_plugin_feature_get_name @ 640 NONAME
-	gst_plugin_feature_get_rank @ 641 NONAME
-	gst_plugin_feature_get_type @ 642 NONAME
-	gst_plugin_feature_list_free @ 643 NONAME
-	gst_plugin_feature_load @ 644 NONAME
-	gst_plugin_feature_set_name @ 645 NONAME
-	gst_plugin_feature_set_rank @ 646 NONAME
-	gst_plugin_feature_type_name_filter @ 647 NONAME
-	gst_plugin_flags_get_type @ 648 NONAME
-	gst_plugin_get_description @ 649 NONAME
-	gst_plugin_get_filename @ 650 NONAME
-	gst_plugin_get_license @ 651 NONAME
-	gst_plugin_get_module @ 652 NONAME
-	gst_plugin_get_name @ 653 NONAME
-	gst_plugin_get_origin @ 654 NONAME
-	gst_plugin_get_package @ 655 NONAME
-	gst_plugin_get_source @ 656 NONAME
-	gst_plugin_get_type @ 657 NONAME
-	gst_plugin_get_version @ 658 NONAME
-	gst_plugin_is_loaded @ 659 NONAME
-	gst_plugin_list_free @ 660 NONAME
-	gst_plugin_load @ 661 NONAME
-	gst_plugin_load_by_name @ 662 NONAME
-	gst_plugin_load_file @ 663 NONAME
-	gst_plugin_name_filter @ 664 NONAME
-	gst_plugin_register_static @ 665 NONAME
-	gst_poll_add_fd @ 666 NONAME
-	gst_poll_fd_can_read @ 667 NONAME
-	gst_poll_fd_can_write @ 668 NONAME
-	gst_poll_fd_ctl_read @ 669 NONAME
-	gst_poll_fd_ctl_write @ 670 NONAME
-	gst_poll_fd_has_closed @ 671 NONAME
-	gst_poll_fd_has_error @ 672 NONAME
-	gst_poll_fd_ignored @ 673 NONAME
-	gst_poll_fd_init @ 674 NONAME
-	gst_poll_free @ 675 NONAME
-	gst_poll_new @ 676 NONAME
-	gst_poll_remove_fd @ 677 NONAME
-	gst_poll_restart @ 678 NONAME
-	gst_poll_set_controllable @ 679 NONAME
-	gst_poll_set_flushing @ 680 NONAME
-	gst_poll_wait @ 681 NONAME
-	gst_print_element_args @ 682 NONAME
-	gst_print_pad_caps @ 683 NONAME
-	gst_query_get_structure @ 684 NONAME
-	gst_query_get_type @ 685 NONAME
-	gst_query_new_application @ 686 NONAME
-	gst_query_new_convert @ 687 NONAME
-	gst_query_new_duration @ 688 NONAME
-	gst_query_new_formats @ 689 NONAME
-	gst_query_new_latency @ 690 NONAME
-	gst_query_new_position @ 691 NONAME
-	gst_query_new_seeking @ 692 NONAME
-	gst_query_new_segment @ 693 NONAME
-	gst_query_parse_convert @ 694 NONAME
-	gst_query_parse_duration @ 695 NONAME
-	gst_query_parse_formats_length @ 696 NONAME
-	gst_query_parse_formats_nth @ 697 NONAME
-	gst_query_parse_latency @ 698 NONAME
-	gst_query_parse_position @ 699 NONAME
-	gst_query_parse_seeking @ 700 NONAME
-	gst_query_parse_segment @ 701 NONAME
-	gst_query_set_convert @ 702 NONAME
-	gst_query_set_duration @ 703 NONAME
-	gst_query_set_formats @ 704 NONAME
-	gst_query_set_formatsv @ 705 NONAME
-	gst_query_set_latency @ 706 NONAME
-	gst_query_set_position @ 707 NONAME
-	gst_query_set_seeking @ 708 NONAME
-	gst_query_set_segment @ 709 NONAME
-	gst_query_type_get_by_nick @ 710 NONAME
-	gst_query_type_get_details @ 711 NONAME
-	gst_query_type_get_name @ 712 NONAME
-	gst_query_type_get_type @ 713 NONAME
-	gst_query_type_iterate_definitions @ 714 NONAME
-	gst_query_type_register @ 715 NONAME
-	gst_query_type_to_quark @ 716 NONAME
-	gst_query_types_contains @ 717 NONAME
-	gst_rank_get_type @ 718 NONAME
-	gst_registry_add_feature @ 719 NONAME
-	gst_registry_add_path @ 720 NONAME
-	gst_registry_add_plugin @ 721 NONAME
-	gst_registry_binary_read_cache @ 722 NONAME
-	gst_registry_binary_write_cache @ 723 NONAME
-	gst_registry_feature_filter @ 724 NONAME
-	gst_registry_find_feature @ 725 NONAME
-	gst_registry_find_plugin @ 726 NONAME
-	gst_registry_fork_is_enabled @ 727 NONAME
-	gst_registry_fork_set_enabled @ 728 NONAME
-	gst_registry_get_default @ 729 NONAME
-	gst_registry_get_feature_list @ 730 NONAME
-	gst_registry_get_feature_list_by_plugin @ 731 NONAME
-	gst_registry_get_path_list @ 732 NONAME
-	gst_registry_get_plugin_list @ 733 NONAME
-	gst_registry_get_type @ 734 NONAME
-	gst_registry_lookup @ 735 NONAME
-	gst_registry_lookup_feature @ 736 NONAME
-	gst_registry_plugin_filter @ 737 NONAME
-	gst_registry_remove_feature @ 738 NONAME
-	gst_registry_remove_plugin @ 739 NONAME
-	gst_registry_scan_path @ 740 NONAME
-	gst_registry_xml_read_cache @ 741 NONAME
-	gst_registry_xml_write_cache @ 742 NONAME
-	gst_resource_error_get_type @ 743 NONAME
-	gst_resource_error_quark @ 744 NONAME
-	gst_seek_flags_get_type @ 745 NONAME
-	gst_seek_type_get_type @ 746 NONAME
-	gst_segment_clip @ 747 NONAME
-	gst_segment_free @ 748 NONAME
-	gst_segment_get_type @ 749 NONAME
-	gst_segment_init @ 750 NONAME
-	gst_segment_new @ 751 NONAME
-	gst_segment_set_duration @ 752 NONAME
-	gst_segment_set_last_stop @ 753 NONAME
-	gst_segment_set_newsegment @ 754 NONAME
-	gst_segment_set_newsegment_full @ 755 NONAME
-	gst_segment_set_seek @ 756 NONAME
-	gst_segment_to_running_time @ 757 NONAME
-	gst_segment_to_stream_time @ 758 NONAME
-	gst_segtrap_is_enabled @ 759 NONAME
-	gst_segtrap_set_enabled @ 760 NONAME
-	gst_state_change_get_type @ 761 NONAME
-	gst_state_change_return_get_type @ 762 NONAME
-	gst_state_get_type @ 763 NONAME
-	gst_static_caps_get @ 764 NONAME
-	gst_static_caps_get_type @ 765 NONAME
-	gst_static_pad_template_get @ 766 NONAME
-	gst_static_pad_template_get_caps @ 767 NONAME
-	gst_static_pad_template_get_type @ 768 NONAME
-	gst_stream_error_get_type @ 769 NONAME
-	gst_stream_error_quark @ 770 NONAME
-	gst_structure_copy @ 771 NONAME
-	gst_structure_empty_new @ 772 NONAME
-	gst_structure_fixate_field_boolean @ 773 NONAME
-	gst_structure_fixate_field_nearest_double @ 774 NONAME
-	gst_structure_fixate_field_nearest_fraction @ 775 NONAME
-	gst_structure_fixate_field_nearest_int @ 776 NONAME
-	gst_structure_foreach @ 777 NONAME
-	gst_structure_free @ 778 NONAME
-	gst_structure_from_string @ 779 NONAME
-	gst_structure_get_boolean @ 780 NONAME
-	gst_structure_get_clock_time @ 781 NONAME
-	gst_structure_get_date @ 782 NONAME
-	gst_structure_get_double @ 783 NONAME
-	gst_structure_get_enum @ 784 NONAME
-	gst_structure_get_field_type @ 785 NONAME
-	gst_structure_get_fourcc @ 786 NONAME
-	gst_structure_get_fraction @ 787 NONAME
-	gst_structure_get_int @ 788 NONAME
-	gst_structure_get_name @ 789 NONAME
-	gst_structure_get_name_id @ 790 NONAME
-	gst_structure_get_string @ 791 NONAME
-	gst_structure_get_type @ 792 NONAME
-	gst_structure_get_uint @ 793 NONAME
-	gst_structure_get_value @ 794 NONAME
-	gst_structure_has_field @ 795 NONAME
-	gst_structure_has_field_typed @ 796 NONAME
-	gst_structure_has_name @ 797 NONAME
-	gst_structure_id_empty_new @ 798 NONAME
-	gst_structure_id_get_value @ 799 NONAME
-	gst_structure_id_set @ 800 NONAME
-	gst_structure_id_set_valist @ 801 NONAME
-	gst_structure_id_set_value @ 802 NONAME
-	gst_structure_map_in_place @ 803 NONAME
-	gst_structure_n_fields @ 804 NONAME
-	gst_structure_new @ 805 NONAME
-	gst_structure_new_valist @ 806 NONAME
-	gst_structure_nth_field_name @ 807 NONAME
-	gst_structure_remove_all_fields @ 808 NONAME
-	gst_structure_remove_field @ 809 NONAME
-	gst_structure_remove_fields @ 810 NONAME
-	gst_structure_remove_fields_valist @ 811 NONAME
-	gst_structure_set @ 812 NONAME
-	gst_structure_set_name @ 813 NONAME
-	gst_structure_set_parent_refcount @ 814 NONAME
-	gst_structure_set_valist @ 815 NONAME
-	gst_structure_set_value @ 816 NONAME
-	gst_structure_to_string @ 817 NONAME
-	gst_system_clock_get_type @ 818 NONAME
-	gst_system_clock_obtain @ 819 NONAME
-	gst_tag_exists @ 820 NONAME
-	gst_tag_flag_get_type @ 821 NONAME
-	gst_tag_get_description @ 822 NONAME
-	gst_tag_get_flag @ 823 NONAME
-	gst_tag_get_nick @ 824 NONAME
-	gst_tag_get_type @ 825 NONAME
-	gst_tag_is_fixed @ 826 NONAME
-	gst_tag_list_add @ 827 NONAME
-	gst_tag_list_add_valist @ 828 NONAME
-	gst_tag_list_add_valist_values @ 829 NONAME
-	gst_tag_list_add_values @ 830 NONAME
-	gst_tag_list_copy @ 831 NONAME
-	gst_tag_list_copy_value @ 832 NONAME
-	gst_tag_list_foreach @ 833 NONAME
-	gst_tag_list_free @ 834 NONAME
-	gst_tag_list_get_boolean @ 835 NONAME
-	gst_tag_list_get_boolean_index @ 836 NONAME
-	gst_tag_list_get_char @ 837 NONAME
-	gst_tag_list_get_char_index @ 838 NONAME
-	gst_tag_list_get_date @ 839 NONAME
-	gst_tag_list_get_date_index @ 840 NONAME
-	gst_tag_list_get_double @ 841 NONAME
-	gst_tag_list_get_double_index @ 842 NONAME
-	gst_tag_list_get_float @ 843 NONAME
-	gst_tag_list_get_float_index @ 844 NONAME
-	gst_tag_list_get_int @ 845 NONAME
-	gst_tag_list_get_int64 @ 846 NONAME
-	gst_tag_list_get_int64_index @ 847 NONAME
-	gst_tag_list_get_int_index @ 848 NONAME
-	gst_tag_list_get_long @ 849 NONAME
-	gst_tag_list_get_long_index @ 850 NONAME
-	gst_tag_list_get_pointer @ 851 NONAME
-	gst_tag_list_get_pointer_index @ 852 NONAME
-	gst_tag_list_get_string @ 853 NONAME
-	gst_tag_list_get_string_index @ 854 NONAME
-	gst_tag_list_get_tag_size @ 855 NONAME
-	gst_tag_list_get_type @ 856 NONAME
-	gst_tag_list_get_uchar @ 857 NONAME
-	gst_tag_list_get_uchar_index @ 858 NONAME
-	gst_tag_list_get_uint @ 859 NONAME
-	gst_tag_list_get_uint64 @ 860 NONAME
-	gst_tag_list_get_uint64_index @ 861 NONAME
-	gst_tag_list_get_uint_index @ 862 NONAME
-	gst_tag_list_get_ulong @ 863 NONAME
-	gst_tag_list_get_ulong_index @ 864 NONAME
-	gst_tag_list_get_value_index @ 865 NONAME
-	gst_tag_list_insert @ 866 NONAME
-	gst_tag_list_is_empty @ 867 NONAME
-	gst_tag_list_merge @ 868 NONAME
-	gst_tag_list_new @ 869 NONAME
-	gst_tag_list_remove_tag @ 870 NONAME
-	gst_tag_merge_mode_get_type @ 871 NONAME
-	gst_tag_merge_strings_with_comma @ 872 NONAME
-	gst_tag_merge_use_first @ 873 NONAME
-	gst_tag_register @ 874 NONAME
-	gst_tag_setter_add_tag_valist @ 875 NONAME
-	gst_tag_setter_add_tag_valist_values @ 876 NONAME
-	gst_tag_setter_add_tag_values @ 877 NONAME
-	gst_tag_setter_add_tags @ 878 NONAME
-	gst_tag_setter_get_tag_list @ 879 NONAME
-	gst_tag_setter_get_tag_merge_mode @ 880 NONAME
-	gst_tag_setter_get_type @ 881 NONAME
-	gst_tag_setter_merge_tags @ 882 NONAME
-	gst_tag_setter_set_tag_merge_mode @ 883 NONAME
-	gst_task_cleanup_all @ 884 NONAME
-	gst_task_create @ 885 NONAME
-	gst_task_get_state @ 886 NONAME
-	gst_task_get_type @ 887 NONAME
-	gst_task_join @ 888 NONAME
-	gst_task_pause @ 889 NONAME
-	gst_task_set_lock @ 890 NONAME
-	gst_task_start @ 891 NONAME
-	gst_task_state_get_type @ 892 NONAME
-	gst_task_stop @ 893 NONAME
-	gst_trace_destroy @ 894 NONAME
-	gst_trace_flush @ 895 NONAME
-	gst_trace_new @ 896 NONAME
-	gst_trace_read_tsc @ 897 NONAME
-	gst_trace_set_default @ 898 NONAME
-	gst_trace_text_flush @ 899 NONAME
-	gst_type_find_factory_call_function @ 900 NONAME
-	gst_type_find_factory_get_caps @ 901 NONAME
-	gst_type_find_factory_get_extensions @ 902 NONAME
-	gst_type_find_factory_get_list @ 903 NONAME
-	gst_type_find_factory_get_type @ 904 NONAME
-	gst_type_find_get_length @ 905 NONAME
-	gst_type_find_get_type @ 906 NONAME
-	gst_type_find_peek @ 907 NONAME
-	gst_type_find_probability_get_type @ 908 NONAME
-	gst_type_find_register @ 909 NONAME
-	gst_type_find_suggest @ 910 NONAME
-	gst_type_register_static_full @ 911 NONAME
-	gst_update_registry @ 912 NONAME
-	gst_uri_construct @ 913 NONAME
-	gst_uri_get_location @ 914 NONAME
-	gst_uri_get_protocol @ 915 NONAME
-	gst_uri_handler_get_protocols @ 916 NONAME
-	gst_uri_handler_get_type @ 917 NONAME
-	gst_uri_handler_get_uri @ 918 NONAME
-	gst_uri_handler_get_uri_type @ 919 NONAME
-	gst_uri_handler_new_uri @ 920 NONAME
-	gst_uri_handler_set_uri @ 921 NONAME
-	gst_uri_has_protocol @ 922 NONAME
-	gst_uri_is_valid @ 923 NONAME
-	gst_uri_protocol_is_supported @ 924 NONAME
-	gst_uri_protocol_is_valid @ 925 NONAME
-	gst_uri_type_get_type @ 926 NONAME
-	gst_util_dump_mem @ 927 NONAME
-	gst_util_gdouble_to_guint64 @ 928 NONAME
-	gst_util_get_timestamp @ 929 NONAME
-	gst_util_guint64_to_gdouble @ 930 NONAME
-	gst_util_set_object_arg @ 931 NONAME
-	gst_util_set_value_from_string @ 932 NONAME
-	gst_util_uint64_scale @ 933 NONAME
-	gst_util_uint64_scale_int @ 934 NONAME
-	gst_value_array_append_value @ 935 NONAME
-	gst_value_array_get_size @ 936 NONAME
-	gst_value_array_get_type @ 937 NONAME
-	gst_value_array_get_value @ 938 NONAME
-	gst_value_array_prepend_value @ 939 NONAME
-	gst_value_can_compare @ 940 NONAME
-	gst_value_can_intersect @ 941 NONAME
-	gst_value_can_subtract @ 942 NONAME
-	gst_value_can_union @ 943 NONAME
-	gst_value_compare @ 944 NONAME
-	gst_value_deserialize @ 945 NONAME
-	gst_value_fraction_multiply @ 946 NONAME
-	gst_value_fraction_subtract @ 947 NONAME
-	gst_value_get_caps @ 948 NONAME
-	gst_value_get_date @ 949 NONAME
-	gst_value_get_double_range_max @ 950 NONAME
-	gst_value_get_double_range_min @ 951 NONAME
-	gst_value_get_fourcc @ 952 NONAME
-	gst_value_get_fraction_denominator @ 953 NONAME
-	gst_value_get_fraction_numerator @ 954 NONAME
-	gst_value_get_fraction_range_max @ 955 NONAME
-	gst_value_get_fraction_range_min @ 956 NONAME
-	gst_value_get_int_range_max @ 957 NONAME
-	gst_value_get_int_range_min @ 958 NONAME
-	gst_value_get_mini_object @ 959 NONAME
-	gst_value_get_structure @ 960 NONAME
-	gst_value_init_and_copy @ 961 NONAME
-	gst_value_intersect @ 962 NONAME
-	gst_value_is_fixed @ 963 NONAME
-	gst_value_list_append_value @ 964 NONAME
-	gst_value_list_concat @ 965 NONAME
-	gst_value_list_get_size @ 966 NONAME
-	gst_value_list_get_type @ 967 NONAME
-	gst_value_list_get_value @ 968 NONAME
-	gst_value_list_prepend_value @ 969 NONAME
-	gst_value_register @ 970 NONAME
-	gst_value_register_intersect_func @ 971 NONAME
-	gst_value_register_subtract_func @ 972 NONAME
-	gst_value_register_union_func @ 973 NONAME
-	gst_value_serialize @ 974 NONAME
-	gst_value_set_caps @ 975 NONAME
-	gst_value_set_date @ 976 NONAME
-	gst_value_set_double_range @ 977 NONAME
-	gst_value_set_fourcc @ 978 NONAME
-	gst_value_set_fraction @ 979 NONAME
-	gst_value_set_fraction_range @ 980 NONAME
-	gst_value_set_fraction_range_full @ 981 NONAME
-	gst_value_set_int_range @ 982 NONAME
-	gst_value_set_mini_object @ 983 NONAME
-	gst_value_set_structure @ 984 NONAME
-	gst_value_subtract @ 985 NONAME
-	gst_value_take_mini_object @ 986 NONAME
-	gst_value_union @ 987 NONAME
-	gst_version @ 988 NONAME
-	gst_version_string @ 989 NONAME
-	init_log_file @ 990 NONAME
-	mutex @ 991 NONAME DATA 4
-	priv_gst_structure_append_to_gstring @ 992 NONAME
-	send_failure_info @ 993 NONAME
-	start_cond @ 994 NONAME DATA 4
-	std_log @ 995 NONAME
-	sync_cond @ 996 NONAME DATA 4
-	testResultXml @ 997 NONAME
-	thread_list @ 998 NONAME DATA 4
-	xmlfile_t @ 999 NONAME DATA 4
+	GST_CAT_AUTOPLUG @ 1 NONAME DATA 4
+	GST_CAT_AUTOPLUG_ATTEMPT @ 2 NONAME DATA 4
+	GST_CAT_BUFFER @ 3 NONAME DATA 4
+	GST_CAT_BUFFER_LIST @ 4 NONAME DATA 4
+	GST_CAT_BUS @ 5 NONAME DATA 4
+	GST_CAT_CALL_TRACE @ 6 NONAME DATA 4
+	GST_CAT_CAPS @ 7 NONAME DATA 4
+	GST_CAT_CLOCK @ 8 NONAME DATA 4
+	GST_CAT_ELEMENT_PADS @ 9 NONAME DATA 4
+	GST_CAT_ERROR_SYSTEM @ 10 NONAME DATA 4
+	GST_CAT_GST_INIT @ 11 NONAME DATA 4
+	GST_CAT_MESSAGE @ 12 NONAME DATA 4
+	GST_CAT_NEGOTIATION @ 13 NONAME DATA 4
+	GST_CAT_PADS @ 14 NONAME DATA 4
+	GST_CAT_PARAMS @ 15 NONAME DATA 4
+	GST_CAT_PARENTAGE @ 16 NONAME DATA 4
+	GST_CAT_PERFORMANCE @ 17 NONAME DATA 4
+	GST_CAT_PIPELINE @ 18 NONAME DATA 4
+	GST_CAT_PLUGIN_INFO @ 19 NONAME DATA 4
+	GST_CAT_PLUGIN_LOADING @ 20 NONAME DATA 4
+	GST_CAT_PROBE @ 21 NONAME DATA 4
+	GST_CAT_PROPERTIES @ 22 NONAME DATA 4
+	GST_CAT_REFCOUNTING @ 23 NONAME DATA 4
+	GST_CAT_REGISTRY @ 24 NONAME DATA 4
+	GST_CAT_SCHEDULING @ 25 NONAME DATA 4
+	GST_CAT_SIGNAL @ 26 NONAME DATA 4
+	GST_CAT_STATES @ 27 NONAME DATA 4
+	GST_CAT_TYPES @ 28 NONAME DATA 4
+	GST_CAT_XML @ 29 NONAME DATA 4
+	_GST_CAT_DEFAULT @ 30 NONAME
+	_GST_CAT_EVENT @ 31 NONAME
+	_GST_CAT_QOS @ 32 NONAME
+	__gst_debug_min @ 33 NONAME DATA 4
+	__gst_element_details_clear @ 34 NONAME
+	__gst_element_details_copy @ 35 NONAME
+	__gst_element_details_set @ 36 NONAME
+	__gst_element_factory_add_interface @ 37 NONAME
+	__gst_element_factory_add_static_pad_template @ 38 NONAME
+	_fail_unless @ 39 NONAME
+	_gst_alloc_trace_register @ 40 NONAME
+	_gst_buffer_initialize @ 41 NONAME
+	_gst_buffer_list_initialize @ 42 NONAME
+	_gst_check_debug @ 43 NONAME DATA 4
+	_gst_check_expecting_log @ 44 NONAME DATA 4
+	_gst_check_raised_critical @ 45 NONAME DATA 4
+	_gst_check_raised_warning @ 46 NONAME DATA 4
+	_gst_check_run_test_func @ 47 NONAME
+	_gst_check_threads_running @ 48 NONAME DATA 4
+	_gst_debug_bin_to_dot_file @ 49 NONAME
+	_gst_debug_bin_to_dot_file_with_ts @ 50 NONAME
+	_gst_debug_category_new @ 51 NONAME
+	_gst_debug_dump_mem @ 52 NONAME
+	_gst_debug_get_category @ 53 NONAME
+	_gst_debug_init @ 54 NONAME
+	_gst_debug_nameof_funcptr @ 55 NONAME
+	_gst_debug_register_funcptr @ 56 NONAME
+	_gst_element_error_printf @ 57 NONAME
+	_gst_event_initialize @ 58 NONAME
+	_gst_format_initialize @ 59 NONAME
+	_gst_message_initialize @ 60 NONAME
+	_gst_plugin_initialize @ 61 NONAME
+	_gst_plugin_register_static @ 62 NONAME
+	_gst_query_initialize @ 63 NONAME
+	_gst_tag_initialize @ 64 NONAME
+	_gst_trace_add_entry @ 65 NONAME
+	_gst_value_initialize @ 66 NONAME
+	_priv_gst_in_valgrind @ 67 NONAME
+	_priv_gst_quarks_initialize @ 68 NONAME
+	_priv_gst_registry_cleanup @ 69 NONAME
+	_priv_gst_registry_remove_cache_plugins @ 70 NONAME
+	_priv_plugin_deps_env_vars_changed @ 71 NONAME
+	_priv_plugin_deps_files_changed @ 72 NONAME
+	buffers @ 73 NONAME DATA 4
+	check_cond @ 74 NONAME DATA 4
+	check_mutex @ 75 NONAME DATA 4
+	close_log_file @ 76 NONAME
+	failed @ 77 NONAME DATA 4
+	fp_std_log_t @ 78 NONAME DATA 4
+	get_assert_failed @ 79 NONAME
+	get_fp_std_log @ 80 NONAME
+	get_xmlfile @ 81 NONAME
+	gnutest @ 82 NONAME DATA 4
+	gst_activate_mode_get_type @ 83 NONAME
+	gst_alloc_trace_available @ 84 NONAME
+	gst_alloc_trace_flags_get_type @ 85 NONAME
+	gst_alloc_trace_get @ 86 NONAME
+	gst_alloc_trace_list @ 87 NONAME
+	gst_alloc_trace_live_all @ 88 NONAME
+	gst_alloc_trace_print @ 89 NONAME
+	gst_alloc_trace_print_all @ 90 NONAME
+	gst_alloc_trace_print_live @ 91 NONAME
+	gst_alloc_trace_set_flags @ 92 NONAME
+	gst_alloc_trace_set_flags_all @ 93 NONAME
+	gst_assoc_flags_get_type @ 94 NONAME
+	gst_atomic_int_set @ 95 NONAME
+	gst_bin_add @ 96 NONAME
+	gst_bin_add_many @ 97 NONAME
+	gst_bin_child_proxy_get_children_count @ 98 NONAME
+	gst_bin_find_unconnected_pad @ 99 NONAME
+	gst_bin_find_unlinked_pad @ 100 NONAME
+	gst_bin_flags_get_type @ 101 NONAME
+	gst_bin_get_by_interface @ 102 NONAME
+	gst_bin_get_by_name @ 103 NONAME
+	gst_bin_get_by_name_recurse_up @ 104 NONAME
+	gst_bin_iterate_all_by_interface @ 105 NONAME
+	gst_bin_iterate_elements @ 106 NONAME
+	gst_bin_iterate_recurse @ 107 NONAME
+	gst_bin_iterate_sinks @ 108 NONAME
+	gst_bin_iterate_sorted @ 109 NONAME
+	gst_bin_iterate_sources @ 110 NONAME
+	gst_bin_new @ 111 NONAME
+	gst_bin_recalculate_latency @ 112 NONAME
+	gst_bin_remove @ 113 NONAME
+	gst_bin_remove_many @ 114 NONAME
+	gst_buffer_copy_flags_get_type @ 115 NONAME
+	gst_buffer_copy_metadata @ 116 NONAME
+	gst_buffer_create_sub @ 117 NONAME
+	gst_buffer_flag_get_type @ 118 NONAME
+	gst_buffer_get_caps @ 119 NONAME
+	gst_buffer_get_type @ 120 NONAME
+	gst_buffer_is_metadata_writable @ 121 NONAME
+	gst_buffer_is_span_fast @ 122 NONAME
+	gst_buffer_join @ 123 NONAME
+	gst_buffer_list_foreach @ 124 NONAME
+	gst_buffer_list_get @ 125 NONAME
+	gst_buffer_list_get_type @ 126 NONAME
+	gst_buffer_list_item_get_type @ 127 NONAME
+	gst_buffer_list_iterate @ 128 NONAME
+	gst_buffer_list_iterator_add @ 129 NONAME
+	gst_buffer_list_iterator_add_group @ 130 NONAME
+	gst_buffer_list_iterator_do @ 131 NONAME
+	gst_buffer_list_iterator_free @ 132 NONAME
+	gst_buffer_list_iterator_merge_group @ 133 NONAME
+	gst_buffer_list_iterator_n_buffers @ 134 NONAME
+	gst_buffer_list_iterator_next @ 135 NONAME
+	gst_buffer_list_iterator_next_group @ 136 NONAME
+	gst_buffer_list_iterator_remove @ 137 NONAME
+	gst_buffer_list_iterator_steal @ 138 NONAME
+	gst_buffer_list_iterator_take @ 139 NONAME
+	gst_buffer_list_n_groups @ 140 NONAME
+	gst_buffer_list_new @ 141 NONAME
+	gst_buffer_make_metadata_writable @ 142 NONAME
+	gst_buffer_merge @ 143 NONAME
+	gst_buffer_new @ 144 NONAME
+	gst_buffer_new_and_alloc @ 145 NONAME
+	gst_buffer_set_caps @ 146 NONAME
+	gst_buffer_span @ 147 NONAME
+	gst_buffer_stamp @ 148 NONAME
+	gst_buffer_straw_get_buffer @ 149 NONAME
+	gst_buffer_straw_start_pipeline @ 150 NONAME
+	gst_buffer_straw_stop_pipeline @ 151 NONAME
+	gst_buffer_try_new_and_alloc @ 152 NONAME
+	gst_buffering_mode_get_type @ 153 NONAME
+	gst_bus_add_signal_watch @ 154 NONAME
+	gst_bus_add_signal_watch_full @ 155 NONAME
+	gst_bus_add_watch @ 156 NONAME
+	gst_bus_add_watch_full @ 157 NONAME
+	gst_bus_async_signal_func @ 158 NONAME
+	gst_bus_create_watch @ 159 NONAME
+	gst_bus_disable_sync_message_emission @ 160 NONAME
+	gst_bus_enable_sync_message_emission @ 161 NONAME
+	gst_bus_flags_get_type @ 162 NONAME
+	gst_bus_get_type @ 163 NONAME
+	gst_bus_have_pending @ 164 NONAME
+	gst_bus_new @ 165 NONAME
+	gst_bus_peek @ 166 NONAME
+	gst_bus_poll @ 167 NONAME
+	gst_bus_pop @ 168 NONAME
+	gst_bus_pop_filtered @ 169 NONAME
+	gst_bus_post @ 170 NONAME
+	gst_bus_remove_signal_watch @ 171 NONAME
+	gst_bus_set_flushing @ 172 NONAME
+	gst_bus_set_sync_handler @ 173 NONAME
+	gst_bus_sync_reply_get_type @ 174 NONAME
+	gst_bus_sync_signal_handler @ 175 NONAME
+	gst_bus_timed_pop @ 176 NONAME
+	gst_bus_timed_pop_filtered @ 177 NONAME
+	gst_caps_append @ 178 NONAME
+	gst_caps_append_structure @ 179 NONAME
+	gst_caps_copy @ 180 NONAME
+	gst_caps_copy_nth @ 181 NONAME
+	gst_caps_do_simplify @ 182 NONAME
+	gst_caps_flags_get_type @ 183 NONAME
+	gst_caps_from_string @ 184 NONAME
+	gst_caps_get_size @ 185 NONAME
+	gst_caps_get_structure @ 186 NONAME
+	gst_caps_get_type @ 187 NONAME
+	gst_caps_intersect @ 188 NONAME
+	gst_caps_is_always_compatible @ 189 NONAME
+	gst_caps_is_any @ 190 NONAME
+	gst_caps_is_empty @ 191 NONAME
+	gst_caps_is_equal @ 192 NONAME
+	gst_caps_is_equal_fixed @ 193 NONAME
+	gst_caps_is_fixed @ 194 NONAME
+	gst_caps_is_subset @ 195 NONAME
+	gst_caps_make_writable @ 196 NONAME
+	gst_caps_merge @ 197 NONAME
+	gst_caps_merge_structure @ 198 NONAME
+	gst_caps_new_any @ 199 NONAME
+	gst_caps_new_empty @ 200 NONAME
+	gst_caps_new_full @ 201 NONAME
+	gst_caps_new_full_valist @ 202 NONAME
+	gst_caps_new_simple @ 203 NONAME
+	gst_caps_normalize @ 204 NONAME
+	gst_caps_ref @ 205 NONAME
+	gst_caps_remove_structure @ 206 NONAME
+	gst_caps_replace @ 207 NONAME
+	gst_caps_set_simple @ 208 NONAME
+	gst_caps_set_simple_valist @ 209 NONAME
+	gst_caps_subtract @ 210 NONAME
+	gst_caps_to_string @ 211 NONAME
+	gst_caps_truncate @ 212 NONAME
+	gst_caps_union @ 213 NONAME
+	gst_caps_unref @ 214 NONAME
+	gst_check_abi_list @ 215 NONAME
+	gst_check_caps_equal @ 216 NONAME
+	gst_check_chain_func @ 217 NONAME
+	gst_check_drop_buffers @ 218 NONAME
+	gst_check_element_push_buffer @ 219 NONAME
+	gst_check_element_push_buffer_list @ 220 NONAME
+	gst_check_init @ 221 NONAME
+	gst_check_message_error @ 222 NONAME
+	gst_check_setup_element @ 223 NONAME
+	gst_check_setup_sink_pad @ 224 NONAME
+	gst_check_setup_sink_pad_by_name @ 225 NONAME
+	gst_check_setup_src_pad @ 226 NONAME
+	gst_check_setup_src_pad_by_name @ 227 NONAME
+	gst_check_teardown_element @ 228 NONAME
+	gst_check_teardown_pad_by_name @ 229 NONAME
+	gst_check_teardown_sink_pad @ 230 NONAME
+	gst_check_teardown_src_pad @ 231 NONAME
+	gst_child_proxy_child_added @ 232 NONAME
+	gst_child_proxy_child_removed @ 233 NONAME
+	gst_child_proxy_get @ 234 NONAME
+	gst_child_proxy_get_child_by_index @ 235 NONAME
+	gst_child_proxy_get_child_by_name @ 236 NONAME
+	gst_child_proxy_get_children_count @ 237 NONAME
+	gst_child_proxy_get_property @ 238 NONAME
+	gst_child_proxy_get_type @ 239 NONAME
+	gst_child_proxy_get_valist @ 240 NONAME
+	gst_child_proxy_lookup @ 241 NONAME
+	gst_child_proxy_set @ 242 NONAME
+	gst_child_proxy_set_property @ 243 NONAME
+	gst_child_proxy_set_valist @ 244 NONAME
+	gst_class_signal_connect @ 245 NONAME
+	gst_clock_add_observation @ 246 NONAME
+	gst_clock_adjust_unlocked @ 247 NONAME
+	gst_clock_entry_type_get_type @ 248 NONAME
+	gst_clock_flags_get_type @ 249 NONAME
+	gst_clock_get_calibration @ 250 NONAME
+	gst_clock_get_internal_time @ 251 NONAME
+	gst_clock_get_master @ 252 NONAME
+	gst_clock_get_resolution @ 253 NONAME
+	gst_clock_get_time @ 254 NONAME
+	gst_clock_get_type @ 255 NONAME
+	gst_clock_id_compare_func @ 256 NONAME
+	gst_clock_id_get_time @ 257 NONAME
+	gst_clock_id_ref @ 258 NONAME
+	gst_clock_id_unref @ 259 NONAME
+	gst_clock_id_unschedule @ 260 NONAME
+	gst_clock_id_wait @ 261 NONAME
+	gst_clock_id_wait_async @ 262 NONAME
+	gst_clock_new_periodic_id @ 263 NONAME
+	gst_clock_new_single_shot_id @ 264 NONAME
+	gst_clock_return_get_type @ 265 NONAME
+	gst_clock_set_calibration @ 266 NONAME
+	gst_clock_set_master @ 267 NONAME
+	gst_clock_set_resolution @ 268 NONAME
+	gst_clock_type_get_type @ 269 NONAME
+	gst_clock_unadjust_unlocked @ 270 NONAME
+	gst_core_error_get_type @ 271 NONAME
+	gst_date_get_type @ 272 NONAME
+	gst_debug_add_log_function @ 273 NONAME
+	gst_debug_category_free @ 274 NONAME
+	gst_debug_category_get_color @ 275 NONAME
+	gst_debug_category_get_description @ 276 NONAME
+	gst_debug_category_get_name @ 277 NONAME
+	gst_debug_category_get_threshold @ 278 NONAME
+	gst_debug_category_reset_threshold @ 279 NONAME
+	gst_debug_category_set_threshold @ 280 NONAME
+	gst_debug_color_flags_get_type @ 281 NONAME
+	gst_debug_construct_term_color @ 282 NONAME
+	gst_debug_construct_win_color @ 283 NONAME
+	gst_debug_enabled @ 284 NONAME
+	gst_debug_get_all_categories @ 285 NONAME
+	gst_debug_get_default_threshold @ 286 NONAME
+	gst_debug_graph_details_get_type @ 287 NONAME
+	gst_debug_is_active @ 288 NONAME
+	gst_debug_is_colored @ 289 NONAME
+	gst_debug_level_get_name @ 290 NONAME
+	gst_debug_level_get_type @ 291 NONAME
+	gst_debug_log @ 292 NONAME
+	gst_debug_log_default @ 293 NONAME
+	gst_debug_log_valist @ 294 NONAME
+	gst_debug_message_get @ 295 NONAME
+	gst_debug_remove_log_function @ 296 NONAME
+	gst_debug_remove_log_function_by_data @ 297 NONAME
+	gst_debug_set_active @ 298 NONAME
+	gst_debug_set_colored @ 299 NONAME
+	gst_debug_set_default_threshold @ 300 NONAME
+	gst_debug_set_threshold_for_name @ 301 NONAME
+	gst_debug_unset_threshold_for_name @ 302 NONAME
+	gst_default_registry_check_feature_version @ 303 NONAME
+	gst_deinit @ 304 NONAME
+	gst_element_abort_state @ 305 NONAME
+	gst_element_add_pad @ 306 NONAME
+	gst_element_change_state @ 307 NONAME
+	gst_element_class_add_pad_template @ 308 NONAME
+	gst_element_class_get_pad_template @ 309 NONAME
+	gst_element_class_get_pad_template_list @ 310 NONAME
+	gst_element_class_install_std_props @ 311 NONAME
+	gst_element_class_set_details @ 312 NONAME
+	gst_element_class_set_details_simple @ 313 NONAME
+	gst_element_continue_state @ 314 NONAME
+	gst_element_create_all_pads @ 315 NONAME
+	gst_element_default_error @ 316 NONAME
+	gst_element_factory_can_sink_caps @ 317 NONAME
+	gst_element_factory_can_src_caps @ 318 NONAME
+	gst_element_factory_create @ 319 NONAME
+	gst_element_factory_find @ 320 NONAME
+	gst_element_factory_get_author @ 321 NONAME
+	gst_element_factory_get_description @ 322 NONAME
+	gst_element_factory_get_element_type @ 323 NONAME
+	gst_element_factory_get_klass @ 324 NONAME
+	gst_element_factory_get_longname @ 325 NONAME
+	gst_element_factory_get_num_pad_templates @ 326 NONAME
+	gst_element_factory_get_static_pad_templates @ 327 NONAME
+	gst_element_factory_get_type @ 328 NONAME
+	gst_element_factory_get_uri_protocols @ 329 NONAME
+	gst_element_factory_get_uri_type @ 330 NONAME
+	gst_element_factory_has_interface @ 331 NONAME
+	gst_element_factory_make @ 332 NONAME
+	gst_element_flags_get_type @ 333 NONAME
+	gst_element_found_tags @ 334 NONAME
+	gst_element_found_tags_for_pad @ 335 NONAME
+	gst_element_get_base_time @ 336 NONAME
+	gst_element_get_bus @ 337 NONAME
+	gst_element_get_clock @ 338 NONAME
+	gst_element_get_compatible_pad @ 339 NONAME
+	gst_element_get_compatible_pad_template @ 340 NONAME
+	gst_element_get_factory @ 341 NONAME
+	gst_element_get_index @ 342 NONAME
+	gst_element_get_pad @ 343 NONAME
+	gst_element_get_query_types @ 344 NONAME
+	gst_element_get_request_pad @ 345 NONAME
+	gst_element_get_start_time @ 346 NONAME
+	gst_element_get_state @ 347 NONAME
+	gst_element_get_static_pad @ 348 NONAME
+	gst_element_get_type @ 349 NONAME
+	gst_element_implements_interface @ 350 NONAME
+	gst_element_is_indexable @ 351 NONAME
+	gst_element_is_locked_state @ 352 NONAME
+	gst_element_iterate_pads @ 353 NONAME
+	gst_element_iterate_sink_pads @ 354 NONAME
+	gst_element_iterate_src_pads @ 355 NONAME
+	gst_element_link @ 356 NONAME
+	gst_element_link_filtered @ 357 NONAME
+	gst_element_link_many @ 358 NONAME
+	gst_element_link_pads @ 359 NONAME
+	gst_element_link_pads_filtered @ 360 NONAME
+	gst_element_lost_state @ 361 NONAME
+	gst_element_lost_state_full @ 362 NONAME
+	gst_element_make_from_uri @ 363 NONAME
+	gst_element_message_full @ 364 NONAME
+	gst_element_no_more_pads @ 365 NONAME
+	gst_element_post_message @ 366 NONAME
+	gst_element_provide_clock @ 367 NONAME
+	gst_element_provides_clock @ 368 NONAME
+	gst_element_query @ 369 NONAME
+	gst_element_query_convert @ 370 NONAME
+	gst_element_query_duration @ 371 NONAME
+	gst_element_query_position @ 372 NONAME
+	gst_element_register @ 373 NONAME
+	gst_element_release_request_pad @ 374 NONAME
+	gst_element_remove_pad @ 375 NONAME
+	gst_element_request_compatible_pad @ 376 NONAME
+	gst_element_requires_clock @ 377 NONAME
+	gst_element_seek @ 378 NONAME
+	gst_element_seek_simple @ 379 NONAME
+	gst_element_send_event @ 380 NONAME
+	gst_element_set_base_time @ 381 NONAME
+	gst_element_set_bus @ 382 NONAME
+	gst_element_set_clock @ 383 NONAME
+	gst_element_set_index @ 384 NONAME
+	gst_element_set_locked_state @ 385 NONAME
+	gst_element_set_start_time @ 386 NONAME
+	gst_element_set_state @ 387 NONAME
+	gst_element_state_change_return_get_name @ 388 NONAME
+	gst_element_state_get_name @ 389 NONAME
+	gst_element_sync_state_with_parent @ 390 NONAME
+	gst_element_unlink @ 391 NONAME
+	gst_element_unlink_many @ 392 NONAME
+	gst_element_unlink_pads @ 393 NONAME
+	gst_error_get_message @ 394 NONAME
+	gst_event_get_seqnum @ 395 NONAME
+	gst_event_get_structure @ 396 NONAME
+	gst_event_get_type @ 397 NONAME
+	gst_event_has_name @ 398 NONAME
+	gst_event_new_buffer_size @ 399 NONAME
+	gst_event_new_custom @ 400 NONAME
+	gst_event_new_eos @ 401 NONAME
+	gst_event_new_flush_start @ 402 NONAME
+	gst_event_new_flush_stop @ 403 NONAME
+	gst_event_new_latency @ 404 NONAME
+	gst_event_new_navigation @ 405 NONAME
+	gst_event_new_new_segment @ 406 NONAME
+	gst_event_new_new_segment_full @ 407 NONAME
+	gst_event_new_qos @ 408 NONAME
+	gst_event_new_seek @ 409 NONAME
+	gst_event_new_step @ 410 NONAME
+	gst_event_new_tag @ 411 NONAME
+	gst_event_parse_buffer_size @ 412 NONAME
+	gst_event_parse_latency @ 413 NONAME
+	gst_event_parse_new_segment @ 414 NONAME
+	gst_event_parse_new_segment_full @ 415 NONAME
+	gst_event_parse_qos @ 416 NONAME
+	gst_event_parse_seek @ 417 NONAME
+	gst_event_parse_step @ 418 NONAME
+	gst_event_parse_tag @ 419 NONAME
+	gst_event_set_seqnum @ 420 NONAME
+	gst_event_type_flags_get_type @ 421 NONAME
+	gst_event_type_get_flags @ 422 NONAME
+	gst_event_type_get_name @ 423 NONAME
+	gst_event_type_get_type @ 424 NONAME
+	gst_event_type_to_quark @ 425 NONAME
+	gst_filter_run @ 426 NONAME
+	gst_flow_get_name @ 427 NONAME
+	gst_flow_return_get_type @ 428 NONAME
+	gst_flow_to_quark @ 429 NONAME
+	gst_format_get_by_nick @ 430 NONAME
+	gst_format_get_details @ 431 NONAME
+	gst_format_get_name @ 432 NONAME
+	gst_format_get_type @ 433 NONAME
+	gst_format_iterate_definitions @ 434 NONAME
+	gst_format_register @ 435 NONAME
+	gst_format_to_quark @ 436 NONAME
+	gst_formats_contains @ 437 NONAME
+	gst_g_error_get_type @ 438 NONAME
+	gst_ghost_pad_construct @ 439 NONAME
+	gst_ghost_pad_get_target @ 440 NONAME
+	gst_ghost_pad_get_type @ 441 NONAME
+	gst_ghost_pad_new @ 442 NONAME
+	gst_ghost_pad_new_from_template @ 443 NONAME
+	gst_ghost_pad_new_no_target @ 444 NONAME
+	gst_ghost_pad_new_no_target_from_template @ 445 NONAME
+	gst_ghost_pad_set_target @ 446 NONAME
+	gst_implements_interface_cast @ 447 NONAME
+	gst_implements_interface_check @ 448 NONAME
+	gst_implements_interface_get_type @ 449 NONAME
+	gst_index_add_association @ 450 NONAME
+	gst_index_add_associationv @ 451 NONAME
+	gst_index_add_format @ 452 NONAME
+	gst_index_add_id @ 453 NONAME
+	gst_index_add_object @ 454 NONAME
+	gst_index_certainty_get_type @ 455 NONAME
+	gst_index_commit @ 456 NONAME
+	gst_index_entry_assoc_map @ 457 NONAME
+	gst_index_entry_copy @ 458 NONAME
+	gst_index_entry_free @ 459 NONAME
+	gst_index_entry_get_type @ 460 NONAME
+	gst_index_entry_type_get_type @ 461 NONAME
+	gst_index_factory_create @ 462 NONAME
+	gst_index_factory_destroy @ 463 NONAME
+	gst_index_factory_find @ 464 NONAME
+	gst_index_factory_get_type @ 465 NONAME
+	gst_index_factory_make @ 466 NONAME
+	gst_index_factory_new @ 467 NONAME
+	gst_index_flags_get_type @ 468 NONAME
+	gst_index_get_assoc_entry @ 469 NONAME
+	gst_index_get_assoc_entry_full @ 470 NONAME
+	gst_index_get_certainty @ 471 NONAME
+	gst_index_get_group @ 472 NONAME
+	gst_index_get_type @ 473 NONAME
+	gst_index_get_writer_id @ 474 NONAME
+	gst_index_lookup_method_get_type @ 475 NONAME
+	gst_index_new @ 476 NONAME
+	gst_index_new_group @ 477 NONAME
+	gst_index_resolver_method_get_type @ 478 NONAME
+	gst_index_set_certainty @ 479 NONAME
+	gst_index_set_filter @ 480 NONAME
+	gst_index_set_filter_full @ 481 NONAME
+	gst_index_set_group @ 482 NONAME
+	gst_index_set_resolver @ 483 NONAME
+	gst_index_set_resolver_full @ 484 NONAME
+	gst_init @ 485 NONAME
+	gst_init_check @ 486 NONAME
+	gst_init_get_option_group @ 487 NONAME
+	gst_is_tag_list @ 488 NONAME
+	gst_iterator_filter @ 489 NONAME
+	gst_iterator_find_custom @ 490 NONAME
+	gst_iterator_fold @ 491 NONAME
+	gst_iterator_foreach @ 492 NONAME
+	gst_iterator_free @ 493 NONAME
+	gst_iterator_item_get_type @ 494 NONAME
+	gst_iterator_new @ 495 NONAME
+	gst_iterator_new_list @ 496 NONAME
+	gst_iterator_next @ 497 NONAME
+	gst_iterator_push @ 498 NONAME
+	gst_iterator_result_get_type @ 499 NONAME
+	gst_iterator_resync @ 500 NONAME
+	gst_library_error_get_type @ 501 NONAME
+	gst_marshal_BOOLEAN__POINTER @ 502 NONAME
+	gst_marshal_BOOLEAN__VOID @ 503 NONAME
+	gst_marshal_BOXED__BOXED @ 504 NONAME
+	gst_marshal_POINTER__POINTER @ 505 NONAME
+	gst_marshal_VOID__BOXED_OBJECT @ 506 NONAME
+	gst_marshal_VOID__INT64 @ 507 NONAME
+	gst_marshal_VOID__INT_INT @ 508 NONAME
+	gst_marshal_VOID__OBJECT_BOXED @ 509 NONAME
+	gst_marshal_VOID__OBJECT_BOXED_STRING @ 510 NONAME
+	gst_marshal_VOID__OBJECT_OBJECT @ 511 NONAME
+	gst_marshal_VOID__OBJECT_OBJECT_STRING @ 512 NONAME
+	gst_marshal_VOID__OBJECT_PARAM @ 513 NONAME
+	gst_marshal_VOID__OBJECT_POINTER @ 514 NONAME
+	gst_marshal_VOID__OBJECT_STRING @ 515 NONAME
+	gst_marshal_VOID__POINTER_OBJECT @ 516 NONAME
+	gst_marshal_VOID__UINT_BOXED @ 517 NONAME
+	gst_message_get_seqnum @ 518 NONAME
+	gst_message_get_stream_status_object @ 519 NONAME
+	gst_message_get_structure @ 520 NONAME
+	gst_message_get_type @ 521 NONAME
+	gst_message_new_application @ 522 NONAME
+	gst_message_new_async_done @ 523 NONAME
+	gst_message_new_async_start @ 524 NONAME
+	gst_message_new_buffering @ 525 NONAME
+	gst_message_new_clock_lost @ 526 NONAME
+	gst_message_new_clock_provide @ 527 NONAME
+	gst_message_new_custom @ 528 NONAME
+	gst_message_new_duration @ 529 NONAME
+	gst_message_new_element @ 530 NONAME
+	gst_message_new_eos @ 531 NONAME
+	gst_message_new_error @ 532 NONAME
+	gst_message_new_info @ 533 NONAME
+	gst_message_new_latency @ 534 NONAME
+	gst_message_new_new_clock @ 535 NONAME
+	gst_message_new_request_state @ 536 NONAME
+	gst_message_new_segment_done @ 537 NONAME
+	gst_message_new_segment_start @ 538 NONAME
+	gst_message_new_state_changed @ 539 NONAME
+	gst_message_new_state_dirty @ 540 NONAME
+	gst_message_new_step_done @ 541 NONAME
+	gst_message_new_step_start @ 542 NONAME
+	gst_message_new_stream_status @ 543 NONAME
+	gst_message_new_structure_change @ 544 NONAME
+	gst_message_new_tag @ 545 NONAME
+	gst_message_new_tag_full @ 546 NONAME
+	gst_message_new_warning @ 547 NONAME
+	gst_message_parse_async_start @ 548 NONAME
+	gst_message_parse_buffering @ 549 NONAME
+	gst_message_parse_buffering_stats @ 550 NONAME
+	gst_message_parse_clock_lost @ 551 NONAME
+	gst_message_parse_clock_provide @ 552 NONAME
+	gst_message_parse_duration @ 553 NONAME
+	gst_message_parse_error @ 554 NONAME
+	gst_message_parse_info @ 555 NONAME
+	gst_message_parse_new_clock @ 556 NONAME
+	gst_message_parse_request_state @ 557 NONAME
+	gst_message_parse_segment_done @ 558 NONAME
+	gst_message_parse_segment_start @ 559 NONAME
+	gst_message_parse_state_changed @ 560 NONAME
+	gst_message_parse_step_done @ 561 NONAME
+	gst_message_parse_step_start @ 562 NONAME
+	gst_message_parse_stream_status @ 563 NONAME
+	gst_message_parse_structure_change @ 564 NONAME
+	gst_message_parse_tag @ 565 NONAME
+	gst_message_parse_tag_full @ 566 NONAME
+	gst_message_parse_warning @ 567 NONAME
+	gst_message_set_buffering_stats @ 568 NONAME
+	gst_message_set_seqnum @ 569 NONAME
+	gst_message_set_stream_status_object @ 570 NONAME
+	gst_message_type_get_name @ 571 NONAME
+	gst_message_type_get_type @ 572 NONAME
+	gst_message_type_to_quark @ 573 NONAME
+	gst_mini_object_copy @ 574 NONAME
+	gst_mini_object_flags_get_type @ 575 NONAME
+	gst_mini_object_get_type @ 576 NONAME
+	gst_mini_object_is_writable @ 577 NONAME
+	gst_mini_object_make_writable @ 578 NONAME
+	gst_mini_object_new @ 579 NONAME
+	gst_mini_object_ref @ 580 NONAME
+	gst_mini_object_replace @ 581 NONAME
+	gst_mini_object_unref @ 582 NONAME
+	gst_object_check_uniqueness @ 583 NONAME
+	gst_object_default_deep_notify @ 584 NONAME
+	gst_object_default_error @ 585 NONAME
+	gst_object_flags_get_type @ 586 NONAME
+	gst_object_get_name @ 587 NONAME
+	gst_object_get_name_prefix @ 588 NONAME
+	gst_object_get_parent @ 589 NONAME
+	gst_object_get_path_string @ 590 NONAME
+	gst_object_get_type @ 591 NONAME
+	gst_object_has_ancestor @ 592 NONAME
+	gst_object_ref @ 593 NONAME
+	gst_object_ref_sink @ 594 NONAME
+	gst_object_replace @ 595 NONAME
+	gst_object_set_name @ 596 NONAME
+	gst_object_set_name_prefix @ 597 NONAME
+	gst_object_set_parent @ 598 NONAME
+	gst_object_sink @ 599 NONAME
+	gst_object_unparent @ 600 NONAME
+	gst_object_unref @ 601 NONAME
+	gst_pad_accept_caps @ 602 NONAME
+	gst_pad_activate_pull @ 603 NONAME
+	gst_pad_activate_push @ 604 NONAME
+	gst_pad_add_buffer_probe @ 605 NONAME
+	gst_pad_add_buffer_probe_full @ 606 NONAME
+	gst_pad_add_data_probe @ 607 NONAME
+	gst_pad_add_data_probe_full @ 608 NONAME
+	gst_pad_add_event_probe @ 609 NONAME
+	gst_pad_add_event_probe_full @ 610 NONAME
+	gst_pad_alloc_buffer @ 611 NONAME
+	gst_pad_alloc_buffer_and_set_caps @ 612 NONAME
+	gst_pad_can_link @ 613 NONAME
+	gst_pad_chain @ 614 NONAME
+	gst_pad_chain_list @ 615 NONAME
+	gst_pad_check_pull_range @ 616 NONAME
+	gst_pad_direction_get_type @ 617 NONAME
+	gst_pad_dispatcher @ 618 NONAME
+	gst_pad_event_default @ 619 NONAME
+	gst_pad_fixate_caps @ 620 NONAME
+	gst_pad_flags_get_type @ 621 NONAME
+	gst_pad_get_allowed_caps @ 622 NONAME
+	gst_pad_get_caps @ 623 NONAME
+	gst_pad_get_direction @ 624 NONAME
+	gst_pad_get_element_private @ 625 NONAME
+	gst_pad_get_fixed_caps_func @ 626 NONAME
+	gst_pad_get_internal_links @ 627 NONAME
+	gst_pad_get_internal_links_default @ 628 NONAME
+	gst_pad_get_negotiated_caps @ 629 NONAME
+	gst_pad_get_pad_template @ 630 NONAME
+	gst_pad_get_pad_template_caps @ 631 NONAME
+	gst_pad_get_parent_element @ 632 NONAME
+	gst_pad_get_peer @ 633 NONAME
+	gst_pad_get_query_types @ 634 NONAME
+	gst_pad_get_query_types_default @ 635 NONAME
+	gst_pad_get_range @ 636 NONAME
+	gst_pad_get_type @ 637 NONAME
+	gst_pad_is_active @ 638 NONAME
+	gst_pad_is_blocked @ 639 NONAME
+	gst_pad_is_blocking @ 640 NONAME
+	gst_pad_is_linked @ 641 NONAME
+	gst_pad_iterate_internal_links @ 642 NONAME
+	gst_pad_iterate_internal_links_default @ 643 NONAME
+	gst_pad_link @ 644 NONAME
+	gst_pad_link_return_get_type @ 645 NONAME
+	gst_pad_new @ 646 NONAME
+	gst_pad_new_from_static_template @ 647 NONAME
+	gst_pad_new_from_template @ 648 NONAME
+	gst_pad_pause_task @ 649 NONAME
+	gst_pad_peer_accept_caps @ 650 NONAME
+	gst_pad_peer_get_caps @ 651 NONAME
+	gst_pad_peer_query @ 652 NONAME
+	gst_pad_presence_get_type @ 653 NONAME
+	gst_pad_proxy_getcaps @ 654 NONAME
+	gst_pad_proxy_setcaps @ 655 NONAME
+	gst_pad_pull_range @ 656 NONAME
+	gst_pad_push @ 657 NONAME
+	gst_pad_push_event @ 658 NONAME
+	gst_pad_push_list @ 659 NONAME
+	gst_pad_query @ 660 NONAME
+	gst_pad_query_convert @ 661 NONAME
+	gst_pad_query_default @ 662 NONAME
+	gst_pad_query_duration @ 663 NONAME
+	gst_pad_query_peer_convert @ 664 NONAME
+	gst_pad_query_peer_duration @ 665 NONAME
+	gst_pad_query_peer_position @ 666 NONAME
+	gst_pad_query_position @ 667 NONAME
+	gst_pad_remove_buffer_probe @ 668 NONAME
+	gst_pad_remove_data_probe @ 669 NONAME
+	gst_pad_remove_event_probe @ 670 NONAME
+	gst_pad_send_event @ 671 NONAME
+	gst_pad_set_acceptcaps_function @ 672 NONAME
+	gst_pad_set_activate_function @ 673 NONAME
+	gst_pad_set_activatepull_function @ 674 NONAME
+	gst_pad_set_activatepush_function @ 675 NONAME
+	gst_pad_set_active @ 676 NONAME
+	gst_pad_set_blocked @ 677 NONAME
+	gst_pad_set_blocked_async @ 678 NONAME
+	gst_pad_set_blocked_async_full @ 679 NONAME
+	gst_pad_set_bufferalloc_function @ 680 NONAME
+	gst_pad_set_caps @ 681 NONAME
+	gst_pad_set_chain_function @ 682 NONAME
+	gst_pad_set_chain_list_function @ 683 NONAME
+	gst_pad_set_checkgetrange_function @ 684 NONAME
+	gst_pad_set_element_private @ 685 NONAME
+	gst_pad_set_event_function @ 686 NONAME
+	gst_pad_set_fixatecaps_function @ 687 NONAME
+	gst_pad_set_getcaps_function @ 688 NONAME
+	gst_pad_set_getrange_function @ 689 NONAME
+	gst_pad_set_internal_link_function @ 690 NONAME
+	gst_pad_set_iterate_internal_links_function @ 691 NONAME
+	gst_pad_set_link_function @ 692 NONAME
+	gst_pad_set_query_function @ 693 NONAME
+	gst_pad_set_query_type_function @ 694 NONAME
+	gst_pad_set_setcaps_function @ 695 NONAME
+	gst_pad_set_unlink_function @ 696 NONAME
+	gst_pad_start_task @ 697 NONAME
+	gst_pad_stop_task @ 698 NONAME
+	gst_pad_template_flags_get_type @ 699 NONAME
+	gst_pad_template_get_caps @ 700 NONAME
+	gst_pad_template_get_type @ 701 NONAME
+	gst_pad_template_pad_created @ 702 NONAME
+	gst_pad_unlink @ 703 NONAME
+	gst_pad_use_fixed_caps @ 704 NONAME
+	gst_param_spec_fraction @ 705 NONAME
+	gst_param_spec_fraction_get_type @ 706 NONAME
+	gst_param_spec_mini_object @ 707 NONAME
+	gst_param_spec_mini_object_get_type @ 708 NONAME
+	gst_parse_bin_from_description @ 709 NONAME
+	gst_parse_bin_from_description_full @ 710 NONAME
+	gst_parse_context_free @ 711 NONAME
+	gst_parse_context_get_missing_elements @ 712 NONAME
+	gst_parse_context_new @ 713 NONAME
+	gst_parse_error_get_type @ 714 NONAME
+	gst_parse_error_quark @ 715 NONAME
+	gst_parse_flags_get_type @ 716 NONAME
+	gst_parse_launch @ 717 NONAME
+	gst_parse_launch_full @ 718 NONAME
+	gst_parse_launchv @ 719 NONAME
+	gst_parse_launchv_full @ 720 NONAME
+	gst_pipeline_auto_clock @ 721 NONAME
+	gst_pipeline_flags_get_type @ 722 NONAME
+	gst_pipeline_get_auto_flush_bus @ 723 NONAME
+	gst_pipeline_get_bus @ 724 NONAME
+	gst_pipeline_get_clock @ 725 NONAME
+	gst_pipeline_get_delay @ 726 NONAME
+	gst_pipeline_new @ 727 NONAME
+	gst_pipeline_set_auto_flush_bus @ 728 NONAME
+	gst_pipeline_set_clock @ 729 NONAME
+	gst_pipeline_set_delay @ 730 NONAME
+	gst_pipeline_use_clock @ 731 NONAME
+	gst_plugin_add_dependency @ 732 NONAME
+	gst_plugin_add_dependency_simple @ 733 NONAME
+	gst_plugin_dependency_flags_get_type @ 734 NONAME
+	gst_plugin_error_get_type @ 735 NONAME
+	gst_plugin_error_quark @ 736 NONAME
+	gst_plugin_feature_check_version @ 737 NONAME
+	gst_plugin_feature_get_name @ 738 NONAME
+	gst_plugin_feature_get_rank @ 739 NONAME
+	gst_plugin_feature_get_type @ 740 NONAME
+	gst_plugin_feature_list_free @ 741 NONAME
+	gst_plugin_feature_set_name @ 742 NONAME
+	gst_plugin_feature_set_rank @ 743 NONAME
+	gst_plugin_feature_type_name_filter @ 744 NONAME
+	gst_plugin_flags_get_type @ 745 NONAME
+	gst_plugin_get_cache_data @ 746 NONAME
+	gst_plugin_get_description @ 747 NONAME
+	gst_plugin_get_filename @ 748 NONAME
+	gst_plugin_get_license @ 749 NONAME
+	gst_plugin_get_module @ 750 NONAME
+	gst_plugin_get_name @ 751 NONAME
+	gst_plugin_get_origin @ 752 NONAME
+	gst_plugin_get_package @ 753 NONAME
+	gst_plugin_get_source @ 754 NONAME
+	gst_plugin_get_type @ 755 NONAME
+	gst_plugin_get_version @ 756 NONAME
+	gst_plugin_is_loaded @ 757 NONAME
+	gst_plugin_list_free @ 758 NONAME
+	gst_plugin_load @ 759 NONAME
+	gst_plugin_load_by_name @ 760 NONAME
+	gst_plugin_load_file @ 761 NONAME
+	gst_plugin_name_filter @ 762 NONAME
+	gst_plugin_register_static @ 763 NONAME
+	gst_plugin_register_static_full @ 764 NONAME
+	gst_plugin_set_cache_data @ 765 NONAME
+	gst_poll_add_fd @ 766 NONAME
+	gst_poll_fd_can_read @ 767 NONAME
+	gst_poll_fd_can_write @ 768 NONAME
+	gst_poll_fd_ctl_read @ 769 NONAME
+	gst_poll_fd_ctl_write @ 770 NONAME
+	gst_poll_fd_has_closed @ 771 NONAME
+	gst_poll_fd_has_error @ 772 NONAME
+	gst_poll_fd_ignored @ 773 NONAME
+	gst_poll_fd_init @ 774 NONAME
+	gst_poll_free @ 775 NONAME
+	gst_poll_new @ 776 NONAME
+	gst_poll_new_timer @ 777 NONAME
+	gst_poll_read_control @ 778 NONAME
+	gst_poll_remove_fd @ 779 NONAME
+	gst_poll_restart @ 780 NONAME
+	gst_poll_set_controllable @ 781 NONAME
+	gst_poll_set_flushing @ 782 NONAME
+	gst_poll_wait @ 783 NONAME
+	gst_poll_write_control @ 784 NONAME
+	gst_preset_delete_preset @ 785 NONAME
+	gst_preset_get_meta @ 786 NONAME
+	gst_preset_get_preset_names @ 787 NONAME
+	gst_preset_get_property_names @ 788 NONAME
+	gst_preset_get_type @ 789 NONAME
+	gst_preset_load_preset @ 790 NONAME
+	gst_preset_rename_preset @ 791 NONAME
+	gst_preset_save_preset @ 792 NONAME
+	gst_preset_set_meta @ 793 NONAME
+	gst_print_element_args @ 794 NONAME
+	gst_print_pad_caps @ 795 NONAME
+	gst_proxy_pad_get_type @ 796 NONAME
+	gst_query_get_structure @ 797 NONAME
+	gst_query_get_type @ 798 NONAME
+	gst_query_new_application @ 799 NONAME
+	gst_query_new_buffering @ 800 NONAME
+	gst_query_new_convert @ 801 NONAME
+	gst_query_new_duration @ 802 NONAME
+	gst_query_new_formats @ 803 NONAME
+	gst_query_new_latency @ 804 NONAME
+	gst_query_new_position @ 805 NONAME
+	gst_query_new_seeking @ 806 NONAME
+	gst_query_new_segment @ 807 NONAME
+	gst_query_new_uri @ 808 NONAME
+	gst_query_parse_buffering_percent @ 809 NONAME
+	gst_query_parse_buffering_range @ 810 NONAME
+	gst_query_parse_buffering_stats @ 811 NONAME
+	gst_query_parse_convert @ 812 NONAME
+	gst_query_parse_duration @ 813 NONAME
+	gst_query_parse_formats_length @ 814 NONAME
+	gst_query_parse_formats_nth @ 815 NONAME
+	gst_query_parse_latency @ 816 NONAME
+	gst_query_parse_position @ 817 NONAME
+	gst_query_parse_seeking @ 818 NONAME
+	gst_query_parse_segment @ 819 NONAME
+	gst_query_parse_uri @ 820 NONAME
+	gst_query_set_buffering_percent @ 821 NONAME
+	gst_query_set_buffering_range @ 822 NONAME
+	gst_query_set_buffering_stats @ 823 NONAME
+	gst_query_set_convert @ 824 NONAME
+	gst_query_set_duration @ 825 NONAME
+	gst_query_set_formats @ 826 NONAME
+	gst_query_set_formatsv @ 827 NONAME
+	gst_query_set_latency @ 828 NONAME
+	gst_query_set_position @ 829 NONAME
+	gst_query_set_seeking @ 830 NONAME
+	gst_query_set_segment @ 831 NONAME
+	gst_query_set_uri @ 832 NONAME
+	gst_query_type_get_by_nick @ 833 NONAME
+	gst_query_type_get_details @ 834 NONAME
+	gst_query_type_get_name @ 835 NONAME
+	gst_query_type_get_type @ 836 NONAME
+	gst_query_type_iterate_definitions @ 837 NONAME
+	gst_query_type_register @ 838 NONAME
+	gst_query_type_to_quark @ 839 NONAME
+	gst_query_types_contains @ 840 NONAME
+	gst_rank_get_type @ 841 NONAME
+	gst_registry_add_feature @ 842 NONAME
+	gst_registry_add_path @ 843 NONAME
+	gst_registry_add_plugin @ 844 NONAME
+	gst_registry_binary_write_cache @ 845 NONAME
+	gst_registry_feature_filter @ 846 NONAME
+	gst_registry_find_feature @ 847 NONAME
+	gst_registry_find_plugin @ 848 NONAME
+	gst_registry_fork_is_enabled @ 849 NONAME
+	gst_registry_fork_set_enabled @ 850 NONAME
+	gst_registry_get_default @ 851 NONAME
+	gst_registry_get_feature_list @ 852 NONAME
+	gst_registry_get_feature_list_by_plugin @ 853 NONAME
+	gst_registry_get_path_list @ 854 NONAME
+	gst_registry_get_plugin_list @ 855 NONAME
+	gst_registry_get_type @ 856 NONAME
+	gst_registry_lookup @ 857 NONAME
+	gst_registry_lookup_feature @ 858 NONAME
+	gst_registry_plugin_filter @ 859 NONAME
+	gst_registry_remove_feature @ 860 NONAME
+	gst_registry_remove_plugin @ 861 NONAME
+	gst_registry_scan_path @ 862 NONAME
+	gst_registry_xml_read_cache @ 863 NONAME
+	gst_registry_xml_write_cache @ 864 NONAME
+	gst_resource_error_get_type @ 865 NONAME
+	gst_search_mode_get_type @ 866 NONAME
+	gst_seek_flags_get_type @ 867 NONAME
+	gst_seek_type_get_type @ 868 NONAME
+	gst_segment_clip @ 869 NONAME
+	gst_segment_copy @ 870 NONAME
+	gst_segment_free @ 871 NONAME
+	gst_segment_get_type @ 872 NONAME
+	gst_segment_init @ 873 NONAME
+	gst_segment_new @ 874 NONAME
+	gst_segment_set_duration @ 875 NONAME
+	gst_segment_set_last_stop @ 876 NONAME
+	gst_segment_set_newsegment @ 877 NONAME
+	gst_segment_set_newsegment_full @ 878 NONAME
+	gst_segment_set_running_time @ 879 NONAME
+	gst_segment_set_seek @ 880 NONAME
+	gst_segment_to_position @ 881 NONAME
+	gst_segment_to_running_time @ 882 NONAME
+	gst_segment_to_stream_time @ 883 NONAME
+	gst_segtrap_is_enabled @ 884 NONAME
+	gst_segtrap_set_enabled @ 885 NONAME
+	gst_state_change_get_type @ 886 NONAME
+	gst_state_change_return_get_type @ 887 NONAME
+	gst_state_get_type @ 888 NONAME
+	gst_static_caps_get @ 889 NONAME
+	gst_static_caps_get_type @ 890 NONAME
+	gst_static_pad_template_get @ 891 NONAME
+	gst_static_pad_template_get_caps @ 892 NONAME
+	gst_static_pad_template_get_type @ 893 NONAME
+	gst_stream_error_get_type @ 894 NONAME
+	gst_stream_status_type_get_type @ 895 NONAME
+	gst_structure_change_type_get_type @ 896 NONAME
+	gst_structure_copy @ 897 NONAME
+	gst_structure_empty_new @ 898 NONAME
+	gst_structure_fixate_field_boolean @ 899 NONAME
+	gst_structure_fixate_field_nearest_double @ 900 NONAME
+	gst_structure_fixate_field_nearest_fraction @ 901 NONAME
+	gst_structure_fixate_field_nearest_int @ 902 NONAME
+	gst_structure_foreach @ 903 NONAME
+	gst_structure_free @ 904 NONAME
+	gst_structure_from_string @ 905 NONAME
+	gst_structure_get @ 906 NONAME
+	gst_structure_get_boolean @ 907 NONAME
+	gst_structure_get_clock_time @ 908 NONAME
+	gst_structure_get_date @ 909 NONAME
+	gst_structure_get_double @ 910 NONAME
+	gst_structure_get_enum @ 911 NONAME
+	gst_structure_get_field_type @ 912 NONAME
+	gst_structure_get_fourcc @ 913 NONAME
+	gst_structure_get_fraction @ 914 NONAME
+	gst_structure_get_int @ 915 NONAME
+	gst_structure_get_name @ 916 NONAME
+	gst_structure_get_name_id @ 917 NONAME
+	gst_structure_get_string @ 918 NONAME
+	gst_structure_get_type @ 919 NONAME
+	gst_structure_get_uint @ 920 NONAME
+	gst_structure_get_valist @ 921 NONAME
+	gst_structure_get_value @ 922 NONAME
+	gst_structure_has_field @ 923 NONAME
+	gst_structure_has_field_typed @ 924 NONAME
+	gst_structure_has_name @ 925 NONAME
+	gst_structure_id_empty_new @ 926 NONAME
+	gst_structure_id_get @ 927 NONAME
+	gst_structure_id_get_valist @ 928 NONAME
+	gst_structure_id_get_value @ 929 NONAME
+	gst_structure_id_new @ 930 NONAME
+	gst_structure_id_set @ 931 NONAME
+	gst_structure_id_set_valist @ 932 NONAME
+	gst_structure_id_set_value @ 933 NONAME
+	gst_structure_map_in_place @ 934 NONAME
+	gst_structure_n_fields @ 935 NONAME
+	gst_structure_new_valist @ 936 NONAME
+	gst_structure_nth_field_name @ 937 NONAME
+	gst_structure_remove_all_fields @ 938 NONAME
+	gst_structure_remove_field @ 939 NONAME
+	gst_structure_remove_fields @ 940 NONAME
+	gst_structure_remove_fields_valist @ 941 NONAME
+	gst_structure_set_name @ 942 NONAME
+	gst_structure_set_parent_refcount @ 943 NONAME
+	gst_structure_set_valist @ 944 NONAME
+	gst_structure_set_value @ 945 NONAME
+	gst_system_clock_get_type @ 946 NONAME
+	gst_system_clock_obtain @ 947 NONAME
+	gst_tag_exists @ 948 NONAME
+	gst_tag_flag_get_type @ 949 NONAME
+	gst_tag_get_description @ 950 NONAME
+	gst_tag_get_flag @ 951 NONAME
+	gst_tag_get_nick @ 952 NONAME
+	gst_tag_get_type @ 953 NONAME
+	gst_tag_is_fixed @ 954 NONAME
+	gst_tag_list_add @ 955 NONAME
+	gst_tag_list_add_valist @ 956 NONAME
+	gst_tag_list_add_valist_values @ 957 NONAME
+	gst_tag_list_add_value @ 958 NONAME
+	gst_tag_list_add_values @ 959 NONAME
+	gst_tag_list_copy @ 960 NONAME
+	gst_tag_list_copy_value @ 961 NONAME
+	gst_tag_list_foreach @ 962 NONAME
+	gst_tag_list_free @ 963 NONAME
+	gst_tag_list_get_boolean_index @ 964 NONAME
+	gst_tag_list_get_buffer @ 965 NONAME
+	gst_tag_list_get_buffer_index @ 966 NONAME
+	gst_tag_list_get_char_index @ 967 NONAME
+	gst_tag_list_get_date @ 968 NONAME
+	gst_tag_list_get_date_index @ 969 NONAME
+	gst_tag_list_get_double_index @ 970 NONAME
+	gst_tag_list_get_float_index @ 971 NONAME
+	gst_tag_list_get_int64_index @ 972 NONAME
+	gst_tag_list_get_int_index @ 973 NONAME
+	gst_tag_list_get_long_index @ 974 NONAME
+	gst_tag_list_get_pointer_index @ 975 NONAME
+	gst_tag_list_get_string_index @ 976 NONAME
+	gst_tag_list_get_tag_size @ 977 NONAME
+	gst_tag_list_get_type @ 978 NONAME
+	gst_tag_list_get_uchar_index @ 979 NONAME
+	gst_tag_list_get_uint64_index @ 980 NONAME
+	gst_tag_list_get_uint_index @ 981 NONAME
+	gst_tag_list_get_ulong_index @ 982 NONAME
+	gst_tag_list_get_value_index @ 983 NONAME
+	gst_tag_list_insert @ 984 NONAME
+	gst_tag_list_is_empty @ 985 NONAME
+	gst_tag_list_merge @ 986 NONAME
+	gst_tag_list_new @ 987 NONAME
+	gst_tag_list_new_full @ 988 NONAME
+	gst_tag_list_new_full_valist @ 989 NONAME
+	gst_tag_list_remove_tag @ 990 NONAME
+	gst_tag_merge_mode_get_type @ 991 NONAME
+	gst_tag_merge_strings_with_comma @ 992 NONAME
+	gst_tag_merge_use_first @ 993 NONAME
+	gst_tag_register @ 994 NONAME
+	gst_tag_setter_add_tag_valist @ 995 NONAME
+	gst_tag_setter_add_tag_valist_values @ 996 NONAME
+	gst_tag_setter_add_tag_value @ 997 NONAME
+	gst_tag_setter_add_tag_values @ 998 NONAME
+	gst_tag_setter_add_tags @ 999 NONAME
+	gst_tag_setter_get_tag_list @ 1000 NONAME
+	gst_tag_setter_get_tag_merge_mode @ 1001 NONAME
+	gst_tag_setter_get_type @ 1002 NONAME
+	gst_tag_setter_merge_tags @ 1003 NONAME
+	gst_tag_setter_reset_tags @ 1004 NONAME
+	gst_tag_setter_set_tag_merge_mode @ 1005 NONAME
+	gst_task_cleanup_all @ 1006 NONAME
+	gst_task_create @ 1007 NONAME
+	gst_task_get_pool @ 1008 NONAME
+	gst_task_get_state @ 1009 NONAME
+	gst_task_get_type @ 1010 NONAME
+	gst_task_join @ 1011 NONAME
+	gst_task_pool_cleanup @ 1012 NONAME
+	gst_task_pool_get_type @ 1013 NONAME
+	gst_task_pool_join @ 1014 NONAME
+	gst_task_pool_new @ 1015 NONAME
+	gst_task_pool_prepare @ 1016 NONAME
+	gst_task_pool_push @ 1017 NONAME
+	gst_task_set_lock @ 1018 NONAME
+	gst_task_set_pool @ 1019 NONAME
+	gst_task_set_priority @ 1020 NONAME
+	gst_task_set_state @ 1021 NONAME
+	gst_task_set_thread_callbacks @ 1022 NONAME
+	gst_task_start @ 1023 NONAME
+	gst_task_state_get_type @ 1024 NONAME
+	gst_task_stop @ 1025 NONAME
+	gst_trace_destroy @ 1026 NONAME
+	gst_trace_flush @ 1027 NONAME
+	gst_trace_new @ 1028 NONAME
+	gst_trace_read_tsc @ 1029 NONAME
+	gst_trace_set_default @ 1030 NONAME
+	gst_trace_text_flush @ 1031 NONAME
+	gst_type_find_factory_call_function @ 1032 NONAME
+	gst_type_find_factory_get_caps @ 1033 NONAME
+	gst_type_find_factory_get_extensions @ 1034 NONAME
+	gst_type_find_factory_get_list @ 1035 NONAME
+	gst_type_find_factory_get_type @ 1036 NONAME
+	gst_type_find_get_length @ 1037 NONAME
+	gst_type_find_peek @ 1038 NONAME
+	gst_type_find_probability_get_type @ 1039 NONAME
+	gst_type_find_register @ 1040 NONAME
+	gst_type_find_suggest @ 1041 NONAME
+	gst_type_find_suggest_simple @ 1042 NONAME
+	gst_type_register_static_full @ 1043 NONAME
+	gst_update_registry @ 1044 NONAME
+	gst_uri_construct @ 1045 NONAME
+	gst_uri_get_location @ 1046 NONAME
+	gst_uri_get_protocol @ 1047 NONAME
+	gst_uri_handler_get_protocols @ 1048 NONAME
+	gst_uri_handler_get_type @ 1049 NONAME
+	gst_uri_handler_get_uri @ 1050 NONAME
+	gst_uri_handler_get_uri_type @ 1051 NONAME
+	gst_uri_handler_new_uri @ 1052 NONAME
+	gst_uri_handler_set_uri @ 1053 NONAME
+	gst_uri_has_protocol @ 1054 NONAME
+	gst_uri_is_valid @ 1055 NONAME
+	gst_uri_protocol_is_supported @ 1056 NONAME
+	gst_uri_protocol_is_valid @ 1057 NONAME
+	gst_uri_type_get_type @ 1058 NONAME
+	gst_util_array_binary_search @ 1059 NONAME
+	gst_util_dump_mem @ 1060 NONAME
+	gst_util_gdouble_to_guint64 @ 1061 NONAME
+	gst_util_get_timestamp @ 1062 NONAME
+	gst_util_guint64_to_gdouble @ 1063 NONAME
+	gst_util_seqnum_compare @ 1064 NONAME
+	gst_util_seqnum_next @ 1065 NONAME
+	gst_util_set_object_arg @ 1066 NONAME
+	gst_util_set_value_from_string @ 1067 NONAME
+	gst_util_uint64_scale @ 1068 NONAME
+	gst_util_uint64_scale_int @ 1069 NONAME
+	gst_value_array_append_value @ 1070 NONAME
+	gst_value_array_get_size @ 1071 NONAME
+	gst_value_array_get_value @ 1072 NONAME
+	gst_value_array_prepend_value @ 1073 NONAME
+	gst_value_can_compare @ 1074 NONAME
+	gst_value_can_intersect @ 1075 NONAME
+	gst_value_can_subtract @ 1076 NONAME
+	gst_value_can_union @ 1077 NONAME
+	gst_value_compare @ 1078 NONAME
+	gst_value_deserialize @ 1079 NONAME
+	gst_value_dup_mini_object @ 1080 NONAME
+	gst_value_fraction_multiply @ 1081 NONAME
+	gst_value_fraction_subtract @ 1082 NONAME
+	gst_value_get_caps @ 1083 NONAME
+	gst_value_get_date @ 1084 NONAME
+	gst_value_get_double_range_max @ 1085 NONAME
+	gst_value_get_double_range_min @ 1086 NONAME
+	gst_value_get_fourcc @ 1087 NONAME
+	gst_value_get_fraction_denominator @ 1088 NONAME
+	gst_value_get_fraction_numerator @ 1089 NONAME
+	gst_value_get_fraction_range_max @ 1090 NONAME
+	gst_value_get_fraction_range_min @ 1091 NONAME
+	gst_value_get_int_range_max @ 1092 NONAME
+	gst_value_get_int_range_min @ 1093 NONAME
+	gst_value_get_mini_object @ 1094 NONAME
+	gst_value_get_structure @ 1095 NONAME
+	gst_value_init_and_copy @ 1096 NONAME
+	gst_value_intersect @ 1097 NONAME
+	gst_value_is_fixed @ 1098 NONAME
+	gst_value_list_append_value @ 1099 NONAME
+	gst_value_list_concat @ 1100 NONAME
+	gst_value_list_get_size @ 1101 NONAME
+	gst_value_list_get_value @ 1102 NONAME
+	gst_value_list_prepend_value @ 1103 NONAME
+	gst_value_register @ 1104 NONAME
+	gst_value_register_intersect_func @ 1105 NONAME
+	gst_value_register_subtract_func @ 1106 NONAME
+	gst_value_register_union_func @ 1107 NONAME
+	gst_value_serialize @ 1108 NONAME
+	gst_value_set_caps @ 1109 NONAME
+	gst_value_set_date @ 1110 NONAME
+	gst_value_set_double_range @ 1111 NONAME
+	gst_value_set_fourcc @ 1112 NONAME
+	gst_value_set_fraction @ 1113 NONAME
+	gst_value_set_fraction_range @ 1114 NONAME
+	gst_value_set_fraction_range_full @ 1115 NONAME
+	gst_value_set_int_range @ 1116 NONAME
+	gst_value_set_mini_object @ 1117 NONAME
+	gst_value_set_structure @ 1118 NONAME
+	gst_value_subtract @ 1119 NONAME
+	gst_value_take_mini_object @ 1120 NONAME
+	gst_value_union @ 1121 NONAME
+	gst_version @ 1122 NONAME
+	gst_version_string @ 1123 NONAME
+	init_log_file @ 1124 NONAME
+	mutex @ 1125 NONAME DATA 4
+	priv_gst_structure_append_to_gstring @ 1126 NONAME
+	send_failure_info @ 1127 NONAME
+	start_cond @ 1128 NONAME DATA 4
+	std_log @ 1129 NONAME
+	sync_cond @ 1130 NONAME DATA 4
+	testResultXml @ 1131 NONAME
+	thread_list @ 1132 NONAME DATA 4
+	xmlfile_t @ 1133 NONAME DATA 4
+	gst_core_error_quark @ 1134 NONAME
+	gst_library_error_quark @ 1135 NONAME
+	gst_resource_error_quark @ 1136 NONAME
+	gst_stream_error_quark @ 1137 NONAME
+	gst_bin_get_type @ 1138 NONAME
+	gst_double_range_get_type @ 1139 NONAME
+	gst_fourcc_get_type @ 1140 NONAME
+	gst_fraction_get_type @ 1141 NONAME
+	gst_fraction_range_get_type @ 1142 NONAME
+	gst_int_range_get_type @ 1143 NONAME
+	gst_pipeline_get_type @ 1144 NONAME
+	gst_tag_list_get_boolean @ 1145 NONAME
+	gst_tag_list_get_char @ 1146 NONAME
+	gst_tag_list_get_double @ 1147 NONAME
+	gst_tag_list_get_float @ 1148 NONAME
+	gst_tag_list_get_int @ 1149 NONAME
+	gst_tag_list_get_int64 @ 1150 NONAME
+	gst_tag_list_get_long @ 1151 NONAME
+	gst_tag_list_get_pointer @ 1152 NONAME
+	gst_tag_list_get_string @ 1153 NONAME
+	gst_tag_list_get_uchar @ 1154 NONAME
+	gst_tag_list_get_uint @ 1155 NONAME
+	gst_tag_list_get_uint64 @ 1156 NONAME
+	gst_tag_list_get_ulong @ 1157 NONAME
+	gst_value_array_get_type @ 1158 NONAME
+	gst_value_list_get_type @ 1159 NONAME
+	gst_debug_print_stack_trace @ 1160 NONAME
+	gst_pad_template_new @ 1161 NONAME
+	gst_pipeline_get_last_stream_time @ 1162 NONAME
+	gst_pipeline_set_new_stream_time @ 1163 NONAME
+	gst_plugin_feature_load @ 1164 NONAME
+	gst_registry_binary_read_cache @ 1165 NONAME
+	gst_structure_new @ 1166 NONAME
+	gst_structure_set @ 1167 NONAME
+	gst_structure_to_string @ 1168 NONAME
+	gst_task_pause @ 1169 NONAME
+	gst_type_find_get_type @ 1170 NONAME
+	gst_debug_min @ 1171 NONAME
+	GST_CAT_DEFAULT @ 1172 NONAME DATA 4
+	GST_CAT_EVENT @ 1173 NONAME DATA 4
+	GST_CAT_QOS @ 1174 NONAME DATA 4
+	_check_debug @ 1175 NONAME
 
--- a/gstreamer_core/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
 *
 */
 
+
 PRJ_PLATFORMS
 DEFAULT
 
@@ -82,6 +83,9 @@
 ../gst/gstparamspecs.h 					/sf/mw/gstreamer/include/gstreamer/gst/gstparamspecs.h
 ../gst/gstpoll.h 					/sf/mw/gstreamer/include/gstreamer/gst/gstpoll.h
 ../gst/gstregistrybinary.h 				/sf/mw/gstreamer/include/gstreamer/gst/gstregistrybinary.h
+../gst/gstpreset.h 				/sf/mw/gstreamer/include/gstreamer/gst/gstpreset.h
+../gst/gstbufferlist.h 				/sf/mw/gstreamer/include/gstreamer/gst/gstbufferlist.h
+../gst/gsttaskpool.h 				/sf/mw/gstreamer/include/gstreamer/gst/gsttaskpool.h
 
 //libs
 
@@ -108,7 +112,10 @@
 ../libs/gst/net/gstnet.h				/sf/mw/gstreamer/include/gstreamer/gst/net/gstnet.h
 ../libs/gst/net/gstnettimepacket.h  			/sf/mw/gstreamer/include/gstreamer/gst/net/gstnettimepacket.h
 ../libs/gst/net/gstnettimeprovider.h			/sf/mw/gstreamer/include/gstreamer/gst/net/gstnettimeprovider.h
-									
+
+
+
+										
 PRJ_MMPFILES							
 gstreamer.mmp		
 gstbase.mmp
@@ -117,3 +124,6 @@
 gstnet.mmp
 gstelements.mmp
 gstindexers.mmp
+
+
+					
--- a/gstreamer_core/group/gstbase.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/group/gstbase.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -57,17 +57,15 @@
 USERINCLUDE		../../include/gstreamer/gst/dataprotocol
 USERINCLUDE		../../include/gstreamer/gst/net
 
-
-SOURCEPATH      ../libs/gst/base
+USERINCLUDE		../libs/
 
-SOURCE          gstadapter.c
-SOURCE          gstbasesink.c
-SOURCE          gstbasesrc.c
-SOURCE          gstbasetransform.c
-SOURCE          gstcollectpads.c
-SOURCE          gstpushsrc.c
-SOURCE          gsttypefindhelper.c
-SOURCE          gstdataqueue.c
+SOURCEPATH ../libs/gst/base
+SOURCE gstadapter.c gstbasesink.c 
+SOURCE gstbasesrc.c gstbasetransform.c 
+SOURCE gstbitreader.c gstbytereader.c 
+SOURCE gstcollectpads.c gstdataqueue.c 
+SOURCE gstpushsrc.c gsttypefindhelper.c
+
 
 LIBRARY         euser.lib
 LIBRARY         libc.lib
--- a/gstreamer_core/group/gstindexers.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/group/gstindexers.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -58,12 +58,12 @@
 //USERINCLUDE		../../include/gstreamer/gst/dataprotocol
 //USERINCLUDE		../../include/gstreamer/gst/net
 
- USERINCLUDE		../../include/gstreamer
- USERINCLUDE		../../include/gstreamer/gst
- USERINCLUDE		../../include/gstreamer/gst/base
- USERINCLUDE		../../include/gstreamer/gst/controller
- USERINCLUDE		../../include/gstreamer/gst/dataprotocol
- USERINCLUDE		../../include/gstreamer/gst/net
+USERINCLUDE		../../include/gstreamer
+USERINCLUDE		../../include/gstreamer/gst
+USERINCLUDE		../../include/gstreamer/gst/base
+USERINCLUDE		../../include/gstreamer/gst/controller
+USERINCLUDE		../../include/gstreamer/gst/dataprotocol
+USERINCLUDE		../../include/gstreamer/gst/net
 
 
 SOURCEPATH      ../plugins/indexers
--- a/gstreamer_core/group/gstreamer.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/group/gstreamer.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -37,7 +37,6 @@
 EpocAllowDllData
 #endif
 
-
 MACRO			HAVE_CONFIG_H
 
 //MACRO			GST_TESTCASE_COMPILATION
@@ -58,6 +57,8 @@
 USERINCLUDE		../../include/gstreamer/gst/dataprotocol
 USERINCLUDE		../../include/gstreamer/gst/net
 
+USERINCLUDE		../gst
+
 
 USERINCLUDE			../libs/gst/check
 
@@ -66,7 +67,6 @@
 
 //#endif	/* GST_TESTCASE_COMPILATION */
 
-
 SOURCEPATH      ../gst
 SOURCE          gstbin.c
 SOURCE          gstbuffer.c
@@ -112,6 +112,10 @@
 SOURCE          gsturi.c
 SOURCE          gstutils.c
 SOURCE          gstvalue.c
+SOURCE          gstpreset.c
+SOURCE          gstbufferlist.c
+SOURCE          gsttaskpool.c
+SOURCE          helpfile.cpp
 
 #ifdef HAVE_LIBXML2
 SOURCE          gstxml.c
@@ -124,7 +128,6 @@
 SOURCE          gstparamspecs.c
 SOURCE          gstdebugutils.c
 SOURCE          gstpoll.c
-SOURCE          helpfile.cpp
 
 #ifdef WINSCW
 SOURCE          libgstreamer_wsd.cpp
@@ -138,12 +141,10 @@
 //#endif	/* GST_TESTCASE_COMPILATION */
 
 
-SOURCEPATH ../gst/parse
-SOURCE grammar.tab.pre.c lex._gst_parse_yy.pre.c
 
-//SOURCEPATH	../gst/parse
-//SOURCE		grammar.tab.c
-//SOURCE		lex._gst_parse_yy.c
+SOURCEPATH	../gst/parse
+SOURCE		grammar.tab.c
+SOURCE		lex._gst_parse_yy.c
 
 LIBRARY			euser.lib
 LIBRARY 		libc.lib
@@ -154,7 +155,7 @@
 LIBRARY			libgobject.lib
 LIBRARY			libgthread.lib
 LIBRARY			libm.lib
-LIBRARY 		libz.lib  
+LIBRARY 		libz.lib
 LIBRARY         efsrv.lib 
 
 #ifdef WINSCW
--- a/gstreamer_core/gst/glib-compat-private.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/glib-compat-private.h	Fri Apr 16 15:15:52 2010 +0300
@@ -14,9 +14,4 @@
 
 /* adaptations */
 
-/* FIXME: remove once we depend on GLib 2.10 */
-#if (!GLIB_CHECK_VERSION (2, 10, 0))
-#define g_intern_string(s) g_quark_to_string(g_quark_from_string(s))
-#endif
-
 G_END_DECLS
--- a/gstreamer_core/gst/gst.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gst.c	Fri Apr 16 15:15:52 2010 +0300
@@ -104,6 +104,7 @@
  */
 
 #include "gst_private.h"
+#include "gstconfig.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -116,6 +117,10 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN     /* prevents from including too many things */
+#include <windows.h>            /* GetStdHandle, windows console */
+#endif
 
 #include "gst-i18n-lib.h"
 #include <locale.h>             /* for LC_ALL */
@@ -124,8 +129,8 @@
 
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
+#include <gst_global.h>
 #include <config.h>
-#include <string.h>
 #endif
 
 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
@@ -136,6 +141,10 @@
 static gboolean gst_initialized = FALSE;
 static gboolean gst_deinitialized = FALSE;
 
+#ifdef G_OS_WIN32
+static HMODULE gst_dll_handle = NULL;
+#endif
+
 #ifndef GST_DISABLE_REGISTRY
 static GList *plugin_paths = NULL;      /* for delayed processing in post_init */
 #endif
@@ -145,7 +154,7 @@
 #endif
 
 /* defaults */
-#ifdef HAVE_FORK
+#if defined(HAVE_FORK) && !defined(GST_HAVE_UNSAFE_FORK)
 #define DEFAULT_FORK TRUE
 #else
 #define DEFAULT_FORK FALSE
@@ -157,10 +166,8 @@
 /* control the behaviour of registry rebuild */
 static gboolean _gst_enable_registry_fork = DEFAULT_FORK;
 
-#ifdef __SYMBIAN32__
 /*set to TRUE when registry needn't to be updated */
 static gboolean _gst_disable_registry_update = FALSE;
-#endif
 
 static void load_plugin_func (gpointer data, gpointer user_data);
 static gboolean init_pre (GOptionContext * context, GOptionGroup * group,
@@ -201,9 +208,7 @@
   ARG_PLUGIN_PATH,
   ARG_PLUGIN_LOAD,
   ARG_SEGTRAP_DISABLE,
-#ifdef __SYMBIAN32__
   ARG_REGISTRY_UPDATE_DISABLE,
-#endif
   ARG_REGISTRY_FORK_DISABLE
 };
 
@@ -289,6 +294,17 @@
 }
 #endif
 
+#ifdef G_OS_WIN32
+BOOL WINAPI
+DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+  if (fdwReason == DLL_PROCESS_ATTACH)
+    gst_dll_handle = (HMODULE) hinstDLL;
+  return TRUE;
+}
+
+#endif
+
 /**
  * gst_init_get_option_group:
  *
@@ -316,7 +332,7 @@
 {
 #ifndef GST_DISABLE_OPTION_PARSING
   GOptionGroup *group;
-  const static GOptionEntry gst_args[] = {
+  static const GOptionEntry gst_args[] = {
     {"gst-version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
         (gpointer) parse_goption_arg, N_("Print the GStreamer version"), NULL},
     {"gst-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
@@ -358,13 +374,11 @@
           (gpointer) parse_goption_arg,
           N_("Disable trapping of segmentation faults during plugin loading"),
         NULL},
-#ifdef __SYMBIAN32__		
     {"gst-disable-registry-update", 0, G_OPTION_FLAG_NO_ARG,
           G_OPTION_ARG_CALLBACK,
           (gpointer) parse_goption_arg,
           N_("Disable updating the registry"),
         NULL},
-#endif		
     {"gst-disable-registry-fork", 0, G_OPTION_FLAG_NO_ARG,
           G_OPTION_ARG_CALLBACK,
           (gpointer) parse_goption_arg,
@@ -435,38 +449,6 @@
 #endif
   gboolean res;
 
-#ifdef __SYMBIAN32__
-	char* checkexe,*temp;
-	/// registry will be updated only if gst_init is called from GSTRegistryGenerator.exe
-	if( argv )
-	{
-		checkexe = *argv[0];
-		temp = checkexe+strlen(checkexe);
-		while(temp!=checkexe && *temp!='\\')
-		    {
-		    temp--;
-		    }
-
-		checkexe = ++temp;
-		
-		if( strcmp(checkexe,GST_REGISTRY_GENERATOR) == 0 )
-		{
-			/// setting flag for update registry if called from GSTRegistryGenerator.exe
-			setenv("GST_REGISTRY_UPDATE", "yes", 1);
-		}
-		else
-		{
-			/// setting flag for disable update registry
-			setenv("GST_REGISTRY_UPDATE", "no", 0);
-		}
-	}
-	else
-	{
-		/// setting flag for disable update registry
-	  setenv("GST_REGISTRY_UPDATE", "no", 0);
-	}
-#endif
-
   if (!g_thread_supported ())
     g_thread_init (NULL);
 
@@ -639,6 +621,7 @@
 #ifdef ENABLE_NLS
   setlocale (LC_ALL, "");
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 #endif /* ENABLE_NLS */
 
 #ifndef GST_DISABLE_GST_DEBUG
@@ -721,12 +704,17 @@
   gboolean changed = FALSE;
   GList *l;
 
+  GST_INFO ("Validating registry cache: %s", registry_file);
+  /* It sounds tempting to just compare the mtime of directories with the mtime
+   * of the registry cache, but it does not work. It would not catch updated
+   * plugins, which might bring more or less features.
+   */
+
   /* scan paths specified via --gst-plugin-path */
   GST_DEBUG ("scanning paths added via --gst-plugin-path");
   for (l = plugin_paths; l != NULL; l = l->next) {
     GST_INFO ("Scanning plugin path: \"%s\"", (gchar *) l->data);
-    /* CHECKME: add changed |= here as well? */
-    gst_registry_scan_path (default_registry, (gchar *) l->data);
+    changed |= gst_registry_scan_path (default_registry, (gchar *) l->data);
   }
   /* keep plugin_paths around in case a re-scan is forced later on */
 
@@ -753,7 +741,15 @@
   plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH");
   if (plugin_path == NULL) {
     char *home_plugins;
-
+#ifdef __SYMBIAN32__
+    
+    GST_DEBUG ("scanning main plugins %s", PLUGIN_LIST_TXT_FILE_PATH_IN_ROM);
+    changed |= gst_registry_scan_path (default_registry, PLUGIN_LIST_TXT_FILE_PATH_IN_ROM);
+    
+    GST_DEBUG ("scanning main plugins %s", PLUGIN_LIST_TXT_FILE_PATH);
+    changed |= gst_registry_scan_path (default_registry, PLUGIN_LIST_TXT_FILE_PATH);
+    
+#else
     GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set");
 
     /* plugins in the user's home directory take precedence over
@@ -764,9 +760,29 @@
     changed |= gst_registry_scan_path (default_registry, home_plugins);
     g_free (home_plugins);
 
+
+    
     /* add the main (installed) library path */
     GST_DEBUG ("scanning main plugins %s", PLUGINDIR);
     changed |= gst_registry_scan_path (default_registry, PLUGINDIR);
+#endif
+#ifdef G_OS_WIN32
+    {
+      char *base_dir;
+      char *dir;
+
+      base_dir =
+          g_win32_get_package_installation_directory_of_module (gst_dll_handle);
+
+      dir = g_build_filename (base_dir, "lib", "gstreamer-0.10", NULL);
+      GST_DEBUG ("scanning DLL dir %s", dir);
+
+      changed |= gst_registry_scan_path (default_registry, dir);
+
+      g_free (dir);
+      g_free (base_dir);
+    }
+#endif
   } else {
     gchar **list;
     gint i;
@@ -788,16 +804,12 @@
   }
 
   if (!write_changes) {
-    GST_INFO ("Registry cached changed, but writing is disabled. Not writing.");
+    GST_INFO ("Registry cache changed, but writing is disabled. Not writing.");
     return REGISTRY_SCAN_AND_UPDATE_FAILURE;
   }
 
   GST_INFO ("Registry cache changed. Writing new registry cache");
-#ifdef USE_BINARY_REGISTRY
   if (!gst_registry_binary_write_cache (default_registry, registry_file)) {
-#else
-  if (!gst_registry_xml_write_cache (default_registry, registry_file)) {
-#endif
     g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
         _("Error writing registry cache to %s: %s"),
         registry_file, g_strerror (errno));
@@ -813,12 +825,6 @@
     const gchar * registry_file, GError ** error)
 {
   /* fork() not available */
-  GST_INFO ("reading registry cache: %s", registry_file);
-#ifdef USE_BINARY_REGISTRY
-  gst_registry_binary_read_cache (default_registry, registry_file);
-#else
-  gst_registry_xml_read_cache (default_registry, registry_file);
-#endif
   GST_DEBUG ("Updating registry cache in-process");
   scan_and_update_registry (default_registry, registry_file, TRUE, error);
   return TRUE;
@@ -846,13 +852,6 @@
     return FALSE;
   }
 
-  GST_INFO ("reading registry cache: %s", registry_file);
-#ifdef USE_BINARY_REGISTRY
-  gst_registry_binary_read_cache (default_registry, registry_file);
-#else
-  gst_registry_xml_read_cache (default_registry, registry_file);
-#endif
-
   pid = fork ();
   if (pid == -1) {
     GST_ERROR ("Failed to fork()");
@@ -924,11 +923,7 @@
     if (result_code == REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED) {
       GST_DEBUG ("Child succeeded. Parent reading registry cache");
       _priv_gst_registry_remove_cache_plugins (default_registry);
-#ifdef USE_BINARY_REGISTRY
       gst_registry_binary_read_cache (default_registry, registry_file);
-#else
-      gst_registry_xml_read_cache (default_registry, registry_file);
-#endif
     } else if (result_code == REGISTRY_SCAN_AND_UPDATE_FAILURE) {
       GST_DEBUG ("Child failed. Parent re-scanning registry, ignoring errors.");
       scan_and_update_registry (default_registry, registry_file, FALSE, NULL);
@@ -941,21 +936,16 @@
 static gboolean
 ensure_current_registry (GError ** error)
 {
-  char *registry_file;
+  gchar *registry_file;
   GstRegistry *default_registry;
   gboolean ret = TRUE;
   gboolean do_fork;
-#ifdef __SYMBIAN32__  
   gboolean do_update;
-  char *temp;
-  gboolean have_cache = FALSE;
-  
-#endif
+  gboolean have_cache;
 
   default_registry = gst_registry_get_default ();
   registry_file = g_strdup (g_getenv ("GST_REGISTRY"));
   if (registry_file == NULL) {
-#ifdef USE_BINARY_REGISTRY
 #ifdef __SYMBIAN32__  
     registry_file = g_build_filename (GSTREAMER_REGISTERY_PATH,
         ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
@@ -970,66 +960,57 @@
     registry_file = g_build_filename (g_get_home_dir (),
         ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
 #endif    
-#else
-    registry_file = g_build_filename (g_get_home_dir (),
-        ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".xml", NULL);
-#endif
   }
 
-#ifdef __SYMBIAN32__
   GST_INFO ("reading registry cache: %s", registry_file);
-#ifdef USE_BINARY_REGISTRY
   have_cache = gst_registry_binary_read_cache (default_registry, registry_file);
-#else
-  have_cache = gst_registry_xml_read_cache (default_registry, registry_file);
-#endif
 
   if (have_cache) {
     do_update = !_gst_disable_registry_update;
     if (do_update) {
       const gchar *update_env;
-
+#if ((defined(__SYMBIAN32__))  && (!defined(__WINSCW__)))  
+      // if GST_REGISTRY_UPDATE is not set, do_update should be FALSE, 
+      // not to update by default.
+      do_update = FALSE;
+#endif      
       if ((update_env = g_getenv ("GST_REGISTRY_UPDATE"))) {
-#ifndef __WINSCW__
         /* do update for any value different from "no" */
-        do_update = (strcmp (update_env, "yes") == 0);
-#endif
+        do_update = (strcmp (update_env, "no") != 0);
       }
     }
   } else {
     do_update = TRUE;
   }
 
-  if (do_update) 
-#endif  
-  {
+  if (do_update) {
 #ifdef __SYMBIAN32__
     /// registry can't be created in ROM, so fixed it to GSTREAMER_REGISTERY_PATH
     registry_file = g_build_filename (GSTREAMER_REGISTERY_PATH,
        ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
 #endif
-  /* first see if forking is enabled */
-  do_fork = _gst_enable_registry_fork;
-  if (do_fork) {
-    const gchar *fork_env;
+    /* first see if forking is enabled */
+    do_fork = _gst_enable_registry_fork;
+    if (do_fork) {
+      const gchar *fork_env;
 
-    /* forking enabled, see if it is disabled with an env var */
-    if ((fork_env = g_getenv ("GST_REGISTRY_FORK"))) {
-      /* fork enabled for any value different from "no" */
-      do_fork = strcmp (fork_env, "no") != 0;
+      /* forking enabled, see if it is disabled with an env var */
+      if ((fork_env = g_getenv ("GST_REGISTRY_FORK"))) {
+        /* fork enabled for any value different from "no" */
+        do_fork = strcmp (fork_env, "no") != 0;
+      }
     }
-  }
 
-  /* now check registry with or without forking */
-  if (do_fork) {
-    GST_DEBUG ("forking for registry rebuild");
-    ret = ensure_current_registry_forking (default_registry, registry_file,
-        error);
-  } else {
-    GST_DEBUG ("requested not to fork for registry rebuild");
-    ret = ensure_current_registry_nonforking (default_registry, registry_file,
-        error);
-  }
+    /* now check registry with or without forking */
+    if (do_fork) {
+      GST_DEBUG ("forking for registry rebuild");
+      ret = ensure_current_registry_forking (default_registry, registry_file,
+          error);
+    } else {
+      GST_DEBUG ("requested not to fork for registry rebuild");
+      ret = ensure_current_registry_nonforking (default_registry, registry_file,
+          error);
+    }
   }
 
   g_free (registry_file);
@@ -1077,13 +1058,77 @@
   g_type_class_ref (gst_element_get_type ());
   g_type_class_ref (gst_type_find_factory_get_type ());
   g_type_class_ref (gst_bin_get_type ());
+  g_type_class_ref (gst_bus_get_type ());
+  g_type_class_ref (gst_task_get_type ());
+  g_type_class_ref (gst_clock_get_type ());
 
-#ifndef GST_DISABLE_INDEX
   g_type_class_ref (gst_index_factory_get_type ());
-#endif /* GST_DISABLE_INDEX */
-#ifndef GST_DISABLE_URI
   gst_uri_handler_get_type ();
-#endif /* GST_DISABLE_URI */
+
+  g_type_class_ref (gst_object_flags_get_type ());
+  g_type_class_ref (gst_bin_flags_get_type ());
+  g_type_class_ref (gst_buffer_flag_get_type ());
+  g_type_class_ref (gst_buffer_copy_flags_get_type ());
+  g_type_class_ref (gst_buffer_list_item_get_type ());
+  g_type_class_ref (gst_bus_flags_get_type ());
+  g_type_class_ref (gst_bus_sync_reply_get_type ());
+  g_type_class_ref (gst_caps_flags_get_type ());
+  g_type_class_ref (gst_clock_return_get_type ());
+  g_type_class_ref (gst_clock_entry_type_get_type ());
+  g_type_class_ref (gst_clock_flags_get_type ());
+  g_type_class_ref (gst_clock_type_get_type ());
+  g_type_class_ref (gst_debug_graph_details_get_type ());
+  g_type_class_ref (gst_state_get_type ());
+  g_type_class_ref (gst_state_change_return_get_type ());
+  g_type_class_ref (gst_state_change_get_type ());
+  g_type_class_ref (gst_element_flags_get_type ());
+  g_type_class_ref (gst_core_error_get_type ());
+  g_type_class_ref (gst_library_error_get_type ());
+  g_type_class_ref (gst_resource_error_get_type ());
+  g_type_class_ref (gst_stream_error_get_type ());
+  g_type_class_ref (gst_event_type_flags_get_type ());
+  g_type_class_ref (gst_event_type_get_type ());
+  g_type_class_ref (gst_seek_type_get_type ());
+  g_type_class_ref (gst_seek_flags_get_type ());
+  g_type_class_ref (gst_format_get_type ());
+  g_type_class_ref (gst_index_certainty_get_type ());
+  g_type_class_ref (gst_index_entry_type_get_type ());
+  g_type_class_ref (gst_index_lookup_method_get_type ());
+  g_type_class_ref (gst_assoc_flags_get_type ());
+  g_type_class_ref (gst_index_resolver_method_get_type ());
+  g_type_class_ref (gst_index_flags_get_type ());
+  g_type_class_ref (gst_debug_level_get_type ());
+  g_type_class_ref (gst_debug_color_flags_get_type ());
+  g_type_class_ref (gst_iterator_result_get_type ());
+  g_type_class_ref (gst_iterator_item_get_type ());
+  g_type_class_ref (gst_message_type_get_type ());
+  g_type_class_ref (gst_mini_object_flags_get_type ());
+  g_type_class_ref (gst_pad_link_return_get_type ());
+  g_type_class_ref (gst_flow_return_get_type ());
+  g_type_class_ref (gst_activate_mode_get_type ());
+  g_type_class_ref (gst_pad_direction_get_type ());
+  g_type_class_ref (gst_pad_flags_get_type ());
+  g_type_class_ref (gst_pad_presence_get_type ());
+  g_type_class_ref (gst_pad_template_flags_get_type ());
+  g_type_class_ref (gst_pipeline_flags_get_type ());
+  g_type_class_ref (gst_plugin_error_get_type ());
+  g_type_class_ref (gst_plugin_flags_get_type ());
+  g_type_class_ref (gst_plugin_dependency_flags_get_type ());
+  g_type_class_ref (gst_rank_get_type ());
+  g_type_class_ref (gst_query_type_get_type ());
+  g_type_class_ref (gst_buffering_mode_get_type ());
+  g_type_class_ref (gst_stream_status_type_get_type ());
+  g_type_class_ref (gst_structure_change_type_get_type ());
+  g_type_class_ref (gst_tag_merge_mode_get_type ());
+  g_type_class_ref (gst_tag_flag_get_type ());
+  g_type_class_ref (gst_task_pool_get_type ());
+  g_type_class_ref (gst_task_state_get_type ());
+  g_type_class_ref (gst_alloc_trace_flags_get_type ());
+  g_type_class_ref (gst_type_find_probability_get_type ());
+  g_type_class_ref (gst_uri_type_get_type ());
+  g_type_class_ref (gst_parse_error_get_type ());
+  g_type_class_ref (gst_parse_flags_get_type ());
+  g_type_class_ref (gst_search_mode_get_type ());
 
   gst_structure_get_type ();
   _gst_value_initialize ();
@@ -1091,11 +1136,14 @@
   gst_caps_get_type ();
   _gst_event_initialize ();
   _gst_buffer_initialize ();
+  _gst_buffer_list_initialize ();
   _gst_message_initialize ();
   _gst_tag_initialize ();
 
   _gst_plugin_initialize ();
 
+  gst_g_error_get_type ();
+
   /* register core plugins */
   gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
       "staticelements", "core elements linked into the GStreamer library",
@@ -1179,6 +1227,20 @@
     GstDebugCategory *cat = (GstDebugCategory *) walk->data;
 
     if (gst_debug_is_colored ()) {
+#ifdef G_OS_WIN32
+      gint color = gst_debug_construct_win_color (cat->color);
+      const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+
+      SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
+      g_print ("%-20s", gst_debug_category_get_name (cat));
+      SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
+      g_print (" %1d %s ", gst_debug_category_get_threshold (cat),
+          gst_debug_level_get_name (gst_debug_category_get_threshold (cat)));
+      SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
+      g_print ("%s", gst_debug_category_get_description (cat));
+      SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
+      g_print ("\n");
+#else /* G_OS_WIN32 */
       gchar *color = gst_debug_construct_term_color (cat->color);
 
       g_print ("%s%-20s\033[00m  %1d %s  %s%s\033[00m\n",
@@ -1188,6 +1250,7 @@
           gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
           color, gst_debug_category_get_description (cat));
       g_free (color);
+#endif /* G_OS_WIN32 */
     } else {
       g_print ("%-20s  %1d %s  %s\n", gst_debug_category_get_name (cat),
           gst_debug_category_get_threshold (cat),
@@ -1253,11 +1316,9 @@
     case ARG_SEGTRAP_DISABLE:
       _gst_disable_segtrap = TRUE;
       break;
-#ifdef __SYMBIAN32__	  
     case ARG_REGISTRY_UPDATE_DISABLE:
       _gst_disable_registry_update = TRUE;
       break;
-#endif	  
     case ARG_REGISTRY_FORK_DISABLE:
       _gst_enable_registry_fork = FALSE;
       break;
@@ -1295,10 +1356,8 @@
     "--gst-plugin-path", ARG_PLUGIN_PATH}, {
     "--gst-plugin-load", ARG_PLUGIN_LOAD}, {
     "--gst-disable-segtrap", ARG_SEGTRAP_DISABLE}, {
-#ifdef __SYMBIAN32__	
     "--gst-disable-registry-update", ARG_REGISTRY_UPDATE_DISABLE}, {
-#endif    
-	"--gst-disable-registry-fork", ARG_REGISTRY_FORK_DISABLE}, {
+    "--gst-disable-registry-fork", ARG_REGISTRY_FORK_DISABLE}, {
     NULL}
   };
   gint val = 0, n;
@@ -1366,9 +1425,76 @@
   g_type_class_unref (g_type_class_peek (gst_element_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_type_find_factory_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_bin_get_type ()));
-#ifndef GST_DISABLE_INDEX
+  g_type_class_unref (g_type_class_peek (gst_bus_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_task_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_index_factory_get_type ()));
-#endif /* GST_DISABLE_INDEX */
+  g_type_class_unref (g_type_class_peek (gst_object_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_buffer_flag_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_buffer_list_item_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_clock_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_clock_return_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_clock_entry_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_clock_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_debug_graph_details_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_state_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_state_change_return_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_state_change_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_element_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_core_error_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_library_error_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_plugin_dependency_flags_get_type
+          ()));
+  g_type_class_unref (g_type_class_peek (gst_parse_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_resource_error_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_search_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_stream_error_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_stream_status_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_structure_change_type_get_type
+          ()));
+  g_type_class_unref (g_type_class_peek (gst_event_type_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_event_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_seek_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_seek_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_format_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_index_certainty_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_index_entry_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_index_lookup_method_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_assoc_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_index_resolver_method_get_type
+          ()));
+  g_type_class_unref (g_type_class_peek (gst_index_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_debug_level_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_debug_color_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_iterator_result_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_iterator_item_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_message_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_mini_object_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_link_return_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_flow_return_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_activate_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_direction_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_presence_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_template_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pipeline_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_rank_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_query_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_tag_flag_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_task_state_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_alloc_trace_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_type_find_probability_get_type
+          ()));
+  g_type_class_unref (g_type_class_peek (gst_uri_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ()));
 
   gst_deinitialized = TRUE;
@@ -1424,7 +1550,7 @@
   if (nano == 0)
     return g_strdup_printf ("GStreamer %d.%d.%d", major, minor, micro);
   else if (nano == 1)
-    return g_strdup_printf ("GStreamer %d.%d.%d (CVS)", major, minor, micro);
+    return g_strdup_printf ("GStreamer %d.%d.%d (GIT)", major, minor, micro);
   else
     return g_strdup_printf ("GStreamer %d.%d.%d (prerelease)", major, minor,
         micro);
--- a/gstreamer_core/gst/gst.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gst.h	Fri Apr 16 15:15:52 2010 +0300
@@ -25,10 +25,6 @@
 #define __GST_H__
 
 #include <glib.h>
-#ifdef __SYMBIAN32__
-#include <gst/gst_global.h>
-#include <glib_global.h>
-#endif
 
 #include <gst/glib-compat.h>
 
@@ -37,6 +33,7 @@
 
 #include <gst/gstbin.h>
 #include <gst/gstbuffer.h>
+#include <gst/gstbufferlist.h>
 #include <gst/gstcaps.h>
 #include <gst/gstchildproxy.h>
 #include <gst/gstclock.h>
@@ -59,6 +56,7 @@
 #include <gst/gstpipeline.h>
 #include <gst/gstplugin.h>
 #include <gst/gstpoll.h>
+#include <gst/gstpreset.h>
 #include <gst/gstquery.h>
 #include <gst/gstregistry.h>
 #include <gst/gstsegment.h>
@@ -67,6 +65,7 @@
 #include <gst/gsttaglist.h>
 #include <gst/gsttagsetter.h>
 #include <gst/gsttask.h>
+#include <gst/gsttaskpool.h>
 #include <gst/gsttrace.h>
 #include <gst/gsttypefind.h>
 #include <gst/gsttypefindfactory.h>
--- a/gstreamer_core/gst/gst_global.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gst_global.h	Fri Apr 16 15:15:52 2010 +0300
@@ -1,24 +1,15 @@
 /*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
+ *  Copyright © 2005-06 Nokia Corporation.
+ *  This material, including documentation and any related 
+ *  computer programs, is protected by copyright controlled by 
+ *  Nokia Corporation. All rights are reserved. Copying, 
+ *  including reproducing, storing, adapting or translating, any 
+ *  or all of this material requires the prior written consent of 
+ *  Nokia Corporation. This material also contains confidential 
+ *  information which may not be disclosed to others without the 
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
 
 #ifndef __GST_GLOBAL_H__
 #define __GST_GLOBAL_H__
@@ -27,5 +18,5 @@
 #define	GST_CAT_DEFAULT	(*_GST_CAT_DEFAULT())
 #define GST_CAT_EVENT (*_GST_CAT_EVENT())
 #define	__gst_debug_enabled	(*gst_debug_enabled())
-
+#define __gst_debug_min (*gst_debug_min())
 #endif /* __GST_GLOBAL_H__ */
--- a/gstreamer_core/gst/gst_private.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gst_private.h	Fri Apr 16 15:15:52 2010 +0300
@@ -20,12 +20,13 @@
  * Boston, MA 02111-1307, USA.
  */
 
-
 #ifndef __GST_PRIVATE_H__
 #define __GST_PRIVATE_H__
 
 #ifdef HAVE_CONFIG_H
+# ifndef GST_LICENSE   /* don't include config.h twice, it has no guards */
 #  include "config.h"
+# endif
 #endif
 
 /* This needs to be before glib.h, since it might be used in inline
@@ -41,8 +42,52 @@
 #include "gstregistry.h"
 #include "gststructure.h"
 
+/* we need this in pretty much all files */
+#include "gstinfo.h"
+
+/* for the flags in the GstPluginDep structure below */
+#include "gstplugin.h"
+
 G_BEGIN_DECLS
 
+/* used by gstparse.c and grammar.y */
+struct _GstParseContext {
+  GList * missing_elements;
+};
+
+/* used by gstplugin.c and gstregistrybinary.c */
+typedef struct {
+  /* details registered via gst_plugin_add_dependency() */
+  GstPluginDependencyFlags  flags;
+  gchar **env_vars;
+  gchar **paths;
+  gchar **names;
+
+  /* information saved from the last time the plugin was loaded (-1 = unset) */
+  guint   env_hash;  /* hash of content of environment variables in env_vars */
+  guint   stat_hash; /* hash of stat() on all relevant files and directories */
+} GstPluginDep;
+
+struct _GstPluginPrivate {
+  GList *deps;    /* list of GstPluginDep structures */
+  GstStructure *cache_data;
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean _priv_plugin_deps_files_changed (GstPlugin * plugin);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 gboolean _priv_gst_in_valgrind (void);
 
 /* Initialize GStreamer private quark storage */
@@ -66,6 +111,11 @@
 IMPORT_C
 #endif
 
+void  _gst_buffer_list_initialize (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void  _gst_event_initialize (void);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -118,69 +168,58 @@
 
 /* registry cache backends */
 /* FIXME 0.11: use priv_ prefix */
-#ifdef USE_BINARY_REGISTRY
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 gboolean 		gst_registry_binary_read_cache 	(GstRegistry * registry, const char *location);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 gboolean 		gst_registry_binary_write_cache	(GstRegistry * registry, const char *location);
-/* FIXME 0.11: this is in registry.h for backwards compatibility
-#else 
-gboolean 		gst_registry_xml_read_cache 	(GstRegistry * registry, const char *location);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
+
 
-gboolean 		gst_registry_xml_write_cache 	(GstRegistry * registry, const char *location);
-*/
-#endif
+/* used in gstvalue.c and gststructure.c */
+#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
+    ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
+    ((c) == '.'))
 
 /*** debugging categories *****************************************************/
 
-#ifndef GST_DISABLE_GST_DEBUG
-
-#ifndef _MSC_VER
-#define IMPORT_SYMBOL
-#else /* _MSC_VER */
-#ifndef LIBGSTREAMER_EXPORTS
-#define IMPORT_SYMBOL __declspec(dllimport)
-#else
-#define IMPORT_SYMBOL 
-#endif
-#endif
-
-#include <gst/gstinfo.h>
+#ifndef GST_REMOVE_GST_DEBUG
 
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_GST_INIT;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_AUTOPLUG;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PARENTAGE;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_STATES;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_SCHEDULING;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_BUFFER;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_BUS;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_CAPS;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_CLOCK;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_ELEMENT_PADS;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PADS;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PIPELINE;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PLUGIN_LOADING;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PLUGIN_INFO;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PROPERTIES;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_XML;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_NEGOTIATION;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_REFCOUNTING;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_ERROR_SYSTEM;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_EVENT;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_MESSAGE;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PARAMS;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_CALL_TRACE;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_SIGNAL;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_PROBE;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_REGISTRY;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_QOS;
-extern IMPORT_SYMBOL GstDebugCategory *GST_CAT_TYPES; /* FIXME 0.11: remove? */
+GST_EXPORT GstDebugCategory *GST_CAT_GST_INIT;
+GST_EXPORT GstDebugCategory *GST_CAT_AUTOPLUG; /* FIXME 0.11: remove? */
+GST_EXPORT GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT; /* FIXME 0.11: remove? */
+GST_EXPORT GstDebugCategory *GST_CAT_PARENTAGE;
+GST_EXPORT GstDebugCategory *GST_CAT_STATES;
+GST_EXPORT GstDebugCategory *GST_CAT_SCHEDULING;
+GST_EXPORT GstDebugCategory *GST_CAT_BUFFER;
+GST_EXPORT GstDebugCategory *GST_CAT_BUFFER_LIST;
+GST_EXPORT GstDebugCategory *GST_CAT_BUS;
+GST_EXPORT GstDebugCategory *GST_CAT_CAPS;
+GST_EXPORT GstDebugCategory *GST_CAT_CLOCK;
+GST_EXPORT GstDebugCategory *GST_CAT_ELEMENT_PADS;
+GST_EXPORT GstDebugCategory *GST_CAT_PADS;
+GST_EXPORT GstDebugCategory *GST_CAT_PERFORMANCE;
+GST_EXPORT GstDebugCategory *GST_CAT_PIPELINE;
+GST_EXPORT GstDebugCategory *GST_CAT_PLUGIN_LOADING;
+GST_EXPORT GstDebugCategory *GST_CAT_PLUGIN_INFO;
+GST_EXPORT GstDebugCategory *GST_CAT_PROPERTIES;
+GST_EXPORT GstDebugCategory *GST_CAT_XML;
+GST_EXPORT GstDebugCategory *GST_CAT_NEGOTIATION;
+GST_EXPORT GstDebugCategory *GST_CAT_REFCOUNTING;
+GST_EXPORT GstDebugCategory *GST_CAT_ERROR_SYSTEM;
+GST_EXPORT GstDebugCategory *GST_CAT_EVENT;
+GST_EXPORT GstDebugCategory *GST_CAT_MESSAGE;
+GST_EXPORT GstDebugCategory *GST_CAT_PARAMS;
+GST_EXPORT GstDebugCategory *GST_CAT_CALL_TRACE;
+GST_EXPORT GstDebugCategory *GST_CAT_SIGNAL;
+GST_EXPORT GstDebugCategory *GST_CAT_PROBE;
+GST_EXPORT GstDebugCategory *GST_CAT_REGISTRY;
+GST_EXPORT GstDebugCategory *GST_CAT_QOS;
+GST_EXPORT GstDebugCategory *GST_CAT_TYPES; /* FIXME 0.11: remove? */
 
 #else
 
@@ -192,11 +231,13 @@
 #define GST_CAT_SCHEDULING       NULL
 #define GST_CAT_DATAFLOW         NULL
 #define GST_CAT_BUFFER           NULL
+#define GST_CAT_BUFFER_LIST      NULL
 #define GST_CAT_BUS              NULL
 #define GST_CAT_CAPS             NULL
 #define GST_CAT_CLOCK            NULL
 #define GST_CAT_ELEMENT_PADS     NULL
 #define GST_CAT_PADS             NULL
+#define GST_CAT_PERFORMANCE      NULL
 #define GST_CAT_PIPELINE         NULL
 #define GST_CAT_PLUGIN_LOADING   NULL
 #define GST_CAT_PLUGIN_INFO      NULL
--- a/gstreamer_core/gst/gstbin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstbin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -51,10 +51,9 @@
  *
  * gst_object_unref() is used to drop your reference to the bin.
  *
- * The <link linkend="GstBin-element-added">element-added</link> signal is
- * fired whenever a new element is added to the bin. Likewise the <link
- * linkend="GstBin-element-removed">element-removed</link> signal is fired
- * whenever an element is removed from the bin.
+ * The #GstBin::element-added signal is fired whenever a new element is added to
+ * the bin. Likewise the #GstBin::element-removed signal is fired whenever an
+ * element is removed from the bin.
  *
  * <refsect2><title>Notes</title>
  * <para>
@@ -174,7 +173,6 @@
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #endif
-
 /* enable for DURATION caching.
  * FIXME currently too many elements don't update
  * their duration when it changes so we return inaccurate values. */
@@ -193,9 +191,20 @@
  * a toplevel bin */
 #define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling)
 
+#define GST_BIN_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BIN, GstBinPrivate))
+
 struct _GstBinPrivate
 {
   gboolean asynchandling;
+  /* if we get an ASYNC_DONE message from ourselves, this means that the
+   * subclass will simulate ASYNC behaviour without having ASYNC children. When
+   * such an ASYNC_DONE message is posted while we are doing a state change, we
+   * have to process the message after finishing the state change even when no
+   * child returned GST_STATE_CHANGE_ASYNC. */
+  gboolean pending_async_done;
+
+  guint32 structure_cookie;
 };
 
 typedef struct
@@ -216,16 +225,15 @@
     GstStateChange transition);
 static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
     GstState * state, GstState * pending, GstClockTime timeout);
-static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret);
+static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
+    gboolean flag_pending);
 static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
 static void bin_push_state_continue (BinContinueData * data);
 
 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
 
-#ifndef GST_DISABLE_INDEX
 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
-#endif
 static GstClock *gst_bin_provide_clock_func (GstElement * element);
 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
 
@@ -235,6 +243,8 @@
     GstMessage * message, GstBin * bin);
 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
 
+static gboolean gst_bin_do_latency_func (GstBin * bin);
+
 #ifndef GST_DISABLE_LOADSAVE
 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
@@ -253,6 +263,7 @@
 {
   ELEMENT_ADDED,
   ELEMENT_REMOVED,
+  DO_LATENCY,
   LAST_SIGNAL
 };
 
@@ -265,69 +276,35 @@
       /* FILL ME */
 };
 
-static void gst_bin_base_init (gpointer g_class);
-static void gst_bin_class_init (GstBinClass * klass);
-static void gst_bin_init (GstBin * bin);
 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
 
-static GstElementClass *parent_class = NULL;
 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
 
-/**
- * gst_bin_get_type:
- *
- * Returns: the type of #GstBin
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_bin_get_type (void)
-{
-  static GType gst_bin_type = 0;
-  const gchar *compat;
-
-  if (G_UNLIKELY (gst_bin_type == 0)) {
-    static const GTypeInfo bin_info = {
-      sizeof (GstBinClass),
-      gst_bin_base_init,
-      NULL,
-      (GClassInitFunc) gst_bin_class_init,
-      NULL,
-      NULL,
-      sizeof (GstBin),
-      0,
-      (GInstanceInitFunc) gst_bin_init,
-      NULL
-    };
-    static const GInterfaceInfo child_proxy_info = {
-      gst_bin_child_proxy_init,
-      NULL,
-      NULL
-    };
-
-    gst_bin_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
-
-    g_type_add_interface_static (gst_bin_type, GST_TYPE_CHILD_PROXY,
-        &child_proxy_info);
-
-    GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
-        "debugging info for the 'bin' container element");
-
-    /* compatibility stuff */
-    compat = g_getenv ("GST_COMPAT");
-    if (compat != NULL) {
-      if (strstr (compat, "no-live-preroll"))
-        enable_latency = FALSE;
-      else if (strstr (compat, "live-preroll"))
-        enable_latency = TRUE;
-    }
-  }
-  return gst_bin_type;
+#define _do_init(type) \
+{ \
+  const gchar *compat; \
+  static const GInterfaceInfo iface_info = { \
+    gst_bin_child_proxy_init, \
+    NULL, \
+    NULL}; \
+  \
+  g_type_add_interface_static (type, GST_TYPE_CHILD_PROXY, &iface_info); \
+  \
+  GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, \
+      "debugging info for the 'bin' container element"); \
+  \
+  /* compatibility stuff */ \
+  compat = g_getenv ("GST_COMPAT"); \
+  if (compat != NULL) { \
+    if (strstr (compat, "no-live-preroll")) \
+      enable_latency = FALSE; \
+    else if (strstr (compat, "live-preroll")) \
+      enable_latency = TRUE; \
+  } \
 }
 
+GST_BOILERPLATE_FULL (GstBin, gst_bin, GstElement, GST_TYPE_ELEMENT, _do_init);
+
 static void
 gst_bin_base_init (gpointer g_class)
 {
@@ -385,6 +362,22 @@
   iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
 }
 
+static gboolean
+_gst_boolean_accumulator (GSignalInvocationHint * ihint,
+    GValue * return_accu, const GValue * handler_return, gpointer dummy)
+{
+  gboolean myboolean;
+
+  myboolean = g_value_get_boolean (handler_return);
+  if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
+    g_value_set_boolean (return_accu, myboolean);
+
+  GST_DEBUG ("invocation %d, %d", ihint->run_type, myboolean);
+
+  /* stop emission */
+  return FALSE;
+}
+
 static void
 gst_bin_class_init (GstBinClass * klass)
 {
@@ -397,7 +390,7 @@
   gstobject_class = (GstObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
+  g_type_class_add_private (klass, sizeof (GstBinPrivate));
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bin_set_property);
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bin_get_property);
@@ -414,7 +407,7 @@
   g_object_class_install_property (gobject_class, PROP_ASYNC_HANDLING,
       g_param_spec_boolean ("async-handling", "Async Handling",
           "The bin will handle Asynchronous state changes",
-          DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE));
+          DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstBin::element-added:
@@ -438,6 +431,29 @@
       g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
       NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
+  /**
+   * GstBin::do-latency:
+   * @bin: the #GstBin
+   *
+   * Will be emitted when the bin needs to perform latency calculations. This
+   * signal is only emited for toplevel bins or when async-handling is
+   * enabled.
+   *
+   * Only one signal handler is invoked. If no signals are connected, the
+   * default handler is invoked, which will query and distribute the lowest
+   * possible latency to all sinks.
+   *
+   * Connect to this signal if the default latency calculations are not
+   * sufficient, like when you need different latencies for different sinks in
+   * the same pipeline.
+   *
+   * Since: 0.10.22
+   */
+  gst_bin_signals[DO_LATENCY] =
+      g_signal_new ("do-latency", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstBinClass, do_latency),
+      _gst_boolean_accumulator, NULL, gst_marshal_BOOLEAN__VOID,
+      G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
 
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
 
@@ -450,9 +466,7 @@
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
   gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
-#ifndef GST_DISABLE_INDEX
   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
-#endif
   gstelement_class->provide_clock =
       GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
@@ -464,6 +478,8 @@
   klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
   klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func);
 
+  klass->do_latency = GST_DEBUG_FUNCPTR (gst_bin_do_latency_func);
+
   GST_DEBUG ("creating bin thread pool");
   err = NULL;
   klass->pool =
@@ -474,7 +490,7 @@
 }
 
 static void
-gst_bin_init (GstBin * bin)
+gst_bin_init (GstBin * bin, GstBinClass * klass)
 {
   GstBus *bus;
 
@@ -492,8 +508,9 @@
       bus);
   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
 
-  bin->priv = g_new0 (GstBinPrivate, 1);
+  bin->priv = GST_BIN_GET_PRIVATE (bin);
   bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING;
+  bin->priv->structure_cookie = 0;
 }
 
 static void
@@ -506,11 +523,12 @@
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
 
-  bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
-
+  GST_OBJECT_LOCK (object);
   gst_object_replace ((GstObject **) child_bus_p, NULL);
   gst_object_replace ((GstObject **) provided_clock_p, NULL);
   gst_object_replace ((GstObject **) clock_provider_p, NULL);
+  bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
+  GST_OBJECT_UNLOCK (object);
 
   while (bin->children) {
     gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
@@ -520,11 +538,6 @@
         GST_STR_NULL (GST_OBJECT_NAME (object)));
   }
 
-  if (bin->priv) {
-    g_free (bin->priv);
-    bin->priv = NULL;
-  }
-
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -590,24 +603,45 @@
  *
  * MT safe
  */
-#ifndef GST_DISABLE_INDEX
 static void
 gst_bin_set_index_func (GstElement * element, GstIndex * index)
 {
   GstBin *bin;
-  GList *children;
+  gboolean done;
+  GstIterator *it;
 
   bin = GST_BIN (element);
 
-  GST_OBJECT_LOCK (bin);
-  for (children = bin->children; children; children = g_list_next (children)) {
-    GstElement *child = GST_ELEMENT (children->data);
-
-    gst_element_set_index (child, index);
+  it = gst_bin_iterate_elements (bin);
+
+  done = FALSE;
+  while (!done) {
+    gpointer data;
+
+    switch (gst_iterator_next (it, &data)) {
+      case GST_ITERATOR_OK:
+      {
+        GstElement *child = GST_ELEMENT_CAST (data);
+
+        GST_DEBUG_OBJECT (bin, "setting index on %s", GST_ELEMENT_NAME (child));
+        gst_element_set_index (child, index);
+
+        gst_object_unref (child);
+        break;
+      }
+      case GST_ITERATOR_RESYNC:
+        GST_DEBUG_OBJECT (bin, "iterator doing resync");
+        gst_iterator_resync (it);
+        break;
+      default:
+      case GST_ITERATOR_DONE:
+        GST_DEBUG_OBJECT (bin, "iterator done");
+        done = TRUE;
+        break;
+    }
   }
-  GST_OBJECT_UNLOCK (bin);
+  gst_iterator_free (it);
 }
-#endif
 
 /* set the clock on all elements in this bin
  *
@@ -616,21 +650,42 @@
 static gboolean
 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
 {
-  GList *children;
   GstBin *bin;
+  gboolean done;
+  GstIterator *it;
   gboolean res = TRUE;
 
   bin = GST_BIN (element);
 
-  GST_OBJECT_LOCK (bin);
-  if (element->clock != clock) {
-    for (children = bin->children; children; children = g_list_next (children)) {
-      GstElement *child = GST_ELEMENT (children->data);
-
-      res &= gst_element_set_clock (child, clock);
+  it = gst_bin_iterate_elements (bin);
+
+  done = FALSE;
+  while (!done) {
+    gpointer data;
+
+    switch (gst_iterator_next (it, &data)) {
+      case GST_ITERATOR_OK:
+      {
+        GstElement *child = GST_ELEMENT_CAST (data);
+
+        res &= gst_element_set_clock (child, clock);
+
+        gst_object_unref (child);
+        break;
+      }
+      case GST_ITERATOR_RESYNC:
+        GST_DEBUG_OBJECT (bin, "iterator doing resync");
+        gst_iterator_resync (it);
+        res = TRUE;
+        break;
+      default:
+      case GST_ITERATOR_DONE:
+        GST_DEBUG_OBJECT (bin, "iterator done");
+        done = TRUE;
+        break;
     }
   }
-  GST_OBJECT_UNLOCK (bin);
+  gst_iterator_free (it);
 
   return res;
 }
@@ -731,6 +786,7 @@
     eq &= GST_MESSAGE_SRC (message) == target->src;
   if (target->types)
     eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0;
+  GST_LOG ("looking at message %p: %d", message, eq);
 
   return (eq ? 0 : 1);
 }
@@ -767,7 +823,7 @@
   return result;
 }
 
-/* with LOCK, returns TRUE if message had a valid SRC, takes ref on
+/* with LOCK, returns TRUE if message had a valid SRC, takes ownership of
  * the message.
  *
  * A message that is cached and has the same SRC and type is replaced
@@ -786,12 +842,16 @@
   if ((src = GST_MESSAGE_SRC (message))) {
     /* first find the previous message posted by this element */
     if ((previous = find_message (bin, src, types))) {
+      GstMessage *previous_msg;
+
       /* if we found a previous message, replace it */
-      gst_message_unref (previous->data);
+      previous_msg = previous->data;
       previous->data = message;
 
-      GST_DEBUG_OBJECT (bin, "replace old message %s from %s",
-          name, GST_ELEMENT_NAME (src));
+      GST_DEBUG_OBJECT (bin, "replace old message %s from %s with %s message",
+          GST_MESSAGE_TYPE_NAME (previous_msg), GST_ELEMENT_NAME (src), name);
+
+      gst_message_unref (previous_msg);
     } else {
       /* keep new message */
       bin->messages = g_list_prepend (bin->messages, message);
@@ -935,12 +995,14 @@
   bin->children = g_list_prepend (bin->children, element);
   bin->numchildren++;
   bin->children_cookie++;
+  bin->priv->structure_cookie++;
 
   /* distribute the bus */
   gst_element_set_bus (element, bin->child_bus);
 
-  /* propagate the current base_time and clock */
+  /* propagate the current base_time, start_time and clock */
   gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
+  gst_element_set_start_time (element, GST_ELEMENT_START_TIME (bin));
   /* it's possible that the element did not accept the clock but
    * that is not important right now. When the pipeline goes to PLAYING,
    * a new clock will be selected */
@@ -968,7 +1030,7 @@
     }
     case GST_STATE_CHANGE_NO_PREROLL:
       /* ignore all async elements we might have and commit our state */
-      bin_handle_async_done (bin, ret);
+      bin_handle_async_done (bin, ret, FALSE);
       break;
     case GST_STATE_CHANGE_FAILURE:
       break;
@@ -1087,6 +1149,8 @@
   GstIterator *it;
   gboolean is_sink, othersink, found;
   GstMessage *clock_message = NULL;
+  GstClock **provided_clock_p;
+  GstElement **clock_provider_p;
   GList *walk, *next;
   gboolean other_async, this_async, have_no_preroll;
   GstStateChangeReturn ret;
@@ -1148,6 +1212,7 @@
    * so that others can detect a change in the children list. */
   bin->numchildren--;
   bin->children_cookie++;
+  bin->priv->structure_cookie++;
 
   if (is_sink && !othersink) {
     /* we're not a sink anymore */
@@ -1163,6 +1228,10 @@
     bin->clock_dirty = TRUE;
     clock_message =
         gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock);
+    provided_clock_p = &bin->provided_clock;
+    clock_provider_p = &bin->clock_provider;
+    gst_object_replace ((GstObject **) provided_clock_p, NULL);
+    gst_object_replace ((GstObject **) clock_provider_p, NULL);
   }
 
   /* remove messages for the element, if there was a pending ASYNC_START
@@ -1173,22 +1242,46 @@
   for (walk = bin->messages; walk; walk = next) {
     GstMessage *message = (GstMessage *) walk->data;
     GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message));
+    gboolean remove;
 
     next = g_list_next (walk);
-
-    if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_START) {
-      if (src == element)
-        this_async = TRUE;
-      else
-        other_async = TRUE;
-
-      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
-          "looking at message %p", message);
+    remove = FALSE;
+
+    switch (GST_MESSAGE_TYPE (message)) {
+      case GST_MESSAGE_ASYNC_START:
+        if (src == element)
+          this_async = TRUE;
+        else
+          other_async = TRUE;
+
+        GST_DEBUG_OBJECT (src, "looking at message %p", message);
+        break;
+      case GST_MESSAGE_STRUCTURE_CHANGE:
+      {
+        GstElement *owner;
+
+        GST_DEBUG_OBJECT (src, "looking at structure change message %p",
+            message);
+        /* it's unlikely that this message is still in the list of messages
+         * because this would mean that a link/unlink is busy in another thread
+         * while we remove the element. We still have to remove the message
+         * because we might not receive the done message anymore when the element
+         * is removed from the bin. */
+        gst_message_parse_structure_change (message, NULL, &owner, NULL);
+        if (owner == element)
+          remove = TRUE;
+        break;
+      }
+      default:
+        break;
     }
-    if (src == element) {
+    if (src == element)
+      remove = TRUE;
+
+    if (remove) {
       /* delete all message types */
-      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
-          "deleting message %p of element \"%s\"", message, elem_name);
+      GST_DEBUG_OBJECT (src, "deleting message %p of element \"%s\"",
+          message, elem_name);
       bin->messages = g_list_delete_link (bin->messages, walk);
       gst_message_unref (message);
     }
@@ -1215,7 +1308,7 @@
     else
       ret = GST_STATE_CHANGE_SUCCESS;
 
-    bin_handle_async_done (bin, ret);
+    bin_handle_async_done (bin, ret, FALSE);
   } else {
     GST_DEBUG_OBJECT (bin,
         "recalc state preroll: %d, other async: %d, this async %d",
@@ -1695,18 +1788,28 @@
   gboolean linked = FALSE;
 
   GST_OBJECT_LOCK (element);
-  /* don't touch degree if element has no sourcepads */
+  /* don't touch degree if element has no sinkpads */
   if (element->numsinkpads != 0) {
     /* loop over all sinkpads, decrement degree for all connected
      * elements in this bin */
     GList *pads;
 
     for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
-      GstPad *peer;
-
-      if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
+      GstPad *pad, *peer;
+
+      pad = GST_PAD_CAST (pads->data);
+
+      if ((peer = gst_pad_get_peer (pad))) {
         GstElement *peer_element;
 
+        /* we're iterating over the sinkpads, this is the peer and thus the
+         * srcpad, check if it's busy in a link/unlink */
+        if (G_UNLIKELY (find_message (bit->bin, GST_OBJECT_CAST (peer),
+                    GST_MESSAGE_STRUCTURE_CHANGE))) {
+          gst_object_unref (peer);
+          continue;
+        }
+
         if ((peer_element = gst_pad_get_parent_element (peer))) {
           GST_OBJECT_LOCK (peer_element);
           /* check that we don't go outside of this bin */
@@ -1729,7 +1832,10 @@
                 GST_ELEMENT_NAME (peer_element), old_deg, new_deg,
                 GST_ELEMENT_NAME (element));
 
-            /* update degree */
+            /* update degree, it is possible that an element was in 0 and
+             * reaches -1 here. This would mean that the element had no sinkpads
+             * but became linked while the state change was happening. We will
+             * resync on this with the structure change message. */
             if (new_deg == 0) {
               /* degree hit 0, add to queue */
               add_to_queue (bit, peer_element);
@@ -1857,7 +1963,7 @@
       gst_iterator_new (sizeof (GstBinSortIterator),
       GST_TYPE_ELEMENT,
       GST_OBJECT_GET_LOCK (bin),
-      &bin->children_cookie,
+      &bin->priv->structure_cookie,
       (GstIteratorNextFunction) gst_bin_sort_iterator_next,
       (GstIteratorItemFunction) NULL,
       (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
@@ -1909,14 +2015,20 @@
 
 static GstStateChangeReturn
 gst_bin_element_set_state (GstBin * bin, GstElement * element,
-    GstClockTime base_time, GstState current, GstState next)
+    GstClockTime base_time, GstClockTime start_time, GstState current,
+    GstState next)
 {
   GstStateChangeReturn ret;
   gboolean locked;
   GList *found;
 
+  GST_STATE_LOCK (element);
+
+  GST_OBJECT_LOCK (element);
+  /* set base_time and start time on child */
+  GST_ELEMENT_START_TIME (element) = start_time;
+  element->base_time = base_time;
   /* peel off the locked flag */
-  GST_OBJECT_LOCK (element);
   locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
   /* get previous state return */
   ret = GST_STATE_RETURN (element);
@@ -1970,12 +2082,11 @@
       GST_ELEMENT_NAME (element), gst_element_state_get_name (next),
       GST_TIME_ARGS (base_time));
 
-  /* set base_time on child */
-  gst_element_set_base_time (element, base_time);
-
   /* change state */
   ret = gst_element_set_state (element, next);
 
+  GST_STATE_UNLOCK (element);
+
   return ret;
 
 locked:
@@ -1983,12 +2094,14 @@
     GST_DEBUG_OBJECT (element,
         "element is locked, return previous return %s",
         gst_element_state_change_return_get_name (ret));
+    GST_STATE_UNLOCK (element);
     return ret;
   }
 was_busy:
   {
     GST_DEBUG_OBJECT (element, "element was busy, delaying state change");
     GST_OBJECT_UNLOCK (bin);
+    GST_STATE_UNLOCK (element);
     return GST_STATE_CHANGE_ASYNC;
   }
 }
@@ -2075,15 +2188,50 @@
   }
 }
 
-/* do latency correction. We do a latency query on the bin, and then send a
- * LATENCY event on the elements fo configure them */
+/**
+ * gst_bin_recalculate_latency:
+ * @bin: a #GstBin
+ *
+ * Query @bin for the current latency using and reconfigures this latency to all the
+ * elements with a LATENCY event.
+ *
+ * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY
+ * is posted on the bus.
+ *
+ * This function simply emits the 'do-latency' signal so any custom latency
+ * calculations will be performed.
+ *
+ * Returns: %TRUE if the latency could be queried and reconfigured.
+ *
+ * Since: 0.10.22.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_bin_recalculate_latency (GstBin * bin)
+{
+  gboolean res;
+
+  g_signal_emit (G_OBJECT (bin), gst_bin_signals[DO_LATENCY], 0, &res);
+  GST_DEBUG_OBJECT (bin, "latency returned %d", res);
+
+  return res;
+}
+
 static gboolean
-do_bin_latency (GstElement * element)
+gst_bin_do_latency_func (GstBin * bin)
 {
   GstQuery *query;
+  GstElement *element;
   GstClockTime min_latency, max_latency;
   gboolean res;
 
+  g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
+
+  element = GST_ELEMENT_CAST (bin);
+
   GST_DEBUG_OBJECT (element, "querying latency");
 
   query = gst_query_new_latency ();
@@ -2136,7 +2284,7 @@
   GstState current, next;
   gboolean have_async;
   gboolean have_no_preroll;
-  GstClockTime base_time;
+  GstClockTime base_time, start_time;
   GstIterator *it;
   gboolean done;
 
@@ -2160,7 +2308,7 @@
       GST_OBJECT_UNLOCK (bin);
 
       if (toplevel)
-        do_bin_latency (element);
+        gst_bin_recalculate_latency (bin);
       break;
     }
     case GST_STATE_PAUSED:
@@ -2210,6 +2358,7 @@
 restart:
   /* take base_time */
   base_time = gst_element_get_base_time (element);
+  start_time = gst_element_get_start_time (element);
 
   have_no_preroll = FALSE;
 
@@ -2225,7 +2374,9 @@
         child = GST_ELEMENT_CAST (data);
 
         /* set state and base_time now */
-        ret = gst_bin_element_set_state (bin, child, base_time, current, next);
+        ret =
+            gst_bin_element_set_state (bin, child, base_time, start_time,
+            current, next);
 
         switch (ret) {
           case GST_STATE_CHANGE_SUCCESS:
@@ -2280,8 +2431,13 @@
     goto done;
 
   if (have_no_preroll) {
+    GST_CAT_DEBUG (GST_CAT_STATES,
+        "we have NO_PREROLL elements %s -> NO_PREROLL",
+        gst_element_state_change_return_get_name (ret));
     ret = GST_STATE_CHANGE_NO_PREROLL;
   } else if (have_async) {
+    GST_CAT_DEBUG (GST_CAT_STATES, "we have ASYNC elements %s -> ASYNC",
+        gst_element_state_change_return_get_name (ret));
     ret = GST_STATE_CHANGE_ASYNC;
   }
 
@@ -2290,8 +2446,13 @@
 
   GST_OBJECT_LOCK (bin);
   bin->polling = FALSE;
-  if (ret != GST_STATE_CHANGE_ASYNC) {
-    /* no element returned ASYNC, we can just complete. */
+  /* it's possible that we did not get ASYNC from the children while the bin is
+   * simulating ASYNC behaviour by posting an ASYNC_DONE message on the bus with
+   * itself as the source. In that case we still want to check if the state
+   * change completed. */
+  if (ret != GST_STATE_CHANGE_ASYNC && !bin->priv->pending_async_done) {
+    /* no element returned ASYNC and there are no pending async_done messages,
+     * we can just complete. */
     GST_DEBUG_OBJECT (bin, "no async elements");
     goto state_end;
   }
@@ -2313,10 +2474,11 @@
     bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
 
     GST_DEBUG_OBJECT (bin, "async elements commited");
-    bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS);
+    bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE);
   }
 
 state_end:
+  bin->priv->pending_async_done = FALSE;
   GST_OBJECT_UNLOCK (bin);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
@@ -2405,7 +2567,6 @@
   GstBin *bin;
   GstState current, next, pending;
   GstStateChange transition;
-  GstStateChangeReturn ret;
 
   bin = data->bin;
   pending = data->pending;
@@ -2426,6 +2587,7 @@
   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
 
   GST_STATE_NEXT (bin) = next;
+  GST_STATE_PENDING (bin) = pending;
   /* mark busy */
   GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
   GST_OBJECT_UNLOCK (bin);
@@ -2435,7 +2597,7 @@
       gst_element_state_get_name (current),
       gst_element_state_get_name (next), gst_element_state_get_name (pending));
 
-  ret = gst_element_change_state (GST_ELEMENT_CAST (bin), transition);
+  gst_element_change_state (GST_ELEMENT_CAST (bin), transition);
 
   GST_STATE_UNLOCK (bin);
   GST_DEBUG_OBJECT (bin, "state continue done");
@@ -2513,7 +2675,6 @@
   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_NO_PREROLL)
     goto was_no_preroll;
 
-
   old_state = GST_STATE (bin);
 
   /* when we PLAYING we go back to PAUSED, when preroll happens, we go back to
@@ -2572,7 +2733,8 @@
  * This function is called with the OBJECT lock.
  */
 static void
-bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret)
+bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
+    gboolean flag_pending)
 {
   GstState current, pending, target;
   GstStateChangeReturn old_ret;
@@ -2616,6 +2778,11 @@
     /* update current state */
     current = GST_STATE (bin) = old_next;
   } else {
+    GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
+        "setting state from %s to %s, pending %s",
+        gst_element_state_get_name (old_state),
+        gst_element_state_get_name (old_state),
+        gst_element_state_get_name (pending));
     current = old_state;
   }
 
@@ -2647,7 +2814,7 @@
     cont->pending = pending;
     /* mark busy */
     GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
-    GST_STATE_NEXT (bin) = pending;
+    GST_STATE_NEXT (bin) = GST_STATE_GET_NEXT (old_state, pending);
   }
 
   if (old_next != GST_STATE_PLAYING) {
@@ -2687,6 +2854,10 @@
 was_busy:
   {
     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy");
+    /* if we were busy with a state change and we are requested to flag a
+     * pending async done, we do so here */
+    if (flag_pending)
+      bin->priv->pending_async_done = TRUE;
     return;
   }
 nothing_pending:
@@ -2755,18 +2926,16 @@
 {
   GstObject *src;
   GstMessageType type;
+  GstMessage *tmessage;
+  guint32 seqnum;
 
   src = GST_MESSAGE_SRC (message);
   type = GST_MESSAGE_TYPE (message);
 
-// Message src can be NULL
-  if(src)
   GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s",
-      message, GST_ELEMENT_NAME (src), GST_MESSAGE_TYPE_NAME (message));
-  else
-  GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s",
-            message, "Null ", GST_MESSAGE_TYPE_NAME (message));
-  
+      message, src ? GST_ELEMENT_NAME (src) : "(NULL)",
+      GST_MESSAGE_TYPE_NAME (message));
+
   switch (type) {
     case GST_MESSAGE_EOS:
     {
@@ -2780,9 +2949,13 @@
 
       /* if we are completely EOS, we forward an EOS message */
       if (eos) {
-        GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
-        gst_element_post_message (GST_ELEMENT_CAST (bin),
-            gst_message_new_eos (GST_OBJECT_CAST (bin)));
+        seqnum = gst_message_get_seqnum (message);
+        tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
+        gst_message_set_seqnum (tmessage, seqnum);
+
+        GST_DEBUG_OBJECT (bin,
+            "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
+        gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
       }
       break;
     }
@@ -2794,13 +2967,37 @@
       gst_message_unref (message);
       break;
     }
-    case GST_MESSAGE_SEGMENT_START:
+    case GST_MESSAGE_SEGMENT_START:{
+      gboolean post = FALSE;
+      GstFormat format;
+      gint64 position;
+
+      gst_message_parse_segment_start (message, &format, &position);
+      seqnum = gst_message_get_seqnum (message);
+
       GST_OBJECT_LOCK (bin);
+      /* if this is the first segment-start, post to parent but not to the
+       * application */
+      if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) &&
+          (GST_OBJECT_PARENT (bin) != NULL)) {
+        post = TRUE;
+      }
       /* replace any previous segment_start message from this source
        * with the new segment start message */
       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
       GST_OBJECT_UNLOCK (bin);
+      if (post) {
+        tmessage = gst_message_new_segment_start (GST_OBJECT_CAST (bin),
+            format, position);
+        gst_message_set_seqnum (tmessage, seqnum);
+
+        /* post segment start with initial format and position. */
+        GST_DEBUG_OBJECT (bin, "posting SEGMENT_START (%u) bus message: %p",
+            seqnum, message);
+        gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
+      }
       break;
+    }
     case GST_MESSAGE_SEGMENT_DONE:
     {
       gboolean post = FALSE;
@@ -2808,6 +3005,7 @@
       gint64 position;
 
       gst_message_parse_segment_done (message, &format, &position);
+      seqnum = gst_message_get_seqnum (message);
 
       GST_OBJECT_LOCK (bin);
       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
@@ -2823,10 +3021,14 @@
       }
       GST_OBJECT_UNLOCK (bin);
       if (post) {
+        tmessage = gst_message_new_segment_done (GST_OBJECT_CAST (bin),
+            format, position);
+        gst_message_set_seqnum (tmessage, seqnum);
+
         /* post segment done with latest format and position. */
-        gst_element_post_message (GST_ELEMENT_CAST (bin),
-            gst_message_new_segment_done (GST_OBJECT_CAST (bin),
-                format, position));
+        GST_DEBUG_OBJECT (bin, "posting SEGMENT_DONE (%u) bus message: %p",
+            seqnum, message);
+        gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
       }
       break;
     }
@@ -2897,12 +3099,9 @@
     {
       gboolean new_base_time;
       GstState target;
-	if(src)
+
       GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
-          GST_OBJECT_NAME (src));
-	else
-	GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
-          "Null Source");
+          src ? GST_OBJECT_NAME (src) : "(NULL)");
 
       gst_message_parse_async_start (message, &new_base_time);
 
@@ -2931,13 +3130,9 @@
     case GST_MESSAGE_ASYNC_DONE:
     {
       GstState target;
-	  
-	  if(src)
+
       GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
-          GST_OBJECT_NAME (src));
-	  else
-	  GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
-          "Null Source");
+          src ? GST_OBJECT_NAME (src) : "(NULL)");
 
       GST_OBJECT_LOCK (bin);
       target = GST_STATE_TARGET (bin);
@@ -2954,7 +3149,13 @@
         bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
 
         GST_DEBUG_OBJECT (bin, "async elements commited");
-        bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS);
+        /* when we get an async done message when a state change was busy, we
+         * need to set the pending_done flag so that at the end of the state
+         * change we can see if we need to verify pending async elements, hence
+         * the TRUE argument here. */
+        bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE);
+      } else {
+        GST_DEBUG_OBJECT (bin, "there are more async elements pending");
       }
       GST_OBJECT_UNLOCK (bin);
       break;
@@ -2968,6 +3169,34 @@
         break;
       }
     }
+    case GST_MESSAGE_STRUCTURE_CHANGE:
+    {
+      gboolean busy;
+
+      gst_message_parse_structure_change (message, NULL, NULL, &busy);
+
+      GST_OBJECT_LOCK (bin);
+      if (busy) {
+        /* while the pad is busy, avoid following it when doing state changes.
+         * Don't update the cookie yet, we will do that after the structure
+         * change finished and we are ready to inspect the new updated
+         * structure. */
+        bin_replace_message (bin, message, GST_MESSAGE_STRUCTURE_CHANGE);
+        message = NULL;
+      } else {
+        /* a pad link/unlink ended, signal the state change iterator that we
+         * need to resync by updating the structure_cookie. */
+        bin_remove_messages (bin, GST_MESSAGE_SRC (message),
+            GST_MESSAGE_STRUCTURE_CHANGE);
+        bin->priv->structure_cookie++;
+      }
+      GST_OBJECT_UNLOCK (bin);
+
+      if (message)
+        gst_message_unref (message);
+
+      break;
+    }
     default:
       goto forward;
   }
@@ -3023,6 +3252,7 @@
   gst_object_unref (item);
   return TRUE;
 }
+
 static void
 bin_query_duration_done (GstBin * bin, QueryFold * fold)
 {
@@ -3062,6 +3292,7 @@
   gst_object_unref (item);
   return TRUE;
 }
+
 static void
 bin_query_position_done (GstBin * bin, QueryFold * fold)
 {
@@ -3089,14 +3320,16 @@
 
     /* for the combined latency we collect the MAX of all min latencies and
      * the MIN of all max latencies */
-    if (min > fold->min)
-      fold->min = min;
-    if (fold->max == -1)
-      fold->max = max;
-    else if (max < fold->max)
-      fold->max = max;
-    if (fold->live == FALSE)
-      fold->live = live;
+    if (live) {
+      if (min > fold->min)
+        fold->min = min;
+      if (fold->max == -1)
+        fold->max = max;
+      else if (max < fold->max)
+        fold->max = max;
+      if (fold->live == FALSE)
+        fold->live = live;
+    }
   } else {
     g_value_set_boolean (ret, FALSE);
     GST_DEBUG_OBJECT (item, "failed query");
@@ -3210,6 +3443,7 @@
 
   fold_data.query = query;
 
+  /* set the result of the query to FALSE initially */
   g_value_init (&ret, G_TYPE_BOOLEAN);
   g_value_set_boolean (&ret, res);
 
@@ -3458,12 +3692,12 @@
   GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
       GST_ELEMENT_NAME (bin), bin->numchildren);
 
-  children = bin->children;
+  children = g_list_last (bin->children);
   while (children) {
     child = GST_ELEMENT (children->data);
     elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
     gst_object_save_thyself (GST_OBJECT (child), elementnode);
-    children = g_list_next (children);
+    children = g_list_previous (children);
   }
   return childlist;
 }
--- a/gstreamer_core/gst/gstbin.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstbin.h	Fri Apr 16 15:15:52 2010 +0300
@@ -130,8 +130,9 @@
  * Subclasses can override the @add_element and @remove_element to
  * update the list of children in the bin.
  *
- * The @handle_message method can be overriden to implement custom
- * message handling.
+ * The @handle_message method can be overridden to implement custom
+ * message handling.  @handle_message takes ownership of the message, just like
+ * #gst_element_post_message.
  */
 struct _GstBinClass {
   GstElementClass parent_class;
@@ -151,7 +152,11 @@
   void		(*handle_message)	(GstBin *bin, GstMessage *message);
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  /* signal added 0.10.22 */
+  gboolean	(*do_latency)           (GstBin *bin);
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING-1];
 };
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -227,6 +232,14 @@
 
 GstIterator*	gst_bin_iterate_all_by_interface (GstBin *bin, GType iface);
 
+/* latency */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean        gst_bin_recalculate_latency      (GstBin * bin);
+
+
 G_END_DECLS
 
 
--- a/gstreamer_core/gst/gstbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -120,16 +120,12 @@
 #include "gstutils.h"
 #include "gstminiobject.h"
 
-static void gst_buffer_init (GTypeInstance * instance, gpointer g_class);
-static void gst_buffer_class_init (gpointer g_class, gpointer class_data);
 static void gst_buffer_finalize (GstBuffer * buffer);
 static GstBuffer *_gst_buffer_copy (GstBuffer * buffer);
 static GType gst_subbuffer_get_type (void);
 
 static GType _gst_subbuffer_type = 0;
 static GType _gst_buffer_type = 0;
-
-static GstMiniObjectClass *parent_class = NULL;
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -144,46 +140,20 @@
   g_type_class_ref (gst_buffer_get_type ());
   g_type_class_ref (gst_subbuffer_get_type ());
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_buffer_get_type (void)
-{
-  if (G_UNLIKELY (_gst_buffer_type == 0)) {
-    static const GTypeInfo buffer_info = {
-      sizeof (GstBufferClass),
-      NULL,
-      NULL,
-      gst_buffer_class_init,
-      NULL,
-      NULL,
-      sizeof (GstBuffer),
-      0,
-      gst_buffer_init,
-      NULL
-    };
-
-    _gst_buffer_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
-        "GstBuffer", &buffer_info, 0);
-  }
-  return _gst_buffer_type;
+#define _do_init \
+{ \
+  _gst_buffer_type = g_define_type_id; \
 }
 
-static void
-gst_buffer_class_init (gpointer g_class, gpointer class_data)
-{
-  GstBufferClass *buffer_class = GST_BUFFER_CLASS (g_class);
+G_DEFINE_TYPE_WITH_CODE (GstBuffer, gst_buffer, GST_TYPE_MINI_OBJECT, _do_init);
 
-  parent_class = g_type_class_peek_parent (g_class);
-
-  buffer_class->mini_object_class.copy =
-      (GstMiniObjectCopyFunction) _gst_buffer_copy;
-  buffer_class->mini_object_class.finalize =
+static void
+gst_buffer_class_init (GstBufferClass * klass)
+{
+  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_buffer_copy;
+  klass->mini_object_class.finalize =
       (GstMiniObjectFinalizeFunction) gst_buffer_finalize;
-
 }
 
 static void
@@ -194,11 +164,13 @@
   GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
 
   /* free our data */
-  g_free (buffer->malloc_data);
+  if (G_LIKELY (buffer->malloc_data))
+    buffer->free_func (buffer->malloc_data);
 
   gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
 
-  GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (buffer));
+/*   ((GstMiniObjectClass *) */
+/*       gst_buffer_parent_class)->finalize (GST_MINI_OBJECT_CAST (buffer)); */
 }
 
 /**
@@ -229,6 +201,10 @@
   g_return_if_fail (dest != NULL);
   g_return_if_fail (src != NULL);
 
+  /* nothing to copy if the buffers are the same */
+  if (G_UNLIKELY (dest == src))
+    return;
+
   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p", src, dest);
 
   if (flags & GST_BUFFER_COPY_FLAGS) {
@@ -237,7 +213,8 @@
     /* copy relevant flags */
     mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
         GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
-        GST_BUFFER_FLAG_GAP;
+        GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
+        GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
     GST_MINI_OBJECT_FLAGS (dest) |= GST_MINI_OBJECT_FLAGS (src) & mask;
   }
 
@@ -249,10 +226,7 @@
   }
 
   if (flags & GST_BUFFER_COPY_CAPS) {
-    if (GST_BUFFER_CAPS (src))
-      GST_BUFFER_CAPS (dest) = gst_caps_ref (GST_BUFFER_CAPS (src));
-    else
-      GST_BUFFER_CAPS (dest) = NULL;
+    gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src));
   }
 }
 
@@ -279,18 +253,15 @@
 }
 
 static void
-gst_buffer_init (GTypeInstance * instance, gpointer g_class)
+gst_buffer_init (GstBuffer * buffer)
 {
-  GstBuffer *buffer;
-
-  buffer = (GstBuffer *) instance;
-
   GST_CAT_LOG (GST_CAT_BUFFER, "init %p", buffer);
 
   GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
+  GST_BUFFER_FREE_FUNC (buffer) = g_free;
 }
 
 /**
@@ -528,43 +499,20 @@
   GstBufferClass buffer_class;
 };
 
-static GstBufferClass *sub_parent_class;
-
-static void gst_subbuffer_init (GTypeInstance * instance, gpointer g_class);
-static void gst_subbuffer_class_init (gpointer g_class, gpointer class_data);
 static void gst_subbuffer_finalize (GstSubBuffer * buffer);
 
-static GType
-gst_subbuffer_get_type (void)
-{
-  if (G_UNLIKELY (_gst_subbuffer_type == 0)) {
-    static const GTypeInfo subbuffer_info = {
-      sizeof (GstSubBufferClass),
-      NULL,
-      NULL,
-      gst_subbuffer_class_init,
-      NULL,
-      NULL,
-      sizeof (GstSubBuffer),
-      0,
-      gst_subbuffer_init,
-      NULL
-    };
-
-    _gst_subbuffer_type = g_type_register_static (GST_TYPE_BUFFER,
-        "GstSubBuffer", &subbuffer_info, 0);
-  }
-  return _gst_subbuffer_type;
+#define _do_init_sub \
+{ \
+  _gst_subbuffer_type = g_define_type_id; \
 }
 
+G_DEFINE_TYPE_WITH_CODE (GstSubBuffer, gst_subbuffer, GST_TYPE_BUFFER,
+    _do_init_sub);
+
 static void
-gst_subbuffer_class_init (gpointer g_class, gpointer class_data)
+gst_subbuffer_class_init (GstSubBufferClass * klass)
 {
-  GstBufferClass *buffer_class = GST_BUFFER_CLASS (g_class);
-
-  sub_parent_class = g_type_class_peek_parent (g_class);
-
-  buffer_class->mini_object_class.finalize =
+  klass->buffer_class.mini_object_class.finalize =
       (GstMiniObjectFinalizeFunction) gst_subbuffer_finalize;
 }
 
@@ -573,12 +521,12 @@
 {
   gst_buffer_unref (buffer->parent);
 
-  GST_MINI_OBJECT_CLASS (sub_parent_class)->
-      finalize (GST_MINI_OBJECT_CAST (buffer));
+  ((GstMiniObjectClass *) gst_subbuffer_parent_class)->finalize
+      (GST_MINI_OBJECT_CAST (buffer));
 }
 
 static void
-gst_subbuffer_init (GTypeInstance * instance, gpointer g_class)
+gst_subbuffer_init (GstSubBuffer * instance)
 {
   GST_BUFFER_FLAG_SET (GST_BUFFER_CAST (instance), GST_BUFFER_FLAG_READONLY);
 }
--- a/gstreamer_core/gst/gstbuffer.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstbuffer.h	Fri Apr 16 15:15:52 2010 +0300
@@ -141,6 +141,19 @@
  * (i.e. when its refcount becomes zero).
  */
 #define GST_BUFFER_MALLOCDATA(buf)		(GST_BUFFER_CAST(buf)->malloc_data)
+/**
+ * GST_BUFFER_FREE_FUNC:
+ * @buf: a #GstBuffer.
+ *
+ * A pointer to a function that will be called on the buffer's malloc_data when
+ * this buffer is finalized. Defaults to g_free().
+ *
+ * Note that the free function only affects the buffer's malloc_data; if the
+ * buffer's malloc_data is %NULL, the function will not be called.
+ *
+ * Since: 0.10.22
+ */
+#define GST_BUFFER_FREE_FUNC(buf)		(GST_BUFFER_CAST(buf)->free_func)
 
 /**
  * GST_BUFFER_OFFSET_NONE:
@@ -201,6 +214,12 @@
  * stream and contains media neutral data (elements can switch to optimized code
  * path that ignores the buffer content).
  * @GST_BUFFER_FLAG_DELTA_UNIT: this unit cannot be decoded independently.
+ * @GST_BUFFER_FLAG_MEDIA1: a flag whose use is specific to the caps of the buffer.
+ * Since: 0.10.23
+ * @GST_BUFFER_FLAG_MEDIA2: a flag whose use is specific to the caps of the buffer.
+ * Since: 0.10.23
+ * @GST_BUFFER_FLAG_MEDIA3: a flag whose use is specific to the caps of the buffer.
+ * Since: 0.10.23
  * @GST_BUFFER_FLAG_LAST: additional flags can be added starting from this flag.
  *
  * A set of buffer flags used to describe properties of a #GstBuffer.
@@ -212,7 +231,9 @@
   GST_BUFFER_FLAG_IN_CAPS    = (GST_MINI_OBJECT_FLAG_LAST << 2),
   GST_BUFFER_FLAG_GAP        = (GST_MINI_OBJECT_FLAG_LAST << 3),
   GST_BUFFER_FLAG_DELTA_UNIT = (GST_MINI_OBJECT_FLAG_LAST << 4),
-  /* padding */
+  GST_BUFFER_FLAG_MEDIA1     = (GST_MINI_OBJECT_FLAG_LAST << 5),
+  GST_BUFFER_FLAG_MEDIA2     = (GST_MINI_OBJECT_FLAG_LAST << 6),
+  GST_BUFFER_FLAG_MEDIA3     = (GST_MINI_OBJECT_FLAG_LAST << 7),
   GST_BUFFER_FLAG_LAST       = (GST_MINI_OBJECT_FLAG_LAST << 8)
 } GstBufferFlag;
 
@@ -234,7 +255,9 @@
  * @offset_end: the last offset contained in this buffer. It has the same 
  *     format as @offset.
  * @malloc_data: a pointer to the allocated memory associated with this buffer.
- *     When the buffer is freed, this data will freed with g_free().
+ *     When the buffer is freed, this data will freed with @free_func.
+ * @free_func: a custom function that will be called with @malloc_data, defaults
+ *     to g_free(). Since 0.10.22.
  *
  * The structure of a #GstBuffer. Use the associated macros to access the public
  * variables.
@@ -260,8 +283,10 @@
 
   guint8                *malloc_data;
 
+  GFreeFunc              free_func;
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING - 1];
 };
 
 struct _GstBufferClass {
@@ -333,8 +358,6 @@
 static inline GstBuffer *
 gst_buffer_ref (GstBuffer * buf)
 {
-  /* not using a macro here because gcc-4.1 will complain
-   * if the return value isn't used (because of the cast) */
   return (GstBuffer *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (buf));
 }
 
@@ -346,7 +369,15 @@
  * will be freed. If GST_BUFFER_MALLOCDATA() is non-NULL, this pointer will
  * also be freed at this time.
  */
-#define		gst_buffer_unref(buf)		gst_mini_object_unref (GST_MINI_OBJECT_CAST (buf))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_buffer_unref (GstBuffer * buf);
+#endif
+
+static inline void
+gst_buffer_unref (GstBuffer * buf)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (buf));
+}
 
 /* copy buffer */
 /**
@@ -355,8 +386,19 @@
  *
  * Create a copy of the given buffer. This will also make a newly allocated
  * copy of the data the source buffer contains.
+ *
+ * Returns: a new copy of @buf.
  */
-#define		gst_buffer_copy(buf)		GST_BUFFER_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (buf)))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstBuffer * gst_buffer_copy (const GstBuffer * buf);
+#endif
+
+static inline GstBuffer *
+gst_buffer_copy (const GstBuffer * buf)
+{
+  return GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CAST (buf)));
+}
+
 
 /**
  * GstBufferCopyFlags:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/gst/gstbufferlist.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,887 @@
+/* GStreamer
+ * Copyright (C) 2009 Axis Communications <dev-gstreamer at axis dot com>
+ * @author Jonas Holmberg <jonas dot holmberg at axis dot com>
+ *
+ * gstbufferlist.c: Buffer list
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:gstbufferlist
+ * @short_description: Grouped scatter data buffer type for data-passing
+ * @see_also: #GstPad, #GstMiniObject
+ *
+ * Buffer lists are units of grouped scatter/gather data transfer in
+ * GStreamer.
+ *
+ * Buffer lists are created with gst_buffer_list_new() and filled with data
+ * using a #GstBufferListIterator. The iterator has no current buffer; its
+ * cursor position lies between buffers, immediately before the buffer that
+ * would be returned by gst_buffer_list_iterator_next(). After iterating to the
+ * end of a group the iterator must be advanced to the next group by a call to
+ * gst_buffer_list_iterator_next_group() before any further calls to
+ * gst_buffer_list_iterator_next() can return buffers again. The cursor position
+ * of a newly created iterator lies before the first group; a call to
+ * gst_buffer_list_iterator_next_group() is necessary before calls to
+ * gst_buffer_list_iterator_next() can return buffers.
+ *
+ * <informalexample>
+ *   <programlisting>
+ *      +--- group0 ----------------------+--- group1 ------------+
+ *      |   buffer0   buffer1   buffer2   |   buffer3   buffer4   |
+ *    ^   ^         ^         ^         ^   ^         ^         ^
+ *    Iterator positions
+ *   </programlisting>
+ * </informalexample>
+ *
+ * The gst_buffer_list_iterator_remove(), gst_buffer_list_iterator_steal(),
+ * gst_buffer_list_iterator_take(), gst_buffer_list_iterator_do() and
+ * gst_buffer_list_iterator_do_data() functions are not defined in terms of the
+ * cursor position; they operate on the last element returned from
+ * gst_buffer_list_iterator_next().
+ *
+ * The basic use pattern of creating a buffer list with an iterator is as
+ * follows:
+ *
+ * <example>
+ * <title>Creating a buffer list</title>
+ *   <programlisting>
+ *    GstBufferList *list;
+ *    GstBufferListIterator *it;
+ *
+ *    list = gst_buffer_list_new ();
+ *    it = gst_buffer_list_iterate (list);
+ *    gst_buffer_list_iterator_add_group (it);
+ *    gst_buffer_list_iterator_add (it, header1);
+ *    gst_buffer_list_iterator_add (it, data1);
+ *    gst_buffer_list_iterator_add_group (it);
+ *    gst_buffer_list_iterator_add (it, header2);
+ *    gst_buffer_list_iterator_add (it, data2);
+ *    gst_buffer_list_iterator_add_group (it);
+ *    gst_buffer_list_iterator_add (it, header3);
+ *    gst_buffer_list_iterator_add (it, data3);
+ *    ...
+ *    gst_buffer_list_iterator_free (it);
+ *   </programlisting>
+ * </example>
+ *
+ * The basic use pattern of iterating over a buffer list is as follows:
+ *
+ * <example>
+ * <title>Iterating a buffer list</title>
+ *   <programlisting>
+ *    GstBufferListIterator *it;
+ *
+ *    it = gst_buffer_list_iterate (list);
+ *    while (gst_buffer_list_iterator_next_group (it)) {
+ *      while ((buffer = gst_buffer_list_iterator_next (it)) != NULL) {
+ *        do_something_with_buffer (buffer);
+ *      }
+ *    }
+ *    gst_buffer_list_iterator_free (it);
+ *   </programlisting>
+ * </example>
+ *
+ * The basic use pattern of modifying a buffer in a list is as follows:
+ *
+ * <example>
+ * <title>Modifying the data of the first buffer in a list</title>
+ *   <programlisting>
+ *    GstBufferListIterator *it;
+ *
+ *    list = gst_buffer_list_make_writable (list);
+ *    it = gst_buffer_list_iterate (list);
+ *    if (gst_buffer_list_iterator_next_group (it)) {
+ *      GstBuffer *buf
+ *
+ *      buf = gst_buffer_list_iterator_next (it);
+ *      if (buf != NULL) {
+ *        buf = gst_buffer_list_iterator_do (it,
+ *            (GstBufferListDoFunction) gst_mini_object_make_writable, NULL);
+ *        modify_data (GST_BUFFER_DATA (buf));
+ *      }
+ *    }
+ *    gst_buffer_list_iterator_free (it);
+ *   </programlisting>
+ * </example>
+ *
+ * Since: 0.10.24
+ */
+#include "gst_private.h"
+
+#include "gstbuffer.h"
+#include "gstbufferlist.h"
+#ifdef __SYMBIAN32__
+#include <glib_global.h>
+#endif
+
+#define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST
+
+#define GROUP_START NULL
+static const gpointer STOLEN = "";
+
+/**
+ * GstBufferList:
+ * @mini_object: the parent structure
+ *
+ * Opaque list of grouped buffers.
+ */
+struct _GstBufferList
+{
+  GstMiniObject mini_object;
+
+  GList *buffers;
+};
+
+struct _GstBufferListClass
+{
+  GstMiniObjectClass mini_object_class;
+};
+
+/**
+ * GstBufferListIterator:
+ *
+ * Opaque iterator for a #GstBufferList.
+ */
+struct _GstBufferListIterator
+{
+  GstBufferList *list;
+  GList *next;
+  GList *last_returned;
+};
+
+static GType _gst_buffer_list_type = 0;
+static GstMiniObjectClass *parent_class = NULL;
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+_gst_buffer_list_initialize (void)
+{
+  g_type_class_ref (gst_buffer_list_get_type ());
+}
+
+static void
+gst_buffer_list_init (GTypeInstance * instance, gpointer g_class)
+{
+  GstBufferList *list;
+
+  list = (GstBufferList *) instance;
+  list->buffers = NULL;
+
+  GST_LOG ("init %p", list);
+}
+
+static void
+gst_buffer_list_finalize (GstBufferList * list)
+{
+  GList *tmp;
+
+  g_return_if_fail (list != NULL);
+
+  GST_LOG ("finalize %p", list);
+
+  tmp = list->buffers;
+  while (tmp) {
+    if (tmp->data != GROUP_START && tmp->data != STOLEN) {
+      gst_buffer_unref (GST_BUFFER_CAST (tmp->data));
+    }
+    tmp = tmp->next;
+  }
+  g_list_free (list->buffers);
+
+  parent_class->finalize (GST_MINI_OBJECT_CAST (list));
+}
+
+static GstBufferList *
+_gst_buffer_list_copy (GstBufferList * list)
+{
+  GstBufferList *list_copy;
+  GList *tmp;
+
+  g_return_val_if_fail (list != NULL, NULL);
+
+  list_copy = gst_buffer_list_new ();
+
+  /* shallow copy of list and pointers */
+  list_copy->buffers = g_list_copy (list->buffers);
+
+  /* ref all buffers in the list */
+  tmp = list_copy->buffers;
+  while (tmp) {
+    if (tmp->data != GROUP_START && tmp->data != STOLEN) {
+      tmp->data = gst_buffer_ref (GST_BUFFER_CAST (tmp->data));
+    }
+    tmp = g_list_next (tmp);
+  }
+
+  return list_copy;
+}
+
+static void
+gst_buffer_list_class_init (gpointer g_class, gpointer class_data)
+{
+  GstBufferListClass *list_class = GST_BUFFER_LIST_CLASS (g_class);
+
+  parent_class = g_type_class_peek_parent (g_class);
+
+  list_class->mini_object_class.copy =
+      (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
+  list_class->mini_object_class.finalize =
+      (GstMiniObjectFinalizeFunction) gst_buffer_list_finalize;
+}
+
+/**
+ * gst_buffer_list_new:
+ *
+ * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
+ * the returned #GstBufferList.
+ *
+ * Returns: the new #GstBufferList. gst_buffer_list_unref() after usage.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBufferList *
+gst_buffer_list_new (void)
+{
+  GstBufferList *list;
+
+  list = (GstBufferList *) gst_mini_object_new (_gst_buffer_list_type);
+
+  GST_LOG ("new %p", list);
+
+  return list;
+}
+
+/**
+ * gst_buffer_list_n_groups:
+ * @list: a #GstBufferList
+ *
+ * Returns the number of groups in @list.
+ *
+ * Returns: the number of groups in the buffer list
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_buffer_list_n_groups (GstBufferList * list)
+{
+  GList *tmp;
+  guint n;
+
+  g_return_val_if_fail (list != NULL, 0);
+
+  tmp = list->buffers;
+  n = 0;
+  while (tmp) {
+    if (tmp->data == GROUP_START) {
+      n++;
+    }
+    tmp = g_list_next (tmp);
+  }
+
+  return n;
+}
+
+/**
+ * gst_buffer_list_foreach:
+ * @list: a #GstBufferList
+ * @func: a #GstBufferListFunc to call
+ * @user_data: user data passed to @func
+ *
+ * Call @func with @data for each buffer in @list.
+ *
+ * @func can modify the passed buffer pointer or its contents. The return value
+ * of @func define if this function returns or if the remaining buffers in a
+ * group should be skipped.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
+    gpointer user_data)
+{
+  GList *tmp, *next;
+  guint group, idx;
+  GstBufferListItem res;
+
+  g_return_if_fail (list != NULL);
+  g_return_if_fail (func != NULL);
+
+  next = list->buffers;
+  group = idx = 0;
+  while (next) {
+    GstBuffer *buffer;
+
+    tmp = next;
+    next = g_list_next (tmp);
+
+    buffer = tmp->data;
+
+    if (buffer == GROUP_START) {
+      group++;
+      idx = 0;
+      continue;
+    } else if (buffer == STOLEN)
+      continue;
+    else
+      idx++;
+
+    /* need to decrement the indices */
+    res = func (&buffer, group - 1, idx - 1, user_data);
+
+    if (G_UNLIKELY (buffer != tmp->data)) {
+      /* the function changed the buffer */
+      if (buffer == NULL) {
+        /* we were asked to remove the item */
+        list->buffers = g_list_delete_link (list->buffers, tmp);
+        idx--;
+      } else {
+        /* change the buffer */
+        tmp->data = buffer;
+      }
+    }
+
+    switch (res) {
+      case GST_BUFFER_LIST_CONTINUE:
+        break;
+      case GST_BUFFER_LIST_SKIP_GROUP:
+        while (next && next->data != GROUP_START)
+          next = g_list_next (next);
+        break;
+      case GST_BUFFER_LIST_END:
+        return;
+    }
+  }
+}
+
+/**
+ * gst_buffer_list_get:
+ * @list: a #GstBufferList
+ * @group: the group
+ * @idx: the index in @group
+ *
+ * Get the buffer at @idx in @group.
+ *
+ * Note that this function is not efficient for iterating over the entire list.
+ * Use an iterator or gst_buffer_list_foreach() instead.
+ *
+ * Returns: the buffer at @idx in @group or NULL when there is no buffer. The
+ * buffer remains valid as long as @list is valid.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBuffer *
+gst_buffer_list_get (GstBufferList * list, guint group, guint idx)
+{
+  GList *tmp;
+  guint cgroup, cidx;
+
+  g_return_val_if_fail (list != NULL, NULL);
+
+  tmp = list->buffers;
+  cgroup = 0;
+  while (tmp) {
+    if (tmp->data == GROUP_START) {
+      if (cgroup == group) {
+        /* we found the group */
+        tmp = g_list_next (tmp);
+        cidx = 0;
+        while (tmp && tmp->data != GROUP_START) {
+          if (tmp->data != STOLEN) {
+            if (cidx == idx)
+              return GST_BUFFER_CAST (tmp->data);
+            else
+              cidx++;
+          }
+          tmp = g_list_next (tmp);
+        }
+        break;
+      } else {
+        cgroup++;
+        if (cgroup > group)
+          break;
+      }
+    }
+    tmp = g_list_next (tmp);
+  }
+  return NULL;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GType
+gst_buffer_list_get_type (void)
+{
+  if (G_UNLIKELY (_gst_buffer_list_type == 0)) {
+    static const GTypeInfo buffer_list_info = {
+      sizeof (GstBufferListClass),
+      NULL,
+      NULL,
+      gst_buffer_list_class_init,
+      NULL,
+      NULL,
+      sizeof (GstBufferList),
+      0,
+      gst_buffer_list_init,
+      NULL
+    };
+
+    _gst_buffer_list_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
+        "GstBufferList", &buffer_list_info, 0);
+  }
+
+  return _gst_buffer_list_type;
+}
+
+/**
+ * gst_buffer_list_iterate:
+ * @list: a #GstBufferList
+ *
+ * Iterate the buffers in @list. The owner of the iterator must also be the
+ * owner of a reference to @list while the returned iterator is in use.
+ *
+ * Returns: a new #GstBufferListIterator of the buffers in @list.
+ * gst_buffer_list_iterator_free() after usage
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBufferListIterator *
+gst_buffer_list_iterate (GstBufferList * list)
+{
+  GstBufferListIterator *it;
+
+  g_return_val_if_fail (list != NULL, NULL);
+
+  it = g_slice_new (GstBufferListIterator);
+  it->list = list;
+  it->next = list->buffers;
+  it->last_returned = NULL;
+
+  return it;
+}
+
+/**
+ * gst_buffer_list_iterator_free:
+ * @it: the #GstBufferListIterator to free
+ *
+ * Free the iterator.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_buffer_list_iterator_free (GstBufferListIterator * it)
+{
+  g_return_if_fail (it != NULL);
+
+  g_slice_free (GstBufferListIterator, it);
+}
+
+/**
+ * gst_buffer_list_iterator_n_buffers:
+ * @it: a #GstBufferListIterator
+ *
+ * Returns the number of buffers left to iterate in the current group. I.e. the
+ * number of calls that can be made to gst_buffer_list_iterator_next() before
+ * it returns NULL.
+ *
+ * This function will not move the implicit cursor or in any other way affect
+ * the state of the iterator @it.
+ *
+ * Returns: the number of buffers left to iterate in the current group
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_buffer_list_iterator_n_buffers (const GstBufferListIterator * it)
+{
+  GList *tmp;
+  guint n;
+
+  g_return_val_if_fail (it != NULL, 0);
+
+  tmp = it->next;
+  n = 0;
+  while (tmp && tmp->data != GROUP_START) {
+    if (tmp->data != STOLEN) {
+      n++;
+    }
+    tmp = g_list_next (tmp);
+  }
+
+  return n;
+}
+
+/**
+ * gst_buffer_list_iterator_add:
+ * @it: a #GstBufferListIterator
+ * @buffer: a #GstBuffer
+ *
+ * Inserts @buffer into the #GstBufferList iterated with @it. The buffer is
+ * inserted into the current group, immediately before the buffer that would be
+ * returned by gst_buffer_list_iterator_next(). The buffer is inserted before
+ * the implicit cursor, a subsequent call to gst_buffer_list_iterator_next()
+ * will return the buffer after the inserted buffer, if any.
+ *
+ * This function takes ownership of @buffer.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_buffer_list_iterator_add (GstBufferListIterator * it, GstBuffer * buffer)
+{
+  g_return_if_fail (it != NULL);
+  g_return_if_fail (buffer != NULL);
+
+  /* adding before the first group start is not allowed */
+  g_return_if_fail (it->next != it->list->buffers);
+
+  /* cheap insert into the GList */
+  it->list->buffers = g_list_insert_before (it->list->buffers, it->next,
+      buffer);
+}
+
+/**
+ * gst_buffer_list_iterator_add_group:
+ * @it: a #GstBufferListIterator
+ *
+ * Inserts a new, empty group into the #GstBufferList iterated with @it. The
+ * group is inserted immediately before the group that would be returned by
+ * gst_buffer_list_iterator_next_group(). A subsequent call to
+ * gst_buffer_list_iterator_next_group() will advance the iterator to the group
+ * after the inserted group, if any.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_buffer_list_iterator_add_group (GstBufferListIterator * it)
+{
+  g_return_if_fail (it != NULL);
+
+  /* advance iterator to next group start */
+  while (it->next != NULL && it->next->data != GROUP_START) {
+    it->next = g_list_next (it->next);
+  }
+
+  /* cheap insert of a group start into the GList */
+  it->list->buffers = g_list_insert_before (it->list->buffers, it->next,
+      GROUP_START);
+}
+
+/**
+ * gst_buffer_list_iterator_next:
+ * @it: a #GstBufferListIterator
+ *
+ * Returns the next buffer in the list iterated with @it. If the iterator is at
+ * the end of a group, NULL will be returned. This function may be called
+ * repeatedly to iterate through the current group.
+ *
+ * The caller will not get a new ref to the returned #GstBuffer and must not
+ * unref it.
+ *
+ * Returns: the next buffer in the current group of the buffer list, or NULL
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBuffer *
+gst_buffer_list_iterator_next (GstBufferListIterator * it)
+{
+  GstBuffer *buffer;
+
+  g_return_val_if_fail (it != NULL, NULL);
+
+  while (it->next != NULL && it->next->data != GROUP_START &&
+      it->next->data == STOLEN) {
+    it->next = g_list_next (it->next);
+  }
+
+  if (it->next == NULL || it->next->data == GROUP_START) {
+    goto no_buffer;
+  }
+
+  buffer = GST_BUFFER_CAST (it->next->data);
+
+  it->last_returned = it->next;
+  it->next = g_list_next (it->next);
+
+  return buffer;
+
+no_buffer:
+  {
+    it->last_returned = NULL;
+    return NULL;
+  }
+}
+
+/**
+ * gst_buffer_list_iterator_next_group:
+ * @it: a #GstBufferListIterator
+ *
+ * Advance the iterator @it to the first buffer in the next group. If the
+ * iterator is at the last group, FALSE will be returned. This function may be
+ * called repeatedly to iterate through the groups in a buffer list.
+ *
+ * Returns: TRUE if the iterator could be advanced to the next group, FALSE if
+ * the iterator was already at the last group
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_buffer_list_iterator_next_group (GstBufferListIterator * it)
+{
+  g_return_val_if_fail (it != NULL, FALSE);
+
+  /* advance iterator to next group start */
+  while (it->next != NULL && it->next->data != GROUP_START) {
+    it->next = g_list_next (it->next);
+  }
+
+  if (it->next) {
+    /* move one step beyond the group start */
+    it->next = g_list_next (it->next);
+  }
+
+  it->last_returned = NULL;
+
+  return (it->next != NULL);
+}
+
+/**
+ * gst_buffer_list_iterator_remove:
+ * @it: a #GstBufferListIterator
+ *
+ * Removes the last buffer returned by gst_buffer_list_iterator_next() from
+ * the #GstBufferList iterated with @it. gst_buffer_list_iterator_next() must
+ * have been called on @it before this function is called. This function can
+ * only be called once per call to gst_buffer_list_iterator_next().
+ *
+ * The removed buffer is unreffed.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_buffer_list_iterator_remove (GstBufferListIterator * it)
+{
+  g_return_if_fail (it != NULL);
+  g_return_if_fail (it->last_returned != NULL);
+  g_assert (it->last_returned->data != GROUP_START);
+
+  if (it->last_returned->data != STOLEN) {
+    gst_buffer_unref (it->last_returned->data);
+  }
+  it->list->buffers = g_list_delete_link (it->list->buffers, it->last_returned);
+  it->last_returned = NULL;
+}
+
+/**
+ * gst_buffer_list_iterator_take:
+ * @it: a #GstBufferListIterator
+ * @buffer: a #GstBuffer
+ *
+ * Replaces the last buffer returned by gst_buffer_list_iterator_next() with
+ * @buffer in the #GstBufferList iterated with @it and takes ownership of
+ * @buffer. gst_buffer_list_iterator_next() must have been called on @it before
+ * this function is called. gst_buffer_list_iterator_remove() must not have been
+ * called since the last call to gst_buffer_list_iterator_next().
+ *
+ * This function unrefs the replaced buffer if it has not been stolen with
+ * gst_buffer_list_iterator_steal() and takes ownership of @buffer (i.e. the
+ * refcount of @buffer is not increased).
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_buffer_list_iterator_take (GstBufferListIterator * it, GstBuffer * buffer)
+{
+  g_return_if_fail (it != NULL);
+  g_return_if_fail (it->last_returned != NULL);
+  g_return_if_fail (buffer != NULL);
+  g_assert (it->last_returned->data != GROUP_START);
+
+  if (it->last_returned->data != STOLEN) {
+    gst_buffer_unref (it->last_returned->data);
+  }
+  it->last_returned->data = buffer;
+}
+
+/**
+ * gst_buffer_list_iterator_steal:
+ * @it: a #GstBufferListIterator
+ *
+ * Returns the last buffer returned by gst_buffer_list_iterator_next() without
+ * modifying the refcount of the buffer.
+ *
+ * Returns: the last buffer returned by gst_buffer_list_iterator_next()
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBuffer *
+gst_buffer_list_iterator_steal (GstBufferListIterator * it)
+{
+  GstBuffer *buffer;
+
+  g_return_val_if_fail (it != NULL, NULL);
+  g_return_val_if_fail (it->last_returned != NULL, NULL);
+  g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
+  g_assert (it->last_returned->data != GROUP_START);
+
+  buffer = it->last_returned->data;
+  it->last_returned->data = STOLEN;
+
+  return buffer;
+}
+
+/**
+ * gst_buffer_list_iterator_do:
+ * @it: a #GstBufferListIterator
+ * @do_func: the function to be called
+ * @user_data: the gpointer to optional user data.
+ *
+ * Calls the given function for the last buffer returned by
+ * gst_buffer_list_iterator_next(). gst_buffer_list_iterator_next() must have
+ * been called on @it before this function is called.
+ * gst_buffer_list_iterator_remove() and gst_buffer_list_iterator_steal() must
+ * not have been called since the last call to gst_buffer_list_iterator_next().
+ *
+ * See #GstBufferListDoFunction for more details.
+ *
+ * Returns: the return value from @do_func
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBuffer *
+gst_buffer_list_iterator_do (GstBufferListIterator * it,
+    GstBufferListDoFunction do_func, gpointer user_data)
+{
+  GstBuffer *buffer;
+
+  g_return_val_if_fail (it != NULL, NULL);
+  g_return_val_if_fail (it->last_returned != NULL, NULL);
+  g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
+  g_return_val_if_fail (do_func != NULL, NULL);
+  g_return_val_if_fail (gst_buffer_list_is_writable (it->list), NULL);
+  g_assert (it->last_returned->data != GROUP_START);
+
+  buffer = gst_buffer_list_iterator_steal (it);
+  buffer = do_func (buffer, user_data);
+  if (buffer == NULL) {
+    gst_buffer_list_iterator_remove (it);
+  } else {
+    gst_buffer_list_iterator_take (it, buffer);
+  }
+
+  return buffer;
+}
+
+/**
+ * gst_buffer_list_iterator_merge_group:
+ * @it: a #GstBufferListIterator
+ *
+ * Merge a buffer list group into a normal #GstBuffer by copying its metadata
+ * and memcpying its data into consecutive memory. All buffers in the current
+ * group after the implicit cursor will be merged into one new buffer. The
+ * metadata of the new buffer will be a copy of the metadata of the buffer that
+ * would be returned by gst_buffer_list_iterator_next(). If there is no buffer
+ * in the current group after the implicit cursor, NULL will be returned.
+ *
+ * This function will not move the implicit cursor or in any other way affect
+ * the state of the iterator @it or the list.
+ *
+ * Returns: a new #GstBuffer, gst_buffer_unref() after usage, or NULL
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBuffer *
+gst_buffer_list_iterator_merge_group (const GstBufferListIterator * it)
+{
+  GList *tmp;
+  guint size;
+  GstBuffer *buf;
+  guint8 *ptr;
+
+  g_return_val_if_fail (it != NULL, NULL);
+
+  /* calculate size of merged buffer */
+  size = 0;
+  tmp = it->next;
+  while (tmp && tmp->data != GROUP_START) {
+    if (tmp->data != STOLEN) {
+      size += GST_BUFFER_SIZE (tmp->data);
+    }
+    tmp = g_list_next (tmp);
+  }
+
+  if (size == 0) {
+    return NULL;
+  }
+
+  /* allocate a new buffer */
+  buf = gst_buffer_new_and_alloc (size);
+
+  /* copy metadata from the next buffer after the implicit cursor */
+  gst_buffer_copy_metadata (buf, GST_BUFFER_CAST (it->next->data),
+      GST_BUFFER_COPY_ALL);
+
+  /* copy data of all buffers before the next group start into the new buffer */
+  ptr = GST_BUFFER_DATA (buf);
+  tmp = it->next;
+  do {
+    if (tmp->data != STOLEN) {
+      memcpy (ptr, GST_BUFFER_DATA (tmp->data), GST_BUFFER_SIZE (tmp->data));
+      ptr += GST_BUFFER_SIZE (tmp->data);
+    }
+    tmp = g_list_next (tmp);
+  } while (tmp && tmp->data != GROUP_START);
+
+  return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/gst/gstbufferlist.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,284 @@
+/* GStreamer
+ * Copyright (C) 2009 Axis Communications <dev-gstreamer at axis dot com>
+ * @author Jonas Holmberg <jonas dot holmberg at axis dot com>
+ *
+ * gstbufferlist.h: Header for GstBufferList 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_LIST_H__
+#define __GST_BUFFER_LIST_H__
+
+#include <gst/gstbuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_BUFFER_LIST (gst_buffer_list_get_type ())
+#define GST_IS_BUFFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_LIST))
+#define GST_IS_BUFFER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_LIST))
+#define GST_BUFFER_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_LIST, GstBufferListClass))
+#define GST_BUFFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_LIST, GstBufferList))
+#define GST_BUFFER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_LIST, GstBufferListClass))
+#define GST_BUFFER_LIST_CAST(obj) ((GstBufferList *)obj)
+
+typedef struct _GstBufferList GstBufferList;
+typedef struct _GstBufferListClass GstBufferListClass;
+typedef struct _GstBufferListIterator GstBufferListIterator;
+
+/**
+ * GstBufferListDoFunction:
+ * @buffer: the #GstBuffer
+ * @user_data: user data
+ *
+ * A function for accessing the last buffer returned by
+ * gst_buffer_list_iterator_next(). The function can leave @buffer in the list,
+ * replace @buffer in the list or remove @buffer from the list, depending on
+ * the return value. If the function returns NULL, @buffer will be removed from
+ * the list, otherwise @buffer will be replaced with the returned buffer.
+ *
+ * The last buffer returned by gst_buffer_list_iterator_next() will be replaced
+ * with the buffer returned from the function. The function takes ownership of
+ * @buffer and if a different value than @buffer is returned, @buffer must be
+ * unreffed. If NULL is returned, the buffer will be removed from the list. The
+ * list must be writable.
+ *
+ * Returns: the buffer to replace @buffer in the list, or NULL to remove @buffer
+ * from the list
+ */
+typedef GstBuffer* (*GstBufferListDoFunction) (GstBuffer * buffer, gpointer user_data);
+
+/**
+ * GstBufferListItem:
+ * @GST_BUFFER_LIST_CONTINUE:   Retrieve next buffer
+ * @GST_BUFFER_LIST_SKIP_GROUP: Skip to next group
+ * @GST_BUFFER_LIST_END:        End iteration
+ *
+ * The result of the #GstBufferListFunc.
+ */
+typedef enum {
+  GST_BUFFER_LIST_CONTINUE,
+  GST_BUFFER_LIST_SKIP_GROUP,
+  GST_BUFFER_LIST_END
+} GstBufferListItem;
+
+/**
+ * GstBufferListFunc:
+ * @buffer: pointer the buffer
+ * @group: the group index of @buffer
+ * @idx: the index in @group of @buffer
+ * @user_data: user data passed to gst_buffer_list_foreach()
+ *
+ * A function that will be called from gst_buffer_list_foreach(). The @buffer
+ * field will point to a the reference of the buffer at @idx in @group.
+ *
+ * When this function returns #GST_BUFFER_LIST_CONTINUE, the next buffer will be
+ * returned. When #GST_BUFFER_LIST_SKIP_GROUP is returned, all remaining buffers
+ * in the current group will be skipped and the first buffer of the next group
+ * is returned (if any). When GST_BUFFER_LIST_END is returned,
+ * gst_buffer_list_foreach() will return.
+ *
+ * When @buffer is set to NULL, the item will be removed from the bufferlist.
+ * When @buffer has been made writable, the new buffer reference can be assigned
+ * to @buffer. This function is responsible for unreffing the old buffer when
+ * removing or modifying.
+ *
+ * Returns: a #GstBufferListItem
+ */
+typedef GstBufferListItem (*GstBufferListFunc)   (GstBuffer **buffer, guint group, guint idx,
+                                                  gpointer user_data);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+
+GType gst_buffer_list_get_type (void);
+
+/* allocation */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBufferList *gst_buffer_list_new (void);
+
+/* refcounting */
+/**
+ * gst_buffer_list_ref:
+ * @list: a #GstBufferList
+ *
+ * Increases the refcount of the given buffer list by one.
+ *
+ * Note that the refcount affects the writeability of @list and its data, see
+ * gst_buffer_list_make_writable(). It is important to note that keeping
+ * additional references to GstBufferList instances can potentially increase
+ * the number of memcpy operations in a pipeline.
+ *
+ * Returns: @list
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstBufferList * gst_buffer_list_ref (GstBufferList * list);
+#endif
+
+static inline GstBufferList *
+gst_buffer_list_ref (GstBufferList * list)
+{
+  return GST_BUFFER_LIST_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (
+      list)));
+}
+
+/**
+ * gst_buffer_list_unref:
+ * @list: a #GstBufferList
+ *
+ * Decreases the refcount of the buffer list. If the refcount reaches 0, the
+ * buffer list will be freed.
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_buffer_list_unref (GstBufferList * list);
+#endif
+
+static inline void
+gst_buffer_list_unref (GstBufferList * list)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (list));
+}
+
+/* copy */
+/**
+ * gst_buffer_list_copy:
+ * @list: a #GstBufferList
+ *
+ * Create a shallow copy of the given buffer list. This will make a newly
+ * allocated copy of the source list with copies of buffer pointers. The
+ * refcount of buffers pointed to will be increased by one.
+ *
+ * Returns: a new copy of @list.
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstBufferList * gst_buffer_list_copy (const GstBufferList * list);
+#endif
+
+static inline GstBufferList *
+gst_buffer_list_copy (const GstBufferList * list)
+{
+  return GST_BUFFER_LIST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (list)));
+}
+
+/**
+ * gst_buffer_list_is_writable:
+ * @list: a #GstBufferList
+ *
+ * Tests if you can safely add buffers and groups into a buffer list.
+ */
+#define gst_buffer_list_is_writable(list) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (list))
+
+/**
+ * gst_buffer_list_make_writable:
+ * @list: a #GstBufferList
+ *
+ * Makes a writable buffer list from the given buffer list. If the source buffer
+ * list is already writable, this will simply return the same buffer list. A
+ * copy will otherwise be made using gst_buffer_list_copy().
+ */
+#define gst_buffer_list_make_writable(list) GST_BUFFER_LIST_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (list)))
+
+guint                    gst_buffer_list_n_groups              (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void                     gst_buffer_list_foreach               (GstBufferList *list,
+                                                                GstBufferListFunc func,
+								gpointer user_data);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBuffer *              gst_buffer_list_get                   (GstBufferList *list, guint group, guint idx);
+
+/* iterator */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBufferListIterator *  gst_buffer_list_iterate               (GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void                     gst_buffer_list_iterator_free         (GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+guint                    gst_buffer_list_iterator_n_buffers    (const GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBuffer *              gst_buffer_list_iterator_next         (GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean                 gst_buffer_list_iterator_next_group   (GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void                     gst_buffer_list_iterator_add          (GstBufferListIterator *it, GstBuffer *buffer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void                     gst_buffer_list_iterator_add_group    (GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void                     gst_buffer_list_iterator_remove       (GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBuffer *              gst_buffer_list_iterator_steal        (GstBufferListIterator *it);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void                     gst_buffer_list_iterator_take         (GstBufferListIterator *it, GstBuffer *buffer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstBuffer *              gst_buffer_list_iterator_do           (GstBufferListIterator *it, GstBufferListDoFunction do_func,
+                                                                gpointer user_data);
+
+/* conversion */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBuffer *              gst_buffer_list_iterator_merge_group  (const GstBufferListIterator *it);
+
+G_END_DECLS
+
+#endif /* __GST_BUFFER_LIST_H__ */
--- a/gstreamer_core/gst/gstbus.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstbus.c	Fri Apr 16 15:15:52 2010 +0300
@@ -95,51 +95,20 @@
 static void gst_bus_init (GstBus * bus);
 static void gst_bus_dispose (GObject * object);
 
-static void gst_bus_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_bus_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
+static void gst_bus_set_main_context (GstBus * bus, GMainContext * ctx);
 
 static GstObjectClass *parent_class = NULL;
 static guint gst_bus_signals[LAST_SIGNAL] = { 0 };
 
-/* the context we wakeup when we posted a message on the bus */
-static GMainContext *main_context;
-
 struct _GstBusPrivate
 {
   guint num_sync_message_emitters;
-
   GCond *queue_cond;
+  GSource *watch_id;
+  GMainContext *main_context;
 };
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-GType
-gst_bus_get_type (void)
-{
-  static GType bus_type = 0;
 
-  if (G_UNLIKELY (bus_type == 0)) {
-    static const GTypeInfo bus_info = {
-      sizeof (GstBusClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_bus_class_init,
-      NULL,
-      NULL,
-      sizeof (GstBus),
-      0,
-      (GInstanceInitFunc) gst_bus_init,
-      NULL
-    };
-
-    bus_type = g_type_register_static (GST_TYPE_OBJECT, "GstBus", &bus_info, 0);
-  }
-  return bus_type;
-}
+G_DEFINE_TYPE (GstBus, gst_bus, GST_TYPE_OBJECT);
 
 /* fixme: do something about this */
 static void
@@ -163,8 +132,8 @@
     data2 = closure->data;
   }
   callback =
-      (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->
-      callback);
+      (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data :
+      cc->callback);
 
   callback (data1, gst_value_get_mini_object (param_values + 1), data2);
 }
@@ -172,20 +141,11 @@
 static void
 gst_bus_class_init (GstBusClass * klass)
 {
-  GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstobject_class = (GstObjectClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bus_dispose);
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bus_set_property);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bus_get_property);
 
   /**
    * GstBus::sync-message:
@@ -223,8 +183,6 @@
       G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL,
       marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
 
-  main_context = g_main_context_default ();
-
   g_type_class_add_private (klass, sizeof (GstBusPrivate));
 }
 
@@ -243,9 +201,7 @@
 static void
 gst_bus_dispose (GObject * object)
 {
-  GstBus *bus;
-
-  bus = GST_BUS (object);
+  GstBus *bus = GST_BUS (object);
 
   if (bus->queue) {
     GstMessage *message;
@@ -265,37 +221,48 @@
     bus->priv->queue_cond = NULL;
   }
 
+  if (bus->priv->main_context) {
+    g_main_context_unref (bus->priv->main_context);
+    bus->priv->main_context = NULL;
+  }
+
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
-gst_bus_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
+gst_bus_wakeup_main_context (GstBus * bus)
 {
-  GstBus *bus;
+  GMainContext *ctx;
 
-  bus = GST_BUS (object);
+  GST_OBJECT_LOCK (bus);
+  if ((ctx = bus->priv->main_context))
+    g_main_context_ref (ctx);
+  GST_OBJECT_UNLOCK (bus);
 
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
+  g_main_context_wakeup (ctx);
+
+  if (ctx)
+    g_main_context_unref (ctx);
 }
 
 static void
-gst_bus_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
+gst_bus_set_main_context (GstBus * bus, GMainContext * ctx)
 {
-  GstBus *bus;
+  GST_OBJECT_LOCK (bus);
+
+  if (bus->priv->main_context != NULL) {
+    g_main_context_unref (bus->priv->main_context);
+    bus->priv->main_context = NULL;
+  }
 
-  bus = GST_BUS (object);
+  if (ctx != NULL) {
+    bus->priv->main_context = g_main_context_ref (ctx);
+  }
 
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
+  GST_DEBUG_OBJECT (bus, "setting main context to %p, GLib default context: %p",
+      ctx, g_main_context_default ());
+
+  GST_OBJECT_UNLOCK (bus);
 }
 
 /**
@@ -387,8 +354,7 @@
       g_mutex_unlock (bus->queue_lock);
       GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message);
 
-      /* FIXME cannot assume sources are only in the default context */
-      g_main_context_wakeup (main_context);
+      gst_bus_wakeup_main_context (bus);
 
       break;
     case GST_BUS_ASYNC:
@@ -412,8 +378,7 @@
       g_cond_broadcast (bus->priv->queue_cond);
       g_mutex_unlock (bus->queue_lock);
 
-      /* FIXME cannot assume sources are only in the default context */
-      g_main_context_wakeup (main_context);
+      gst_bus_wakeup_main_context (bus);
 
       /* now block till the message is freed */
       g_cond_wait (cond, lock);
@@ -781,6 +746,7 @@
 {
   GSource source;
   GstBus *bus;
+  gboolean inited;
 } GstBusSource;
 
 static gboolean
@@ -788,6 +754,14 @@
 {
   GstBusSource *bsrc = (GstBusSource *) source;
 
+  /* we do this here now that we know that we're attached to a main context
+   * (we don't support detaching a source from a main context and then
+   * re-attaching it to a different main context) */
+  if (G_UNLIKELY (!bsrc->inited)) {
+    gst_bus_set_main_context (bsrc->bus, g_source_get_context (source));
+    bsrc->inited = TRUE;
+  }
+
   *timeout = -1;
   return gst_bus_have_pending (bsrc->bus);
 }
@@ -817,7 +791,11 @@
   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
 
   message = gst_bus_pop (bus);
-  g_return_val_if_fail (message != NULL, FALSE);
+
+  /* The message queue might be empty if some other thread or callback set
+   * the bus to flushing between check/prepare and dispatch */
+  if (G_UNLIKELY (message == NULL))
+    return TRUE;
 
   if (!handler)
     goto no_handler;
@@ -844,7 +822,18 @@
 gst_bus_source_finalize (GSource * source)
 {
   GstBusSource *bsource = (GstBusSource *) source;
+  GstBus *bus;
 
+  bus = bsource->bus;
+
+  GST_DEBUG_OBJECT (bus, "finalize source %p", source);
+
+  GST_OBJECT_LOCK (bus);
+  if (bus->priv->watch_id == source)
+    bus->priv->watch_id = NULL;
+  GST_OBJECT_UNLOCK (bus);
+
+  gst_bus_set_main_context (bsource->bus, NULL);
   gst_object_unref (bsource->bus);
   bsource->bus = NULL;
 }
@@ -879,12 +868,44 @@
 
   source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
       sizeof (GstBusSource));
-  gst_object_ref (bus);
-  source->bus = bus;
+  source->bus = gst_object_ref (bus);
+  source->inited = FALSE;
 
   return (GSource *) source;
 }
 
+/* must be called with the bus OBJECT LOCK */
+static guint
+gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
+    GstBusFunc func, gpointer user_data, GDestroyNotify notify)
+{
+  guint id;
+  GSource *source;
+
+  if (bus->priv->watch_id) {
+    GST_ERROR_OBJECT (bus,
+        "Tried to add new watch while one was already there");
+    return 0;
+  }
+
+  source = gst_bus_create_watch (bus);
+
+  if (priority != G_PRIORITY_DEFAULT)
+    g_source_set_priority (source, priority);
+
+  g_source_set_callback (source, (GSourceFunc) func, user_data, notify);
+
+  id = g_source_attach (source, NULL);
+  g_source_unref (source);
+
+  if (id) {
+    bus->priv->watch_id = source;
+  }
+
+  GST_DEBUG_OBJECT (bus, "New source %p with id %u", source, id);
+  return id;
+}
+
 /**
  * gst_bus_add_watch_full:
  * @bus: a #GstBus to create the watch for.
@@ -895,6 +916,8 @@
  *
  * Adds a bus watch to the default main context with the given @priority.
  * This function is used to receive asynchronous messages in the main loop.
+ * There can only be a single bus watch per bus, you must remove it before you
+ * can set a new one.
  *
  * When @func is called, the message belongs to the caller; if you want to
  * keep a copy of it, call gst_message_ref() before leaving @func.
@@ -915,21 +938,13 @@
     GstBusFunc func, gpointer user_data, GDestroyNotify notify)
 {
   guint id;
-  GSource *source;
 
   g_return_val_if_fail (GST_IS_BUS (bus), 0);
 
-  source = gst_bus_create_watch (bus);
-
-  if (priority != G_PRIORITY_DEFAULT)
-    g_source_set_priority (source, priority);
+  GST_OBJECT_LOCK (bus);
+  id = gst_bus_add_watch_full_unlocked (bus, priority, func, user_data, notify);
+  GST_OBJECT_UNLOCK (bus);
 
-  g_source_set_callback (source, (GSourceFunc) func, user_data, notify);
-
-  id = g_source_attach (source, NULL);
-  g_source_unref (source);
-
-  GST_DEBUG_OBJECT (bus, "New source %p", source);
   return id;
 }
 
@@ -941,6 +956,8 @@
  *
  * Adds a bus watch to the default main context with the default priority.
  * This function is used to receive asynchronous messages in the main loop.
+ * There can only be a single bus watch per bus, you must remove it before you
+ * can set a new one.
  *
  * The watch can be removed using g_source_remove() or by returning FALSE
  * from @func.
@@ -1028,7 +1045,8 @@
  * @bus: a #GstBus
  * @events: a mask of #GstMessageType, representing the set of message types to
  * poll for.
- * @timeout: the poll timeout, as a #GstClockTimeDiff, or -1 to poll indefinitely.
+ * @timeout: the poll timeout, as a #GstClockTimeDiff, or -1 to poll
+ * indefinitely.
  *
  * Poll the bus for messages. Will block while waiting for messages to come.
  * You can specify a maximum time to poll with the @timeout parameter. If
@@ -1045,6 +1063,23 @@
  * This function will run a main loop from the default main context when
  * polling.
  *
+ * You should never use this function, since it is pure evil. This is
+ * especially true for GUI applications based on Gtk+ or Qt, but also for any
+ * other non-trivial application that uses the GLib main loop. As this function
+ * runs a GLib main loop, any callback attached to the default GLib main
+ * context may be invoked. This could be timeouts, GUI events, I/O events etc.;
+ * even if gst_bus_poll() is called with a 0 timeout. Any of these callbacks
+ * may do things you do not expect, e.g. destroy the main application window or
+ * some other resource; change other application state; display a dialog and
+ * run another main loop until the user clicks it away. In short, using this
+ * function may add a lot of complexity to your code through unexpected
+ * re-entrancy and unexpected changes to your application's state.
+ *
+ * For 0 timeouts use gst_bus_pop_filtered() instead of this function; for
+ * other short timeouts use gst_bus_timed_pop_filtered(); everything else is
+ * better handled by setting up an asynchronous bus watch and doing things
+ * from there.
+ *
  * Returns: The message that was received, or NULL if the poll timed out.
  * The message is taken from the bus and needs to be unreffed with
  * gst_message_unref() after usage.
@@ -1192,9 +1227,7 @@
   g_return_if_fail (GST_IS_BUS (bus));
 
   GST_OBJECT_LOCK (bus);
-
   bus->priv->num_sync_message_emitters++;
-
   GST_OBJECT_UNLOCK (bus);
 }
 
@@ -1223,13 +1256,10 @@
 gst_bus_disable_sync_message_emission (GstBus * bus)
 {
   g_return_if_fail (GST_IS_BUS (bus));
-
   g_return_if_fail (bus->num_signal_watchers == 0);
 
   GST_OBJECT_LOCK (bus);
-
   bus->priv->num_sync_message_emitters--;
-
   GST_OBJECT_UNLOCK (bus);
 }
 
@@ -1246,6 +1276,9 @@
  * responsible for calling gst_bus_remove_signal_watch() as many times as this
  * function is called.
  *
+ * There can only be a single bus watch per bus, you most remove all signal watch
+ * before you can set another type of watch.
+ *
  * MT safe.
  */
 #ifdef __SYMBIAN32__
@@ -1263,17 +1296,30 @@
   if (bus->num_signal_watchers > 0)
     goto done;
 
+  /* this should not fail because the counter above takes care of it */
   g_assert (bus->signal_watch_id == 0);
 
   bus->signal_watch_id =
-      gst_bus_add_watch_full (bus, priority, gst_bus_async_signal_func, NULL,
-      NULL);
+      gst_bus_add_watch_full_unlocked (bus, priority, gst_bus_async_signal_func,
+      NULL, NULL);
+
+  if (G_UNLIKELY (bus->signal_watch_id == 0))
+    goto add_failed;
 
 done:
 
   bus->num_signal_watchers++;
 
   GST_OBJECT_UNLOCK (bus);
+  return;
+
+  /* ERRORS */
+add_failed:
+  {
+    g_critical ("Could not add signal watch to bus %s", GST_OBJECT_NAME (bus));
+    GST_OBJECT_UNLOCK (bus);
+    return;
+  }
 }
 
 /**
@@ -1295,7 +1341,6 @@
 EXPORT_C
 #endif
 
- 
 void
 gst_bus_add_signal_watch (GstBus * bus)
 {
@@ -1317,6 +1362,8 @@
 void
 gst_bus_remove_signal_watch (GstBus * bus)
 {
+  guint id = 0;
+
   g_return_if_fail (GST_IS_BUS (bus));
 
   /* I know the callees don't take this lock, so go ahead and abuse it */
@@ -1330,13 +1377,20 @@
   if (bus->num_signal_watchers > 0)
     goto done;
 
-  g_source_remove (bus->signal_watch_id);
+  id = bus->signal_watch_id;
   bus->signal_watch_id = 0;
 
+  GST_DEBUG_OBJECT (bus, "removing signal watch %u", id);
+
 done:
   GST_OBJECT_UNLOCK (bus);
+
+  if (id)
+    g_source_remove (id);
+
   return;
 
+  /* ERRORS */
 error:
   {
     g_critical ("Bus %s has no signal watches attached", GST_OBJECT_NAME (bus));
--- a/gstreamer_core/gst/gstbus.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstbus.h	Fri Apr 16 15:15:52 2010 +0300
@@ -114,7 +114,7 @@
 {
   GstObject 	    object;
 
-  /*< private > */
+  /*< private >*/
   GQueue           *queue;
   GMutex           *queue_lock;
 
@@ -124,7 +124,7 @@
   guint             signal_watch_id;
   guint             num_signal_watchers;
 
-  /*< private > */
+  /*< private >*/
   GstBusPrivate    *priv;
   gpointer _gst_reserved[GST_PADDING - 1];
 };
@@ -137,7 +137,7 @@
   void (*message)  	(GstBus *bus, GstMessage *message);
   void (*sync_message)  (GstBus *bus, GstMessage *message);
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 #ifdef __SYMBIAN32__
--- a/gstreamer_core/gst/gstcaps.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstcaps.c	Fri Apr 16 15:15:52 2010 +0300
@@ -95,13 +95,11 @@
 #define IS_WRITABLE(caps) \
   (g_atomic_int_get (&(caps)->refcount) == 1)
 
-#if GLIB_CHECK_VERSION (2, 10, 0)
-#define ALLOC_CAPS()    g_slice_new (GstCaps)
-#define FREE_CAPS(caps) g_slice_free (GstCaps, caps)
-#else
-#define ALLOC_CAPS()    g_new (GstCaps, 1)
-#define FREE_CAPS(caps) g_free (caps)
-#endif
+/* quick way to get a caps structure at an index without doing a type or array
+ * length check */
+#define gst_caps_get_structure_unchecked(caps, index) \
+     ((GstStructure *)g_ptr_array_index ((caps)->structs, (index)))
+
 
 /* lock to protect multiple invocations of static caps to caps conversion */
 G_LOCK_DEFINE_STATIC (static_caps_lock);
@@ -151,7 +149,7 @@
 GstCaps *
 gst_caps_new_empty (void)
 {
-  GstCaps *caps = ALLOC_CAPS ();
+  GstCaps *caps = g_slice_new (GstCaps);
 
   caps->type = GST_TYPE_CAPS;
   caps->refcount = 1;
@@ -304,15 +302,16 @@
 {
   GstCaps *newcaps;
   GstStructure *structure;
-  guint i;
+  guint i, n;
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
   newcaps = gst_caps_new_empty ();
   newcaps->flags = caps->flags;
+  n = caps->structs->len;
 
-  for (i = 0; i < caps->structs->len; i++) {
-    structure = gst_caps_get_structure (caps, i);
+  for (i = 0; i < n; i++) {
+    structure = gst_caps_get_structure_unchecked (caps, i);
     gst_caps_append_structure (newcaps, gst_structure_copy (structure));
   }
 
@@ -323,13 +322,13 @@
 _gst_caps_free (GstCaps * caps)
 {
   GstStructure *structure;
-  guint i;
+  guint i, len;
 
   /* The refcount must be 0, but since we're only called by gst_caps_unref,
    * don't bother testing. */
-
-  for (i = 0; i < caps->structs->len; i++) {
-    structure = (GstStructure *) gst_caps_get_structure (caps, i);
+  len = caps->structs->len;
+  for (i = 0; i < len; i++) {
+    structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
     gst_structure_set_parent_refcount (structure, NULL);
     gst_structure_free (structure);
   }
@@ -341,7 +340,7 @@
 #ifdef DEBUG_REFCOUNT
   GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
 #endif
-  FREE_CAPS (caps);
+  g_slice_free (GstCaps, caps);
 }
 
 /**
@@ -513,7 +512,7 @@
 
     /* initialize the caps to a refcount of 1 so the caps can be writable for
      * the next statement */
-    gst_atomic_int_set (&temp.refcount, 1);
+    temp.refcount = 1;
 
     /* convert to string */
     if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string)))
@@ -524,7 +523,7 @@
     caps->flags = temp.flags;
     caps->structs = temp.structs;
     /* and bump the refcount so other threads can now read */
-    gst_atomic_int_set (&caps->refcount, 1);
+    g_atomic_int_set (&caps->refcount, 1);
 
     GST_CAT_LOG (GST_CAT_CAPS, "created %p", static_caps);
   done:
@@ -562,7 +561,7 @@
   GstStructure *struct1 = (GstStructure *) data;
   const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
 
-  if (val1 == NULL)
+  if (G_UNLIKELY (val1 == NULL))
     return FALSE;
   if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
     return TRUE;
@@ -578,37 +577,43 @@
   GstStructure *subtract_from = user_data;
   GValue subtraction = { 0, };
   const GValue *other;
-  gint res;
 
-  other = gst_structure_id_get_value (subtract_from, field_id);
-  if (!other) {
+  if (!(other = gst_structure_id_get_value (subtract_from, field_id)))
     /* field is missing in one set */
     return FALSE;
-  }
+
+  /* equal values are subset */
+  if (gst_value_compare (other, value) == GST_VALUE_EQUAL)
+    return TRUE;
+
   /*
+   * 1 - [1,2] = empty
+   * -> !subset
+   *
    * [1,2] - 1 = 2
-   * 1 - [1,2] = ???
+   *  -> 1 - [1,2] = empty
+   *  -> subset
+   *
+   * [1,3] - [1,2] = 3
+   * -> [1,2] - [1,3] = empty
+   * -> subset
+   *
+   * {1,2} - {1,3} = 2
+   * -> {1,3} - {1,2} = 3
+   * -> !subset
+   *
+   *  First caps subtraction needs to return a non-empty set, second
+   *  subtractions needs to give en empty set.
    */
-  if (!gst_value_subtract (&subtraction, other, value)) {
-    /* empty result -> values are the same, or first was a value and
-     * second was a list
-     * verify that result is empty by swapping args */
-    if (!gst_value_subtract (&subtraction, value, other)) {
-      return TRUE;
-    }
+  if (gst_value_subtract (&subtraction, other, value)) {
     g_value_unset (&subtraction);
-    return FALSE;
-  }
-
-  res = gst_value_compare (&subtraction, other);
-  g_value_unset (&subtraction);
+    /* !empty result, swapping must be empty */
+    if (!gst_value_subtract (&subtraction, value, other))
+      return TRUE;
 
-  if (res == GST_VALUE_EQUAL) {
-    /* value was empty ? */
-    return FALSE;
-  } else {
-    return TRUE;
+    g_value_unset (&subtraction);
   }
+  return FALSE;
 }
 
 static gboolean
@@ -652,7 +657,7 @@
 #ifdef USE_POISONING
   CAPS_POISON (caps2);
 #endif
-  if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) {
+  if (G_UNLIKELY (gst_caps_is_any (caps1) || gst_caps_is_any (caps2))) {
     /* FIXME: this leaks */
     caps1->flags |= GST_CAPS_FLAGS_ANY;
     for (i = caps2->structs->len - 1; i >= 0; i--) {
@@ -660,9 +665,7 @@
       gst_structure_free (structure);
     }
   } else {
-    int len = caps2->structs->len;
-
-    for (i = 0; i < len; i++) {
+    for (i = caps2->structs->len; i; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, 0);
       gst_caps_append_structure (caps1, structure);
     }
@@ -700,21 +703,19 @@
 #ifdef USE_POISONING
   CAPS_POISON (caps2);
 #endif
-  if (gst_caps_is_any (caps1)) {
+  if (G_UNLIKELY (gst_caps_is_any (caps1))) {
     for (i = caps2->structs->len - 1; i >= 0; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, i);
       gst_structure_free (structure);
     }
-  } else if (gst_caps_is_any (caps2)) {
+  } else if (G_UNLIKELY (gst_caps_is_any (caps2))) {
     caps1->flags |= GST_CAPS_FLAGS_ANY;
     for (i = caps1->structs->len - 1; i >= 0; i--) {
       structure = gst_caps_remove_and_get_structure (caps1, i);
       gst_structure_free (structure);
     }
   } else {
-    int len = caps2->structs->len;
-
-    for (i = 0; i < len; i++) {
+    for (i = caps2->structs->len; i; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, 0);
       gst_caps_merge_structure (caps1, structure);
     }
@@ -817,7 +818,7 @@
 #endif
     /* check each structure */
     for (i = caps->structs->len - 1; i >= 0; i--) {
-      structure1 = gst_caps_get_structure (caps, i);
+      structure1 = gst_caps_get_structure_unchecked (caps, i);
       /* if structure is a subset of structure1, then skip it */
       if (gst_caps_structure_is_subset (structure1, structure)) {
         unique = FALSE;
@@ -865,7 +866,14 @@
  * WARNING: This function takes a const GstCaps *, but returns a
  * non-const GstStructure *.  This is for programming convenience --
  * the caller should be aware that structures inside a constant
- * #GstCaps should not be modified.
+ * #GstCaps should not be modified. However, if you know the caps
+ * are writable, either because you have just copied them or made
+ * them writable with gst_caps_make_writable(), you may modify the
+ * structure returned in the usual way, e.g. with functions like
+ * gst_structure_set_simple().
+ *
+ * You do not need to free or unref the structure returned, it
+ * belongs to the #GstCaps.
  *
  * Returns: a pointer to the #GstStructure corresponding to @index
  */
@@ -879,7 +887,7 @@
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
   g_return_val_if_fail (index < caps->structs->len, NULL);
 
-  return g_ptr_array_index (caps->structs, index);
+  return gst_caps_get_structure_unchecked (caps, index);
 }
 
 /**
@@ -907,8 +915,8 @@
   newcaps = gst_caps_new_empty ();
   newcaps->flags = caps->flags;
 
-  if (caps->structs->len > nth) {
-    structure = gst_caps_get_structure (caps, nth);
+  if (G_LIKELY (caps->structs->len > nth)) {
+    structure = gst_caps_get_structure_unchecked (caps, nth);
     gst_caps_append_structure (newcaps, gst_structure_copy (structure));
   }
 
@@ -955,7 +963,7 @@
 #endif
 
 void
-gst_caps_set_simple (GstCaps * caps, char *field, ...)
+gst_caps_set_simple (GstCaps * caps, const char *field, ...)
 {
   GstStructure *structure;
   va_list var_args;
@@ -964,7 +972,7 @@
   g_return_if_fail (caps->structs->len == 1);
   g_return_if_fail (IS_WRITABLE (caps));
 
-  structure = gst_caps_get_structure (caps, 0);
+  structure = gst_caps_get_structure_unchecked (caps, 0);
 
   va_start (var_args, field);
   gst_structure_set_valist (structure, field, var_args);
@@ -986,7 +994,7 @@
 #endif
 
 void
-gst_caps_set_simple_valist (GstCaps * caps, char *field, va_list varargs)
+gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs)
 {
   GstStructure *structure;
 
@@ -994,7 +1002,7 @@
   g_return_if_fail (caps->structs->len == 1);
   g_return_if_fail (IS_WRITABLE (caps));
 
-  structure = gst_caps_get_structure (caps, 0);
+  structure = gst_caps_get_structure_unchecked (caps, 0);
 
   gst_structure_set_valist (structure, field, varargs);
 }
@@ -1075,7 +1083,7 @@
   if (caps->structs->len != 1)
     return FALSE;
 
-  structure = gst_caps_get_structure (caps, 0);
+  structure = gst_caps_get_structure_unchecked (caps, 0);
 
   return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL);
 }
@@ -1102,8 +1110,8 @@
   g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE);
   g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE);
 
-  struct1 = gst_caps_get_structure (caps1, 0);
-  struct2 = gst_caps_get_structure (caps2, 0);
+  struct1 = gst_caps_get_structure_unchecked (caps1, 0);
+  struct2 = gst_caps_get_structure_unchecked (caps2, 0);
 
   if (struct1->name != struct2->name) {
     return FALSE;
@@ -1195,16 +1203,19 @@
 gboolean
 gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2)
 {
+  /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error
+   * So there should be an assertion that caps1 and caps2 != NULL */
+
   /* NULL <-> NULL is allowed here */
-  if (caps1 == caps2)
+  if (G_UNLIKELY (caps1 == caps2))
     return TRUE;
 
   /* one of them NULL => they are different (can't be both NULL because
    * we checked that above) */
-  if (caps1 == NULL || caps2 == NULL)
+  if (G_UNLIKELY (caps1 == NULL || caps2 == NULL))
     return FALSE;
 
-  if (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2))
+  if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2)))
     return gst_caps_is_equal_fixed (caps1, caps2);
 
   return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
@@ -1226,7 +1237,7 @@
   GValue dest_value = { 0 };
   const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
 
-  if (val2 == NULL) {
+  if (G_UNLIKELY (val2 == NULL)) {
     gst_structure_id_set_value (idata->dest, id, val1);
   } else if (idata->first_run) {
     if (gst_value_intersect (&dest_value, val1, val2)) {
@@ -1249,20 +1260,20 @@
   g_return_val_if_fail (struct1 != NULL, NULL);
   g_return_val_if_fail (struct2 != NULL, NULL);
 
-  if (struct1->name != struct2->name)
+  if (G_UNLIKELY (struct1->name != struct2->name))
     return NULL;
 
   data.dest = gst_structure_id_empty_new (struct1->name);
   data.intersect = struct2;
   data.first_run = TRUE;
-  if (!gst_structure_foreach ((GstStructure *) struct1,
-          gst_caps_structure_intersect_field, &data))
+  if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
+              gst_caps_structure_intersect_field, &data)))
     goto error;
 
   data.intersect = struct1;
   data.first_run = FALSE;
-  if (!gst_structure_foreach ((GstStructure *) struct2,
-          gst_caps_structure_intersect_field, &data))
+  if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
+              gst_caps_structure_intersect_field, &data)))
     goto error;
 
   return data.dest;
@@ -1332,7 +1343,7 @@
 gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
 {
   guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
-  guint j, k;
+  guint j, k, len1, len2;
 
   GstStructure *struct1;
   GstStructure *struct2;
@@ -1343,17 +1354,17 @@
   g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
 
   /* caps are exactly the same pointers, just copy one caps */
-  if (caps1 == caps2)
+  if (G_UNLIKELY (caps1 == caps2))
     return gst_caps_copy (caps1);
 
   /* empty caps on either side, return empty */
-  if (gst_caps_is_empty (caps1) || gst_caps_is_empty (caps2))
+  if (G_UNLIKELY (gst_caps_is_empty (caps1) || gst_caps_is_empty (caps2)))
     return gst_caps_new_empty ();
 
   /* one of the caps is any, just copy the other caps */
-  if (gst_caps_is_any (caps1))
+  if (G_UNLIKELY (gst_caps_is_any (caps1)))
     return gst_caps_copy (caps2);
-  if (gst_caps_is_any (caps2))
+  if (G_UNLIKELY (gst_caps_is_any (caps2)))
     return gst_caps_copy (caps1);
 
   dest = gst_caps_new_empty ();
@@ -1374,25 +1385,27 @@
    * the structures diagonally down, then we iterate over the caps2
    * structures.
    */
-  for (i = 0; i < caps1->structs->len + caps2->structs->len - 1; i++) {
+  len1 = caps1->structs->len;
+  len2 = caps2->structs->len;
+  for (i = 0; i < len1 + len2 - 1; i++) {
     /* caps1 index goes from 0 to caps1->structs->len-1 */
-    j = MIN (i, caps1->structs->len - 1);
+    j = MIN (i, len1 - 1);
     /* caps2 index stays 0 until i reaches caps1->structs->len, then it counts
      * up from 1 to caps2->structs->len - 1 */
     k = MAX (0, i - j);
 
     /* now run the diagonal line, end condition is the left or bottom
      * border */
-    while (k < caps2->structs->len) {
-      struct1 = gst_caps_get_structure (caps1, j);
-      struct2 = gst_caps_get_structure (caps2, k);
+    while (k < len2) {
+      struct1 = gst_caps_get_structure_unchecked (caps1, j);
+      struct2 = gst_caps_get_structure_unchecked (caps2, k);
 
       istruct = gst_caps_structure_intersect (struct1, struct2);
 
       gst_caps_append_structure (dest, istruct);
       /* move down left */
       k++;
-      if (j == 0)
+      if (G_UNLIKELY (j == 0))
         break;                  /* so we don't roll back to G_MAXUINT */
       j--;
     }
@@ -1478,7 +1491,7 @@
 GstCaps *
 gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
 {
-  guint i, j;
+  guint i, j, sublen;
   GstStructure *min;
   GstStructure *sub;
   GstCaps *dest = NULL, *src;
@@ -1498,18 +1511,22 @@
      You can only remove everything or nothing and that is done above.
      Note: there's a test that checks this behaviour. */
   g_return_val_if_fail (!gst_caps_is_any (minuend), NULL);
-  g_assert (subtrahend->structs->len > 0);
+  sublen = subtrahend->structs->len;
+  g_assert (sublen > 0);
 
   src = gst_caps_copy (minuend);
-  for (i = 0; i < subtrahend->structs->len; i++) {
-    sub = gst_caps_get_structure (subtrahend, i);
+  for (i = 0; i < sublen; i++) {
+    guint srclen;
+
+    sub = gst_caps_get_structure_unchecked (subtrahend, i);
     if (dest) {
       gst_caps_unref (src);
       src = dest;
     }
     dest = gst_caps_new_empty ();
-    for (j = 0; j < src->structs->len; j++) {
-      min = gst_caps_get_structure (src, j);
+    srclen = src->structs->len;
+    for (j = 0; j < srclen; j++) {
+      min = gst_caps_get_structure_unchecked (src, j);
       if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub)) {
         GSList *list;
 
@@ -1558,6 +1575,16 @@
   GstCaps *dest1;
   GstCaps *dest2;
 
+  /* NULL pointers are no correct GstCaps */
+  g_return_val_if_fail (caps1 != NULL, NULL);
+  g_return_val_if_fail (caps2 != NULL, NULL);
+
+  if (gst_caps_is_empty (caps1))
+    return gst_caps_copy (caps2);
+
+  if (gst_caps_is_empty (caps2))
+    return gst_caps_copy (caps1);
+
   if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2))
     return gst_caps_new_any ();
 
@@ -1584,7 +1611,8 @@
   guint i;
 
   if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
-    for (i = 1; i < gst_value_list_get_size (value); i++) {
+    guint len = gst_value_list_get_size (value);
+    for (i = 1; i < len; i++) {
       const GValue *v = gst_value_list_get_value (value, i);
       GstStructure *structure = gst_structure_copy (nf->structure);
 
@@ -1620,15 +1648,16 @@
 {
   NormalizeForeach nf;
   GstCaps *newcaps;
-  guint i;
+  guint i, nlen;
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
   newcaps = gst_caps_copy (caps);
   nf.caps = newcaps;
+  nlen = newcaps->structs->len;
 
-  for (i = 0; i < newcaps->structs->len; i++) {
-    nf.structure = gst_caps_get_structure (newcaps, i);
+  for (i = 0; i < nlen; i++) {
+    nf.structure = gst_caps_get_structure_unchecked (newcaps, i);
 
     while (!gst_structure_foreach (nf.structure,
             gst_caps_normalize_foreach, &nf));
@@ -1793,14 +1822,15 @@
 
   start = caps->structs->len - 1;
   for (i = caps->structs->len - 1; i >= 0; i--) {
-    simplify = gst_caps_get_structure (caps, i);
+    simplify = gst_caps_get_structure_unchecked (caps, i);
     if (gst_structure_get_name_id (simplify) !=
-        gst_structure_get_name_id (gst_caps_get_structure (caps, start)))
+        gst_structure_get_name_id (gst_caps_get_structure_unchecked (caps,
+                start)))
       start = i;
     for (j = start; j >= 0; j--) {
       if (j == i)
         continue;
-      compare = gst_caps_get_structure (caps, j);
+      compare = gst_caps_get_structure_unchecked (caps, j);
       if (gst_structure_get_name_id (simplify) !=
           gst_structure_get_name_id (compare)) {
         break;
@@ -1911,9 +1941,9 @@
  * can be converted back to a #GstCaps by gst_caps_from_string().
  *
  * For debugging purposes its easier to do something like this:
- * <programlisting>
- *  GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
- * </programlisting>
+ * |[
+ * GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
+ * ]|
  * This prints the caps in human readble form.
  *
  * Returns: a newly allocated string representing @caps.
@@ -1925,7 +1955,7 @@
 gchar *
 gst_caps_to_string (const GstCaps * caps)
 {
-  guint i, slen;
+  guint i, slen, clen;
   GString *s;
 
   /* NOTE:  This function is potentially called by the debug system,
@@ -1946,12 +1976,15 @@
 
   /* estimate a rough string length to avoid unnecessary reallocs in GString */
   slen = 0;
-  for (i = 0; i < caps->structs->len; i++) {
-    slen += STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i));
+  clen = caps->structs->len;
+  for (i = 0; i < clen; i++) {
+    slen +=
+        STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked (caps,
+            i));
   }
 
   s = g_string_sized_new (slen);
-  for (i = 0; i < caps->structs->len; i++) {
+  for (i = 0; i < clen; i++) {
     GstStructure *structure;
 
     if (i > 0) {
@@ -1959,7 +1992,7 @@
       g_string_append_c (s, ' ');
     }
 
-    structure = gst_caps_get_structure (caps, i);
+    structure = gst_caps_get_structure_unchecked (caps, i);
     priv_gst_structure_append_to_gstring (structure, s);
   }
   if (s->len && s->str[s->len - 1] == ';') {
--- a/gstreamer_core/gst/gstcaps.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstcaps.h	Fri Apr 16 15:15:52 2010 +0300
@@ -296,13 +296,13 @@
 #endif
 
 void              gst_caps_set_simple              (GstCaps       *caps,
-                                                    char          *field, ...) G_GNUC_NULL_TERMINATED;
+                                                    const char    *field, ...) G_GNUC_NULL_TERMINATED;
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 void              gst_caps_set_simple_valist       (GstCaps       *caps,
-                                                    char          *field,
+                                                    const char    *field,
                                                     va_list        varargs);
 
 /* tests */
--- a/gstreamer_core/gst/gstchildproxy.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstchildproxy.c	Fri Apr 16 15:15:52 2010 +0300
@@ -467,7 +467,7 @@
 /**
  * gst_child_proxy_child_removed:
  * @object: the parent object
- * @child: the newly added child
+ * @child: the removed child
  *
  * Emits the "child-removed" signal.
  */
@@ -497,6 +497,8 @@
 	 *
 	 * Will be emitted after the @object was added to the @child_proxy.
 	 */
+    /* FIXME 0.11: use GST_TYPE_OBJECT as GstChildProxy only
+     * supports GstObjects */
     signals[CHILD_ADDED] =
         g_signal_new ("child-added", G_TYPE_FROM_CLASS (g_class),
         G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
@@ -510,6 +512,8 @@
 	 *
 	 * Will be emitted after the @object was removed from the @child_proxy.
 	 */
+    /* FIXME 0.11: use GST_TYPE_OBJECT as GstChildProxy only
+     * supports GstObjects */
     signals[CHILD_REMOVED] =
         g_signal_new ("child-removed", G_TYPE_FROM_CLASS (g_class),
         G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
@@ -527,9 +531,10 @@
 GType
 gst_child_proxy_get_type (void)
 {
-  static GType type = 0;
+  static volatile gsize type = 0;
 
-  if (G_UNLIKELY (type == 0)) {
+  if (g_once_init_enter (&type)) {
+    GType _type;
     static const GTypeInfo info = {
       sizeof (GstChildProxyInterface),
       gst_child_proxy_base_init,        /* base_init */
@@ -541,9 +546,12 @@
       0,                        /* n_preallocs */
       NULL                      /* instance_init */
     };
-    type = g_type_register_static (G_TYPE_INTERFACE, "GstChildProxy", &info, 0);
 
-    g_type_interface_add_prerequisite (type, GST_TYPE_OBJECT);
+    _type =
+        g_type_register_static (G_TYPE_INTERFACE, "GstChildProxy", &info, 0);
+
+    g_type_interface_add_prerequisite (_type, GST_TYPE_OBJECT);
+    g_once_init_leave (&type, (gsize) _type);
   }
   return type;
 }
--- a/gstreamer_core/gst/gstchildproxy.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstchildproxy.h	Fri Apr 16 15:15:52 2010 +0300
@@ -47,7 +47,7 @@
  * @get_child_by_index: virtual method to fetch the child
  * @get_children_count: virtual method to get the children count
  *
- * #GstChildProxyInterface interface.
+ * #GstChildProxy interface.
  */
 struct _GstChildProxyInterface
 {
@@ -56,12 +56,12 @@
   /* methods */
   GstObject *(*get_child_by_index) (GstChildProxy * parent, guint index);
   guint (*get_children_count) (GstChildProxy * parent);
-  /*< private > */
+  /*< private >*/
   /* signals */
   void (*child_added) (GstChildProxy * parent, GstObject * child);
   void (*child_removed) (GstChildProxy * parent, GstObject * child);
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 #ifdef __SYMBIAN32__
--- a/gstreamer_core/gst/gstclock.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstclock.c	Fri Apr 16 15:15:52 2010 +0300
@@ -28,7 +28,7 @@
  *
  * GStreamer uses a global clock to synchronize the plugins in a pipeline.
  * Different clock implementations are possible by implementing this abstract
- * base class.
+ * base class or, more conveniently, by subclassing #GstSystemClock.
  *
  * The #GstClock returns a monotonically increasing time with the method
  * gst_clock_get_time(). Its accuracy and base time depend on the specific
@@ -37,7 +37,7 @@
  * meaningful in itself, what matters are the deltas between two clock times.
  * The time returned by a clock is called the absolute time.
  *
- * The pipeline uses the clock to calculate the stream time. Usually all
+ * The pipeline uses the clock to calculate the running time. Usually all
  * renderers synchronize to the global clock using the buffer timestamps, the
  * newsegment events and the element's base time, see #GstPipeline.
  *
@@ -52,18 +52,18 @@
  * gst_clock_id_wait(). To receive a callback when the specific time is reached
  * in the clock use gst_clock_id_wait_async(). Both these calls can be
  * interrupted with the gst_clock_id_unschedule() call. If the blocking wait is
- * unscheduled a return value of GST_CLOCK_UNSCHEDULED is returned.
+ * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned.
  *
- * Periodic callbacks scheduled async will be repeadedly called automatically
+ * Periodic callbacks scheduled async will be repeatedly called automatically
  * until it is unscheduled. To schedule a sync periodic callback,
- * gst_clock_id_wait() should be called repeadedly.
+ * gst_clock_id_wait() should be called repeatedly.
  *
  * The async callbacks can happen from any thread, either provided by the core
  * or from a streaming thread. The application should be prepared for this.
  *
  * A #GstClockID that has been unscheduled cannot be used again for any wait
  * operation, a new #GstClockID should be created and the old unscheduled one
- * should be destroyed wirth gst_clock_id_unref().
+ * should be destroyed with gst_clock_id_unref().
  *
  * It is possible to perform a blocking wait on the same #GstClockID from
  * multiple threads. However, registering the same #GstClockID for multiple
@@ -77,14 +77,14 @@
  * state changes and if the entry would be unreffed automatically, the handle 
  * might become invalid without any notification.
  *
- * These clock operations do not operate on the stream time, so the callbacks
+ * These clock operations do not operate on the running time, so the callbacks
  * will also occur when not in PLAYING state as if the clock just keeps on
  * running. Some clocks however do not progress when the element that provided
  * the clock is not PLAYING.
  *
- * When a clock has the GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
+ * When a clock has the #GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
  * slaved to another #GstClock with the gst_clock_set_master(). The clock will
- * then automatically be synchronized to this master clock by repeadedly
+ * then automatically be synchronized to this master clock by repeatedly
  * sampling the master clock and the slave clock and recalibrating the slave
  * clock with gst_clock_set_calibration(). This feature is mostly useful for
  * plugins that have an internal clock but must operate with another clock
@@ -92,14 +92,14 @@
  * of their internal clock relative to the master clock by using the
  * gst_clock_get_calibration() function. 
  *
- * The master/slave synchronisation can be tuned with the "timeout", "window-size"
- * and "window-threshold" properties. The "timeout" property defines the interval
- * to sample the master clock and run the calibration functions. 
- * "window-size" defines the number of samples to use when calibrating and
- * "window-threshold" defines the minimum number of samples before the 
- * calibration is performed.
+ * The master/slave synchronisation can be tuned with the #GstClock:timeout,
+ * #GstClock:window-size and #GstClock:window-threshold properties.
+ * The #GstClock:timeout property defines the interval to sample the master
+ * clock and run the calibration functions. #GstClock:window-size defines the
+ * number of samples to use when calibrating and #GstClock:window-threshold
+ * defines the minimum number of samples before the calibration is performed.
  *
- * Last reviewed on 2006-08-11 (0.10.10)
+ * Last reviewed on 2009-05-21 (0.10.24)
  */
 
 
@@ -119,15 +119,6 @@
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #endif
-
-#if GLIB_CHECK_VERSION (2, 10, 0)
-#define ALLOC_ENTRY()     g_slice_new (GstClockEntry)
-#define FREE_ENTRY(entry) g_slice_free (GstClockEntry, entry)
-#else
-#define ALLOC_ENTRY()     g_new (GstClockEntry, 1)
-#define FREE_ENTRY(entry) g_free (entry)
-#endif
-
 /* #define DEBUGGING_ENABLED */
 
 #define DEFAULT_STATS                   FALSE
@@ -144,6 +135,41 @@
   PROP_TIMEOUT
 };
 
+struct _GstClockPrivate
+{
+  gint pre_count;
+  gint post_count;
+};
+
+/* seqlocks */
+#define read_seqbegin(clock)                                   \
+  g_atomic_int_get (&clock->ABI.priv->post_count);
+
+static inline gboolean
+read_seqretry (GstClock * clock, gint seq)
+{
+  /* no retry if the seqnum did not change */
+  if (G_LIKELY (seq == g_atomic_int_get (&clock->ABI.priv->pre_count)))
+    return FALSE;
+
+  /* wait for the writer to finish and retry */
+  GST_OBJECT_LOCK (clock);
+  GST_OBJECT_UNLOCK (clock);
+  return TRUE;
+}
+
+#define write_seqlock(clock)                      \
+G_STMT_START {                                    \
+  GST_OBJECT_LOCK (clock);                        \
+  g_atomic_int_inc (&clock->ABI.priv->pre_count);     \
+} G_STMT_END;
+
+#define write_sequnlock(clock)                    \
+G_STMT_START {                                    \
+  g_atomic_int_inc (&clock->ABI.priv->post_count);    \
+  GST_OBJECT_UNLOCK (clock);                      \
+} G_STMT_END;
+
 static void gst_clock_class_init (GstClockClass * klass);
 static void gst_clock_init (GstClock * clock);
 static void gst_clock_dispose (GObject * object);
@@ -166,19 +192,19 @@
 {
   GstClockEntry *entry;
 
-  entry = ALLOC_ENTRY ();
+  entry = g_slice_new (GstClockEntry);
 #ifndef GST_DISABLE_TRACE
   gst_alloc_trace_new (_gst_clock_entry_trace, entry);
 #endif
   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
       "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
 
-  gst_atomic_int_set (&entry->refcount, 1);
+  entry->refcount = 1;
   entry->clock = clock;
   entry->type = type;
   entry->time = time;
   entry->interval = interval;
-  entry->status = GST_CLOCK_BUSY;
+  entry->status = GST_CLOCK_OK;
   entry->func = NULL;
   entry->user_data = NULL;
 
@@ -219,7 +245,7 @@
 #ifndef GST_DISABLE_TRACE
   gst_alloc_trace_free (_gst_clock_entry_trace, id);
 #endif
-  FREE_ENTRY (id);
+  g_slice_free (GstClockEntry, id);
 }
 
 /**
@@ -282,8 +308,8 @@
  * @interval: the requested interval
  *
  * Get an ID from @clock to trigger a periodic notification.
- * The periodeic notifications will be start at time start_time and
- * will then be fired with the given interval. @id should be unreffed
+ * The periodic notifications will start at time @start_time and
+ * will then be fired with the given @interval. @id should be unreffed
  * after usage.
  *
  * Returns: A #GstClockID that can be used to request the time notification.
@@ -365,14 +391,14 @@
 /**
  * gst_clock_id_wait
  * @id: The #GstClockID to wait on
- * @jitter: A pointer that will contain the jitter, can be NULL.
+ * @jitter: A pointer that will contain the jitter, can be %NULL.
  *
  * Perform a blocking wait on @id. 
  * @id should have been created with gst_clock_new_single_shot_id()
  * or gst_clock_new_periodic_id() and should not have been unscheduled
  * with a call to gst_clock_id_unschedule(). 
  *
- * If the @jitter argument is not NULL and this function returns #GST_CLOCK_OK
+ * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK
  * or #GST_CLOCK_EARLY, it will contain the difference
  * against the clock and the time of @id when this method was
  * called. 
@@ -412,10 +438,6 @@
   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
     goto invalid_time;
 
-  /* a previously unscheduled entry cannot be scheduled again */
-  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
-    goto unscheduled;
-
   cclass = GST_CLOCK_GET_CLASS (clock);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);
@@ -448,7 +470,7 @@
   if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
     entry->time = requested + entry->interval;
 
-  if (clock->stats)
+  if (G_UNLIKELY (clock->stats))
     gst_clock_update_stats (clock);
 
   return res;
@@ -460,12 +482,6 @@
         "invalid time requested, returning _BADTIME");
     return GST_CLOCK_BADTIME;
   }
-unscheduled:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
-        "entry was unscheduled return _UNSCHEDULED");
-    return GST_CLOCK_UNSCHEDULED;
-  }
 not_supported:
   {
     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
@@ -477,14 +493,17 @@
  * gst_clock_id_wait_async:
  * @id: a #GstClockID to wait on
  * @func: The callback function
- * @user_data: User data passed in the calback
+ * @user_data: User data passed in the callback
  *
  * Register a callback on the given #GstClockID @id with the given
  * function and user_data. When passing a #GstClockID with an invalid
- * time to this function, the callback will be called immediatly
+ * time to this function, the callback will be called immediately
  * with  a time set to GST_CLOCK_TIME_NONE. The callback will
  * be called when the time of @id has been reached.
  *
+ * The callback @func can be invoked from any thread, either provided by the
+ * core or from a streaming thread. The application should be prepared for this.
+ *
  * Returns: the result of the non blocking wait.
  *
  * MT safe.
@@ -514,10 +533,6 @@
   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
     goto invalid_time;
 
-  /* a previously unscheduled entry cannot be scheduled again */
-  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
-    goto unscheduled;
-
   cclass = GST_CLOCK_GET_CLASS (clock);
 
   if (G_UNLIKELY (cclass->wait_async == NULL))
@@ -538,12 +553,6 @@
         "invalid time requested, returning _BADTIME");
     return GST_CLOCK_BADTIME;
   }
-unscheduled:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
-        "entry was unscheduled return _UNSCHEDULED");
-    return GST_CLOCK_UNSCHEDULED;
-  }
 not_supported:
   {
     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
@@ -585,52 +594,18 @@
 }
 
 
-/**
+/*
  * GstClock abstract base class implementation
  */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_clock_get_type (void)
-{
-  static GType clock_type = 0;
-
-  if (G_UNLIKELY (clock_type == 0)) {
-    static const GTypeInfo clock_info = {
-      sizeof (GstClockClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_clock_class_init,
-      NULL,
-      NULL,
-      sizeof (GstClock),
-      0,
-      (GInstanceInitFunc) gst_clock_init,
-      NULL
-    };
-
-    clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
-        &clock_info, G_TYPE_FLAG_ABSTRACT);
-  }
-  return clock_type;
-}
+G_DEFINE_TYPE (GstClock, gst_clock, GST_TYPE_OBJECT);
 
 static void
 gst_clock_class_init (GstClockClass * klass)
 {
-  GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gstobject_class = GST_OBJECT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-
 #ifndef GST_DISABLE_TRACE
   _gst_clock_entry_trace =
       gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
@@ -644,19 +619,23 @@
   g_object_class_install_property (gobject_class, PROP_STATS,
       g_param_spec_boolean ("stats", "Stats",
           "Enable clock stats (unimplemented)", DEFAULT_STATS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_WINDOW_SIZE,
       g_param_spec_int ("window-size", "Window size",
           "The size of the window used to calculate rate and offset", 2, 1024,
-          DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE));
+          DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_WINDOW_THRESHOLD,
       g_param_spec_int ("window-threshold", "Window threshold",
           "The threshold to start calculating rate and offset", 2, 1024,
-          DEFAULT_WINDOW_THRESHOLD, G_PARAM_READWRITE));
+          DEFAULT_WINDOW_THRESHOLD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
       g_param_spec_uint64 ("timeout", "Timeout",
           "The amount of time, in nanoseconds, to sample master and slave clocks",
-          0, G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE));
+          0, G_MAXUINT64, DEFAULT_TIMEOUT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_type_class_add_private (klass, sizeof (GstClockPrivate));
 }
 
 static void
@@ -667,6 +646,9 @@
   clock->entries_changed = g_cond_new ();
   clock->stats = FALSE;
 
+  clock->ABI.priv =
+      G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
+
   clock->internal_calibration = 0;
   clock->external_calibration = 0;
   clock->rate_numerator = 1;
@@ -790,7 +772,7 @@
  * that the returned time is increasing. This function should be called with the
  * clock's OBJECT_LOCK held and is mainly used by clock subclasses.
  *
- * This function is te reverse of gst_clock_unadjust_unlocked().
+ * This function is the reverse of gst_clock_unadjust_unlocked().
  *
  * Returns: the converted time of the clock.
  */
@@ -810,22 +792,24 @@
   cdenom = clock->rate_denominator;
 
   /* avoid divide by 0 */
-  if (cdenom == 0)
+  if (G_UNLIKELY (cdenom == 0))
     cnum = cdenom = 1;
 
   /* The formula is (internal - cinternal) * cnum / cdenom + cexternal
    *
    * Since we do math on unsigned 64-bit ints we have to special case for
-   * interal < cinternal to get the sign right. this case is not very common,
+   * internal < cinternal to get the sign right. this case is not very common,
    * though.
    */
   if (G_LIKELY (internal >= cinternal)) {
-    ret = gst_util_uint64_scale (internal - cinternal, cnum, cdenom);
+    ret = internal - cinternal;
+    ret = gst_util_uint64_scale (ret, cnum, cdenom);
     ret += cexternal;
   } else {
-    ret = gst_util_uint64_scale (cinternal - internal, cnum, cdenom);
+    ret = cinternal - internal;
+    ret = gst_util_uint64_scale (ret, cnum, cdenom);
     /* clamp to 0 */
-    if (cexternal > ret)
+    if (G_LIKELY (cexternal > ret))
       ret = cexternal - ret;
     else
       ret = 0;
@@ -847,7 +831,7 @@
  * This function should be called with the clock's OBJECT_LOCK held and
  * is mainly used by clock subclasses.
  *
- * This function is te reverse of gst_clock_adjust_unlocked().
+ * This function is the reverse of gst_clock_adjust_unlocked().
  *
  * Returns: the internal time of the clock corresponding to @external.
  *
@@ -869,16 +853,18 @@
   cdenom = clock->rate_denominator;
 
   /* avoid divide by 0 */
-  if (cnum == 0)
+  if (G_UNLIKELY (cnum == 0))
     cnum = cdenom = 1;
 
   /* The formula is (external - cexternal) * cdenom / cnum + cinternal */
-  if (external >= cexternal) {
-    ret = gst_util_uint64_scale (external - cexternal, cdenom, cnum);
+  if (G_LIKELY (external >= cexternal)) {
+    ret = external - cexternal;
+    ret = gst_util_uint64_scale (ret, cdenom, cnum);
     ret += cinternal;
   } else {
-    ret = gst_util_uint64_scale (cexternal - external, cdenom, cnum);
-    if (cinternal > ret)
+    ret = cexternal - external;
+    ret = gst_util_uint64_scale (ret, cdenom, cnum);
+    if (G_LIKELY (cinternal > ret))
       ret = cinternal - ret;
     else
       ret = 0;
@@ -894,7 +880,7 @@
  * unadjusted for the offset and the rate.
  *
  * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
- * giving wrong input.
+ * given invalid input.
  *
  * MT safe.
  */
@@ -940,7 +926,7 @@
  * offset and rate.
  *
  * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
- * giving wrong input.
+ * given invalid input.
  *
  * MT safe.
  */
@@ -952,15 +938,19 @@
 gst_clock_get_time (GstClock * clock)
 {
   GstClockTime ret;
+  gint seq;
 
   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
 
-  ret = gst_clock_get_internal_time (clock);
+  do {
+    /* reget the internal time when we retry to get the most current
+     * timevalue */
+    ret = gst_clock_get_internal_time (clock);
 
-  GST_OBJECT_LOCK (clock);
-  /* this will scale for rate and offset */
-  ret = gst_clock_adjust_unlocked (clock, ret);
-  GST_OBJECT_UNLOCK (clock);
+    seq = read_seqbegin (clock);
+    /* this will scale for rate and offset */
+    ret = gst_clock_adjust_unlocked (clock, ret);
+  } while (read_seqretry (clock, seq));
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
       GST_TIME_ARGS (ret));
@@ -989,7 +979,7 @@
  * follows:
  *
  * <programlisting>
- *   time = (internal_time - @internal) * @rate_num / @rate_denom + @external
+ *   time = (internal_time - internal) * rate_num / rate_denom + external
  * </programlisting>
  *
  * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
@@ -1010,22 +1000,21 @@
     external, GstClockTime rate_num, GstClockTime rate_denom)
 {
   g_return_if_fail (GST_IS_CLOCK (clock));
-  g_return_if_fail (rate_num >= 0);
-  g_return_if_fail (rate_denom > 0);
-  g_return_if_fail (internal <= gst_clock_get_internal_time (clock));
+  g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
+  g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
 
-  GST_OBJECT_LOCK (clock);
+  write_seqlock (clock);
   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
       "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
       G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal),
       GST_TIME_ARGS (external), rate_num, rate_denom,
-      gst_guint64_to_gdouble (rate_num / rate_denom));
+      gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom));
 
   clock->internal_calibration = internal;
   clock->external_calibration = external;
   clock->rate_numerator = rate_num;
   clock->rate_denominator = rate_denom;
-  GST_OBJECT_UNLOCK (clock);
+  write_sequnlock (clock);
 }
 
 /**
@@ -1039,7 +1028,7 @@
  * Gets the internal rate and reference time of @clock. See
  * gst_clock_set_calibration() for more information.
  *
- * @internal, @external, @rate_num, and @rate_denom can be left NULL if the
+ * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the
  * caller is not interested in the values.
  *
  * MT safe.
@@ -1052,21 +1041,24 @@
 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
     GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
 {
+  gint seq;
+
   g_return_if_fail (GST_IS_CLOCK (clock));
 
-  GST_OBJECT_LOCK (clock);
-  if (rate_num)
-    *rate_num = clock->rate_numerator;
-  if (rate_denom)
-    *rate_denom = clock->rate_denominator;
-  if (external)
-    *external = clock->external_calibration;
-  if (internal)
-    *internal = clock->internal_calibration;
-  GST_OBJECT_UNLOCK (clock);
+  do {
+    seq = read_seqbegin (clock);
+    if (rate_num)
+      *rate_num = clock->rate_numerator;
+    if (rate_denom)
+      *rate_denom = clock->rate_denominator;
+    if (external)
+      *external = clock->external_calibration;
+    if (internal)
+      *internal = clock->internal_calibration;
+  } while (read_seqretry (clock, seq));
 }
 
-/* will be called repeadedly to sample the master and slave clock
+/* will be called repeatedly to sample the master and slave clock
  * to recalibrate the clock  */
 static gboolean
 gst_clock_slave_callback (GstClock * master, GstClockTime time,
@@ -1102,13 +1094,13 @@
  * A clock provider that slaves its clock to a master can get the current
  * calibration values with gst_clock_get_calibration().
  *
- * @master can be NULL in which case @clock will not be slaved anymore. It will
+ * @master can be %NULL in which case @clock will not be slaved anymore. It will
  * however keep reporting its time adjusted with the last configured rate 
  * and time offsets.
  *
- * Returns: TRUE if the clock is capable of being slaved to a master clock. 
+ * Returns: %TRUE if the clock is capable of being slaved to a master clock. 
  * Trying to set a master on a clock without the 
- * GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return FALSE.
+ * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE.
  *
  * MT safe.
  */
@@ -1169,11 +1161,11 @@
  * gst_clock_get_master
  * @clock: a #GstClock 
  *
- * Get the master clock that @clock is slaved to or NULL when the clock is
+ * Get the master clock that @clock is slaved to or %NULL when the clock is
  * not slaved to any master clock.
  *
- * Returns: a master #GstClock or NULL when this clock is not slaved to a master
- * clock. Unref after usage.
+ * Returns: a master #GstClock or %NULL when this clock is not slaved to a
+ * master clock. Unref after usage.
  *
  * MT safe.
  */
@@ -1332,12 +1324,12 @@
  * observations and @clock is recalibrated.
  *
  * If this functions returns %TRUE, @r_squared will contain the 
- * correlation coefficient of the interpollation. A value of 1.0
+ * correlation coefficient of the interpolation. A value of 1.0
  * means a perfect regression was performed. This value can
  * be used to control the sampling frequency of the master and slave
  * clocks.
  *
- * Returns: TRUE if enough observations were added to run the 
+ * Returns: %TRUE if enough observations were added to run the 
  * regression algorithm.
  *
  * MT safe.
@@ -1357,6 +1349,10 @@
 
   GST_CLOCK_SLAVE_LOCK (clock);
 
+  GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
+      "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
+
   clock->times[(4 * clock->time_index)] = slave;
   clock->times[(4 * clock->time_index) + 2] = master;
 
--- a/gstreamer_core/gst/gstclock.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstclock.h	Fri Apr 16 15:15:52 2010 +0300
@@ -50,14 +50,14 @@
 /**
  * GST_TYPE_CLOCK_TIME:
  *
- * The GType of a GstClockTime.
+ * The #GType of a #GstClockTime.
  */
 #define GST_TYPE_CLOCK_TIME G_TYPE_UINT64
 
 /**
  * GstClockTimeDiff:
  *
- * A datatype to hold a timedifference, measured in nanoseconds.
+ * A datatype to hold a time difference, measured in nanoseconds.
  */
 typedef gint64 GstClockTimeDiff;
 /**
@@ -118,6 +118,7 @@
 #define GST_TIME_AS_SECONDS(time)  ((time) / GST_SECOND)
 /**
  * GST_TIME_AS_MSECONDS:
+ * @time: the time
  *
  * Convert a #GstClockTime to milliseconds (1/1000 of a second).
  *
@@ -125,7 +126,8 @@
  */
 #define GST_TIME_AS_MSECONDS(time) ((time) / G_GINT64_CONSTANT (1000000))
 /**
- * GST_TIME_TO_USECONDS:
+ * GST_TIME_AS_USECONDS:
+ * @time: the time
  *
  * Convert a #GstClockTime to microseconds (1/1000000 of a second).
  *
@@ -133,7 +135,8 @@
  */
 #define GST_TIME_AS_USECONDS(time) ((time) / G_GINT64_CONSTANT (1000))
 /**
- * GST_TIME_TO_NSECONDS:
+ * GST_TIME_AS_NSECONDS:
+ * @time: the time
  *
  * Convert a #GstClockTime to nanoseconds (1/1000000000 of a second).
  *
@@ -155,20 +158,20 @@
  * GST_TIMEVAL_TO_TIME:
  * @tv: the timeval to convert
  *
- * Convert a GTimeVal to a #GstClockTime.
+ * Convert a #GTimeVal to a #GstClockTime.
  */
 #define GST_TIMEVAL_TO_TIME(tv)		(GstClockTime)((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
 
 /**
  * GST_TIME_TO_TIMEVAL:
- * @t: The GstClockTime to convert
+ * @t: The #GstClockTime to convert
  * @tv: The target timeval
  *
- * Note: on 32-bit systems, a timeval has a range of only 2^32 - 1 seconds,
+ * Convert a #GstClockTime to a #GTimeVal
+ *
+ * <note>on 32-bit systems, a timeval has a range of only 2^32 - 1 seconds,
  * which is about 68 years.  Expect trouble if you want to schedule stuff
- * in your pipeline for 2038.
- *
- * Convert a GstClockTime to a GTimeVal
+ * in your pipeline for 2038.</note>
  */
 #define GST_TIME_TO_TIMEVAL(t,tv)				\
 G_STMT_START {							\
@@ -187,7 +190,7 @@
 #define GST_TIMESPEC_TO_TIME(ts)	(GstClockTime)((ts).tv_sec * GST_SECOND + (ts).tv_nsec * GST_NSECOND)
 /**
  * GST_TIME_TO_TIMESPEC:
- * @t: The GstClockTime to convert
+ * @t: The #GstClockTime to convert
  * @ts: The target timespec
  *
  * Convert a #GstClockTime to a struct timespec (see man pselect)
@@ -203,7 +206,7 @@
  * GST_TIME_FORMAT:
  *
  * A format that can be used in printf like format strings to format
- * a GstClockTime value.
+ * a #GstClockTime value.
  */
 #define GST_TIME_FORMAT "u:%02u:%02u.%09u"
 /**
@@ -232,6 +235,7 @@
 typedef struct _GstClockEntry	GstClockEntry;
 typedef struct _GstClock	GstClock;
 typedef struct _GstClockClass	GstClockClass;
+typedef struct _GstClockPrivate	GstClockPrivate;
 
 /* --- prototype for async callbacks --- */
 /**
@@ -249,12 +253,12 @@
 						 GstClockID id, gpointer user_data);
 /**
  * GstClockReturn:
- * @GST_CLOCK_OK: The operation succeded.
+ * @GST_CLOCK_OK: The operation succeeded.
  * @GST_CLOCK_EARLY: The operation was scheduled too late.
  * @GST_CLOCK_UNSCHEDULED: The clockID was unscheduled
  * @GST_CLOCK_BUSY: The ClockID is busy
  * @GST_CLOCK_BADTIME: A bad time was provided to a function.
- * @GST_CLOCK_ERROR: An error occured
+ * @GST_CLOCK_ERROR: An error occurred
  * @GST_CLOCK_UNSUPPORTED: Operation is not supported
  *
  * The return value of a clock operation.
@@ -379,7 +383,7 @@
  * GST_CLOCK_COND:
  * @clock: the clock to query
  *
- * Gets the #GCond that gets signaled when the entries of the clock
+ * Gets the #GCond that gets signalled when the entries of the clock
  * changed.
  */
 #define GST_CLOCK_COND(clock)            (GST_CLOCK_CAST(clock)->entries_changed)
@@ -393,10 +397,10 @@
 /**
  * GST_CLOCK_TIMED_WAIT:
  * @clock: the clock to wait on
- * @tv: a GTimeVal to wait.
+ * @tv: a #GTimeVal to wait.
  *
  * Wait on the clock until the entries changed or the specified timeout
- * occured. 
+ * occurred. 
  */
 #define GST_CLOCK_TIMED_WAIT(clock,tv)   g_cond_timed_wait(GST_CLOCK_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
 /**
@@ -410,7 +414,7 @@
 /**
  * GstClock:
  *
- * GstClock base structure. The values of this structure are
+ * #GstClock base structure. The values of this structure are
  * protected for subclasses, use the methods to use the #GstClock.
  */
 struct _GstClock {
@@ -444,7 +448,10 @@
   GstClockID     clockid;
 
   /*< private >*/
-  GstClockTime	 _gst_reserved[GST_PADDING];
+  union {
+    GstClockPrivate *priv;
+    GstClockTime     _gst_reserved[GST_PADDING];
+  } ABI;
 };
 
 /**
@@ -454,11 +461,11 @@
  *                     be acceptable. The new resolution should be returned.
  * @get_resolution: get the resolution of the clock.
  * @get_internal_time: get the internal unadjusted time of the clock.
- * @wait: perform a blocking wait for the given GstClockEntry. Deprecated,
+ * @wait: perform a blocking wait for the given #GstClockEntry. Deprecated,
  *        implement @wait_jitter instead.
- * @wait_async: perform an asynchronous wait for the given GstClockEntry.
+ * @wait_async: perform an asynchronous wait for the given #GstClockEntry.
  * @unschedule: unblock a blocking or async wait operation.
- * @wait_jitter: perform a blocking wait on the given GstClockEntry and return
+ * @wait_jitter: perform a blocking wait on the given #GstClockEntry and return
  *               the jitter. (Since: 0.10.10)
  *
  * GStreamer clock class. Override the vmethods to implement the clock
--- a/gstreamer_core/gst/gstconfig.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstconfig.h	Fri Apr 16 15:15:52 2010 +0300
@@ -59,10 +59,7 @@
 #define GST_DISABLE_TRACE 1
 #define GST_DISABLE_ALLOC_TRACE 1
 #define GST_DISABLE_REGISTRY 1
-#define GST_DISABLE_ENUMTYPES 1
-#define GST_DISABLE_INDEX 1
 #define GST_DISABLE_PLUGIN 1
-#define GST_DISABLE_URI 1
 #define GST_DISABLE_XML 1
 #define GST_DISABLE_LOADSAVE_REGISTRY 1
 #define GST_HAVE_GLIB_2_8 1
@@ -133,18 +130,8 @@
 #define GST_DISABLE_XML 1
 
 /* FIXME: test and document these! */
-/* Configure the use of glib enumtypes (useful for introspection)
- * see http://bugzilla.gnome.org/show_bug.cgi?id=342564
- */
-/* #undef GST_DISABLE_ENUMTYPES */
-/* Configure the use of indizies for seeking
- * (not used in plugins right now)
- */
-/* #undef GST_DISABLE_INDEX */
 /* Configures the use of external plugins */
 /* #undef GST_DISABLE_PLUGIN */
-/* Configures the use of uri-handlers */
-/* #undef GST_DISABLE_URI */
 
 /* printf extension format */
 /**
@@ -212,7 +199,12 @@
 #endif
 #else /* not _MSC_VER */
 #define GST_PLUGIN_EXPORT
+#ifdef __SYMBIAN32__
+#define GST_EXPORT __declspec(dllexport) extern
+#else
 #define GST_EXPORT extern
 #endif
 
+#endif
+
 #endif /* __GST_CONFIG_H__ */
--- a/gstreamer_core/gst/gstdebugutils.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstdebugutils.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,10 +20,18 @@
  */
 /* TODO:
  * edge [ constraint=false ];
- * edge [ minlen=0 ];
- *   does not create spacial dependency
- * node [ margin="0.02,0.01" ];
- *   space surrounding the label
+ *   this creates strange graphs ("minlen=0" is better)
+ * try puting src/sink ghostpads for each bin into invisible clusters
+ *
+ * for more compact nodes, try
+ * - changing node-shape from box into record
+ * - use labels like : element [ label="{element | <src> src | <sink> sink}"]
+ * - point to record-connectors : element1:src -> element2:sink
+ * - we use head/tail labels for pad-caps right now
+ *   - this does not work well, as dot seems to not llok at their sizen when
+ *     doing the layout
+ *   - we could add the caps to the pad itself, then we should use one line per
+ *     caps (simple caps = one line)
  */
 
 #include "gst_private.h"
@@ -42,11 +50,19 @@
 #include "gstghostpad.h"
 #include "gstpad.h"
 #include "gstutils.h"
+#include "gstvalue.h"
 
 /*** PIPELINE GRAPHS **********************************************************/
 
 const gchar *priv_gst_dump_dot_dir;     /* NULL *//* set from gst.c */
 
+const gchar spaces[] = {
+  "                                "    /* 32 */
+      "                                "        /* 64 */
+      "                                "        /* 96 */
+      "                                "        /* 128 */
+};
+
 extern GstClockTime _priv_gst_info_start_time;
 
 static gchar *
@@ -67,7 +83,7 @@
   if (pending == GST_STATE_VOID_PENDING) {
     state_name = g_strdup_printf ("\\n[%c]", state_icons[state]);
   } else {
-    state_name = g_strdup_printf ("\\n[%c]->[%c]", state_icons[state],
+    state_name = g_strdup_printf ("\\n[%c] -> [%c]", state_icons[state],
         state_icons[pending]);
   }
   return state_name;
@@ -119,6 +135,351 @@
   return param_name;
 }
 
+static void
+debug_dump_pad (GstPad * pad, gchar * color_name, gchar * element_name,
+    FILE * out, const gint indent)
+{
+  GstPadTemplate *pad_templ;
+  GstPadPresence presence;
+  gchar *pad_name, *style_name;
+  gchar pad_flags[6];
+  const gchar *activation_mode = "-><";
+  const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
+
+  pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
+
+  /* pad availability */
+  style_name = "filled,solid";
+  if ((pad_templ = gst_pad_get_pad_template (pad))) {
+    presence = GST_PAD_TEMPLATE_PRESENCE (pad_templ);
+    if (presence == GST_PAD_SOMETIMES) {
+      style_name = "filled,dotted";
+    } else if (presence == GST_PAD_REQUEST) {
+      style_name = "filled,dashed";
+    }
+  }
+  /* check if pad flags */
+  pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b';
+  pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f';
+  pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g';
+  pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS) ? 's' : 's';
+  pad_flags[4] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b';
+  pad_flags[5] = '\0';
+
+  fprintf (out, "%s  %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n", spc, element_name, pad_name, color_name, GST_OBJECT_NAME (pad), activation_mode[pad->mode],      /* NONE/PUSH/PULL */
+      pad_flags, style_name);
+
+  g_free (pad_name);
+}
+
+static void
+debug_dump_element_pad (GstPad * pad, GstElement * element,
+    GstDebugGraphDetails details, FILE * out, const gint indent)
+{
+  GstElement *target_element;
+  GstPad *target_pad, *tmp_pad;
+  GstPadDirection dir;
+  gchar *pad_name, *element_name;
+  gchar *target_element_name;
+  gchar *color_name;
+
+  dir = gst_pad_get_direction (pad);
+  pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
+  element_name = debug_dump_make_object_name (GST_OBJECT (element));
+  if (GST_IS_GHOST_PAD (pad)) {
+    color_name =
+        (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir ==
+            GST_PAD_SINK) ? "#ddddff" : "#ffffff");
+    /* output target-pad so that it belongs to this element */
+    if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
+      if ((target_pad = gst_pad_get_peer (tmp_pad))) {
+        if ((target_element = gst_pad_get_parent_element (target_pad))) {
+          target_element_name =
+              debug_dump_make_object_name (GST_OBJECT (target_element));
+        } else {
+          target_element_name = "";
+        }
+        debug_dump_pad (target_pad, color_name, target_element_name, out,
+            indent);
+        if (target_element) {
+          g_free (target_element_name);
+          gst_object_unref (target_element);
+        }
+        gst_object_unref (target_pad);
+      }
+      gst_object_unref (tmp_pad);
+    }
+  } else {
+    color_name =
+        (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir ==
+            GST_PAD_SINK) ? "#aaaaff" : "#cccccc");
+  }
+  /* pads */
+  debug_dump_pad (pad, color_name, element_name, out, indent);
+  g_free (element_name);
+}
+
+static gboolean
+string_append_field (GQuark field, const GValue * value, gpointer ptr)
+{
+  GString *str = (GString *) ptr;
+  gchar *value_str = gst_value_serialize (value);
+
+  /* some enums can become really long */
+  if (strlen (value_str) > 25) {
+    gint pos = 24;
+
+    /* truncate */
+    value_str[25] = '\0';
+
+    /* mirror any brackets */
+    if (value_str[0] == '<')
+      value_str[pos--] = '>';
+    if (value_str[0] == '[')
+      value_str[pos--] = ']';
+    if (value_str[0] == '(')
+      value_str[pos--] = ')';
+    if (value_str[0] == '{')
+      value_str[pos--] = '}';
+    if (pos != 24)
+      value_str[pos--] = ' ';
+    /* elippsize */
+    value_str[pos--] = '.';
+    value_str[pos--] = '.';
+    value_str[pos--] = '.';
+  }
+  g_string_append_printf (str, "  %18s: %s\\l", g_quark_to_string (field),
+      value_str);
+
+  g_free (value_str);
+  return TRUE;
+}
+
+static gchar *
+debug_dump_describe_caps (GstCaps * caps, GstDebugGraphDetails details,
+    gboolean * need_free)
+{
+  gchar *media = NULL;
+
+  if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) {
+
+    if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) {
+      media = gst_caps_to_string (caps);
+      *need_free = TRUE;
+
+    } else {
+      GString *str = NULL;
+      guint i;
+      guint slen = 0;
+
+      for (i = 0; i < gst_caps_get_size (caps); i++) {
+        slen += 25 +
+            STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i));
+      }
+
+      str = g_string_sized_new (slen);
+      for (i = 0; i < gst_caps_get_size (caps); i++) {
+        GstStructure *structure = gst_caps_get_structure (caps, i);
+
+        g_string_append (str, gst_structure_get_name (structure));
+        g_string_append (str, "\\l");
+
+        gst_structure_foreach (structure, string_append_field, (gpointer) str);
+      }
+
+      media = g_string_free (str, FALSE);
+      *need_free = TRUE;
+    }
+
+  } else {
+    if (GST_CAPS_IS_SIMPLE (caps))
+      media =
+          (gchar *) gst_structure_get_name (gst_caps_get_structure (caps, 0));
+    else
+      media = "*";
+    *need_free = FALSE;
+  }
+  return media;
+}
+
+static void
+debug_dump_element_pad_link (GstPad * pad, GstElement * element,
+    GstDebugGraphDetails details, FILE * out, const gint indent)
+{
+  GstElement *peer_element, *target_element;
+  GstPad *peer_pad, *target_pad, *tmp_pad;
+  GstCaps *caps, *peer_caps;
+  gboolean free_caps, free_peer_caps;
+  gboolean free_media, free_media_src, free_media_sink;
+  gchar *media = NULL;
+  gchar *media_src = NULL, *media_sink = NULL;
+  gchar *pad_name, *element_name;
+  gchar *peer_pad_name, *peer_element_name;
+  gchar *target_pad_name, *target_element_name;
+  const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
+
+  if ((peer_pad = gst_pad_get_peer (pad))) {
+    free_media = free_media_src = free_media_sink = FALSE;
+    if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) ||
+        (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS)
+        ) {
+      if ((caps = gst_pad_get_negotiated_caps (pad))) {
+        free_caps = TRUE;
+      } else {
+        free_caps = FALSE;
+        if (!(caps = (GstCaps *)
+                gst_pad_get_pad_template_caps (pad))) {
+          /* this should not happen */
+          media = "?";
+        }
+      }
+      if ((peer_caps = gst_pad_get_negotiated_caps (peer_pad))) {
+        free_peer_caps = TRUE;
+      } else {
+        free_peer_caps = FALSE;
+        peer_caps = (GstCaps *) gst_pad_get_pad_template_caps (peer_pad);
+      }
+      if (caps) {
+        media = debug_dump_describe_caps (caps, details, &free_media);
+        /* check if peer caps are different */
+        if (peer_caps && !gst_caps_is_equal (caps, peer_caps)) {
+          gchar *tmp;
+          gboolean free_tmp;
+
+          tmp = debug_dump_describe_caps (peer_caps, details, &free_tmp);
+          if (gst_pad_get_direction (pad) == GST_PAD_SRC) {
+            media_src = media;
+            free_media_src = free_media;
+            media_sink = tmp;
+            free_media_sink = free_tmp;
+          } else {
+            media_src = tmp;
+            free_media_src = free_tmp;
+            media_sink = media;
+            free_media_sink = free_media;
+          }
+          media = NULL;
+          free_media = FALSE;
+        }
+        if (free_caps) {
+          gst_caps_unref (caps);
+        }
+      }
+      if (free_peer_caps && peer_caps) {
+        gst_caps_unref (peer_caps);
+      }
+    }
+
+    pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
+    if (element) {
+      element_name = debug_dump_make_object_name (GST_OBJECT (element));
+    } else {
+      element_name = "";
+    }
+    peer_pad_name = debug_dump_make_object_name (GST_OBJECT (peer_pad));
+    if ((peer_element = gst_pad_get_parent_element (peer_pad))) {
+      peer_element_name =
+          debug_dump_make_object_name (GST_OBJECT (peer_element));
+    } else {
+      peer_element_name = "";
+    }
+
+    if (GST_IS_GHOST_PAD (pad)) {
+      if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
+        if ((target_pad = gst_pad_get_peer (tmp_pad))) {
+          target_pad_name =
+              debug_dump_make_object_name (GST_OBJECT (target_pad));
+          if ((target_element = gst_pad_get_parent_element (target_pad))) {
+            target_element_name =
+                debug_dump_make_object_name (GST_OBJECT (target_element));
+          } else {
+            target_element_name = "";
+          }
+          /* src ghostpad relationship */
+          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
+              target_element_name, target_pad_name, element_name, pad_name);
+
+          g_free (target_pad_name);
+          if (target_element) {
+            g_free (target_element_name);
+            gst_object_unref (target_element);
+          }
+          gst_object_unref (target_pad);
+        }
+        gst_object_unref (tmp_pad);
+      }
+    }
+    if (GST_IS_GHOST_PAD (peer_pad)) {
+      if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer_pad)))) {
+        if ((target_pad = gst_pad_get_peer (tmp_pad))) {
+          target_pad_name =
+              debug_dump_make_object_name (GST_OBJECT (target_pad));
+          if ((target_element = gst_pad_get_parent_element (target_pad))) {
+            target_element_name =
+                debug_dump_make_object_name (GST_OBJECT (target_element));
+          } else {
+            target_element_name = "";
+          }
+          /* sink ghostpad relationship */
+          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
+              peer_element_name, peer_pad_name,
+              target_element_name, target_pad_name);
+          /* FIXME: we are missing links from the proxy pad
+           * theoretically we need to:
+           * pad=gst_object_ref(target_pad);
+           * goto line 280: if ((peer_pad = gst_pad_get_peer (pad)))
+           * as this would be ugly we need to refactor ...
+           */
+          debug_dump_element_pad_link (target_pad, target_element, details, out,
+              indent);
+          g_free (target_pad_name);
+          if (target_element) {
+            g_free (target_element_name);
+            gst_object_unref (target_element);
+          }
+          gst_object_unref (target_pad);
+        }
+        gst_object_unref (tmp_pad);
+      }
+    }
+
+    /* pad link */
+    if (media) {
+      fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
+          element_name, pad_name, peer_element_name, peer_pad_name, media);
+      if (free_media) {
+        g_free (media);
+      }
+    } else if (media_src && media_sink) {
+      /* dot has some issues with placement of head and taillabels,
+       * we need an empty label to make space */
+      fprintf (out, "%s%s_%s -> %s_%s [labeldistance=\"10\", labelangle=\"0\", "
+          "label=\"                                                  \", "
+          "headlabel=\"%s\", taillabel=\"%s\"]\n",
+          spc, element_name, pad_name, peer_element_name, peer_pad_name,
+          media_src, media_sink);
+      if (free_media_src)
+        g_free (media_src);
+      if (free_media_sink)
+        g_free (media_sink);
+    } else {
+      fprintf (out, "%s%s_%s -> %s_%s\n", spc,
+          element_name, pad_name, peer_element_name, peer_pad_name);
+    }
+
+    g_free (pad_name);
+    if (element) {
+      g_free (element_name);
+    }
+    g_free (peer_pad_name);
+    if (peer_element) {
+      g_free (peer_element_name);
+      gst_object_unref (peer_element);
+    }
+    gst_object_unref (peer_pad);
+  }
+}
+
 /*
  * debug_dump_element:
  * @bin: the bin that should be analyzed
@@ -133,25 +494,14 @@
 {
   GstIterator *element_iter, *pad_iter;
   gboolean elements_done, pads_done;
-  GstElement *element, *peer_element, *target_element;
-  GstPad *pad, *peer_pad, *target_pad;
+  GstElement *element;
+  GstPad *pad;
   GstPadDirection dir;
-  GstCaps *caps;
-  GstStructure *structure;
-  gboolean free_caps, free_media;
   guint src_pads, sink_pads;
-  gchar *media = NULL;
-  gchar *pad_name, *element_name;
-  gchar *peer_pad_name, *peer_element_name;
-  gchar *target_pad_name, *target_element_name;
-  gchar *color_name;
+  gchar *element_name;
   gchar *state_name = NULL;
   gchar *param_name = NULL;
-  gchar *spc = NULL;
-
-  spc = g_malloc (1 + indent * 2);
-  memset (spc, 32, indent * 2);
-  spc[indent * 2] = '\0';
+  const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
 
   element_iter = gst_bin_iterate_elements (bin);
   elements_done = FALSE;
@@ -172,7 +522,7 @@
         fprintf (out, "%s  fontsize=\"8\";\n", spc);
         fprintf (out, "%s  style=filled;\n", spc);
         fprintf (out, "%s  color=black;\n\n", spc);
-        fprintf (out, "%s  label=\"<%s>\\n%s%s%s\";\n", spc,
+        fprintf (out, "%s  label=\"%s\\n%s%s%s\";\n", spc,
             G_OBJECT_TYPE_NAME (element), GST_OBJECT_NAME (element),
             (state_name ? state_name : ""), (param_name ? param_name : "")
             );
@@ -192,31 +542,12 @@
           while (!pads_done) {
             switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
               case GST_ITERATOR_OK:
+                debug_dump_element_pad (pad, element, details, out, indent);
                 dir = gst_pad_get_direction (pad);
-                pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
-                element_name =
-                    debug_dump_make_object_name (GST_OBJECT (element));
-                if (GST_IS_GHOST_PAD (pad)) {
-                  color_name =
-                      (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir ==
-                          GST_PAD_SINK) ? "#ddddff" : "#ffffff");
-                } else {
-                  color_name =
-                      (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir ==
-                          GST_PAD_SINK) ? "#aaaaff" : "#cccccc");
-                }
-                /* pads */
-                fprintf (out,
-                    "%s  %s_%s [color=black, fillcolor=\"%s\", label=\"%s\"];\n",
-                    spc, element_name, pad_name, color_name,
-                    GST_OBJECT_NAME (pad));
-
                 if (dir == GST_PAD_SRC)
                   src_pads++;
                 else if (dir == GST_PAD_SINK)
                   sink_pads++;
-                g_free (pad_name);
-                g_free (element_name);
                 gst_object_unref (pad);
                 break;
               case GST_ITERATOR_RESYNC:
@@ -252,135 +583,8 @@
               case GST_ITERATOR_OK:
                 if (gst_pad_is_linked (pad)
                     && gst_pad_get_direction (pad) == GST_PAD_SRC) {
-                  if ((peer_pad = gst_pad_get_peer (pad))) {
-                    free_media = FALSE;
-                    if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) ||
-                        (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS)
-                        ) {
-                      if ((caps = gst_pad_get_negotiated_caps (pad))) {
-                        free_caps = TRUE;
-                      } else {
-                        free_caps = FALSE;
-                        if (!(caps = (GstCaps *)
-                                gst_pad_get_pad_template_caps (pad))) {
-                          /* this should not happen */
-                          media = "?";
-                        }
-                      }
-                      if (caps) {
-                        if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) {
-                          gchar *tmp =
-                              g_strdelimit (gst_caps_to_string (caps), ",",
-                              '\n');
-
-                          media = g_strescape (tmp, NULL);
-                          free_media = TRUE;
-                          g_free (tmp);
-                        } else {
-                          if (GST_CAPS_IS_SIMPLE (caps)) {
-                            structure = gst_caps_get_structure (caps, 0);
-                            media =
-                                (gchar *) gst_structure_get_name (structure);
-                          } else
-                            media = "*";
-                        }
-                        if (free_caps) {
-                          gst_caps_unref (caps);
-                        }
-                      }
-                    }
-
-                    pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
-                    element_name =
-                        debug_dump_make_object_name (GST_OBJECT (element));
-                    peer_pad_name =
-                        debug_dump_make_object_name (GST_OBJECT (peer_pad));
-                    if ((peer_element = gst_pad_get_parent_element (peer_pad))) {
-                      peer_element_name =
-                          debug_dump_make_object_name (GST_OBJECT
-                          (peer_element));
-                    } else {
-                      peer_element_name = "";
-                    }
-                    /* pad link */
-                    if (media) {
-                      fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
-                          element_name, pad_name, peer_element_name,
-                          peer_pad_name, media);
-                      if (free_media) {
-                        g_free (media);
-                      }
-                    } else {
-                      fprintf (out, "%s%s_%s -> %s_%s\n", spc,
-                          element_name, pad_name, peer_element_name,
-                          peer_pad_name);
-                    }
-
-                    if (GST_IS_GHOST_PAD (pad)) {
-                      if ((target_pad =
-                              gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
-                        target_pad_name =
-                            debug_dump_make_object_name (GST_OBJECT
-                            (target_pad));
-                        if ((target_element =
-                                gst_pad_get_parent_element (target_pad))) {
-                          target_element_name =
-                              debug_dump_make_object_name (GST_OBJECT
-                              (target_element));
-                        } else {
-                          target_element_name = "";
-                        }
-                        /* src ghostpad relationship */
-                        fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc,
-                            target_element_name, target_pad_name, element_name,
-                            pad_name);
-
-                        g_free (target_pad_name);
-                        if (target_element) {
-                          g_free (target_element_name);
-                          gst_object_unref (target_element);
-                        }
-                        gst_object_unref (target_pad);
-                      }
-                    }
-                    if (GST_IS_GHOST_PAD (peer_pad)) {
-                      if ((target_pad =
-                              gst_ghost_pad_get_target (GST_GHOST_PAD
-                                  (peer_pad)))) {
-                        target_pad_name =
-                            debug_dump_make_object_name (GST_OBJECT
-                            (target_pad));
-                        if ((target_element =
-                                gst_pad_get_parent_element (target_pad))) {
-                          target_element_name =
-                              debug_dump_make_object_name (GST_OBJECT
-                              (target_element));
-                        } else {
-                          target_element_name = "";
-                        }
-                        /* sink ghostpad relationship */
-                        fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc,
-                            peer_element_name, peer_pad_name,
-                            target_element_name, target_pad_name);
-
-                        g_free (target_pad_name);
-                        if (target_element) {
-                          g_free (target_element_name);
-                          gst_object_unref (target_element);
-                        }
-                        gst_object_unref (target_pad);
-                      }
-                    }
-
-                    g_free (pad_name);
-                    g_free (element_name);
-                    g_free (peer_pad_name);
-                    if (peer_element) {
-                      g_free (peer_element_name);
-                      gst_object_unref (peer_element);
-                    }
-                    gst_object_unref (peer_pad);
-                  }
+                  debug_dump_element_pad_link (pad, element, details, out,
+                      indent);
                 }
                 gst_object_unref (pad);
                 break;
@@ -407,7 +611,6 @@
     }
   }
   gst_iterator_free (element_iter);
-  g_free (spc);
 }
 
 /*
@@ -462,14 +665,14 @@
     fprintf (out,
         "digraph pipeline {\n"
         "  rankdir=LR;\n"
-        "  fontname=\"Bitstream Vera Sans\";\n"
-        "  fontsize=\"8\";\n"
+        "  fontname=\"sans\";\n"
+        "  fontsize=\"10\";\n"
         "  labelloc=t;\n"
         "  nodesep=.1;\n"
         "  ranksep=.2;\n"
         "  label=\"<%s>\\n%s%s%s\";\n"
-        "  node [style=filled, shape=box, fontsize=\"7\", fontname=\"Bitstream Vera Sans\"];\n"
-        "  edge [labelfontsize=\"7\", fontsize=\"7\", labelfontname=\"Bitstream Vera Sans\", fontname=\"Bitstream Vera Sans\"];\n"
+        "  node [style=filled, shape=box, fontsize=\"9\", fontname=\"sans\", margin=\"0.0,0.0\"];\n"
+        "  edge [labelfontsize=\"6\", fontsize=\"9\", fontname=\"monospace\"];\n"
         "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin),
         (state_name ? state_name : ""), (param_name ? param_name : "")
         );
@@ -521,12 +724,32 @@
   /* add timestamp */
   elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
       gst_util_get_timestamp ());
+
+  /* we don't use GST_TIME_FORMAT as such filenames would fail on some
+   * filesystems like fat */
   ts_file_name =
-      g_strdup_printf ("%" GST_TIME_FORMAT "-%s", GST_TIME_ARGS (elapsed),
+      g_strdup_printf ("%u.%02u.%02u.%09u-%s", GST_TIME_ARGS (elapsed),
       file_name);
 
   _gst_debug_bin_to_dot_file (bin, details, ts_file_name);
   g_free (ts_file_name);
 }
+#else /* !GST_DISABLE_GST_DEBUG */
+#ifndef GST_REMOVE_DISABLED
+void
+_gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
+    const gchar * file_name)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
+
+void
+_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
+    const gchar * file_name)
+{
+}
+#endif /* GST_REMOVE_DISABLED */
 #endif /* GST_DISABLE_GST_DEBUG */
--- a/gstreamer_core/gst/gstdebugutils.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstdebugutils.h	Fri Apr 16 15:15:52 2010 +0300
@@ -39,6 +39,8 @@
  *
  * Available details for pipeline graphs produced by GST_DEBUG_BIN_TO_DOT_FILE()
  * and GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS().
+ *
+ * Since: 0.10.15
  */
 typedef enum {
   GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE         = (1<<0),
@@ -67,7 +69,8 @@
 /**
  * GST_DEBUG_BIN_TO_DOT_FILE:
  * @bin: the top-level pipeline that should be analyzed
- * @details: graph-details to show
+ * @details: details to show in the graph, e.g. #GST_DEBUG_GRAPH_SHOW_ALL or
+ *    one or more other #GstDebugGraphDetails flags.
  * @file_name: output base filename (e.g. "myplayer")
  *
  * To aid debugging applications one can use this method to write out the whole
@@ -80,17 +83,22 @@
  * The macro is only active if gstreamer is configured with
  * &quot;--gst-enable-gst-debug&quot; and the environment variable
  * GST_DEBUG_DUMP_DOT_DIR is set to a basepath (e.g. /tmp).
+ *
+ * Since: 0.10.15
  */
 #define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) _gst_debug_bin_to_dot_file (bin, details, file_name)
 
 /**
  * GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS:
  * @bin: the top-level pipeline that should be analyzed
- * @details: graph-details to show
+ * @details: details to show in the graph, e.g. #GST_DEBUG_GRAPH_SHOW_ALL or
+ *    one or more other #GstDebugGraphDetails flags.
  * @file_name: output base filename (e.g. "myplayer")
  *
  * This works like _gst_debug_bin_to_dot_file(), but adds the current timestamp
  * to the filename, so that it can be used to take multiple snapshots.
+ *
+ * Since: 0.10.15
  */
 #define GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(bin, details, file_name) _gst_debug_bin_to_dot_file_with_ts (bin, details, file_name)
 
--- a/gstreamer_core/gst/gstelement.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstelement.c	Fri Apr 16 15:15:52 2010 +0300
@@ -73,7 +73,7 @@
  * toplevel #GstPipeline so the clock functions are only to be used in very
  * specific situations.
  *
- * Last reviewed on 2006-03-12 (0.10.5)
+ * Last reviewed on 2009-05-29 (0.10.24)
  */
 
 #include "gst_private.h"
@@ -89,6 +89,7 @@
 #include "gstevent.h"
 #include "gstutils.h"
 #include "gstinfo.h"
+#include "gstvalue.h"
 #include "gst-i18n-lib.h"
 
 #ifdef __SYMBIAN32__
@@ -148,6 +149,9 @@
 
 static GstObjectClass *parent_class = NULL;
 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
+
+/* this is used in gstelementfactory.c:gst_element_register() */
+GQuark _gst_elementclass_factory = 0;
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -156,9 +160,10 @@
 GType
 gst_element_get_type (void)
 {
-  static GType gst_element_type = 0;
-
-  if (G_UNLIKELY (gst_element_type == 0)) {
+  static volatile gsize gst_element_type = 0;
+
+  if (g_once_init_enter (&gst_element_type)) {
+    GType _type;
     static const GTypeInfo element_info = {
       sizeof (GstElementClass),
       gst_element_base_class_init,
@@ -172,8 +177,12 @@
       NULL
     };
 
-    gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
+    _type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
         &element_info, G_TYPE_FLAG_ABSTRACT);
+
+    _gst_elementclass_factory =
+        g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY");
+    g_once_init_leave (&gst_element_type, _type);
   }
   return gst_element_type;
 }
@@ -258,6 +267,13 @@
    */
   memset (&element_class->details, 0, sizeof (GstElementDetails));
   element_class->padtemplates = NULL;
+
+  /* set the factory, see gst_element_register() */
+  element_class->elementfactory =
+      g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
+      _gst_elementclass_factory);
+  GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class),
+      element_class->elementfactory);
 }
 
 static void
@@ -323,6 +339,10 @@
  * Makes the element free the previously requested pad as obtained
  * with gst_element_get_request_pad().
  *
+ * This does not unref the pad. If the pad was created by using 
+ * gst_element_get_request_pad(), gst_element_release_request_pad() needs to be
+ * followed by gst_object_unref() to free the @pad.
+ *
  * MT safe.
  */
 #ifdef __SYMBIAN32__
@@ -548,7 +568,7 @@
  * Returns the base time of the element. The base time is the
  * absolute time of the clock when this element was last put to
  * PLAYING. Subtracting the base time from the clock time gives
- * the stream time of the element.
+ * the running time of the element.
  *
  * Returns: the base time of the element.
  *
@@ -572,7 +592,81 @@
   return result;
 }
 
-#ifndef GST_DISABLE_INDEX
+/**
+ * gst_element_set_start_time:
+ * @element: a #GstElement.
+ * @time: the base time to set.
+ *
+ * Set the start time of an element. The start time of the element is the
+ * running time of the element when it last went to the PAUSED state. In READY
+ * or after a flushing seek, it is set to 0.
+ *
+ * Toplevel elements like #GstPipeline will manage the start_time and
+ * base_time on its children. Setting the start_time to #GST_CLOCK_TIME_NONE
+ * on such a toplevel element will disable the distribution of the base_time to
+ * the children and can be useful if the application manages the base_time
+ * itself, for example if you want to synchronize capture from multiple
+ * pipelines, and you can also ensure that the pipelines have the same clock.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_element_set_start_time (GstElement * element, GstClockTime time)
+{
+  GstClockTime old;
+
+  g_return_if_fail (GST_IS_ELEMENT (element));
+
+  GST_OBJECT_LOCK (element);
+  old = GST_ELEMENT_START_TIME (element);
+  GST_ELEMENT_START_TIME (element) = time;
+  GST_OBJECT_UNLOCK (element);
+
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element,
+      "set start_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (time), GST_TIME_ARGS (old));
+}
+
+/**
+ * gst_element_get_start_time:
+ * @element: a #GstElement.
+ *
+ * Returns the start time of the element. The start time is the
+ * running time of the clock when this element was last put to PAUSED. 
+ *
+ * Usually the start_time is managed by a toplevel element such as
+ * #GstPipeline. 
+ *
+ * MT safe.
+ *
+ * Returns: the start time of the element.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstClockTime
+gst_element_get_start_time (GstElement * element)
+{
+  GstClockTime result;
+
+  g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
+
+  GST_OBJECT_LOCK (element);
+  result = GST_ELEMENT_START_TIME (element);
+  GST_OBJECT_UNLOCK (element);
+
+  return result;
+}
+
 /**
  * gst_element_is_indexable:
  * @element: a #GstElement.
@@ -657,7 +751,6 @@
 
   return result;
 }
-#endif
 
 /**
  * gst_element_add_pad:
@@ -1083,17 +1176,18 @@
  * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
  * first, then gst_element_get_request_pad().
  *
- * <note>Usage of this function is not recommended as it is unclear if the reference
+ * Deprecated: This function is deprecated as it's unclear if the reference
  * to the result pad should be released with gst_object_unref() in case of a static pad
- * or gst_element_release_request_pad() in case of a request pad.</note>
+ * or gst_element_release_request_pad() in case of a request pad.
+ * Use gst_element_get_static_pad() or gst_element_get_request_pad() instead.
  *
  * Returns: the #GstPad if found, otherwise %NULL. Unref or Release after usage,
  * depending on the type of the pad.
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 GstPad *
 gst_element_get_pad (GstElement * element, const gchar * name)
 {
@@ -1108,6 +1202,7 @@
 
   return pad;
 }
+#endif /* GST_REMOVE_DEPRECATED */
 
 static GstIteratorItem
 iterate_pad (GstIterator * it, GstPad * pad)
@@ -1793,7 +1888,7 @@
   GstMessage *message = NULL;
 
   /* checks */
-  GST_DEBUG_OBJECT (element, "start");
+  GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element, "start");
   g_return_if_fail (GST_IS_ELEMENT (element));
   g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
       (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO));
@@ -1932,7 +2027,7 @@
 
 was_ok:
   {
-    GST_CAT_DEBUG (GST_CAT_STATES, "elements %s was in locked state %d",
+    GST_CAT_DEBUG (GST_CAT_STATES, "elements %s was already in locked state %d",
         GST_ELEMENT_NAME (element), old);
     GST_OBJECT_UNLOCK (element);
 
@@ -2004,6 +2099,7 @@
     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
         "syncing state failed (%s)",
         gst_element_state_change_return_get_name (ret));
+    gst_object_unref (parent);
     return FALSE;
   }
 }
@@ -2054,7 +2150,7 @@
     } else {
       timeval = NULL;
     }
-    /* get cookie to dected state change during waiting */
+    /* get cookie to detect state changes during waiting */
     cookie = element->state_cookie;
 
     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
@@ -2292,10 +2388,10 @@
   GST_OBJECT_UNLOCK (element);
 
   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
-      "committing state from %s to %s, pending %s",
+      "committing state from %s to %s, pending %s, next %s",
       gst_element_state_get_name (old_state),
       gst_element_state_get_name (old_next),
-      gst_element_state_get_name (pending));
+      gst_element_state_get_name (pending), gst_element_state_get_name (next));
 
   message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
       old_state, old_next, pending);
@@ -2349,15 +2445,16 @@
 }
 
 /**
- * gst_element_lost_state:
+ * gst_element_lost_state_full:
  * @element: a #GstElement the state is lost of
+ * @new_base_time: if a new base time should be distributed
  *
  * Brings the element to the lost state. The current state of the
  * element is copied to the pending state so that any call to
  * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
  *
- * An ASYNC_START message is posted with an indication to distribute a new
- * base_time to the element.
+ * An ASYNC_START message is posted with indication to distribute a new
+ * base_time to the element when @new_base_time is %TRUE.
  * If the element was PLAYING, it will go to PAUSED. The element
  * will be restored to its PLAYING state by the parent pipeline when it
  * prerolls again.
@@ -2372,13 +2469,15 @@
  * plugins or applications.
  *
  * MT safe.
+ *
+ * Since: 0.10.24
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 void
-gst_element_lost_state (GstElement * element)
+gst_element_lost_state_full (GstElement * element, gboolean new_base_time)
 {
   GstState old_state, new_state;
   GstMessage *message;
@@ -2386,10 +2485,12 @@
   g_return_if_fail (GST_IS_ELEMENT (element));
 
   GST_OBJECT_LOCK (element);
-  if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING ||
-      GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
+  if (GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
     goto nothing_lost;
 
+  if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING)
+    goto only_async_start;
+
   old_state = GST_STATE (element);
 
   /* when we were PLAYING, the new state is PAUSED. We will also not
@@ -2408,13 +2509,16 @@
   GST_STATE_NEXT (element) = new_state;
   GST_STATE_PENDING (element) = new_state;
   GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
+  if (new_base_time)
+    GST_ELEMENT_START_TIME (element) = 0;
   GST_OBJECT_UNLOCK (element);
 
   message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
       new_state, new_state, new_state);
   gst_element_post_message (element, message);
 
-  message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE);
+  message =
+      gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time);
   gst_element_post_message (element, message);
 
   return;
@@ -2424,6 +2528,36 @@
     GST_OBJECT_UNLOCK (element);
     return;
   }
+only_async_start:
+  {
+    GST_OBJECT_UNLOCK (element);
+
+    message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE);
+    gst_element_post_message (element, message);
+    return;
+  }
+}
+
+/**
+ * gst_element_lost_state:
+ * @element: a #GstElement the state is lost of
+ *
+ * Brings the element to the lost state. This function calls
+ * gst_element_lost_state_full() with the new_base_time set to %TRUE.
+ *
+ * This function is used internally and should normally not be called from
+ * plugins or applications.
+ *
+ * MT safe.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_element_lost_state (GstElement * element)
+{
+  gst_element_lost_state_full (element, TRUE);
 }
 
 /**
@@ -2441,6 +2575,9 @@
  * An application can use gst_element_get_state() to wait for the completion
  * of the state change or it can wait for a state change message on the bus.
  *
+ * State changes to %GST_STATE_READY or %GST_STATE_NULL never return
+ * #GST_STATE_CHANGE_ASYNC.
+ *
  * Returns: Result of the state change using #GstStateChangeReturn.
  *
  * MT safe.
@@ -2504,6 +2641,8 @@
   /* this is the (new) state we should go to. TARGET is the last state we set on
    * the element. */
   if (state != GST_STATE_TARGET (element)) {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
+        "setting target state to %s", gst_element_state_get_name (state));
     GST_STATE_TARGET (element) = state;
     /* increment state cookie so that we can track each state change. We only do
      * this if this is actually a new state change. */
@@ -2600,15 +2739,9 @@
 {
   GstElementClass *oclass;
   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstState current;
-  GstState next;
 
   oclass = GST_ELEMENT_GET_CLASS (element);
 
-  /* start with the current state. */
-  current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
-  next = GST_STATE_TRANSITION_NEXT (transition);
-
   /* call the state change function so it can set the state */
   if (oclass->change_state)
     ret = (oclass->change_state) (element, transition);
@@ -2797,17 +2930,20 @@
   /* ERRORS */
 src_failed:
   {
-    GST_DEBUG_OBJECT (element, "source pads_activate failed");
+    GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
+        "source pads_activate failed");
     return FALSE;
   }
 sink_failed:
   {
-    GST_DEBUG_OBJECT (element, "sink pads_activate failed");
+    GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
+        "sink pads_activate failed");
     return FALSE;
   }
 caps_failed:
   {
-    GST_DEBUG_OBJECT (element, "failed to clear caps on pads");
+    GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
+        "failed to clear caps on pads");
     return FALSE;
   }
 }
@@ -2818,6 +2954,7 @@
 {
   GstState state, next;
   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+  GstClock **clock_p;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
 
@@ -2854,6 +2991,12 @@
       } else {
         gst_element_set_base_time (element, 0);
       }
+
+      /* In null state release the reference to the clock */
+      GST_OBJECT_LOCK (element);
+      clock_p = &element->clock;
+      gst_object_replace ((GstObject **) clock_p, NULL);
+      GST_OBJECT_UNLOCK (element);
       break;
     default:
       /* this will catch real but unhandled state changes;
@@ -3031,7 +3174,13 @@
       else if (G_IS_PARAM_SPEC_INT64 (spec))
         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
             g_value_get_int64 (&value));
-      else
+      else if (GST_VALUE_HOLDS_STRUCTURE (&value)) {
+        if (g_value_get_boxed (&value) != NULL) {
+          contents = g_strdup_value_contents (&value);
+        } else {
+          contents = g_strdup ("NULL");
+        }
+      } else
         contents = g_strdup_value_contents (&value);
 
       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
@@ -3043,7 +3192,7 @@
 
   g_free (specs);
 
-  pads = GST_ELEMENT_PADS (element);
+  pads = g_list_last (GST_ELEMENT_PADS (element));
 
   while (pads) {
     GstPad *pad = GST_PAD_CAST (pads->data);
@@ -3054,7 +3203,7 @@
 
       gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag);
     }
-    pads = g_list_next (pads);
+    pads = g_list_previous (pads);
   }
 
   return parent;
--- a/gstreamer_core/gst/gstelement.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstelement.h	Fri Apr 16 15:15:52 2010 +0300
@@ -263,10 +263,21 @@
 #define GST_ELEMENT_PADS(elem)			(GST_ELEMENT_CAST(elem)->pads)
 
 /**
+ * GST_ELEMENT_START_TIME:
+ * @elem: a #GstElement to return the start time for.
+ *
+ * This macro returns the start_time of the @elem. The start_time is the
+ * running_time of the pipeline when the element went to PAUSED.
+ *
+ * Since: 0.10.24
+ */
+#define GST_ELEMENT_START_TIME(elem)		(GST_ELEMENT_CAST(elem)->abidata.ABI.start_time)
+
+/**
  * GST_ELEMENT_ERROR:
  * @el:     the element that generates the error
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #GstGError)
- * @code:   error code defined for that domain (see #GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
+ * @code:   error code defined for that domain (see #gstreamer-GstGError)
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -394,7 +405,7 @@
  * element by the toplevel #GstPipeline.
  * @base_time: the time of the clock right before the element is set to
  * PLAYING. Subtracting @base_time from the current clock time in the PLAYING
- * state will yield the stream time.
+ * state will yield the running_time against the clock.
  * @numpads: number of pads of the element, includes both source and sink pads.
  * @pads: list of pads
  * @numsrcpads: number of source pads of the element.
@@ -441,6 +452,8 @@
     struct {
       /* state set by application */
       GstState              target_state;
+      /* running time of the last PAUSED state */
+      GstClockTime          start_time;
     } ABI;
     /* adding + 0 to mark ABI change to be undone later */
     gpointer _gst_reserved[GST_PADDING + 0];
@@ -638,6 +651,16 @@
 #endif
 
 GstClockTime		gst_element_get_base_time	(GstElement *element);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void			gst_element_set_start_time	(GstElement *element, GstClockTime time);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstClockTime		gst_element_get_start_time	(GstElement *element);
 
 /* indexes */
 #ifdef __SYMBIAN32__
@@ -684,12 +707,10 @@
 #endif
 
 void			gst_element_no_more_pads	(GstElement *element);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
 
-
+#ifndef GST_DISABLE_DEPRECATED
 GstPad*			gst_element_get_pad		(GstElement *element, const gchar *name);
+#endif /* GST_DISABLE_DEPRECATED */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -820,6 +841,11 @@
 #endif
 
 void			gst_element_lost_state	        (GstElement * element);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void			gst_element_lost_state_full     (GstElement * element, gboolean new_base_time);
 
 /* factory management */
 #ifdef __SYMBIAN32__
--- a/gstreamer_core/gst/gstelementfactory.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstelementfactory.c	Fri Apr 16 15:15:52 2010 +0300
@@ -40,13 +40,16 @@
  * <title>Using an element factory</title>
  * <programlisting language="c">
  *   #include &lt;gst/gst.h&gt;
+ *   
  *   GstElement *src;
  *   GstElementFactory *srcfactory;
- *   gst_init(&amp;argc,&amp;argv);
- *   srcfactory = gst_element_factory_find("filesrc");
- *   g_return_if_fail(srcfactory != NULL);
- *   src = gst_element_factory_create(srcfactory,"src");
- *   g_return_if_fail(src != NULL);
+ *   
+ *   gst_init (&amp;argc, &amp;argv);
+ *   
+ *   srcfactory = gst_element_factory_find ("filesrc");
+ *   g_return_if_fail (srcfactory != NULL);
+ *   src = gst_element_factory_create (srcfactory, "src");
+ *   g_return_if_fail (src != NULL);
  *   ...
  * </programlisting>
  * </example>
@@ -75,48 +78,24 @@
 static GstPluginFeatureClass *parent_class = NULL;
 
 /* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_element_factory_get_type (void)
-{
-  static GType elementfactory_type = 0;
+/* this is defined in gstelement.c */
+extern GQuark _gst_elementclass_factory;
 
-  if (G_UNLIKELY (elementfactory_type == 0)) {
-    static const GTypeInfo elementfactory_info = {
-      sizeof (GstElementFactoryClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_element_factory_class_init,
-      NULL,
-      NULL,
-      sizeof (GstElementFactory),
-      0,
-      (GInstanceInitFunc) gst_element_factory_init,
-      NULL
-    };
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", \
+      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, \
+      "element factories keep information about installed elements"); \
+}
 
-    elementfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
-        "GstElementFactory", &elementfactory_info, 0);
-    GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY",
-        GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED,
-        "element factories keep information about installed elements");
-  }
-  return elementfactory_type;
-}
+G_DEFINE_TYPE_WITH_CODE (GstElementFactory, gst_element_factory,
+    GST_TYPE_PLUGIN_FEATURE, _do_init);
+
 static void
 gst_element_factory_class_init (GstElementFactoryClass * klass)
 {
-  GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
-  GstPluginFeatureClass *gstpluginfeature_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstobject_class = (GstObjectClass *) klass;
-  gstpluginfeature_class = (GstPluginFeatureClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -198,11 +177,12 @@
         __src->__entry);                                                \
     __dest->__entry = g_strdup ("[ERROR: invalid UTF-8]");              \
   }                                                                     \
-} G_STMT_END
-
+}G_STMT_END
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
+
 void
 __gst_element_details_set (GstElementDetails * dest,
     const GstElementDetails * src)
@@ -232,8 +212,7 @@
 
   __gst_element_details_clear (&factory->details);
   if (factory->type) {
-    g_type_class_unref (g_type_class_peek (factory->type));
-    factory->type = 0;
+    factory->type = G_TYPE_INVALID;
   }
 
   for (item = factory->staticpadtemplates; item; item = item->next) {
@@ -292,6 +271,8 @@
 gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
     GType type)
 {
+  GstPluginFeature *existing_feature;
+  GstRegistry *registry;
   GstElementFactory *factory;
   GType *interfaces;
   guint n_interfaces, i;
@@ -301,8 +282,27 @@
   g_return_val_if_fail (name != NULL, FALSE);
   g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE);
 
-  factory = GST_ELEMENT_FACTORY (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL));
-  gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name);
+  registry = gst_registry_get_default ();
+
+  /* check if feature already exists, if it exists there is no need to update it
+   * when the registry is getting updated, outdated plugins and all there
+   * feature are removed and readded.
+   */
+  existing_feature = gst_registry_lookup_feature (registry, name);
+  if (existing_feature) {
+    GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)",
+        existing_feature, name);
+    factory = GST_ELEMENT_FACTORY_CAST (existing_feature);
+    factory->type = type;
+    existing_feature->loaded = TRUE;
+    g_type_set_qdata (type, _gst_elementclass_factory, factory);
+    gst_object_unref (existing_feature);
+    return TRUE;
+  }
+
+  factory =
+      GST_ELEMENT_FACTORY_CAST (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL));
+  gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name);
   GST_LOG_OBJECT (factory, "Created new elementfactory for type %s",
       g_type_name (type));
 
@@ -326,7 +326,7 @@
         g_list_append (factory->staticpadtemplates, newt);
   }
   factory->numpadtemplates = klass->numpadtemplates;
-  klass->elementfactory = factory;
+  g_type_set_qdata (type, _gst_elementclass_factory, factory);
 
   /* special stuff for URI handling */
   if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) {
@@ -357,15 +357,14 @@
   g_free (interfaces);
 
   if (plugin && plugin->desc.name) {
-    GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name;
+    GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name;
   } else {
-    GST_PLUGIN_FEATURE (factory)->plugin_name = "NULL";
+    GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL";
   }
-  gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
-  GST_PLUGIN_FEATURE (factory)->loaded = TRUE;
+  gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank);
+  GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE;
 
-  gst_registry_add_feature (gst_registry_get_default (),
-      GST_PLUGIN_FEATURE (factory));
+  gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory));
 
   return TRUE;
 
@@ -435,16 +434,16 @@
 
   /* fill in the pointer to the factory in the element class. The
    * class will not be unreffed currently. 
-   * FIXME: This isn't safe and may leak a refcount on the factory if 2 threads
-   * create the first instance of an element at the same moment */
+   * Be thread safe as there might be 2 threads creating the first instance of
+   * an element at the same moment
+   */
   oclass = GST_ELEMENT_GET_CLASS (element);
-  if (G_UNLIKELY (oclass->elementfactory == NULL))
-    oclass->elementfactory = factory;
-  else
+  if (!g_atomic_pointer_compare_and_exchange (
+          (gpointer) & oclass->elementfactory, NULL, factory))
     gst_object_unref (factory);
 
   if (name)
-    gst_object_set_name (GST_OBJECT (element), name);
+    gst_object_set_name (GST_OBJECT_CAST (element), name);
 
   GST_DEBUG ("created element \"%s\"", GST_PLUGIN_FEATURE_NAME (factory));
 
@@ -453,7 +452,8 @@
   /* ERRORS */
 load_failed:
   {
-    GST_WARNING_OBJECT (factory, "loading plugin returned NULL!");
+    GST_WARNING_OBJECT (factory,
+        "loading plugin containing feature %s returned NULL!", name);
     return NULL;
   }
 no_type:
@@ -503,10 +503,10 @@
 
   GST_LOG_OBJECT (factory, "found factory %p", factory);
   element = gst_element_factory_create (factory, name);
-  gst_object_unref (factory);
   if (element == NULL)
     goto create_failed;
 
+  gst_object_unref (factory);
   return element;
 
   /* ERRORS */
@@ -518,6 +518,7 @@
 create_failed:
   {
     GST_INFO_OBJECT (factory, "couldn't create instance!");
+    gst_object_unref (factory);
     return NULL;
   }
 }
@@ -709,7 +710,7 @@
  * gst_element_factory_get_uri_type:
  * @factory: a #GstElementFactory
  *
- * Gets the type of URIs the element supports or GST_URI_UNKNOWN if none.
+ * Gets the type of URIs the element supports or #GST_URI_UNKNOWN if none.
  *
  * Returns: type of URIs this element supports
  */
--- a/gstreamer_core/gst/gstelementfactory.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstelementfactory.h	Fri Apr 16 15:15:52 2010 +0300
@@ -65,7 +65,7 @@
   gchar *description;
   gchar *author;
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 
--- a/gstreamer_core/gst/gstenumtypes.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstenumtypes.c	Fri Apr 16 15:15:52 2010 +0300
@@ -8,17 +8,6 @@
  
 
 /* enumerations from "gstobject.h" */
-static void
-register_gst_object_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_OBJECT_DISPOSING), "GST_OBJECT_DISPOSING", "disposing" },
-    { C_FLAGS(GST_OBJECT_FLOATING), "GST_OBJECT_FLOATING", "floating" },
-    { C_FLAGS(GST_OBJECT_FLAG_LAST), "GST_OBJECT_FLAG_LAST", "flag-last" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstObjectFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -26,23 +15,23 @@
 GType
 gst_object_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_OBJECT_DISPOSING), "GST_OBJECT_DISPOSING", "disposing" },
+    { C_FLAGS(GST_OBJECT_FLOATING), "GST_OBJECT_FLOATING", "floating" },
+    { C_FLAGS(GST_OBJECT_FLAG_LAST), "GST_OBJECT_FLAG_LAST", "flag-last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_object_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstObjectFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstbin.h" */
-static void
-register_gst_bin_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_BIN_FLAG_LAST), "GST_BIN_FLAG_LAST", "last" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstBinFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -50,17 +39,29 @@
 GType
 gst_bin_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_BIN_FLAG_LAST), "GST_BIN_FLAG_LAST", "last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_bin_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstBinFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstbuffer.h" */
-static void
-register_gst_buffer_flag (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_buffer_flag_get_type (void)
 {
+  static gsize id = 0;
   static const GFlagsValue values[] = {
     { C_FLAGS(GST_BUFFER_FLAG_READONLY), "GST_BUFFER_FLAG_READONLY", "readonly" },
     { C_FLAGS(GST_BUFFER_FLAG_PREROLL), "GST_BUFFER_FLAG_PREROLL", "preroll" },
@@ -68,34 +69,19 @@
     { C_FLAGS(GST_BUFFER_FLAG_IN_CAPS), "GST_BUFFER_FLAG_IN_CAPS", "in-caps" },
     { C_FLAGS(GST_BUFFER_FLAG_GAP), "GST_BUFFER_FLAG_GAP", "gap" },
     { C_FLAGS(GST_BUFFER_FLAG_DELTA_UNIT), "GST_BUFFER_FLAG_DELTA_UNIT", "delta-unit" },
+    { C_FLAGS(GST_BUFFER_FLAG_MEDIA1), "GST_BUFFER_FLAG_MEDIA1", "media1" },
+    { C_FLAGS(GST_BUFFER_FLAG_MEDIA2), "GST_BUFFER_FLAG_MEDIA2", "media2" },
+    { C_FLAGS(GST_BUFFER_FLAG_MEDIA3), "GST_BUFFER_FLAG_MEDIA3", "media3" },
     { C_FLAGS(GST_BUFFER_FLAG_LAST), "GST_BUFFER_FLAG_LAST", "last" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstBufferFlag", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_buffer_flag_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_buffer_flag, &id);
-  return id;
-}
-static void
-register_gst_buffer_copy_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_BUFFER_COPY_FLAGS), "GST_BUFFER_COPY_FLAGS", "flags" },
-    { C_FLAGS(GST_BUFFER_COPY_TIMESTAMPS), "GST_BUFFER_COPY_TIMESTAMPS", "timestamps" },
-    { C_FLAGS(GST_BUFFER_COPY_CAPS), "GST_BUFFER_COPY_CAPS", "caps" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstBufferCopyFlags", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstBufferFlag", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -104,24 +90,47 @@
 GType
 gst_buffer_copy_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_BUFFER_COPY_FLAGS), "GST_BUFFER_COPY_FLAGS", "flags" },
+    { C_FLAGS(GST_BUFFER_COPY_TIMESTAMPS), "GST_BUFFER_COPY_TIMESTAMPS", "timestamps" },
+    { C_FLAGS(GST_BUFFER_COPY_CAPS), "GST_BUFFER_COPY_CAPS", "caps" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstBufferCopyFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
 
-  g_once (&once, (GThreadFunc)register_gst_buffer_copy_flags, &id);
-  return id;
+/* enumerations from "gstbufferlist.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_buffer_list_item_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_BUFFER_LIST_CONTINUE), "GST_BUFFER_LIST_CONTINUE", "continue" },
+    { C_ENUM(GST_BUFFER_LIST_SKIP_GROUP), "GST_BUFFER_LIST_SKIP_GROUP", "skip-group" },
+    { C_ENUM(GST_BUFFER_LIST_END), "GST_BUFFER_LIST_END", "end" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstBufferListItem", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstbus.h" */
-static void
-register_gst_bus_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_BUS_FLUSHING), "GST_BUS_FLUSHING", "flushing" },
-    { C_FLAGS(GST_BUS_FLAG_LAST), "GST_BUS_FLAG_LAST", "flag-last" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstBusFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -129,22 +138,19 @@
 GType
 gst_bus_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_bus_flags, &id);
-  return id;
-}
-static void
-register_gst_bus_sync_reply (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_BUS_DROP), "GST_BUS_DROP", "drop" },
-    { C_ENUM(GST_BUS_PASS), "GST_BUS_PASS", "pass" },
-    { C_ENUM(GST_BUS_ASYNC), "GST_BUS_ASYNC", "async" },
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_BUS_FLUSHING), "GST_BUS_FLUSHING", "flushing" },
+    { C_FLAGS(GST_BUS_FLAG_LAST), "GST_BUS_FLAG_LAST", "flag-last" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstBusSyncReply", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstBusFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -153,23 +159,23 @@
 GType
 gst_bus_sync_reply_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_BUS_DROP), "GST_BUS_DROP", "drop" },
+    { C_ENUM(GST_BUS_PASS), "GST_BUS_PASS", "pass" },
+    { C_ENUM(GST_BUS_ASYNC), "GST_BUS_ASYNC", "async" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_bus_sync_reply, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstBusSyncReply", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstcaps.h" */
-static void
-register_gst_caps_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_CAPS_FLAGS_ANY), "GST_CAPS_FLAGS_ANY", "any" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstCapsFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -177,17 +183,29 @@
 GType
 gst_caps_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_CAPS_FLAGS_ANY), "GST_CAPS_FLAGS_ANY", "any" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_caps_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstCapsFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstclock.h" */
-static void
-register_gst_clock_return (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_clock_return_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_CLOCK_OK), "GST_CLOCK_OK", "ok" },
     { C_ENUM(GST_CLOCK_EARLY), "GST_CLOCK_EARLY", "early" },
@@ -198,30 +216,13 @@
     { C_ENUM(GST_CLOCK_UNSUPPORTED), "GST_CLOCK_UNSUPPORTED", "unsupported" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstClockReturn", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_clock_return_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_clock_return, &id);
-  return id;
-}
-static void
-register_gst_clock_entry_type (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_CLOCK_ENTRY_SINGLE), "GST_CLOCK_ENTRY_SINGLE", "single" },
-    { C_ENUM(GST_CLOCK_ENTRY_PERIODIC), "GST_CLOCK_ENTRY_PERIODIC", "periodic" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstClockEntryType", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstClockReturn", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -230,15 +231,28 @@
 GType
 gst_clock_entry_type_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_CLOCK_ENTRY_SINGLE), "GST_CLOCK_ENTRY_SINGLE", "single" },
+    { C_ENUM(GST_CLOCK_ENTRY_PERIODIC), "GST_CLOCK_ENTRY_PERIODIC", "periodic" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_clock_entry_type, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstClockEntryType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
-static void
-register_gst_clock_flags (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_clock_flags_get_type (void)
 {
+  static gsize id = 0;
   static const GFlagsValue values[] = {
     { C_FLAGS(GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC), "GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC", "can-do-single-sync" },
     { C_FLAGS(GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC), "GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC", "can-do-single-async" },
@@ -249,26 +263,24 @@
     { C_FLAGS(GST_CLOCK_FLAG_LAST), "GST_CLOCK_FLAG_LAST", "last" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstClockFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstClockFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
+
+/* enumerations from "gstdebugutils.h" */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_clock_flags_get_type (void)
+gst_debug_graph_details_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_clock_flags, &id);
-  return id;
-}
-
-/* enumerations from "gstdebugutils.h" */
-static void
-register_gst_debug_graph_details (GType* id)
-{
+  static gsize id = 0;
   static const GFlagsValue values[] = {
     { C_FLAGS(GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE), "GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE", "media-type" },
     { C_FLAGS(GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS), "GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS", "caps-details" },
@@ -277,26 +289,24 @@
     { C_FLAGS(GST_DEBUG_GRAPH_SHOW_ALL), "GST_DEBUG_GRAPH_SHOW_ALL", "all" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstDebugGraphDetails", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstDebugGraphDetails", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
+
+/* enumerations from "gstelement.h" */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_debug_graph_details_get_type (void)
+gst_state_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_debug_graph_details, &id);
-  return id;
-}
-
-/* enumerations from "gstelement.h" */
-static void
-register_gst_state (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_STATE_VOID_PENDING), "GST_STATE_VOID_PENDING", "void-pending" },
     { C_ENUM(GST_STATE_NULL), "GST_STATE_NULL", "null" },
@@ -305,32 +315,13 @@
     { C_ENUM(GST_STATE_PLAYING), "GST_STATE_PLAYING", "playing" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstState", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_state_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_state, &id);
-  return id;
-}
-static void
-register_gst_state_change_return (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_STATE_CHANGE_FAILURE), "GST_STATE_CHANGE_FAILURE", "failure" },
-    { C_ENUM(GST_STATE_CHANGE_SUCCESS), "GST_STATE_CHANGE_SUCCESS", "success" },
-    { C_ENUM(GST_STATE_CHANGE_ASYNC), "GST_STATE_CHANGE_ASYNC", "async" },
-    { C_ENUM(GST_STATE_CHANGE_NO_PREROLL), "GST_STATE_CHANGE_NO_PREROLL", "no-preroll" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstStateChangeReturn", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstState", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -339,15 +330,30 @@
 GType
 gst_state_change_return_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_STATE_CHANGE_FAILURE), "GST_STATE_CHANGE_FAILURE", "failure" },
+    { C_ENUM(GST_STATE_CHANGE_SUCCESS), "GST_STATE_CHANGE_SUCCESS", "success" },
+    { C_ENUM(GST_STATE_CHANGE_ASYNC), "GST_STATE_CHANGE_ASYNC", "async" },
+    { C_ENUM(GST_STATE_CHANGE_NO_PREROLL), "GST_STATE_CHANGE_NO_PREROLL", "no-preroll" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_state_change_return, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstStateChangeReturn", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
-static void
-register_gst_state_change (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_state_change_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_STATE_CHANGE_NULL_TO_READY), "GST_STATE_CHANGE_NULL_TO_READY", "null-to-ready" },
     { C_ENUM(GST_STATE_CHANGE_READY_TO_PAUSED), "GST_STATE_CHANGE_READY_TO_PAUSED", "ready-to-paused" },
@@ -357,32 +363,13 @@
     { C_ENUM(GST_STATE_CHANGE_READY_TO_NULL), "GST_STATE_CHANGE_READY_TO_NULL", "ready-to-null" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstStateChange", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_state_change_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_state_change, &id);
-  return id;
-}
-static void
-register_gst_element_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_ELEMENT_LOCKED_STATE), "GST_ELEMENT_LOCKED_STATE", "locked-state" },
-    { C_FLAGS(GST_ELEMENT_IS_SINK), "GST_ELEMENT_IS_SINK", "is-sink" },
-    { C_FLAGS(GST_ELEMENT_UNPARENTING), "GST_ELEMENT_UNPARENTING", "unparenting" },
-    { C_FLAGS(GST_ELEMENT_FLAG_LAST), "GST_ELEMENT_FLAG_LAST", "flag-last" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstElementFlags", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstStateChange", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -391,17 +378,32 @@
 GType
 gst_element_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_ELEMENT_LOCKED_STATE), "GST_ELEMENT_LOCKED_STATE", "locked-state" },
+    { C_FLAGS(GST_ELEMENT_IS_SINK), "GST_ELEMENT_IS_SINK", "is-sink" },
+    { C_FLAGS(GST_ELEMENT_UNPARENTING), "GST_ELEMENT_UNPARENTING", "unparenting" },
+    { C_FLAGS(GST_ELEMENT_FLAG_LAST), "GST_ELEMENT_FLAG_LAST", "flag-last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_element_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstElementFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gsterror.h" */
-static void
-register_gst_core_error (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_core_error_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_CORE_ERROR_FAILED), "GST_CORE_ERROR_FAILED", "failed" },
     { C_ENUM(GST_CORE_ERROR_TOO_LAZY), "GST_CORE_ERROR_TOO_LAZY", "too-lazy" },
@@ -420,24 +422,22 @@
     { C_ENUM(GST_CORE_ERROR_NUM_ERRORS), "GST_CORE_ERROR_NUM_ERRORS", "num-errors" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstCoreError", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstCoreError", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_core_error_get_type (void)
+gst_library_error_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_core_error, &id);
-  return id;
-}
-static void
-register_gst_library_error (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_LIBRARY_ERROR_FAILED), "GST_LIBRARY_ERROR_FAILED", "failed" },
     { C_ENUM(GST_LIBRARY_ERROR_TOO_LAZY), "GST_LIBRARY_ERROR_TOO_LAZY", "too-lazy" },
@@ -448,24 +448,22 @@
     { C_ENUM(GST_LIBRARY_ERROR_NUM_ERRORS), "GST_LIBRARY_ERROR_NUM_ERRORS", "num-errors" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstLibraryError", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstLibraryError", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_library_error_get_type (void)
+gst_resource_error_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_library_error, &id);
-  return id;
-}
-static void
-register_gst_resource_error (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_RESOURCE_ERROR_FAILED), "GST_RESOURCE_ERROR_FAILED", "failed" },
     { C_ENUM(GST_RESOURCE_ERROR_TOO_LAZY), "GST_RESOURCE_ERROR_TOO_LAZY", "too-lazy" },
@@ -484,24 +482,22 @@
     { C_ENUM(GST_RESOURCE_ERROR_NUM_ERRORS), "GST_RESOURCE_ERROR_NUM_ERRORS", "num-errors" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstResourceError", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstResourceError", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_resource_error_get_type (void)
+gst_stream_error_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_resource_error, &id);
-  return id;
-}
-static void
-register_gst_stream_error (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_STREAM_ERROR_FAILED), "GST_STREAM_ERROR_FAILED", "failed" },
     { C_ENUM(GST_STREAM_ERROR_TOO_LAZY), "GST_STREAM_ERROR_TOO_LAZY", "too-lazy" },
@@ -514,37 +510,21 @@
     { C_ENUM(GST_STREAM_ERROR_DEMUX), "GST_STREAM_ERROR_DEMUX", "demux" },
     { C_ENUM(GST_STREAM_ERROR_MUX), "GST_STREAM_ERROR_MUX", "mux" },
     { C_ENUM(GST_STREAM_ERROR_FORMAT), "GST_STREAM_ERROR_FORMAT", "format" },
+    { C_ENUM(GST_STREAM_ERROR_DECRYPT), "GST_STREAM_ERROR_DECRYPT", "decrypt" },
+    { C_ENUM(GST_STREAM_ERROR_DECRYPT_NOKEY), "GST_STREAM_ERROR_DECRYPT_NOKEY", "decrypt-nokey" },
     { C_ENUM(GST_STREAM_ERROR_NUM_ERRORS), "GST_STREAM_ERROR_NUM_ERRORS", "num-errors" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstStreamError", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-GType
-gst_stream_error_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstStreamError", values);
+    g_once_init_leave (&id, tmp);
+  }
 
-  g_once (&once, (GThreadFunc)register_gst_stream_error, &id);
-  return id;
+  return (GType) id;
 }
 
 /* enumerations from "gstevent.h" */
-static void
-register_gst_event_type_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_EVENT_TYPE_UPSTREAM), "GST_EVENT_TYPE_UPSTREAM", "upstream" },
-    { C_FLAGS(GST_EVENT_TYPE_DOWNSTREAM), "GST_EVENT_TYPE_DOWNSTREAM", "downstream" },
-    { C_FLAGS(GST_EVENT_TYPE_SERIALIZED), "GST_EVENT_TYPE_SERIALIZED", "serialized" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstEventTypeFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -552,15 +532,29 @@
 GType
 gst_event_type_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_EVENT_TYPE_UPSTREAM), "GST_EVENT_TYPE_UPSTREAM", "upstream" },
+    { C_FLAGS(GST_EVENT_TYPE_DOWNSTREAM), "GST_EVENT_TYPE_DOWNSTREAM", "downstream" },
+    { C_FLAGS(GST_EVENT_TYPE_SERIALIZED), "GST_EVENT_TYPE_SERIALIZED", "serialized" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_event_type_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstEventTypeFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
-static void
-register_gst_event_type (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_event_type_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_EVENT_UNKNOWN), "GST_EVENT_UNKNOWN", "unknown" },
     { C_ENUM(GST_EVENT_FLUSH_START), "GST_EVENT_FLUSH_START", "flush-start" },
@@ -573,6 +567,7 @@
     { C_ENUM(GST_EVENT_SEEK), "GST_EVENT_SEEK", "seek" },
     { C_ENUM(GST_EVENT_NAVIGATION), "GST_EVENT_NAVIGATION", "navigation" },
     { C_ENUM(GST_EVENT_LATENCY), "GST_EVENT_LATENCY", "latency" },
+    { C_ENUM(GST_EVENT_STEP), "GST_EVENT_STEP", "step" },
     { C_ENUM(GST_EVENT_CUSTOM_UPSTREAM), "GST_EVENT_CUSTOM_UPSTREAM", "custom-upstream" },
     { C_ENUM(GST_EVENT_CUSTOM_DOWNSTREAM), "GST_EVENT_CUSTOM_DOWNSTREAM", "custom-downstream" },
     { C_ENUM(GST_EVENT_CUSTOM_DOWNSTREAM_OOB), "GST_EVENT_CUSTOM_DOWNSTREAM_OOB", "custom-downstream-oob" },
@@ -580,32 +575,13 @@
     { C_ENUM(GST_EVENT_CUSTOM_BOTH_OOB), "GST_EVENT_CUSTOM_BOTH_OOB", "custom-both-oob" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstEventType", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_event_type_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_event_type, &id);
-  return id;
-}
-static void
-register_gst_seek_type (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_SEEK_TYPE_NONE), "GST_SEEK_TYPE_NONE", "none" },
-    { C_ENUM(GST_SEEK_TYPE_CUR), "GST_SEEK_TYPE_CUR", "cur" },
-    { C_ENUM(GST_SEEK_TYPE_SET), "GST_SEEK_TYPE_SET", "set" },
-    { C_ENUM(GST_SEEK_TYPE_END), "GST_SEEK_TYPE_END", "end" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstSeekType", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstEventType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -614,24 +590,21 @@
 GType
 gst_seek_type_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_seek_type, &id);
-  return id;
-}
-static void
-register_gst_seek_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_SEEK_FLAG_NONE), "GST_SEEK_FLAG_NONE", "none" },
-    { C_FLAGS(GST_SEEK_FLAG_FLUSH), "GST_SEEK_FLAG_FLUSH", "flush" },
-    { C_FLAGS(GST_SEEK_FLAG_ACCURATE), "GST_SEEK_FLAG_ACCURATE", "accurate" },
-    { C_FLAGS(GST_SEEK_FLAG_KEY_UNIT), "GST_SEEK_FLAG_KEY_UNIT", "key-unit" },
-    { C_FLAGS(GST_SEEK_FLAG_SEGMENT), "GST_SEEK_FLAG_SEGMENT", "segment" },
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_SEEK_TYPE_NONE), "GST_SEEK_TYPE_NONE", "none" },
+    { C_ENUM(GST_SEEK_TYPE_CUR), "GST_SEEK_TYPE_CUR", "cur" },
+    { C_ENUM(GST_SEEK_TYPE_SET), "GST_SEEK_TYPE_SET", "set" },
+    { C_ENUM(GST_SEEK_TYPE_END), "GST_SEEK_TYPE_END", "end" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstSeekFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstSeekType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -640,17 +613,34 @@
 GType
 gst_seek_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_SEEK_FLAG_NONE), "GST_SEEK_FLAG_NONE", "none" },
+    { C_FLAGS(GST_SEEK_FLAG_FLUSH), "GST_SEEK_FLAG_FLUSH", "flush" },
+    { C_FLAGS(GST_SEEK_FLAG_ACCURATE), "GST_SEEK_FLAG_ACCURATE", "accurate" },
+    { C_FLAGS(GST_SEEK_FLAG_KEY_UNIT), "GST_SEEK_FLAG_KEY_UNIT", "key-unit" },
+    { C_FLAGS(GST_SEEK_FLAG_SEGMENT), "GST_SEEK_FLAG_SEGMENT", "segment" },
+    { C_FLAGS(GST_SEEK_FLAG_SKIP), "GST_SEEK_FLAG_SKIP", "skip" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_seek_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstSeekFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstformat.h" */
-static void
-register_gst_format (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_format_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_FORMAT_UNDEFINED), "GST_FORMAT_UNDEFINED", "undefined" },
     { C_ENUM(GST_FORMAT_DEFAULT), "GST_FORMAT_DEFAULT", "default" },
@@ -660,34 +650,16 @@
     { C_ENUM(GST_FORMAT_PERCENT), "GST_FORMAT_PERCENT", "percent" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstFormat", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-GType
-gst_format_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstFormat", values);
+    g_once_init_leave (&id, tmp);
+  }
 
-  g_once (&once, (GThreadFunc)register_gst_format, &id);
-  return id;
+  return (GType) id;
 }
 
 /* enumerations from "gstindex.h" */
-static void
-register_gst_index_certainty (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_INDEX_UNKNOWN), "GST_INDEX_UNKNOWN", "unknown" },
-    { C_ENUM(GST_INDEX_CERTAIN), "GST_INDEX_CERTAIN", "certain" },
-    { C_ENUM(GST_INDEX_FUZZY), "GST_INDEX_FUZZY", "fuzzy" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstIndexCertainty", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -695,23 +667,20 @@
 GType
 gst_index_certainty_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_index_certainty, &id);
-  return id;
-}
-static void
-register_gst_index_entry_type (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
-    { C_ENUM(GST_INDEX_ENTRY_ID), "GST_INDEX_ENTRY_ID", "id" },
-    { C_ENUM(GST_INDEX_ENTRY_ASSOCIATION), "GST_INDEX_ENTRY_ASSOCIATION", "association" },
-    { C_ENUM(GST_INDEX_ENTRY_OBJECT), "GST_INDEX_ENTRY_OBJECT", "object" },
-    { C_ENUM(GST_INDEX_ENTRY_FORMAT), "GST_INDEX_ENTRY_FORMAT", "format" },
+    { C_ENUM(GST_INDEX_UNKNOWN), "GST_INDEX_UNKNOWN", "unknown" },
+    { C_ENUM(GST_INDEX_CERTAIN), "GST_INDEX_CERTAIN", "certain" },
+    { C_ENUM(GST_INDEX_FUZZY), "GST_INDEX_FUZZY", "fuzzy" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstIndexEntryType", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstIndexCertainty", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -720,22 +689,21 @@
 GType
 gst_index_entry_type_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_index_entry_type, &id);
-  return id;
-}
-static void
-register_gst_index_lookup_method (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
-    { C_ENUM(GST_INDEX_LOOKUP_EXACT), "GST_INDEX_LOOKUP_EXACT", "exact" },
-    { C_ENUM(GST_INDEX_LOOKUP_BEFORE), "GST_INDEX_LOOKUP_BEFORE", "before" },
-    { C_ENUM(GST_INDEX_LOOKUP_AFTER), "GST_INDEX_LOOKUP_AFTER", "after" },
+    { C_ENUM(GST_INDEX_ENTRY_ID), "GST_INDEX_ENTRY_ID", "id" },
+    { C_ENUM(GST_INDEX_ENTRY_ASSOCIATION), "GST_INDEX_ENTRY_ASSOCIATION", "association" },
+    { C_ENUM(GST_INDEX_ENTRY_OBJECT), "GST_INDEX_ENTRY_OBJECT", "object" },
+    { C_ENUM(GST_INDEX_ENTRY_FORMAT), "GST_INDEX_ENTRY_FORMAT", "format" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstIndexLookupMethod", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstIndexEntryType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -744,23 +712,20 @@
 GType
 gst_index_lookup_method_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_index_lookup_method, &id);
-  return id;
-}
-static void
-register_gst_assoc_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_ASSOCIATION_FLAG_NONE), "GST_ASSOCIATION_FLAG_NONE", "none" },
-    { C_FLAGS(GST_ASSOCIATION_FLAG_KEY_UNIT), "GST_ASSOCIATION_FLAG_KEY_UNIT", "key-unit" },
-    { C_FLAGS(GST_ASSOCIATION_FLAG_DELTA_UNIT), "GST_ASSOCIATION_FLAG_DELTA_UNIT", "delta-unit" },
-    { C_FLAGS(GST_ASSOCIATION_FLAG_LAST), "GST_ASSOCIATION_FLAG_LAST", "last" },
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_INDEX_LOOKUP_EXACT), "GST_INDEX_LOOKUP_EXACT", "exact" },
+    { C_ENUM(GST_INDEX_LOOKUP_BEFORE), "GST_INDEX_LOOKUP_BEFORE", "before" },
+    { C_ENUM(GST_INDEX_LOOKUP_AFTER), "GST_INDEX_LOOKUP_AFTER", "after" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstAssocFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstIndexLookupMethod", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -769,22 +734,21 @@
 GType
 gst_assoc_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_assoc_flags, &id);
-  return id;
-}
-static void
-register_gst_index_resolver_method (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_INDEX_RESOLVER_CUSTOM), "GST_INDEX_RESOLVER_CUSTOM", "custom" },
-    { C_ENUM(GST_INDEX_RESOLVER_GTYPE), "GST_INDEX_RESOLVER_GTYPE", "gtype" },
-    { C_ENUM(GST_INDEX_RESOLVER_PATH), "GST_INDEX_RESOLVER_PATH", "path" },
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_ASSOCIATION_FLAG_NONE), "GST_ASSOCIATION_FLAG_NONE", "none" },
+    { C_FLAGS(GST_ASSOCIATION_FLAG_KEY_UNIT), "GST_ASSOCIATION_FLAG_KEY_UNIT", "key-unit" },
+    { C_FLAGS(GST_ASSOCIATION_FLAG_DELTA_UNIT), "GST_ASSOCIATION_FLAG_DELTA_UNIT", "delta-unit" },
+    { C_FLAGS(GST_ASSOCIATION_FLAG_LAST), "GST_ASSOCIATION_FLAG_LAST", "last" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstIndexResolverMethod", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstAssocFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -793,22 +757,20 @@
 GType
 gst_index_resolver_method_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_index_resolver_method, &id);
-  return id;
-}
-static void
-register_gst_index_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_INDEX_WRITABLE), "GST_INDEX_WRITABLE", "writable" },
-    { C_FLAGS(GST_INDEX_READABLE), "GST_INDEX_READABLE", "readable" },
-    { C_FLAGS(GST_INDEX_FLAG_LAST), "GST_INDEX_FLAG_LAST", "flag-last" },
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_INDEX_RESOLVER_CUSTOM), "GST_INDEX_RESOLVER_CUSTOM", "custom" },
+    { C_ENUM(GST_INDEX_RESOLVER_GTYPE), "GST_INDEX_RESOLVER_GTYPE", "gtype" },
+    { C_ENUM(GST_INDEX_RESOLVER_PATH), "GST_INDEX_RESOLVER_PATH", "path" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstIndexFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstIndexResolverMethod", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -817,17 +779,31 @@
 GType
 gst_index_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_INDEX_WRITABLE), "GST_INDEX_WRITABLE", "writable" },
+    { C_FLAGS(GST_INDEX_READABLE), "GST_INDEX_READABLE", "readable" },
+    { C_FLAGS(GST_INDEX_FLAG_LAST), "GST_INDEX_FLAG_LAST", "flag-last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_index_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstIndexFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstinfo.h" */
-static void
-register_gst_debug_level (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_debug_level_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_LEVEL_NONE), "GST_LEVEL_NONE", "none" },
     { C_ENUM(GST_LEVEL_ERROR), "GST_LEVEL_ERROR", "error" },
@@ -835,27 +811,27 @@
     { C_ENUM(GST_LEVEL_INFO), "GST_LEVEL_INFO", "info" },
     { C_ENUM(GST_LEVEL_DEBUG), "GST_LEVEL_DEBUG", "debug" },
     { C_ENUM(GST_LEVEL_LOG), "GST_LEVEL_LOG", "log" },
+    { C_ENUM(GST_LEVEL_FIXME), "GST_LEVEL_FIXME", "fixme" },
+    { C_ENUM(GST_LEVEL_MEMDUMP), "GST_LEVEL_MEMDUMP", "memdump" },
     { C_ENUM(GST_LEVEL_COUNT), "GST_LEVEL_COUNT", "count" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstDebugLevel", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstDebugLevel", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_debug_level_get_type (void)
+gst_debug_color_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_debug_level, &id);
-  return id;
-}
-static void
-register_gst_debug_color_flags (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_DEBUG_FG_BLACK), "GST_DEBUG_FG_BLACK", "fg-black" },
     { C_ENUM(GST_DEBUG_FG_RED), "GST_DEBUG_FG_RED", "fg-red" },
@@ -877,26 +853,24 @@
     { C_ENUM(GST_DEBUG_UNDERLINE), "GST_DEBUG_UNDERLINE", "underline" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstDebugColorFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstDebugColorFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
+
+/* enumerations from "gstiterator.h" */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_debug_color_flags_get_type (void)
+gst_iterator_result_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_debug_color_flags, &id);
-  return id;
-}
-
-/* enumerations from "gstiterator.h" */
-static void
-register_gst_iterator_result (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_ITERATOR_DONE), "GST_ITERATOR_DONE", "done" },
     { C_ENUM(GST_ITERATOR_OK), "GST_ITERATOR_OK", "ok" },
@@ -904,31 +878,13 @@
     { C_ENUM(GST_ITERATOR_ERROR), "GST_ITERATOR_ERROR", "error" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstIteratorResult", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_iterator_result_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_iterator_result, &id);
-  return id;
-}
-static void
-register_gst_iterator_item (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_ITERATOR_ITEM_SKIP), "GST_ITERATOR_ITEM_SKIP", "skip" },
-    { C_ENUM(GST_ITERATOR_ITEM_PASS), "GST_ITERATOR_ITEM_PASS", "pass" },
-    { C_ENUM(GST_ITERATOR_ITEM_END), "GST_ITERATOR_ITEM_END", "end" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstIteratorItem", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstIteratorResult", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -937,17 +893,31 @@
 GType
 gst_iterator_item_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_ITERATOR_ITEM_SKIP), "GST_ITERATOR_ITEM_SKIP", "skip" },
+    { C_ENUM(GST_ITERATOR_ITEM_PASS), "GST_ITERATOR_ITEM_PASS", "pass" },
+    { C_ENUM(GST_ITERATOR_ITEM_END), "GST_ITERATOR_ITEM_END", "end" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_iterator_item, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstIteratorItem", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstmessage.h" */
-static void
-register_gst_message_type (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_message_type_get_type (void)
 {
+  static gsize id = 0;
   static const GFlagsValue values[] = {
     { C_FLAGS(GST_MESSAGE_UNKNOWN), "GST_MESSAGE_UNKNOWN", "unknown" },
     { C_FLAGS(GST_MESSAGE_EOS), "GST_MESSAGE_EOS", "eos" },
@@ -972,36 +942,68 @@
     { C_FLAGS(GST_MESSAGE_LATENCY), "GST_MESSAGE_LATENCY", "latency" },
     { C_FLAGS(GST_MESSAGE_ASYNC_START), "GST_MESSAGE_ASYNC_START", "async-start" },
     { C_FLAGS(GST_MESSAGE_ASYNC_DONE), "GST_MESSAGE_ASYNC_DONE", "async-done" },
+    { C_FLAGS(GST_MESSAGE_REQUEST_STATE), "GST_MESSAGE_REQUEST_STATE", "request-state" },
+    { C_FLAGS(GST_MESSAGE_STEP_START), "GST_MESSAGE_STEP_START", "step-start" },
     { C_FLAGS(GST_MESSAGE_ANY), "GST_MESSAGE_ANY", "any" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstMessageType", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstMessageType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_message_type_get_type (void)
+gst_structure_change_type_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_STRUCTURE_CHANGE_TYPE_PAD_LINK), "GST_STRUCTURE_CHANGE_TYPE_PAD_LINK", "link" },
+    { C_ENUM(GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK), "GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK", "unlink" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstStructureChangeType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-  g_once (&once, (GThreadFunc)register_gst_message_type, &id);
-  return id;
+GType
+gst_stream_status_type_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_STREAM_STATUS_TYPE_CREATE), "GST_STREAM_STATUS_TYPE_CREATE", "create" },
+    { C_ENUM(GST_STREAM_STATUS_TYPE_ENTER), "GST_STREAM_STATUS_TYPE_ENTER", "enter" },
+    { C_ENUM(GST_STREAM_STATUS_TYPE_LEAVE), "GST_STREAM_STATUS_TYPE_LEAVE", "leave" },
+    { C_ENUM(GST_STREAM_STATUS_TYPE_DESTROY), "GST_STREAM_STATUS_TYPE_DESTROY", "destroy" },
+    { C_ENUM(GST_STREAM_STATUS_TYPE_START), "GST_STREAM_STATUS_TYPE_START", "start" },
+    { C_ENUM(GST_STREAM_STATUS_TYPE_PAUSE), "GST_STREAM_STATUS_TYPE_PAUSE", "pause" },
+    { C_ENUM(GST_STREAM_STATUS_TYPE_STOP), "GST_STREAM_STATUS_TYPE_STOP", "stop" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstStreamStatusType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstminiobject.h" */
-static void
-register_gst_mini_object_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_MINI_OBJECT_FLAG_READONLY), "GST_MINI_OBJECT_FLAG_READONLY", "readonly" },
-    { C_FLAGS(GST_MINI_OBJECT_FLAG_LAST), "GST_MINI_OBJECT_FLAG_LAST", "last" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstMiniObjectFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1009,17 +1011,30 @@
 GType
 gst_mini_object_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_MINI_OBJECT_FLAG_READONLY), "GST_MINI_OBJECT_FLAG_READONLY", "readonly" },
+    { C_FLAGS(GST_MINI_OBJECT_FLAG_LAST), "GST_MINI_OBJECT_FLAG_LAST", "last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_mini_object_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstMiniObjectFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstpad.h" */
-static void
-register_gst_pad_link_return (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_pad_link_return_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_PAD_LINK_OK), "GST_PAD_LINK_OK", "ok" },
     { C_ENUM(GST_PAD_LINK_WRONG_HIERARCHY), "GST_PAD_LINK_WRONG_HIERARCHY", "wrong-hierarchy" },
@@ -1030,24 +1045,22 @@
     { C_ENUM(GST_PAD_LINK_REFUSED), "GST_PAD_LINK_REFUSED", "refused" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstPadLinkReturn", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstPadLinkReturn", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_pad_link_return_get_type (void)
+gst_flow_return_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_pad_link_return, &id);
-  return id;
-}
-static void
-register_gst_flow_return (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_FLOW_CUSTOM_SUCCESS), "GST_FLOW_CUSTOM_SUCCESS", "custom-success" },
     { C_ENUM(GST_FLOW_RESEND), "GST_FLOW_RESEND", "resend" },
@@ -1061,31 +1074,13 @@
     { C_ENUM(GST_FLOW_CUSTOM_ERROR), "GST_FLOW_CUSTOM_ERROR", "custom-error" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstFlowReturn", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_flow_return_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_flow_return, &id);
-  return id;
-}
-static void
-register_gst_activate_mode (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_ACTIVATE_NONE), "GST_ACTIVATE_NONE", "none" },
-    { C_ENUM(GST_ACTIVATE_PUSH), "GST_ACTIVATE_PUSH", "push" },
-    { C_ENUM(GST_ACTIVATE_PULL), "GST_ACTIVATE_PULL", "pull" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstActivateMode", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstFlowReturn", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1094,22 +1089,20 @@
 GType
 gst_activate_mode_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_activate_mode, &id);
-  return id;
-}
-static void
-register_gst_pad_direction (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
-    { C_ENUM(GST_PAD_UNKNOWN), "GST_PAD_UNKNOWN", "unknown" },
-    { C_ENUM(GST_PAD_SRC), "GST_PAD_SRC", "src" },
-    { C_ENUM(GST_PAD_SINK), "GST_PAD_SINK", "sink" },
+    { C_ENUM(GST_ACTIVATE_NONE), "GST_ACTIVATE_NONE", "none" },
+    { C_ENUM(GST_ACTIVATE_PUSH), "GST_ACTIVATE_PUSH", "push" },
+    { C_ENUM(GST_ACTIVATE_PULL), "GST_ACTIVATE_PULL", "pull" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstPadDirection", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstActivateMode", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1118,15 +1111,29 @@
 GType
 gst_pad_direction_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_PAD_UNKNOWN), "GST_PAD_UNKNOWN", "unknown" },
+    { C_ENUM(GST_PAD_SRC), "GST_PAD_SRC", "src" },
+    { C_ENUM(GST_PAD_SINK), "GST_PAD_SINK", "sink" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_pad_direction, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstPadDirection", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
-static void
-register_gst_pad_flags (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_pad_flags_get_type (void)
 {
+  static gsize id = 0;
   static const GFlagsValue values[] = {
     { C_FLAGS(GST_PAD_BLOCKED), "GST_PAD_BLOCKED", "blocked" },
     { C_FLAGS(GST_PAD_FLUSHING), "GST_PAD_FLUSHING", "flushing" },
@@ -1136,34 +1143,16 @@
     { C_FLAGS(GST_PAD_FLAG_LAST), "GST_PAD_FLAG_LAST", "flag-last" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstPadFlags", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-GType
-gst_pad_flags_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstPadFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
 
-  g_once (&once, (GThreadFunc)register_gst_pad_flags, &id);
-  return id;
+  return (GType) id;
 }
 
 /* enumerations from "gstpadtemplate.h" */
-static void
-register_gst_pad_presence (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_PAD_ALWAYS), "GST_PAD_ALWAYS", "always" },
-    { C_ENUM(GST_PAD_SOMETIMES), "GST_PAD_SOMETIMES", "sometimes" },
-    { C_ENUM(GST_PAD_REQUEST), "GST_PAD_REQUEST", "request" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstPadPresence", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1171,21 +1160,20 @@
 GType
 gst_pad_presence_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_pad_presence, &id);
-  return id;
-}
-static void
-register_gst_pad_template_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_PAD_TEMPLATE_FIXED), "GST_PAD_TEMPLATE_FIXED", "fixed" },
-    { C_FLAGS(GST_PAD_TEMPLATE_FLAG_LAST), "GST_PAD_TEMPLATE_FLAG_LAST", "flag-last" },
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_PAD_ALWAYS), "GST_PAD_ALWAYS", "always" },
+    { C_ENUM(GST_PAD_SOMETIMES), "GST_PAD_SOMETIMES", "sometimes" },
+    { C_ENUM(GST_PAD_REQUEST), "GST_PAD_REQUEST", "request" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstPadTemplateFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstPadPresence", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1194,24 +1182,22 @@
 GType
 gst_pad_template_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_PAD_TEMPLATE_FIXED), "GST_PAD_TEMPLATE_FIXED", "fixed" },
+    { C_FLAGS(GST_PAD_TEMPLATE_FLAG_LAST), "GST_PAD_TEMPLATE_FLAG_LAST", "flag-last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_pad_template_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstPadTemplateFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstpipeline.h" */
-static void
-register_gst_pipeline_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_PIPELINE_FLAG_FIXED_CLOCK), "GST_PIPELINE_FLAG_FIXED_CLOCK", "fixed-clock" },
-    { C_FLAGS(GST_PIPELINE_FLAG_LAST), "GST_PIPELINE_FLAG_LAST", "last" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstPipelineFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1219,25 +1205,22 @@
 GType
 gst_pipeline_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_PIPELINE_FLAG_FIXED_CLOCK), "GST_PIPELINE_FLAG_FIXED_CLOCK", "fixed-clock" },
+    { C_FLAGS(GST_PIPELINE_FLAG_LAST), "GST_PIPELINE_FLAG_LAST", "last" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_pipeline_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstPipelineFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstplugin.h" */
-static void
-register_gst_plugin_error (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_PLUGIN_ERROR_MODULE), "GST_PLUGIN_ERROR_MODULE", "module" },
-    { C_ENUM(GST_PLUGIN_ERROR_DEPENDENCIES), "GST_PLUGIN_ERROR_DEPENDENCIES", "dependencies" },
-    { C_ENUM(GST_PLUGIN_ERROR_NAME_MISMATCH), "GST_PLUGIN_ERROR_NAME_MISMATCH", "name-mismatch" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstPluginError", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1245,20 +1228,20 @@
 GType
 gst_plugin_error_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_plugin_error, &id);
-  return id;
-}
-static void
-register_gst_plugin_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_PLUGIN_FLAG_CACHED), "GST_PLUGIN_FLAG_CACHED", "cached" },
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_PLUGIN_ERROR_MODULE), "GST_PLUGIN_ERROR_MODULE", "module" },
+    { C_ENUM(GST_PLUGIN_ERROR_DEPENDENCIES), "GST_PLUGIN_ERROR_DEPENDENCIES", "dependencies" },
+    { C_ENUM(GST_PLUGIN_ERROR_NAME_MISMATCH), "GST_PLUGIN_ERROR_NAME_MISMATCH", "name-mismatch" },
     { 0, NULL, NULL }
   };
-  *id = g_flags_register_static ("GstPluginFlags", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstPluginError", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1267,17 +1250,52 @@
 GType
 gst_plugin_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_PLUGIN_FLAG_CACHED), "GST_PLUGIN_FLAG_CACHED", "cached" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstPluginFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-  g_once (&once, (GThreadFunc)register_gst_plugin_flags, &id);
-  return id;
+GType
+gst_plugin_dependency_flags_get_type (void)
+{
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_PLUGIN_DEPENDENCY_FLAG_NONE), "GST_PLUGIN_DEPENDENCY_FLAG_NONE", "none" },
+    { C_FLAGS(GST_PLUGIN_DEPENDENCY_FLAG_RECURSE), "GST_PLUGIN_DEPENDENCY_FLAG_RECURSE", "recurse" },
+    { C_FLAGS(GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY), "GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY", "paths-are-default-only" },
+    { C_FLAGS(GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX), "GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX", "file-name-is-suffix" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstPluginDependencyFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstpluginfeature.h" */
-static void
-register_gst_rank (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_rank_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_RANK_NONE), "GST_RANK_NONE", "none" },
     { C_ENUM(GST_RANK_MARGINAL), "GST_RANK_MARGINAL", "marginal" },
@@ -1285,26 +1303,24 @@
     { C_ENUM(GST_RANK_PRIMARY), "GST_RANK_PRIMARY", "primary" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstRank", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstRank", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
+
+/* enumerations from "gstquery.h" */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_rank_get_type (void)
+gst_query_type_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
-
-  g_once (&once, (GThreadFunc)register_gst_rank, &id);
-  return id;
-}
-
-/* enumerations from "gstquery.h" */
-static void
-register_gst_query_type (GType* id)
-{
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_QUERY_NONE), "GST_QUERY_NONE", "none" },
     { C_ENUM(GST_QUERY_POSITION), "GST_QUERY_POSITION", "position" },
@@ -1316,28 +1332,75 @@
     { C_ENUM(GST_QUERY_SEGMENT), "GST_QUERY_SEGMENT", "segment" },
     { C_ENUM(GST_QUERY_CONVERT), "GST_QUERY_CONVERT", "convert" },
     { C_ENUM(GST_QUERY_FORMATS), "GST_QUERY_FORMATS", "formats" },
+    { C_ENUM(GST_QUERY_BUFFERING), "GST_QUERY_BUFFERING", "buffering" },
+    { C_ENUM(GST_QUERY_CUSTOM), "GST_QUERY_CUSTOM", "custom" },
+    { C_ENUM(GST_QUERY_URI), "GST_QUERY_URI", "uri" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstQueryType", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstQueryType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_query_type_get_type (void)
+gst_buffering_mode_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_BUFFERING_STREAM), "GST_BUFFERING_STREAM", "stream" },
+    { C_ENUM(GST_BUFFERING_DOWNLOAD), "GST_BUFFERING_DOWNLOAD", "download" },
+    { C_ENUM(GST_BUFFERING_TIMESHIFT), "GST_BUFFERING_TIMESHIFT", "timeshift" },
+    { C_ENUM(GST_BUFFERING_LIVE), "GST_BUFFERING_LIVE", "live" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstBufferingMode", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
 
-  g_once (&once, (GThreadFunc)register_gst_query_type, &id);
-  return id;
+/* enumerations from "gstsystemclock.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_clock_type_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_CLOCK_TYPE_REALTIME), "GST_CLOCK_TYPE_REALTIME", "realtime" },
+    { C_ENUM(GST_CLOCK_TYPE_MONOTONIC), "GST_CLOCK_TYPE_MONOTONIC", "monotonic" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstClockType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gsttaglist.h" */
-static void
-register_gst_tag_merge_mode (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_tag_merge_mode_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_TAG_MERGE_UNDEFINED), "GST_TAG_MERGE_UNDEFINED", "undefined" },
     { C_ENUM(GST_TAG_MERGE_REPLACE_ALL), "GST_TAG_MERGE_REPLACE_ALL", "replace-all" },
@@ -1349,33 +1412,13 @@
     { C_ENUM(GST_TAG_MERGE_COUNT), "GST_TAG_MERGE_COUNT", "count" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstTagMergeMode", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GType
-gst_tag_merge_mode_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
 
-  g_once (&once, (GThreadFunc)register_gst_tag_merge_mode, &id);
-  return id;
-}
-static void
-register_gst_tag_flag (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_TAG_FLAG_UNDEFINED), "GST_TAG_FLAG_UNDEFINED", "undefined" },
-    { C_ENUM(GST_TAG_FLAG_META), "GST_TAG_FLAG_META", "meta" },
-    { C_ENUM(GST_TAG_FLAG_ENCODED), "GST_TAG_FLAG_ENCODED", "encoded" },
-    { C_ENUM(GST_TAG_FLAG_DECODED), "GST_TAG_FLAG_DECODED", "decoded" },
-    { C_ENUM(GST_TAG_FLAG_COUNT), "GST_TAG_FLAG_COUNT", "count" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstTagFlag", values);
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstTagMergeMode", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1384,25 +1427,25 @@
 GType
 gst_tag_flag_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_TAG_FLAG_UNDEFINED), "GST_TAG_FLAG_UNDEFINED", "undefined" },
+    { C_ENUM(GST_TAG_FLAG_META), "GST_TAG_FLAG_META", "meta" },
+    { C_ENUM(GST_TAG_FLAG_ENCODED), "GST_TAG_FLAG_ENCODED", "encoded" },
+    { C_ENUM(GST_TAG_FLAG_DECODED), "GST_TAG_FLAG_DECODED", "decoded" },
+    { C_ENUM(GST_TAG_FLAG_COUNT), "GST_TAG_FLAG_COUNT", "count" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_tag_flag, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstTagFlag", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gsttask.h" */
-static void
-register_gst_task_state (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_TASK_STARTED), "GST_TASK_STARTED", "started" },
-    { C_ENUM(GST_TASK_STOPPED), "GST_TASK_STOPPED", "stopped" },
-    { C_ENUM(GST_TASK_PAUSED), "GST_TASK_PAUSED", "paused" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstTaskState", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1410,24 +1453,23 @@
 GType
 gst_task_state_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_TASK_STARTED), "GST_TASK_STARTED", "started" },
+    { C_ENUM(GST_TASK_STOPPED), "GST_TASK_STOPPED", "stopped" },
+    { C_ENUM(GST_TASK_PAUSED), "GST_TASK_PAUSED", "paused" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_task_state, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstTaskState", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gsttrace.h" */
-static void
-register_gst_alloc_trace_flags (GType* id)
-{
-  static const GFlagsValue values[] = {
-    { C_FLAGS(GST_ALLOC_TRACE_LIVE), "GST_ALLOC_TRACE_LIVE", "live" },
-    { C_FLAGS(GST_ALLOC_TRACE_MEM_LIVE), "GST_ALLOC_TRACE_MEM_LIVE", "mem-live" },
-    { 0, NULL, NULL }
-  };
-  *id = g_flags_register_static ("GstAllocTraceFlags", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1435,17 +1477,30 @@
 GType
 gst_alloc_trace_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_ALLOC_TRACE_LIVE), "GST_ALLOC_TRACE_LIVE", "live" },
+    { C_FLAGS(GST_ALLOC_TRACE_MEM_LIVE), "GST_ALLOC_TRACE_MEM_LIVE", "mem-live" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_alloc_trace_flags, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstAllocTraceFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gsttypefind.h" */
-static void
-register_gst_type_find_probability (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_type_find_probability_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_TYPE_FIND_MINIMUM), "GST_TYPE_FIND_MINIMUM", "minimum" },
     { C_ENUM(GST_TYPE_FIND_POSSIBLE), "GST_TYPE_FIND_POSSIBLE", "possible" },
@@ -1454,34 +1509,16 @@
     { C_ENUM(GST_TYPE_FIND_MAXIMUM), "GST_TYPE_FIND_MAXIMUM", "maximum" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstTypeFindProbability", values);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-GType
-gst_type_find_probability_get_type (void)
-{
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstTypeFindProbability", values);
+    g_once_init_leave (&id, tmp);
+  }
 
-  g_once (&once, (GThreadFunc)register_gst_type_find_probability, &id);
-  return id;
+  return (GType) id;
 }
 
 /* enumerations from "gsturi.h" */
-static void
-register_gst_uri_type (GType* id)
-{
-  static const GEnumValue values[] = {
-    { C_ENUM(GST_URI_UNKNOWN), "GST_URI_UNKNOWN", "unknown" },
-    { C_ENUM(GST_URI_SINK), "GST_URI_SINK", "sink" },
-    { C_ENUM(GST_URI_SRC), "GST_URI_SRC", "src" },
-    { 0, NULL, NULL }
-  };
-  *id = g_enum_register_static ("GstURIType", values);
-}
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1489,17 +1526,55 @@
 GType
 gst_uri_type_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_URI_UNKNOWN), "GST_URI_UNKNOWN", "unknown" },
+    { C_ENUM(GST_URI_SINK), "GST_URI_SINK", "sink" },
+    { C_ENUM(GST_URI_SRC), "GST_URI_SRC", "src" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstURIType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
 
-  g_once (&once, (GThreadFunc)register_gst_uri_type, &id);
-  return id;
+/* enumerations from "gstutils.h" */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_search_mode_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    { C_ENUM(GST_SEARCH_MODE_EXACT), "GST_SEARCH_MODE_EXACT", "exact" },
+    { C_ENUM(GST_SEARCH_MODE_BEFORE), "GST_SEARCH_MODE_BEFORE", "before" },
+    { C_ENUM(GST_SEARCH_MODE_AFTER), "GST_SEARCH_MODE_AFTER", "after" },
+    { 0, NULL, NULL }
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstSearchMode", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* enumerations from "gstparse.h" */
-static void
-register_gst_parse_error (GType* id)
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GType
+gst_parse_error_get_type (void)
 {
+  static gsize id = 0;
   static const GEnumValue values[] = {
     { C_ENUM(GST_PARSE_ERROR_SYNTAX), "GST_PARSE_ERROR_SYNTAX", "syntax" },
     { C_ENUM(GST_PARSE_ERROR_NO_SUCH_ELEMENT), "GST_PARSE_ERROR_NO_SUCH_ELEMENT", "no-such-element" },
@@ -1510,20 +1585,34 @@
     { C_ENUM(GST_PARSE_ERROR_EMPTY), "GST_PARSE_ERROR_EMPTY", "empty" },
     { 0, NULL, NULL }
   };
-  *id = g_enum_register_static ("GstParseError", values);
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstParseError", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GType
-gst_parse_error_get_type (void)
+gst_parse_flags_get_type (void)
 {
-  static GType id;
-  static GOnce once = G_ONCE_INIT;
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    { C_FLAGS(GST_PARSE_FLAG_NONE), "GST_PARSE_FLAG_NONE", "none" },
+    { C_FLAGS(GST_PARSE_FLAG_FATAL_ERRORS), "GST_PARSE_FLAG_FATAL_ERRORS", "fatal-errors" },
+    { 0, NULL, NULL }
+  };
 
-  g_once (&once, (GThreadFunc)register_gst_parse_error, &id);
-  return id;
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstParseFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
 }
 
 /* Generated data ends here */
--- a/gstreamer_core/gst/gstenumtypes.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstenumtypes.h	Fri Apr 16 15:15:52 2010 +0300
@@ -34,6 +34,14 @@
 GType gst_buffer_copy_flags_get_type (void);
 #define GST_TYPE_BUFFER_COPY_FLAGS (gst_buffer_copy_flags_get_type())
 
+/* enumerations from "gstbufferlist.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_buffer_list_item_get_type (void);
+#define GST_TYPE_BUFFER_LIST_ITEM (gst_buffer_list_item_get_type())
+
 /* enumerations from "gstbus.h" */
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -167,6 +175,10 @@
 
 GType gst_message_type_get_type (void);
 #define GST_TYPE_MESSAGE_TYPE (gst_message_type_get_type())
+GType gst_structure_change_type_get_type (void);
+#define GST_TYPE_STRUCTURE_CHANGE_TYPE (gst_structure_change_type_get_type())
+GType gst_stream_status_type_get_type (void);
+#define GST_TYPE_STREAM_STATUS_TYPE (gst_stream_status_type_get_type())
 
 /* enumerations from "gstminiobject.h" */
 #ifdef __SYMBIAN32__
@@ -219,6 +231,8 @@
 #define GST_TYPE_PLUGIN_ERROR (gst_plugin_error_get_type())
 GType gst_plugin_flags_get_type (void);
 #define GST_TYPE_PLUGIN_FLAGS (gst_plugin_flags_get_type())
+GType gst_plugin_dependency_flags_get_type (void);
+#define GST_TYPE_PLUGIN_DEPENDENCY_FLAGS (gst_plugin_dependency_flags_get_type())
 
 /* enumerations from "gstpluginfeature.h" */
 #ifdef __SYMBIAN32__
@@ -235,6 +249,16 @@
 
 GType gst_query_type_get_type (void);
 #define GST_TYPE_QUERY_TYPE (gst_query_type_get_type())
+GType gst_buffering_mode_get_type (void);
+#define GST_TYPE_BUFFERING_MODE (gst_buffering_mode_get_type())
+
+/* enumerations from "gstsystemclock.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_clock_type_get_type (void);
+#define GST_TYPE_CLOCK_TYPE (gst_clock_type_get_type())
 
 /* enumerations from "gsttaglist.h" */
 #ifdef __SYMBIAN32__
@@ -278,6 +302,14 @@
 GType gst_uri_type_get_type (void);
 #define GST_TYPE_URI_TYPE (gst_uri_type_get_type())
 
+/* enumerations from "gstutils.h" */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GType gst_search_mode_get_type (void);
+#define GST_TYPE_SEARCH_MODE (gst_search_mode_get_type())
+
 /* enumerations from "gstparse.h" */
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -285,6 +317,8 @@
 
 GType gst_parse_error_get_type (void);
 #define GST_TYPE_PARSE_ERROR (gst_parse_error_get_type())
+GType gst_parse_flags_get_type (void);
+#define GST_TYPE_PARSE_FLAGS (gst_parse_flags_get_type())
 G_END_DECLS
 
 #endif /* __GST_ENUM_TYPES_H__ */
--- a/gstreamer_core/gst/gsterror.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsterror.c	Fri Apr 16 15:15:52 2010 +0300
@@ -147,7 +147,8 @@
   TABLE (t, CORE, NOT_IMPLEMENTED,
       N_("Internal GStreamer error: code not implemented." FILE_A_BUG));
   TABLE (t, CORE, STATE_CHANGE,
-      N_("Internal GStreamer error: state change failed." FILE_A_BUG));
+      N_("GStreamer error: state change failed and some element failed to "
+          "post a proper error message with the reason for the failure."));
   TABLE (t, CORE, PAD, N_("Internal GStreamer error: pad problem." FILE_A_BUG));
   TABLE (t, CORE, THREAD,
       N_("Internal GStreamer error: thread problem." FILE_A_BUG));
@@ -248,6 +249,11 @@
   TABLE (t, STREAM, DEMUX, N_("Could not demultiplex stream."));
   TABLE (t, STREAM, MUX, N_("Could not multiplex stream."));
   TABLE (t, STREAM, FORMAT, N_("The stream is in the wrong format."));
+  TABLE (t, STREAM, DECRYPT,
+      N_("The stream is encrypted and decryption is not supported."));
+  TABLE (t, STREAM, DECRYPT_NOKEY,
+      N_("The stream is encrypted and can't be decrypted because no suitable "
+          "key has been supplied."));
 
   return t;
 }
--- a/gstreamer_core/gst/gsterror.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsterror.h	Fri Apr 16 15:15:52 2010 +0300
@@ -169,6 +169,10 @@
  * @GST_STREAM_ERROR_MUX: used when muxing fails.
  * @GST_STREAM_ERROR_FORMAT: used when the stream is of the wrong format
  * (for example, wrong caps).
+ * @GST_STREAM_ERROR_DECRYPT: used when the stream is encrypted and can't be
+ * decrypted because this is not supported by the element. (Since: 0.10.20)
+ * @GST_STREAM_ERROR_DECRYPT_NOKEY: used when the stream is encrypted and
+ * can't be decrypted because no suitable key is available. (Since: 0.10.20)
  * @GST_STREAM_ERROR_NUM_ERRORS: the number of stream error types.
  *
  * Stream errors are for anything related to the stream being processed:
@@ -188,6 +192,8 @@
   GST_STREAM_ERROR_DEMUX,
   GST_STREAM_ERROR_MUX,
   GST_STREAM_ERROR_FORMAT,
+  GST_STREAM_ERROR_DECRYPT,
+  GST_STREAM_ERROR_DECRYPT_NOKEY,
   GST_STREAM_ERROR_NUM_ERRORS
 } GstStreamError;
 
--- a/gstreamer_core/gst/gstevent.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstevent.c	Fri Apr 16 15:15:52 2010 +0300
@@ -83,9 +83,10 @@
 #include "gstevent.h"
 #include "gstenumtypes.h"
 #include "gstutils.h"
+#include "gstquark.h"
 
-static void gst_event_init (GTypeInstance * instance, gpointer g_class);
-static void gst_event_class_init (gpointer g_class, gpointer class_data);
+#define GST_EVENT_SEQNUM(e) ((GstEvent*)e)->abidata.seqnum
+
 static void gst_event_finalize (GstEvent * event);
 static GstEvent *_gst_event_copy (GstEvent * event);
 
@@ -200,62 +201,31 @@
 
   return ret;
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_event_get_type (void)
-{
-  static GType _gst_event_type = 0;
-  int i;
-
-  if (G_UNLIKELY (_gst_event_type == 0)) {
-    static const GTypeInfo event_info = {
-      sizeof (GstEventClass),
-      NULL,
-      NULL,
-      gst_event_class_init,
-      NULL,
-      NULL,
-      sizeof (GstEvent),
-      0,
-      gst_event_init,
-      NULL
-    };
-
-    _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
-        "GstEvent", &event_info, 0);
-
-    for (i = 0; event_quarks[i].name; i++) {
-      event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
-    }
-  }
-
-  return _gst_event_type;
+#define _do_init \
+{ \
+  gint i; \
+  \
+  for (i = 0; event_quarks[i].name; i++) { \
+    event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name); \
+  } \
 }
 
-static void
-gst_event_class_init (gpointer g_class, gpointer class_data)
-{
-  GstEventClass *event_class = GST_EVENT_CLASS (g_class);
+G_DEFINE_TYPE_WITH_CODE (GstEvent, gst_event, GST_TYPE_MINI_OBJECT, _do_init);
 
-  parent_class = g_type_class_peek_parent (g_class);
+static void
+gst_event_class_init (GstEventClass * klass)
+{
+  parent_class = g_type_class_peek_parent (klass);
 
-  event_class->mini_object_class.copy =
-      (GstMiniObjectCopyFunction) _gst_event_copy;
-  event_class->mini_object_class.finalize =
+  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
+  klass->mini_object_class.finalize =
       (GstMiniObjectFinalizeFunction) gst_event_finalize;
 }
 
 static void
-gst_event_init (GTypeInstance * instance, gpointer g_class)
+gst_event_init (GstEvent * event)
 {
-  GstEvent *event;
-
-  event = GST_EVENT (instance);
-
   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
 }
 
@@ -277,7 +247,7 @@
     gst_structure_free (event->structure);
   }
 
-  GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (event));
+/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (event)); */
 }
 
 static GstEvent *
@@ -289,6 +259,7 @@
 
   GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
+  GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event);
 
   if (GST_EVENT_SRC (event)) {
     GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
@@ -314,6 +285,7 @@
   event->type = type;
   event->src = NULL;
   event->structure = NULL;
+  GST_EVENT_SEQNUM (event) = gst_util_seqnum_next ();
 
   return event;
 }
@@ -383,6 +355,95 @@
 }
 
 /**
+ * gst_event_has_name:
+ * @event: The #GstEvent.
+ * @name: name to check
+ *
+ * Checks if @event has the given @name. This function is usually used to
+ * check the name of a custom event.
+ *
+ * Returns: %TRUE if @name matches the name of the event structure.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_event_has_name (GstEvent * event, const gchar * name)
+{
+  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
+
+  if (event->structure == NULL)
+    return FALSE;
+
+  return gst_structure_has_name (event->structure, name);
+}
+
+/**
+ * gst_event_get_seqnum:
+ * @event: A #GstEvent.
+ *
+ * Retrieve the sequence number of a event.
+ *
+ * Events have ever-incrementing sequence numbers, which may also be set
+ * explicitly via gst_event_set_seqnum(). Sequence numbers are typically used to
+ * indicate that a event corresponds to some other set of events or messages,
+ * for example an EOS event corresponding to a SEEK event. It is considered good
+ * practice to make this correspondence when possible, though it is not
+ * required.
+ *
+ * Note that events and messages share the same sequence number incrementor;
+ * two events or messages will never not have the same sequence number unless
+ * that correspondence was made explicitly.
+ *
+ * Returns: The event's sequence number.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_event_get_seqnum (GstEvent * event)
+{
+  g_return_val_if_fail (GST_IS_EVENT (event), -1);
+
+  return GST_EVENT_SEQNUM (event);
+}
+
+/**
+ * gst_event_set_seqnum:
+ * @event: A #GstEvent.
+ * @seqnum: A sequence number.
+ *
+ * Set the sequence number of a event.
+ *
+ * This function might be called by the creator of a event to indicate that the
+ * event relates to other events or messages. See gst_event_get_seqnum() for
+ * more information.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_event_set_seqnum (GstEvent * event, guint32 seqnum)
+{
+  g_return_if_fail (GST_IS_EVENT (event));
+
+  GST_EVENT_SEQNUM (event) = seqnum;
+}
+
+/**
  * gst_event_new_flush_start:
  *
  * Allocate a new flush start event. The flush start event can be sent
@@ -541,7 +602,8 @@
  * The newsegment event marks the range of buffers to be processed. All
  * data not within the segment range is not to be processed. This can be
  * used intelligently by plugins to apply more efficient methods of skipping
- * unneeded data.
+ * unneeded data. The valid range is expressed with the @start and @stop
+ * values.
  *
  * The position value of the segment is used in conjunction with the start
  * value to convert the buffer timestamps into the stream time. This is 
@@ -572,11 +634,15 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 GstEvent *
 gst_event_new_new_segment_full (gboolean update, gdouble rate,
     gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
     gint64 position)
 {
+  GstEvent *event;
+  GstStructure *structure;
+
   g_return_val_if_fail (rate != 0.0, NULL);
   g_return_val_if_fail (applied_rate != 0.0, NULL);
 
@@ -589,9 +655,10 @@
         GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
   } else {
     GST_CAT_INFO (GST_CAT_EVENT,
-        "creating newsegment update %d, rate %lf, format %d, "
+        "creating newsegment update %d, rate %lf, format %s, "
         "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
-        G_GINT64_FORMAT, update, rate, format, start, stop, position);
+        G_GINT64_FORMAT, update, rate, gst_format_get_name (format), start,
+        stop, position);
   }
 
   g_return_val_if_fail (position != -1, NULL);
@@ -599,15 +666,17 @@
   if (stop != -1)
     g_return_val_if_fail (start <= stop, NULL);
 
-  return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
-      gst_structure_new ("GstEventNewsegment",
-          "update", G_TYPE_BOOLEAN, update,
-          "rate", G_TYPE_DOUBLE, rate,
-          "applied_rate", G_TYPE_DOUBLE, applied_rate,
-          "format", GST_TYPE_FORMAT, format,
-          "start", G_TYPE_INT64, start,
-          "stop", G_TYPE_INT64, stop,
-          "position", G_TYPE_INT64, position, NULL));
+  structure = gst_structure_id_new (GST_QUARK (EVENT_NEWSEGMENT),
+      GST_QUARK (UPDATE), G_TYPE_BOOLEAN, update,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, applied_rate,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (START), G_TYPE_INT64, start,
+      GST_QUARK (STOP), G_TYPE_INT64, stop,
+      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
+  event = gst_event_new_custom (GST_EVENT_NEWSEGMENT, structure);
+
+  return event;
 }
 
 /**
@@ -644,27 +713,37 @@
   structure = gst_event_get_structure (event);
   if (G_LIKELY (update))
     *update =
-        g_value_get_boolean (gst_structure_get_value (structure, "update"));
+        g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (UPDATE)));
   if (G_LIKELY (rate))
-    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
+    *rate =
+        g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (RATE)));
   if (G_LIKELY (applied_rate))
     *applied_rate =
-        g_value_get_double (gst_structure_get_value (structure,
-            "applied_rate"));
+        g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (APPLIED_RATE)));
   if (G_LIKELY (format))
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (G_LIKELY (start))
-    *start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
+    *start =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (START)));
   if (G_LIKELY (stop))
-    *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
+    *stop =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (STOP)));
   if (G_LIKELY (position))
     *position =
-        g_value_get_int64 (gst_structure_get_value (structure, "position"));
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (POSITION)));
 }
 
 /**
  * gst_event_new_tag:
- * @taglist: metadata list
+ * @taglist: metadata list. The event will take ownership of @taglist.
  *
  * Generates a metadata tag event from the given @taglist.
  *
@@ -726,17 +805,22 @@
 gst_event_new_buffer_size (GstFormat format, gint64 minsize,
     gint64 maxsize, gboolean async)
 {
+  GstEvent *event;
+  GstStructure *structure;
+
   GST_CAT_INFO (GST_CAT_EVENT,
-      "creating buffersize format %d, minsize %" G_GINT64_FORMAT
-      ", maxsize %" G_GINT64_FORMAT ", async %d", format,
+      "creating buffersize format %s, minsize %" G_GINT64_FORMAT
+      ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format),
       minsize, maxsize, async);
 
-  return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
-      gst_structure_new ("GstEventBufferSize",
-          "format", GST_TYPE_FORMAT, format,
-          "minsize", G_TYPE_INT64, minsize,
-          "maxsize", G_TYPE_INT64, maxsize,
-          "async", G_TYPE_BOOLEAN, async, NULL));
+  structure = gst_structure_id_new (GST_QUARK (EVENT_BUFFER_SIZE),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (MINSIZE), G_TYPE_INT64, minsize,
+      GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize,
+      GST_QUARK (ASYNC), G_TYPE_BOOLEAN, async, NULL);
+  event = gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure);
+
+  return event;
 }
 
 /**
@@ -764,15 +848,21 @@
 
   structure = gst_event_get_structure (event);
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (minsize)
     *minsize =
-        g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (MINSIZE)));
   if (maxsize)
     *maxsize =
-        g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (MAXSIZE)));
   if (async)
-    *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
+    *async =
+        g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (ASYNC)));
 }
 
 /**
@@ -809,7 +899,8 @@
  * The upstream element can use the @diff and @timestamp values to decide
  * whether to process more buffers. For possitive @diff, all buffers with
  * timestamp <= @timestamp + @diff will certainly arrive late in the sink
- * as well. 
+ * as well. A (negative) @diff value so that @timestamp + @diff would yield a
+ * result smaller than 0 is not allowed.
  *
  * The application can use general event probes to intercept the QoS
  * event and implement custom application specific QoS handling.
@@ -824,16 +915,24 @@
 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
     GstClockTime timestamp)
 {
+  GstEvent *event;
+  GstStructure *structure;
+
+  /* diff must be positive or timestamp + diff must be positive */
+  g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL);
+
   GST_CAT_INFO (GST_CAT_EVENT,
       "creating qos proportion %lf, diff %" G_GINT64_FORMAT
       ", timestamp %" GST_TIME_FORMAT, proportion,
       diff, GST_TIME_ARGS (timestamp));
 
-  return gst_event_new_custom (GST_EVENT_QOS,
-      gst_structure_new ("GstEventQOS",
-          "proportion", G_TYPE_DOUBLE, proportion,
-          "diff", G_TYPE_INT64, diff,
-          "timestamp", G_TYPE_UINT64, timestamp, NULL));
+  structure = gst_structure_id_new (GST_QUARK (EVENT_QOS),
+      GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
+      GST_QUARK (DIFF), G_TYPE_INT64, diff,
+      GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, NULL);
+  event = gst_event_new_custom (GST_EVENT_QOS, structure);
+
+  return event;
 }
 
 /**
@@ -862,12 +961,16 @@
   structure = gst_event_get_structure (event);
   if (proportion)
     *proportion =
-        g_value_get_double (gst_structure_get_value (structure, "proportion"));
+        g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (PROPORTION)));
   if (diff)
-    *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
+    *diff =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (DIFF)));
   if (timestamp)
     *timestamp =
-        g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
+        g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (TIMESTAMP)));
 }
 
 /**
@@ -896,9 +999,9 @@
  * configured playback segment can be queried with #GST_QUERY_SEGMENT. 
  *
  * @start_type and @stop_type specify how to adjust the currently configured 
- * start and stop fields in @segment. Adjustments can be made relative or
- * absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE means
- * that the position should not be updated.
+ * start and stop fields in playback segment. Adjustments can be made relative
+ * or absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE
+ * means that the position should not be updated.
  *
  * When the rate is positive and @start has been updated, playback will start
  * from the newly configured start position. 
@@ -910,17 +1013,22 @@
  * It is not possible to seek relative to the current playback position, to do
  * this, PAUSE the pipeline, query the current playback position with
  * #GST_QUERY_POSITION and update the playback segment current position with a
- * #GST_SEEK_TYPE_SET to the desired position.
+ * #GST_SEEK_TYPE_SET to the desired position. 
  *
  * Returns: A new seek event.
  */
+
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 GstEvent *
 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
     GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop)
 {
+  GstEvent *event;
+  GstStructure *structure;
+
   g_return_val_if_fail (rate != 0.0, NULL);
 
   if (format == GST_FORMAT_TIME) {
@@ -932,20 +1040,24 @@
         stop_type, GST_TIME_ARGS (stop));
   } else {
     GST_CAT_INFO (GST_CAT_EVENT,
-        "creating seek rate %lf, format %d, flags %d, "
+        "creating seek rate %lf, format %s, flags %d, "
         "start_type %d, start %" G_GINT64_FORMAT ", "
         "stop_type %d, stop %" G_GINT64_FORMAT,
-        rate, format, flags, start_type, start, stop_type, stop);
+        rate, gst_format_get_name (format), flags, start_type, start, stop_type,
+        stop);
   }
 
-  return gst_event_new_custom (GST_EVENT_SEEK,
-      gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
-          "format", GST_TYPE_FORMAT, format,
-          "flags", GST_TYPE_SEEK_FLAGS, flags,
-          "cur_type", GST_TYPE_SEEK_TYPE, start_type,
-          "cur", G_TYPE_INT64, start,
-          "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
-          "stop", G_TYPE_INT64, stop, NULL));
+  structure = gst_structure_id_new (GST_QUARK (EVENT_SEEK),
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags,
+      GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type,
+      GST_QUARK (CUR), G_TYPE_INT64, start,
+      GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type,
+      GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
+  event = gst_event_new_custom (GST_EVENT_SEEK, structure);
+
+  return event;
 }
 
 /**
@@ -977,26 +1089,39 @@
 
   structure = gst_event_get_structure (event);
   if (rate)
-    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
+    *rate =
+        g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (RATE)));
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
   if (flags)
-    *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
+    *flags =
+        g_value_get_flags (gst_structure_id_get_value (structure,
+            GST_QUARK (FLAGS)));
   if (start_type)
     *start_type =
-        g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
+        g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (CUR_TYPE)));
   if (start)
-    *start = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
+    *start =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (CUR)));
   if (stop_type)
     *stop_type =
-        g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
+        g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (STOP_TYPE)));
   if (stop)
-    *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
+    *stop =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (STOP)));
 }
 
 /**
  * gst_event_new_navigation:
- * @structure: description of the event
+ * @structure: description of the event. The event will take ownership of the
+ *     structure.
  *
  * Create a new navigation event from the given description.
  *
@@ -1020,7 +1145,7 @@
  *
  * Create a new latency event. The event is sent upstream from the sinks and
  * notifies elements that they should add an additional @latency to the
- * timestamps before synchronising against the clock.
+ * running time before synchronising against the clock.
  *
  * The latency is mostly used in live sinks and is always expressed in
  * the time format.
@@ -1036,12 +1161,17 @@
 GstEvent *
 gst_event_new_latency (GstClockTime latency)
 {
+  GstEvent *event;
+  GstStructure *structure;
+
   GST_CAT_INFO (GST_CAT_EVENT,
       "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
 
-  return gst_event_new_custom (GST_EVENT_LATENCY,
-      gst_structure_new ("GstEventLatency",
-          "latency", G_TYPE_UINT64, latency, NULL));
+  structure = gst_structure_id_new (GST_QUARK (EVENT_LATENCY),
+      GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL);
+  event = gst_event_new_custom (GST_EVENT_LATENCY, structure);
+
+  return event;
 }
 
 /**
@@ -1068,5 +1198,101 @@
   structure = gst_event_get_structure (event);
   if (latency)
     *latency =
-        g_value_get_uint64 (gst_structure_get_value (structure, "latency"));
+        g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (LATENCY)));
 }
+
+/**
+ * gst_event_new_step:
+ * @format: the format of @amount
+ * @amount: the amount of data to step
+ * @rate: the step rate
+ * @flush: flushing steps
+ * @intermediate: intermediate steps
+ *
+ * Create a new step event. The purpose of the step event is to instruct a sink
+ * to skip @amount (expressed in @format) of media. It can be used to implement
+ * stepping through the video frame by frame or for doing fast trick modes.
+ *
+ * A rate of <= 0.0 is not allowed, pause the pipeline or reverse the playback
+ * direction of the pipeline to get the same effect.
+ *
+ * The @flush flag will clear any pending data in the pipeline before starting
+ * the step operation.
+ *
+ * The @intermediate flag instructs the pipeline that this step operation is
+ * part of a larger step operation.
+ *
+ * Returns: a new #GstEvent
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstEvent *
+gst_event_new_step (GstFormat format, guint64 amount, gdouble rate,
+    gboolean flush, gboolean intermediate)
+{
+  GstEvent *event;
+  GstStructure *structure;
+
+  g_return_val_if_fail (rate > 0.0, NULL);
+
+  GST_CAT_INFO (GST_CAT_EVENT, "creating step event");
+
+  structure = gst_structure_id_new (GST_QUARK (EVENT_STEP),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  event = gst_event_new_custom (GST_EVENT_STEP, structure);
+
+  return event;
+}
+
+/**
+ * gst_event_parse_step:
+ * @event: The event to query
+ * @format: A pointer to store the format in.
+ * @amount: A pointer to store the amount in.
+ * @rate: A pointer to store the rate in.
+ * @flush: A pointer to store the flush boolean in.
+ * @intermediate: A pointer to store the intermediate boolean in.
+ *
+ * Parse the step event.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
+    gdouble * rate, gboolean * flush, gboolean * intermediate)
+{
+  const GstStructure *structure;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STEP);
+
+  structure = gst_event_get_structure (event);
+  if (format)
+    *format = g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
+  if (amount)
+    *amount = g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (AMOUNT)));
+  if (rate)
+    *rate = g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (RATE)));
+  if (flush)
+    *flush = g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (FLUSH)));
+  if (intermediate)
+    *intermediate = g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (INTERMEDIATE)));
+}
--- a/gstreamer_core/gst/gstevent.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstevent.h	Fri Apr 16 15:15:52 2010 +0300
@@ -92,6 +92,7 @@
  *                        user requests, such as mouse or keyboard movements,
  *                        to upstream elements.
  * @GST_EVENT_LATENCY: Notification of new latency adjustment. Since: 0.10.12
+ * @GST_EVENT_STEP: A request for stepping through the media. Since: 0.10.24
  * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event
  * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the
  *                        data flow.
@@ -124,6 +125,7 @@
   GST_EVENT_SEEK		  = GST_EVENT_MAKE_TYPE (16, FLAG(UPSTREAM)),
   GST_EVENT_NAVIGATION		  = GST_EVENT_MAKE_TYPE (17, FLAG(UPSTREAM)),
   GST_EVENT_LATENCY		  = GST_EVENT_MAKE_TYPE (18, FLAG(UPSTREAM)),
+  GST_EVENT_STEP		  = GST_EVENT_MAKE_TYPE (19, FLAG(UPSTREAM)),
 
   /* custom events start here */
   GST_EVENT_CUSTOM_UPSTREAM	  = GST_EVENT_MAKE_TYPE (32, FLAG(UPSTREAM)),
@@ -228,7 +230,10 @@
 /**
  * GstSeekType:
  * @GST_SEEK_TYPE_NONE: no change in position is required
- * @GST_SEEK_TYPE_CUR: change relative to current position
+ * @GST_SEEK_TYPE_CUR: change relative to currently configured segment. This
+ *    can't be used to seek relative to the current playback position - do a
+ *    position query, calculate the desired position and then do an absolute
+ *    position seek instead if that's what you want to do.
  * @GST_SEEK_TYPE_SET: absolute position is requested
  * @GST_SEEK_TYPE_END: relative position to duration is requested
  *
@@ -254,6 +259,9 @@
  * @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be
  *		       faster but less accurate.
  * @GST_SEEK_FLAG_SEGMENT: perform a segment seek.
+ * @GST_SEEK_FLAG_SKIP: when doing fast foward or fast reverse playback, allow
+ *                     elements to skip frames instead of generating all
+ *                     frames. Since 0.10.22.
  *
  * Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags
  * can be used together.
@@ -271,16 +279,21 @@
  * When this message is posted, it is possible to send a new seek event to
  * continue playback. With this seek method it is possible to perform seemless
  * looping or simple linear editing.
+ *
+ * When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode
+ * playback, the @GST_SEEK_FLAG_SKIP flag can be used to instruct decoders
+ * and demuxers to adjust the playback rate by skipping frames. This can improve
+ * performance and decrease CPU usage because not all frames need to be decoded. 
  */
 typedef enum {
   GST_SEEK_FLAG_NONE		= 0,
   GST_SEEK_FLAG_FLUSH		= (1 << 0),
   GST_SEEK_FLAG_ACCURATE	= (1 << 1),
   GST_SEEK_FLAG_KEY_UNIT	= (1 << 2),
-  GST_SEEK_FLAG_SEGMENT		= (1 << 3)
+  GST_SEEK_FLAG_SEGMENT		= (1 << 3),
+  GST_SEEK_FLAG_SKIP		= (1 << 4)
 } GstSeekFlags;
 
-
 /**
  * GstEvent:
  * @mini_object: the parent structure
@@ -302,7 +315,10 @@
   GstStructure	*structure;
 
   /*< private >*/
-  gpointer _gst_reserved;
+  union {
+    guint32 seqnum;
+    gpointer _gst_reserved;
+  } abidata;
 };
 
 struct _GstEventClass {
@@ -350,29 +366,44 @@
 #endif
 
 static inline GstEvent *
-gst_event_ref (GstEvent * ev)
+gst_event_ref (GstEvent * event)
 {
-  /* not using a macro here because gcc-4.1 will complain
-   * if the return value isn't used (because of the cast) */
-  return (GstEvent *) gst_mini_object_ref (GST_MINI_OBJECT (ev));
+  return (GstEvent *) gst_mini_object_ref (GST_MINI_OBJECT (event));
 }
 
 /**
  * gst_event_unref:
- * @ev: The event to refcount
+ * @event: The event to refcount
  *
  * Decrease the refcount of an event, freeing it if the refcount reaches 0.
  */
-#define         gst_event_unref(ev)		gst_mini_object_unref (GST_MINI_OBJECT (ev))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_event_unref (GstEvent * event);
+#endif
+
+static inline void
+gst_event_unref (GstEvent * event)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT (event));
+}
 
 /* copy event */
 /**
  * gst_event_copy:
- * @ev: The event to copy
+ * @event: The event to copy
  *
  * Copy the event using the event specific copy function.
  */
-#define         gst_event_copy(ev)		GST_EVENT_CAST (gst_mini_object_copy (GST_MINI_OBJECT (ev)))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_event_copy (GstEvent * event);
+#endif
+
+static inline GstEvent *
+gst_event_copy (const GstEvent * event)
+{
+  return GST_EVENT_CAST (gst_mini_object_copy (GST_MINI_OBJECT (event)));
+}
+
 
 /* custom event */
 #ifdef __SYMBIAN32__
@@ -387,6 +418,24 @@
 
 const GstStructure *
 		gst_event_get_structure		(GstEvent *event);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean        gst_event_has_name              (GstEvent *event, const gchar *name);
+
+/* identifiers for events and messages */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint32         gst_event_get_seqnum            (GstEvent *event);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_event_set_seqnum            (GstEvent *event, guint32 seqnum);
 
 /* flush events */
 #ifdef __SYMBIAN32__
@@ -521,6 +570,20 @@
 
 void		gst_event_parse_latency		(GstEvent *event, GstClockTime *latency);
 
+/* step event */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstEvent*	gst_event_new_step		(GstFormat format, guint64 amount, gdouble rate,
+                                                 gboolean flush, gboolean intermediate);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_event_parse_step		(GstEvent *event, GstFormat *format, guint64 *amount,
+                                                 gdouble *rate, gboolean *flush, gboolean *intermediate);
+
 G_END_DECLS
 
 #endif /* __GST_EVENT_H__ */
--- a/gstreamer_core/gst/gstformat.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstformat.h	Fri Apr 16 15:15:52 2010 +0300
@@ -35,11 +35,15 @@
  * GstFormat:
  * @GST_FORMAT_UNDEFINED: undefined format
  * @GST_FORMAT_DEFAULT: the default format of the pad/element. This can be
- *    samples for raw audio, frames/fields for raw video.
+ *    samples for raw audio, frames/fields for raw video (some, but not all,
+ *    elements support this; use @GST_FORMAT_TIME if you don't have a good
+ *    reason to query for samples/frames)
  * @GST_FORMAT_BYTES: bytes
  * @GST_FORMAT_TIME: time in nanoseconds
- * @GST_FORMAT_BUFFERS: buffers
- * @GST_FORMAT_PERCENT: percentage of stream
+ * @GST_FORMAT_BUFFERS: buffers (few, if any, elements implement this as of
+ *     May 2009)
+ * @GST_FORMAT_PERCENT: percentage of stream (few, if any, elements implement
+ *     this as of May 2009)
  *
  * Standard predefined formats
  */
--- a/gstreamer_core/gst/gstghostpad.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstghostpad.c	Fri Apr 16 15:15:52 2010 +0300
@@ -56,43 +56,24 @@
 
 #define GST_CAT_DEFAULT GST_CAT_PADS
 
-#define GST_TYPE_PROXY_PAD              (gst_proxy_pad_get_type ())
-#define GST_IS_PROXY_PAD(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROXY_PAD))
-#define GST_IS_PROXY_PAD_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD))
-#define GST_PROXY_PAD(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad))
-#define GST_PROXY_PAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass))
 #define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
-
-#define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD_CAST (pad)->target)
-#define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_CAST (pad)->internal)
-
-typedef struct _GstProxyPad GstProxyPad;
-typedef struct _GstProxyPadClass GstProxyPadClass;
-
-#define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_CAST (pad)->proxy_lock)
+#define GST_PROXY_PAD_PRIVATE(obj)      (GST_PROXY_PAD_CAST (obj)->priv)
+#define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD_PRIVATE (pad)->target)
+#define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_PRIVATE (pad)->internal)
+#define GST_PROXY_PAD_RETARGET(pad)     (GST_PROXY_PAD_PRIVATE (pad)->retarget)
+#define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock)
 #define GST_PROXY_LOCK(pad)     (g_mutex_lock (GST_PROXY_GET_LOCK (pad)))
 #define GST_PROXY_UNLOCK(pad)   (g_mutex_unlock (GST_PROXY_GET_LOCK (pad)))
 
-struct _GstProxyPad
+struct _GstProxyPadPrivate
 {
-  GstPad pad;
-
   /* with PROXY_LOCK */
   GMutex *proxy_lock;
   GstPad *target;
   GstPad *internal;
+  gboolean retarget;
 };
 
-struct _GstProxyPadClass
-{
-  GstPadClass parent_class;
-
-  /*< private > */
-  gpointer _gst_reserved[1];
-};
-
-static GType gst_proxy_pad_get_type (void);
-
 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
 
 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
@@ -105,12 +86,17 @@
     xmlNodePtr parent);
 #endif
 
+static void on_src_target_notify (GstPad * target,
+    GParamSpec * unused, GstGhostPad * pad);
+
 
 static void
 gst_proxy_pad_class_init (GstProxyPadClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
 
+  g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
+
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_proxy_pad_dispose);
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_proxy_pad_finalize);
 
@@ -162,14 +148,14 @@
   return res;
 }
 
-static GList *
-gst_proxy_pad_do_internal_link (GstPad * pad)
+static GstIterator *
+gst_proxy_pad_do_iterate_internal_links (GstPad * pad)
 {
-  GList *res = NULL;
+  GstIterator *res = NULL;
   GstPad *target = gst_proxy_pad_get_target (pad);
 
   if (target) {
-    res = gst_pad_get_internal_links (target);
+    res = gst_pad_iterate_internal_links (target);
     gst_object_unref (target);
   }
 
@@ -200,6 +186,17 @@
 }
 
 static GstFlowReturn
+gst_proxy_pad_do_chain_list (GstPad * pad, GstBufferList * list)
+{
+  GstFlowReturn res;
+  GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
+
+  res = gst_pad_push_list (internal, list);
+
+  return res;
+}
+
+static GstFlowReturn
 gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
     GstBuffer ** buffer)
 {
@@ -234,7 +231,8 @@
     res = gst_pad_get_caps (target);
     gst_object_unref (target);
 
-    GST_DEBUG_OBJECT (pad, "get caps of target: %" GST_PTR_FORMAT, res);
+    GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
+        GST_DEBUG_PAD_NAME (target), res);
 
     /* filter against the template */
     if (templ && res) {
@@ -331,9 +329,9 @@
     GST_LOG_OBJECT (pad, "clearing target");
 
   /* clear old target */
-  if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) {
+  if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
     gst_object_unref (oldtarget);
-  }
+
   /* set and ref new target if any */
   if (target)
     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
@@ -378,6 +376,24 @@
 }
 
 static void
+gst_proxy_pad_do_unlink (GstPad * pad)
+{
+  GstPad *internal;
+
+  /* don't do anything if this unlink resulted from retargeting the pad
+   * controlled by the ghostpad. We only want to invalidate the target pad when
+   * the element suddently unlinked with our internal pad. */
+  if (GST_PROXY_PAD_RETARGET (pad))
+    return;
+
+  internal = GST_PROXY_PAD_INTERNAL (pad);
+
+  GST_DEBUG_OBJECT (pad, "pad is unlinked");
+
+  gst_proxy_pad_set_target (internal, NULL);
+}
+
+static void
 gst_proxy_pad_dispose (GObject * object)
 {
   GstPad *pad = GST_PAD (object);
@@ -400,8 +416,8 @@
 {
   GstProxyPad *pad = GST_PROXY_PAD (object);
 
-  g_mutex_free (pad->proxy_lock);
-  pad->proxy_lock = NULL;
+  g_mutex_free (GST_PROXY_GET_LOCK (pad));
+  GST_PROXY_GET_LOCK (pad) = NULL;
 
   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
 }
@@ -411,14 +427,16 @@
 {
   GstPad *pad = (GstPad *) ppad;
 
-  ppad->proxy_lock = g_mutex_new ();
+  GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
+      GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
+  GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
 
   gst_pad_set_query_type_function (pad,
       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
   gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
-  gst_pad_set_internal_link_function (pad,
-      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
+  gst_pad_set_iterate_internal_links_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_iterate_internal_links));
 
   gst_pad_set_getcaps_function (pad,
       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
@@ -428,6 +446,8 @@
       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
   gst_pad_set_setcaps_function (pad,
       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
+  gst_pad_set_unlink_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_unlink));
 }
 
 #ifndef GST_DISABLE_LOADSAVE
@@ -490,26 +510,16 @@
  */
 
 
-struct _GstGhostPad
+#define GST_GHOST_PAD_PRIVATE(obj)	(GST_GHOST_PAD_CAST (obj)->priv)
+
+struct _GstGhostPadPrivate
 {
-  GstProxyPad pad;
-
   /* with PROXY_LOCK */
   gulong notify_id;
 
-  /*< private > */
-  gpointer _gst_reserved[GST_PADDING];
+  gboolean constructed;
 };
 
-struct _GstGhostPadClass
-{
-  GstProxyPadClass parent_class;
-
-  /*< private > */
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-
 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
 
 static void gst_ghost_pad_dispose (GObject * object);
@@ -519,6 +529,8 @@
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
 
+  g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
+
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
 }
 
@@ -662,44 +674,74 @@
 static void
 gst_ghost_pad_do_unlink (GstPad * pad)
 {
-  GstPad *target;
   GstPad *internal;
 
-  target = gst_proxy_pad_get_target (pad);
   internal = GST_PROXY_PAD_INTERNAL (pad);
 
   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
 
   /* The target of the internal pad is no longer valid */
   gst_proxy_pad_set_target (internal, NULL);
-
-  if (target) {
-    if (GST_PAD_UNLINKFUNC (target))
-      GST_PAD_UNLINKFUNC (target) (target);
-
-    gst_object_unref (target);
-  }
 }
 
 static void
 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
 {
   GstCaps *caps;
+  gboolean changed;
 
   g_object_get (internal, "caps", &caps, NULL);
 
   GST_OBJECT_LOCK (pad);
-  gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
+  changed = (GST_PAD_CAPS (pad) != caps);
+  if (changed)
+    gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
   GST_OBJECT_UNLOCK (pad);
 
-  g_object_notify (G_OBJECT (pad), "caps");
+  if (changed)
+    g_object_notify (G_OBJECT (pad), "caps");
+
   if (caps)
     gst_caps_unref (caps);
 }
 
 static void
+on_src_target_notify (GstPad * target, GParamSpec * unused, GstGhostPad * pad)
+{
+  GstCaps *caps;
+  gboolean changed;
+
+  g_object_get (target, "caps", &caps, NULL);
+
+  GST_OBJECT_LOCK (pad);
+  changed = (GST_PAD_CAPS (pad) != caps);
+  gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
+  GST_OBJECT_UNLOCK (pad);
+
+  if (changed)
+    g_object_notify (G_OBJECT (pad), "caps");
+
+  if (caps)
+    gst_caps_unref (caps);
+}
+
+static gboolean
+gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps)
+{
+  if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
+    return TRUE;
+
+  return gst_proxy_pad_do_setcaps (pad, caps);
+}
+
+static void
 gst_ghost_pad_init (GstGhostPad * pad)
 {
+  GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
+      GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
+
+  gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
+      GST_DEBUG_FUNCPTR (gst_ghost_pad_do_setcaps));
   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull));
   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
@@ -711,85 +753,109 @@
 {
   GstPad *pad;
   GstPad *internal;
-  GstPad *intpeer;
+  GstPad *peer;
 
   pad = GST_PAD (object);
 
   GST_DEBUG_OBJECT (pad, "dispose");
 
+  gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
+
+  /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
+   * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */
+  peer = gst_pad_get_peer (pad);
+  if (peer) {
+    if (GST_PAD_IS_SRC (pad))
+      gst_pad_unlink (pad, peer);
+    else
+      gst_pad_unlink (peer, pad);
+
+    gst_object_unref (peer);
+  }
+
   GST_PROXY_LOCK (pad);
   internal = GST_PROXY_PAD_INTERNAL (pad);
 
   gst_pad_set_activatepull_function (internal, NULL);
   gst_pad_set_activatepush_function (internal, NULL);
 
-  g_signal_handler_disconnect (internal, GST_GHOST_PAD_CAST (pad)->notify_id);
-
-  intpeer = gst_pad_get_peer (internal);
-  if (intpeer) {
-    if (GST_PAD_IS_SRC (internal))
-      gst_pad_unlink (internal, intpeer);
-    else
-      gst_pad_unlink (intpeer, internal);
-
-    gst_object_unref (intpeer);
-  }
-
-  GST_PROXY_PAD_INTERNAL (internal) = NULL;
+  g_signal_handler_disconnect (internal,
+      GST_GHOST_PAD_PRIVATE (pad)->notify_id);
 
   /* disposes of the internal pad, since the ghostpad is the only possible object
    * that has a refcount on the internal pad. */
   gst_object_unparent (GST_OBJECT_CAST (internal));
+  GST_PROXY_PAD_INTERNAL (pad) = NULL;
 
   GST_PROXY_UNLOCK (pad);
 
   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
 }
 
-static GstPad *
-gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
-    GstPadTemplate * templ)
-{
-  GstPad *ret;
-  GstPad *internal;
-  GstPadDirection otherdir;
+/**
+ * gst_ghost_pad_construct:
+ * @gpad: the newly allocated ghost pad
+ *
+ * Finish initialization of a newly allocated ghost pad.
+ *
+ * This function is most useful in language bindings and when subclassing
+ * #GstGhostPad; plugin and application developers normally will not call this
+ * function. Call this function directly after a call to g_object_new
+ * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
+ *
+ * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-  g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
+gboolean
+gst_ghost_pad_construct (GstGhostPad * gpad)
+{
+  GstPadDirection dir, otherdir;
+  GstPadTemplate *templ;
+  GstPad *pad, *internal;
 
-  /* OBJECT CREATION */
-  if (templ) {
-    ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
-        "direction", dir, "template", templ, NULL);
-  } else {
-    ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
-        "direction", dir, NULL);
-  }
+  g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
+  g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
+      FALSE);
+
+  g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
+
+  g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
+
+  pad = GST_PAD (gpad);
 
   /* Set directional padfunctions for ghostpad */
   if (dir == GST_PAD_SINK) {
-    gst_pad_set_bufferalloc_function (ret,
+    gst_pad_set_bufferalloc_function (pad,
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
-    gst_pad_set_chain_function (ret,
+    gst_pad_set_chain_function (pad,
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
+    gst_pad_set_chain_list_function (pad,
+        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list));
   } else {
-    gst_pad_set_getrange_function (ret,
+    gst_pad_set_getrange_function (pad,
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
-    gst_pad_set_checkgetrange_function (ret,
+    gst_pad_set_checkgetrange_function (pad,
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
   }
 
   /* link/unlink functions */
-  gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
-  gst_pad_set_unlink_function (ret,
+  gst_pad_set_link_function (pad, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
+  gst_pad_set_unlink_function (pad,
       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink));
 
-
   /* INTERNAL PAD, it always exists and is child of the ghostpad */
   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
   if (templ) {
     internal =
         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
         "direction", otherdir, "template", templ, NULL);
+    /* release ref obtained via g_object_get */
+    gst_object_unref (templ);
   } else {
     internal =
         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
@@ -803,6 +869,8 @@
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
     gst_pad_set_chain_function (internal,
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
+    gst_pad_set_chain_list_function (internal,
+        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list));
   } else {
     gst_pad_set_getrange_function (internal,
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
@@ -810,11 +878,11 @@
         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
   }
 
-  GST_PROXY_LOCK (ret);
+  GST_PROXY_LOCK (pad);
 
   /* now make the ghostpad a parent of the internal pad */
   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
-          GST_OBJECT_CAST (ret)))
+          GST_OBJECT_CAST (pad)))
     goto parent_failed;
 
   /* The ghostpad is the parent of the internal pad and is the only object that
@@ -825,17 +893,17 @@
    * it's refcount on the internal pad in the dispose method by un-parenting it.
    * This is why we don't take extra refcounts in the assignments below
    */
-  GST_PROXY_PAD_INTERNAL (ret) = internal;
-  GST_PROXY_PAD_INTERNAL (internal) = ret;
+  GST_PROXY_PAD_INTERNAL (pad) = internal;
+  GST_PROXY_PAD_INTERNAL (internal) = pad;
 
   /* could be more general here, iterating over all writable properties...
    * taking the short road for now tho */
-  GST_GHOST_PAD_CAST (ret)->notify_id =
+  GST_GHOST_PAD_PRIVATE (pad)->notify_id =
       g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
-      ret);
+      pad);
 
   /* call function to init values of the pad caps */
-  on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret));
+  on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad));
 
   /* special activation functions for the internal pad */
   gst_pad_set_activatepull_function (internal,
@@ -843,24 +911,52 @@
   gst_pad_set_activatepush_function (internal,
       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
 
-  GST_PROXY_UNLOCK (ret);
+  GST_PROXY_UNLOCK (pad);
 
-  return ret;
+  GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
+  return TRUE;
 
   /* ERRORS */
 parent_failed:
   {
-    GST_WARNING_OBJECT (ret, "Could not set internal pad %s:%s",
+    GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
         GST_DEBUG_PAD_NAME (internal));
     g_critical ("Could not set internal pad %s:%s",
         GST_DEBUG_PAD_NAME (internal));
-    GST_PROXY_UNLOCK (ret);
-    gst_object_unref (ret);
+    GST_PROXY_UNLOCK (pad);
     gst_object_unref (internal);
-    return NULL;
+    return FALSE;
   }
 }
 
+static GstPad *
+gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
+    GstPadTemplate * templ)
+{
+  GstGhostPad *ret;
+
+  g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
+
+  /* OBJECT CREATION */
+  if (templ) {
+    ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
+        "direction", dir, "template", templ, NULL);
+  } else {
+    ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
+        "direction", dir, NULL);
+  }
+
+  if (!gst_ghost_pad_construct (ret))
+    goto construct_failed;
+
+  return GST_PAD (ret);
+
+construct_failed:
+  /* already logged */
+  gst_object_unref (ret);
+  return NULL;
+}
+
 /**
  * gst_ghost_pad_new_no_target:
  * @name: the name of the new pad, or NULL to assign a default name.
@@ -1049,7 +1145,8 @@
  * @newtarget: the new pad target
  *
  * Set the new target of the ghostpad @gpad. Any existing target
- * is unlinked and links to the new target are established.
+ * is unlinked and links to the new target are established. if @newtarget is
+ * NULL the target will be cleared.
  *
  * Returns: TRUE if the new target could be set. This function can return FALSE
  * when the internal pads could not be linked.
@@ -1070,23 +1167,39 @@
 
   GST_PROXY_LOCK (gpad);
   internal = GST_PROXY_PAD_INTERNAL (gpad);
+  g_assert (internal);
 
-  GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
+  if (newtarget)
+    GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
+  else
+    GST_DEBUG_OBJECT (gpad, "clearing target");
 
   /* clear old target */
   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
-    /* if we have an internal pad, unlink */
-    if (internal) {
-      if (GST_PAD_IS_SRC (internal))
-        gst_pad_unlink (internal, oldtarget);
-      else
-        gst_pad_unlink (oldtarget, internal);
+    if (GST_PAD_IS_SRC (oldtarget)) {
+      g_signal_handlers_disconnect_by_func (oldtarget,
+          (gpointer) on_src_target_notify, gpad);
     }
+
+    GST_PROXY_PAD_RETARGET (internal) = TRUE;
+
+    /* unlink internal pad */
+    if (GST_PAD_IS_SRC (internal))
+      gst_pad_unlink (internal, oldtarget);
+    else
+      gst_pad_unlink (oldtarget, internal);
+
+    GST_PROXY_PAD_RETARGET (internal) = FALSE;
   }
 
   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
 
   if (result && newtarget) {
+    if (GST_PAD_IS_SRC (newtarget)) {
+      g_signal_connect (newtarget, "notify::caps",
+          G_CALLBACK (on_src_target_notify), gpad);
+    }
+
     /* and link to internal pad */
     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
 
--- a/gstreamer_core/gst/gstghostpad.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstghostpad.h	Fri Apr 16 15:15:52 2010 +0300
@@ -31,6 +31,39 @@
 
 G_BEGIN_DECLS
 
+#define GST_TYPE_PROXY_PAD              (gst_proxy_pad_get_type ())
+#define GST_IS_PROXY_PAD(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROXY_PAD))
+#define GST_IS_PROXY_PAD_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD))
+#define GST_PROXY_PAD(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad))
+#define GST_PROXY_PAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass))
+
+typedef struct _GstProxyPad GstProxyPad;
+typedef struct _GstProxyPadPrivate GstProxyPadPrivate;
+typedef struct _GstProxyPadClass GstProxyPadClass;
+
+struct _GstProxyPad
+{
+  GstPad pad;
+
+  /*< private >*/
+  GstProxyPadPrivate *priv;
+};
+
+struct _GstProxyPadClass
+{
+  GstPadClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[1];
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_proxy_pad_get_type (void);
+
+
 #define GST_TYPE_GHOST_PAD		(gst_ghost_pad_get_type ())
 #define GST_IS_GHOST_PAD(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD))
 #define GST_IS_GHOST_PAD_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD))
@@ -44,12 +77,30 @@
  * Opaque #GstGhostPad structure.
  */
 typedef struct _GstGhostPad GstGhostPad;
+typedef struct _GstGhostPadPrivate GstGhostPadPrivate;
 typedef struct _GstGhostPadClass GstGhostPadClass;
+
+struct _GstGhostPad
+{
+  GstProxyPad pad;
+
+  /*< private >*/
+  GstGhostPadPrivate *priv;
+};
+
+struct _GstGhostPadClass
+{
+  GstProxyPadClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
+
 GType		 gst_ghost_pad_get_type 	(void);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -84,6 +135,12 @@
 #endif
 
 gboolean	 gst_ghost_pad_set_target	(GstGhostPad *gpad, GstPad *newtarget);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean	 gst_ghost_pad_construct	(GstGhostPad *gpad);
 
 G_END_DECLS
 
--- a/gstreamer_core/gst/gstindex.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstindex.c	Fri Apr 16 15:15:52 2010 +0300
@@ -39,6 +39,7 @@
 /* for constructing an entry name */
 #include "gstelement.h"
 #include "gstpad.h"
+#include "gstinfo.h"
 
 /* Index signals and args */
 enum
@@ -54,6 +55,9 @@
       /* FILL ME */
 };
 
+GST_DEBUG_CATEGORY_STATIC (index_debug);
+#define GST_CAT_DEFAULT index_debug
+
 static void gst_index_class_init (GstIndexClass * klass);
 static void gst_index_init (GstIndex * index);
 static void gst_index_finalize (GObject * object);
@@ -94,12 +98,9 @@
 {
   static GType index_resolver_type = 0;
   static const GEnumValue index_resolver[] = {
-    {GST_INDEX_RESOLVER_CUSTOM, "GST_INDEX_RESOLVER_CUSTOM",
-        "Use a custom resolver"},
-    {GST_INDEX_RESOLVER_GTYPE, "GST_INDEX_RESOLVER_GTYPE",
-        "Resolve an object to its GType[.padname]"},
-    {GST_INDEX_RESOLVER_PATH, "GST_INDEX_RESOLVER_PATH",
-        "Resolve an object to its path in the pipeline"},
+    {GST_INDEX_RESOLVER_CUSTOM, "GST_INDEX_RESOLVER_CUSTOM", "custom"},
+    {GST_INDEX_RESOLVER_GTYPE, "GST_INDEX_RESOLVER_GTYPE", "gtype"},
+    {GST_INDEX_RESOLVER_PATH, "GST_INDEX_RESOLVER_PATH", "path"},
     {0, NULL, NULL},
   };
 
@@ -126,43 +127,19 @@
   }
   return index_entry_type;
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-
-GType
-gst_index_get_type (void)
-{
-  static GType index_type = 0;
 
-  if (!index_type) {
-    static const GTypeInfo index_info = {
-      sizeof (GstIndexClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_index_class_init,
-      NULL,
-      NULL,
-      sizeof (GstIndex),
-      0,
-      (GInstanceInitFunc) gst_index_init,
-      NULL
-    };
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (index_debug, "GST_INDEX", GST_DEBUG_BOLD, \
+      "Generic indexing support"); \
+}
 
-    index_type =
-        g_type_register_static (GST_TYPE_OBJECT, "GstIndex", &index_info, 0);
-  }
-  return index_type;
-}
+G_DEFINE_TYPE_WITH_CODE (GstIndex, gst_index, GST_TYPE_OBJECT, _do_init);
 
 static void
 gst_index_class_init (GstIndexClass * klass)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -185,7 +162,8 @@
   g_object_class_install_property (gobject_class, ARG_RESOLVER,
       g_param_spec_enum ("resolver", "Resolver",
           "Select a predefined object to string mapper",
-          GST_TYPE_INDEX_RESOLVER, GST_INDEX_RESOLVER_PATH, G_PARAM_READWRITE));
+          GST_TYPE_INDEX_RESOLVER, GST_INDEX_RESOLVER_PATH,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
--- a/gstreamer_core/gst/gstindexfactory.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstindexfactory.c	Fri Apr 16 15:15:52 2010 +0300
@@ -43,46 +43,12 @@
 static GstPluginFeatureClass *factory_parent_class = NULL;
 
 /* static guint gst_index_factory_signals[LAST_SIGNAL] = { 0 }; */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-GType
-gst_index_factory_get_type (void)
-{
-  static GType indexfactory_type = 0;
-
-  if (G_UNLIKELY (indexfactory_type == 0)) {
-    static const GTypeInfo indexfactory_info = {
-      sizeof (GstIndexFactoryClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_index_factory_class_init,
-      NULL,
-      NULL,
-      sizeof (GstIndexFactory),
-      0,
-      NULL,
-      NULL
-    };
-
-    indexfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
-        "GstIndexFactory", &indexfactory_info, 0);
-  }
-  return indexfactory_type;
-}
+G_DEFINE_TYPE (GstIndexFactory, gst_index_factory, GST_TYPE_PLUGIN_FEATURE);
 
 static void
 gst_index_factory_class_init (GstIndexFactoryClass * klass)
 {
-  GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
-  GstPluginFeatureClass *gstpluginfeature_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstobject_class = (GstObjectClass *) klass;
-  gstpluginfeature_class = (GstPluginFeatureClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   factory_parent_class = g_type_class_peek_parent (klass);
 
@@ -90,6 +56,11 @@
 }
 
 static void
+gst_index_factory_init (GstIndexFactory * factory)
+{
+}
+
+static void
 gst_index_factory_finalize (GObject * object)
 {
   GstIndexFactory *factory = GST_INDEX_FACTORY (object);
@@ -229,13 +200,33 @@
 gst_index_factory_make (const gchar * name)
 {
   GstIndexFactory *factory;
+  GstIndex *index;
 
   g_return_val_if_fail (name != NULL, NULL);
 
   factory = gst_index_factory_find (name);
 
   if (factory == NULL)
-    return NULL;
+    goto no_factory;
+
+  index = gst_index_factory_create (factory);
+
+  if (index == NULL)
+    goto create_failed;
+
+  gst_object_unref (factory);
+  return index;
 
-  return gst_index_factory_create (factory);
+  /* ERRORS */
+no_factory:
+  {
+    GST_INFO ("no such index factory \"%s\"!", name);
+    return NULL;
+  }
+create_failed:
+  {
+    GST_INFO_OBJECT (factory, "couldn't create instance!");
+    gst_object_unref (factory);
+    return NULL;
+  }
 }
--- a/gstreamer_core/gst/gstinfo.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstinfo.c	Fri Apr 16 15:15:52 2010 +0300
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000 Wim Taymans <wtay@chello.be>
  *                    2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ * Copyright (C) 2008-2009 Tim-Philipp Müller <tim centricular net>
  *
  * gstinfo.c: debugging functions
  *
@@ -85,6 +86,8 @@
  * categories. These are explained at GST_DEBUG_CATEGORY_INIT().
  */
 
+#define GST_INFO_C
+
 #include "gst_private.h"
 #include "gstinfo.h"
 
@@ -104,18 +107,71 @@
 #  include <process.h>          /* getpid on win32 */
 #endif
 #include <string.h>             /* G_VA_COPY */
+#ifdef G_OS_WIN32
+#  define WIN32_LEAN_AND_MEAN   /* prevents from including too many things */
+#  include <windows.h>          /* GetStdHandle, windows console */
+#endif
 
 #include "gst_private.h"
 #include "gstutils.h"
+#include "gstquark.h"
 #include "gstsegment.h"
-#ifdef HAVE_VALGRIND
+#ifdef HAVE_VALGRIND_H
 #  include <valgrind/valgrind.h>
 #endif
 #include <glib/gprintf.h>       /* g_sprintf */
-
+#endif /* !GST_DISABLE_GST_DEBUG */
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
+
 #endif
+/* we want these symbols exported even if debug is disabled, to maintain
+ * ABI compatibility. Unless GST_REMOVE_DISABLED is defined. */
+#if !defined(GST_DISABLE_GST_DEBUG) || !defined(GST_REMOVE_DISABLED)
+
+/* disabled by default, as soon as some threshold is set > NONE,
+ * it becomes enabled. */
+gboolean __gst_debug_enabled = FALSE;
+GstDebugLevel __gst_debug_min = GST_LEVEL_NONE;
+
+GstDebugCategory *GST_CAT_DEFAULT = NULL;
+
+GstDebugCategory *GST_CAT_GST_INIT = NULL;
+GstDebugCategory *GST_CAT_AUTOPLUG = NULL;
+GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT = NULL;
+GstDebugCategory *GST_CAT_PARENTAGE = NULL;
+GstDebugCategory *GST_CAT_STATES = NULL;
+GstDebugCategory *GST_CAT_SCHEDULING = NULL;
+
+GstDebugCategory *GST_CAT_BUFFER = NULL;
+GstDebugCategory *GST_CAT_BUFFER_LIST = NULL;
+GstDebugCategory *GST_CAT_BUS = NULL;
+GstDebugCategory *GST_CAT_CAPS = NULL;
+GstDebugCategory *GST_CAT_CLOCK = NULL;
+GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL;
+GstDebugCategory *GST_CAT_PADS = NULL;
+GstDebugCategory *GST_CAT_PERFORMANCE = NULL;
+GstDebugCategory *GST_CAT_PIPELINE = NULL;
+GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
+GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
+GstDebugCategory *GST_CAT_PROPERTIES = NULL;
+GstDebugCategory *GST_CAT_TYPES = NULL;
+GstDebugCategory *GST_CAT_XML = NULL;
+GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
+GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
+GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
+GstDebugCategory *GST_CAT_EVENT = NULL;
+GstDebugCategory *GST_CAT_MESSAGE = NULL;
+GstDebugCategory *GST_CAT_PARAMS = NULL;
+GstDebugCategory *GST_CAT_CALL_TRACE = NULL;
+GstDebugCategory *GST_CAT_SIGNAL = NULL;
+GstDebugCategory *GST_CAT_PROBE = NULL;
+GstDebugCategory *GST_CAT_REGISTRY = NULL;
+GstDebugCategory *GST_CAT_QOS = NULL;
+
+#endif /* !defined(GST_DISABLE_GST_DEBUG) || !defined(GST_REMOVE_DISABLED) */
+
+#ifndef GST_DISABLE_GST_DEBUG
 
 /* underscore is to prevent conflict with GST_CAT_DEBUG define */
 GST_DEBUG_CATEGORY_STATIC (_GST_CAT_DEBUG);
@@ -163,9 +219,14 @@
     const struct printf_info *info, const void *const *args);
 static int _gst_info_printf_extension_segment (FILE * stream,
     const struct printf_info *info, const void *const *args);
+#if HAVE_REGISTER_PRINTF_SPECIFIER
+static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
+    size_t n, int *argtypes, int *size);
+#else
 static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
     size_t n, int *argtypes);
 #endif
+#endif
 
 struct _GstDebugMessage
 {
@@ -198,47 +259,12 @@
 static GStaticMutex __log_func_mutex = G_STATIC_MUTEX_INIT;
 static GSList *__log_functions = NULL;
 
+#define PRETTY_TAGS_DEFAULT  TRUE
+static gboolean pretty_tags = PRETTY_TAGS_DEFAULT;
+
 static gint __default_level;
 static gint __use_color;
 
-/* disabled by default, as soon as some threshold is set > NONE,
- * it becomes enabled. */
-gboolean __gst_debug_enabled = FALSE;
-GstDebugLevel __gst_debug_min = GST_LEVEL_NONE;
-
-GstDebugCategory *GST_CAT_DEFAULT = NULL;
-
-GstDebugCategory *GST_CAT_GST_INIT = NULL;
-GstDebugCategory *GST_CAT_AUTOPLUG = NULL;
-GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT = NULL;
-GstDebugCategory *GST_CAT_PARENTAGE = NULL;
-GstDebugCategory *GST_CAT_STATES = NULL;
-GstDebugCategory *GST_CAT_SCHEDULING = NULL;
-
-GstDebugCategory *GST_CAT_BUFFER = NULL;
-GstDebugCategory *GST_CAT_BUS = NULL;
-GstDebugCategory *GST_CAT_CAPS = NULL;
-GstDebugCategory *GST_CAT_CLOCK = NULL;
-GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL;
-GstDebugCategory *GST_CAT_PADS = NULL;
-GstDebugCategory *GST_CAT_PIPELINE = NULL;
-GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
-GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
-GstDebugCategory *GST_CAT_PROPERTIES = NULL;
-GstDebugCategory *GST_CAT_TYPES = NULL;
-GstDebugCategory *GST_CAT_XML = NULL;
-GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
-GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
-GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
-GstDebugCategory *GST_CAT_EVENT = NULL;
-GstDebugCategory *GST_CAT_MESSAGE = NULL;
-GstDebugCategory *GST_CAT_PARAMS = NULL;
-GstDebugCategory *GST_CAT_CALL_TRACE = NULL;
-GstDebugCategory *GST_CAT_SIGNAL = NULL;
-GstDebugCategory *GST_CAT_PROBE = NULL;
-GstDebugCategory *GST_CAT_REGISTRY = NULL;
-GstDebugCategory *GST_CAT_QOS = NULL;
-
 /* FIXME: export this? */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -256,7 +282,7 @@
   in_valgrind = GST_VG_UNCHECKED;
 
   if (in_valgrind == GST_VG_UNCHECKED) {
-#ifdef HAVE_VALGRIND
+#ifdef HAVE_VALGRIND_H
     if (RUNNING_ON_VALGRIND) {
       GST_CAT_INFO (GST_CAT_GST_INIT, "we're running inside valgrind");
       printf ("GStreamer has detected that it is running inside valgrind.\n");
@@ -289,18 +315,30 @@
 void
 _gst_debug_init (void)
 {
-  gst_atomic_int_set (&__default_level, GST_LEVEL_DEFAULT);
-  gst_atomic_int_set (&__use_color, 1);
+  const gchar *env;
 
+  g_atomic_int_set (&__default_level, GST_LEVEL_DEFAULT);
+#ifndef __SYMBIAN32__
+  g_atomic_int_set (&__use_color, 1);
+#else
+  g_atomic_int_set (&__use_color, 0);
+#endif
   /* get time we started for debugging messages */
   _priv_gst_info_start_time = gst_util_get_timestamp ();
 
 #ifdef HAVE_PRINTF_EXTENSION
+#if HAVE_REGISTER_PRINTF_SPECIFIER
+  register_printf_specifier (GST_PTR_FORMAT[0], _gst_info_printf_extension_ptr,
+      _gst_info_printf_extension_arginfo);
+  register_printf_specifier (GST_SEGMENT_FORMAT[0],
+      _gst_info_printf_extension_segment, _gst_info_printf_extension_arginfo);
+#else
   register_printf_function (GST_PTR_FORMAT[0], _gst_info_printf_extension_ptr,
       _gst_info_printf_extension_arginfo);
   register_printf_function (GST_SEGMENT_FORMAT[0],
       _gst_info_printf_extension_segment, _gst_info_printf_extension_arginfo);
 #endif
+#endif
 
   /* do NOT use a single debug function before this line has been run */
   GST_CAT_DEFAULT = _gst_debug_category_new ("default",
@@ -325,6 +363,8 @@
       GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL);
   GST_CAT_BUFFER = _gst_debug_category_new ("GST_BUFFER",
       GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL);
+  GST_CAT_BUFFER_LIST = _gst_debug_category_new ("GST_BUFFER_LIST",
+      GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL);
   GST_CAT_BUS = _gst_debug_category_new ("GST_BUS", GST_DEBUG_BG_YELLOW, NULL);
   GST_CAT_CAPS = _gst_debug_category_new ("GST_CAPS",
       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
@@ -333,6 +373,8 @@
   GST_CAT_ELEMENT_PADS = _gst_debug_category_new ("GST_ELEMENT_PADS",
       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
   GST_CAT_PADS = _gst_debug_category_new ("GST_PADS",
+      GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_RED, NULL);
+  GST_CAT_PERFORMANCE = _gst_debug_category_new ("GST_PERFORMANCE",
       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
   GST_CAT_PIPELINE = _gst_debug_category_new ("GST_PIPELINE",
       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
@@ -371,6 +413,14 @@
 
   /* print out the valgrind message if we're in valgrind */
   _priv_gst_in_valgrind ();
+
+  env = g_getenv ("GST_DEBUG_OPTIONS");
+  if (env != NULL) {
+    if (strstr (env, "full_tags") || strstr (env, "full-tags"))
+      pretty_tags = FALSE;
+    else if (strstr (env, "pretty_tags") || strstr (env, "pretty-tags"))
+      pretty_tags = TRUE;
+  }
 }
 
 /* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */
@@ -432,11 +482,24 @@
   LogFuncEntry *entry;
   GSList *handler;
 
+#ifdef _MSC_VER
+  gchar *file_basename;
+#endif
+
   g_return_if_fail (category != NULL);
   g_return_if_fail (file != NULL);
   g_return_if_fail (function != NULL);
   g_return_if_fail (format != NULL);
 
+#ifdef _MSC_VER
+  /*
+   * The predefined macro __FILE__ is always the exact path given to the
+   * compiler with MSVC, which may or may not be the basename.  We work
+   * around it at runtime to improve the readability.
+   */
+  file = file_basename = g_path_get_basename (file);
+#endif
+
   message.message = NULL;
   message.format = format;
   G_VA_COPY (message.arguments, args);
@@ -450,6 +513,10 @@
   }
   g_free (message.message);
   va_end (message.arguments);
+
+#ifdef _MSC_VER
+  g_free (file_basename);
+#endif
 }
 
 /**
@@ -474,6 +541,54 @@
   return message->message;
 }
 
+#define MAX_BUFFER_DUMP_STRING_LEN  100
+
+/* structure_to_pretty_string:
+ * @structure: a #GstStructure
+ *
+ * Converts @structure to a human-readable string representation. Basically
+ * the same as gst_structure_to_string(), but if the structure contains large
+ * buffers such as images the hex representation of those buffers will be
+ * shortened so that the string remains readable.
+ *
+ * Returns: a newly-allocated string. g_free() when no longer needed.
+ */
+static gchar *
+structure_to_pretty_string (const GstStructure * s)
+{
+  gchar *str, *pos, *end;
+
+  str = gst_structure_to_string (s);
+  if (str == NULL)
+    return NULL;
+
+  pos = str;
+  while ((pos = strstr (pos, "(buffer)"))) {
+    guint count = 0;
+
+    pos += strlen ("(buffer)");
+    for (end = pos; *end != '\0' && *end != ';' && *end != ' '; ++end)
+      ++count;
+    if (count > MAX_BUFFER_DUMP_STRING_LEN) {
+      memcpy (pos + MAX_BUFFER_DUMP_STRING_LEN - 6, "..", 2);
+      memcpy (pos + MAX_BUFFER_DUMP_STRING_LEN - 4, pos + count - 4, 4);
+      g_memmove (pos + MAX_BUFFER_DUMP_STRING_LEN, pos + count,
+          strlen (pos + count) + 1);
+      pos += MAX_BUFFER_DUMP_STRING_LEN;
+    }
+  }
+
+  return str;
+}
+
+static inline gchar *
+gst_info_structure_to_string (GstStructure * s)
+{
+  if (G_UNLIKELY (pretty_tags && s->name == GST_QUARK (TAGLIST)))
+    return structure_to_pretty_string (s);
+  else
+    return gst_structure_to_string (s);
+}
 
 static gchar *
 gst_debug_print_object (gpointer ptr)
@@ -501,7 +616,7 @@
     return gst_caps_to_string ((GstCaps *) ptr);
   }
   if (*(GType *) ptr == GST_TYPE_STRUCTURE) {
-    return gst_structure_to_string ((GstStructure *) ptr);
+    return gst_info_structure_to_string ((GstStructure *) ptr);
   }
 #ifdef USE_POISONING
   if (*(guint32 *) ptr == 0xffffffff) {
@@ -522,7 +637,7 @@
     gchar *s, *ret;
 
     if (msg->structure) {
-      s = gst_structure_to_string (msg->structure);
+      s = gst_info_structure_to_string (msg->structure);
     } else {
       s = g_strdup ("(NULL)");
     }
@@ -533,6 +648,22 @@
     g_free (s);
     return ret;
   }
+  if (GST_IS_QUERY (object)) {
+    GstQuery *query = GST_QUERY_CAST (object);
+
+    if (query->structure) {
+      return gst_info_structure_to_string (query->structure);
+    } else {
+      const gchar *query_type_name;
+
+      query_type_name = gst_query_type_get_name (query->type);
+      if (G_LIKELY (query_type_name != NULL)) {
+        return g_strdup_printf ("%s query", query_type_name);
+      } else {
+        return g_strdup_printf ("query of unknown type %d", query->type);
+      }
+    }
+  }
 
   return g_strdup_printf ("%p", ptr);
 }
@@ -623,6 +754,124 @@
 }
 
 /**
+ * gst_debug_construct_win_color:
+ * @colorinfo: the color info
+ *
+ * Constructs an integer that can be used for getting the desired color in
+ * windows' terminals (cmd.exe). As there is no mean to underline, we simply
+ * ignore this attribute.
+ *
+ * This function returns 0 on non-windows machines.
+ *
+ * Returns: an integer containing the color definition
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gint
+gst_debug_construct_win_color (guint colorinfo)
+{
+  gint color = 0;
+#ifdef G_OS_WIN32
+  static const guchar ansi_to_win_fg[8] = {
+    0,                          /* black   */
+    FOREGROUND_RED,             /* red     */
+    FOREGROUND_GREEN,           /* green   */
+    FOREGROUND_RED | FOREGROUND_GREEN,  /* yellow  */
+    FOREGROUND_BLUE,            /* blue    */
+    FOREGROUND_RED | FOREGROUND_BLUE,   /* magenta */
+    FOREGROUND_GREEN | FOREGROUND_BLUE, /* cyan    */
+    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* white   */
+  };
+  static const guchar ansi_to_win_bg[8] = {
+    0,
+    BACKGROUND_RED,
+    BACKGROUND_GREEN,
+    BACKGROUND_RED | BACKGROUND_GREEN,
+    BACKGROUND_BLUE,
+    BACKGROUND_RED | BACKGROUND_BLUE,
+    BACKGROUND_GREEN | FOREGROUND_BLUE,
+    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
+  };
+
+  /* we draw black as white, as cmd.exe can only have black bg */
+  if (colorinfo == 0) {
+    return ansi_to_win_fg[7];
+  }
+
+  if (colorinfo & GST_DEBUG_BOLD) {
+    color |= FOREGROUND_INTENSITY;
+  }
+  if (colorinfo & GST_DEBUG_FG_MASK) {
+    color |= ansi_to_win_fg[colorinfo & GST_DEBUG_FG_MASK];
+  }
+  if (colorinfo & GST_DEBUG_BG_MASK) {
+    color |= ansi_to_win_bg[(colorinfo & GST_DEBUG_BG_MASK) >> 4];
+  }
+#endif
+  return color;
+}
+
+/* width of %p varies depending on actual value of pointer, which can make
+ * output unevenly aligned if multiple threads are involved, hence the %14p
+ * (should really be %18p, but %14p seems a good compromise between too many
+ * white spaces and likely unalignment on my system) */
+#if defined (GLIB_SIZEOF_VOID_P) && GLIB_SIZEOF_VOID_P == 8
+#define PTR_FMT "%14p"
+#else
+#define PTR_FMT "%10p"
+#endif
+#define PID_FMT "%5d"
+#define CAT_FMT "%20s %s:%d:%s:%s"
+
+#ifdef G_OS_WIN32
+static const guchar levelcolormap[GST_LEVEL_COUNT] = {
+  /* GST_LEVEL_NONE */
+  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
+  /* GST_LEVEL_ERROR */
+  FOREGROUND_RED | FOREGROUND_INTENSITY,
+  /* GST_LEVEL_WARNING */
+  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+  /* GST_LEVEL_INFO */
+  FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+  /* GST_LEVEL_DEBUG */
+  FOREGROUND_GREEN | FOREGROUND_BLUE,
+  /* GST_LEVEL_LOG */
+  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
+  /* GST_LEVEL_FIXME */
+  FOREGROUND_RED | FOREGROUND_GREEN,
+  /* placeholder for log level 7 */
+  0,
+  /* placeholder for log level 8 */
+  0,
+  /* GST_LEVEL_MEMDUMP */
+  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
+};
+
+static const guchar available_colors[] = {
+  FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_RED | FOREGROUND_GREEN,
+  FOREGROUND_BLUE, FOREGROUND_RED | FOREGROUND_BLUE,
+  FOREGROUND_GREEN | FOREGROUND_BLUE,
+};
+#else
+static const gchar *levelcolormap[GST_LEVEL_COUNT] = {
+  "\033[37m",                   /* GST_LEVEL_NONE */
+  "\033[31;01m",                /* GST_LEVEL_ERROR */
+  "\033[33;01m",                /* GST_LEVEL_WARNING */
+  "\033[32;01m",                /* GST_LEVEL_INFO */
+  "\033[36m",                   /* GST_LEVEL_DEBUG */
+  "\033[37m",                   /* GST_LEVEL_LOG */
+  "\033[33;01m",                /* GST_LEVEL_FIXME */
+  "\033[37m",                   /* placeholder for log level 7 */
+  "\033[37m",                   /* placeholder for log level 8 */
+  "\033[37m"                    /* GST_LEVEL_MEMDUMP */
+};
+#endif
+
+/**
  * gst_debug_log_default:
  * @category: category to log
  * @level: level of the message
@@ -649,43 +898,20 @@
     const gchar * file, const gchar * function, gint line,
     GObject * object, GstDebugMessage * message, gpointer unused)
 {
-  gchar *color = NULL;
-  gchar *clear;
-  gchar *obj = NULL;
-  gchar pidcolor[10];
-  const gchar *levelcolor;
   gint pid;
   GstClockTime elapsed;
-  gboolean free_color = TRUE;
+  gchar *obj = NULL;
   gboolean free_obj = TRUE;
-  static const gchar *levelcolormap[] = {
-    "\033[37m",                 /* GST_LEVEL_NONE */
-    "\033[31;01m",              /* GST_LEVEL_ERROR */
-    "\033[33;01m",              /* GST_LEVEL_WARNING */
-    "\033[32;01m",              /* GST_LEVEL_INFO */
-    "\033[36m",                 /* GST_LEVEL_DEBUG */
-    "\033[37m"                  /* GST_LEVEL_LOG */
-  };
+  gboolean is_colored;
 
   if (level > gst_debug_category_get_threshold (category))
     return;
 
   pid = getpid ();
+  is_colored = gst_debug_is_colored ();
 
-  /* color info */
-  if (gst_debug_is_colored ()) {
-    color = gst_debug_construct_term_color (gst_debug_category_get_color
-        (category));
-    clear = "\033[00m";
-    g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31);
-    levelcolor = levelcolormap[level];
-  } else {
-    color = "\0";
-    free_color = FALSE;
-    clear = "";
-    pidcolor[0] = '\0';
-    levelcolor = "\0";
-  }
+  elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
+      gst_util_get_timestamp ());
 
   if (object) {
     obj = gst_debug_print_object (object);
@@ -694,26 +920,78 @@
     free_obj = FALSE;
   }
 
-  elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
-      gst_util_get_timestamp ());
+  if (is_colored) {
+#ifndef G_OS_WIN32
+    /* colors, non-windows */
+    gchar *color = NULL;
+    gchar *clear;
+    gchar pidcolor[10];
+    const gchar *levelcolor;
+
+    color = gst_debug_construct_term_color (gst_debug_category_get_color
+        (category));
+    clear = "\033[00m";
+    g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31);
+    levelcolor = levelcolormap[level];
 
-  /*
-     g_printerr ("%s (%p - %" GST_TIME_FORMAT ") %s%20s%s(%s%5d%s) %s%s(%d):%s:%s%s %s\n",
-     gst_debug_level_get_name (level), g_thread_self (),
-     GST_TIME_ARGS (elapsed), color,
-     gst_debug_category_get_name (category), clear, pidcolor, pid, clear,
-     color, file, line, function, obj, clear, gst_debug_message_get (message));
-   */
+#ifdef __SYMBIAN32__
+    g_printerr ("%" GST_TIME_FORMAT
+        " %s%5d%s %10p %s%s%s %s%20s %s:%d:%s:%s%s %s\n", GST_TIME_ARGS (elapsed),
+        pidcolor, pid, clear, g_thread_self (), levelcolor,
+        gst_debug_level_get_name (level), clear, color,
+        gst_debug_category_get_name (category), file, line, function, obj, clear,
+        gst_debug_message_get (message));
+#else
+#define PRINT_FMT " %s"PID_FMT"%s "PTR_FMT" %s%s%s %s"CAT_FMT"%s %s\n"
+    g_printerr ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed),
+        pidcolor, pid, clear, g_thread_self (), levelcolor,
+        gst_debug_level_get_name (level), clear, color,
+        gst_debug_category_get_name (category), file, line, function, obj,
+        clear, gst_debug_message_get (message));
+#undef PRINT_FMT
+#endif //__SYMBIAN32__
+    
+    g_free (color);
+#else
+    /* colors, windows. We take a lock to keep colors and content together.
+     * Maybe there is a better way but for now this will do the right
+     * thing. */
+    static GStaticMutex win_print_mutex = G_STATIC_MUTEX_INIT;
+    const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+#define SET_COLOR(c) \
+  SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (c));
+    g_static_mutex_lock (&win_print_mutex);
+    /* timestamp */
+    g_printerr ("%" GST_TIME_FORMAT " ", GST_TIME_ARGS (elapsed));
+    /* pid */
+    SET_COLOR (available_colors[pid % G_N_ELEMENTS (available_colors)]);
+    g_printerr (PID_FMT, pid);
+    /* thread */
+    SET_COLOR (clear);
+    g_printerr (" " PTR_FMT " ", g_thread_self ());
+    /* level */
+    SET_COLOR (levelcolormap[level]);
+    g_printerr ("%s ", gst_debug_level_get_name (level));
+    /* category */
+    SET_COLOR (gst_debug_construct_win_color (gst_debug_category_get_color
+            (category)));
+    g_printerr (CAT_FMT, gst_debug_category_get_name (category),
+        file, line, function, obj);
+    /* message */
+    SET_COLOR (clear);
+    g_printerr (" %s\n", gst_debug_message_get (message));
+    g_static_mutex_unlock (&win_print_mutex);
+#endif
+  } else {
+    /* no color, all platforms */
+#define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
+    g_printerr ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed), pid,
+        g_thread_self (), gst_debug_level_get_name (level),
+        gst_debug_category_get_name (category), file, line, function, obj,
+        gst_debug_message_get (message));
+#undef PRINT_FMT
+  }
 
-  g_printerr ("%" GST_TIME_FORMAT
-      " %s%5d%s %p %s%s%s %s%20s %s:%d:%s:%s%s %s\n", GST_TIME_ARGS (elapsed),
-      pidcolor, pid, clear, g_thread_self (), levelcolor,
-      gst_debug_level_get_name (level), clear, color,
-      gst_debug_category_get_name (category), file, line, function, obj, clear,
-      gst_debug_message_get (message));
-
-  if (free_color)
-    g_free (color);
   if (free_obj)
     g_free (obj);
 }
@@ -737,15 +1015,19 @@
     case GST_LEVEL_NONE:
       return "";
     case GST_LEVEL_ERROR:
-      return "ERROR";
+      return "ERROR  ";
     case GST_LEVEL_WARNING:
-      return "WARN ";
+      return "WARN   ";
     case GST_LEVEL_INFO:
-      return "INFO ";
+      return "INFO   ";
     case GST_LEVEL_DEBUG:
-      return "DEBUG";
+      return "DEBUG  ";
     case GST_LEVEL_LOG:
-      return "LOG  ";
+      return "LOG    ";
+    case GST_LEVEL_FIXME:
+      return "FIXME  ";
+    case GST_LEVEL_MEMDUMP:
+      return "MEMDUMP";
     default:
       g_warning ("invalid level specified for gst_debug_level_get_name");
       return "";
@@ -817,6 +1099,8 @@
   new = __log_functions;
   while ((found = g_slist_find_custom (new, data, func))) {
     if (new == __log_functions) {
+      /* make a copy when we have the first hit, so that we modify the copy and
+       * make that the new list later */
       new = g_slist_copy (new);
       continue;
     }
@@ -899,7 +1183,7 @@
 void
 gst_debug_set_colored (gboolean colored)
 {
-  gst_atomic_int_set (&__use_color, colored ? 1 : 0);
+  g_atomic_int_set (&__use_color, colored ? 1 : 0);
 }
 
 /**
@@ -974,7 +1258,7 @@
 void
 gst_debug_set_default_threshold (GstDebugLevel level)
 {
-  gst_atomic_int_set (&__default_level, level);
+  g_atomic_int_set (&__default_level, level);
   gst_debug_reset_all_thresholds ();
 }
 
@@ -994,6 +1278,7 @@
 {
   return (GstDebugLevel) g_atomic_int_get (&__default_level);
 }
+
 static void
 gst_debug_reset_threshold (gpointer category, gpointer unused)
 {
@@ -1018,6 +1303,7 @@
 exit:
   g_static_mutex_unlock (&__level_name_mutex);
 }
+
 static void
 gst_debug_reset_all_thresholds (void)
 {
@@ -1025,6 +1311,7 @@
   g_slist_foreach (__categories, gst_debug_reset_threshold, NULL);
   g_static_mutex_unlock (&__cat_mutex);
 }
+
 static void
 for_each_threshold_by_entry (gpointer data, gpointer user_data)
 {
@@ -1128,7 +1415,7 @@
   } else {
     cat->description = g_strdup ("no description");
   }
-  gst_atomic_int_set (&cat->threshold, 0);
+  g_atomic_int_set (&cat->threshold, 0);
   gst_debug_reset_threshold (cat, NULL);
 
   /* add to category list */
@@ -1194,7 +1481,7 @@
     __gst_debug_min = level;
   }
 
-  gst_atomic_int_set (&category->threshold, level);
+  g_atomic_int_set (&category->threshold, level);
 }
 
 /**
@@ -1314,6 +1601,25 @@
 
   return ret;
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GstDebugCategory *
+_gst_debug_get_category (const gchar * name)
+{
+  GstDebugCategory *ret = NULL;
+  GSList *node;
+
+  for (node = __categories; node; node = g_slist_next (node)) {
+    ret = (GstDebugCategory *) node->data;
+    if (!strcmp (name, ret->name)) {
+      return ret;
+    }
+  }
+  return NULL;
+}
 
 /*** FUNCTION POINTERS ********************************************************/
 
@@ -1427,28 +1733,376 @@
   return len;
 }
 
+#if HAVE_REGISTER_PRINTF_SPECIFIER
+static int
+_gst_info_printf_extension_arginfo (const struct printf_info *info, size_t n,
+    int *argtypes, int *size)
+#else
 static int
 _gst_info_printf_extension_arginfo (const struct printf_info *info, size_t n,
     int *argtypes)
+#endif
 {
-  if (n > 0)
+  if (n > 0) {
     argtypes[0] = PA_POINTER;
+#if HAVE_REGISTER_PRINTF_SPECIFIER
+    *size = sizeof (gpointer);
+#endif
+  }
   return 1;
 }
 #endif /* HAVE_PRINTF_EXTENSION */
 
+static void
+gst_info_dump_mem_line (gchar * linebuf, gsize linebuf_size,
+    const guint8 * mem, gsize mem_offset, gsize mem_size)
+{
+  gchar hexstr[50], ascstr[18], digitstr[4];
+
+  if (mem_size > 16)
+    mem_size = 16;
+
+  hexstr[0] = '\0';
+  ascstr[0] = '\0';
+
+  if (mem != NULL) {
+    guint i = 0;
+
+    mem += mem_offset;
+    while (i < mem_size) {
+      ascstr[i] = (g_ascii_isprint (mem[i])) ? mem[i] : '.';
+      g_snprintf (digitstr, sizeof (digitstr), "%02x ", mem[i]);
+      g_strlcat (hexstr, digitstr, sizeof (hexstr));
+      ++i;
+    }
+    ascstr[i] = '\0';
+  }
+
+  g_snprintf (linebuf, linebuf_size, "%08x: %-48.48s %-16.16s",
+      (guint) mem_offset, hexstr, ascstr);
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+_gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
+    const gchar * func, gint line, GObject * obj, const gchar * msg,
+    const guint8 * data, guint length)
+{
+  guint off = 0;
+
+  gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "--------"
+      "-------------------------------------------------------------------");
+
+  if (msg != NULL && *msg != '\0') {
+    gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, msg);
+  }
+
+  while (off < length) {
+    gchar buf[128];
+
+    /* gst_info_dump_mem_line will process 16 bytes at most */
+    gst_info_dump_mem_line (buf, sizeof (buf), data, off, length - off);
+    gst_debug_log (cat, GST_LEVEL_MEMDUMP, file, func, line, obj, "%s", buf);
+    off += 16;
+  }
+
+  gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "--------"
+      "-------------------------------------------------------------------");
+}
+
 #else /* !GST_DISABLE_GST_DEBUG */
+#ifdef GST_REMOVE_DISABLED
+
+GstDebugCategory *
+_gst_debug_category_new (const gchar * name, guint color,
+    const gchar * description)
+{
+  return NULL;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+_gst_debug_register_funcptr (gpointer func, const gchar * ptrname)
+{
+}
+
+/* This function MUST NOT return NULL */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+const gchar *
+_gst_debug_nameof_funcptr (gpointer func)
+{
+  return "(NULL)";
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_log (GstDebugCategory * category, GstDebugLevel level,
+    const gchar * file, const gchar * function, gint line,
+    GObject * object, const gchar * format, ...)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level,
+    const gchar * file, const gchar * function, gint line,
+    GObject * object, const gchar * format, va_list args)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+const gchar *
+gst_debug_message_get (GstDebugMessage * message)
+{
+  return "";
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
+    const gchar * file, const gchar * function, gint line,
+    GObject * object, GstDebugMessage * message, gpointer unused)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+G_CONST_RETURN gchar *
+gst_debug_level_get_name (GstDebugLevel level)
+{
+  return "NONE";
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_add_log_function (GstLogFunction func, gpointer data)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
 guint
 gst_debug_remove_log_function (GstLogFunction func)
 {
   return 0;
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
 
 guint
 gst_debug_remove_log_function_by_data (gpointer data)
 {
   return 0;
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_set_active (gboolean active)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_debug_is_active (void)
+{
+  return FALSE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_set_colored (gboolean colored)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_debug_is_colored (void)
+{
+  return FALSE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_set_default_threshold (GstDebugLevel level)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GstDebugLevel
+gst_debug_get_default_threshold (void)
+{
+  return GST_LEVEL_NONE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_unset_threshold_for_name (const gchar * name)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_category_free (GstDebugCategory * category)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_category_set_threshold (GstDebugCategory * category,
+    GstDebugLevel level)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_debug_category_reset_threshold (GstDebugCategory * category)
+{
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GstDebugLevel
+gst_debug_category_get_threshold (GstDebugCategory * category)
+{
+  return GST_LEVEL_NONE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+G_CONST_RETURN gchar *
+gst_debug_category_get_name (GstDebugCategory * category)
+{
+  return "";
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+guint
+gst_debug_category_get_color (GstDebugCategory * category)
+{
+  return 0;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+G_CONST_RETURN gchar *
+gst_debug_category_get_description (GstDebugCategory * category)
+{
+  return "";
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GSList *
+gst_debug_get_all_categories (void)
+{
+  return NULL;
+}
+
+GstDebugCategory *
+_gst_debug_get_category (const gchar * name)
+{
+  return NULL;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gchar *
+gst_debug_construct_term_color (guint colorinfo)
+{
+  return g_strdup ("00");
+}
+
+gint
+gst_debug_construct_win_color (guint colorinfo)
+{
+  return 0;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
 
 gboolean
 _priv_gst_in_valgrind (void)
@@ -1456,6 +2110,13 @@
   return FALSE;
 }
 
+void
+_gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
+    const gchar * func, gint line, GObject * obj, const gchar * msg,
+    const guint8 * data, guint length)
+{
+}
+#endif /* GST_REMOVE_DISABLED */
 #endif /* GST_DISABLE_GST_DEBUG */
 
 
@@ -1523,6 +2184,9 @@
   }
 }
 #else
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 void
 gst_debug_print_stack_trace (void)
 {
@@ -1550,6 +2214,14 @@
 EXPORT_C
 #endif
 
+GstDebugLevel*   gst_debug_min()
+{
+    return &__gst_debug_min;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
 GstDebugCategory** _GST_CAT_QOS()
 {
 	return &GST_CAT_QOS;
--- a/gstreamer_core/gst/gstinfo.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstinfo.h	Fri Apr 16 15:15:52 2010 +0300
@@ -28,17 +28,6 @@
 #include <glib-object.h>
 #include <gst/gstconfig.h>
 
-
-#ifndef _MSC_VER
-#define IMPORT_SYMBOL
-#else /* _MSC_VER */
-#ifndef LIBGSTREAMER_EXPORTS
-#define IMPORT_SYMBOL __declspec(dllimport)
-#else
-#define IMPORT_SYMBOL 
-#endif
-#endif
-
 #ifndef M_PI
 #define M_PI  3.14159265358979323846
 #endif
@@ -70,6 +59,14 @@
  *  useful to know. As a rule of thumb a pipeline that is iterating as expected
  *  should never output anzthing else but LOG messages.
  *  Examples for this are referencing/dereferencing of objects or cothread switches.
+ * @GST_LEVEL_FIXME: Fixme messages are messages that indicate that something
+ *  in the executed code path is not fully implemented or handled yet. Note
+ *  that this does not replace proper error handling in any way, the purpose
+ *  of this message is to make it easier to spot incomplete/unfinished pieces
+ *  of code when reading the debug log. (Since: 0.10.23)
+ * @GST_LEVEL_MEMDUMP: memory dump messages are used to log (small) chunks of
+ *  data as memory dumps in the log. They will be displayed as hexdump with
+ *  ASCII characters. (Since: 0.10.23)
  * @GST_LEVEL_COUNT: The number of defined debugging levels.
  *
  * The level defines the importance of a debugging message. The more important a
@@ -82,6 +79,9 @@
   GST_LEVEL_INFO,
   GST_LEVEL_DEBUG,
   GST_LEVEL_LOG,
+  GST_LEVEL_FIXME = 6,
+  /* add more */
+  GST_LEVEL_MEMDUMP = 9,
   /* add more */
   GST_LEVEL_COUNT
 } GstDebugLevel;
@@ -213,14 +213,17 @@
  * be defined when configuring your project, as it is compiler dependant. If it
  * is not defined, some default value is used. It is used to provide debugging
  * output with the function name of the message.
+ *
+ * Note that this is different from G_STRFUNC as we do not want the full
+ * function signature in C++ code.
  */
 #ifndef GST_FUNCTION
-#if defined (__GNUC__)
+#if defined (__GNUC__) || (defined (_MSC_VER) && _MSC_VER >= 1300)
 #  define GST_FUNCTION     ((const char*) (__FUNCTION__))
-#elif defined (G_HAVE_ISO_VARARGS)
+#elif defined (__STDC__) && defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 #  define GST_FUNCTION     ((const char*) (__func__))
 #else
-#  define GST_FUNCTION     ((const char*) ("???"))
+#  define GST_FUNCTION     ((const char*) (__PRETTY_FUNCTION__))
 #endif
 #endif /* ifndef GST_FUNCTION */
 
@@ -415,7 +418,8 @@
  * This macro expands to nothing if debugging is disabled.
  */
 #define GST_DEBUG_CATEGORY_STATIC(cat) static GstDebugCategory *cat = NULL
-/* do not use this function, use the macros below */
+
+/* do not use this function, use the GST_DEBUG_CATEGORY_INIT macro below */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -508,12 +512,54 @@
 
 GSList *
         gst_debug_get_all_categories	(void);
+
+/* do not use this function, use the GST_DEBUG_CATEGORY_GET macro below */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+GstDebugCategory *_gst_debug_get_category (const gchar *name);
 
-gchar *	gst_debug_construct_term_color	(guint colorinfo);
+/**
+ * GST_DEBUG_CATEGORY_GET:
+ * @cat: the category to initialize.
+ * @name: log category name
+ *
+ * Lookup an exiting #GstDebugCategory by its @name and sets @cat. If category
+ * is not found, but %GST_CAT_DEFAULT is defined, that is assigned to @cat.
+ * Otherwise cat will be NULL.
+ *
+ * |[
+ * GST_DEBUG_CATEGORY_STATIC (gst_myplugin_debug);
+ * #define GST_CAT_DEFAULT gst_myplugin_debug
+ * GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
+ * ...
+ * GST_DEBUG_CATEGORY_INIT (gst_myplugin_debug, "myplugin", 0, "nice element");
+ * GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "performance);
+ * ]|
+ *
+ * Since: 0.10.24
+ */
+#ifdef GST_CAT_DEFAULT
+#define GST_DEBUG_CATEGORY_GET(cat,name)  G_STMT_START{\
+  cat = _gst_debug_get_category (name);			\
+  if (!cat) {						\
+    cat = GST_CAT_DEFAULT;				\
+  }							\
+}G_STMT_END
+#else
+#define GST_DEBUG_CATEGORY_GET(cat,name)  G_STMT_START{\
+  cat = _gst_debug_get_category (name);			\
+}G_STMT_END
+#endif
+
+
+gchar * gst_debug_construct_term_color	(guint colorinfo);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gint    gst_debug_construct_win_color (guint colorinfo);
 
 
 /**
@@ -525,6 +571,10 @@
 /* this symbol may not be used */
 extern gboolean			__gst_debug_enabled;
 
+/* since 0.10.7, the min debug level, used for quickly discarding debug
+ * messages that fall under the threshold. */
+GST_EXPORT GstDebugLevel            __gst_debug_min; 
+
 #ifdef __SYMBIAN32__
 GstDebugCategory ** _GST_CAT_DEFAULT();
 #ifdef __SYMBIAN32__
@@ -535,17 +585,18 @@
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
-
 GstDebugCategory** _GST_CAT_QOS();
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 GstDebugCategory ** _GST_CAT_DEFAULT();
+
+#ifdef __SYMBIAN32__
+IMPORT_C
 #endif
-/* since 0.10.7, the min debug level, used for quickly discarding debug
- * messages that fall under the threshold. */
-extern IMPORT_SYMBOL GstDebugLevel            __gst_debug_min; 
+GstDebugLevel*            gst_debug_min();
+#endif
 
 /**
  * GST_CAT_LEVEL_LOG:
@@ -578,7 +629,7 @@
 GST_CAT_LEVEL_LOG_valist (GstDebugCategory * cat,
     GstDebugLevel level, gpointer object, const char *format, va_list varargs)
 {
-#ifdef DEBUG_ENABLE
+#ifdef __SYMBIAN32__
   GstDebugCategory** cat1;
   GstDebugCategory* p;
   cat1 = _GST_CAT_DEFAULT();
@@ -586,6 +637,11 @@
   if (G_UNLIKELY (level <= __gst_debug_min)) {
     gst_debug_log_valist (p, level, "", "", 0, (GObject *) object, format,
         varargs);
+    }
+#else
+    if (G_UNLIKELY (level <= __gst_debug_min)) {
+      gst_debug_log_valist (cat, level, "", "", 0, (GObject *) object, format,
+          varargs);
   }
 #endif
 }
@@ -603,6 +659,34 @@
 #endif
 #endif /* G_HAVE_ISO_VARARGS */
 
+/* private helper function */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
+    const gchar * func, gint line, GObject * obj, const gchar * msg,
+    const guint8 * data, guint length);
+
+/* This one doesn't have varargs in the macro, so it's different than all the
+ * other macros and hence in a separate block right here. Docs chunks are
+ * with the other doc chunks below though. */
+#define __GST_CAT_MEMDUMP_LOG(cat,object,msg,data,length) G_STMT_START{       \
+  if (G_UNLIKELY (GST_LEVEL_MEMDUMP <= __gst_debug_min)) {                    \
+    _gst_debug_dump_mem ((cat), __FILE__, GST_FUNCTION, __LINE__,             \
+        (GObject *) (object), (msg), (data), (length));                       \
+  }                                                                           \
+}G_STMT_END
+
+#define GST_CAT_MEMDUMP_OBJECT(cat,obj,msg,data,length)  \
+    __GST_CAT_MEMDUMP_LOG(cat,obj,msg,data,length)
+#define GST_CAT_MEMDUMP(cat,msg,data,length)             \
+    __GST_CAT_MEMDUMP_LOG(cat,NULL,msg,data,length)
+#define GST_MEMDUMP_OBJECT(obj,msg,data,length)          \
+    __GST_CAT_MEMDUMP_LOG(GST_CAT_DEFAULT,obj,msg,data,length)
+#define GST_MEMDUMP(msg,data,length)                     \
+    __GST_CAT_MEMDUMP_LOG(GST_CAT_DEFAULT,NULL,msg,data,length)
+
 /**
  * GST_CAT_ERROR_OBJECT:
  * @cat: category to use
@@ -644,6 +728,29 @@
  *
  * Output an logging message belonging to the given object in the given category.
  */
+/**
+ * GST_CAT_FIXME_OBJECT:
+ * @cat: category to use
+ * @obj: the #GObject the message belongs to
+ * @...: printf-style message to output
+ *
+ * Output a fixme message belonging to the given object in the given category.
+ *
+ * Since: 0.10.23
+ */
+/**
+ * GST_CAT_MEMDUMP_OBJECT:
+ * @cat: category to use
+ * @obj: the #GObject the message belongs to
+ * @msg: message string to log with the data
+ * @data: pointer to the data to output
+ * @length: length of the data to output
+ *
+ * Output a hexdump of @data relating to the given object in the given
+ * category.
+ *
+ * Since: 0.10.23
+ */
 
 
 /**
@@ -681,6 +788,26 @@
  *
  * Output an logging message in the given category.
  */
+/**
+ * GST_CAT_FIXME:
+ * @cat: category to use
+ * @...: printf-style message to output
+ *
+ * Output an fixme message in the given category.
+ *
+ * Since: 0.10.23
+ */
+/**
+ * GST_CAT_MEMDUMP:
+ * @cat: category to use
+ * @msg: message string to log with the data
+ * @data: pointer to the data to output
+ * @length: length of the data to output
+ *
+ * Output a hexdump of @data in the given category.
+ *
+ * Since: 0.10.23
+ */
 
 
 /**
@@ -720,6 +847,26 @@
  *
  * Output a logging message belonging to the given object in the default category.
  */
+/**
+ * GST_FIXME_OBJECT:
+ * @obj: the #GObject the message belongs to
+ * @...: printf-style message to output
+ *
+ * Output a logging message belonging to the given object in the default category.
+ *
+ * Since: 0.10.23
+ */
+/**
+ * GST_MEMDUMP_OBJECT:
+ * @obj: the #GObject the message belongs to
+ * @msg: message string to log with the data
+ * @data: pointer to the data to output
+ * @length: length of the data to output
+ *
+ * Output a logging message belonging to the given object in the default category.
+ *
+ * Since: 0.10.23
+ */
 
 
 /**
@@ -752,6 +899,24 @@
  *
  * Output a logging message in the default category.
  */
+/**
+ * GST_FIXME:
+ * @...: printf-style message to output
+ *
+ * Output a fixme message in the default category.
+ *
+ * Since: 0.10.23
+ */
+/**
+ * GST_MEMDUMP:
+ * @msg: message string to log with the data
+ * @data: pointer to the data to output
+ * @length: length of the data to output
+ *
+ * Output a hexdump of @data.
+ *
+ * Since: 0.10.23
+ */
 
 #ifdef G_HAVE_ISO_VARARGS
 
@@ -760,24 +925,28 @@
 #define GST_CAT_INFO_OBJECT(cat,obj,...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO,    obj,  __VA_ARGS__)
 #define GST_CAT_DEBUG_OBJECT(cat,obj,...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG,   obj,  __VA_ARGS__)
 #define GST_CAT_LOG_OBJECT(cat,obj,...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG,     obj,  __VA_ARGS__)
+#define GST_CAT_FIXME_OBJECT(cat,obj,...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME,   obj,  __VA_ARGS__)
 
 #define GST_CAT_ERROR(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR,   NULL, __VA_ARGS__)
 #define GST_CAT_WARNING(cat,...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, NULL, __VA_ARGS__)
 #define GST_CAT_INFO(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO,    NULL, __VA_ARGS__)
 #define GST_CAT_DEBUG(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG,   NULL, __VA_ARGS__)
 #define GST_CAT_LOG(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG,     NULL, __VA_ARGS__)
+#define GST_CAT_FIXME(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME,   NULL, __VA_ARGS__)
 
 #define GST_ERROR_OBJECT(obj,...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR,   obj,  __VA_ARGS__)
 #define GST_WARNING_OBJECT(obj,...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj,  __VA_ARGS__)
 #define GST_INFO_OBJECT(obj,...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO,    obj,  __VA_ARGS__)
 #define GST_DEBUG_OBJECT(obj,...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG,   obj,  __VA_ARGS__)
 #define GST_LOG_OBJECT(obj,...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG,     obj,  __VA_ARGS__)
+#define GST_FIXME_OBJECT(obj,...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME,   obj,  __VA_ARGS__)
 
 #define GST_ERROR(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR,   NULL, __VA_ARGS__)
 #define GST_WARNING(...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, __VA_ARGS__)
 #define GST_INFO(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO,    NULL, __VA_ARGS__)
 #define GST_DEBUG(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG,   NULL, __VA_ARGS__)
 #define GST_LOG(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG,     NULL, __VA_ARGS__)
+#define GST_FIXME(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME,   NULL, __VA_ARGS__)
 
 #else
 #ifdef G_HAVE_GNUC_VARARGS
@@ -787,24 +956,28 @@
 #define GST_CAT_INFO_OBJECT(cat,obj,args...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO,    obj,  ##args )
 #define GST_CAT_DEBUG_OBJECT(cat,obj,args...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG,   obj,  ##args )
 #define GST_CAT_LOG_OBJECT(cat,obj,args...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG,     obj,  ##args )
+#define GST_CAT_FIXME_OBJECT(cat,obj,args...)	GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME,   obj,  ##args )
 
 #define GST_CAT_ERROR(cat,args...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR,   NULL, ##args )
 #define GST_CAT_WARNING(cat,args...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, NULL, ##args )
 #define GST_CAT_INFO(cat,args...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO,    NULL, ##args )
 #define GST_CAT_DEBUG(cat,args...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG,   NULL, ##args )
 #define GST_CAT_LOG(cat,args...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG,     NULL, ##args )
+#define GST_CAT_FIXME(cat,args...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME,   NULL, ##args )
 
 #define GST_ERROR_OBJECT(obj,args...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR,   obj,  ##args )
 #define GST_WARNING_OBJECT(obj,args...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj,  ##args )
 #define GST_INFO_OBJECT(obj,args...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO,    obj,  ##args )
 #define GST_DEBUG_OBJECT(obj,args...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG,   obj,  ##args )
 #define GST_LOG_OBJECT(obj,args...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG,     obj,  ##args )
+#define GST_FIXME_OBJECT(obj,args...)	GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME,   obj,  ##args )
 
 #define GST_ERROR(args...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR,   NULL, ##args )
 #define GST_WARNING(args...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, ##args )
 #define GST_INFO(args...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO,    NULL, ##args )
 #define GST_DEBUG(args...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG,   NULL, ##args )
 #define GST_LOG(args...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG,     NULL, ##args )
+#define GST_FIXME(args...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME,   NULL, ##args )
 
 #else
 /* no variadic macros, use inline */
@@ -864,6 +1037,17 @@
 }
 
 static inline void
+GST_CAT_FIXME_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format,
+    ...)
+{
+  va_list varargs;
+
+  va_start (varargs, format);
+  GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_FIXME, obj, format, varargs);
+  va_end (varargs);
+}
+
+static inline void
 GST_CAT_ERROR (GstDebugCategory * cat, const char *format, ...)
 {
   va_list varargs;
@@ -914,6 +1098,16 @@
 }
 
 static inline void
+GST_CAT_FIXME (GstDebugCategory * cat, const char *format, ...)
+{
+  va_list varargs;
+
+  va_start (varargs, format);
+  GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_FIXME, NULL, format, varargs);
+  va_end (varargs);
+}
+
+static inline void
 GST_ERROR_OBJECT (gpointer obj, const char *format, ...)
 {
   va_list varargs;
@@ -969,6 +1163,17 @@
 }
 
 static inline void
+GST_FIXME_OBJECT (gpointer obj, const char *format, ...)
+{
+  va_list varargs;
+
+  va_start (varargs, format);
+  GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_FIXME, obj, format,
+      varargs);
+  va_end (varargs);
+}
+
+static inline void
 GST_ERROR (const char *format, ...)
 {
   va_list varargs;
@@ -1022,6 +1227,17 @@
       format, varargs);
   va_end (varargs);
 }
+
+static inline void
+GST_FIXME (const char *format, ...)
+{
+  va_list varargs;
+
+  va_start (varargs, format);
+  GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_FIXME, NULL, format,
+      varargs);
+  va_end (varargs);
+}
 #endif
 #endif
 
@@ -1069,19 +1285,23 @@
 #else /* GST_DISABLE_GST_DEBUG */
 
 
+#ifndef GST_INFO_C
+
 #if defined(__GNUC__) && __GNUC__ >= 3
 #  pragma GCC poison gst_debug_log
 #  pragma GCC poison gst_debug_log_valist
 #  pragma GCC poison _gst_debug_category_new
 #endif
 
+#define __gst_debug_min GST_LEVEL_NONE
+
 #define _gst_debug_init()				/* NOP */
 
 #define gst_debug_set_default_threshold(level)		/* NOP */
 #define gst_debug_get_default_threshold()		(GST_LEVEL_NONE)
 
 #define gst_debug_level_get_name(level)				("NONE")
-#define gst_debug_message_get(message)  			("NONE")
+#define gst_debug_message_get(message)  			("")
 #define gst_debug_add_log_function(func,data)		/* NOP */
 guint gst_debug_remove_log_function (GstLogFunction func);
 guint gst_debug_remove_log_function_by_data (gpointer data);
@@ -1102,6 +1322,7 @@
 #define GST_DEBUG_CATEGORY_STATIC(var)			/* NOP */
 #endif
 #define GST_DEBUG_CATEGORY_INIT(var,name,color,desc)	/* NOP */
+#define GST_DEBUG_CATEGORY_GET(var,name)		/* NOP */
 #define gst_debug_category_free(category)		/* NOP */
 #define gst_debug_category_set_threshold(category,level) /* NOP */
 #define gst_debug_category_reset_threshold(category)	/* NOP */
@@ -1111,6 +1332,9 @@
 #define gst_debug_category_get_description(cat)		("")
 #define gst_debug_get_all_categories()			(NULL)
 #define gst_debug_construct_term_color(colorinfo)	(g_strdup ("00"))
+#define gst_debug_construct_win_color(colorinfo)	(0)
+
+#endif /* !GST_INFO_C */
 
 #ifdef G_HAVE_ISO_VARARGS
 
@@ -1121,26 +1345,30 @@
 #define GST_CAT_INFO_OBJECT(...)			/* NOP */
 #define GST_CAT_DEBUG_OBJECT(...)			/* NOP */
 #define GST_CAT_LOG_OBJECT(...)				/* NOP */
+#define GST_CAT_FIXME_OBJECT(...)			/* NOP */
 
 #define GST_CAT_ERROR(...)				/* NOP */
 #define GST_CAT_WARNING(...)				/* NOP */
 #define GST_CAT_INFO(...)				/* NOP */
 #define GST_CAT_DEBUG(...)				/* NOP */
 #define GST_CAT_LOG(...)				/* NOP */
+#define GST_CAT_FIXME(...)				/* NOP */
 
 #define GST_ERROR_OBJECT(...)				/* NOP */
 #define GST_WARNING_OBJECT(...)				/* NOP */
 #define GST_INFO_OBJECT(...)				/* NOP */
 #define GST_DEBUG_OBJECT(...)				/* NOP */
 #define GST_LOG_OBJECT(...)				/* NOP */
+#define GST_FIXME_OBJECT(...)				/* NOP */
 
 #define GST_ERROR(...)					/* NOP */
 #define GST_WARNING(...)				/* NOP */
 #define GST_INFO(...)					/* NOP */
 #define GST_DEBUG(...)					/* NOP */
 #define GST_LOG(...)					/* NOP */
+#define GST_FIXME(...)					/* NOP */
 
-#else
+#else /* !G_HAVE_ISO_VARARGS */
 #ifdef G_HAVE_GNUC_VARARGS
 
 #define GST_CAT_LEVEL_LOG(cat,level,args...)		/* NOP */
@@ -1150,26 +1378,30 @@
 #define GST_CAT_INFO_OBJECT(args...)			/* NOP */
 #define GST_CAT_DEBUG_OBJECT(args...)			/* NOP */
 #define GST_CAT_LOG_OBJECT(args...)			/* NOP */
+#define GST_CAT_FIXME_OBJECT(args...)			/* NOP */
 
 #define GST_CAT_ERROR(args...)				/* NOP */
 #define GST_CAT_WARNING(args...)			/* NOP */
 #define GST_CAT_INFO(args...)				/* NOP */
 #define GST_CAT_DEBUG(args...)				/* NOP */
 #define GST_CAT_LOG(args...)				/* NOP */
+#define GST_CAT_FIXME(args...)				/* NOP */
 
 #define GST_ERROR_OBJECT(args...)			/* NOP */
 #define GST_WARNING_OBJECT(args...)			/* NOP */
 #define GST_INFO_OBJECT(args...)			/* NOP */
 #define GST_DEBUG_OBJECT(args...)			/* NOP */
 #define GST_LOG_OBJECT(args...)				/* NOP */
+#define GST_FIXME_OBJECT(args...)			/* NOP */
 
 #define GST_ERROR(args...)				/* NOP */
 #define GST_WARNING(args...)				/* NOP */
 #define GST_INFO(args...)				/* NOP */
 #define GST_DEBUG(args...)				/* NOP */
 #define GST_LOG(args...)				/* NOP */
+#define GST_FIXME(args...)				/* NOP */
 
-#else
+#else /* !G_HAVE_GNUC_VARARGS */
 static inline void
 GST_CAT_LEVEL_LOG_valist (GstDebugCategory * cat,
     GstDebugLevel level, gpointer object, const char *format, va_list varargs)
@@ -1207,6 +1439,12 @@
 }
 
 static inline void
+GST_CAT_FIXME_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format,
+    ...)
+{
+}
+
+static inline void
 GST_CAT_ERROR (GstDebugCategory * cat, const char *format, ...)
 {
 }
@@ -1232,6 +1470,11 @@
 }
 
 static inline void
+GST_CAT_FIXME (GstDebugCategory * cat, const char *format, ...)
+{
+}
+
+static inline void
 GST_ERROR_OBJECT (gpointer obj, const char *format, ...)
 {
 }
@@ -1257,6 +1500,11 @@
 }
 
 static inline void
+GST_FIXME_OBJECT (gpointer obj, const char *format, ...)
+{
+}
+
+static inline void
 GST_ERROR (const char *format, ...)
 {
 }
@@ -1280,13 +1528,27 @@
 GST_LOG (const char *format, ...)
 {
 }
-#endif
-#endif
+
+static inline void
+GST_FIXME (const char *format, ...)
+{
+}
+
+#endif /* G_HAVE_GNUC_VARARGS */
+#endif /* G_HAVE_ISO_VARARGS */
 
 #define GST_DEBUG_FUNCPTR(ptr) (ptr)
 #define GST_DEBUG_FUNCPTR_NAME(ptr) (g_strdup_printf ("%p", ptr))
 
+#define GST_CAT_MEMDUMP_OBJECT(cat,obj,msg,data,length) /* NOP */
+#define GST_CAT_MEMDUMP(cat,msg,data,length)            /* NOP */
+#define GST_MEMDUMP_OBJECT(obj,msg,data,length)         /* NOP */
+#define GST_MEMDUMP(msg,data,length)                    /* NOP */
+
 #endif /* GST_DISABLE_GST_DEBUG */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
 
 
 void gst_debug_print_stack_trace (void);
--- a/gstreamer_core/gst/gstinterface.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstinterface.c	Fri Apr 16 15:15:52 2010 +0300
@@ -51,9 +51,10 @@
 GType
 gst_implements_interface_get_type (void)
 {
-  static GType gst_interface_type = 0;
+  static volatile gsize gst_interface_type = 0;
 
-  if (!gst_interface_type) {
+  if (g_once_init_enter (&gst_interface_type)) {
+    GType _type;
     static const GTypeInfo gst_interface_info = {
       sizeof (GstImplementsInterfaceClass),
       (GBaseInitFunc) gst_implements_interface_class_init,
@@ -67,10 +68,11 @@
       NULL
     };
 
-    gst_interface_type = g_type_register_static (G_TYPE_INTERFACE,
+    _type = g_type_register_static (G_TYPE_INTERFACE,
         "GstImplementsInterface", &gst_interface_info, 0);
 
-    g_type_interface_add_prerequisite (gst_interface_type, GST_TYPE_ELEMENT);
+    g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT);
+    g_once_init_leave (&gst_interface_type, _type);
   }
 
   return gst_interface_type;
@@ -188,15 +190,11 @@
 gboolean
 gst_implements_interface_check (gpointer from, GType type)
 {
-  GstImplementsInterface *iface;
-
   /* check cast, return FALSE if it fails, don't give a warning... */
   if (!G_TYPE_CHECK_INSTANCE_TYPE (from, type)) {
     return FALSE;
   }
 
-  iface = G_TYPE_CHECK_INSTANCE_CAST (from, type, GstImplementsInterface);
-
   /* now, if we're an element (or derivative), is this thing
    * actually implemented for real? */
   if (GST_IS_ELEMENT (from)) {
--- a/gstreamer_core/gst/gstinterface.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstinterface.h	Fri Apr 16 15:15:52 2010 +0300
@@ -32,13 +32,8 @@
 #define GST_IMPLEMENTS_INTERFACE(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_IMPLEMENTS_INTERFACE, \
 				      GstImplementsInterface))
-#define GST_IMPLEMENTS_INTERFACE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_IMPLEMENTS_INTERFACE, \
-			    GstImplementsInterfaceClass))
 #define GST_IS_IMPLEMENTS_INTERFACE(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_IMPLEMENTS_INTERFACE))
-#define GST_IS_IMPLEMENTS_INTERFACE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_IMPLEMENTS_INTERFACE))
 #define GST_IMPLEMENTS_INTERFACE_GET_CLASS(inst) \
   (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_IMPLEMENTS_INTERFACE, \
 				  GstImplementsInterfaceClass))
--- a/gstreamer_core/gst/gstiterator.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstiterator.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,6 +31,10 @@
  * Various GStreamer objects provide access to their internal structures using
  * an iterator.
  *
+ * In general, whenever calling a GstIterator function results in your code
+ * receiving a refcounted object, the refcount for that object will have been
+ * increased.  Your code is responsible for unrefing that object after use.
+ *
  * The basic use pattern of an iterator is as follows:
  *
  * <example>
@@ -49,7 +53,7 @@
  *          gst_iterator_resync (it);
  *          break;
  *        case GST_ITERATOR_ERROR:
- *          ...wrong parameter were given...
+ *          ...wrong parameters were given...
  *          done = TRUE;
  *          break;
  *        case GST_ITERATOR_DONE:
@@ -61,7 +65,7 @@
  *   </programlisting>
  * </example>
  *
- * Last reviewed on 2005-11-09 (0.9.4)
+ * Last reviewed on 2009-06-16 (0.10.24)
  */
 
 #include "gst_private.h"
@@ -96,7 +100,8 @@
  * @size: the size of the iterator structure
  * @type: #GType of children
  * @lock: pointer to a #GMutex.
- * @master_cookie: pointer to a guint32 to protect the iterated object.
+ * @master_cookie: pointer to a guint32 that is changed when the items in the
+ *    iterator changed.
  * @next: function to get next item
  * @item: function to call on each item retrieved
  * @resync: function to resync the iterator
@@ -150,7 +155,6 @@
   gpointer owner;
   GList **orig;
   GList *list;                  /* pointer in list */
-  GType *type;
   GstIteratorDisposeFunction freefunc;
 } GstListIterator;
 
@@ -185,7 +189,8 @@
  * gst_iterator_new_list:
  * @type: #GType of elements
  * @lock: pointer to a #GMutex protecting the list.
- * @master_cookie: pointer to a guint32 to protect the list.
+ * @master_cookie: pointer to a guint32 that is incremented when the list
+ *     is changed.
  * @list: pointer to the list
  * @owner: object owning the list
  * @item: function to call for each item
@@ -193,6 +198,28 @@
  *
  * Create a new iterator designed for iterating @list.
  *
+ * The list you iterate is usually part of a data structure @owner and is
+ * protected with @lock. 
+ *
+ * The iterator will use @lock to retrieve the next item of the list and it
+ * will then call the @item function before releasing @lock again.
+ *
+ * The @item function usualy makes sure that the item remains alive while
+ * @lock is released and the application is using the item. The application is
+ * responsible for freeing/
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+unreffing the item after usage as explained in
+ * gst_iterator_next().
+ *
+ * When a concurrent update to the list is performed, usually by @owner while
+ * holding @lock, @master_cookie will be updated. The iterator implementation
+ * will notice the update of the cookie and will return %GST_ITERATOR_RESYNC to
+ * the user of the iterator in the next call to gst_iterator_next().
+ *
+ * @owner will be passed to the @free function when the iterator is freed.
+ *
  * Returns: the new #GstIterator for @list.
  *
  * MT safe.
@@ -243,12 +270,24 @@
  * @it: The #GstIterator to iterate
  * @elem: pointer to hold next element
  *
- * Get the next item from the iterator. For iterators that return
- * refcounted objects, the returned object will have its refcount
- * increased and should therefore be unreffed after usage.
+ * Get the next item from the iterator in @elem. 
+ *
+ * Only when this function returns %GST_ITERATOR_OK, @elem will contain a valid
+ * value. For iterators that return refcounted objects, the returned object
+ * will have its refcount increased and should therefore be unreffed after
+ * usage.
  *
- * Returns: The result of the iteration. Unref after usage if this is
- * a refcounted object.
+ * When this function returns %GST_ITERATOR_DONE, no more elements can be
+ * retrieved from @it.
+ *
+ * A return value of %GST_ITERATOR_RESYNC indicates that the element list was
+ * concurrently updated. The user of @it should call gst_iterator_resync() to
+ * get the newly updated list. 
+ *
+ * A return value of %GST_ITERATOR_ERROR indicates an unrecoverable fatal error.
+ *
+ * Returns: The result of the iteration. Unref @elem after usage if this
+ * is a refcounted object.
  *
  * MT safe.
  */
@@ -316,6 +355,9 @@
  * Resync the iterator. this function is mostly called
  * after gst_iterator_next() returned %GST_ITERATOR_RESYNC.
  *
+ * When an iterator was pushed on @it, it will automatically be popped again
+ * with this function.
+ *
  * MT safe.
  */
 #ifdef __SYMBIAN32__
@@ -365,12 +407,15 @@
  * @other: The #GstIterator to push
  *
  * Pushes @other iterator onto @it. All calls performed on @it are
- * forwarded tot @other. If @other returns #GST_ITERATOR_DONE, it is
+ * forwarded to @other. If @other returns %GST_ITERATOR_DONE, it is
  * popped again and calls are handled by @it again.
  *
  * This function is mainly used by objects implementing the iterator
  * next function to recurse into substructures.
  *
+ * When gst_iterator_resync() is called on @it, @other will automatically be
+ * popped.
+ *
  * MT safe.
  */
 #ifdef __SYMBIAN32__
@@ -500,18 +545,19 @@
  * @ret: the seed value passed to the fold function
  * @user_data: user data passed to the fold function
  *
- * Folds @func over the elements of @iter. That is to say, @proc will be called
- * as @proc (object, @ret, @user_data) for each object in @iter. The normal use
+ * Folds @func over the elements of @iter. That is to say, @func will be called
+ * as @func (object, @ret, @user_data) for each object in @it. The normal use
  * of this procedure is to accumulate the results of operating on the objects in
- * @ret.
+ * @ret.  If object is a refcounted object its refcount will be increased 
+ * before @func is called, and it should be unrefed after use in @func.
  *
- * This procedure can be used (and is used internally) to implement the foreach
- * and find_custom operations.
+ * This procedure can be used (and is used internally) to implement the
+ * gst_iterator_foreach() and gst_iterator_find_custom() operations.
  *
  * The fold will proceed as long as @func returns TRUE. When the iterator has no
- * more arguments, #GST_ITERATOR_DONE will be returned. If @func returns FALSE,
- * the fold will stop, and #GST_ITERATOR_OK will be returned. Errors or resyncs
- * will cause fold to return #GST_ITERATOR_ERROR or #GST_ITERATOR_RESYNC as
+ * more arguments, %GST_ITERATOR_DONE will be returned. If @func returns FALSE,
+ * the fold will stop, and %GST_ITERATOR_OK will be returned. Errors or resyncs
+ * will cause fold to return %GST_ITERATOR_ERROR or %GST_ITERATOR_RESYNC as
  * appropriate.
  *
  * The iterator will not be freed.
@@ -572,7 +618,9 @@
  * @user_data: user data passed to the function
  *
  * Iterate over all element of @it and call the given function @func for
- * each element.
+ * each element.  As in gst_iterator_fold(), the refcount of a refcounted 
+ * object will be increased before @func is called, and should be unrefed
+ * after use.
  *
  * Returns: the result call to gst_iterator_fold(). The iterator will not be
  * freed.
@@ -619,7 +667,9 @@
  * @user_data: user data passed to the compare function
  *
  * Find the first element in @it that matches the compare function @func.
- * @func should return 0 when the element is found.
+ * @func should return 0 when the element is found.  As in gst_iterator_fold(),
+ * the refcount of a refcounted object will be increased before @func is 
+ * called, and should be unrefed after use.
  *
  * The iterator will not be freed.
  *
--- a/gstreamer_core/gst/gstiterator.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstiterator.h	Fri Apr 16 15:15:52 2010 +0300
@@ -51,7 +51,7 @@
  * @GST_ITERATOR_ITEM_PASS:  Return item
  * @GST_ITERATOR_ITEM_END:   Stop after this item.
  *
- * The result of a GstIteratorItemFunction.
+ * The result of a #GstIteratorItemFunction.
  */
 typedef enum {
   GST_ITERATOR_ITEM_SKIP	= 0,
@@ -63,8 +63,8 @@
  * GstIteratorDisposeFunction:
  * @owner: the owner of the iterator
  *
- * The function that will be called when a GList iterator is freed. The
- * owner of the GList iterator can then clean up its resources.
+ * The function that will be called when a #GList iterator is freed. The
+ * owner of the #GList iterator can then clean up its resources.
  */
 typedef void		  (*GstIteratorDisposeFunction)	(gpointer owner);
 
@@ -128,7 +128,7 @@
 /**
  * GstIteratorFoldFunction:
  * @item: the item to fold
- * @ret: a GValue collecting the result
+ * @ret: a #GValue collecting the result
  * @user_data: data passed to gst_iterator_fold()
  *
  * A function to be passed to gst_iterator_fold().
@@ -186,7 +186,7 @@
  *          created.
  * @master_cookie: A pointer to the master cookie.
  *
- * GstIterator base structure. The values of this structure are 
+ * #GstIterator base structure. The values of this structure are 
  * protected for subclasses, use the methods to use the #GstIterator.
  */
 struct _GstIterator {
--- a/gstreamer_core/gst/gstmacros.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstmacros.h	Fri Apr 16 15:15:52 2010 +0300
@@ -20,6 +20,7 @@
  * SECTION:gstmacros
  * @short_description: Various portabillity helper macros
  *
+ * A set of macros complementing the glib portability macros.
  */
 
 #ifndef __GST_MACROS_H__
--- a/gstreamer_core/gst/gstmessage.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstmessage.c	Fri Apr 16 15:15:52 2010 +0300
@@ -57,14 +57,14 @@
 #include "gstmessage.h"
 #include "gsttaglist.h"
 #include "gstutils.h"
+#include "gstquark.h"
 
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #endif
 
+#define GST_MESSAGE_SEQNUM(e) ((GstMessage*)e)->abidata.ABI.seqnum
 
-static void gst_message_init (GTypeInstance * instance, gpointer g_class);
-static void gst_message_class_init (gpointer g_class, gpointer class_data);
 static void gst_message_finalize (GstMessage * message);
 static GstMessage *_gst_message_copy (GstMessage * message);
 
@@ -116,6 +116,8 @@
   {GST_MESSAGE_LATENCY, "latency", 0},
   {GST_MESSAGE_ASYNC_START, "async-start", 0},
   {GST_MESSAGE_ASYNC_DONE, "async-done", 0},
+  {GST_MESSAGE_REQUEST_STATE, "request-state", 0},
+  {GST_MESSAGE_STEP_START, "step-start", 0},
   {0, NULL, 0}
 };
 
@@ -166,60 +168,33 @@
   }
   return 0;
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_message_get_type (void)
-{
-  static GType _gst_message_type;
-
-  if (G_UNLIKELY (_gst_message_type == 0)) {
-    gint i;
-    static const GTypeInfo message_info = {
-      sizeof (GstMessageClass),
-      NULL,
-      NULL,
-      gst_message_class_init,
-      NULL,
-      NULL,
-      sizeof (GstMessage),
-      0,
-      gst_message_init,
-      NULL
-    };
-
-    _gst_message_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
-        "GstMessage", &message_info, 0);
-
-    for (i = 0; message_quarks[i].name; i++) {
-      message_quarks[i].quark =
-          g_quark_from_static_string (message_quarks[i].name);
-    }
-  }
-  return _gst_message_type;
+#define _do_init \
+{ \
+  gint i; \
+  \
+  for (i = 0; message_quarks[i].name; i++) { \
+    message_quarks[i].quark = \
+        g_quark_from_static_string (message_quarks[i].name); \
+  } \
 }
 
-static void
-gst_message_class_init (gpointer g_class, gpointer class_data)
-{
-  GstMessageClass *message_class = GST_MESSAGE_CLASS (g_class);
+G_DEFINE_TYPE_WITH_CODE (GstMessage, gst_message, GST_TYPE_MINI_OBJECT,
+    _do_init);
 
-  parent_class = g_type_class_peek_parent (g_class);
+static void
+gst_message_class_init (GstMessageClass * klass)
+{
+  parent_class = g_type_class_peek_parent (klass);
 
-  message_class->mini_object_class.copy =
-      (GstMiniObjectCopyFunction) _gst_message_copy;
-  message_class->mini_object_class.finalize =
+  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_message_copy;
+  klass->mini_object_class.finalize =
       (GstMiniObjectFinalizeFunction) gst_message_finalize;
 }
 
 static void
-gst_message_init (GTypeInstance * instance, gpointer g_class)
+gst_message_init (GstMessage * message)
 {
-  GstMessage *message = GST_MESSAGE (instance);
-
   GST_CAT_LOG (GST_CAT_MESSAGE, "new message %p", message);
   GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
 }
@@ -247,7 +222,7 @@
     gst_structure_free (message->structure);
   }
 
-  GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (message));
+/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (message)); */
 }
 
 static GstMessage *
@@ -266,6 +241,7 @@
   GST_MESSAGE_COND (copy) = GST_MESSAGE_COND (message);
   GST_MESSAGE_TYPE (copy) = GST_MESSAGE_TYPE (message);
   GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
+  GST_MESSAGE_SEQNUM (copy) = GST_MESSAGE_SEQNUM (message);
 
   if (GST_MESSAGE_SRC (message)) {
     GST_MESSAGE_SRC (copy) = gst_object_ref (GST_MESSAGE_SRC (message));
@@ -323,10 +299,74 @@
   }
   message->structure = structure;
 
+  GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next ();
+
   return message;
 }
 
 /**
+ * gst_message_get_seqnum:
+ * @message: A #GstMessage.
+ *
+ * Retrieve the sequence number of a message.
+ *
+ * Messages have ever-incrementing sequence numbers, which may also be set
+ * explicitly via gst_message_set_seqnum(). Sequence numbers are typically used
+ * to indicate that a message corresponds to some other set of messages or
+ * events, for example a SEGMENT_DONE message corresponding to a SEEK event. It
+ * is considered good practice to make this correspondence when possible, though
+ * it is not required.
+ *
+ * Note that events and messages share the same sequence number incrementor;
+ * two events or messages will never not have the same sequence number unless
+ * that correspondence was made explicitly.
+ *
+ * Returns: The message's sequence number.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_message_get_seqnum (GstMessage * message)
+{
+  g_return_val_if_fail (GST_IS_MESSAGE (message), -1);
+
+  return GST_MESSAGE_SEQNUM (message);
+}
+
+/**
+ * gst_message_set_seqnum:
+ * @message: A #GstMessage.
+ * @seqnum: A sequence number.
+ *
+ * Set the sequence number of a message.
+ *
+ * This function might be called by the creator of a message to indicate that
+ * the message relates to other messages or events. See gst_message_get_seqnum()
+ * for more information.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_set_seqnum (GstMessage * message, guint32 seqnum)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+
+  GST_MESSAGE_SEQNUM (message) = seqnum;
+}
+
+/**
  * gst_message_new_eos:
  * @src: The object originating the message.
  *
@@ -356,7 +396,7 @@
  * gst_message_new_error:
  * @src: The object originating the message.
  * @error: The GError for this message.
- * @debug: A debugging string for something or other.
+ * @debug: A debugging string.
  *
  * Create a new error message. The message will copy @error and
  * @debug. This message is posted by element when a fatal event
@@ -372,13 +412,15 @@
 #endif
 
 GstMessage *
-gst_message_new_error (GstObject * src, GError * error, gchar * debug)
+gst_message_new_error (GstObject * src, GError * error, const gchar * debug)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_ERROR, src,
-      gst_structure_new ("GstMessageError", "gerror", GST_TYPE_G_ERROR, error,
-          "debug", G_TYPE_STRING, debug, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_ERROR),
+      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_ERROR, src, structure);
 
   return message;
 }
@@ -387,7 +429,7 @@
  * gst_message_new_warning:
  * @src: The object originating the message.
  * @error: The GError for this message.
- * @debug: A debugging string for something or other.
+ * @debug: A debugging string.
  *
  * Create a new warning message. The message will make copies of @error and
  * @debug.
@@ -401,13 +443,15 @@
 #endif
 
 GstMessage *
-gst_message_new_warning (GstObject * src, GError * error, gchar * debug)
+gst_message_new_warning (GstObject * src, GError * error, const gchar * debug)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_WARNING, src,
-      gst_structure_new ("GstMessageWarning", "gerror", GST_TYPE_G_ERROR, error,
-          "debug", G_TYPE_STRING, debug, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_WARNING),
+      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_WARNING, src, structure);
 
   return message;
 }
@@ -416,29 +460,31 @@
  * gst_message_new_info:
  * @src: The object originating the message.
  * @error: The GError for this message.
- * @debug: A debugging string for something or other.
+ * @debug: A debugging string.
  *
  * Create a new info message. The message will make copies of @error and
  * @debug.
  *
+ * MT safe.
+ *
  * Returns: The new info message.
  *
  * Since: 0.10.12
- *
- * MT safe.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GstMessage *
-gst_message_new_info (GstObject * src, GError * error, gchar * debug)
+gst_message_new_info (GstObject * src, GError * error, const gchar * debug)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_INFO, src,
-      gst_structure_new ("GstMessageInfo", "gerror", GST_TYPE_G_ERROR, error,
-          "debug", G_TYPE_STRING, debug, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_INFO),
+      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_INFO, src, structure);
 
   return message;
 }
@@ -473,6 +519,43 @@
 }
 
 /**
+ * gst_message_new_tag_full:
+ * @src: The object originating the message.
+ * @pad: The originating pad for the tag.
+ * @tag_list: The tag list for the message.
+ *
+ * Create a new tag message. The message will take ownership of the tag list.
+ * The message is posted by elements that discovered a new taglist.
+ *
+ * MT safe.
+ *
+ * Returns: The new tag message.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_message_new_tag_full (GstObject * src, GstPad * pad, GstTagList * tag_list)
+{
+  GstMessage *message;
+  GstStructure *s;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL);
+  g_return_val_if_fail (pad == NULL || GST_IS_PAD (pad), NULL);
+
+  s = (GstStructure *) tag_list;
+  if (pad)
+    gst_structure_set (s, "source-pad", GST_TYPE_PAD, pad, NULL);
+
+  message = gst_message_new_custom (GST_MESSAGE_TAG, src, s);
+
+  return message;
+}
+
+/**
  * gst_message_new_buffering:
  * @src: The object originating the message.
  * @percent: The buffering percent
@@ -488,11 +571,11 @@
  * message with @percent set to 100, which can happen after the pipeline
  * completed prerolling. 
  *
+ * MT safe.
+ *
  * Returns: The new buffering message.
  *
  * Since: 0.10.11
- *
- * MT safe.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -502,12 +585,18 @@
 gst_message_new_buffering (GstObject * src, gint percent)
 {
   GstMessage *message;
+  GstStructure *structure;
 
   g_return_val_if_fail (percent >= 0 && percent <= 100, NULL);
 
-  message = gst_message_new_custom (GST_MESSAGE_BUFFERING, src,
-      gst_structure_new ("GstMessageBuffering",
-          "buffer-percent", G_TYPE_INT, percent, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_BUFFERING),
+      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent,
+      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
+      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
+      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
+      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  message = gst_message_new_custom (GST_MESSAGE_BUFFERING, src, structure);
 
   return message;
 }
@@ -535,12 +624,13 @@
     GstState oldstate, GstState newstate, GstState pending)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src,
-      gst_structure_new ("GstMessageState",
-          "old-state", GST_TYPE_STATE, (gint) oldstate,
-          "new-state", GST_TYPE_STATE, (gint) newstate,
-          "pending-state", GST_TYPE_STATE, (gint) pending, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STATE),
+      GST_QUARK (OLD_STATE), GST_TYPE_STATE, (gint) oldstate,
+      GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) newstate,
+      GST_QUARK (PENDING_STATE), GST_TYPE_STATE, (gint) pending, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src, structure);
 
   return message;
 }
@@ -597,11 +687,12 @@
     gboolean ready)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src,
-      gst_structure_new ("GstMessageClockProvide",
-          "clock", GST_TYPE_CLOCK, clock,
-          "ready", G_TYPE_BOOLEAN, ready, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_CLOCK_PROVIDE),
+      GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock,
+      GST_QUARK (READY), G_TYPE_BOOLEAN, ready, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src, structure);
 
   return message;
 }
@@ -630,10 +721,11 @@
 gst_message_new_clock_lost (GstObject * src, GstClock * clock)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src,
-      gst_structure_new ("GstMessageClockLost",
-          "clock", GST_TYPE_CLOCK, clock, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_CLOCK_LOST),
+      GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src, structure);
 
   return message;
 }
@@ -658,10 +750,56 @@
 gst_message_new_new_clock (GstObject * src, GstClock * clock)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src,
-      gst_structure_new ("GstMessageNewClock",
-          "clock", GST_TYPE_CLOCK, clock, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_NEW_CLOCK),
+      GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_new_structure_change:
+ * @src: The object originating the message.
+ * @type: The change type.
+ * @owner: The owner element of @src.
+ * @busy: Whether the structure change is busy.
+ *
+ * Create a new structure change message. This message is posted when the
+ * structure of a pipeline is in the process of being changed, for example
+ * when pads are linked or unlinked.
+ *
+ * @src should be the srcpad that unlinked or linked.
+ *
+ * Returns: The new structure change message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.22.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_message_new_structure_change (GstObject * src, GstStructureChangeType type,
+    GstElement * owner, gboolean busy)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_IS_PAD (src), NULL);
+  g_return_val_if_fail (GST_PAD_DIRECTION (src) == GST_PAD_SRC, NULL);
+  g_return_val_if_fail (GST_IS_ELEMENT (owner), NULL);
+
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STRUCTURE_CHANGE),
+      GST_QUARK (TYPE), GST_TYPE_STRUCTURE_CHANGE_TYPE, type,
+      GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner,
+      GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, NULL);
+
+  message = gst_message_new_custom (GST_MESSAGE_STRUCTURE_CHANGE, src,
+      structure);
 
   return message;
 }
@@ -690,11 +828,12 @@
     gint64 position)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src,
-      gst_structure_new ("GstMessageSegmentStart",
-          "format", GST_TYPE_FORMAT, format,
-          "position", G_TYPE_INT64, position, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_SEGMENT_START),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src, structure);
 
   return message;
 }
@@ -723,11 +862,12 @@
     gint64 position)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src,
-      gst_structure_new ("GstMessageSegmentDone",
-          "format", GST_TYPE_FORMAT, format,
-          "position", G_TYPE_INT64, position, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_SEGMENT_DONE),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src, structure);
 
   return message;
 }
@@ -806,11 +946,12 @@
 gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_DURATION, src,
-      gst_structure_new ("GstMessageDuration",
-          "format", GST_TYPE_FORMAT, format,
-          "duration", G_TYPE_INT64, duration, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_DURATION),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_DURATION, src, structure);
 
   return message;
 }
@@ -838,10 +979,11 @@
 gst_message_new_async_start (GstObject * src, gboolean new_base_time)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src,
-      gst_structure_new ("GstMessageAsyncStart",
-          "new-base-time", G_TYPE_BOOLEAN, new_base_time, NULL));
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_ASYNC_START),
+      GST_QUARK (NEW_BASE_TIME), G_TYPE_BOOLEAN, new_base_time, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, structure);
 
   return message;
 }
@@ -900,6 +1042,38 @@
 }
 
 /**
+ * gst_message_new_request_state:
+ * @src: The object originating the message.
+ * @state: The new requested state
+ *
+ * This message can be posted by elements when they want to have their state
+ * changed. A typical use case would be an audio server that wants to pause the
+ * pipeline because a higher priority stream is being played.
+ *
+ * Returns: The new requst state message. 
+ *
+ * MT safe.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_message_new_request_state (GstObject * src, GstState state)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_REQUEST_STATE),
+      GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) state, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_REQUEST_STATE, src, structure);
+
+  return message;
+}
+
+/**
  * gst_message_get_structure:
  * @message: The #GstMessage.
  *
@@ -940,11 +1114,61 @@
 void
 gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
 {
+  GstStructure *ret;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
   g_return_if_fail (tag_list != NULL);
 
-  *tag_list = (GstTagList *) gst_structure_copy (message->structure);
+  ret = gst_structure_copy (message->structure);
+  gst_structure_remove_field (ret, "source-pad");
+
+  *tag_list = (GstTagList *) ret;
+}
+
+/**
+ * gst_message_parse_tag_full:
+ * @message: A valid #GstMessage of type GST_MESSAGE_TAG.
+ * @pad: Location where the originating pad is stored, unref after usage
+ * @tag_list: Return location for the tag-list.
+ *
+ * Extracts the tag list from the GstMessage. The tag list returned in the
+ * output argument is a copy; the caller must free it when done.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_tag_full (GstMessage * message, GstPad ** pad,
+    GstTagList ** tag_list)
+{
+  GstStructure *ret;
+
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
+  g_return_if_fail (tag_list != NULL);
+
+  ret = gst_structure_copy (message->structure);
+
+  if (gst_structure_has_field (ret, "source-pad") && pad) {
+    const GValue *v;
+
+    v = gst_structure_get_value (ret, "source-pad");
+    if (v && G_VALUE_HOLDS (v, GST_TYPE_PAD))
+      *pad = (GstPad*)g_value_dup_object (v);
+    else
+      *pad = NULL;
+  } else if (pad) {
+    *pad = NULL;
+  }
+  gst_structure_remove_field (ret, "source-pad");
+
+  *tag_list = (GstTagList *) ret;
 }
 
 /**
@@ -955,9 +1179,9 @@
  * Extracts the buffering percent from the GstMessage. see also
  * gst_message_new_buffering().
  *
- * Since: 0.10.11
+ * MT safe.
  *
- * MT safe.
+ * Since: 0.10.11
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -970,7 +1194,75 @@
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
 
   if (percent)
-    gst_structure_get_int (message->structure, "buffer-percent", percent);
+    *percent = g_value_get_int (gst_structure_id_get_value (message->structure,
+            GST_QUARK (BUFFER_PERCENT)));
+}
+
+/**
+ * gst_message_set_buffering_stats:
+ * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING.
+ * @mode: a buffering mode 
+ * @avg_in: the average input rate
+ * @avg_out: the average output rate
+ * @buffering_left: amount of buffering time left in milliseconds
+ *
+ * Configures the buffering stats values in @message.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_set_buffering_stats (GstMessage * message, GstBufferingMode mode,
+    gint avg_in, gint avg_out, gint64 buffering_left)
+{
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
+
+  gst_structure_id_set (message->structure,
+      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
+      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
+      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
+      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+}
+
+/**
+ * gst_message_parse_buffering_stats:
+ * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING.
+ * @mode: a buffering mode 
+ * @avg_in: the average input rate
+ * @avg_out: the average output rate
+ * @buffering_left: amount of buffering time left in milliseconds.
+ *
+ * Extracts the buffering stats values from @message.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_buffering_stats (GstMessage * message,
+    GstBufferingMode * mode, gint * avg_in, gint * avg_out,
+    gint64 * buffering_left)
+{
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
+
+  if (mode)
+    *mode = g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (BUFFERING_MODE)));
+  if (avg_in)
+    *avg_in = g_value_get_int (gst_structure_id_get_value (message->structure,
+            GST_QUARK (AVG_IN_RATE)));
+  if (avg_out)
+    *avg_out = g_value_get_int (gst_structure_id_get_value (message->structure,
+            GST_QUARK (AVG_OUT_RATE)));
+  if (buffering_left)
+    *buffering_left =
+        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+            GST_QUARK (BUFFERING_LEFT)));
 }
 
 /**
@@ -996,14 +1288,16 @@
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED);
 
   if (oldstate)
-    gst_structure_get_enum (message->structure, "old-state",
-        GST_TYPE_STATE, (gint *) oldstate);
+    *oldstate =
+        g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (OLD_STATE)));
   if (newstate)
-    gst_structure_get_enum (message->structure, "new-state",
-        GST_TYPE_STATE, (gint *) newstate);
+    *newstate =
+        g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (NEW_STATE)));
   if (pending)
-    gst_structure_get_enum (message->structure, "pending-state",
-        GST_TYPE_STATE, (gint *) pending);
+    *pending = g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (PENDING_STATE)));
 }
 
 /**
@@ -1030,12 +1324,15 @@
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE);
 
-  clock_gvalue = gst_structure_get_value (message->structure, "clock");
+  clock_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (CLOCK));
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
   if (ready)
-    gst_structure_get_boolean (message->structure, "ready", ready);
+    *ready =
+        g_value_get_boolean (gst_structure_id_get_value (message->structure,
+            GST_QUARK (READY)));
   if (clock)
     *clock = (GstClock *) g_value_get_object (clock_gvalue);
 }
@@ -1062,7 +1359,8 @@
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_LOST);
 
-  clock_gvalue = gst_structure_get_value (message->structure, "clock");
+  clock_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (CLOCK));
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
@@ -1092,7 +1390,8 @@
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);
 
-  clock_gvalue = gst_structure_get_value (message->structure, "clock");
+  clock_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (CLOCK));
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
@@ -1101,6 +1400,49 @@
 }
 
 /**
+ * gst_message_parse_structure_change:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STRUCTURE_CHANGE.
+ * @type: A pointer to hold the change type
+ * @owner: The owner element of the message source
+ * @busy: A pointer to hold whether the change is in progress or has been
+ * completed
+ *
+ * Extracts the change type and completion status from the GstMessage.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_structure_change (GstMessage * message,
+    GstStructureChangeType * type, GstElement ** owner, gboolean * busy)
+{
+  const GValue *owner_gvalue;
+
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STRUCTURE_CHANGE);
+
+  owner_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (OWNER));
+  g_return_if_fail (owner_gvalue != NULL);
+  g_return_if_fail (G_VALUE_TYPE (owner_gvalue) == GST_TYPE_ELEMENT);
+
+  if (type)
+    *type = g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (TYPE)));
+  if (owner)
+    *owner = (GstElement *) g_value_get_object (owner_gvalue);
+  if (busy)
+    *busy =
+        g_value_get_boolean (gst_structure_id_get_value (message->structure,
+            GST_QUARK (BUSY)));
+}
+
+/**
  * gst_message_parse_error:
  * @message: A valid #GstMessage of type GST_MESSAGE_ERROR.
  * @gerror: Location for the GError
@@ -1124,7 +1466,8 @@
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
 
-  error_gvalue = gst_structure_get_value (message->structure, "gerror");
+  error_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
 
@@ -1135,7 +1478,9 @@
     *gerror = NULL;
 
   if (debug)
-    *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
+    *debug =
+        g_value_dup_string (gst_structure_id_get_value (message->structure,
+            GST_QUARK (DEBUG)));
 }
 
 /**
@@ -1163,7 +1508,8 @@
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
 
-  error_gvalue = gst_structure_get_value (message->structure, "gerror");
+  error_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
 
@@ -1174,7 +1520,9 @@
     *gerror = NULL;
 
   if (debug)
-    *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
+    *debug =
+        g_value_dup_string (gst_structure_id_get_value (message->structure,
+            GST_QUARK (DEBUG)));
 }
 
 /**
@@ -1203,7 +1551,8 @@
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
 
-  error_gvalue = gst_structure_get_value (message->structure, "gerror");
+  error_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
 
@@ -1214,7 +1563,9 @@
     *gerror = NULL;
 
   if (debug)
-    *debug = g_strdup (gst_structure_get_string (message->structure, "debug"));
+    *debug =
+        g_value_dup_string (gst_structure_id_get_value (message->structure,
+            GST_QUARK (DEBUG)));
 }
 
 /**
@@ -1235,17 +1586,17 @@
 gst_message_parse_segment_start (GstMessage * message, GstFormat * format,
     gint64 * position)
 {
-  const GstStructure *structure;
-
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_START);
 
-  structure = gst_message_get_structure (message);
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (FORMAT)));
   if (position)
     *position =
-        g_value_get_int64 (gst_structure_get_value (structure, "position"));
+        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+            GST_QUARK (POSITION)));
 }
 
 /**
@@ -1266,17 +1617,17 @@
 gst_message_parse_segment_done (GstMessage * message, GstFormat * format,
     gint64 * position)
 {
-  const GstStructure *structure;
-
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_DONE);
 
-  structure = gst_message_get_structure (message);
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (FORMAT)));
   if (position)
     *position =
-        g_value_get_int64 (gst_structure_get_value (structure, "position"));
+        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+            GST_QUARK (POSITION)));
 }
 
 /**
@@ -1300,17 +1651,17 @@
 gst_message_parse_duration (GstMessage * message, GstFormat * format,
     gint64 * duration)
 {
-  const GstStructure *structure;
-
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION);
 
-  structure = gst_message_get_structure (message);
   if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+    *format =
+        g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (FORMAT)));
   if (duration)
     *duration =
-        g_value_get_int64 (gst_structure_get_value (structure, "duration"));
+        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+            GST_QUARK (DURATION)));
 }
 
 /**
@@ -1331,14 +1682,337 @@
 void
 gst_message_parse_async_start (GstMessage * message, gboolean * new_base_time)
 {
-  const GstStructure *structure;
-
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_START);
 
-  structure = gst_message_get_structure (message);
   if (new_base_time)
     *new_base_time =
-        g_value_get_boolean (gst_structure_get_value (structure,
-            "new-base-time"));
+        g_value_get_boolean (gst_structure_id_get_value (message->structure,
+            GST_QUARK (NEW_BASE_TIME)));
+}
+
+/**
+ * gst_message_parse_request_state:
+ * @message: A valid #GstMessage of type GST_MESSAGE_REQUEST_STATE.
+ * @state: Result location for the requested state or NULL
+ *
+ * Extract the requested state from the request_state message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_request_state (GstMessage * message, GstState * state)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REQUEST_STATE);
+
+  if (state)
+    *state = g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (NEW_STATE)));
+}
+
+/**
+ * gst_message_new_stream_status:
+ * @src: The object originating the message.
+ * @type: The stream status type.
+ * @owner: The owner element of @src.
+ *
+ * Create a new stream status message. This message is posted when a streaming
+ * thread is created/destroyed or when the state changed.
+ * 
+ * Returns: The new stream status message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_message_new_stream_status (GstObject * src, GstStreamStatusType type,
+    GstElement * owner)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STREAM_STATUS),
+      GST_QUARK (TYPE), GST_TYPE_STREAM_STATUS_TYPE, (gint) type,
+      GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_STREAM_STATUS, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_stream_status:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS.
+ * @type: A pointer to hold the status type
+ * @owner: The owner element of the message source
+ *
+ * Extracts the stream status type and owner the GstMessage. The returned
+ * owner remains valid for as long as the reference to @message is valid and
+ * should thus not be unreffed.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_stream_status (GstMessage * message,
+    GstStreamStatusType * type, GstElement ** owner)
+{
+  const GValue *owner_gvalue;
+
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
+
+  owner_gvalue =
+      gst_structure_id_get_value (message->structure, GST_QUARK (OWNER));
+  g_return_if_fail (owner_gvalue != NULL);
+
+  if (type)
+    *type = g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (TYPE)));
+  if (owner)
+    *owner = (GstElement *) g_value_get_object (owner_gvalue);
+}
+
+/**
+ * gst_message_set_stream_status_object:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS.
+ * @object: the object controlling the streaming
+ *
+ * Configures the object handling the streaming thread. This is usually a
+ * GstTask object but other objects might be added in the future.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_set_stream_status_object (GstMessage * message,
+    const GValue * object)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
+
+  gst_structure_id_set_value (message->structure, GST_QUARK (OBJECT), object);
+}
+
+/**
+ * gst_message_get_stream_status_object:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS.
+ *
+ * Extracts the object managing the streaming thread from @message.
+ *
+ * Returns: a GValue containing the object that manages the streaming thread.
+ * This object is usually of type GstTask but other types can be added in the
+ * future. The object remains valid as long as @message is valid.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+const GValue *
+gst_message_get_stream_status_object (GstMessage * message)
+{
+  const GValue *result;
+
+  g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
+  g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS,
+      NULL);
+
+  result = gst_structure_id_get_value (message->structure, GST_QUARK (OBJECT));
+
+  return result;
 }
+
+/**
+ * gst_message_new_step_done:
+ * @src: The object originating the message.
+ * @format: the format of @amount
+ * @amount: the amount of stepped data
+ * @rate: the rate of the stepped amount
+ * @flush: is this an flushing step
+ * @intermediate: is this an intermediate step
+ * @duration: the duration of the data
+ * @eos: the step caused EOS
+ *
+ * This message is posted by elements when they complete a part, when @intermediate set
+ * to TRUE, or a complete step operation.
+ *
+ * @duration will contain the amount of time (in GST_FORMAT_TIME) of the stepped
+ * @amount of media in format @format.
+ *
+ * Returns: The new step_done message. 
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
+    gdouble rate, gboolean flush, gboolean intermediate, guint64 duration,
+    gboolean eos)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STEP_DONE),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
+      GST_QUARK (DURATION), G_TYPE_UINT64, duration,
+      GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_step_done:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE.
+ * @format: result location for the format
+ * @amount: result location for the amount
+ * @rate: result location for the rate
+ * @flush: result location for the flush flag
+ * @intermediate: result location for the intermediate flag
+ * @duration: result location for the duration
+ * @eos: result location for the EOS flag
+ *
+ * Extract the values the step_done message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_step_done (GstMessage * message, GstFormat * format,
+    guint64 * amount, gdouble * rate, gboolean * flush, gboolean * intermediate,
+    guint64 * duration, gboolean * eos)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
+
+  gst_structure_id_get (message->structure,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
+      GST_QUARK (DURATION), G_TYPE_UINT64, duration,
+      GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
+}
+
+/**
+ * gst_message_new_step_start:
+ * @src: The object originating the message.
+ * @active: if the step is active or queued
+ * @format: the format of @amount
+ * @amount: the amount of stepped data
+ * @rate: the rate of the stepped amount
+ * @flush: is this an flushing step
+ * @intermediate: is this an intermediate step
+ *
+ * This message is posted by elements when they accept or activate a new step
+ * event for @amount in @format. 
+ *
+ * @active is set to FALSE when the element accepted the new step event and has
+ * queued it for execution in the streaming threads.
+ *
+ * @active is set to TRUE when the element has activated the step operation and
+ * is now ready to start executing the step in the streaming thread. After this
+ * message is emited, the application can queue a new step operation in the
+ * element.
+ *
+ * Returns: The new step_start message. 
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstMessage *
+gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format,
+    guint64 amount, gdouble rate, gboolean flush, gboolean intermediate)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STEP_START),
+      GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_STEP_START, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_step_start:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE.
+ * @active: result location for the active flag
+ * @format: result location for the format
+ * @amount: result location for the amount
+ * @rate: result location for the rate
+ * @flush: result location for the flush flag
+ * @intermediate: result location for the intermediate flag
+ *
+ * Extract the values from step_start message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_message_parse_step_start (GstMessage * message, gboolean * active,
+    GstFormat * format, guint64 * amount, gdouble * rate, gboolean * flush,
+    gboolean * intermediate)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_START);
+
+  gst_structure_id_get (message->structure,
+      GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+}
--- a/gstreamer_core/gst/gstmessage.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstmessage.h	Fri Apr 16 15:15:52 2010 +0300
@@ -58,8 +58,8 @@
  *                          unusable. The pipeline will select a new clock on
  *                          the next PLAYING state change.
  * @GST_MESSAGE_NEW_CLOCK: a new clock was selected in the pipeline.
- * @GST_MESSAGE_STRUCTURE_CHANGE: the structure of the pipeline changed. Not
- * implemented yet.
+ * @GST_MESSAGE_STRUCTURE_CHANGE: the structure of the pipeline changed. This
+ * message is used internally and never forwarded to the application.
  * @GST_MESSAGE_STREAM_STATUS: status about a stream, emitted when it starts,
  *                             stops, errors, etc.. Not implemented yet.
  * @GST_MESSAGE_APPLICATION: message posted by the application, possibly
@@ -81,6 +81,10 @@
  * pipeline. Since: 0.10.13
  * @GST_MESSAGE_LATENCY: Posted by elements when their latency changes. The
  * pipeline will calculate and distribute a new latency. Since: 0.10.12
+ * @GST_MESSAGE_REQUEST_STATE: Posted by elements when they want the pipeline to
+ * change state. This message is a suggestion to the application which can
+ * decide to perform the state change on (part of) the pipeline. Since: 0.10.23.
+ * @GST_MESSAGE_STEP_START: A stepping operation was started.
  * @GST_MESSAGE_ANY: mask for all of the above messages.
  *
  * The different message types that are available.
@@ -113,6 +117,8 @@
   GST_MESSAGE_LATENCY           = (1 << 19),
   GST_MESSAGE_ASYNC_START       = (1 << 20),
   GST_MESSAGE_ASYNC_DONE        = (1 << 21),
+  GST_MESSAGE_REQUEST_STATE     = (1 << 22),
+  GST_MESSAGE_STEP_START        = (1 << 23),
   GST_MESSAGE_ANY               = ~0
 } GstMessageType;
 
@@ -178,6 +184,57 @@
  * Get the object that posted @message.
  */
 #define GST_MESSAGE_SRC(message)	(GST_MESSAGE(message)->src)
+/**
+ * GST_MESSAGE_SRC_NAME:
+ * @message: a #GstMessage
+ *
+ * Get the name of the object that posted @message. Returns "(NULL)" if
+ * the message has no source object set.
+ *
+ * Since: 0.10.24
+ */
+#define GST_MESSAGE_SRC_NAME(message)	(GST_MESSAGE_SRC(message) ? \
+    GST_OBJECT_NAME (GST_MESSAGE_SRC(message)) : "(NULL)")
+
+/**
+ * GstStructureChangeType:
+ * @GST_STRUCTURE_CHANGE_TYPE_PAD_LINK: Pad linking is starting or done.
+ * @GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK: Pad unlinking is starting or done.
+ *
+ * The type of a #GstMessageStructureChange.
+ *
+ * Since: 0.10.22
+ */
+typedef enum {
+  GST_STRUCTURE_CHANGE_TYPE_PAD_LINK   = 0,
+  GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK = 1
+} GstStructureChangeType;
+
+/**
+ * GstStreamStatusType:
+ * @GST_STREAM_STATUS_TYPE_CREATE: A new thread need to be created.
+ * @GST_STREAM_STATUS_TYPE_ENTER: a thread entered its loop function
+ * @GST_STREAM_STATUS_TYPE_LEAVE: a thread left its loop function
+ * @GST_STREAM_STATUS_TYPE_DESTROY: a thread is destroyed
+ * @GST_STREAM_STATUS_TYPE_START: a thread is started
+ * @GST_STREAM_STATUS_TYPE_PAUSE: a thread is paused
+ * @GST_STREAM_STATUS_TYPE_STOP: a thread is stopped
+ *
+ * The type of a #GstMessageStreamStatus. The stream status messages inform the
+ * application of new streaming threads and their status.
+ *
+ * Since: 0.10.24
+ */
+typedef enum {
+  GST_STREAM_STATUS_TYPE_CREATE   = 0,
+  GST_STREAM_STATUS_TYPE_ENTER    = 1,
+  GST_STREAM_STATUS_TYPE_LEAVE    = 2,
+  GST_STREAM_STATUS_TYPE_DESTROY  = 3,
+
+  GST_STREAM_STATUS_TYPE_START    = 8,
+  GST_STREAM_STATUS_TYPE_PAUSE    = 9,
+  GST_STREAM_STATUS_TYPE_STOP     = 10
+} GstStreamStatusType;
 
 /**
  * GstMessage:
@@ -193,7 +250,7 @@
 {
   GstMiniObject mini_object;
 
-  /*< private > *//* with MESSAGE_LOCK */
+  /*< private >*//* with MESSAGE_LOCK */
   GMutex *lock;                 /* lock and cond for async delivery */
   GCond *cond;
 
@@ -204,14 +261,20 @@
 
   GstStructure *structure;
 
-  /*< private > */
-  gpointer _gst_reserved[GST_PADDING];
+  /*< private >*/
+  union {
+    struct {
+      guint32 seqnum;
+    } ABI;
+    /* + 0 to mark ABI change for future greppage */
+    gpointer _gst_reserved[GST_PADDING + 0];
+  } abidata;
 };
 
 struct _GstMessageClass {
   GstMiniObjectClass mini_object_class;
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 #ifdef __SYMBIAN32__
@@ -248,8 +311,6 @@
 static inline GstMessage *
 gst_message_ref (GstMessage * msg)
 {
-  /* not using a macro here because gcc-4.1 will complain
-   * if the return value isn't used (because of the cast) */
   return (GstMessage *) gst_mini_object_ref (GST_MINI_OBJECT (msg));
 }
 
@@ -260,7 +321,16 @@
  * Convenience macro to decrease the reference count of the message, possibly
  * freeing it.
  */
-#define         gst_message_unref(msg)		gst_mini_object_unref (GST_MINI_OBJECT (msg))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_message_unref (GstMessage * msg);
+#endif
+
+static inline void
+gst_message_unref (GstMessage * msg)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (msg));
+}
+
 /* copy message */
 /**
  * gst_message_copy:
@@ -268,9 +338,20 @@
  *
  * Creates a copy of the message. Returns a copy of the message.
  *
+ * Returns: a new copy of @msg.
+ *
  * MT safe
  */
-#define         gst_message_copy(msg)		GST_MESSAGE (gst_mini_object_copy (GST_MINI_OBJECT (msg)))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstMessage * gst_message_copy (const GstMessage * msg);
+#endif
+
+static inline GstMessage *
+gst_message_copy (const GstMessage * msg)
+{
+  return GST_MESSAGE (gst_mini_object_copy (GST_MINI_OBJECT_CAST (msg)));
+}
+
 /**
  * gst_message_make_writable:
  * @msg: the message to make writable
@@ -282,22 +363,63 @@
  */
 #define         gst_message_make_writable(msg)	GST_MESSAGE (gst_mini_object_make_writable (GST_MINI_OBJECT (msg)))
 
+/* identifiers for events and messages */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint32         gst_message_get_seqnum          (GstMessage *message);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_message_set_seqnum          (GstMessage *message, guint32 seqnum);
+
+/* EOS */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_eos		(GstObject * src);
+
+/* ERROR */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-GstMessage *	gst_message_new_error		(GstObject * src, GError * error, gchar * debug);
+
+GstMessage *	gst_message_new_error		(GstObject * src, GError * error, const gchar * debug);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_message_parse_error		(GstMessage *message, GError **gerror, gchar **debug);
+
+/* WARNING */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-GstMessage *	gst_message_new_warning		(GstObject * src, GError * error, gchar * debug);
+GstMessage *	gst_message_new_warning		(GstObject * src, GError * error, const gchar * debug);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-GstMessage *	gst_message_new_info		(GstObject * src, GError * error, gchar * debug);
+void		gst_message_parse_warning	(GstMessage *message, GError **gerror, gchar **debug);
+
+/* INFO */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *	gst_message_new_info		(GstObject * src, GError * error, const gchar * debug);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_message_parse_info 		(GstMessage *message, GError **gerror, gchar **debug);
+
+/* TAG */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -307,7 +429,45 @@
 IMPORT_C
 #endif
 
-GstMessage *	gst_message_new_buffering	(GstObject * src, gint percent);
+GstMessage *	gst_message_new_tag_full	(GstObject * src, GstPad *pad, GstTagList * tag_list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_message_parse_tag		(GstMessage *message, GstTagList **tag_list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_message_parse_tag_full	(GstMessage *message, GstPad **pad, GstTagList **tag_list);
+
+/* BUFFERING */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *	gst_message_new_buffering	  (GstObject * src, gint percent);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void 		gst_message_parse_buffering	  (GstMessage *message, gint *percent);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_message_set_buffering_stats   (GstMessage *message, GstBufferingMode mode,
+                                                   gint avg_in, gint avg_out,
+                                                   gint64 buffering_left);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_message_parse_buffering_stats (GstMessage *message, GstBufferingMode *mode,
+                                                   gint *avg_in, gint *avg_out,
+                                                   gint64 *buffering_left);
+
+/* STATE_CHANGED */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -318,7 +478,32 @@
 IMPORT_C
 #endif
 
+void		gst_message_parse_state_changed	(GstMessage *message, GstState *oldstate,
+                                                 GstState *newstate, GstState *pending);
+
+/* STATE_DIRTY */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_state_dirty	(GstObject * src);
+
+/* STEP_DONE */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *    gst_message_new_step_done       (GstObject * src, GstFormat format, guint64 amount,
+                                                 gdouble rate, gboolean flush, gboolean intermediate, 
+						 guint64 duration, gboolean eos);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_message_parse_step_done     (GstMessage * message, GstFormat *format, guint64 *amount,
+                                                 gdouble *rate, gboolean *flush, gboolean *intermediate,
+						 guint64 *duration, gboolean *eos);
+/* CLOCK_PROVIDE */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -328,22 +513,48 @@
 IMPORT_C
 #endif
 
+void		gst_message_parse_clock_provide (GstMessage *message, GstClock **clock,
+                                                 gboolean *ready);
+
+/* CLOCK_LOST */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_clock_lost	(GstObject * src, GstClock *clock);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void		gst_message_parse_clock_lost	(GstMessage *message, GstClock **clock);
+
+/* NEW_CLOCK */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_new_clock	(GstObject * src, GstClock *clock);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void		gst_message_parse_new_clock	(GstMessage *message, GstClock **clock);
+
+/* APPLICATION */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_application	(GstObject * src, GstStructure * structure);
+
+/* ELEMENT */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 GstMessage *	gst_message_new_element		(GstObject * src, GstStructure * structure);
+
+/* SEGMENT_START */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -353,27 +564,128 @@
 IMPORT_C
 #endif
 
+void		gst_message_parse_segment_start (GstMessage *message, GstFormat *format,
+                                                 gint64 *position);
+
+/* SEGMENT_DONE */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_segment_done	(GstObject * src, GstFormat format, gint64 position);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void		gst_message_parse_segment_done	(GstMessage *message, GstFormat *format,
+                                                 gint64 *position);
+
+/* DURATION */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_duration	(GstObject * src, GstFormat format, gint64 duration);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void		gst_message_parse_duration	(GstMessage *message, GstFormat *format,
+                                                 gint64 *duration);
+
+/* LATENCY */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *	gst_message_new_latency         (GstObject * src);
+
+/* ASYNC_START */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_async_start	(GstObject * src, gboolean new_base_time);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+void		gst_message_parse_async_start	(GstMessage *message, gboolean *new_base_time);
+
+/* ASYNC_DONE */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstMessage *	gst_message_new_async_done	(GstObject * src);
+
+/* STRUCTURE CHANGE */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *	gst_message_new_structure_change   (GstObject * src, GstStructureChangeType type,
+                                                    GstElement *owner, gboolean busy);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_message_parse_structure_change (GstMessage *message, GstStructureChangeType *type,
+                                                    GstElement **owner, gboolean *busy);
+
+/* STREAM STATUS */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *	gst_message_new_stream_status        (GstObject * src, GstStreamStatusType type,
+                                                      GstElement *owner);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_message_parse_stream_status      (GstMessage *message, GstStreamStatusType *type,
+                                                      GstElement **owner);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-GstMessage *	gst_message_new_latency         (GstObject * src);
+void            gst_message_set_stream_status_object (GstMessage *message, const GValue *object);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+const GValue *  gst_message_get_stream_status_object (GstMessage *message);
+
+/* REQUEST_STATE */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *    gst_message_new_request_state   (GstObject * src, GstState state);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_message_parse_request_state (GstMessage * message, GstState *state);
+
+/* STEP_START */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMessage *    gst_message_new_step_start      (GstObject * src, gboolean active, GstFormat format,
+                                                 guint64 amount, gdouble rate, gboolean flush,
+						 gboolean intermediate);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_message_parse_step_start    (GstMessage * message, gboolean *active, GstFormat *format,
+                                                 guint64 *amount, gdouble *rate, gboolean *flush,
+						 gboolean *intermediate);
+
+/* custom messages */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -385,74 +697,6 @@
 IMPORT_C
 #endif
 
-
-void		gst_message_parse_error		(GstMessage *message, GError **gerror, gchar **debug);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_warning	(GstMessage *message, GError **gerror, gchar **debug);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_info 		(GstMessage *message, GError **gerror, gchar **debug);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_tag		(GstMessage *message, GstTagList **tag_list);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void 		gst_message_parse_buffering	(GstMessage *message, gint *percent);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_state_changed	(GstMessage *message, GstState *oldstate,
-                                                 GstState *newstate, GstState *pending);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_clock_provide (GstMessage *message, GstClock **clock, gboolean *ready);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_clock_lost	(GstMessage *message, GstClock **clock);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_new_clock	(GstMessage *message, GstClock **clock);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_segment_start (GstMessage *message, GstFormat *format, gint64 *position);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_segment_done	(GstMessage *message, GstFormat *format, gint64 *position);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_duration	(GstMessage *message, GstFormat *format, gint64 *duration);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-void		gst_message_parse_async_start	(GstMessage *message, gboolean *new_base_time);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
 const GstStructure *  gst_message_get_structure	(GstMessage *message);
 
 G_END_DECLS
--- a/gstreamer_core/gst/gstminiobject.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstminiobject.c	Fri Apr 16 15:15:52 2010 +0300
@@ -37,7 +37,9 @@
 #include "gst/gstminiobject.h"
 #include "gst/gstinfo.h"
 #include <gobject/gvaluecollector.h>
-
+#ifdef __SYMBIAN32__
+#include <glib_global.h>
+#endif
 #ifndef GST_DISABLE_TRACE
 #include "gsttrace.h"
 static GstAllocTrace *_gst_mini_object_trace;
@@ -163,6 +165,14 @@
 gst_mini_object_finalize (GstMiniObject * obj)
 {
   /* do nothing */
+
+  /* WARNING: if anything is ever put in this method, make sure that the
+   * following sub-classes' finalize method chains up to this one:
+   * gstbuffer
+   * gstevent
+   * gstmessage
+   * gstquery
+   */
 }
 
 /**
@@ -287,6 +297,8 @@
   if (gst_mini_object_is_writable (mini_object)) {
     ret = (GstMiniObject *) mini_object;
   } else {
+    GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy %s miniobject",
+        g_type_name (G_TYPE_FROM_INSTANCE (mini_object)));
     ret = gst_mini_object_copy (mini_object);
     gst_mini_object_unref ((GstMiniObject *) mini_object);
   }
@@ -446,8 +458,8 @@
 {
   if (src_value->data[0].v_pointer) {
     dest_value->data[0].v_pointer =
-        gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->data[0].
-            v_pointer));
+        gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->
+            data[0].v_pointer));
   } else {
     dest_value->data[0].v_pointer = NULL;
   }
@@ -565,18 +577,31 @@
   return value->data[0].v_pointer;
 }
 
-/* param spec */
-
-static GType gst_param_spec_mini_object_get_type (void);
+/**
+ * gst_value_dup_mini_object:
+ * @value:   a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
+ *
+ * Get the contents of a %GST_TYPE_MINI_OBJECT derived #GValue,
+ * increasing its reference count.
+ *
+ * Returns: mini object contents of @value
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-#define GST_TYPE_PARAM_SPEC_MINI_OBJECT (gst_param_spec_mini_object_get_type())
-#define GST_PARAM_SPEC_MINI_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_PARAM_SPEC_MINI_OBJECT, GstParamSpecMiniObject))
+GstMiniObject *
+gst_value_dup_mini_object (const GValue * value)
+{
+  g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
 
-typedef struct _GstParamSpecMiniObject GstParamSpecMiniObject;
-struct _GstParamSpecMiniObject
-{
-  GParamSpec parent_instance;
-};
+  return gst_mini_object_ref (value->data[0].v_pointer);
+}
+
+
+/* param spec */
 
 static void
 param_mini_object_init (GParamSpec * pspec)
@@ -619,8 +644,12 @@
 
   return p1 < p2 ? -1 : p1 > p2;
 }
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
 
-static GType
+
+GType
 gst_param_spec_mini_object_get_type (void)
 {
   static GType type;
@@ -667,7 +696,7 @@
 
   g_return_val_if_fail (g_type_is_a (object_type, GST_TYPE_MINI_OBJECT), NULL);
 
-  ospec = g_param_spec_internal (GST_TYPE_PARAM_SPEC_MINI_OBJECT,
+  ospec = g_param_spec_internal (GST_TYPE_PARAM_MINI_OBJECT,
       name, nick, blurb, flags);
   G_PARAM_SPEC (ospec)->value_type = object_type;
 
--- a/gstreamer_core/gst/gstminiobject.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstminiobject.h	Fri Apr 16 15:15:52 2010 +0300
@@ -204,10 +204,39 @@
 void 		gst_mini_object_replace 	(GstMiniObject **olddata, GstMiniObject *newdata);
 
 /* GParamSpec */
+
+#define	GST_TYPE_PARAM_MINI_OBJECT	        (gst_param_spec_mini_object_get_type())
+#define GST_IS_PARAM_SPEC_MINI_OBJECT(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), \
+                                                 GST_TYPE_PARAM_MINI_OBJECT))
+#define GST_PARAM_SPEC_MINI_OBJECT(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), \
+                                                 GST_TYPE_PARAM_MINI_OBJECT, \
+						 GstParamSpecMiniObject))
+
+typedef struct _GstParamSpecMiniObject GstParamSpecMiniObject;
+
+/**
+ * GstParamSpecMiniObject:
+ * @parent_instance: private %GParamSpec portion
+ * 
+ * A %GParamSpec derived structure that contains the meta data
+ * for %GstMiniObject properties.
+ */
+struct _GstParamSpecMiniObject
+{
+  GParamSpec parent_instance;
+};
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+
+
+GType gst_param_spec_mini_object_get_type (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 GParamSpec* 	gst_param_spec_mini_object 	(const char *name, const char *nick,
     						 const char *blurb, GType object_type, 
 						 GParamFlags flags);
@@ -217,6 +246,7 @@
 IMPORT_C
 #endif
 
+
 void 		gst_value_set_mini_object 	(GValue *value, GstMiniObject *mini_object);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -228,6 +258,11 @@
 #endif
 
 GstMiniObject* 	gst_value_get_mini_object 	(const GValue *value);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstMiniObject*  gst_value_dup_mini_object       (const GValue *value);
 
 
 G_END_DECLS
--- a/gstreamer_core/gst/gstobject.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstobject.c	Fri Apr 16 15:15:52 2010 +0300
@@ -83,7 +83,6 @@
  * Last reviewed on 2005-11-09 (0.9.4)
  */
 
-
 #include "gst_private.h"
 
 #include "gstobject.h"
@@ -101,10 +100,11 @@
 static GstAllocTrace *_gst_object_trace;
 #endif
 
-
 #define DEBUG_REFCOUNT
 
 /* Object signals and args */
+/* FIXME-0.11: have a read-only parent property instead of the two signals
+ * then we get notify::parent for free */
 enum
 {
   PARENT_SET,
@@ -145,9 +145,6 @@
 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
 #endif
 
-static void gst_object_class_init (GstObjectClass * klass);
-static void gst_object_init (GTypeInstance * instance, gpointer g_class);
-
 static void gst_object_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_object_get_property (GObject * object, guint prop_id,
@@ -167,43 +164,13 @@
 
 static GObjectClass *parent_class = NULL;
 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_object_get_type (void)
-{
-  static GType gst_object_type = 0;
-
-  if (G_UNLIKELY (gst_object_type == 0)) {
-    static const GTypeInfo object_info = {
-      sizeof (GstObjectClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_object_class_init,
-      NULL,
-      NULL,
-      sizeof (GstObject),
-      0,
-      gst_object_init,
-      NULL
-    };
-
-    gst_object_type =
-        g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info,
-        G_TYPE_FLAG_ABSTRACT);
-  }
-  return gst_object_type;
-}
+G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_OBJECT);
 
 static void
 gst_object_class_init (GstObjectClass * klass)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -216,7 +183,8 @@
 
   g_object_class_install_property (gobject_class, ARG_NAME,
       g_param_spec_string ("name", "Name", "The name of the object",
-          NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+          NULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstObject::parent-set:
@@ -294,10 +262,8 @@
 }
 
 static void
-gst_object_init (GTypeInstance * instance, gpointer g_class)
+gst_object_init (GstObject * object)
 {
-  GstObject *object = GST_OBJECT (instance);
-
   object->lock = g_mutex_new ();
   object->parent = NULL;
   object->name = NULL;
@@ -328,6 +294,7 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 gpointer
 gst_object_ref (gpointer object)
 {
@@ -373,6 +340,43 @@
 }
 
 /**
+ * gst_object_ref_sink:
+ * @object: a #GstObject to sink
+ *
+ * Increase the reference count of @object, and possibly remove the floating
+ * reference, if @object has a floating reference.
+ *
+ * In other words, if the object is floating, then this call "assumes ownership"
+ * of the floating reference, converting it to a normal reference by clearing
+ * the floating flag while leaving the reference count unchanged. If the object
+ * is not floating, then this call adds a new normal reference increasing the
+ * reference count by one.
+ *
+ * MT safe. This function grabs and releases @object lock.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_object_ref_sink (gpointer object)
+{
+  g_return_if_fail (GST_IS_OBJECT (object));
+
+  GST_OBJECT_LOCK (object);
+  if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) {
+    GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unsetting floating flag");
+    GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING);
+    GST_OBJECT_UNLOCK (object);
+  } else {
+    GST_OBJECT_UNLOCK (object);
+    gst_object_ref (object);
+  }
+}
+
+/**
  * gst_object_sink:
  * @object: a #GstObject to sink
  *
@@ -437,10 +441,10 @@
   g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
 
 #ifdef DEBUG_REFCOUNT
-  GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %s (%d) with %s (%d)",
-      *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)",
+  GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)",
+      *oldobj, *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)",
       *oldobj ? G_OBJECT (*oldobj)->ref_count : 0,
-      newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)",
+      newobj, newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)",
       newobj ? G_OBJECT (newobj)->ref_count : 0);
 #endif
 
@@ -525,16 +529,9 @@
   GstObject *gst_object, *parent, *old_parent;
   guint i;
   gchar *name, *debug_name;
-  GstObjectClass *klass;
-
-  /* we fail when this is not a GstObject */
-  g_return_if_fail (GST_IS_OBJECT (object));
-
-  klass = GST_OBJECT_GET_CLASS (object);
 
   /* do the standard dispatching */
-  G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs,
-      pspecs);
+  parent_class->dispatch_properties_changed (object, n_pspecs, pspecs);
 
   gst_object = GST_OBJECT_CAST (object);
   name = gst_object_get_name (gst_object);
@@ -544,12 +541,11 @@
   parent = gst_object_get_parent (gst_object);
   while (parent) {
     for (i = 0; i < n_pspecs; i++) {
-      GST_LOG_OBJECT (parent, "deep notification from %s (%s)",
-          debug_name, pspecs[i]->name);
+      GST_CAT_LOG_OBJECT (GST_CAT_PROPERTIES, parent,
+          "deep notification from %s (%s)", debug_name, pspecs[i]->name);
 
       g_signal_emit (parent, gst_object_signals[DEEP_NOTIFY],
-          g_quark_from_string (pspecs[i]->name), GST_OBJECT_CAST (object),
-          pspecs[i]);
+          g_quark_from_string (pspecs[i]->name), gst_object, pspecs[i]);
     }
 
     old_parent = parent;
@@ -597,15 +593,16 @@
     g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
     g_object_get_property (G_OBJECT (orig), pspec->name, &value);
 
+    /* FIXME: handle flags */
     if (G_IS_PARAM_SPEC_ENUM (pspec)) {
       GEnumValue *enum_value;
+      GEnumClass *klass = G_ENUM_CLASS (g_type_class_ref (pspec->value_type));
 
-      enum_value =
-          g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (pspec->value_type)),
-          g_value_get_enum (&value));
+      enum_value = g_enum_get_value (klass, g_value_get_enum (&value));
 
       str = g_strdup_printf ("%s (%d)", enum_value->value_nick,
           enum_value->value);
+      g_type_class_unref (klass);
     } else {
       str = g_strdup_value_contents (&value);
     }
@@ -649,7 +646,7 @@
   if (strncmp (type_name, "Gst", 3) == 0)
     type_name += 3;
   tmp = g_strdup_printf ("%s%d", type_name, count);
-  name = g_ascii_strdown (tmp, strlen (tmp));
+  name = g_ascii_strdown (tmp, -1);
   g_free (tmp);
 
   result = gst_object_set_name (object, name);
@@ -726,7 +723,8 @@
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
+
 gchar *
 gst_object_get_name (GstObject * object)
 {
@@ -814,9 +812,11 @@
  *
  * MT safe. Grabs and releases @object's LOCK.
  */
+
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
+
 gboolean
 gst_object_set_parent (GstObject * object, GstObject * parent)
 {
@@ -844,7 +844,7 @@
     gst_object_ref (object);
   }
 
-  g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_SET], 0, parent);
+  g_signal_emit (object, gst_object_signals[PARENT_SET], 0, parent);
 
   return TRUE;
 
@@ -899,9 +899,11 @@
  *
  * MT safe. Grabs and releases @object's lock.
  */
+
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
+
 void
 gst_object_unparent (GstObject * object)
 {
@@ -917,8 +919,7 @@
     object->parent = NULL;
     GST_OBJECT_UNLOCK (object);
 
-    g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_UNSET], 0,
-        parent);
+    g_signal_emit (object, gst_object_signals[PARENT_UNSET], 0, parent);
 
     gst_object_unref (object);
   } else {
@@ -1031,8 +1032,7 @@
   if (oclass->save_thyself)
     oclass->save_thyself (object, parent);
 
-  g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0,
-      parent);
+  g_signal_emit (object, gst_object_signals[OBJECT_SAVED], 0, parent);
 
   return parent;
 }
@@ -1128,6 +1128,7 @@
   GSList *parents;
   void *parent;
   gchar *prevpath, *path;
+  const gchar *typename;
   gchar *component;
   gchar *separator;
 
@@ -1156,16 +1157,27 @@
    * decrease the refcounting on each element after we handled
    * it. */
   for (parents = parentage; parents; parents = g_slist_next (parents)) {
+    if (G_IS_OBJECT (parents->data)) {
+      typename = G_OBJECT_TYPE_NAME (parents->data);
+    } else {
+      typename = NULL;
+    }
     if (GST_IS_OBJECT (parents->data)) {
       GstObject *item = GST_OBJECT_CAST (parents->data);
       GstObjectClass *oclass = GST_OBJECT_GET_CLASS (item);
+      gchar *objname = gst_object_get_name (item);
 
-      component = gst_object_get_name (item);
+      component = g_strdup_printf ("%s:%s", typename, objname);
       separator = oclass->path_string_separator;
       /* and unref now */
       gst_object_unref (item);
+      g_free (objname);
     } else {
-      component = g_strdup_printf ("%p", parents->data);
+      if (typename) {
+        component = g_strdup_printf ("%s:%p", typename, parents->data);
+      } else {
+        component = g_strdup_printf ("%p", parents->data);
+      }
       separator = "/";
     }
 
@@ -1197,39 +1209,11 @@
 #endif
 };
 
-static GType
-gst_signal_object_get_type (void)
-{
-  static GType signal_object_type = 0;
-
-  if (G_UNLIKELY (signal_object_type == 0)) {
-    static const GTypeInfo signal_object_info = {
-      sizeof (GstSignalObjectClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_signal_object_class_init,
-      NULL,
-      NULL,
-      sizeof (GstSignalObject),
-      0,
-      (GInstanceInitFunc) gst_signal_object_init,
-      NULL
-    };
-
-    signal_object_type =
-        g_type_register_static (G_TYPE_OBJECT, "GstSignalObject",
-        &signal_object_info, 0);
-  }
-  return signal_object_type;
-}
+G_DEFINE_TYPE (GstSignalObject, gst_signal_object, G_TYPE_OBJECT);
 
 static void
 gst_signal_object_class_init (GstSignalObjectClass * klass)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = (GObjectClass *) klass;
-
   parent_class = g_type_class_peek_parent (klass);
 
 #ifndef GST_DISABLE_LOADSAVE
--- a/gstreamer_core/gst/gstobject.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstobject.h	Fri Apr 16 15:15:52 2010 +0300
@@ -342,6 +342,11 @@
 IMPORT_C
 #endif
 
+void 		gst_object_ref_sink		(gpointer object);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void 		gst_object_sink			(gpointer object);
 
 /* replace object pointer */
--- a/gstreamer_core/gst/gstpad.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpad.c	Fri Apr 16 15:15:52 2010 +0300
@@ -99,8 +99,16 @@
   /* FILL ME */
 };
 
-static void gst_pad_class_init (GstPadClass * klass);
-static void gst_pad_init (GstPad * pad);
+#define GST_PAD_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate))
+
+#define GST_PAD_CHAINLISTFUNC(pad) ((pad)->abidata.ABI.priv->chainlistfunc)
+
+struct _GstPadPrivate
+{
+  GstPadChainListFunction chainlistfunc;
+};
+
 static void gst_pad_dispose (GObject * object);
 static void gst_pad_finalize (GObject * object);
 static void gst_pad_set_property (GObject * object, guint prop_id,
@@ -142,9 +150,7 @@
   {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0},
   {GST_FLOW_ERROR, "error", 0},
   {GST_FLOW_NOT_SUPPORTED, "not-supported", 0},
-  {GST_FLOW_CUSTOM_ERROR, "custom-error", 0},
-
-  {0, NULL, 0}
+  {GST_FLOW_CUSTOM_ERROR, "custom-error", 0}
 };
 
 /**
@@ -166,7 +172,7 @@
 
   ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS);
 
-  for (i = 0; flow_quarks[i].name; i++) {
+  for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {
     if (ret == flow_quarks[i].ret)
       return flow_quarks[i].name;
   }
@@ -193,48 +199,30 @@
 
   ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS);
 
-  for (i = 0; flow_quarks[i].name; i++) {
+  for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {
     if (ret == flow_quarks[i].ret)
       return flow_quarks[i].quark;
   }
   return 0;
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-GType
-gst_pad_get_type (void)
-{
-  static GType gst_pad_type = 0;
-
-  if (G_UNLIKELY (gst_pad_type == 0)) {
-    static const GTypeInfo pad_info = {
-      sizeof (GstPadClass), NULL, NULL,
-      (GClassInitFunc) gst_pad_class_init, NULL, NULL,
-      sizeof (GstPad),
-      0,
-      (GInstanceInitFunc) gst_pad_init, NULL
-    };
-    gint i;
-
-    gst_pad_type = g_type_register_static (GST_TYPE_OBJECT, "GstPad",
-        &pad_info, 0);
-
-    buffer_quark = g_quark_from_static_string ("buffer");
-    event_quark = g_quark_from_static_string ("event");
-
-    for (i = 0; flow_quarks[i].name; i++) {
-      flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name);
-    }
-
-    GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW",
-        GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads");
-  }
-  return gst_pad_type;
+
+#define _do_init \
+{ \
+  gint i; \
+  \
+  buffer_quark = g_quark_from_static_string ("buffer"); \
+  event_quark = g_quark_from_static_string ("event"); \
+  \
+  for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {			\
+    flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); \
+  } \
+  \
+  GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", \
+      GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); \
 }
 
+G_DEFINE_TYPE_WITH_CODE (GstPad, gst_pad, GST_TYPE_OBJECT, _do_init);
+
 static gboolean
 _gst_do_pass_data_accumulator (GSignalInvocationHint * ihint,
     GValue * return_accu, const GValue * handler_return, gpointer dummy)
@@ -262,6 +250,8 @@
   gobject_class = G_OBJECT_CLASS (klass);
   gstobject_class = GST_OBJECT_CLASS (klass);
 
+  g_type_class_add_private (klass, sizeof (GstPadPrivate));
+
   parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pad_dispose);
@@ -324,16 +314,16 @@
 
   g_object_class_install_property (gobject_class, PAD_PROP_CAPS,
       g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad",
-          GST_TYPE_CAPS, G_PARAM_READABLE));
+          GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION,
       g_param_spec_enum ("direction", "Direction", "The direction of the pad",
           GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
   /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */
   g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE,
       g_param_spec_object ("template", "Template",
           "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 #ifndef GST_DISABLE_LOADSAVE
   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself);
@@ -346,6 +336,8 @@
 static void
 gst_pad_init (GstPad * pad)
 {
+  pad->abidata.ABI.priv = GST_PAD_GET_PRIVATE (pad);
+
   GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN;
   GST_PAD_PEER (pad) = NULL;
 
@@ -363,6 +355,9 @@
   GST_PAD_QUERYFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_query_default);
   GST_PAD_INTLINKFUNC (pad) =
       GST_DEBUG_FUNCPTR (gst_pad_get_internal_links_default);
+  GST_PAD_ITERINTLINKFUNC (pad) =
+      GST_DEBUG_FUNCPTR (gst_pad_iterate_internal_links_default);
+
   GST_PAD_ACCEPTCAPSFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_acceptcaps_default);
 
   pad->do_buffer_signals = 0;
@@ -405,6 +400,11 @@
 
   gst_pad_set_pad_template (pad, NULL);
 
+  if (pad->block_destroy_data && pad->block_data) {
+    pad->block_destroy_data (pad->block_data);
+    pad->block_data = NULL;
+  }
+
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -588,9 +588,7 @@
    * error return value */
   g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
 
-  GST_OBJECT_LOCK (pad);
   result = GST_PAD_DIRECTION (pad);
-  GST_OBJECT_UNLOCK (pad);
 
   return result;
 }
@@ -801,7 +799,13 @@
         goto peer_failed;
       gst_object_unref (peer);
     } else {
-      goto not_linked;
+      /* there is no peer, this is only fatal when we activate. When we
+       * deactivate, we must assume the application has unlinked the peer and
+       * will deactivate it eventually. */
+      if (active)
+        goto not_linked;
+      else
+        GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
     }
   } else {
     if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
@@ -1004,6 +1008,107 @@
 }
 
 /**
+ * gst_pad_set_blocked_async_full:
+ * @pad: the #GstPad to block or unblock
+ * @blocked: boolean indicating whether the pad should be blocked or unblocked
+ * @callback: #GstPadBlockCallback that will be called when the
+ *            operation succeeds
+ * @user_data: user data passed to the callback
+ * @destroy_data: #GDestroyNotify for user_data
+ *
+ * Blocks or unblocks the dataflow on a pad. The provided callback
+ * is called when the operation succeeds; this happens right before the next
+ * attempt at pushing a buffer on the pad.
+ *
+ * This can take a while as the pad can only become blocked when real dataflow
+ * is happening.
+ * When the pipeline is stalled, for example in PAUSED, this can
+ * take an indeterminate amount of time.
+ * You can pass NULL as the callback to make this call block. Be careful with
+ * this blocking call as it might not return for reasons stated above.
+ *
+ * Returns: TRUE if the pad could be blocked. This function can fail if the
+ * wrong parameters were passed or the pad was already in the requested state.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
+    GstPadBlockCallback callback, gpointer user_data,
+    GDestroyNotify destroy_data)
+{
+  gboolean was_blocked = FALSE;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+
+  GST_OBJECT_LOCK (pad);
+
+  was_blocked = GST_PAD_IS_BLOCKED (pad);
+
+  if (G_UNLIKELY (was_blocked == blocked))
+    goto had_right_state;
+
+  if (blocked) {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad");
+
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
+
+    if (pad->block_destroy_data && pad->block_data &&
+        pad->block_data != user_data)
+      pad->block_destroy_data (pad->block_data);
+
+    pad->block_callback = callback;
+    pad->block_data = user_data;
+    pad->block_destroy_data = destroy_data;
+    pad->abidata.ABI.block_callback_called = FALSE;
+    if (!callback) {
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
+      GST_PAD_BLOCK_WAIT (pad);
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked");
+    }
+  } else {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad");
+
+    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
+
+    if (pad->block_destroy_data && pad->block_data &&
+        pad->block_data != user_data)
+      pad->block_destroy_data (pad->block_data);
+
+    pad->block_callback = callback;
+    pad->block_data = user_data;
+    pad->block_destroy_data = destroy_data;
+    pad->abidata.ABI.block_callback_called = FALSE;
+
+    GST_PAD_BLOCK_BROADCAST (pad);
+    if (!callback) {
+      /* no callback, wait for the unblock to happen */
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock");
+      GST_PAD_BLOCK_WAIT (pad);
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocked");
+    }
+  }
+  GST_OBJECT_UNLOCK (pad);
+
+  return TRUE;
+
+had_right_state:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pad was in right state (%d)", was_blocked);
+    GST_OBJECT_UNLOCK (pad);
+
+    return FALSE;
+  }
+}
+
+/**
  * gst_pad_set_blocked_async:
  * @pad: the #GstPad to block or unblock
  * @blocked: boolean indicating whether the pad should be blocked or unblocked
@@ -1035,56 +1140,8 @@
 gst_pad_set_blocked_async (GstPad * pad, gboolean blocked,
     GstPadBlockCallback callback, gpointer user_data)
 {
-  gboolean was_blocked = FALSE;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-
-  GST_OBJECT_LOCK (pad);
-
-  was_blocked = GST_PAD_IS_BLOCKED (pad);
-
-  if (G_UNLIKELY (was_blocked == blocked))
-    goto had_right_state;
-
-  if (blocked) {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad");
-
-    GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
-    pad->block_callback = callback;
-    pad->block_data = user_data;
-    if (!callback) {
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
-      GST_PAD_BLOCK_WAIT (pad);
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked");
-    }
-  } else {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad");
-
-    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
-
-    pad->block_callback = callback;
-    pad->block_data = user_data;
-
-    GST_PAD_BLOCK_BROADCAST (pad);
-    if (!callback) {
-      /* no callback, wait for the unblock to happen */
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock");
-      GST_PAD_BLOCK_WAIT (pad);
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocked");
-    }
-  }
-  GST_OBJECT_UNLOCK (pad);
-
-  return TRUE;
-
-had_right_state:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pad was in right state (%d)", was_blocked);
-    GST_OBJECT_UNLOCK (pad);
-
-    return FALSE;
-  }
+  return gst_pad_set_blocked_async_full (pad, blocked,
+      callback, user_data, NULL);
 }
 
 /**
@@ -1262,7 +1319,7 @@
 gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
 {
   g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
+  g_return_if_fail (GST_PAD_IS_SINK (pad));
 
   GST_PAD_CHAINFUNC (pad) = chain;
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s",
@@ -1270,6 +1327,33 @@
 }
 
 /**
+ * gst_pad_set_chain_list_function:
+ * @pad: a sink #GstPad.
+ * @chainlist: the #GstPadChainListFunction to set.
+ *
+ * Sets the given chain list function for the pad. The chainlist function is
+ * called to process a #GstBufferList input buffer list. See
+ * #GstPadChainListFunction for more details.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_pad_set_chain_list_function (GstPad * pad,
+    GstPadChainListFunction chainlist)
+{
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (GST_PAD_IS_SINK (pad));
+
+  GST_PAD_CHAINLISTFUNC (pad) = chainlist;
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s",
+      GST_DEBUG_FUNCPTR_NAME (chainlist));
+}
+
+/**
  * gst_pad_set_getrange_function:
  * @pad: a source #GstPad.
  * @get: the #GstPadGetRangeFunction to set.
@@ -1286,7 +1370,7 @@
 gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get)
 {
   g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
+  g_return_if_fail (GST_PAD_IS_SRC (pad));
 
   GST_PAD_GETRANGEFUNC (pad) = get;
 
@@ -1311,7 +1395,7 @@
     GstPadCheckGetRangeFunction check)
 {
   g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
+  g_return_if_fail (GST_PAD_IS_SRC (pad));
 
   GST_PAD_CHECKGETRANGEFUNC (pad) = check;
 
@@ -1453,12 +1537,39 @@
 }
 
 /**
+ * gst_pad_set_iterate_internal_links_function:
+ * @pad: a #GstPad of either direction.
+ * @iterintlink: the #GstPadIterIntLinkFunction to set.
+ *
+ * Sets the given internal link iterator function for the pad.
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_pad_set_iterate_internal_links_function (GstPad * pad,
+    GstPadIterIntLinkFunction iterintlink)
+{
+  g_return_if_fail (GST_IS_PAD (pad));
+
+  GST_PAD_ITERINTLINKFUNC (pad) = iterintlink;
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s",
+      GST_DEBUG_FUNCPTR_NAME (iterintlink));
+}
+
+/**
  * gst_pad_set_internal_link_function:
  * @pad: a #GstPad of either direction.
  * @intlink: the #GstPadIntLinkFunction to set.
  *
  * Sets the given internal link function for the pad.
+ *
+ * Deprecated: Use the thread-safe gst_pad_set_iterate_internal_links_function()
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -1472,6 +1583,7 @@
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link set to %s",
       GST_DEBUG_FUNCPTR_NAME (intlink));
 }
+#endif /* GST_REMOVE_DEPRECATED */
 
 /**
  * gst_pad_set_link_function:
@@ -1684,23 +1796,36 @@
 gboolean
 gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
 {
+  gboolean result = FALSE;
+  GstElement *parent = NULL;
+
   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
+  g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), FALSE);
   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
+  g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), FALSE);
 
   GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)",
       GST_DEBUG_PAD_NAME (srcpad), srcpad,
       GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
 
+  /* We need to notify the parent before taking any pad locks as the bin in
+   * question might be waiting for a lock on the pad while holding its lock
+   * that our message will try to take. */
+  if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
+    if (GST_IS_ELEMENT (parent)) {
+      gst_element_post_message (parent,
+          gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
+              GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, TRUE));
+    } else {
+      gst_object_unref (parent);
+      parent = NULL;
+    }
+  }
+
   GST_OBJECT_LOCK (srcpad);
 
-  if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC))
-    goto not_srcpad;
-
   GST_OBJECT_LOCK (sinkpad);
 
-  if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK))
-    goto not_sinkpad;
-
   if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad))
     goto not_linked_together;
 
@@ -1726,28 +1851,25 @@
   GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s",
       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
 
-  return TRUE;
-
-not_srcpad:
-  {
-    g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad));
-    GST_OBJECT_UNLOCK (srcpad);
-    return FALSE;
+  result = TRUE;
+
+done:
+  if (parent != NULL) {
+    gst_element_post_message (parent,
+        gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
+            GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, FALSE));
+    gst_object_unref (parent);
   }
-not_sinkpad:
-  {
-    g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad));
-    GST_OBJECT_UNLOCK (sinkpad);
-    GST_OBJECT_UNLOCK (srcpad);
-    return FALSE;
-  }
+  return result;
+
+  /* ERRORS */
 not_linked_together:
   {
     /* we do not emit a warning in this case because unlinking cannot
      * be made MT safe.*/
     GST_OBJECT_UNLOCK (sinkpad);
     GST_OBJECT_UNLOCK (srcpad);
-    return FALSE;
+    goto done;
   }
 }
 
@@ -1800,8 +1922,13 @@
 
   /* if we have caps on both pads we can check the intersection. If one
    * of the caps is NULL, we return TRUE. */
-  if (srccaps == NULL || sinkcaps == NULL)
+  if (G_UNLIKELY (srccaps == NULL || sinkcaps == NULL)) {
+    if (srccaps)
+      gst_caps_unref (srccaps);
+    if (sinkcaps)
+      gst_caps_unref (sinkcaps);
     goto done;
+  }
 
   icaps = gst_caps_intersect (srccaps, sinkcaps);
   gst_caps_unref (srccaps);
@@ -1909,26 +2036,16 @@
 static GstPadLinkReturn
 gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad)
 {
-  /* generic checks */
-  g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
-  g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED);
-
   GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
 
   GST_OBJECT_LOCK (srcpad);
 
-  if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC))
-    goto not_srcpad;
-
   if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL))
     goto src_was_linked;
 
   GST_OBJECT_LOCK (sinkpad);
 
-  if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK))
-    goto not_sinkpad;
-
   if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL))
     goto sink_was_linked;
 
@@ -1945,12 +2062,6 @@
 
   return GST_PAD_LINK_OK;
 
-not_srcpad:
-  {
-    g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad));
-    GST_OBJECT_UNLOCK (srcpad);
-    return GST_PAD_LINK_WRONG_DIRECTION;
-  }
 src_was_linked:
   {
     GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s",
@@ -1961,13 +2072,6 @@
     GST_OBJECT_UNLOCK (srcpad);
     return GST_PAD_LINK_WAS_LINKED;
   }
-not_sinkpad:
-  {
-    g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad));
-    GST_OBJECT_UNLOCK (sinkpad);
-    GST_OBJECT_UNLOCK (srcpad);
-    return GST_PAD_LINK_WRONG_DIRECTION;
-  }
 sink_was_linked:
   {
     GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s",
@@ -1996,6 +2100,46 @@
 }
 
 /**
+ * gst_pad_can_link:
+ * @srcpad: the source #GstPad.
+ * @sinkpad: the sink #GstPad.
+ *
+ * Checks if the source pad and the sink pad are compatible so they can be
+ * linked. 
+ *
+ * Returns: TRUE if the pads can be linked.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
+{
+  GstPadLinkReturn result;
+
+  /* generic checks */
+  g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
+  g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
+
+  GST_CAT_INFO (GST_CAT_PADS, "check if %s:%s can link with %s:%s",
+      GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+
+  /* gst_pad_link_prepare does everything for us, we only release the locks
+   * on the pads that it gets us. If this function returns !OK the locks are not
+   * taken anymore. */
+  result = gst_pad_link_prepare (srcpad, sinkpad);
+  if (result != GST_PAD_LINK_OK)
+    goto done;
+
+  GST_OBJECT_UNLOCK (srcpad);
+  GST_OBJECT_UNLOCK (sinkpad);
+
+done:
+  return result == GST_PAD_LINK_OK;
+}
+
+/**
  * gst_pad_link:
  * @srcpad: the source #GstPad to link.
  * @sinkpad: the sink #GstPad to link.
@@ -2015,12 +2159,31 @@
 gst_pad_link (GstPad * srcpad, GstPad * sinkpad)
 {
   GstPadLinkReturn result;
+  GstElement *parent;
+
+  g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
+  g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
+  g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED);
+  g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad),
+      GST_PAD_LINK_WRONG_DIRECTION);
+
+  /* Notify the parent early. See gst_pad_unlink for details. */
+  if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
+    if (GST_IS_ELEMENT (parent)) {
+      gst_element_post_message (parent,
+          gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
+              GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE));
+    } else {
+      gst_object_unref (parent);
+      parent = NULL;
+    }
+  }
 
   /* prepare will also lock the two pads */
   result = gst_pad_link_prepare (srcpad, sinkpad);
 
   if (result != GST_PAD_LINK_OK)
-    goto prepare_failed;
+    goto done;
 
   /* must set peers before calling the link function */
   GST_PAD_PEER (srcpad) = sinkpad;
@@ -2066,12 +2229,16 @@
     GST_OBJECT_UNLOCK (sinkpad);
     GST_OBJECT_UNLOCK (srcpad);
   }
+
+done:
+  if (parent) {
+    gst_element_post_message (parent,
+        gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
+            GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
+    gst_object_unref (parent);
+  }
+
   return result;
-
-prepare_failed:
-  {
-    return result;
-  }
 }
 
 static void
@@ -2194,7 +2361,7 @@
  *
  * Gets the capabilities this pad can produce or consume.
  * Note that this method doesn't necessarily return the caps set by
- * gst_pad_set_caps() - use #GST_PAD_CAPS for that instead.
+ * gst_pad_set_caps() - use GST_PAD_CAPS() for that instead.
  * gst_pad_get_caps returns all possible caps a pad can operate with, using
  * the pad's get_caps function;
  * this returns the pad template caps if not explicitly set.
@@ -2300,10 +2467,11 @@
     g_value_unset (&temp);
   } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
     gboolean res = FALSE;
-    guint n;
-
+    guint n, len;
+
+    len = gst_value_array_get_size (src);
     g_value_init (dest, GST_TYPE_ARRAY);
-    for (n = 0; n < gst_value_array_get_size (src); n++) {
+    for (n = 0; n < len; n++) {
       GValue kid = { 0 };
       const GValue *orig_kid = gst_value_array_get_value (src, n);
 
@@ -2356,7 +2524,7 @@
 gst_pad_fixate_caps (GstPad * pad, GstCaps * caps)
 {
   GstPadFixateCapsFunction fixatefunc;
-  guint n;
+  guint n, len;
 
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (caps != NULL);
@@ -2370,7 +2538,8 @@
   }
 
   /* default fixation */
-  for (n = 0; n < gst_caps_get_size (caps); n++) {
+  len = gst_caps_get_size (caps);
+  for (n = 0; n < len; n++) {
     GstStructure *s = gst_caps_get_structure (caps, n);
 
     gst_structure_foreach (s, gst_pad_default_fixate, s);
@@ -2401,8 +2570,6 @@
   GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect);
 
   result = !gst_caps_is_empty (intersect);
-  if (!result)
-    GST_DEBUG_OBJECT (pad, "intersection gave empty caps");
 
   gst_caps_unref (allowed);
   gst_caps_unref (intersect);
@@ -2445,13 +2612,13 @@
 
   /* lock for checking the existing caps */
   GST_OBJECT_LOCK (pad);
-  acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad);
   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps);
   /* The current caps on a pad are trivially acceptable */
   if (G_LIKELY ((existing = GST_PAD_CAPS (pad)))) {
     if (caps == existing || gst_caps_is_equal (caps, existing))
       goto is_same_caps;
   }
+  acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad);
   GST_OBJECT_UNLOCK (pad);
 
   if (G_LIKELY (acceptfunc)) {
@@ -2503,8 +2670,13 @@
   if (G_UNLIKELY (peerpad == NULL))
     goto no_peer;
 
+  gst_object_ref (peerpad);
+  /* release lock before calling external methods but keep ref to pad */
+  GST_OBJECT_UNLOCK (pad);
+
   result = gst_pad_accept_caps (peerpad, caps);
-  GST_OBJECT_UNLOCK (pad);
+
+  gst_object_unref (peerpad);
 
   return result;
 
@@ -2634,15 +2806,15 @@
 {
   gboolean res;
 
-  /* See if pad accepts the caps */
-  if (!gst_pad_accept_caps (pad, caps))
-    goto not_accepted;
-
-  if (dosetcaps)
+  if (dosetcaps) {
+    /* See if pad accepts the caps */
+    if (!gst_pad_accept_caps (pad, caps))
+      goto not_accepted;
+
     res = gst_pad_set_caps (pad, caps);
-  else
+  } else {
     res = TRUE;
-
+  }
   return res;
 
 not_accepted:
@@ -2862,8 +3034,10 @@
     goto fallback;
 
   ret = bufferallocfunc (pad, offset, size, caps, buf);
+
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto error;
+
   /* no error, but NULL buffer means fallback to the default */
   if (G_UNLIKELY (*buf == NULL))
     goto fallback;
@@ -2895,27 +3069,35 @@
     /* fallback case, allocate a buffer of our own, add pad caps. */
     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fallback buffer alloc");
 
-    *buf = gst_buffer_new_and_alloc (size);
-    GST_BUFFER_OFFSET (*buf) = offset;
-    gst_buffer_set_caps (*buf, caps);
-
-    return GST_FLOW_OK;
+    if ((*buf = gst_buffer_try_new_and_alloc (size))) {
+      GST_BUFFER_OFFSET (*buf) = offset;
+      gst_buffer_set_caps (*buf, caps);
+      return GST_FLOW_OK;
+    } else {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
+          "out of memory allocating %d bytes", size);
+      return GST_FLOW_ERROR;
+    }
   }
 }
 
+/* FIXME 0.11: size should be unsigned */
 static GstFlowReturn
 gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size,
     GstCaps * caps, GstBuffer ** buf, gboolean setcaps)
 {
   GstPad *peer;
   GstFlowReturn ret;
+  GstCaps *newcaps;
   gboolean caps_changed;
 
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
-  GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d", offset, size);
+  g_return_val_if_fail (size >= 0, GST_FLOW_ERROR);
+
+  GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d, caps %"
+      GST_PTR_FORMAT, offset, size, caps);
 
   GST_OBJECT_LOCK (pad);
   while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
@@ -2935,24 +3117,29 @@
     goto peer_error;
 
   /* FIXME, move capnego this into a base class? */
-  caps = GST_BUFFER_CAPS (*buf);
+  newcaps = GST_BUFFER_CAPS (*buf);
 
   /* Lock for checking caps, pretty pointless as the _pad_push() function might
    * change it concurrently, one of the problems with automatic caps setting in
    * pad_alloc_and_set_caps. Worst case, if does a check too much, but only
    * when there is heavy renegotiation going on in both directions. */
   GST_OBJECT_LOCK (pad);
-  caps_changed = caps && caps != GST_PAD_CAPS (pad);
+  caps_changed = newcaps && newcaps != GST_PAD_CAPS (pad);
   GST_OBJECT_UNLOCK (pad);
 
   /* we got a new datatype on the pad, see if it can handle it */
   if (G_UNLIKELY (caps_changed)) {
     GST_DEBUG_OBJECT (pad,
         "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
-        GST_PAD_CAPS (pad), caps, caps);
-    if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, setcaps)))
+        GST_PAD_CAPS (pad), newcaps, newcaps);
+    if (G_UNLIKELY (!gst_pad_configure_src (pad, newcaps, setcaps)))
       goto not_negotiated;
   }
+
+  /* sanity check (only if caps are the same) */
+  if (G_LIKELY (newcaps == caps) && G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size))
+    goto wrong_size_fallback;
+
   return ret;
 
 flushed:
@@ -2983,6 +3170,24 @@
         "alloc function returned unacceptable buffer");
     return GST_FLOW_NOT_NEGOTIATED;
   }
+wrong_size_fallback:
+  {
+    GST_CAT_ERROR_OBJECT (GST_CAT_PADS, pad, "buffer returned by alloc "
+        "function is too small (%u < %d), doing fallback buffer alloc",
+        GST_BUFFER_SIZE (*buf), size);
+
+    gst_buffer_unref (*buf);
+
+    if ((*buf = gst_buffer_try_new_and_alloc (size))) {
+      GST_BUFFER_OFFSET (*buf) = offset;
+      gst_buffer_set_caps (*buf, caps);
+      return GST_FLOW_OK;
+    } else {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
+          "out of memory allocating %d bytes", size);
+      return GST_FLOW_ERROR;
+    }
+  }
 }
 
 /**
@@ -2998,7 +3203,9 @@
  *
  * A new, empty #GstBuffer will be put in the @buf argument.
  * You need to check the caps of the buffer after performing this
- * function and renegotiate to the format if needed.
+ * function and renegotiate to the format if needed. If the caps changed, it is
+ * possible that the buffer returned in @buf is not of the right size for the
+ * new format, @buf needs to be unreffed and reallocated if this is the case.
  *
  * Returns: a result code indicating success of the operation. Any
  * result code other than #GST_FLOW_OK is an error and @buf should
@@ -3008,6 +3215,8 @@
  *
  * MT safe.
  */
+
+/* FIXME 0.11: size should be unsigned */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -3031,6 +3240,10 @@
  * automatically calls gst_pad_set_caps() when the caps of the
  * newly allocated buffer are different from the @pad caps.
  *
+ * After a renegotiation, the size of the new buffer returned in @buf could
+ * be of the wrong size for the new format and must be unreffed an reallocated
+ * in that case.
+ *
  * Returns: a result code indicating success of the operation. Any
  * result code other than #GST_FLOW_OK is an error and @buf should
  * not be used.
@@ -3039,6 +3252,8 @@
  *
  * MT safe.
  */
+
+/* FIXME 0.11: size should be unsigned */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -3050,6 +3265,170 @@
   return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, TRUE);
 }
 
+
+#ifndef GST_REMOVE_DEPRECATED
+typedef struct
+{
+  GList *list;
+  guint32 cookie;
+} IntLinkIterData;
+
+static void
+int_link_iter_data_free (IntLinkIterData * data)
+{
+  g_list_free (data->list);
+  g_free (data);
+}
+#endif
+
+static GstIteratorItem
+iterate_pad (GstIterator * it, GstPad * pad)
+{
+  gst_object_ref (pad);
+  return GST_ITERATOR_ITEM_PASS;
+}
+
+/**
+ * gst_pad_iterate_internal_links_default:
+ * @pad: the #GstPad to get the internal links of.
+ *
+ * Iterate the list of pads to which the given pad is linked to inside of
+ * the parent element.
+ * This is the default handler, and thus returns an iterator of all of the
+ * pads inside the parent element with opposite direction.
+ *
+ * The caller must free this iterator after use with gst_iterator_free().
+ *
+ * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
+ * returned pad with gst_object_unref().
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstIterator *
+gst_pad_iterate_internal_links_default (GstPad * pad)
+{
+  GstIterator *res;
+  GList **padlist;
+  guint32 *cookie;
+  GMutex *lock;
+  gpointer owner;
+  GstIteratorDisposeFunction dispose;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+#ifndef GST_REMOVE_DEPRECATED
+  /* when we get here, the default handler for the iterate links is called,
+   * which means that the user has not installed a custom one. We first check if
+   * there is maybe a custom legacy function we can call. */
+  if (GST_PAD_INTLINKFUNC (pad) &&
+      GST_PAD_INTLINKFUNC (pad) != gst_pad_get_internal_links_default) {
+    IntLinkIterData *data;
+
+    /* make an iterator for the list. We can't protect the list with a
+     * cookie. If we would take the cookie of the parent element, we need to
+     * have a parent, which is not required for GST_PAD_INTLINKFUNC(). We could
+     * cache the per-pad list and invalidate the list when a new call to
+     * INTLINKFUNC() returned a different list but then this would only work if
+     * two concurrent iterators were used and the last iterator would still be
+     * thread-unsafe. Just don't use this method anymore. */
+    data = g_new0 (IntLinkIterData, 1);
+    data->list = GST_PAD_INTLINKFUNC (pad) (pad);
+    data->cookie = 0;
+
+    GST_WARNING_OBJECT (pad, "Making unsafe iterator");
+
+    cookie = &data->cookie;
+    padlist = &data->list;
+    owner = data;
+    dispose = (GstIteratorDisposeFunction) int_link_iter_data_free;
+    /* reuse the pad lock, it's all we have here */
+    lock = GST_OBJECT_GET_LOCK (pad);
+  } else
+#endif
+  {
+    GstElement *parent;
+
+    GST_OBJECT_LOCK (pad);
+    parent = GST_PAD_PARENT (pad);
+    if (!parent || !GST_IS_ELEMENT (parent))
+      goto no_parent;
+
+    gst_object_ref (parent);
+    GST_OBJECT_UNLOCK (pad);
+
+    if (pad->direction == GST_PAD_SRC)
+      padlist = &parent->sinkpads;
+    else
+      padlist = &parent->srcpads;
+
+    GST_DEBUG_OBJECT (pad, "Making iterator");
+
+    cookie = &parent->pads_cookie;
+    owner = parent;
+    dispose = (GstIteratorDisposeFunction) gst_object_unref;
+    lock = GST_OBJECT_GET_LOCK (parent);
+  }
+
+  res = gst_iterator_new_list (GST_TYPE_PAD,
+      lock, cookie, padlist, owner, (GstIteratorItemFunction) iterate_pad,
+      dispose);
+
+  return res;
+
+  /* ERRORS */
+no_parent:
+  {
+    GST_OBJECT_UNLOCK (pad);
+    GST_DEBUG_OBJECT (pad, "no parent element");
+    return NULL;
+  }
+}
+
+/**
+ * gst_pad_iterate_internal_links:
+ * @pad: the GstPad to get the internal links of.
+ *
+ * Gets an iterator for the pads to which the given pad is linked to inside
+ * of the parent element.
+ *
+ * Each #GstPad element yielded by the iterator will have its refcount increased,
+ * so unref after use.
+ *
+ * Returns: a new #GstIterator of #GstPad or %NULL when the pad does not have an
+ * iterator function configured. Use gst_iterator_free() after usage.
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstIterator *
+gst_pad_iterate_internal_links (GstPad * pad)
+{
+  GstIterator *res = NULL;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+  if (GST_PAD_ITERINTLINKFUNC (pad))
+    res = GST_PAD_ITERINTLINKFUNC (pad) (pad);
+
+  return res;
+}
+
+#ifndef GST_REMOVE_DEPRECATED
+static void
+add_unref_pad_to_list (GstPad * pad, GList * list)
+{
+  list = g_list_prepend (list, pad);
+  gst_object_unref (pad);
+}
+#endif
+
 /**
  * gst_pad_get_internal_links_default:
  * @pad: the #GstPad to get the internal links of.
@@ -3058,52 +3437,98 @@
  * inside of the parent element.
  * This is the default handler, and thus returns a list of all of the
  * pads inside the parent element with opposite direction.
- * The caller must free this list after use.
+ *
+ * The caller must free this list after use with g_list_free().
  *
  * Returns: a newly allocated #GList of pads, or NULL if the pad has no parent.
  *
  * Not MT safe.
+ *
+ * Deprecated: This function does not ref the pads in the list so that they
+ * could become invalid by the time the application accesses them. It's also
+ * possible that the list changes while handling the pads, which the caller of
+ * this function is unable to know. Use the thread-safe 
+ * gst_pad_iterate_internal_links_default() instead.
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 GList *
 gst_pad_get_internal_links_default (GstPad * pad)
 {
   GList *res = NULL;
   GstElement *parent;
-  GList *parent_pads;
-  GstPadDirection direction;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  direction = pad->direction;
-
-  parent = GST_PAD_PARENT (pad);
-  if (!parent)
-    goto no_parent;
-
-  parent_pads = parent->pads;
-
-  while (parent_pads) {
-    GstPad *parent_pad = GST_PAD_CAST (parent_pads->data);
-
-    if (parent_pad->direction != direction) {
-      GST_DEBUG_OBJECT (pad, "adding pad %s:%s",
-          GST_DEBUG_PAD_NAME (parent_pad));
-      res = g_list_prepend (res, parent_pad);
-    }
-    parent_pads = g_list_next (parent_pads);
+  GST_WARNING_OBJECT (pad, "Unsafe internal links used");
+
+  /* when we get here, the default handler for get_internal_links is called,
+   * which means that the user has not installed a custom one. We first check if
+   * there is maybe a custom iterate function we can call. */
+  if (GST_PAD_ITERINTLINKFUNC (pad) &&
+      GST_PAD_ITERINTLINKFUNC (pad) != gst_pad_iterate_internal_links_default) {
+    GstIterator *it;
+    GstIteratorResult ires;
+    gboolean done = FALSE;
+
+    it = gst_pad_iterate_internal_links (pad);
+    /* loop over the iterator and put all elements into a list, we also
+     * immediatly unref them, which is bad. */
+    do {
+      ires = gst_iterator_foreach (it, (GFunc) add_unref_pad_to_list, res);
+      switch (ires) {
+        case GST_ITERATOR_OK:
+        case GST_ITERATOR_DONE:
+        case GST_ITERATOR_ERROR:
+          done = TRUE;
+          break;
+        case GST_ITERATOR_RESYNC:
+          /* restart, discard previous list */
+          gst_iterator_resync (it);
+          g_list_free (res);
+          res = NULL;
+          break;
+      }
+    } while (!done);
+
+    gst_iterator_free (it);
+  } else {
+    /* lock pad, check and ref parent */
+    GST_OBJECT_LOCK (pad);
+    parent = GST_PAD_PARENT (pad);
+    if (!parent || !GST_IS_ELEMENT (parent))
+      goto no_parent;
+
+    parent = gst_object_ref (parent);
+    GST_OBJECT_UNLOCK (pad);
+
+    /* now lock the parent while we copy the pads */
+    GST_OBJECT_LOCK (parent);
+    if (pad->direction == GST_PAD_SRC)
+      res = g_list_copy (parent->sinkpads);
+    else
+      res = g_list_copy (parent->srcpads);
+    GST_OBJECT_UNLOCK (parent);
+
+    gst_object_unref (parent);
   }
+
+  /* At this point pads can be changed and unreffed. Nothing we can do about it
+   * because for compatibility reasons this function cannot ref the pads or
+   * notify the app that the list changed. */
+
   return res;
 
 no_parent:
   {
     GST_DEBUG_OBJECT (pad, "no parent");
+    GST_OBJECT_UNLOCK (pad);
     return NULL;
   }
 }
+#endif /* GST_REMOVE_DEPRECATED */
 
 /**
  * gst_pad_get_internal_links:
@@ -3113,14 +3538,20 @@
  * inside of the parent element.
  * The caller must free this list after use.
  *
- * Returns: a newly allocated #GList of pads.
- *
  * Not MT safe.
+ *
+ * Returns: a newly allocated #GList of pads, free with g_list_free().
+ * 
+ * Deprecated: This function does not ref the pads in the list so that they
+ * could become invalid by the time the application accesses them. It's also
+ * possible that the list changes while handling the pads, which the caller of
+ * this function is unable to know. Use the thread-safe 
+ * gst_pad_iterate_internal_links() instead.
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 GList *
 gst_pad_get_internal_links (GstPad * pad)
 {
@@ -3128,53 +3559,98 @@
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
+  GST_WARNING_OBJECT (pad, "Calling unsafe internal links");
+
   if (GST_PAD_INTLINKFUNC (pad))
     res = GST_PAD_INTLINKFUNC (pad) (pad);
 
   return res;
 }
-
+#endif /* GST_REMOVE_DEPRECATED */
 
 static gboolean
 gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
 {
-  GList *orig, *pads;
-  gboolean result;
+  gboolean result = FALSE;
+  GstIterator *iter;
+  gboolean done = FALSE;
+  gpointer item;
+  GstPad *eventpad;
+  GList *pushed_pads = NULL;
 
   GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
       event, GST_EVENT_TYPE_NAME (event));
 
-  result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
-
-  orig = pads = gst_pad_get_internal_links (pad);
-
-  while (pads) {
-    GstPad *eventpad = GST_PAD_CAST (pads->data);
-
-    pads = g_list_next (pads);
-
-    if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
-      /* for each pad we send to, we should ref the event; it's up
-       * to downstream to unref again when handled. */
-      GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
-          event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad));
-      gst_event_ref (event);
-      gst_pad_push_event (eventpad, event);
-    } else {
-      /* we only send the event on one pad, multi-sinkpad elements
-       * should implement a handler */
-      GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
-          event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad));
-      result = gst_pad_push_event (eventpad, event);
-      goto done;
+  iter = gst_pad_iterate_internal_links (pad);
+
+  if (!iter)
+    goto no_iter;
+
+  while (!done) {
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:
+        eventpad = GST_PAD (item);
+
+        /* if already pushed,  skip */
+        if (g_list_find (pushed_pads, eventpad)) {
+          gst_object_unref (item);
+          break;
+        }
+
+        if (GST_PAD_IS_SRC (eventpad)) {
+          /* for each pad we send to, we should ref the event; it's up
+           * to downstream to unref again when handled. */
+          GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
+              event, GST_EVENT_TYPE_NAME (event),
+              GST_DEBUG_PAD_NAME (eventpad));
+          gst_event_ref (event);
+          result |= gst_pad_push_event (eventpad, event);
+        } else {
+          /* we only send the event on one pad, multi-sinkpad elements
+           * should implement a handler */
+          GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
+              event, GST_EVENT_TYPE_NAME (event),
+              GST_DEBUG_PAD_NAME (eventpad));
+          result = gst_pad_push_event (eventpad, event);
+          done = TRUE;
+          event = NULL;
+        }
+
+        pushed_pads = g_list_prepend (pushed_pads, eventpad);
+
+        gst_object_unref (item);
+        break;
+      case GST_ITERATOR_RESYNC:
+        /* FIXME, if we want to reset the result value we need to remember which
+         * pads pushed with which result */
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
     }
   }
+  gst_iterator_free (iter);
+
+no_iter:
+
+  /* If this is a sinkpad and we don't have pads to send the event to, we
+   * return TRUE. This is so that when using the default handler on a sink
+   * element, we don't fail to push it. */
+  if (!pushed_pads)
+    result = GST_PAD_IS_SINK (pad);
+
+  g_list_free (pushed_pads);
+
   /* we handled the incoming event so we unref once */
-  GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
-  gst_event_unref (event);
-
-done:
-  g_list_free (orig);
+  if (event) {
+    GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
+    gst_event_unref (event);
+  }
 
   return result;
 }
@@ -3202,6 +3678,8 @@
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
+  GST_LOG_OBJECT (pad, "default event handler");
+
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_EOS:
     {
@@ -3238,32 +3716,54 @@
     gpointer data)
 {
   gboolean res = FALSE;
-  GList *int_pads, *orig;
+  GstIterator *iter = NULL;
+  gboolean done = FALSE;
+  gpointer item;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (dispatch != NULL, FALSE);
 
-  orig = int_pads = gst_pad_get_internal_links (pad);
-
-  while (int_pads) {
-    GstPad *int_pad = GST_PAD_CAST (int_pads->data);
-    GstPad *int_peer = gst_pad_get_peer (int_pad);
-
-    if (int_peer) {
-      GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
-          GST_DEBUG_PAD_NAME (int_peer));
-      res = dispatch (int_peer, data);
-      gst_object_unref (int_peer);
-      if (res)
+  iter = gst_pad_iterate_internal_links (pad);
+
+  if (!iter)
+    goto no_iter;
+
+  while (!done) {
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:
+      {
+        GstPad *int_pad = GST_PAD_CAST (item);
+        GstPad *int_peer = gst_pad_get_peer (int_pad);
+
+        if (int_peer) {
+          GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
+              GST_DEBUG_PAD_NAME (int_peer));
+          done = res = dispatch (int_peer, data);
+          gst_object_unref (int_peer);
+        } else {
+          GST_DEBUG_OBJECT (int_pad, "no peer");
+        }
+      }
+        gst_object_unref (item);
         break;
-    } else {
-      GST_DEBUG_OBJECT (int_pad, "no peer");
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        done = TRUE;
+        GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads");
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
     }
-    int_pads = g_list_next (int_pads);
   }
-  g_list_free (orig);
+  gst_iterator_free (iter);
+
   GST_DEBUG_OBJECT (pad, "done, result %d", res);
 
+no_iter:
+
   return res;
 }
 
@@ -3411,6 +3911,7 @@
 {
   xmlNodePtr field = self->xmlChildrenNode;
   GstPad *pad = NULL, *targetpad;
+  GstPadTemplate *tmpl;
   gchar *peer = NULL;
   gchar **split;
   GstElement *target;
@@ -3420,7 +3921,10 @@
   while (field) {
     if (!strcmp ((char *) field->name, "name")) {
       name = (gchar *) xmlNodeGetContent (field);
-      pad = gst_element_get_pad (GST_ELEMENT (parent), name);
+      pad = gst_element_get_static_pad (GST_ELEMENT (parent), name);
+      if ((!pad) || ((tmpl = gst_pad_get_pad_template (pad))
+              && (GST_PAD_REQUEST == GST_PAD_TEMPLATE_PRESENCE (tmpl))))
+        pad = gst_element_get_request_pad (GST_ELEMENT (parent), name);
       g_free (name);
     } else if (!strcmp ((char *) field->name, "peer")) {
       peer = (gchar *) xmlNodeGetContent (field);
@@ -3456,12 +3960,17 @@
   if (target == NULL)
     goto cleanup;
 
-  targetpad = gst_element_get_pad (target, split[1]);
+  targetpad = gst_element_get_static_pad (target, split[1]);
+  if (!pad)
+    targetpad = gst_element_get_request_pad (target, split[1]);
 
   if (targetpad == NULL)
     goto cleanup;
 
-  gst_pad_link (pad, targetpad);
+  if (gst_pad_get_direction (pad) == GST_PAD_SRC)
+    gst_pad_link (pad, targetpad);
+  else
+    gst_pad_link (targetpad, pad);
 
 cleanup:
   g_strfreev (split);
@@ -3593,31 +4102,38 @@
    * all taken when calling this function. */
   gst_object_ref (pad);
 
-  /* we either have a callback installed to notify the block or
-   * some other thread is doing a GCond wait. */
-  callback = pad->block_callback;
-  if (callback) {
-    /* there is a callback installed, call it. We release the
-     * lock so that the callback can do something usefull with the
-     * pad */
-    user_data = pad->block_data;
-    GST_OBJECT_UNLOCK (pad);
-    callback (pad, TRUE, user_data);
-    GST_OBJECT_LOCK (pad);
-
-    /* we released the lock, recheck flushing */
-    if (GST_PAD_IS_FLUSHING (pad))
-      goto flushing;
-  } else {
-    /* no callback, signal the thread that is doing a GCond wait
-     * if any. */
-    GST_PAD_BLOCK_BROADCAST (pad);
-  }
-
-  /* OBJECT_LOCK could have been released when we did the callback, which
-   * then could have made the pad unblock so we need to check the blocking
-   * condition again.   */
   while (GST_PAD_IS_BLOCKED (pad)) {
+    do {
+      /* we either have a callback installed to notify the block or
+       * some other thread is doing a GCond wait. */
+      callback = pad->block_callback;
+      pad->abidata.ABI.block_callback_called = TRUE;
+      if (callback) {
+        /* there is a callback installed, call it. We release the
+         * lock so that the callback can do something usefull with the
+         * pad */
+        user_data = pad->block_data;
+        GST_OBJECT_UNLOCK (pad);
+        callback (pad, TRUE, user_data);
+        GST_OBJECT_LOCK (pad);
+
+        /* we released the lock, recheck flushing */
+        if (GST_PAD_IS_FLUSHING (pad))
+          goto flushing;
+      } else {
+        /* no callback, signal the thread that is doing a GCond wait
+         * if any. */
+        GST_PAD_BLOCK_BROADCAST (pad);
+      }
+    } while (pad->abidata.ABI.block_callback_called == FALSE
+        && GST_PAD_IS_BLOCKED (pad));
+
+    /* OBJECT_LOCK could have been released when we did the callback, which
+     * then could have made the pad unblock so we need to check the blocking
+     * condition again.   */
+    if (!GST_PAD_IS_BLOCKED (pad))
+      break;
+
     /* now we block the streaming thread. It can be unlocked when we
      * deactivate the pad (which will also set the FLUSHING flag) or
      * when the pad is unblocked. A flushing event will also unblock
@@ -3703,15 +4219,42 @@
   return res;
 }
 
+static void
+gst_pad_data_unref (gboolean is_buffer, void *data)
+{
+  if (G_LIKELY (is_buffer)) {
+    gst_buffer_unref (data);
+  } else {
+    gst_buffer_list_unref (data);
+  }
+}
+
+static GstCaps *
+gst_pad_data_get_caps (gboolean is_buffer, void *data)
+{
+  GstCaps *caps;
+
+  if (G_LIKELY (is_buffer)) {
+    caps = GST_BUFFER_CAPS (data);
+  } else {
+    GstBuffer *buf;
+
+    if ((buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (data), 0, 0)))
+      caps = GST_BUFFER_CAPS (buf);
+    else
+      caps = NULL;
+  }
+  return caps;
+}
+
 /* this is the chain function that does not perform the additional argument
  * checking for that little extra speed.
  */
 static inline GstFlowReturn
-gst_pad_chain_unchecked (GstPad * pad, GstBuffer * buffer)
+gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data)
 {
   GstCaps *caps;
   gboolean caps_changed;
-  GstPadChainFunction chainfunc;
   GstFlowReturn ret;
   gboolean emit_signal;
 
@@ -3721,7 +4264,7 @@
   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
     goto flushing;
 
-  caps = GST_BUFFER_CAPS (buffer);
+  caps = gst_pad_data_get_caps (is_buffer, data);
   caps_changed = caps && caps != GST_PAD_CAPS (pad);
 
   emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
@@ -3730,8 +4273,14 @@
   /* see if the signal should be emited, we emit before caps nego as
    * we might drop the buffer and do capsnego for nothing. */
   if (G_UNLIKELY (emit_signal)) {
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)))
-      goto dropping;
+    if (G_LIKELY (is_buffer)) {
+      if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data)))
+        goto dropping;
+    } else {
+      /* chain all groups in the buffer list one by one to avoid problems with
+       * buffer probes that push buffers or events */
+      goto chain_groups;
+    }
   }
 
   /* we got a new datatype on the pad, see if it can handle it */
@@ -3746,26 +4295,81 @@
    * the data to the wrong function. This is not really a
    * problem since functions are assigned at creation time
    * and don't change that often... */
-  if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
-    goto no_function;
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc));
-
-  ret = chainfunc (pad, buffer);
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "called chainfunction &%s, returned %s",
-      GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret));
+  if (G_LIKELY (is_buffer)) {
+    GstPadChainFunction chainfunc;
+
+    if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
+      goto no_function;
+
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc));
+
+    ret = chainfunc (pad, GST_BUFFER_CAST (data));
+
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "called chainfunction &%s, returned %s",
+        GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret));
+  } else {
+    GstPadChainListFunction chainlistfunc;
+
+    if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL))
+      goto chain_groups;
+
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "calling chainlistfunction &%s",
+        GST_DEBUG_FUNCPTR_NAME (chainlistfunc));
+
+    ret = chainlistfunc (pad, GST_BUFFER_LIST_CAST (data));
+
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "called chainlistfunction &%s, returned %s",
+        GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret));
+  }
 
   GST_PAD_STREAM_UNLOCK (pad);
 
   return ret;
 
+chain_groups:
+  {
+    GstBufferList *list;
+    GstBufferListIterator *it;
+    GstBuffer *group;
+
+    GST_PAD_STREAM_UNLOCK (pad);
+
+    GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
+
+    list = GST_BUFFER_LIST_CAST (data);
+    it = gst_buffer_list_iterate (list);
+
+    ret = GST_FLOW_OK;
+    if (gst_buffer_list_iterator_next_group (it)) {
+      do {
+        group = gst_buffer_list_iterator_merge_group (it);
+        if (group == NULL) {
+          group = gst_buffer_new ();
+          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
+        } else {
+          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
+        }
+        ret = gst_pad_chain_data_unchecked (pad, TRUE, group);
+      } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
+    } else {
+      GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
+      ret = gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_new ());
+    }
+
+    gst_buffer_list_iterator_free (it);
+    gst_buffer_list_unref (list);
+
+    return ret;
+  }
+
   /* ERRORS */
 flushing:
   {
-    gst_buffer_unref (buffer);
+    gst_pad_data_unref (is_buffer, data);
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "pushing, but pad was flushing");
     GST_OBJECT_UNLOCK (pad);
@@ -3774,22 +4378,22 @@
   }
 dropping:
   {
-    gst_buffer_unref (buffer);
+    gst_pad_data_unref (is_buffer, data);
     GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
     GST_PAD_STREAM_UNLOCK (pad);
     return GST_FLOW_OK;
   }
 not_negotiated:
   {
-    gst_buffer_unref (buffer);
+    gst_pad_data_unref (is_buffer, data);
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing buffer but pad did not accept");
+        "pushing data but pad did not accept");
     GST_PAD_STREAM_UNLOCK (pad);
     return GST_FLOW_NOT_NEGOTIATED;
   }
 no_function:
   {
-    gst_buffer_unref (buffer);
+    gst_pad_data_unref (is_buffer, data);
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "pushing, but not chainhandler");
     GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
@@ -3834,11 +4438,180 @@
 gst_pad_chain (GstPad * pad, GstBuffer * buffer)
 {
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK,
-      GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
 
-  return gst_pad_chain_unchecked (pad, buffer);
+  return gst_pad_chain_data_unchecked (pad, TRUE, buffer);
+}
+
+/**
+ * gst_pad_chain_list:
+ * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
+ * @list: the #GstBufferList to send, return GST_FLOW_ERROR if not.
+ *
+ * Chain a bufferlist to @pad.
+ *
+ * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
+ *
+ * If the caps on the first buffer of @list are different from the current
+ * caps on @pad, this function will call any setcaps function
+ * (see gst_pad_set_setcaps_function()) installed on @pad. If the new caps
+ * are not acceptable for @pad, this function returns #GST_FLOW_NOT_NEGOTIATED.
+ *
+ * The function proceeds calling the chainlist function installed on @pad (see
+ * gst_pad_set_chain_list_function()) and the return value of that function is
+ * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no
+ * chainlist function.
+ *
+ * In all cases, success or failure, the caller loses its reference to @list
+ * after calling this function.
+ *
+ * MT safe.
+ *
+ * Returns: a #GstFlowReturn from the pad.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstFlowReturn
+gst_pad_chain_list (GstPad * pad, GstBufferList * list)
+{
+  g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
+
+  return gst_pad_chain_data_unchecked (pad, FALSE, list);
+}
+
+static GstFlowReturn
+gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data)
+{
+  GstPad *peer;
+  GstFlowReturn ret;
+  GstCaps *caps;
+  gboolean caps_changed;
+
+  GST_OBJECT_LOCK (pad);
+
+  /* FIXME: this check can go away; pad_set_blocked could be implemented with
+   * probes completely or probes with an extended pad block. */
+  while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
+    if ((ret = handle_pad_block (pad)) != GST_FLOW_OK)
+      goto flushed;
+
+  /* we emit signals on the pad arg, the peer will have a chance to
+   * emit in the _chain() function */
+  if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) {
+    /* unlock before emitting */
+    GST_OBJECT_UNLOCK (pad);
+
+    if (G_LIKELY (is_buffer)) {
+      /* if the signal handler returned FALSE, it means we should just drop the
+       * buffer */
+      if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data)))
+        goto dropped;
+    } else {
+      /* push all buffers in the list */
+      goto push_groups;
+    }
+    GST_OBJECT_LOCK (pad);
+  }
+
+  if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
+    goto not_linked;
+
+  /* Before pushing the buffer to the peer pad, ensure that caps
+   * are set on this pad */
+  caps = gst_pad_data_get_caps (is_buffer, data);
+  caps_changed = caps && caps != GST_PAD_CAPS (pad);
+
+  /* take ref to peer pad before releasing the lock */
+  gst_object_ref (peer);
+
+  GST_OBJECT_UNLOCK (pad);
+
+  /* we got a new datatype from the pad, it had better handle it */
+  if (G_UNLIKELY (caps_changed)) {
+    GST_DEBUG_OBJECT (pad,
+        "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
+        GST_PAD_CAPS (pad), caps, caps);
+    if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
+      goto not_negotiated;
+  }
+
+  ret = gst_pad_chain_data_unchecked (peer, is_buffer, data);
+
+  gst_object_unref (peer);
+
+  return ret;
+
+push_groups:
+  {
+    GstBufferList *list;
+    GstBufferListIterator *it;
+    GstBuffer *group;
+
+    GST_INFO_OBJECT (pad, "pushing each group in list as a merged buffer");
+
+    list = GST_BUFFER_LIST_CAST (data);
+    it = gst_buffer_list_iterate (list);
+
+    ret = GST_FLOW_OK;
+    if (gst_buffer_list_iterator_next_group (it)) {
+      do {
+        group = gst_buffer_list_iterator_merge_group (it);
+        if (group == NULL) {
+          group = gst_buffer_new ();
+          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
+        } else {
+          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing group");
+        }
+        ret = gst_pad_push_data (pad, TRUE, group);
+      } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
+    } else {
+      GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
+      ret = gst_pad_push_data (pad, TRUE, gst_buffer_new ());
+    }
+
+    gst_buffer_list_iterator_free (it);
+    gst_buffer_list_unref (list);
+
+    return ret;
+  }
+
+  /* ERROR recovery here */
+flushed:
+  {
+    gst_pad_data_unref (is_buffer, data);
+    GST_DEBUG_OBJECT (pad, "pad block stopped by flush");
+    GST_OBJECT_UNLOCK (pad);
+    return ret;
+  }
+dropped:
+  {
+    gst_pad_data_unref (is_buffer, data);
+    GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
+    return GST_FLOW_OK;
+  }
+not_linked:
+  {
+    gst_pad_data_unref (is_buffer, data);
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing, but it was not linked");
+    GST_OBJECT_UNLOCK (pad);
+    return GST_FLOW_NOT_LINKED;
+  }
+not_negotiated:
+  {
+    gst_pad_data_unref (is_buffer, data);
+    gst_object_unref (peer);
+    GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "element pushed data then refused to accept the caps");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
 }
 
 /**
@@ -3870,99 +4643,64 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 GstFlowReturn
 gst_pad_push (GstPad * pad, GstBuffer * buffer)
 {
-  GstPad *peer;
-  GstFlowReturn ret;
-
-  GstCaps *caps;
-  gboolean caps_changed;
-
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
 
-  GST_OBJECT_LOCK (pad);
-
-  /* FIXME: this check can go away; pad_set_blocked could be implemented with
-   * probes completely or probes with an extended pad block. */
-  while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
-    if ((ret = handle_pad_block (pad)) != GST_FLOW_OK)
-      goto flushed;
-
-  /* we emit signals on the pad arg, the peer will have a chance to
-   * emit in the _chain() function */
-  if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) {
-    /* unlock before emitting */
-    GST_OBJECT_UNLOCK (pad);
-
-    /* if the signal handler returned FALSE, it means we should just drop the
-     * buffer */
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)))
-      goto dropped;
-
-    GST_OBJECT_LOCK (pad);
-  }
-
-  if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
-    goto not_linked;
-
-  /* take ref to peer pad before releasing the lock */
-  gst_object_ref (peer);
-
-  /* Before pushing the buffer to the peer pad, ensure that caps
-   * are set on this pad */
-  caps = GST_BUFFER_CAPS (buffer);
-  caps_changed = caps && caps != GST_PAD_CAPS (pad);
-
-  GST_OBJECT_UNLOCK (pad);
-
-  /* we got a new datatype from the pad, it had better handle it */
-  if (G_UNLIKELY (caps_changed)) {
-    GST_DEBUG_OBJECT (pad,
-        "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
-        GST_PAD_CAPS (pad), caps, caps);
-    if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
-      goto not_negotiated;
-  }
-
-  ret = gst_pad_chain_unchecked (peer, buffer);
-
-  gst_object_unref (peer);
-
-  return ret;
-
-  /* ERROR recovery here */
-flushed:
-  {
-    gst_buffer_unref (buffer);
-    GST_DEBUG_OBJECT (pad, "pad block stopped by flush");
-    GST_OBJECT_UNLOCK (pad);
-    return ret;
-  }
-dropped:
-  {
-    gst_buffer_unref (buffer);
-    GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
-    return GST_FLOW_OK;
-  }
-not_linked:
-  {
-    gst_buffer_unref (buffer);
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing, but it was not linked");
-    GST_OBJECT_UNLOCK (pad);
-    return GST_FLOW_NOT_LINKED;
-  }
-not_negotiated:
-  {
-    gst_buffer_unref (buffer);
-    gst_object_unref (peer);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "element pushed buffer then refused to accept the caps");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
+  return gst_pad_push_data (pad, TRUE, buffer);
+}
+
+/**
+ * gst_pad_push_list:
+ * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
+ * @list: the #GstBufferList to push returns GST_FLOW_ERROR if not.
+ *
+ * Pushes a buffer list to the peer of @pad.
+ *
+ * This function will call an installed pad block before triggering any
+ * installed pad probes.
+ *
+ * If the caps on the first buffer in the first group of @list are different
+ * from the currently configured caps on @pad, this function will call any
+ * installed setcaps function on @pad (see gst_pad_set_setcaps_function()). In
+ * case of failure to renegotiate the new format, this function returns
+ * #GST_FLOW_NOT_NEGOTIATED.
+ *
+ * If there are any probes installed on @pad every group of the buffer list
+ * will be merged into a normal #GstBuffer and pushed via gst_pad_push and the
+ * buffer list will be unreffed.
+ *
+ * The function proceeds calling the chain function on the peer pad and returns
+ * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will
+ * be returned. If the peer pad does not have any installed chainlist function
+ * every group buffer of the list will be merged into a normal #GstBuffer and
+ * chained via gst_pad_chain().
+ *
+ * In all cases, success or failure, the caller loses its reference to @list
+ * after calling this function.
+ *
+ * Returns: a #GstFlowReturn from the peer pad.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstFlowReturn
+gst_pad_push_list (GstPad * pad, GstBufferList * list)
+{
+  g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
+
+  return gst_pad_push_data (pad, FALSE, list);
 }
 
 /**
@@ -3995,7 +4733,7 @@
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
   GST_OBJECT_LOCK (pad);
-  if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK)
+  if (!GST_PAD_IS_SINK (pad))
     goto wrong_direction;
 
   if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
@@ -4054,10 +4792,6 @@
  * installed (see gst_pad_set_getrange_function()) this function returns
  * #GST_FLOW_NOT_SUPPORTED.
  *
- * @buffer's caps must either be unset or the same as what is already
- * configured on @pad. Renegotiation within a running pull-mode pipeline is not
- * supported.
- *
  * This is a lowlevel function. Usualy gst_pad_pull_range() is used.
  *
  * Returns: a #GstFlowReturn from the pad.
@@ -4075,9 +4809,11 @@
   GstFlowReturn ret;
   GstPadGetRangeFunction getrangefunc;
   gboolean emit_signal;
+  GstCaps *caps;
+  gboolean caps_changed;
 
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
   GST_PAD_STREAM_LOCK (pad);
@@ -4107,23 +4843,22 @@
 
   GST_PAD_STREAM_UNLOCK (pad);
 
-  if (G_LIKELY (ret == GST_FLOW_OK)) {
-    GstCaps *caps;
-    gboolean caps_changed;
-
-    GST_OBJECT_LOCK (pad);
-    /* Before pushing the buffer to the peer pad, ensure that caps
-     * are set on this pad */
-    caps = GST_BUFFER_CAPS (*buffer);
-    caps_changed = caps && caps != GST_PAD_CAPS (pad);
-    GST_OBJECT_UNLOCK (pad);
-
-    /* we got a new datatype from the pad not supported in a running pull-mode
-     * pipeline */
-    if (G_UNLIKELY (caps_changed))
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto get_range_failed;
+
+  GST_OBJECT_LOCK (pad);
+  /* Before pushing the buffer to the peer pad, ensure that caps
+   * are set on this pad */
+  caps = GST_BUFFER_CAPS (*buffer);
+  caps_changed = caps && caps != GST_PAD_CAPS (pad);
+  GST_OBJECT_UNLOCK (pad);
+
+  if (G_UNLIKELY (caps_changed)) {
+    GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
+    /* this should usually work because the element produced the buffer */
+    if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
       goto not_negotiated;
   }
-
   return ret;
 
   /* ERRORS */
@@ -4152,23 +4887,20 @@
     *buffer = NULL;
     return GST_FLOW_UNEXPECTED;
   }
+get_range_failed:
+  {
+    *buffer = NULL;
+    GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
+        "getrange failed %s", gst_flow_get_name (ret));
+    return ret;
+  }
 not_negotiated:
   {
-    /* ideally we want to use the commented-out code, but currently demuxers
-     * and typefind do not follow part-negotiation.txt. When switching into
-     * pull mode, typefind should probably return the found caps from
-     * getcaps(), and demuxers should do the setcaps(). */
-
-#if 0
     gst_buffer_unref (*buffer);
     *buffer = NULL;
     GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
-        "getrange returned buffer of different caps");
+        "getrange returned buffer of unaccaptable caps");
     return GST_FLOW_NOT_NEGOTIATED;
-#endif
-    GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "getrange returned buffer of different caps");
-    return ret;
   }
 }
 
@@ -4213,10 +4945,11 @@
   GstPad *peer;
   GstFlowReturn ret;
   gboolean emit_signal;
+  GstCaps *caps;
+  gboolean caps_changed;
 
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK,
-      GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
   GST_OBJECT_LOCK (pad);
@@ -4238,28 +4971,28 @@
 
   gst_object_unref (peer);
 
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto pull_range_failed;
+
   /* can only fire the signal if we have a valid buffer */
-  if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) {
+  if (G_UNLIKELY (emit_signal)) {
     if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer)))
       goto dropping;
   }
 
-  if (G_LIKELY (ret == GST_FLOW_OK)) {
-    GstCaps *caps;
-    gboolean caps_changed;
-
-    GST_OBJECT_LOCK (pad);
-    /* Before pushing the buffer to the peer pad, ensure that caps
-     * are set on this pad */
-    caps = GST_BUFFER_CAPS (*buffer);
-    caps_changed = caps && caps != GST_PAD_CAPS (pad);
-    GST_OBJECT_UNLOCK (pad);
-
-    /* we got a new datatype on the pad, see if it can handle it */
-    if (G_UNLIKELY (caps_changed))
+  GST_OBJECT_LOCK (pad);
+  /* Before pushing the buffer to the peer pad, ensure that caps
+   * are set on this pad */
+  caps = GST_BUFFER_CAPS (*buffer);
+  caps_changed = caps && caps != GST_PAD_CAPS (pad);
+  GST_OBJECT_UNLOCK (pad);
+
+  /* we got a new datatype on the pad, see if it can handle it */
+  if (G_UNLIKELY (caps_changed)) {
+    GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
+    if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps)))
       goto not_negotiated;
   }
-
   return ret;
 
   /* ERROR recovery here */
@@ -4270,6 +5003,13 @@
     GST_OBJECT_UNLOCK (pad);
     return GST_FLOW_NOT_LINKED;
   }
+pull_range_failed:
+  {
+    *buffer = NULL;
+    GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pullrange failed %s", gst_flow_get_name (ret));
+    return ret;
+  }
 dropping:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
@@ -4280,21 +5020,11 @@
   }
 not_negotiated:
   {
-    /* ideally we want to use the commented-out code, but currently demuxers
-     * and typefind do not follow part-negotiation.txt. When switching into
-     * pull mode, typefind should probably return the found caps from
-     * getcaps(), and demuxers should do the setcaps(). */
-
-#if 0
     gst_buffer_unref (*buffer);
     *buffer = NULL;
     GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
         "pullrange returned buffer of different caps");
     return GST_FLOW_NOT_NEGOTIATED;
-#endif
-    GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pullrange returned buffer of different caps");
-    return ret;
   }
 }
 
@@ -4623,6 +5353,53 @@
   return pad->element_private;
 }
 
+static void
+do_stream_status (GstPad * pad, GstStreamStatusType type,
+    GThread * thread, GstTask * task)
+{
+  GstElement *parent;
+
+  GST_DEBUG_OBJECT (pad, "doing stream-status %d", type);
+
+  if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (pad)))) {
+    if (GST_IS_ELEMENT (parent)) {
+      GstMessage *message;
+      GValue value = { 0 };
+
+      message = gst_message_new_stream_status (GST_OBJECT_CAST (pad),
+          type, parent);
+
+      g_value_init (&value, GST_TYPE_TASK);
+      g_value_set_object (&value, task);
+      gst_message_set_stream_status_object (message, &value);
+      g_value_unset (&value);
+
+      GST_DEBUG_OBJECT (pad, "posting stream-status %d", type);
+      gst_element_post_message (parent, message);
+    }
+    gst_object_unref (parent);
+  }
+}
+
+static void
+pad_enter_thread (GstTask * task, GThread * thread, gpointer user_data)
+{
+  do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_ENTER,
+      thread, task);
+}
+
+static void
+pad_leave_thread (GstTask * task, GThread * thread, gpointer user_data)
+{
+  do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_LEAVE,
+      thread, task);
+}
+
+static GstTaskThreadCallbacks thr_callbacks = {
+  pad_enter_thread,
+  pad_leave_thread,
+};
+
 /**
  * gst_pad_start_task:
  * @pad: the #GstPad to start the task of
@@ -4644,6 +5421,7 @@
 gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer data)
 {
   GstTask *task;
+  gboolean res;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (func != NULL, FALSE);
@@ -4655,13 +5433,33 @@
   if (task == NULL) {
     task = gst_task_create (func, data);
     gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad));
+    gst_task_set_thread_callbacks (task, &thr_callbacks, pad, NULL);
+    GST_DEBUG_OBJECT (pad, "created task");
     GST_PAD_TASK (pad) = task;
-    GST_DEBUG_OBJECT (pad, "created task");
+    gst_object_ref (task);
+    /* release lock to post the message */
+    GST_OBJECT_UNLOCK (pad);
+
+    do_stream_status (pad, GST_STREAM_STATUS_TYPE_CREATE, NULL, task);
+
+    gst_object_unref (task);
+
+    GST_OBJECT_LOCK (pad);
+    /* nobody else is supposed to have changed the pad now */
+    if (GST_PAD_TASK (pad) != task)
+      goto concurrent_stop;
   }
-  gst_task_start (task);
+  res = gst_task_set_state (task, GST_TASK_STARTED);
   GST_OBJECT_UNLOCK (pad);
 
-  return TRUE;
+  return res;
+
+  /* ERRORS */
+concurrent_stop:
+  {
+    GST_OBJECT_UNLOCK (pad);
+    return TRUE;
+  }
 }
 
 /**
@@ -4683,6 +5481,7 @@
 gst_pad_pause_task (GstPad * pad)
 {
   GstTask *task;
+  gboolean res;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
@@ -4692,7 +5491,7 @@
   task = GST_PAD_TASK (pad);
   if (task == NULL)
     goto no_task;
-  gst_task_pause (task);
+  res = gst_task_set_state (task, GST_TASK_PAUSED);
   GST_OBJECT_UNLOCK (pad);
 
   /* wait for task function to finish, this lock is recursive so it does nothing
@@ -4700,7 +5499,7 @@
   GST_PAD_STREAM_LOCK (pad);
   GST_PAD_STREAM_UNLOCK (pad);
 
-  return TRUE;
+  return res;
 
 no_task:
   {
@@ -4734,6 +5533,7 @@
 gst_pad_stop_task (GstPad * pad)
 {
   GstTask *task;
+  gboolean res;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
@@ -4744,7 +5544,7 @@
   if (task == NULL)
     goto no_task;
   GST_PAD_TASK (pad) = NULL;
-  gst_task_stop (task);
+  res = gst_task_set_state (task, GST_TASK_STOPPED);
   GST_OBJECT_UNLOCK (pad);
 
   GST_PAD_STREAM_LOCK (pad);
@@ -4755,7 +5555,7 @@
 
   gst_object_unref (task);
 
-  return TRUE;
+  return res;
 
 no_task:
   {
--- a/gstreamer_core/gst/gstpad.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpad.h	Fri Apr 16 15:15:52 2010 +0300
@@ -28,6 +28,7 @@
 
 #include <gst/gstobject.h>
 #include <gst/gstbuffer.h>
+#include <gst/gstbufferlist.h>
 #include <gst/gstcaps.h>
 #include <gst/gstevent.h>
 #include <gst/gstquery.h>
@@ -47,6 +48,7 @@
 
 
 typedef struct _GstPad GstPad;
+typedef struct _GstPadPrivate GstPadPrivate;
 typedef struct _GstPadClass GstPadClass;
 
 /**
@@ -229,11 +231,31 @@
  * gst_buffer_unref() when the buffer is no longer needed.
  *
  * When a chain function detects an error in the data stream, it must post an
- * error on the buffer and return an appropriate #GstFlowReturn value.
+ * error on the bus and return an appropriate #GstFlowReturn value.
  *
  * Returns: #GST_FLOW_OK for success
  */
 typedef GstFlowReturn		(*GstPadChainFunction)		(GstPad *pad, GstBuffer *buffer);
+
+/**
+ * GstPadChainListFunction:
+ * @pad: the sink #GstPad that performed the chain.
+ * @list: the #GstBufferList that is chained, not %NULL.
+ *
+ * A function that will be called on sinkpads when chaining buffer lists.
+ * The function typically processes the data contained in the buffer list and
+ * either consumes the data or passes it on to the internally linked pad(s).
+ *
+ * The implementer of this function receives a refcount to @list and
+ * should gst_buffer_list_unref() when the list is no longer needed.
+ *
+ * When a chainlist function detects an error in the data stream, it must
+ * post an error on the bus and return an appropriate #GstFlowReturn value.
+ *
+ * Returns: #GST_FLOW_OK for success
+ */
+typedef GstFlowReturn		(*GstPadChainListFunction)	(GstPad *pad, GstBufferList *list);
+
 /**
  * GstPadGetRangeFunction:
  * @pad: the src #GstPad to perform the getrange on.
@@ -312,11 +334,28 @@
  * The signature of the internal pad link function.
  *
  * Returns: a newly allocated #GList of pads that are linked to the given pad on
- *  the inside of the parent element.
- *  The caller must call g_list_free() on it after use.
+ * the inside of the parent element.
+ *
+ * The caller must call g_list_free() on it after use.
+ *
+ * Deprecated: use the threadsafe #GstPadIterIntLinkFunction instead.
  */
 typedef GList*			(*GstPadIntLinkFunction)	(GstPad *pad);
 
+/**
+ * GstPadIterIntLinkFunction:
+ * @pad: The #GstPad to query.
+ *
+ * The signature of the internal pad link iterator function.
+ *
+ * Returns: a new #GstIterator that will iterate over all pads that are
+ * linked to the given pad on the inside of the parent element.
+ *
+ * the caller must call gst_iterator_free() after usage.
+ *
+ * Since 0.10.21
+ */
+typedef GstIterator*           (*GstPadIterIntLinkFunction)    (GstPad *pad);
 
 /* generic query function */
 /**
@@ -424,13 +463,16 @@
  * be processed by @pad. The function is mostly overridden by elements that can
  * provide a hardware buffer in order to avoid additional memcpy operations.
  *
- * The function can return a buffer that does not have @caps, in which case the
- * upstream element requests a format change. If a format change was requested,
- * the returned buffer will be one to hold the data of said new caps, so its
- * size might be different from @size.
+ * The function can return a buffer that has caps different from the requested
+ * @caps, in which case the upstream element requests a format change to this
+ * new caps.
+ * If a format change was requested, the returned buffer will be one to hold
+ * the data of said new caps, so its size might be different from the requested
+ * @size.
  *
  * When this function returns anything else than #GST_FLOW_OK, the buffer allocation
- * failed and @buf does not contain valid data.
+ * failed and @buf does not contain valid data. If the function returns #GST_FLOW_OK and
+ * the @buf is NULL, a #GstBuffer will be created with @caps, @offset and @size.
  *
  * By default this function returns a new buffer of @size and with @caps containing
  * purely malloced data. The buffer should be freed with gst_buffer_unref()
@@ -530,7 +572,7 @@
  * @unlinkfunc: function called when pad is unlinked
  * @peer: the pad this pad is linked to
  * @sched_private: private storage for the scheduler
- * @chainfunc: function to chain data to pad
+ * @chainfunc: function to chain buffer to pad
  * @checkgetrangefunc: function to check if pad can operate in pull mode
  * @getrangefunc: function to get a range of data from a pad
  * @eventfunc: function to send an event to a pad
@@ -541,6 +583,8 @@
  * @bufferallocfunc: function to allocate a buffer for this pad
  * @do_buffer_signals: counter counting installed buffer signals
  * @do_event_signals: counter counting installed event signals
+ * @iterintlinkfunc: get the internal links iterator of this pad
+ * @block_destroy_data: notify function for gst_pad_set_blocked_async_full()
  *
  * The #GstPad structure. Use the functions to update the variables.
  */
@@ -608,8 +652,21 @@
   gint				 do_buffer_signals;
   gint				 do_event_signals;
 
+  /* ABI added */
+  /* iterate internal links */
+  GstPadIterIntLinkFunction     iterintlinkfunc;
+
+  /* free block_data */
+  GDestroyNotify block_destroy_data;
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  union {
+    struct {
+      gboolean                      block_callback_called;
+      GstPadPrivate                *priv;
+    } ABI;
+    gpointer _gst_reserved[GST_PADDING - 2];
+  } abidata;
 };
 
 struct _GstPadClass {
@@ -646,11 +703,18 @@
 #define GST_PAD_QUERYTYPEFUNC(pad)	(GST_PAD_CAST(pad)->querytypefunc)
 #define GST_PAD_QUERYFUNC(pad)		(GST_PAD_CAST(pad)->queryfunc)
 #define GST_PAD_INTLINKFUNC(pad)	(GST_PAD_CAST(pad)->intlinkfunc)
+#define GST_PAD_ITERINTLINKFUNC(pad)    (GST_PAD_CAST(pad)->iterintlinkfunc)
 
 #define GST_PAD_PEER(pad)		(GST_PAD_CAST(pad)->peer)
 #define GST_PAD_LINKFUNC(pad)		(GST_PAD_CAST(pad)->linkfunc)
 #define GST_PAD_UNLINKFUNC(pad)		(GST_PAD_CAST(pad)->unlinkfunc)
 
+/**
+ * GST_PAD_CAPS:
+ * @pad: a #GstPad.
+ *
+ * The caps for this pad.
+ */
 #define GST_PAD_CAPS(pad)		(GST_PAD_CAST(pad)->caps)
 #define GST_PAD_GETCAPSFUNC(pad)	(GST_PAD_CAST(pad)->getcapsfunc)
 #define GST_PAD_SETCAPSFUNC(pad)	(GST_PAD_CAST(pad)->setcapsfunc)
@@ -821,6 +885,13 @@
 IMPORT_C
 #endif
 
+gboolean		gst_pad_set_blocked_async_full		(GstPad *pad, gboolean blocked,
+								 GstPadBlockCallback callback, gpointer user_data,
+                                                                 GDestroyNotify destroy_data);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 gboolean		gst_pad_is_blocked			(GstPad *pad);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -888,6 +959,11 @@
 IMPORT_C
 #endif
 
+void			gst_pad_set_chain_list_function	(GstPad *pad, GstPadChainListFunction chainlist);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void			gst_pad_set_getrange_function		(GstPad *pad, GstPadGetRangeFunction get);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -916,6 +992,11 @@
 #endif
 
 
+gboolean                gst_pad_can_link                        (GstPad *srcpad, GstPad *sinkpad);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstPadLinkReturn        gst_pad_link				(GstPad *srcpad, GstPad *sinkpad);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -962,7 +1043,7 @@
 
 G_CONST_RETURN GstCaps*	gst_pad_get_pad_template_caps		(GstPad *pad);
 
-/* capsnego function for connected/unconnected pads */
+/* capsnego function for linked/unlinked pads */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -995,7 +1076,7 @@
 
 gboolean		gst_pad_peer_accept_caps		(GstPad * pad, GstCaps *caps);
 
-/* capsnego for connected pads */
+/* capsnego for linked pads */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -1017,6 +1098,11 @@
 IMPORT_C
 #endif
 
+GstFlowReturn		gst_pad_push_list			(GstPad *pad, GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 gboolean		gst_pad_check_pull_range		(GstPad *pad);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -1045,6 +1131,11 @@
 IMPORT_C
 #endif
 
+GstFlowReturn		gst_pad_chain_list                      (GstPad *pad, GstBufferList *list);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstFlowReturn		gst_pad_get_range			(GstPad *pad, guint64 offset, guint size,
 								 GstBuffer **buffer);
 #ifdef __SYMBIAN32__
@@ -1087,6 +1178,24 @@
 #endif
 
 GList*			gst_pad_get_internal_links_default	(GstPad *pad);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void                    gst_pad_set_iterate_internal_links_function (GstPad * pad,
+                                                                 GstPadIterIntLinkFunction iterintlink);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstIterator *           gst_pad_iterate_internal_links          (GstPad * pad);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstIterator *           gst_pad_iterate_internal_links_default  (GstPad * pad);
+
 
 /* generic query function */
 #ifdef __SYMBIAN32__
--- a/gstreamer_core/gst/gstpadtemplate.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpadtemplate.c	Fri Apr 16 15:15:52 2010 +0300
@@ -110,6 +110,14 @@
 
 enum
 {
+  PROP_NAME_TEMPLATE = 1,
+  PROP_DIRECTION,
+  PROP_PRESENCE,
+  PROP_CAPS
+};
+
+enum
+{
   TEMPL_PAD_CREATED,
   /* FILL ME */
   LAST_SIGNAL
@@ -118,35 +126,13 @@
 static GstObject *parent_class = NULL;
 static guint gst_pad_template_signals[LAST_SIGNAL] = { 0 };
 
-static void gst_pad_template_class_init (GstPadTemplateClass * klass);
-static void gst_pad_template_init (GstPadTemplate * templ,
-    GstPadTemplateClass * klass);
 static void gst_pad_template_dispose (GObject * object);
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-GType
-gst_pad_template_get_type (void)
-{
-  static GType padtemplate_type = 0;
+static void gst_pad_template_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_pad_template_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
-  if (G_UNLIKELY (padtemplate_type == 0)) {
-    static const GTypeInfo padtemplate_info = {
-      sizeof (GstPadTemplateClass), NULL, NULL,
-      (GClassInitFunc) gst_pad_template_class_init, NULL, NULL,
-      sizeof (GstPadTemplate),
-      0,
-      (GInstanceInitFunc) gst_pad_template_init, NULL
-    };
-
-    padtemplate_type =
-        g_type_register_static (GST_TYPE_OBJECT, "GstPadTemplate",
-        &padtemplate_info, 0);
-  }
-  return padtemplate_type;
-}
+G_DEFINE_TYPE (GstPadTemplate, gst_pad_template, GST_TYPE_OBJECT);
 
 static void
 gst_pad_template_class_init (GstPadTemplateClass * klass)
@@ -173,11 +159,65 @@
 
   gobject_class->dispose = gst_pad_template_dispose;
 
+  gobject_class->get_property = gst_pad_template_get_property;
+  gobject_class->set_property = gst_pad_template_set_property;
+
+  /**
+   * GstPadTemplate:name-template
+   *
+   * The name template of the pad template.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_NAME_TEMPLATE,
+      g_param_spec_string ("name-template", "Name template",
+          "The name template of the pad template", NULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstPadTemplate:direction
+   *
+   * The direction of the pad described by the pad template.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_DIRECTION,
+      g_param_spec_enum ("direction", "Direction",
+          "The direction of the pad described by the pad template",
+          GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstPadTemplate:presence
+   *
+   * When the pad described by the pad template will become available.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_PRESENCE,
+      g_param_spec_enum ("presence", "Presence",
+          "When the pad described by the pad template will become available",
+          GST_TYPE_PAD_PRESENCE, GST_PAD_ALWAYS,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstPadTemplate:caps
+   *
+   * The capabilities of the pad described by the pad template.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_CAPS,
+      g_param_spec_boxed ("caps", "Caps",
+          "The capabilities of the pad described by the pad template",
+          GST_TYPE_CAPS,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
   gstobject_class->path_string_separator = "*";
 }
 
 static void
-gst_pad_template_init (GstPadTemplate * templ, GstPadTemplateClass * klass)
+gst_pad_template_init (GstPadTemplate * templ)
 {
   /* FIXME 0.11: Does anybody remember why this is here? If not, let's
    * change it for 0.11 and let gst_element_class_add_pad_template() for
@@ -191,8 +231,7 @@
    * owned by the creator of the object
    */
   if (GST_OBJECT_IS_FLOATING (templ)) {
-    gst_object_ref (templ);
-    gst_object_sink (templ);
+    gst_object_ref_sink (templ);
   }
 }
 
@@ -234,9 +273,9 @@
           " allowed in GST_PAD_REQUEST padtemplate", name);
       return FALSE;
     }
-    if (str && (*(str + 1) != 's' && *(str + 1) != 'd')) {
+    if (str && (*(str + 1) != 's' && *(str + 1) != 'd' && *(str + 1) != 'u')) {
       g_warning ("invalid name template %s: conversion specification must be of"
-          " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name);
+          " type '%%d', '%%u' or '%%s' for GST_PAD_REQUEST padtemplate", name);
       return FALSE;
     }
     if (str && (*(str + 2) != '\0')) {
@@ -281,19 +320,20 @@
 gst_static_pad_template_get (GstStaticPadTemplate * pad_template)
 {
   GstPadTemplate *new;
+  GstCaps *caps;
 
   if (!name_is_valid (pad_template->name_template, pad_template->presence))
     return NULL;
 
-  new = g_object_new (gst_pad_template_get_type (),
-      "name", pad_template->name_template, NULL);
+  caps = gst_static_caps_get (&pad_template->static_caps);
 
-  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (pad_template->name_template);
-  GST_PAD_TEMPLATE_DIRECTION (new) = pad_template->direction;
-  GST_PAD_TEMPLATE_PRESENCE (new) = pad_template->presence;
+  new = g_object_new (gst_pad_template_get_type (),
+      "name", pad_template->name_template,
+      "name-template", pad_template->name_template,
+      "direction", pad_template->direction,
+      "presence", pad_template->presence, "caps", caps, NULL);
 
-  GST_PAD_TEMPLATE_CAPS (new) =
-      gst_caps_make_writable (gst_static_caps_get (&pad_template->static_caps));
+  gst_caps_unref (caps);
 
   return new;
 }
@@ -333,12 +373,11 @@
   }
 
   new = g_object_new (gst_pad_template_get_type (),
-      "name", name_template, NULL);
+      "name", name_template, "name-template", name_template,
+      "direction", direction, "presence", presence, "caps", caps, NULL);
 
-  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template);
-  GST_PAD_TEMPLATE_DIRECTION (new) = direction;
-  GST_PAD_TEMPLATE_PRESENCE (new) = presence;
-  GST_PAD_TEMPLATE_CAPS (new) = caps;
+  if (caps)
+    gst_caps_unref (caps);
 
   return new;
 }
@@ -349,8 +388,10 @@
  *
  * Gets the capabilities of the static pad template.
  *
- * Returns: the #GstCaps of the static pad template. If you need to keep a
- * reference to the caps, take a ref (see gst_caps_ref ()).
+ * Returns: the #GstCaps of the static pad template.
+ * Unref after usage. Since the core holds an additional
+ * ref to the returned caps, use gst_caps_make_writable()
+ * on the returned caps to modify it.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -402,3 +443,56 @@
   g_signal_emit (G_OBJECT (templ),
       gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
 }
+
+static void
+gst_pad_template_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  /* these properties are all construct-only */
+  switch (prop_id) {
+    case PROP_NAME_TEMPLATE:
+      GST_PAD_TEMPLATE_NAME_TEMPLATE (object) = g_value_dup_string (value);
+      break;
+    case PROP_DIRECTION:
+      GST_PAD_TEMPLATE_DIRECTION (object) = g_value_get_enum (value);
+      break;
+    case PROP_PRESENCE:
+      GST_PAD_TEMPLATE_PRESENCE (object) = g_value_get_enum (value);
+      break;
+    case PROP_CAPS:
+      /* allow caps == NULL for backwards compatibility (ie. g_object_new()
+       * called without any of the new properties) (FIXME 0.11) */
+      if (g_value_get_boxed (value) != NULL) {
+        GST_PAD_TEMPLATE_CAPS (object) =
+            gst_caps_copy (g_value_get_boxed (value));
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_pad_template_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  /* these properties are all construct-only */
+  switch (prop_id) {
+    case PROP_NAME_TEMPLATE:
+      g_value_set_string (value, GST_PAD_TEMPLATE_NAME_TEMPLATE (object));
+      break;
+    case PROP_DIRECTION:
+      g_value_set_enum (value, GST_PAD_TEMPLATE_DIRECTION (object));
+      break;
+    case PROP_PRESENCE:
+      g_value_set_enum (value, GST_PAD_TEMPLATE_PRESENCE (object));
+      break;
+    case PROP_CAPS:
+      g_value_set_boxed (value, GST_PAD_TEMPLATE_CAPS (object));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
--- a/gstreamer_core/gst/gstparamspecs.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstparamspecs.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,6 +16,15 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:gstparamspec
+ * @short_description: GParamSpec implementations specific
+ * to GStreamer
+ *
+ * GParamSpec implementations specific to GStreamer.
+ *
+ * Last reviewed on 2008-03-11 (0.10.18)
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
--- a/gstreamer_core/gst/gstparamspecs.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstparamspecs.h	Fri Apr 16 15:15:52 2010 +0300
@@ -24,6 +24,56 @@
 
 G_BEGIN_DECLS
 
+/* --- paramspec flags */
+
+/**
+ * GST_PARAM_CONTROLLABLE:
+ *
+ * Use this flag on GObject properties to signal they can make sense to be.
+ * controlled over time. This hint is used by the GstController.
+ */
+#define	GST_PARAM_CONTROLLABLE	(1 << (G_PARAM_USER_SHIFT + 1))
+
+/**
+ * GST_PARAM_MUTABLE_READY:
+ *
+ * Use this flag on GObject properties of GstElements to indicate that
+ * they can be changed when the element is in the READY or lower state.
+ *
+ * Since: 0.10.23
+ */
+#define GST_PARAM_MUTABLE_READY  (1 << (G_PARAM_USER_SHIFT + 2))
+
+/**
+ * GST_PARAM_MUTABLE_PAUSED:
+ *
+ * Use this flag on GObject properties of GstElements to indicate that
+ * they can be changed when the element is in the PAUSED or lower state.
+ * This flag implies GST_PARAM_MUTABLE_READY.
+ *
+ * Since: 0.10.23
+ */
+#define GST_PARAM_MUTABLE_PAUSED  (1 << (G_PARAM_USER_SHIFT + 3))
+
+/**
+ * GST_PARAM_MUTABLE_PLAYING:
+ *
+ * Use this flag on GObject properties of GstElements to indicate that
+ * they can be changed when the element is in the PLAYING or lower state.
+ * This flag implies GST_PARAM_MUTABLE_PAUSED.
+ *
+ * Since: 0.10.23
+ */
+#define GST_PARAM_MUTABLE_PLAYING  (1 << (G_PARAM_USER_SHIFT + 4))
+
+/**
+ * GST_PARAM_USER_SHIFT:
+ *
+ * Bits based on GST_PARAM_USER_SHIFT can be used by 3rd party applications.
+ */
+#define	GST_PARAM_USER_SHIFT	(1 << (G_PARAM_USER_SHIFT + 8))
+
+
 /* --- type macros --- */
 
 #define GST_TYPE_PARAM_FRACTION           (gst_param_spec_fraction_get_type ())
--- a/gstreamer_core/gst/gstparse.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstparse.c	Fri Apr 16 15:15:52 2010 +0300
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000 Wim Taymans <wtay@chello.be>
  *                    2002 Andy Wingo <wingo@pobox.com>
+ *                    2008 Tim-Philipp Müller <tim centricular net>
  *
  * gstparse.c: get a pipeline from a text pipeline description
  *
@@ -26,7 +27,7 @@
  * @short_description: Get a pipeline from a text pipeline description
  *
  * These function allow to create a pipeline based on the syntax used in the
- * gst-launch utillity.
+ * gst-launch utility.
  */
 
 
@@ -37,7 +38,8 @@
 #include "gsterror.h"
 #include "gstinfo.h"
 
-extern GstElement *_gst_parse_launch (const gchar *, GError **);
+extern GstElement *_gst_parse_launch (const gchar *, GError **,
+    GstParseContext *, GstParseFlags);
 
 /**
  * gst_parse_error_quark:
@@ -60,12 +62,111 @@
   return quark;
 }
 
+
+/**
+ * gst_parse_context_new:
+ *
+ * Allocates a parse context for use with gst_parse_launch_full() or
+ * gst_parse_launchv_full().
+ *
+ * Returns: a newly-allocated parse context. Free with gst_parse_context_free()
+ *     when no longer needed.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstParseContext *
+gst_parse_context_new (void)
+{
+#ifndef GST_DISABLE_PARSE
+  GstParseContext *ctx;
+
+  ctx = g_slice_new (GstParseContext);
+  ctx->missing_elements = NULL;
+
+  return ctx;
+#else
+  return NULL;
+#endif
+}
+
+/**
+ * gst_parse_context_free:
+ * @context: a #GstParseContext
+ *
+ * Frees a parse context previously allocated with gst_parse_context_new().
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_parse_context_free (GstParseContext * context)
+{
+#ifndef GST_DISABLE_PARSE
+  if (context) {
+    g_list_foreach (context->missing_elements, (GFunc) g_free, NULL);
+    g_list_free (context->missing_elements);
+    g_slice_free (GstParseContext, context);
+  }
+#endif
+}
+
+/**
+ * gst_parse_context_get_missing_elements:
+ * @context: a #GstParseContext
+ *
+ * Retrieve missing elements from a previous run of gst_parse_launch_full()
+ * or gst_parse_launchv_full(). Will only return results if an error code
+ * of %GST_PARSE_ERROR_NO_SUCH_ELEMENT was returned.
+ *
+ * Returns: a NULL-terminated array of element factory name strings of
+ *     missing elements. Free with g_strfreev() when no longer needed.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gchar **
+gst_parse_context_get_missing_elements (GstParseContext * context)
+{
+#ifndef GST_DISABLE_PARSE
+  gchar **arr;
+  GList *l;
+  guint len, i;
+
+  g_return_val_if_fail (context != NULL, NULL);
+
+  len = g_list_length (context->missing_elements);
+
+  if (G_UNLIKELY (len == 0))
+    return NULL;
+
+  arr = g_new (gchar *, len + 1);
+
+  for (i = 0, l = context->missing_elements; l != NULL; l = l->next, ++i)
+    arr[i] = g_strdup (l->data);
+
+  arr[i] = NULL;
+
+  return arr;
+#else
+  return NULL;
+#endif
+}
+
 #ifndef GST_DISABLE_PARSE
 static gchar *
 _gst_parse_escape (const gchar * str)
 {
   GString *gstr = NULL;
-  gchar *newstr = NULL;
 
   g_return_val_if_fail (str != NULL, NULL);
 
@@ -78,10 +179,7 @@
     str++;
   }
 
-  newstr = gstr->str;
-  g_string_free (gstr, FALSE);
-
-  return newstr;
+  return g_string_free (gstr, FALSE);
 }
 #endif /* !GST_DISABLE_PARSE */
 
@@ -103,6 +201,35 @@
 GstElement *
 gst_parse_launchv (const gchar ** argv, GError ** error)
 {
+  return gst_parse_launchv_full (argv, NULL, 0, error);
+}
+
+/**
+ * gst_parse_launchv_full:
+ * @argv: null-terminated array of arguments
+ * @context: a parse context allocated with gst_parse_context_new(), or %NULL
+ * @flags: parsing options, or #GST_PARSE_FLAG_NONE
+ * @error: pointer to a #GError (which must be initialised to %NULL)
+ *
+ * Create a new element based on command line syntax.
+ * @error will contain an error message if an erroneous pipeline is specified.
+ * An error does not mean that the pipeline could not be constructed.
+ *
+ * Returns: a new element on success; on failure, either %NULL or a
+ * partially-constructed bin or element will be returned and @error will be set
+ * (unless you passed #GST_PARSE_FLAG_FATAL_ERRORS in @flags, then %NULL will
+ * always be returned on failure)
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstElement *
+gst_parse_launchv_full (const gchar ** argv, GstParseContext * context,
+    GstParseFlags flags, GError ** error)
+{
 #ifndef GST_DISABLE_PARSE
   GstElement *element;
   GString *str;
@@ -110,6 +237,7 @@
   gchar *tmp;
 
   g_return_val_if_fail (argv != NULL, NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
   /* let's give it a nice size. */
   str = g_string_sized_new (1024);
@@ -124,21 +252,14 @@
     argvp++;
   }
 
-  element = gst_parse_launch (str->str, error);
+  element = gst_parse_launch_full (str->str, context, flags, error);
 
   g_string_free (str, TRUE);
 
   return element;
 #else
-  gchar *msg;
-
-  GST_WARNING ("Disabled API called: gst_parse_launchv()");
-
-  msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
-  g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
-  g_free (msg);
-
-  return NULL;
+  /* gst_parse_launch_full() will set a GST_CORE_ERROR_DISABLED error for us */
+  return gst_parse_launch_full ("", NULL, 0, error);
 #endif
 }
 
@@ -163,21 +284,59 @@
 GstElement *
 gst_parse_launch (const gchar * pipeline_description, GError ** error)
 {
+  return gst_parse_launch_full (pipeline_description, NULL, 0, error);
+}
+
+/**
+ * gst_parse_launch_full:
+ * @pipeline_description: the command line describing the pipeline
+ * @context: a parse context allocated with gst_parse_context_new(), or %NULL
+ * @flags: parsing options, or #GST_PARSE_FLAG_NONE
+ * @error: the error message in case of an erroneous pipeline.
+ *
+ * Create a new pipeline based on command line syntax.
+ * Please note that you might get a return value that is not %NULL even though
+ * the @error is set. In this case there was a recoverable parsing error and you
+ * can try to play the pipeline.
+ *
+ * Returns: a new element on success, %NULL on failure. If more than one toplevel
+ * element is specified by the @pipeline_description, all elements are put into
+ * a #GstPipeline, which then is returned.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstElement *
+gst_parse_launch_full (const gchar * pipeline_description,
+    GstParseContext * context, GstParseFlags flags, GError ** error)
+{
 #ifndef GST_DISABLE_PARSE
   GstElement *element;
 
   g_return_val_if_fail (pipeline_description != NULL, NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-  GST_CAT_INFO (GST_CAT_PIPELINE, "parsing pipeline description %s",
+  GST_CAT_INFO (GST_CAT_PIPELINE, "parsing pipeline description '%s'",
       pipeline_description);
 
-  element = _gst_parse_launch (pipeline_description, error);
+  element = _gst_parse_launch (pipeline_description, error, context, flags);
+
+  /* don't return partially constructed pipeline if FATAL_ERRORS was given */
+  if (G_UNLIKELY (error != NULL && *error != NULL && element != NULL)) {
+    if ((flags & GST_PARSE_FLAG_FATAL_ERRORS)) {
+      gst_object_unref (element);
+      element = NULL;
+    }
+  }
 
   return element;
 #else
   gchar *msg;
 
-  GST_WARNING ("Disabled API called: gst_parse_launch()");
+  GST_WARNING ("Disabled API called");
 
   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
   g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
--- a/gstreamer_core/gst/gstparse.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstparse.h	Fri Apr 16 15:15:52 2010 +0300
@@ -57,18 +57,87 @@
   GST_PARSE_ERROR_EMPTY_BIN,
   GST_PARSE_ERROR_EMPTY
 } GstParseError;
+
+/**
+ * GstParseFlags:
+ * @GST_PARSE_FLAG_NONE: Do not use any special parsing options.
+ * @GST_PARSE_FLAG_FATAL_ERRORS: Always return NULL when an error occurs
+ *     (default behaviour is to return partially constructed bins or elements
+ *      in some cases)
+ *
+ * Parsing options.
+ *
+ * Since: 0.10.20
+ */
+typedef enum
+{
+  GST_PARSE_FLAG_NONE = 0,
+  GST_PARSE_FLAG_FATAL_ERRORS = (1 << 0)
+} GstParseFlags;
+
+/**
+ * GstParseContext:
+ *
+ * Opaque structure.
+ *
+ * Since: 0.10.20
+ */
+typedef struct _GstParseContext GstParseContext;
+
+/* create, process and free a parse context */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstParseContext * gst_parse_context_new (void);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
+gchar          ** gst_parse_context_get_missing_elements (GstParseContext * context);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
 
-GstElement*	gst_parse_launch	(const gchar *pipeline_description, GError **error);
+
+void              gst_parse_context_free (GstParseContext * context);
+
+
+/* parse functions */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstElement      * gst_parse_launch       (const gchar      * pipeline_description,
+                                          GError          ** error);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-GstElement*	gst_parse_launchv	(const gchar **argv, GError **error);
+
+GstElement      * gst_parse_launchv      (const gchar     ** argv,
+                                          GError          ** error);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstElement      * gst_parse_launch_full  (const gchar      * pipeline_description,
+                                          GstParseContext  * context,
+                                          GstParseFlags      flags,
+                                          GError          ** error);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstElement      * gst_parse_launchv_full (const gchar     ** argv,
+                                          GstParseContext  * context,
+                                          GstParseFlags      flags,
+                                          GError          ** error);
 
 G_END_DECLS
 
--- a/gstreamer_core/gst/gstpipeline.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpipeline.c	Fri Apr 16 15:15:52 2010 +0300
@@ -62,21 +62,23 @@
  * gst_pipeline_auto_clock() the default clock selection algorithm can be
  * restored.
  *
- * A #GstPipeline maintains a stream time for the elements. The stream
+ * A #GstPipeline maintains a running time for the elements. The running
  * time is defined as the difference between the current clock time and
  * the base time. When the pipeline goes to READY or a flushing seek is
- * performed on it, the stream time is reset to 0. When the pipeline is
+ * performed on it, the running time is reset to 0. When the pipeline is
  * set from PLAYING to PAUSED, the current clock time is sampled and used to
  * configure the base time for the elements when the pipeline is set
- * to PLAYING again. This default behaviour can be changed with the
- * gst_pipeline_set_new_stream_time() method.
+ * to PLAYING again. The effect is that the running time (as the difference
+ * between the clock time and the base time) will count how much time was spent
+ * in the PLAYING state. This default behaviour can be changed with the
+ * gst_element_set_start_time() method.
  *
  * When sending a flushing seek event to a GstPipeline (see
  * gst_element_seek()), it will make sure that the pipeline is properly
- * PAUSED and resumed as well as set the new stream time to 0 when the
+ * PAUSED and resumed as well as set the new running time to 0 when the
  * seek succeeded.
  *
- * Last reviewed on 2006-03-12 (0.10.5)
+ * Last reviewed on 2009-05-29 (0.10.24)
  */
 
 #include "gst_private.h"
@@ -86,7 +88,7 @@
 #include "gstpipeline.h"
 #include "gstinfo.h"
 #include "gstsystemclock.h"
-
+#include "gstutils.h"
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #endif
@@ -121,14 +123,12 @@
 
   /* when we need to update stream_time or clock when going back to
    * PLAYING*/
-  gboolean update_stream_time;
+  GstClockTime last_start_time;
   gboolean update_clock;
 };
 
 
 static void gst_pipeline_base_init (gpointer g_class);
-static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
-static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
 
 static void gst_pipeline_dispose (GObject * object);
 static void gst_pipeline_set_property (GObject * object, guint prop_id,
@@ -142,41 +142,16 @@
 
 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message);
 
-static GstBinClass *parent_class = NULL;
-
 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-GType
-gst_pipeline_get_type (void)
-{
-  static GType pipeline_type = 0;
 
-  if (G_UNLIKELY (pipeline_type == 0)) {
-    static const GTypeInfo pipeline_info = {
-      sizeof (GstPipelineClass),
-      gst_pipeline_base_init,
-      NULL,
-      (GClassInitFunc) gst_pipeline_class_init,
-      NULL,
-      NULL,
-      sizeof (GstPipeline),
-      0,
-      gst_pipeline_init,
-      NULL
-    };
+#define _do_init(type) \
+{ \
+  GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD, \
+      "debugging info for the 'pipeline' container element"); \
+}
 
-    pipeline_type =
-        g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0);
-
-    GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD,
-        "debugging info for the 'pipeline' container element");
-  }
-  return pipeline_type;
-}
+GST_BOILERPLATE_FULL (GstPipeline, gst_pipeline, GstBin, GST_TYPE_BIN,
+    _do_init);
 
 static void
 gst_pipeline_base_init (gpointer g_class)
@@ -190,12 +165,11 @@
 }
 
 static void
-gst_pipeline_class_init (gpointer g_class, gpointer class_data)
+gst_pipeline_class_init (GstPipelineClass * klass)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-  GstBinClass *gstbin_class = GST_BIN_CLASS (g_class);
-  GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  GstBinClass *gstbin_class = GST_BIN_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -217,7 +191,7 @@
       g_param_spec_uint64 ("delay", "Delay",
           "Expected delay needed for elements "
           "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstPipeline:auto-flush-bus:
@@ -232,7 +206,7 @@
       g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus",
           "Whether to automatically flush the pipeline's bus when going "
           "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
 
@@ -245,9 +219,8 @@
 }
 
 static void
-gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
+gst_pipeline_init (GstPipeline * pipeline, GstPipelineClass * klass)
 {
-  GstPipeline *pipeline = GST_PIPELINE (instance);
   GstBus *bus;
 
   pipeline->priv = GST_PIPELINE_GET_PRIVATE (pipeline);
@@ -322,15 +295,16 @@
   }
 }
 
-/* set the stream time to 0 */
+/* set the start_time to 0, this will cause us to select a new base_time and
+ * make the running_time start from 0 again. */
 static void
-reset_stream_time (GstPipeline * pipeline)
+reset_start_time (GstPipeline * pipeline)
 {
   GST_OBJECT_LOCK (pipeline);
-  if (pipeline->stream_time != GST_CLOCK_TIME_NONE) {
-    GST_DEBUG_OBJECT (pipeline, "reset stream_time to 0");
-    pipeline->stream_time = 0;
-    pipeline->priv->update_stream_time = TRUE;
+  if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) {
+    GST_DEBUG_OBJECT (pipeline, "reset start_time to 0");
+    GST_ELEMENT_START_TIME (pipeline) = 0;
+    pipeline->priv->last_start_time = -1;
   } else {
     GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time");
   }
@@ -380,8 +354,8 @@
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     {
       GstClockTime new_base_time;
-      GstClockTime start_time, stream_time, delay;
-      gboolean new_clock, update_stream_time, update_clock;
+      GstClockTime now, start_time, last_start_time, delay;
+      gboolean update_clock;
       GstClock *cur_clock;
 
       GST_DEBUG_OBJECT (element, "selecting clock and base_time");
@@ -390,18 +364,20 @@
       cur_clock = element->clock;
       if (cur_clock)
         gst_object_ref (cur_clock);
-      stream_time = pipeline->stream_time;
-      update_stream_time = pipeline->priv->update_stream_time;
+      /* get the desired running_time of the first buffer aka the start_time */
+      start_time = GST_ELEMENT_START_TIME (pipeline);
+      last_start_time = pipeline->priv->last_start_time;
+      pipeline->priv->last_start_time = start_time;
+      /* see if we need to update the clock */
       update_clock = pipeline->priv->update_clock;
-      pipeline->priv->update_stream_time = FALSE;
       pipeline->priv->update_clock = FALSE;
       delay = pipeline->delay;
       GST_OBJECT_UNLOCK (element);
 
-      /* stream time changed, either with a PAUSED or a flush, we need to check
+      /* running time changed, either with a PAUSED or a flush, we need to check
        * if there is a new clock & update the base time */
-      if (update_stream_time) {
-        GST_DEBUG_OBJECT (pipeline, "Need to update stream_time");
+      if (last_start_time != start_time) {
+        GST_DEBUG_OBJECT (pipeline, "Need to update start_time");
 
         /* when going to PLAYING, select a clock when needed. If we just got
          * flushed, we don't reselect the clock. */
@@ -414,17 +390,14 @@
           clock = gst_object_ref (cur_clock);
         }
 
-        new_clock = (clock != cur_clock);
-
         if (clock) {
-          start_time = gst_clock_get_time (clock);
+          now = gst_clock_get_time (clock);
         } else {
           GST_DEBUG ("no clock, using base time of NONE");
-          start_time = GST_CLOCK_TIME_NONE;
-          new_base_time = GST_CLOCK_TIME_NONE;
+          now = GST_CLOCK_TIME_NONE;
         }
 
-        if (new_clock) {
+        if (clock != cur_clock) {
           /* now distribute the clock (which could be NULL). If some
            * element refuses the clock, this will return FALSE and
            * we effectively fail the state change. */
@@ -440,13 +413,12 @@
         if (clock)
           gst_object_unref (clock);
 
-        if (stream_time != GST_CLOCK_TIME_NONE
-            && start_time != GST_CLOCK_TIME_NONE) {
-          new_base_time = start_time - stream_time + delay;
+        if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) {
+          new_base_time = now - start_time + delay;
           GST_DEBUG_OBJECT (element,
-              "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
+              "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
               ", base_time %" GST_TIME_FORMAT,
-              GST_TIME_ARGS (stream_time), GST_TIME_ARGS (start_time),
+              GST_TIME_ARGS (start_time), GST_TIME_ARGS (now),
               GST_TIME_ARGS (new_base_time));
         } else
           new_base_time = GST_CLOCK_TIME_NONE;
@@ -455,7 +427,7 @@
           gst_element_set_base_time (element, new_base_time);
         else
           GST_DEBUG_OBJECT (pipeline,
-              "NOT adjusting base_time because stream_time is NONE");
+              "NOT adjusting base_time because start_time is NONE");
       } else {
         GST_DEBUG_OBJECT (pipeline,
             "NOT adjusting base_time because we selected one before");
@@ -466,6 +438,33 @@
       break;
     }
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      GST_OBJECT_LOCK (element);
+      if ((clock = element->clock)) {
+        GstClockTime now;
+
+        gst_object_ref (clock);
+        GST_OBJECT_UNLOCK (element);
+
+        /* calculate the time when we stopped */
+        now = gst_clock_get_time (clock);
+        gst_object_unref (clock);
+
+        GST_OBJECT_LOCK (element);
+        /* store the current running time */
+        if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) {
+          GST_ELEMENT_START_TIME (pipeline) = now - element->base_time;
+          /* we went to PAUSED, when going to PLAYING select clock and new
+           * base_time */
+          pipeline->priv->update_clock = TRUE;
+        }
+        GST_DEBUG_OBJECT (element,
+            "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
+            ", base_time %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (GST_ELEMENT_START_TIME (pipeline)),
+            GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
+      }
+      GST_OBJECT_UNLOCK (element);
+      break;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -479,54 +478,37 @@
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
     {
-      reset_stream_time (pipeline);
+      reset_start_time (pipeline);
       break;
     }
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      GST_OBJECT_LOCK (element);
-      if ((clock = element->clock)) {
-        GstClockTime now;
-
-        gst_object_ref (clock);
-        GST_OBJECT_UNLOCK (element);
-
-        /* calculate the time when we stopped */
-        now = gst_clock_get_time (clock);
-        gst_object_unref (clock);
-
-        GST_OBJECT_LOCK (element);
-        /* store the current stream time */
-        if (pipeline->stream_time != GST_CLOCK_TIME_NONE) {
-          pipeline->stream_time = now - element->base_time;
-          /* we went to PAUSED, when going to PLAYING select clock and new
-           * base_time */
-          pipeline->priv->update_stream_time = TRUE;
-          pipeline->priv->update_clock = TRUE;
-        }
-
-        GST_DEBUG_OBJECT (element,
-            "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
-            ", base_time %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (pipeline->stream_time), GST_TIME_ARGS (now),
-            GST_TIME_ARGS (element->base_time));
-      }
-      GST_OBJECT_UNLOCK (element);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
+    {
+      GstBus *bus;
+      gboolean auto_flush;
+
+      /* grab some stuff before we release the lock to flush out the bus */
       GST_OBJECT_LOCK (element);
-      if (element->bus) {
-        if (pipeline->priv->auto_flush_bus) {
-          gst_bus_set_flushing (element->bus, TRUE);
+      if ((bus = element->bus))
+        gst_object_ref (bus);
+      auto_flush = pipeline->priv->auto_flush_bus;
+      GST_OBJECT_UNLOCK (element);
+
+      if (bus) {
+        if (auto_flush) {
+          gst_bus_set_flushing (bus, TRUE);
         } else {
           GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled");
         }
+        gst_object_unref (bus);
       }
-      GST_OBJECT_UNLOCK (element);
       break;
+    }
   }
   return result;
 
@@ -546,6 +528,12 @@
   }
 }
 
+/* intercept the bus messages from our children. We watch for the ASYNC_START
+ * message with is posted by the elements (sinks) that require a reset of the
+ * running_time after a flush. ASYNC_START also brings the pipeline back into
+ * the PAUSED, pending PAUSED state. When the ASYNC_DONE message is received the
+ * pipeline will redistribute the new base_time and will bring the elements back
+ * to the desired state of the pipeline. */
 static void
 gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
 {
@@ -558,10 +546,10 @@
 
       gst_message_parse_async_start (message, &new_base_time);
 
-      /* reset our stream time if we need to distribute a new base_time to the
+      /* reset our running time if we need to distribute a new base_time to the
        * children. */
       if (new_base_time)
-        reset_stream_time (pipeline);
+        reset_start_time (pipeline);
 
       break;
     }
@@ -575,7 +563,7 @@
  * gst_pipeline_get_bus:
  * @pipeline: a #GstPipeline
  *
- * Gets the #GstBus of @pipeline.
+ * Gets the #GstBus of @pipeline. The bus allows applications to receive #GstMessages.
  *
  * Returns: a #GstBus, unref after usage.
  *
@@ -594,9 +582,9 @@
 /**
  * gst_pipeline_set_new_stream_time:
  * @pipeline: a #GstPipeline
- * @time: the new stream time to set
+ * @time: the new running time to set
  *
- * Set the new stream time of @pipeline to @time. The stream time is used to
+ * Set the new start time of @pipeline to @time. The start time is used to
  * set the base time on the elements (see gst_element_set_base_time())
  * in the PAUSED->PLAYING state transition.
  *
@@ -607,49 +595,50 @@
  * pipelines have the same clock.
  *
  * MT safe.
+ *
+ * Deprecated: This function has the wrong name and is equivalent to
+ * gst_element_set_start_time(). 
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 void
 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
 {
   g_return_if_fail (GST_IS_PIPELINE (pipeline));
 
-  GST_OBJECT_LOCK (pipeline);
-  pipeline->stream_time = time;
-  pipeline->priv->update_stream_time = TRUE;
-  GST_OBJECT_UNLOCK (pipeline);
-
-  GST_DEBUG_OBJECT (pipeline, "set new stream_time to %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (time));
+  gst_element_set_start_time (GST_ELEMENT_CAST (pipeline), time);
 
   if (time == GST_CLOCK_TIME_NONE)
     GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time");
 }
+#endif /* GST_REMOVE_DEPRECATED */
 
 /**
  * gst_pipeline_get_last_stream_time:
  * @pipeline: a #GstPipeline
  *
- * Gets the last stream time of @pipeline. If the pipeline is PLAYING,
- * the returned time is the stream time used to configure the element's
+ * Gets the last running time of @pipeline. If the pipeline is PLAYING,
+ * the returned time is the running time used to configure the element's
  * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the
- * returned time is the stream time when the pipeline was paused.
+ * returned time is the running time when the pipeline was paused.
  *
  * This function returns #GST_CLOCK_TIME_NONE if the pipeline was
  * configured to not handle the management of the element's base time
  * (see gst_pipeline_set_new_stream_time()).
  *
+ * MT safe.
+ *
  * Returns: a #GstClockTime.
  *
- * MT safe.
+ * Deprecated: This function has the wrong name and is equivalent to
+ * gst_element_get_start_time(). 
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 GstClockTime
 gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
 {
@@ -657,12 +646,11 @@
 
   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
 
-  GST_OBJECT_LOCK (pipeline);
-  result = pipeline->stream_time;
-  GST_OBJECT_UNLOCK (pipeline);
+  result = gst_element_get_start_time (GST_ELEMENT_CAST (pipeline));
 
   return result;
 }
+#endif /* GST_REMOVE_DEPRECATED */
 
 static GstClock *
 gst_pipeline_provide_clock_func (GstElement * element)
@@ -684,8 +672,8 @@
     GST_OBJECT_UNLOCK (pipeline);
     /* let the parent bin select a clock */
     clock =
-        GST_ELEMENT_CLASS (parent_class)->
-        provide_clock (GST_ELEMENT (pipeline));
+        GST_ELEMENT_CLASS (parent_class)->provide_clock (GST_ELEMENT
+        (pipeline));
     /* no clock, use a system clock */
     if (!clock) {
       clock = gst_system_clock_obtain ();
--- a/gstreamer_core/gst/gstpipeline.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpipeline.h	Fri Apr 16 15:15:52 2010 +0300
@@ -59,7 +59,8 @@
  *               GST_PIPELINE_FLAG_FIXED_CLOCK is set.
  * @stream_time: The stream time of the pipeline. A better name for this
  *         property would be the running_time, the total time spent in the
- *         PLAYING state without being flushed.
+ *         PLAYING state without being flushed. (deprecated, use the start_time
+ *         on GstElement).
  * @delay: Extra delay added to base_time to compensate for computing delays
  *         when setting elements to PLAYING.
  *
@@ -103,22 +104,23 @@
 
 
 GstBus*		gst_pipeline_get_bus		(GstPipeline *pipeline);
+
+#ifndef GST_DISABLE_DEPRECATED
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-
 void		gst_pipeline_set_new_stream_time  (GstPipeline *pipeline, GstClockTime time);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 GstClockTime	gst_pipeline_get_last_stream_time (GstPipeline *pipeline);
+#endif
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-
 void            gst_pipeline_use_clock          (GstPipeline *pipeline, GstClock *clock);
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gstreamer_core/gst/gstplugin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstplugin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -36,12 +36,9 @@
  * #GstPluginInitFunc function that was provided in the
  * <symbol>gst_plugin_desc</symbol>.
  *
- * Once you have a handle to a #GstPlugin (e.g. from the #GstRegistryPool), you
+ * Once you have a handle to a #GstPlugin (e.g. from the #GstRegistry), you
  * can add any object that subclasses #GstPluginFeature.
  *
- * Use gst_plugin_find_feature() and gst_plugin_get_feature_list() to find
- * features in a plugin.
- *
  * Usually plugins are always automaticlly loaded so you don't need to call
  * gst_plugin_load() explicitly to bring it into memory. There are options to
  * statically link plugins to an app or even use GStreamer without a plugin
@@ -81,10 +78,6 @@
 /* static variables for segfault handling of plugin loading */
 static char *_gst_plugin_fault_handler_filename = NULL;
 
-#ifndef HAVE_WIN32
-static gboolean _gst_plugin_fault_handler_is_setup = FALSE;
-#endif
-
 /* list of valid licenses.
  * One of these must be specified or the plugin won't be loaded
  * Contact gstreamer-devel@lists.sourceforge.net if your license should be
@@ -111,18 +104,20 @@
 };
 
 static GstPlugin *gst_plugin_register_func (GstPlugin * plugin,
-    const GstPluginDesc * desc);
+    const GstPluginDesc * desc, gpointer user_data);
 static void gst_plugin_desc_copy (GstPluginDesc * dest,
     const GstPluginDesc * src);
 static void gst_plugin_desc_free (GstPluginDesc * desc);
 
+static void gst_plugin_ext_dep_free (GstPluginDep * dep);
 
 G_DEFINE_TYPE (GstPlugin, gst_plugin, GST_TYPE_OBJECT);
 
 static void
 gst_plugin_init (GstPlugin * plugin)
 {
-  /* do nothing, needed because of G_DEFINE_TYPE */
+  plugin->priv =
+      G_TYPE_INSTANCE_GET_PRIVATE (plugin, GST_TYPE_PLUGIN, GstPluginPrivate);
 }
 
 static void
@@ -142,6 +137,14 @@
   g_free (plugin->basename);
   gst_plugin_desc_free (&plugin->desc);
 
+  g_list_foreach (plugin->priv->deps, (GFunc) gst_plugin_ext_dep_free, NULL);
+  g_list_free (plugin->priv->deps);
+  plugin->priv->deps = NULL;
+
+  if (plugin->priv->cache_data) {
+    gst_structure_free (plugin->priv->cache_data);
+  }
+
   G_OBJECT_CLASS (gst_plugin_parent_class)->finalize (object);
 }
 
@@ -149,6 +152,8 @@
 gst_plugin_class_init (GstPluginClass * klass)
 {
   G_OBJECT_CLASS (klass)->finalize = GST_DEBUG_FUNCPTR (gst_plugin_finalize);
+
+  g_type_class_add_private (klass, sizeof (GstPluginPrivate));
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -274,7 +279,96 @@
 
   GST_LOG ("attempting to load static plugin \"%s\" now...", name);
   plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
-  if (gst_plugin_register_func (plugin, &desc) != NULL) {
+  if (gst_plugin_register_func (plugin, &desc, NULL) != NULL) {
+    GST_INFO ("registered static plugin \"%s\"", name);
+    res = gst_default_registry_add_plugin (plugin);
+    GST_INFO ("added static plugin \"%s\", result: %d", name, res);
+  }
+  return res;
+}
+
+/**
+ * gst_plugin_register_static_full:
+ * @major_version: the major version number of the GStreamer core that the
+ *     plugin was compiled for, you can just use GST_VERSION_MAJOR here
+ * @minor_version: the minor version number of the GStreamer core that the
+ *     plugin was compiled for, you can just use GST_VERSION_MINOR here
+ * @name: a unique name of the plugin (ideally prefixed with an application- or
+ *     library-specific namespace prefix in order to avoid name conflicts in
+ *     case a similar plugin with the same name ever gets added to GStreamer)
+ * @description: description of the plugin
+ * @init_full_func: pointer to the init function with user data of this plugin.
+ * @version: version string of the plugin
+ * @license: effective license of plugin. Must be one of the approved licenses
+ *     (see #GstPluginDesc above) or the plugin will not be registered.
+ * @source: source module plugin belongs to
+ * @package: shipped package plugin belongs to
+ * @origin: URL to provider of plugin
+ * @user_data: gpointer to user data
+ *
+ * Registers a static plugin, ie. a plugin which is private to an application
+ * or library and contained within the application or library (as opposed to
+ * being shipped as a separate module file) with a #GstPluginInitFullFunc
+ * which allows user data to be passed to the callback function (useful
+ * for bindings).
+ *
+ * You must make sure that GStreamer has been initialised (with gst_init() or
+ * via gst_init_get_option_group()) before calling this function.
+ *
+ * Returns: TRUE if the plugin was registered correctly, otherwise FALSE.
+ *
+ * Since: 0.10.24
+ *
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_plugin_register_static_full (gint major_version, gint minor_version,
+    const gchar * name, gchar * description,
+    GstPluginInitFullFunc init_full_func, const gchar * version,
+    const gchar * license, const gchar * source, const gchar * package,
+    const gchar * origin, gpointer user_data)
+{
+#ifdef __SYMBIAN32__
+  GstPluginDesc desc;
+  GstPlugin *plugin;
+  gboolean res = FALSE;
+
+  desc.major_version = major_version;
+  desc.minor_version = minor_version;
+  desc.name = name;
+  desc.description = description;
+  desc.plugin_init = (GstPluginInitFunc)init_full_func;
+  desc.version = version;
+  desc.license = license;
+  desc.source = source;
+  desc.package = package;
+  desc.origin = origin;
+#else
+  GstPluginDesc desc = { major_version, minor_version, name, description,
+    (GstPluginInitFunc) init_full_func, version, license, source, package,
+    origin,
+  };
+  GstPlugin *plugin;
+  gboolean res = FALSE;
+#endif
+  g_return_val_if_fail (name != NULL, FALSE);
+  g_return_val_if_fail (description != NULL, FALSE);
+  g_return_val_if_fail (init_full_func != NULL, FALSE);
+  g_return_val_if_fail (version != NULL, FALSE);
+  g_return_val_if_fail (license != NULL, FALSE);
+  g_return_val_if_fail (source != NULL, FALSE);
+  g_return_val_if_fail (package != NULL, FALSE);
+  g_return_val_if_fail (origin != NULL, FALSE);
+
+  /* make sure gst_init() has been called */
+  g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE);
+
+  GST_LOG ("attempting to load static plugin \"%s\" now...", name);
+  plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
+  if (gst_plugin_register_func (plugin, &desc, user_data) != NULL) {
     GST_INFO ("registered static plugin \"%s\"", name);
     res = gst_default_registry_add_plugin (plugin);
     GST_INFO ("added static plugin \"%s\", result: %d", name, res);
@@ -342,7 +436,8 @@
 }
 
 static GstPlugin *
-gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc)
+gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc,
+    gpointer user_data)
 {
   if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) {
     if (GST_CAT_DEFAULT)
@@ -371,11 +466,20 @@
 
   gst_plugin_desc_copy (&plugin->desc, desc);
 
-  if (!((desc->plugin_init) (plugin))) {
-    if (GST_CAT_DEFAULT)
-      GST_WARNING ("plugin \"%s\" failed to initialise", plugin->filename);
-    plugin->module = NULL;
-    return NULL;
+  if (user_data) {
+    if (!(((GstPluginInitFullFunc) (desc->plugin_init)) (plugin, user_data))) {
+      if (GST_CAT_DEFAULT)
+        GST_WARNING ("plugin \"%s\" failed to initialise", plugin->filename);
+      plugin->module = NULL;
+      return NULL;
+    }
+  } else {
+    if (!((desc->plugin_init) (plugin))) {
+      if (GST_CAT_DEFAULT)
+        GST_WARNING ("plugin \"%s\" failed to initialise", plugin->filename);
+      plugin->module = NULL;
+      return NULL;
+    }
   }
 
   if (GST_CAT_DEFAULT)
@@ -386,6 +490,7 @@
 
 #ifdef HAVE_SIGACTION
 static struct sigaction oldaction;
+static gboolean _gst_plugin_fault_handler_is_setup = FALSE;
 
 /*
  * _gst_plugin_fault_handler_restore:
@@ -451,7 +556,7 @@
 
   sigaction (SIGSEGV, &action, &oldaction);
 }
-#else
+#else /* !HAVE_SIGACTION */
 static void
 _gst_plugin_fault_handler_restore (void)
 {
@@ -461,12 +566,17 @@
 _gst_plugin_fault_handler_setup (void)
 {
 }
-#endif
+#endif /* HAVE_SIGACTION */
 
 static void _gst_plugin_fault_handler_setup ();
 
 static GStaticMutex gst_plugin_loading_mutex = G_STATIC_MUTEX_INIT;
 
+#define CHECK_PLUGIN_DESC_FIELD(desc,field,fn)                               \
+  if (G_UNLIKELY ((desc)->field == NULL)) {                                  \
+    GST_ERROR ("GstPluginDesc for '%s' has no %s", fn, G_STRINGIFY (field)); \
+  }
+
 /**
  * gst_plugin_load_file:
  * @filename: the plugin filename to load
@@ -490,6 +600,7 @@
   gpointer ptr;
   struct stat file_status;
   GstRegistry *registry;
+  gboolean new_plugin = TRUE;
    #ifdef __SYMBIAN32__
    GstPluginDesc* (*fn)(void)=NULL;
    void *temp;
@@ -504,11 +615,12 @@
   plugin = gst_registry_lookup (registry, filename);
   if (plugin) {
     if (plugin->module) {
+      /* already loaded */
       g_static_mutex_unlock (&gst_plugin_loading_mutex);
       return plugin;
     } else {
-      gst_object_unref (plugin);
-      plugin = NULL;
+      /* load plugin and update fields */
+      new_plugin = FALSE;
     }
   }
 
@@ -546,13 +658,14 @@
     goto return_error;
   }
 
-  plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
-
+  if (new_plugin) {
+    plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
+    plugin->file_mtime = file_status.st_mtime;
+    plugin->file_size = file_status.st_size;
+    plugin->filename = g_strdup (filename);
+    plugin->basename = g_path_get_basename (filename);
+  }
   plugin->module = module;
-  plugin->filename = g_strdup (filename);
-  plugin->basename = g_path_get_basename (filename);
-  plugin->file_mtime = file_status.st_mtime;
-  plugin->file_size = file_status.st_size;
 
 #ifdef __SYMBIAN32__
    ret = g_module_symbol (module, "1", &ptr);
@@ -575,6 +688,20 @@
    #else
   plugin->orig_desc = (GstPluginDesc *) ptr;
    #endif
+  if (new_plugin) {
+    /* check plugin description: complain about bad values but accept them, to
+     * maintain backwards compatibility (FIXME: 0.11) */
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, name, filename);
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, description, filename);
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, version, filename);
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, license, filename);
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, source, filename);
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, package, filename);
+    CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, origin, filename);
+  } else {
+    /* this is overwritten by gst_plugin_register_func() */
+    g_free (plugin->desc.description);
+  }
 
   GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...",
       plugin, filename);
@@ -586,7 +713,7 @@
   GST_LOG ("Plugin %p for file \"%s\" prepared, registering...",
       plugin, filename);
 
-  if (!gst_plugin_register_func (plugin, plugin->orig_desc)) {
+  if (!gst_plugin_register_func (plugin, plugin->orig_desc, NULL)) {
     /* remove signal handler */
     _gst_plugin_fault_handler_restore ();
     GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename);
@@ -605,8 +732,10 @@
   _gst_plugin_fault_handler_filename = NULL;
   GST_INFO ("plugin \"%s\" loaded", plugin->filename);
 
-  gst_object_ref (plugin);
-  gst_default_registry_add_plugin (plugin);
+  if (new_plugin) {
+    gst_object_ref (plugin);
+    gst_default_registry_add_plugin (plugin);
+  }
 
   g_static_mutex_unlock (&gst_plugin_loading_mutex);
   return plugin;
@@ -846,6 +975,57 @@
   return (plugin->module != NULL || plugin->filename == NULL);
 }
 
+/**
+ * gst_plugin_get_cache_data:
+ * @plugin: a plugin
+ *
+ * Gets the plugin specific data cache. If it is %NULL there is no cached data
+ * stored. This is the case when the registry is getting rebuild.
+ *
+ * Returns: The cached data as a #GstStructure or %NULL.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+G_CONST_RETURN GstStructure *
+gst_plugin_get_cache_data (GstPlugin * plugin)
+{
+  g_return_val_if_fail (GST_IS_PLUGIN (plugin), NULL);
+
+  return plugin->priv->cache_data;
+}
+
+/**
+ * gst_plugin_set_cache_data:
+ * @plugin: a plugin
+ * @cache_data: a structure containing the data to cache
+ *
+ * Adds plugin specific data to cache. Passes the ownership of the structure to
+ * the @plugin.
+ *
+ * The cache is flushed every time the registry is rebuild.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_plugin_set_cache_data (GstPlugin * plugin, GstStructure * cache_data)
+{
+  g_return_if_fail (GST_IS_PLUGIN (plugin));
+  g_return_if_fail (GST_IS_STRUCTURE (cache_data));
+
+  if (plugin->priv->cache_data) {
+    gst_structure_free (plugin->priv->cache_data);
+  }
+  plugin->priv->cache_data = cache_data;
+}
+
 #if 0
 /**
  * gst_plugin_feature_list:
@@ -1132,3 +1312,536 @@
   }
   g_list_free (list);
 }
+
+/* ===== plugin dependencies ===== */
+
+/* Scenarios:
+ * ENV + xyz     where ENV can contain multiple values separated by SEPARATOR
+ *               xyz may be "" (if ENV contains path to file rather than dir)
+ * ENV + *xyz   same as above, but xyz acts as suffix filter
+ * ENV + xyz*   same as above, but xyz acts as prefix filter (is this needed?)
+ * ENV + *xyz*  same as above, but xyz acts as strstr filter (is this needed?)
+ * 
+ * same as above, with additional paths hard-coded at compile-time:
+ *   - only check paths + ... if ENV is not set or yields not paths
+ *   - always check paths + ... in addition to ENV
+ *
+ * When user specifies set of environment variables, he/she may also use e.g.
+ * "HOME/.mystuff/plugins", and we'll expand the content of $HOME with the
+ * remainder 
+ */
+
+/* we store in registry:
+ *  sets of:
+ *   { 
+ *     - environment variables (array of strings)
+ *     - last hash of env variable contents (uint) (so we can avoid doing stats
+ *       if one of the env vars has changed; premature optimisation galore)
+ *     - hard-coded paths (array of strings)
+ *     - xyz filename/suffix/prefix strings (array of strings)
+ *     - flags (int)
+ *     - last hash of file/dir stats (int)
+ *   }
+ *   (= struct GstPluginDep)
+ */
+
+static guint
+gst_plugin_ext_dep_get_env_vars_hash (GstPlugin * plugin, GstPluginDep * dep)
+{
+  gchar **e;
+  guint hash;
+
+  /* there's no deeper logic to what we do here; all we want to know (when
+   * checking if the plugin needs to be rescanned) is whether the content of
+   * one of the environment variables in the list is different from when it
+   * was last scanned */
+  hash = 0;
+  for (e = dep->env_vars; e != NULL && *e != NULL; ++e) {
+    const gchar *val;
+    gchar env_var[256];
+
+    /* order matters: "val",NULL needs to yield a different hash than
+     * NULL,"val", so do a shift here whether the var is set or not */
+    hash = hash << 5;
+
+    /* want environment variable at beginning of string */
+    if (!g_ascii_isalnum (**e)) {
+      GST_WARNING_OBJECT (plugin, "string prefix is not a valid environment "
+          "variable string: %s", *e);
+      continue;
+    }
+
+    /* user is allowed to specify e.g. "HOME/.pitivi/plugins" */
+    g_strlcpy (env_var, *e, sizeof (env_var));
+    g_strdelimit (env_var, "/\\", '\0');
+
+    if ((val = g_getenv (env_var)))
+      hash += g_str_hash (val);
+  }
+
+  return hash;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+_priv_plugin_deps_env_vars_changed (GstPlugin * plugin)
+{
+  GList *l;
+
+  for (l = plugin->priv->deps; l != NULL; l = l->next) {
+    GstPluginDep *dep = l->data;
+
+    if (dep->env_hash != gst_plugin_ext_dep_get_env_vars_hash (plugin, dep))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+static GList *
+gst_plugin_ext_dep_extract_env_vars_paths (GstPlugin * plugin,
+    GstPluginDep * dep)
+{
+  gchar **evars;
+  GList *paths = NULL;
+
+  for (evars = dep->env_vars; evars != NULL && *evars != NULL; ++evars) {
+    const gchar *e;
+    gchar **components;
+
+    /* want environment variable at beginning of string */
+    if (!g_ascii_isalnum (**evars)) {
+      GST_WARNING_OBJECT (plugin, "string prefix is not a valid environment "
+          "variable string: %s", *evars);
+      continue;
+    }
+
+    /* user is allowed to specify e.g. "HOME/.pitivi/plugins", which we want to
+     * split into the env_var name component and the path component */
+    components = g_strsplit_set (*evars, "/\\", 2);
+    g_assert (components != NULL);
+
+    e = g_getenv (components[0]);
+    GST_LOG_OBJECT (plugin, "expanding %s = '%s' (path suffix: %s)",
+        components[0], GST_STR_NULL (e), GST_STR_NULL (components[1]));
+
+    if (components[1] != NULL) {
+      g_strdelimit (components[1], "/\\", G_DIR_SEPARATOR);
+    }
+
+    if (e != NULL && *e != '\0') {
+      gchar **arr;
+      guint i;
+
+      arr = g_strsplit (e, G_SEARCHPATH_SEPARATOR_S, -1);
+
+      for (i = 0; arr != NULL && arr[i] != NULL; ++i) {
+        gchar *full_path;
+
+        if (!g_path_is_absolute (arr[i])) {
+          GST_INFO_OBJECT (plugin, "ignoring environment variable content '%s'"
+              ": either not an absolute path or not a path at all", arr[i]);
+          continue;
+        }
+
+        if (components[1] != NULL) {
+          full_path = g_build_filename (arr[i], components[1], NULL);
+        } else {
+          full_path = g_strdup (arr[i]);
+        }
+
+        if (!g_list_find_custom (paths, full_path, (GCompareFunc) strcmp)) {
+          GST_LOG_OBJECT (plugin, "path: '%s'", full_path);
+          paths = g_list_prepend (paths, full_path);
+          full_path = NULL;
+        } else {
+          GST_LOG_OBJECT (plugin, "path: '%s' (duplicate,ignoring)", full_path);
+          g_free (full_path);
+        }
+      }
+
+      g_strfreev (arr);
+    }
+
+    g_strfreev (components);
+  }
+
+  GST_LOG_OBJECT (plugin, "Extracted %d paths from environment",
+      g_list_length (paths));
+
+  return paths;
+}
+
+static guint
+gst_plugin_ext_dep_get_hash_from_stat_entry (struct stat *s)
+{
+  if (!(s->st_mode & (S_IFDIR | S_IFREG)))
+    return (guint) - 1;
+
+  /* completely random formula */
+  return ((s->st_size << 3) + (s->st_mtime << 5)) ^ s->st_ctime;
+}
+
+static gboolean
+gst_plugin_ext_dep_direntry_matches (GstPlugin * plugin, const gchar * entry,
+    const gchar ** filenames, GstPluginDependencyFlags flags)
+{
+  /* no filenames specified, match all entries for now (could probably
+   * optimise by just taking the dir stat hash or so) */
+  if (filenames == NULL || *filenames == NULL || **filenames == '\0')
+    return TRUE;
+
+  while (*filenames != NULL) {
+    /* suffix match? */
+    if (((flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX)) &&
+        g_str_has_suffix (entry, *filenames)) {
+      return TRUE;
+      /* else it's an exact match that's needed */
+    } else if (strcmp (entry, *filenames) == 0) {
+      return TRUE;
+    }
+    GST_LOG ("%s does not match %s, flags=0x%04x", entry, *filenames, flags);
+    ++filenames;
+  }
+  return FALSE;
+}
+
+static guint
+gst_plugin_ext_dep_scan_dir_and_match_names (GstPlugin * plugin,
+    const gchar * path, const gchar ** filenames,
+    GstPluginDependencyFlags flags, int depth)
+{
+  const gchar *entry;
+  gboolean recurse_dirs;
+  GError *err = NULL;
+  GDir *dir;
+  guint hash = 0;
+
+  recurse_dirs = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE);
+
+  dir = g_dir_open (path, 0, &err);
+  if (dir == NULL) {
+    GST_DEBUG_OBJECT (plugin, "g_dir_open(%s) failed: %s", path, err->message);
+    g_error_free (err);
+    return (guint) - 1;
+  }
+
+  /* FIXME: we're assuming here that we always get the directory entries in
+   * the same order, and not in a random order */
+  while ((entry = g_dir_read_name (dir))) {
+    gboolean have_match;
+    struct stat s;
+    gchar *full_path;
+    guint fhash;
+
+    have_match =
+        gst_plugin_ext_dep_direntry_matches (plugin, entry, filenames, flags);
+
+    /* avoid the stat if possible */
+    if (!have_match && !recurse_dirs)
+      continue;
+
+    full_path = g_build_filename (path, entry, NULL);
+    if (g_stat (full_path, &s) < 0) {
+      fhash = (guint) - 1;
+      GST_LOG_OBJECT (plugin, "stat: %s (error: %s)", full_path,
+          g_strerror (errno));
+    } else if (have_match) {
+      fhash = gst_plugin_ext_dep_get_hash_from_stat_entry (&s);
+      GST_LOG_OBJECT (plugin, "stat: %s (result: %u)", full_path, fhash);
+    } else if ((s.st_mode & (S_IFDIR))) {
+      fhash = gst_plugin_ext_dep_scan_dir_and_match_names (plugin, full_path,
+          filenames, flags, depth + 1);
+    } else {
+      /* it's not a name match, we want to recurse, but it's not a directory */
+      g_free (full_path);
+      continue;
+    }
+
+    hash = (hash + fhash) << 1;
+    g_free (full_path);
+  }
+
+  g_dir_close (dir);
+  return hash;
+}
+
+static guint
+gst_plugin_ext_dep_scan_path_with_filenames (GstPlugin * plugin,
+    const gchar * path, const gchar ** filenames,
+    GstPluginDependencyFlags flags)
+{
+  const gchar *empty_filenames[] = { "", NULL };
+  gboolean recurse_into_dirs, partial_names;
+  guint i, hash = 0;
+
+  /* to avoid special-casing below (FIXME?) */
+  if (filenames == NULL || *filenames == NULL)
+    filenames = empty_filenames;
+
+  recurse_into_dirs = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE);
+  partial_names = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX);
+
+  /* if we can construct the exact paths to check with the data we have, just
+   * stat them one by one; this is more efficient than opening the directory
+   * and going through each entry to see if it matches one of our filenames. */
+  if (!recurse_into_dirs && !partial_names) {
+    for (i = 0; filenames[i] != NULL; ++i) {
+      struct stat s;
+      gchar *full_path;
+      guint fhash;
+
+      full_path = g_build_filename (path, filenames[i], NULL);
+      if (g_stat (full_path, &s) < 0) {
+        fhash = (guint) - 1;
+        GST_LOG_OBJECT (plugin, "stat: %s (error: %s)", full_path,
+            g_strerror (errno));
+      } else {
+        fhash = gst_plugin_ext_dep_get_hash_from_stat_entry (&s);
+        GST_LOG_OBJECT (plugin, "stat: %s (result: %08x)", full_path, fhash);
+      }
+      hash = (hash + fhash) << 1;
+      g_free (full_path);
+    }
+  } else {
+    hash = gst_plugin_ext_dep_scan_dir_and_match_names (plugin, path,
+        filenames, flags, 0);
+  }
+
+  return hash;
+}
+
+static guint
+gst_plugin_ext_dep_get_stat_hash (GstPlugin * plugin, GstPluginDep * dep)
+{
+  gboolean paths_are_default_only;
+  GList *scan_paths;
+  guint scan_hash = 0;
+
+  GST_LOG_OBJECT (plugin, "start");
+
+  paths_are_default_only =
+      dep->flags & GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY;
+
+  scan_paths = gst_plugin_ext_dep_extract_env_vars_paths (plugin, dep);
+
+  if (scan_paths == NULL || !paths_are_default_only) {
+    gchar **paths;
+
+    for (paths = dep->paths; paths != NULL && *paths != NULL; ++paths) {
+      const gchar *path = *paths;
+
+      if (!g_list_find_custom (scan_paths, path, (GCompareFunc) strcmp)) {
+        GST_LOG_OBJECT (plugin, "path: '%s'", path);
+        scan_paths = g_list_prepend (scan_paths, g_strdup (path));
+      } else {
+        GST_LOG_OBJECT (plugin, "path: '%s' (duplicate, ignoring)", path);
+      }
+    }
+  }
+
+  /* not that the order really matters, but it makes debugging easier */
+  scan_paths = g_list_reverse (scan_paths);
+
+  while (scan_paths != NULL) {
+    const gchar *path = scan_paths->data;
+
+    scan_hash += gst_plugin_ext_dep_scan_path_with_filenames (plugin, path,
+        (const gchar **) dep->names, dep->flags);
+    scan_hash = scan_hash << 1;
+
+    g_free (scan_paths->data);
+    scan_paths = g_list_delete_link (scan_paths, scan_paths);
+  }
+
+  GST_LOG_OBJECT (plugin, "done, scan_hash: %08x", scan_hash);
+  return scan_hash;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+_priv_plugin_deps_files_changed (GstPlugin * plugin)
+{
+  GList *l;
+
+  for (l = plugin->priv->deps; l != NULL; l = l->next) {
+    GstPluginDep *dep = l->data;
+
+    if (dep->stat_hash != gst_plugin_ext_dep_get_stat_hash (plugin, dep))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+static void
+gst_plugin_ext_dep_free (GstPluginDep * dep)
+{
+  g_strfreev (dep->env_vars);
+  g_strfreev (dep->paths);
+  g_strfreev (dep->names);
+  g_free (dep);
+}
+
+static gboolean
+gst_plugin_ext_dep_strv_equal (gchar ** arr1, gchar ** arr2)
+{
+  if (arr1 == arr2)
+    return TRUE;
+  if (arr1 == NULL || arr2 == NULL)
+    return FALSE;
+  for (; *arr1 != NULL && *arr2 != NULL; ++arr1, ++arr2) {
+    if (strcmp (*arr1, *arr2) != 0)
+      return FALSE;
+  }
+  return (*arr1 == *arr2);
+}
+
+static gboolean
+gst_plugin_ext_dep_equals (GstPluginDep * dep, const gchar ** env_vars,
+    const gchar ** paths, const gchar ** names, GstPluginDependencyFlags flags)
+{
+  if (dep->flags != flags)
+    return FALSE;
+
+  return gst_plugin_ext_dep_strv_equal (dep->env_vars, (gchar **) env_vars) &&
+      gst_plugin_ext_dep_strv_equal (dep->paths, (gchar **) paths) &&
+      gst_plugin_ext_dep_strv_equal (dep->names, (gchar **) names);
+}
+
+/**
+ * gst_plugin_add_dependency:
+ * @plugin: a #GstPlugin
+ * @env_vars: NULL-terminated array of environent variables affecting the
+ *     feature set of the plugin (e.g. an environment variable containing
+ *     paths where to look for additional modules/plugins of a library),
+ *     or NULL. Environment variable names may be followed by a path component
+ *      which will be added to the content of the environment variable, e.g.
+ *      "HOME/.mystuff/plugins".
+ * @paths: NULL-terminated array of directories/paths where dependent files
+ *     may be.
+ * @names: NULL-terminated array of file names (or file name suffixes,
+ *     depending on @flags) to be used in combination with the paths from
+ *     @paths and/or the paths extracted from the environment variables in
+ *     @env_vars, or NULL.
+ * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE
+ *
+ * Make GStreamer aware of external dependencies which affect the feature
+ * set of this plugin (ie. the elements or typefinders associated with it).
+ *
+ * GStreamer will re-inspect plugins with external dependencies whenever any
+ * of the external dependencies change. This is useful for plugins which wrap
+ * other plugin systems, e.g. a plugin which wraps a plugin-based visualisation
+ * library and makes visualisations available as GStreamer elements, or a
+ * codec loader which exposes elements and/or caps dependent on what external
+ * codec libraries are currently installed.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_plugin_add_dependency (GstPlugin * plugin, const gchar ** env_vars,
+    const gchar ** paths, const gchar ** names, GstPluginDependencyFlags flags)
+{
+  GstPluginDep *dep;
+  GList *l;
+
+  g_return_if_fail (GST_IS_PLUGIN (plugin));
+  g_return_if_fail (env_vars != NULL || paths != NULL);
+
+  for (l = plugin->priv->deps; l != NULL; l = l->next) {
+    if (gst_plugin_ext_dep_equals (l->data, env_vars, paths, names, flags)) {
+      GST_LOG_OBJECT (plugin, "dependency already registered");
+      return;
+    }
+  }
+
+  dep = g_new0 (GstPluginDep, 1);
+
+  dep->env_vars = g_strdupv ((gchar **) env_vars);
+  dep->paths = g_strdupv ((gchar **) paths);
+  dep->names = g_strdupv ((gchar **) names);
+  dep->flags = flags;
+
+  dep->env_hash = gst_plugin_ext_dep_get_env_vars_hash (plugin, dep);
+  dep->stat_hash = gst_plugin_ext_dep_get_stat_hash (plugin, dep);
+
+  plugin->priv->deps = g_list_append (plugin->priv->deps, dep);
+
+  GST_DEBUG_OBJECT (plugin, "added dependency:");
+  for (; env_vars != NULL && *env_vars != NULL; ++env_vars)
+    GST_DEBUG_OBJECT (plugin, " evar: %s", *env_vars);
+  for (; paths != NULL && *paths != NULL; ++paths)
+    GST_DEBUG_OBJECT (plugin, " path: %s", *paths);
+  for (; names != NULL && *names != NULL; ++names)
+    GST_DEBUG_OBJECT (plugin, " name: %s", *names);
+}
+
+/**
+ * gst_plugin_add_dependency_simple:
+ * @plugin: the #GstPlugin
+ * @env_vars: one or more environent variables (separated by ':', ';' or ','),
+ *      or NULL. Environment variable names may be followed by a path component
+ *      which will be added to the content of the environment variable, e.g.
+ *      "HOME/.mystuff/plugins:MYSTUFF_PLUGINS_PATH"
+ * @paths: one ore more directory paths (separated by ':' or ';' or ','),
+ *      or NULL. Example: "/usr/lib/mystuff/plugins"
+ * @names: one or more file names or file name suffixes (separated by commas),
+ *   or NULL
+ * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE
+ *
+ * Make GStreamer aware of external dependencies which affect the feature
+ * set of this plugin (ie. the elements or typefinders associated with it).
+ *
+ * GStreamer will re-inspect plugins with external dependencies whenever any
+ * of the external dependencies change. This is useful for plugins which wrap
+ * other plugin systems, e.g. a plugin which wraps a plugin-based visualisation
+ * library and makes visualisations available as GStreamer elements, or a
+ * codec loader which exposes elements and/or caps dependent on what external
+ * codec libraries are currently installed.
+ *
+ * Convenience wrapper function for gst_plugin_add_dependency() which
+ * takes simple strings as arguments instead of string arrays, with multiple
+ * arguments separated by predefined delimiters (see above).
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_plugin_add_dependency_simple (GstPlugin * plugin,
+    const gchar * env_vars, const gchar * paths, const gchar * names,
+    GstPluginDependencyFlags flags)
+{
+  gchar **a_evars = NULL;
+  gchar **a_paths = NULL;
+  gchar **a_names = NULL;
+
+  if (env_vars)
+    a_evars = g_strsplit_set (env_vars, ":;,", -1);
+  if (paths)
+    a_paths = g_strsplit_set (paths, ":;,", -1);
+  if (names)
+    a_names = g_strsplit_set (names, ",", -1);
+
+  gst_plugin_add_dependency (plugin, (const gchar **) a_evars,
+      (const gchar **) a_paths, (const gchar **) a_names, flags);
+
+  if (a_evars)
+    g_strfreev (a_evars);
+  if (a_paths)
+    g_strfreev (a_paths);
+  if (a_names)
+    g_strfreev (a_names);
+}
--- a/gstreamer_core/gst/gstplugin.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstplugin.h	Fri Apr 16 15:15:52 2010 +0300
@@ -32,11 +32,13 @@
 #include <gmodule.h>
 #include <gst/gstobject.h>
 #include <gst/gstmacros.h>
+#include <gst/gststructure.h>
 
 G_BEGIN_DECLS
 
 typedef struct _GstPlugin GstPlugin;
 typedef struct _GstPluginClass GstPluginClass;
+typedef struct _GstPluginPrivate GstPluginPrivate;
 typedef struct _GstPluginDesc GstPluginDesc;
 
 /**
@@ -80,6 +82,27 @@
 } GstPluginFlags;
 
 /**
+ * GstPluginDependencyFlags:
+ * @GST_PLUGIN_DEPENDENCY_FLAG_NONE : no special flags
+ * @GST_PLUGIN_DEPENDENCY_FLAG_RECURSE : recurse into subdirectories
+ * @GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY : use paths
+ *         argument only if none of the environment variables is set
+ * @GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX : interpret
+ *         filename argument as filter suffix and check all matching files in
+ *         the directory
+ *
+ * Flags used in connection with gst_plugin_add_dependency().
+ *
+ * Since: 0.10.22
+ */
+typedef enum {
+  GST_PLUGIN_DEPENDENCY_FLAG_NONE = 0,
+  GST_PLUGIN_DEPENDENCY_FLAG_RECURSE = (1 << 0),
+  GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY = (1 << 1),
+  GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX = (1 << 2)
+} GstPluginDependencyFlags;
+
+/**
  * GstPluginInitFunc:
  * @plugin: The plugin object that can be used to register #GstPluginFeatures for this plugin.
  *
@@ -92,6 +115,23 @@
 typedef gboolean (*GstPluginInitFunc) (GstPlugin *plugin);
 
 /**
+ * GstPluginInitFullFunc:
+ * @plugin: The plugin object that can be used to register #GstPluginFeatures for this plugin.
+ * @user_data: The user data.
+ *
+ * A plugin should provide a pointer to a function of either #GstPluginInitFunc
+ * or this type in the plugin_desc struct.
+ * The function will be called by the loader at startup. This version allows
+ * user data to be passed to init function (useful for bindings).
+ *
+ * Returns: %TRUE if plugin initialised successfully
+ *
+ * Since: 0.10.24
+ *
+ */
+typedef gboolean (*GstPluginInitFullFunc) (GstPlugin *plugin, gpointer user_data);
+
+/**
  * GstPluginDesc:
  * @major_version: the major version number of core that plugin was compiled for
  * @minor_version: the minor version number of core that plugin was compiled for
@@ -160,7 +200,8 @@
   gboolean      registered;     /* TRUE when the registry has seen a filename
                                  * that matches the plugin's basename */
 
-  gpointer _gst_reserved[GST_PADDING];
+  GstPluginPrivate *priv;
+  gpointer _gst_reserved[GST_PADDING - 1];
 };
 
 struct _GstPluginClass {
@@ -184,7 +225,9 @@
  *
  * This macro needs to be used to define the entry point and meta data of a
  * plugin. One would use this macro to export a plugin, so that it can be used
- * by other applications
+ * by other applications.
+ *
+ * The macro uses a define named PACKAGE for the #GstPluginDesc,source field.
  */
 #define GST_PLUGIN_DEFINE(major,minor,name,description,init,version,license,package,origin)	\
 GST_PLUGIN_EXPORT GstPluginDesc gst_plugin_desc = {	\
@@ -217,9 +260,12 @@
  * local plugin. One would use this macro to define a local plugin that can only
  * be used by the own application.
  *
+ * The macro uses a define named PACKAGE for the #GstPluginDesc.source field.
+ *
  * Deprecated: Use gst_plugin_register_static() instead. This macro was
  * deprecated because it uses constructors, which is a compiler feature not
  * available on all compilers.
+ *
  */
 /* We don't have deprecation guards here on purpose, it's enough to have
  * deprecation guards around _gst_plugin_register_static(), and will result in
@@ -292,6 +338,22 @@
 #endif
 
 
+gboolean		gst_plugin_register_static_full	(gint major_version,
+                                                         gint minor_version,
+                                                         const gchar *name,
+                                                         gchar *description,
+                                                         GstPluginInitFullFunc init_full_func,
+                                                         const gchar *version,
+                                                         const gchar *license,
+                                                         const gchar *source,
+                                                         const gchar *package,
+                                                         const gchar *origin,
+                                                         gpointer user_data);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 G_CONST_RETURN gchar*	gst_plugin_get_name		(GstPlugin *plugin);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -332,6 +394,17 @@
 IMPORT_C
 #endif
 
+G_CONST_RETURN GstStructure*	gst_plugin_get_cache_data	(GstPlugin * plugin);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_plugin_set_cache_data	(GstPlugin * plugin, GstStructure *cache_data);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 GModule *		gst_plugin_get_module		(GstPlugin *plugin);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -366,6 +439,26 @@
 #endif
 
 
+void                    gst_plugin_add_dependency (GstPlugin    * plugin,
+                                                   const gchar ** env_vars,
+                                                   const gchar ** paths,
+                                                   const gchar ** names,
+                                                   GstPluginDependencyFlags flags);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void                    gst_plugin_add_dependency_simple (GstPlugin   * plugin,
+                                                          const gchar * env_vars,
+                                                          const gchar * paths,
+                                                          const gchar * names,
+                                                          GstPluginDependencyFlags flags);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 void gst_plugin_list_free (GList *list);
 
 G_END_DECLS
--- a/gstreamer_core/gst/gstpluginfeature.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpluginfeature.c	Fri Apr 16 15:15:52 2010 +0300
@@ -81,14 +81,14 @@
  * unaffected; use the return value instead.
  *
  * Normally this function is used like this:
- *
- * <programlisting>
+ * |[
  * GstPluginFeature *loaded_feature;
+ * 
  * loaded_feature = gst_plugin_feature_load (feature);
  * // presumably, we're no longer interested in the potentially-unloaded feature
  * gst_object_unref (feature);
  * feature = loaded_feature;
- * </programlisting>
+ * ]|
  *
  * Returns: A reference to the loaded feature, or NULL on error.
  */
@@ -196,7 +196,7 @@
   } else {
     feature->name = g_strdup (name);
   }
-  gst_object_set_name (GST_OBJECT (feature), feature->name);
+  gst_object_set_name (GST_OBJECT_CAST (feature), feature->name);
 }
 
 /**
--- a/gstreamer_core/gst/gstpoll.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpoll.c	Fri Apr 16 15:15:52 2010 +0300
@@ -68,6 +68,8 @@
 #include <sys/time.h>
 #endif
 
+#include "gst_private.h"
+
 #include <sys/types.h>
 
 #ifdef HAVE_UNISTD_H
@@ -89,8 +91,6 @@
 /* OS/X needs this because of bad headers */
 #include <string.h>
 
-#include "gst_private.h"
-
 #include "gstpoll.h"
 
 #ifdef __SYMBIAN32__
@@ -112,15 +112,25 @@
 /* the poll/select call is also performed on a control socket, that way
  * we can send special commands to control it
  */
-#define SEND_COMMAND(set, command)                   \
+/* FIXME: Shouldn't we check or return the return value
+ * of write()?
+ */
+#define SEND_COMMAND(set, command, result)           \
 G_STMT_START {                                       \
   unsigned char c = command;                         \
-  write (set->control_write_fd.fd, &c, 1);           \
+  result = write (set->control_write_fd.fd, &c, 1);  \
+  if (result > 0)                                    \
+    set->control_pending++;                          \
 } G_STMT_END
 
-#define READ_COMMAND(set, command, res)              \
-G_STMT_START {                                       \
-  res = read (set->control_read_fd.fd, &command, 1); \
+#define READ_COMMAND(set, command, res)                \
+G_STMT_START {                                         \
+  if (set->control_pending > 0) {                      \
+    res = read (set->control_read_fd.fd, &command, 1); \
+    if (res == 1)                                      \
+      set->control_pending--;                          \
+  } else                                               \
+    res = 0;                                           \
 } G_STMT_END
 
 #define GST_POLL_CMD_WAKEUP  'W'        /* restart the poll/select call */
@@ -160,7 +170,6 @@
   GstPollFD control_write_fd;
 #else
   GArray *active_fds_ignored;
-
   GArray *events;
   GArray *active_events;
 
@@ -169,8 +178,10 @@
 
   gboolean controllable;
   gboolean new_controllable;
-  gboolean waiting;
+  guint waiting;
+  guint control_pending;
   gboolean flushing;
+  gboolean timer;
 };
 
 static gint
@@ -298,7 +309,7 @@
   FD_ZERO (writefds);
 
   g_mutex_lock (set->lock);
-  
+
   for (i = 0; i < set->active_fds->len; i++) {
 #ifndef __SYMBIAN32__ 
     struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, i);
@@ -316,8 +327,7 @@
     }
   }
 
-    g_mutex_unlock (set->lock);
-
+  g_mutex_unlock (set->lock);
 
   return max_fd;
 }
@@ -502,7 +512,7 @@
 {
   GstPoll *nset;
 
-  nset = g_new0 (GstPoll, 1);
+  nset = g_slice_new0 (GstPoll);
   nset->lock = g_mutex_new ();
 #ifndef G_OS_WIN32
   nset->mode = GST_POLL_MODE_AUTO;
@@ -537,6 +547,40 @@
 }
 
 /**
+ * gst_poll_new_timer:
+ *
+ * Create a new poll object that can be used for scheduling cancellable
+ * timeouts.
+ *
+ * A timeout is performed with gst_poll_wait(). Multiple timeouts can be
+ * performed from different threads. 
+ *
+ * Returns: a new #GstPoll, or %NULL in case of an error. Free with
+ * gst_poll_free().
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+ 
+GstPoll *
+gst_poll_new_timer (void)
+{
+  GstPoll *poll;
+
+  /* make a new controllable poll set */
+  if (!(poll = gst_poll_new (TRUE)))
+    goto done;
+
+  /* we are a timer */
+  poll->timer = TRUE;
+
+done:
+  return poll;
+}
+
+/**
  * gst_poll_free:
  * @set: a file descriptor set.
  *
@@ -575,7 +619,7 @@
   g_array_free (set->active_fds, TRUE);
   g_array_free (set->fds, TRUE);
   g_mutex_free (set->lock);
-  g_free (set);
+  g_slice_free (GstPoll, set);
 }
 
 /**
@@ -756,7 +800,8 @@
     else
       pfd->events &= ~POLLOUT;
 #else
-    gst_poll_update_winsock_event_mask (set, idx, FD_WRITE, active);
+    gst_poll_update_winsock_event_mask (set, idx, FD_WRITE | FD_CONNECT,
+        active);
 #endif
   }
 
@@ -812,7 +857,9 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
- gboolean gst_poll_fd_ctl_read (GstPoll * set, GstPollFD * fd, gboolean active)
+
+gboolean
+gst_poll_fd_ctl_read (GstPoll * set, GstPollFD * fd, gboolean active)
 {
   gboolean ret;
 
@@ -849,7 +896,8 @@
 EXPORT_C
 #endif
 
- void gst_poll_fd_ignored (GstPoll * set, GstPollFD * fd)
+void
+gst_poll_fd_ignored (GstPoll * set, GstPollFD * fd)
 {
 #ifdef G_OS_WIN32
   gint idx;
@@ -886,7 +934,8 @@
 EXPORT_C
 #endif
 
- gboolean gst_poll_fd_has_closed (const GstPoll * set, GstPollFD * fd)
+gboolean
+gst_poll_fd_has_closed (const GstPoll * set, GstPollFD * fd)
 {
   gboolean res = FALSE;
   gint idx;
@@ -959,7 +1008,8 @@
     res = (wfd->events.iErrorCode[FD_CLOSE_BIT] != 0) ||
         (wfd->events.iErrorCode[FD_READ_BIT] != 0) ||
         (wfd->events.iErrorCode[FD_WRITE_BIT] != 0) ||
-        (wfd->events.iErrorCode[FD_ACCEPT_BIT] != 0);
+        (wfd->events.iErrorCode[FD_ACCEPT_BIT] != 0) ||
+        (wfd->events.iErrorCode[FD_CONNECT_BIT] != 0);
 #endif
   }
 
@@ -1006,7 +1056,8 @@
 EXPORT_C
 #endif
 
-gboolean gst_poll_fd_can_read (const GstPoll * set, GstPollFD * fd)
+gboolean
+gst_poll_fd_can_read (const GstPoll * set, GstPollFD * fd)
 {
   gboolean res = FALSE;
 
@@ -1038,7 +1089,8 @@
 EXPORT_C
 #endif
 
-gboolean gst_poll_fd_can_write (const GstPoll * set, GstPollFD * fd)
+gboolean
+gst_poll_fd_can_write (const GstPoll * set, GstPollFD * fd)
 {
   gboolean res = FALSE;
   gint idx;
@@ -1113,8 +1165,13 @@
  * Wait for activity on the file descriptors in @set. This function waits up to
  * the specified @timeout.  A timeout of #GST_CLOCK_TIME_NONE waits forever.
  *
- * When this function is called from multiple threads, -1 will be returned with
- * errno set to EPERM.
+ * For #GstPoll objects created with gst_poll_new(), this function can only be
+ * called from a single thread at a time.  If called from multiple threads,
+ * -1 will be returned with errno set to EPERM.
+ *
+ * This is not true for timer #GstPoll objects created with
+ * gst_poll_new_timer(), where it is allowed to have multiple threads waiting
+ * simultaneously.
  *
  * Returns: The number of #GstPollFD in @set that have activity or 0 when no
  * activity was detected after @timeout. If an error occurs, -1 is returned
@@ -1126,24 +1183,26 @@
 EXPORT_C
 #endif
 
-gint gst_poll_wait (GstPoll * set, GstClockTime timeout)
+gint
+gst_poll_wait (GstPoll * set, GstClockTime timeout)
 {
   gboolean restarting;
-  int res = -1;
+  int res;
 
   g_return_val_if_fail (set != NULL, -1);
 
   g_mutex_lock (set->lock);
 
-  /* we cannot wait from multiple threads */
-  if (set->waiting)
+  /* we cannot wait from multiple threads unless we are a timer */
+  if (G_UNLIKELY (set->waiting > 0 && !set->timer))
     goto already_waiting;
 
   /* flushing, exit immediatly */
-  if (set->flushing)
+  if (G_UNLIKELY (set->flushing))
     goto flushing;
 
-  set->waiting = TRUE;
+  /* add one more waiter */
+  set->waiting++;
 
   do {
     GstPollMode mode;
@@ -1240,7 +1299,7 @@
           } else {
             tvptr = NULL;
           }
-//temporary  fix for multifdsink  
+	  
           FD_ZERO(&excepfds);
          
         if( max_fd != -1)
@@ -1332,20 +1391,21 @@
 
     g_mutex_lock (set->lock);
 
-    gst_poll_check_ctrl_commands (set, res, &restarting);
+    if (!set->timer)
+      gst_poll_check_ctrl_commands (set, res, &restarting);
 
     /* update the controllable state if needed */
     set->controllable = set->new_controllable;
 
-    if (set->flushing) {
+    if (G_UNLIKELY (set->flushing)) {
       /* we got woken up and we are flushing, we need to stop */
       errno = EBUSY;
       res = -1;
       break;
     }
-  } while (restarting);
+  } while (G_UNLIKELY (restarting));
 
-  set->waiting = FALSE;
+  set->waiting--;
 
   g_mutex_unlock (set->lock);
 
@@ -1367,6 +1427,7 @@
 #ifdef G_OS_WIN32
 winsock_error:
   {
+    set->waiting--;
     g_mutex_unlock (set->lock);
     return -1;
   }
@@ -1390,7 +1451,8 @@
 EXPORT_C
 #endif
 
-gboolean gst_poll_set_controllable (GstPoll * set, gboolean controllable)
+gboolean
+gst_poll_set_controllable (GstPoll * set, gboolean controllable)
 {
   g_return_val_if_fail (set != NULL, FALSE);
 
@@ -1403,6 +1465,7 @@
     if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0)
       goto no_socket_pair;
 */
+    pipe(control_sock);
     fcntl (control_sock[0], F_SETFL, O_NONBLOCK);
     fcntl (control_sock[1], F_SETFL, O_NONBLOCK);
 
@@ -1418,7 +1481,7 @@
 
   /* delay the change of the controllable state if we are waiting */
   set->new_controllable = controllable;
-  if (!set->waiting)
+  if (set->waiting == 0)
     set->controllable = controllable;
 
   g_mutex_unlock (set->lock);
@@ -1450,17 +1513,20 @@
 EXPORT_C
 #endif
 
-void gst_poll_restart (GstPoll * set)
+void
+gst_poll_restart (GstPoll * set)
 {
   g_return_if_fail (set != NULL);
 
   g_mutex_lock (set->lock);
 
-  if (set->controllable && set->waiting) {
+  if (set->controllable && set->waiting > 0) {
 #ifndef G_OS_WIN32
+    gint result;
+
     /* if we are waiting, we can send the command, else we do not have to
      * bother, future calls will automatically pick up the new fdset */
-    SEND_COMMAND (set, GST_POLL_CMD_WAKEUP);
+    SEND_COMMAND (set, GST_POLL_CMD_WAKEUP, result);
 #else
     SetEvent (set->wakeup_event);
 #endif
@@ -1485,7 +1551,8 @@
 EXPORT_C
 #endif
 
-void gst_poll_set_flushing (GstPoll * set, gboolean flushing)
+void
+gst_poll_set_flushing (GstPoll * set, gboolean flushing)
 {
   g_return_if_fail (set != NULL);
 
@@ -1494,12 +1561,14 @@
   /* update the new state first */
   set->flushing = flushing;
 
-  if (flushing && set->controllable && set->waiting) {
+  if (flushing && set->controllable && set->waiting > 0) {
     /* we are flushing, controllable and waiting, wake up the waiter. When we
      * stop the flushing operation we don't clear the wakeup fd here, this will
      * happen in the _wait() thread. */
 #ifndef G_OS_WIN32
-    SEND_COMMAND (set, GST_POLL_CMD_WAKEUP);
+    gint result;
+
+    SEND_COMMAND (set, GST_POLL_CMD_WAKEUP, result);
 #else
     SetEvent (set->wakeup_event);
 #endif
@@ -1507,3 +1576,88 @@
 
   g_mutex_unlock (set->lock);
 }
+
+/**
+ * gst_poll_write_control:
+ * @set: a #GstPoll.
+ *
+ * Write a byte to the control socket of the controllable @set.
+ * This function is mostly useful for timer #GstPoll objects created with
+ * gst_poll_new_timer(). 
+ *
+ * It will make any current and future gst_poll_wait() function return with
+ * 1, meaning the control socket is set. After an equal amount of calls to
+ * gst_poll_read_control() have been performed, calls to gst_poll_wait() will
+ * block again until their timeout expired.
+ *
+ * Returns: %TRUE on success. %FALSE when @set is not controllable or when the
+ * byte could not be written.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_poll_write_control (GstPoll * set)
+{
+  gboolean res = FALSE;
+
+  g_return_val_if_fail (set != NULL, FALSE);
+
+  g_mutex_lock (set->lock);
+  if (set->controllable) {
+#ifndef G_OS_WIN32
+    gint result;
+
+    SEND_COMMAND (set, GST_POLL_CMD_WAKEUP, result);
+    res = (result > 0);
+#else
+    res = SetEvent (set->wakeup_event);
+#endif
+  }
+  g_mutex_unlock (set->lock);
+
+  return res;
+}
+
+/**
+ * gst_poll_read_control:
+ * @set: a #GstPoll.
+ *
+ * Read a byte from the control socket of the controllable @set.
+ * This function is mostly useful for timer #GstPoll objects created with
+ * gst_poll_new_timer(). 
+ *
+ * Returns: %TRUE on success. %FALSE when @set is not controllable or when there
+ * was no byte to read.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_poll_read_control (GstPoll * set)
+{
+  gboolean res = FALSE;
+
+  g_return_val_if_fail (set != NULL, FALSE);
+
+  g_mutex_lock (set->lock);
+  if (set->controllable) {
+#ifndef G_OS_WIN32
+    guchar cmd;
+    gint result;
+    READ_COMMAND (set, cmd, result);
+    res = (result > 0);
+#else
+    res = ResetEvent (set->wakeup_event);
+#endif
+  }
+  g_mutex_unlock (set->lock);
+
+  return res;
+}
--- a/gstreamer_core/gst/gstpoll.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstpoll.h	Fri Apr 16 15:15:52 2010 +0300
@@ -72,6 +72,11 @@
 IMPORT_C
 #endif
 
+GstPoll*        gst_poll_new_timer        (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void            gst_poll_free             (GstPoll *set);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -149,6 +154,17 @@
 #endif
 
 void            gst_poll_set_flushing     (GstPoll *set, gboolean flushing);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean        gst_poll_write_control    (GstPoll *set);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean        gst_poll_read_control     (GstPoll *set);
 
 G_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/gst/gstpreset.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1153 @@
+/* GStreamer
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * gstpreset.c: helper interface for element presets
+ *
+ * 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.
+ */
+/**
+ * SECTION:gstpreset
+ * @short_description: helper interface for element presets
+ *
+ * This interface offers methods to query and manipulate parameter preset sets.
+ * A preset is a bunch of property settings, together with meta data and a name.
+ * The name of a preset serves as key for subsequent method calls to manipulate
+ * single presets.
+ * All instances of one type will share the list of presets. The list is created
+ * on demand, if presets are not used, the list is not created.
+ *
+ * The interface comes with a default implementation that serves most plugins.
+ * Wrapper plugins will override most methods to implement support for the
+ * native preset format of those wrapped plugins.
+ * One method that is useful to be overridden is gst_preset_get_property_names().
+ * With that one can control which properties are saved and in which order.
+ */
+/* FIXME:
+ * - non racyness
+ *   - we need to avoid two instances writing the preset file
+ *     -> flock(fileno()), http://www.ecst.csuchico.edu/~beej/guide/ipc/flock.html
+ *     -> open exclusive
+ *     -> better save the new file to a tempfile and then rename?
+ *   - we like to know when any other instance makes changes to the keyfile
+ *     - then ui can be updated
+ *     - and we make sure that we don't lose edits
+ *   -> its the same problem actually, once for inside a process, once system-
+ *      wide
+ *     - can we use a lock inside a names shared memory segment?
+ *
+ * - need to add support for GstChildProxy
+ *   we can do this in a next iteration, the format is flexible enough
+ *   http://www.buzztard.org/index.php/Preset_handling_interface
+ *
+ * - should there be a 'preset-list' property to get the preset list
+ *   (and to connect a notify:: to to listen for changes)
+ *   we could use gnome_vfs_monitor_add() to monitor the user preset_file.
+ *
+ * - should there be a 'preset-name' property so that we can set a preset via
+ *   gst-launch, or should we handle this with special syntax in gst-launch:
+ *   gst-launch element preset:<preset-name> property=value ...
+ *   - this would alloow to hanve preset-bundles too (a preset on bins that
+ *     specifies presets for children
+ *
+ * - GstChildProxy suport
+ *   - if we stick with GParamSpec **_list_properties()
+ *     we need to use g_param_spec_set_qdata() to specify the instance on each GParamSpec
+ *     OBJECT_LOCK(obj);  // ChildProxy needs GstIterator support
+ *     num=gst_child_proxy_get_children_count(obj);
+ *     for(i=0;i<num;i++) {
+ *       child=gst_child_proxy_get_child_by_index(obj,i);
+ *       // v1 ----
+ *       g_object_class_list_properties(child,&num);
+ *       // foreach prop
+ *       //   g_param_spec_set_qdata(prop, quark, (gpointer)child);
+ *       //   add to result
+ *       // v2 ----
+ *       // children have to implement preset-iface too tag the returned GParamSpec* with the owner
+ *       props=gst_preset_list_properties(child);
+ *       // add props to result
+ *     }
+ *     OBJECT_UNLOCK(obj);
+ *
+ */
+
+#include "gst_private.h"
+
+#include "gstpreset.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <glib/gstdio.h>
+
+#define GST_CAT_DEFAULT preset_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+/* defines for keyfile usage, this group contains the element type name and
+ * version these presets belong to. */
+#define PRESET_HEADER "_presets_"
+
+/* keys of the preset header section */
+#define PRESET_HEADER_ELEMENT_NAME "element-name"
+#define PRESET_HEADER_VERSION "version"
+
+static GQuark preset_user_path_quark = 0;
+static GQuark preset_system_path_quark = 0;
+static GQuark preset_quark = 0;
+
+/*static GQuark property_list_quark = 0;*/
+
+/* default iface implementation */
+
+static gboolean gst_preset_default_save_presets_file (GstPreset * preset);
+
+/*
+ * preset_get_paths:
+ * @preset: a #GObject that implements #GstPreset
+ * @preset_user_path: location for path or %NULL
+ * @preset_system_path: location for path or %NULL
+ *
+ * Fetch the preset_path for user local and system wide settings. Don't free
+ * after use.
+ *
+ * Returns: %FALSE if no paths could be found.
+ */
+static gboolean
+preset_get_paths (GstPreset * preset, const gchar ** preset_user_path,
+    const gchar ** preset_system_path)
+{
+  GType type = G_TYPE_FROM_INSTANCE (preset);
+  gchar *preset_path;
+  const gchar *element_name;
+
+  /* we use the element name when we must contruct the paths */
+  element_name = G_OBJECT_TYPE_NAME (preset);
+  GST_INFO_OBJECT (preset, "element_name: '%s'", element_name);
+
+  if (preset_user_path) {
+    /* preset user path requested, see if we have it cached in the qdata */
+    if (!(preset_path = g_type_get_qdata (type, preset_user_path_quark))) {
+      gchar *preset_dir;
+
+      /* user presets go in '$HOME/.gstreamer-0.10/presets/GstSimSyn.prs' */
+      preset_dir = g_build_filename (g_get_home_dir (),
+          ".gstreamer-" GST_MAJORMINOR, "presets", NULL);
+      GST_INFO_OBJECT (preset, "user_preset_dir: '%s'", preset_dir);
+      preset_path =
+          g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", preset_dir,
+          element_name);
+      GST_INFO_OBJECT (preset, "user_preset_path: '%s'", preset_path);
+      /* create dirs */
+      g_mkdir_with_parents (preset_dir, 0755);
+      g_free (preset_dir);
+
+      /* cache the preset path to the type */
+      g_type_set_qdata (type, preset_user_path_quark, preset_path);
+    }
+    *preset_user_path = preset_path;
+  }
+
+  if (preset_system_path) {
+    /* preset system path requested, see if we have it cached in the qdata */
+    if (!(preset_path = g_type_get_qdata (type, preset_system_path_quark))) {
+      gchar *preset_dir;
+
+      /* system presets in '$GST_DATADIR/gstreamer-0.10/presets/GstAudioPanorama.prs' */
+      preset_dir = g_build_filename (GST_DATADIR, "gstreamer-" GST_MAJORMINOR,
+          "presets", NULL);
+      GST_INFO_OBJECT (preset, "system_preset_dir: '%s'", preset_dir);
+      preset_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs",
+          preset_dir, element_name);
+      GST_INFO_OBJECT (preset, "system_preset_path: '%s'", preset_path);
+      /* create dirs */
+      g_mkdir_with_parents (preset_dir, 0755);
+      g_free (preset_dir);
+
+      /* cache the preset path to the type */
+      g_type_set_qdata (type, preset_system_path_quark, preset_path);
+    }
+    *preset_system_path = preset_path;
+  }
+  return TRUE;
+}
+
+static gboolean
+preset_skip_property (GParamSpec * property)
+{
+  if (((property->flags & G_PARAM_READWRITE) != G_PARAM_READWRITE) ||
+      (property->flags & G_PARAM_CONSTRUCT_ONLY))
+    return TRUE;
+  /* FIXME: skip GST_PARAM_NOT_PRESETABLE, see #522205 */
+  return FALSE;
+}
+
+/* caller must free @preset_version after use */
+static GKeyFile *
+preset_open_and_parse_header (GstPreset * preset, const gchar * preset_path,
+    gchar ** preset_version)
+{
+  GKeyFile *in;
+  GError *error = NULL;
+  gboolean res;
+  const gchar *element_name;
+  gchar *name;
+
+  in = g_key_file_new ();
+
+  res = g_key_file_load_from_file (in, preset_path,
+      G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error);
+  if (!res || error != NULL)
+    goto load_error;
+
+  /* element type name and preset name must match or we are dealing with a wrong
+   * preset file */
+  element_name = G_OBJECT_TYPE_NAME (preset);
+  name =
+      g_key_file_get_value (in, PRESET_HEADER, PRESET_HEADER_ELEMENT_NAME,
+      NULL);
+
+  if (!name || strcmp (name, element_name))
+    goto wrong_name;
+
+  g_free (name);
+
+  /* get the version now so that the caller can check it */
+  if (preset_version)
+    *preset_version =
+        g_key_file_get_value (in, PRESET_HEADER, PRESET_HEADER_VERSION, NULL);
+
+  return in;
+
+  /* ERRORS */
+load_error:
+  {
+    GST_WARNING_OBJECT (preset, "Unable to read preset file %s: %s",
+        preset_path, error->message);
+    g_error_free (error);
+    g_key_file_free (in);
+    return NULL;
+  }
+wrong_name:
+  {
+    GST_WARNING_OBJECT (preset,
+        "Wrong element name in preset file %s. Expected %s, got %s",
+        preset_path, element_name, GST_STR_NULL (name));
+    g_free (name);
+    g_key_file_free (in);
+    return NULL;
+  }
+}
+
+static guint64
+preset_parse_version (const gchar * str_version)
+{
+  gint major, minor, micro, nano, num;
+
+  major = minor = micro = nano = 0;
+
+  /* parse version (e.g. 0.10.15.1) to guint64 */
+  num = sscanf (str_version, "%d.%d.%d.%d", &major, &minor, &micro, &nano);
+  /* make sure we have atleast "major.minor" */
+  if (num > 1) {
+    guint64 version;
+
+    version = ((((major << 8 | minor) << 8) | micro) << 8) | nano;
+    GST_DEBUG ("version %s -> %" G_GUINT64_FORMAT, str_version, version);
+    return version;
+  }
+  return G_GUINT64_CONSTANT (0);
+}
+
+static void
+preset_merge (GKeyFile * system, GKeyFile * user)
+{
+  gchar *str;
+  gchar **groups, **keys;
+  gsize i, j, num_groups, num_keys;
+
+  /* copy file comment if there is any */
+  if ((str = g_key_file_get_comment (user, NULL, NULL, NULL))) {
+    g_key_file_set_comment (system, NULL, NULL, str, NULL);
+    g_free (str);
+  }
+
+  /* get groups in user and copy into system */
+  groups = g_key_file_get_groups (user, &num_groups);
+  for (i = 0; i < num_groups; i++) {
+    /* copy group comment if there is any */
+    if ((str = g_key_file_get_comment (user, groups[i], NULL, NULL))) {
+      g_key_file_set_comment (system, groups[i], NULL, str, NULL);
+      g_free (str);
+    }
+
+    /* ignore private groups */
+    if (groups[i][0] == '_')
+      continue;
+
+    /* if group already exists in system, remove and re-add keys from user */
+    if (g_key_file_has_group (system, groups[i])) {
+      g_key_file_remove_group (system, groups[i], NULL);
+    }
+
+    keys = g_key_file_get_keys (user, groups[i], &num_keys, NULL);
+    for (j = 0; j < num_keys; j++) {
+      /* copy key comment if there is any */
+      if ((str = g_key_file_get_comment (user, groups[i], keys[j], NULL))) {
+        g_key_file_set_comment (system, groups[i], keys[j], str, NULL);
+        g_free (str);
+      }
+      str = g_key_file_get_value (user, groups[i], keys[j], NULL);
+      g_key_file_set_value (system, groups[i], keys[j], str);
+      g_free (str);
+    }
+    g_strfreev (keys);
+  }
+  g_strfreev (groups);
+}
+
+/* reads the user and system presets files and merges them together. This
+ * function caches the GKeyFile on the element type. If there is no existing
+ * preset file, a new in-memory GKeyFile will be created. */
+static GKeyFile *
+preset_get_keyfile (GstPreset * preset)
+{
+  GKeyFile *presets;
+  GType type = G_TYPE_FROM_INSTANCE (preset);
+
+  /* first see if the have a cached version for the type */
+  if (!(presets = g_type_get_qdata (type, preset_quark))) {
+    const gchar *preset_user_path, *preset_system_path;
+    gchar *str_version_user = NULL, *str_version_system = NULL;
+    gboolean updated_from_system = FALSE;
+    GKeyFile *in_user, *in_system;
+
+    preset_get_paths (preset, &preset_user_path, &preset_system_path);
+
+    /* try to load the user and system presets, we do this to get the versions
+     * of both files. */
+    in_user = preset_open_and_parse_header (preset, preset_user_path,
+        &str_version_user);
+    in_system = preset_open_and_parse_header (preset, preset_system_path,
+        &str_version_system);
+
+    /* compare version to check for merge */
+    if (in_system) {
+      /* keep system presets if there is no user preset or when the system
+       * version is higher than the user version. */
+      if (!in_user) {
+        presets = in_system;
+      } else if (preset_parse_version (str_version_system) >
+          preset_parse_version (str_version_user)) {
+        presets = in_system;
+        updated_from_system = TRUE;
+      }
+    }
+    if (in_user) {
+      if (updated_from_system) {
+        /* merge user on top of system presets */
+        preset_merge (presets, in_user);
+        g_key_file_free (in_user);
+      } else {
+        /* keep user presets */
+        presets = in_user;
+      }
+    }
+    if (!in_user && !in_system) {
+      /* we did not load a user or system presets file, create a new one */
+      presets = g_key_file_new ();
+      g_key_file_set_string (presets, PRESET_HEADER, PRESET_HEADER_ELEMENT_NAME,
+          G_OBJECT_TYPE_NAME (preset));
+    }
+
+    g_free (str_version_user);
+    g_free (str_version_system);
+
+    /* attach the preset to the type */
+    g_type_set_qdata (type, preset_quark, (gpointer) presets);
+
+    if (updated_from_system) {
+      gst_preset_default_save_presets_file (preset);
+    }
+  }
+  return presets;
+}
+
+/* get a list of all supported preset names for an element */
+static gchar **
+gst_preset_default_get_preset_names (GstPreset * preset)
+{
+  GKeyFile *presets;
+  gsize i, num_groups;
+  gchar **groups;
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  /* get the groups, which are also the preset names */
+  if (!(groups = g_key_file_get_groups (presets, &num_groups)))
+    goto no_groups;
+
+  /* remove all private group names starting with '_' from the array */
+  for (i = 0; i < num_groups; i++) {
+    if (groups[i][0] == '_') {
+      /* free private group */
+      g_free (groups[i]);
+      /* move last element of list down */
+      num_groups--;
+      /* move last element into removed element */
+      groups[i] = groups[num_groups];
+      groups[num_groups] = NULL;
+    }
+  }
+  /* sort the array now */
+  g_qsort_with_data (groups, num_groups, sizeof (gchar *),
+      (GCompareDataFunc) strcmp, NULL);
+
+  return groups;
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "Could not load presets");
+    return NULL;
+  }
+no_groups:
+  {
+    GST_WARNING_OBJECT (preset, "Could not find preset groups");
+    return NULL;
+  }
+}
+
+/* get a list of all property names that are used for presets */
+static gchar **
+gst_preset_default_get_property_names (GstPreset * preset)
+{
+  GParamSpec **props;
+  guint i, j, n_props;
+  GObjectClass *gclass;
+  gchar **result;
+
+  gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset));
+
+  /* get a list of normal properties. 
+   * FIXME, change this for childproxy support. */
+  props = g_object_class_list_properties (gclass, &n_props);
+  if (!props)
+    goto no_properties;
+
+  /* allocate array big enough to hold the worst case, including a terminating
+   * NULL pointer. */
+  result = g_new (gchar *, n_props + 1);
+
+  /* now filter out the properties that we can use for presets */
+  GST_DEBUG_OBJECT (preset, "  filtering properties: %u", n_props);
+  for (i = j = 0; i < n_props; i++) {
+    if (preset_skip_property (props[i]))
+      continue;
+
+    /* copy and increment out pointer */
+    result[j++] = g_strdup (props[i]->name);
+  }
+  result[j] = NULL;
+  g_free (props);
+
+  return result;
+
+  /* ERRORS */
+no_properties:
+  {
+    GST_INFO_OBJECT (preset, "object has no properties");
+    return NULL;
+  }
+}
+
+/* load the presets of @name for the instance @preset. Returns %FALSE if something
+ * failed. */
+static gboolean
+gst_preset_default_load_preset (GstPreset * preset, const gchar * name)
+{
+  GKeyFile *presets;
+  gchar **props;
+  guint i;
+  GObjectClass *gclass;
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  /* get the preset name */
+  if (!g_key_file_has_group (presets, name))
+    goto no_group;
+
+  GST_DEBUG_OBJECT (preset, "loading preset : '%s'", name);
+
+  /* get the properties that we can configure in this element */
+  if (!(props = gst_preset_get_property_names (preset)))
+    goto no_properties;
+
+  gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset));
+
+  /* for each of the property names, find the preset parameter and try to
+   * configure the property with its value */
+  for (i = 0; props[i]; i++) {
+    gchar *str;
+    GValue gvalue = { 0, };
+    GParamSpec *property;
+
+    /* check if we have a settings for this element property */
+    if (!(str = g_key_file_get_value (presets, name, props[i], NULL))) {
+      /* the element has a property but the parameter is not in the keyfile */
+      GST_WARNING_OBJECT (preset, "parameter '%s' not in preset", props[i]);
+      continue;
+    }
+
+    GST_DEBUG_OBJECT (preset, "setting value '%s' for property '%s'", str,
+        props[i]);
+
+    /* FIXME, change for childproxy to get the property and element.  */
+    if (!(property = g_object_class_find_property (gclass, props[i]))) {
+      /* the parameter was in the keyfile, the element said it supported it but
+       * then the property was not found in the element. This should not happen. */
+      GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]);
+      g_free (str);
+      continue;
+    }
+
+    /* try to deserialize the property value from the keyfile and set it as
+     * the object property */
+    g_value_init (&gvalue, property->value_type);
+    if (gst_value_deserialize (&gvalue, str)) {
+      /* FIXME, change for childproxy support */
+      g_object_set_property (G_OBJECT (preset), props[i], &gvalue);
+    } else {
+      GST_WARNING_OBJECT (preset,
+          "deserialization of value '%s' for property '%s' failed", str,
+          props[i]);
+    }
+    g_value_unset (&gvalue);
+    g_free (str);
+  }
+  g_strfreev (props);
+
+  return TRUE;
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "no presets");
+    return FALSE;
+  }
+no_group:
+  {
+    GST_WARNING_OBJECT (preset, "no preset named '%s'", name);
+    return FALSE;
+  }
+no_properties:
+  {
+    GST_INFO_OBJECT (preset, "no properties");
+    return FALSE;
+  }
+}
+
+/* save the presets file. A copy of the existing presets file is stored in a
+ * .bak file */
+static gboolean
+gst_preset_default_save_presets_file (GstPreset * preset)
+{
+  GKeyFile *presets;
+  const gchar *preset_path;
+  GError *error = NULL;
+  gchar *bak_file_name;
+  gboolean backup = TRUE;
+  gchar *data;
+  gsize data_size;
+
+  preset_get_paths (preset, &preset_path, NULL);
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  GST_DEBUG_OBJECT (preset, "saving preset file: '%s'", preset_path);
+
+  /* create backup if possible */
+  bak_file_name = g_strdup_printf ("%s.bak", preset_path);
+  if (g_file_test (bak_file_name, G_FILE_TEST_EXISTS)) {
+    if (g_unlink (bak_file_name)) {
+      backup = FALSE;
+      GST_INFO_OBJECT (preset, "cannot remove old backup file : %s",
+          bak_file_name);
+    }
+  }
+  if (backup) {
+    if (g_rename (preset_path, bak_file_name)) {
+      GST_INFO_OBJECT (preset, "cannot backup file : %s -> %s", preset_path,
+          bak_file_name);
+    }
+  }
+  g_free (bak_file_name);
+
+  /* update gstreamer version */
+  g_key_file_set_string (presets, PRESET_HEADER, PRESET_HEADER_VERSION,
+      PACKAGE_VERSION);
+
+  /* get new contents, wee need this to save it */
+  if (!(data = g_key_file_to_data (presets, &data_size, &error)))
+    goto convert_failed;
+
+  /* write presets */
+  if (!g_file_set_contents (preset_path, data, data_size, &error))
+    goto write_failed;
+
+  g_free (data);
+
+  return TRUE;
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset,
+        "no presets, trying to unlink possibly existing preset file: '%s'",
+        preset_path);
+    g_unlink (preset_path);
+    return FALSE;
+  }
+convert_failed:
+  {
+    GST_WARNING_OBJECT (preset, "can not get the keyfile contents: %s",
+        error->message);
+    g_error_free (error);
+    g_free (data);
+    return FALSE;
+  }
+write_failed:
+  {
+    GST_WARNING_OBJECT (preset, "Unable to store preset file %s: %s",
+        preset_path, error->message);
+    g_error_free (error);
+    g_free (data);
+    return FALSE;
+  }
+}
+
+/* save the preset with the given name */
+static gboolean
+gst_preset_default_save_preset (GstPreset * preset, const gchar * name)
+{
+  GKeyFile *presets;
+  gchar **props;
+  guint i;
+  GObjectClass *gclass;
+
+  GST_INFO_OBJECT (preset, "saving new preset: %s", name);
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  /* take copies of current gobject properties from preset */
+  if (!(props = gst_preset_get_property_names (preset)))
+    goto no_properties;
+
+  gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset));
+
+  /* loop over the object properties and store the property value in the
+   * keyfile */
+  for (i = 0; props[i]; i++) {
+    GValue gvalue = { 0, };
+    gchar *str;
+    GParamSpec *property;
+
+    /* FIXME, change for childproxy to get the property and element.  */
+    if (!(property = g_object_class_find_property (gclass, props[i]))) {
+      /* the element said it supported the property but then it does not have
+       * that property. This should not happen. */
+      GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]);
+      continue;
+    }
+
+    g_value_init (&gvalue, property->value_type);
+    /* FIXME, change for childproxy */
+    g_object_get_property (G_OBJECT (preset), props[i], &gvalue);
+
+    if ((str = gst_value_serialize (&gvalue))) {
+      g_key_file_set_string (presets, name, props[i], (gpointer) str);
+      g_free (str);
+    } else {
+      GST_WARNING_OBJECT (preset, "serialization for property '%s' failed",
+          props[i]);
+    }
+    g_value_unset (&gvalue);
+  }
+  GST_INFO_OBJECT (preset, "  saved");
+  g_strfreev (props);
+
+  /* save updated version */
+  return gst_preset_default_save_presets_file (preset);
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "no presets");
+    return FALSE;
+  }
+no_properties:
+  {
+    GST_INFO_OBJECT (preset, "no properties");
+    return FALSE;
+  }
+}
+
+/* copies all keys and comments from one group to another, deleting the old
+ * group. */
+static gboolean
+gst_preset_default_rename_preset (GstPreset * preset, const gchar * old_name,
+    const gchar * new_name)
+{
+  GKeyFile *presets;
+  gchar *str;
+  gchar **keys;
+  gsize i, num_keys;
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  if (!g_key_file_has_group (presets, old_name))
+    goto no_group;
+
+  /* copy group comment if there is any */
+  if ((str = g_key_file_get_comment (presets, old_name, NULL, NULL))) {
+    g_key_file_set_comment (presets, new_name, NULL, str, NULL);
+    g_free (str);
+  }
+
+  /* get all keys from the old group and copy them in the new group */
+  keys = g_key_file_get_keys (presets, old_name, &num_keys, NULL);
+  for (i = 0; i < num_keys; i++) {
+    /* copy key comment if there is any */
+    if ((str = g_key_file_get_comment (presets, old_name, keys[i], NULL))) {
+      g_key_file_set_comment (presets, new_name, keys[i], str, NULL);
+      g_free (str);
+    }
+    /* copy key value */
+    str = g_key_file_get_value (presets, old_name, keys[i], NULL);
+    g_key_file_set_value (presets, new_name, keys[i], str);
+    g_free (str);
+  }
+  g_strfreev (keys);
+
+  /* remove old group */
+  g_key_file_remove_group (presets, old_name, NULL);
+
+  /* save updated version */
+  return gst_preset_default_save_presets_file (preset);
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "no presets");
+    return FALSE;
+  }
+no_group:
+  {
+    GST_WARNING_OBJECT (preset, "no preset named %s", old_name);
+    return FALSE;
+  }
+}
+
+/* delete a group from the keyfile */
+static gboolean
+gst_preset_default_delete_preset (GstPreset * preset, const gchar * name)
+{
+  GKeyFile *presets;
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  /* get the group */
+  if (!g_key_file_has_group (presets, name))
+    goto no_group;
+
+  /* remove the group */
+  g_key_file_remove_group (presets, name, NULL);
+
+  /* save updated version */
+  return gst_preset_default_save_presets_file (preset);
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "no presets");
+    return FALSE;
+  }
+no_group:
+  {
+    GST_WARNING_OBJECT (preset, "no preset named %s", name);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_preset_default_set_meta (GstPreset * preset, const gchar * name,
+    const gchar * tag, const gchar * value)
+{
+  GKeyFile *presets;
+  gchar *key;
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  key = g_strdup_printf ("_meta/%s", tag);
+  if (value && *value) {
+    g_key_file_set_value (presets, name, key, value);
+  } else {
+    g_key_file_remove_key (presets, name, key, NULL);
+  }
+  g_free (key);
+
+  /* save updated keyfile */
+  return gst_preset_default_save_presets_file (preset);
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "no presets");
+    return FALSE;
+  }
+}
+
+/* the caller must free @value after usage */
+static gboolean
+gst_preset_default_get_meta (GstPreset * preset, const gchar * name,
+    const gchar * tag, gchar ** value)
+{
+  GKeyFile *presets;
+  gchar *key;
+
+  /* get the presets from the type */
+  if (!(presets = preset_get_keyfile (preset)))
+    goto no_presets;
+
+  key = g_strdup_printf ("_meta/%s", tag);
+  *value = g_key_file_get_value (presets, name, key, NULL);
+  g_free (key);
+
+  return TRUE;
+
+  /* ERRORS */
+no_presets:
+  {
+    GST_WARNING_OBJECT (preset, "no presets");
+    *value = NULL;
+    return FALSE;
+  }
+}
+
+/* wrapper */
+
+/**
+ * gst_preset_get_preset_names:
+ * @preset: a #GObject that implements #GstPreset
+ *
+ * Get a copy of preset names as a NULL terminated string array.
+ *
+ * Returns: list with names, ue g_strfreev() after usage.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gchar **
+gst_preset_get_preset_names (GstPreset * preset)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), NULL);
+
+  return (GST_PRESET_GET_INTERFACE (preset)->get_preset_names (preset));
+}
+
+/**
+ * gst_preset_get_property_names:
+ * @preset: a #GObject that implements #GstPreset
+ *
+ * Get a the names of the GObject properties that can be used for presets.
+ *
+ * Returns: an array of property names which should be freed with g_strfreev() after use.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gchar **
+gst_preset_get_property_names (GstPreset * preset)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), NULL);
+
+  return (GST_PRESET_GET_INTERFACE (preset)->get_property_names (preset));
+}
+
+/**
+ * gst_preset_load_preset:
+ * @preset: a #GObject that implements #GstPreset
+ * @name: preset name to load
+ *
+ * Load the given preset.
+ *
+ * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_preset_load_preset (GstPreset * preset, const gchar * name)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), FALSE);
+  g_return_val_if_fail (name, FALSE);
+
+  return (GST_PRESET_GET_INTERFACE (preset)->load_preset (preset, name));
+}
+
+/**
+ * gst_preset_save_preset:
+ * @preset: a #GObject that implements #GstPreset
+ * @name: preset name to save
+ *
+ * Save the current preset under the given name. If there is already a preset by
+ * this @name it will be overwritten.
+ *
+ * Returns: %TRUE for success, %FALSE
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_preset_save_preset (GstPreset * preset, const gchar * name)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), FALSE);
+  g_return_val_if_fail (name, FALSE);
+
+  return (GST_PRESET_GET_INTERFACE (preset)->save_preset (preset, name));
+}
+
+/**
+ * gst_preset_rename_preset:
+ * @preset: a #GObject that implements #GstPreset
+ * @old_name: current preset name
+ * @new_name: new preset name
+ *
+ * Renames a preset. If there is already a preset by the @new_name it will be
+ * overwritten.
+ *
+ * Returns: %TRUE for success, %FALSE if e.g. there is no preset with @old_name
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_preset_rename_preset (GstPreset * preset, const gchar * old_name,
+    const gchar * new_name)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), FALSE);
+  g_return_val_if_fail (old_name, FALSE);
+  g_return_val_if_fail (new_name, FALSE);
+
+  return (GST_PRESET_GET_INTERFACE (preset)->rename_preset (preset, old_name,
+          new_name));
+}
+
+/**
+ * gst_preset_delete_preset:
+ * @preset: a #GObject that implements #GstPreset
+ * @name: preset name to remove
+ *
+ * Delete the given preset.
+ *
+ * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_preset_delete_preset (GstPreset * preset, const gchar * name)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), FALSE);
+  g_return_val_if_fail (name, FALSE);
+
+  return (GST_PRESET_GET_INTERFACE (preset)->delete_preset (preset, name));
+}
+
+/**
+ * gst_preset_set_meta:
+ * @preset: a #GObject that implements #GstPreset
+ * @name: preset name
+ * @tag: meta data item name
+ * @value: new value
+ *
+ * Sets a new @value for an existing meta data item or adds a new item. Meta
+ * data @tag names can be something like e.g. "comment". Supplying %NULL for the
+ * @value will unset an existing value.
+ *
+ * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_preset_set_meta (GstPreset * preset, const gchar * name, const gchar * tag,
+    const gchar * value)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), FALSE);
+  g_return_val_if_fail (name, FALSE);
+  g_return_val_if_fail (tag, FALSE);
+
+  return GST_PRESET_GET_INTERFACE (preset)->set_meta (preset, name, tag, value);
+}
+
+/**
+ * gst_preset_get_meta:
+ * @preset: a #GObject that implements #GstPreset
+ * @name: preset name
+ * @tag: meta data item name
+ * @value: value
+ *
+ * Gets the @value for an existing meta data @tag. Meta data @tag names can be
+ * something like e.g. "comment". Returned values need to be released when done.
+ *
+ * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name
+ * or no value for the given @tag
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_preset_get_meta (GstPreset * preset, const gchar * name, const gchar * tag,
+    gchar ** value)
+{
+  g_return_val_if_fail (GST_IS_PRESET (preset), FALSE);
+  g_return_val_if_fail (name, FALSE);
+  g_return_val_if_fail (tag, FALSE);
+  g_return_val_if_fail (value, FALSE);
+
+  return GST_PRESET_GET_INTERFACE (preset)->get_meta (preset, name, tag, value);
+}
+
+/* class internals */
+
+static void
+gst_preset_class_init (GstPresetInterface * iface)
+{
+  iface->get_preset_names = gst_preset_default_get_preset_names;
+  iface->get_property_names = gst_preset_default_get_property_names;
+
+  iface->load_preset = gst_preset_default_load_preset;
+  iface->save_preset = gst_preset_default_save_preset;
+  iface->rename_preset = gst_preset_default_rename_preset;
+  iface->delete_preset = gst_preset_default_delete_preset;
+
+  iface->set_meta = gst_preset_default_set_meta;
+  iface->get_meta = gst_preset_default_get_meta;
+}
+
+static void
+gst_preset_base_init (gpointer g_class)
+{
+  static gboolean initialized = FALSE;
+
+  if (!initialized) {
+    /* init default implementation */
+    GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "preset",
+        GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLACK, "preset interface");
+
+    /* create quarks for use with g_type_{g,s}et_qdata() */
+    preset_quark = g_quark_from_static_string ("GstPreset::presets");
+    preset_user_path_quark =
+        g_quark_from_static_string ("GstPreset::user_path");
+    preset_system_path_quark =
+        g_quark_from_static_string ("GstPreset::system_path");
+
+#if 0
+    property_list_quark = g_quark_from_static_string ("GstPreset::properties");
+
+    /* create interface properties, each element would need to override this
+     *   g_object_class_override_property(gobject_class, PROP_PRESET_NAME, "preset-name");
+     * and in _set_property() do
+     *   case PROP_PRESET_NAME: {
+     *     gchar *name = g_value_get_string (value);
+     *     if (name)
+     *       gst_preset_load_preset(preset, name);
+     *   } break;
+     */
+    g_object_interface_install_property (g_class,
+        g_param_spec_string ("preset-name",
+            "preset-name property",
+            "load given preset", NULL, G_PARAM_WRITABLE));
+#endif
+
+    initialized = TRUE;
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GType
+gst_preset_get_type (void)
+{
+  static volatile gsize type = 0;
+
+  if (g_once_init_enter (&type)) {
+    GType _type;
+    const GTypeInfo info = {
+      sizeof (GstPresetInterface),
+      (GBaseInitFunc) gst_preset_base_init,     /* base_init */
+      NULL,                     /* base_finalize */
+      (GClassInitFunc) gst_preset_class_init,   /* class_init */
+      NULL,                     /* class_finalize */
+      NULL,                     /* class_data */
+      0,
+      0,                        /* n_preallocs */
+      NULL                      /* instance_init */
+    };
+    _type = g_type_register_static (G_TYPE_INTERFACE, "GstPreset", &info, 0);
+    g_once_init_leave (&type, _type);
+  }
+  return type;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/gst/gstpreset.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,135 @@
+/* GStreamer
+ * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
+ *
+ * gstpreset.h: helper interface header for element presets
+ *
+ * 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_PRESET_H__
+#define __GST_PRESET_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_PRESET               (gst_preset_get_type())
+#define GST_PRESET(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PRESET, GstPreset))
+#define GST_IS_PRESET(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PRESET))
+#define GST_PRESET_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_PRESET, GstPresetInterface))
+
+/**
+ * GstPreset:
+ *
+ * Opaque #GstPreset data structure.
+ */
+typedef struct _GstPreset GstPreset; /* dummy object */
+typedef struct _GstPresetInterface GstPresetInterface;
+
+/**
+ * GstPresetInterface:
+ * @parent: parent interface type.
+ * @get_preset_names: virtual method to get list of presets
+ * @get_property_names: virtual methods to get properties that are persistent
+ * @load_preset: virtual methods to load a preset into properties
+ * @save_preset: virtual methods to save properties into a preset
+ * @rename_preset: virtual methods to rename a preset
+ * @delete_preset: virtual methods to remove a preset
+ * @set_meta: virtual methods to set textual meta data to a preset
+ * @get_meta: virtual methods to get textual meta data from a preset
+ *
+ * #GstPreset interface.
+ */
+struct _GstPresetInterface
+{
+  GTypeInterface parent;
+
+  /* methods */
+  gchar**      (*get_preset_names)    (GstPreset *preset);
+
+  gchar**      (*get_property_names)  (GstPreset *preset);
+
+  gboolean     (*load_preset)         (GstPreset *preset, const gchar *name);
+  gboolean     (*save_preset)         (GstPreset *preset, const gchar *name);
+  gboolean     (*rename_preset)       (GstPreset *preset, const gchar *old_name,
+                                       const gchar *new_name);
+  gboolean     (*delete_preset)       (GstPreset *preset, const gchar *name);
+  
+  gboolean     (*set_meta)            (GstPreset *preset, const gchar *name,
+                                       const gchar *tag, const gchar *value);
+  gboolean     (*get_meta)            (GstPreset *preset, const gchar *name,
+                                       const gchar *tag, gchar **value);
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType gst_preset_get_type(void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gchar**      gst_preset_get_preset_names   (GstPreset *preset);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gchar**      gst_preset_get_property_names (GstPreset *preset);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean     gst_preset_load_preset        (GstPreset *preset, const gchar *name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean     gst_preset_save_preset        (GstPreset *preset, const gchar *name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean     gst_preset_rename_preset      (GstPreset *preset, const gchar *old_name,
+                                            const gchar *new_name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean     gst_preset_delete_preset      (GstPreset *preset, const gchar *name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean     gst_preset_set_meta           (GstPreset *preset, const gchar *name,
+                                            const gchar *tag, const gchar *value);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean     gst_preset_get_meta           (GstPreset *preset, const gchar *name,
+                                            const gchar *tag, gchar **value);
+
+G_END_DECLS
+
+#endif /* __GST_PRESET_H__ */
--- a/gstreamer_core/gst/gstquark.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstquark.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,7 +29,25 @@
   "format", "current", "duration", "rate",
   "seekable", "segment-start", "segment-end",
   "src_format", "src_value", "dest_format", "dest_value",
-  "start_format", "start_value", "stop_format", "stop_value"
+  "start_format", "start_value", "stop_format", "stop_value",
+  "gerror", "debug", "buffer-percent", "buffering-mode",
+  "avg-in-rate", "avg-out-rate", "buffering-left",
+  "estimated-total", "old-state", "new-state", "pending-state",
+  "clock", "ready", "position", "new-base-time", "live", "min-latency",
+  "max-latency", "busy", "type", "owner", "update", "applied-rate",
+  "start", "stop", "minsize", "maxsize", "async", "proportion",
+  "diff", "timestamp", "flags", "cur-type", "cur", "stop-type",
+  "latency", "uri", "object", "taglist", "GstEventNewsegment",
+  "GstEventBufferSize", "GstEventQOS", "GstEventSeek", "GstEventLatency",
+  "GstMessageError", "GstMessageWarning", "GstMessageInfo",
+  "GstMessageBuffering", "GstMessageState", "GstMessageClockProvide",
+  "GstMessageClockLost", "GstMessageNewClock", "GstMessageStructureChange",
+  "GstMessageSegmentStart", "GstMessageSegmentDone", "GstMessageDuration",
+  "GstMessageAsyncStart", "GstMessageRequestState", "GstMessageStreamStatus",
+  "GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert",
+  "GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering",
+  "GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush",
+  "intermediate", "GstMessageStepStart", "active", "eos"
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
@@ -43,6 +61,10 @@
 {
   gint i;
 
+  if (G_N_ELEMENTS (_quark_strings) != GST_QUARK_MAX)
+    g_warning ("the quark table is not consistent! %d != %d",
+        (int) G_N_ELEMENTS (_quark_strings), GST_QUARK_MAX);
+
   for (i = 0; i < GST_QUARK_MAX; i++) {
     _priv_gst_quark_table[i] = g_quark_from_static_string (_quark_strings[i]);
   }
--- a/gstreamer_core/gst/gstquark.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstquark.h	Fri Apr 16 15:15:52 2010 +0300
@@ -41,8 +41,84 @@
   GST_QUARK_START_VALUE = 12,
   GST_QUARK_STOP_FORMAT = 13,
   GST_QUARK_STOP_VALUE = 14,
+  GST_QUARK_GERROR = 15,
+  GST_QUARK_DEBUG = 16,
+  GST_QUARK_BUFFER_PERCENT = 17,
+  GST_QUARK_BUFFERING_MODE = 18,
+  GST_QUARK_AVG_IN_RATE = 19,
+  GST_QUARK_AVG_OUT_RATE = 20,
+  GST_QUARK_BUFFERING_LEFT = 21,
+  GST_QUARK_ESTIMATED_TOTAL = 22,
+  GST_QUARK_OLD_STATE = 23,
+  GST_QUARK_NEW_STATE = 24,
+  GST_QUARK_PENDING_STATE = 25,
+  GST_QUARK_CLOCK = 26,
+  GST_QUARK_READY = 27,
+  GST_QUARK_POSITION = 28,
+  GST_QUARK_NEW_BASE_TIME = 29,
+  GST_QUARK_LIVE = 30,
+  GST_QUARK_MIN_LATENCY = 31,
+  GST_QUARK_MAX_LATENCY = 32,
+  GST_QUARK_BUSY = 33,
+  GST_QUARK_TYPE = 34,
+  GST_QUARK_OWNER = 35,
+  GST_QUARK_UPDATE = 36,
+  GST_QUARK_APPLIED_RATE = 37,
+  GST_QUARK_START = 38,
+  GST_QUARK_STOP = 39,
+  GST_QUARK_MINSIZE = 40,
+  GST_QUARK_MAXSIZE = 41,
+  GST_QUARK_ASYNC = 42,
+  GST_QUARK_PROPORTION = 43,
+  GST_QUARK_DIFF = 44,
+  GST_QUARK_TIMESTAMP = 45,
+  GST_QUARK_FLAGS = 46,
+  GST_QUARK_CUR_TYPE = 47,
+  GST_QUARK_CUR = 48,
+  GST_QUARK_STOP_TYPE = 49,
+  GST_QUARK_LATENCY = 50,
+  GST_QUARK_URI = 51,
+  GST_QUARK_OBJECT = 52,
+  GST_QUARK_TAGLIST = 53,
+  GST_QUARK_EVENT_NEWSEGMENT = 54,
+  GST_QUARK_EVENT_BUFFER_SIZE = 55,
+  GST_QUARK_EVENT_QOS = 56,
+  GST_QUARK_EVENT_SEEK = 57,
+  GST_QUARK_EVENT_LATENCY = 58,
+  GST_QUARK_MESSAGE_ERROR = 59,
+  GST_QUARK_MESSAGE_WARNING = 60,
+  GST_QUARK_MESSAGE_INFO = 61,
+  GST_QUARK_MESSAGE_BUFFERING = 62,
+  GST_QUARK_MESSAGE_STATE = 63,
+  GST_QUARK_MESSAGE_CLOCK_PROVIDE = 64,
+  GST_QUARK_MESSAGE_CLOCK_LOST = 65,
+  GST_QUARK_MESSAGE_NEW_CLOCK = 66,
+  GST_QUARK_MESSAGE_STRUCTURE_CHANGE = 67,
+  GST_QUARK_MESSAGE_SEGMENT_START = 68,
+  GST_QUARK_MESSAGE_SEGMENT_DONE = 69,
+  GST_QUARK_MESSAGE_DURATION = 70,
+  GST_QUARK_MESSAGE_ASYNC_START = 71,
+  GST_QUARK_MESSAGE_REQUEST_STATE = 72,
+  GST_QUARK_MESSAGE_STREAM_STATUS = 73,
+  GST_QUARK_QUERY_POSITION = 74,
+  GST_QUARK_QUERY_DURATION = 75,
+  GST_QUARK_QUERY_LATENCY = 76,
+  GST_QUARK_QUERY_CONVERT = 77,
+  GST_QUARK_QUERY_SEGMENT = 78,
+  GST_QUARK_QUERY_SEEKING = 79,
+  GST_QUARK_QUERY_FORMATS = 80,
+  GST_QUARK_QUERY_BUFFERING = 81,
+  GST_QUARK_QUERY_URI = 82,
+  GST_QUARK_EVENT_STEP = 83,
+  GST_QUARK_MESSAGE_STEP_DONE = 84,
+  GST_QUARK_AMOUNT = 85,
+  GST_QUARK_FLUSH = 86,
+  GST_QUARK_INTERMEDIATE = 87,
+  GST_QUARK_MESSAGE_STEP_START = 88,
+  GST_QUARK_ACTIVE = 89,
+  GST_QUARK_EOS = 90,
 
-  GST_QUARK_MAX = 15
+  GST_QUARK_MAX = 91
 } GstQuarkId;
 
 extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
--- a/gstreamer_core/gst/gstquery.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstquery.c	Fri Apr 16 15:15:52 2010 +0300
@@ -65,7 +65,7 @@
 #include "gstvalue.h"
 #include "gstenumtypes.h"
 #include "gstquark.h"
-
+#include "gsturi.h"
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #endif
@@ -73,7 +73,6 @@
 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
 #define GST_CAT_DEFAULT gst_query_debug
 
-static void gst_query_class_init (gpointer g_class, gpointer class_data);
 static void gst_query_finalize (GstQuery * query);
 static GstQuery *_gst_query_copy (GstQuery * query);
 
@@ -95,6 +94,9 @@
   {GST_QUERY_SEGMENT, "segment", "currently configured segment", 0},
   {GST_QUERY_CONVERT, "convert", "Converting between formats", 0},
   {GST_QUERY_FORMATS, "formats", "Supported formats for conversion", 0},
+  {GST_QUERY_BUFFERING, "buffering", "Buffering status", 0},
+  {GST_QUERY_CUSTOM, "custom", "Custom query", 0},
+  {GST_QUERY_URI, "uri", "URI of the source or sink", 0},
   {0, NULL, NULL, 0}
 };
 #ifdef __SYMBIAN32__
@@ -175,48 +177,23 @@
 
   return def->quark;
 }
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_query_get_type (void)
-{
-  static GType _gst_query_type;
+G_DEFINE_TYPE (GstQuery, gst_query, GST_TYPE_MINI_OBJECT);
 
-  if (G_UNLIKELY (_gst_query_type == 0)) {
-    static const GTypeInfo query_info = {
-      sizeof (GstQueryClass),
-      NULL,
-      NULL,
-      gst_query_class_init,
-      NULL,
-      NULL,
-      sizeof (GstQuery),
-      0,
-      NULL,
-      NULL
-    };
+static void
+gst_query_class_init (GstQueryClass * klass)
+{
+  parent_class = g_type_class_peek_parent (klass);
 
-    _gst_query_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
-        "GstQuery", &query_info, 0);
-  }
-  return _gst_query_type;
+  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_query_copy;
+  klass->mini_object_class.finalize =
+      (GstMiniObjectFinalizeFunction) gst_query_finalize;
+
 }
 
 static void
-gst_query_class_init (gpointer g_class, gpointer class_data)
+gst_query_init (GstQuery * query)
 {
-  GstQueryClass *query_class = GST_QUERY_CLASS (g_class);
-
-  parent_class = g_type_class_peek_parent (g_class);
-
-  query_class->mini_object_class.copy =
-      (GstMiniObjectCopyFunction) _gst_query_copy;
-  query_class->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_query_finalize;
-
 }
 
 static void
@@ -229,7 +206,7 @@
     gst_structure_free (query->structure);
   }
 
-  GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (query));
+/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (query)); */
 }
 
 static GstQuery *
@@ -449,10 +426,9 @@
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_empty_new ("GstQueryPosition");
-  gst_structure_id_set (structure,
+  structure = gst_structure_id_new (GST_QUARK (QUERY_POSITION),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (CURRENT), G_TYPE_INT64, (gint64) - 1, NULL);
+      GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new (GST_QUERY_POSITION, structure);
 
@@ -534,10 +510,9 @@
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_empty_new ("GstQueryDuration");
-  gst_structure_id_set (structure,
+  structure = gst_structure_id_new (GST_QUARK (QUERY_DURATION),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (DURATION), G_TYPE_INT64, (gint64) - 1, NULL);
+      GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new (GST_QUERY_DURATION, structure);
 
@@ -621,11 +596,10 @@
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_empty_new ("GstQueryLatency");
-  gst_structure_set (structure,
-      "live", G_TYPE_BOOLEAN, FALSE,
-      "min-latency", G_TYPE_UINT64, (gint64) 0,
-      "max-latency", G_TYPE_UINT64, (gint64) - 1, NULL);
+  structure = gst_structure_id_new (GST_QUARK (QUERY_LATENCY),
+      GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
+      GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
+      GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new (GST_QUERY_LATENCY, structure);
 
@@ -656,10 +630,10 @@
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
 
   structure = gst_query_get_structure (query);
-  gst_structure_set (structure,
-      "live", G_TYPE_BOOLEAN, live,
-      "min-latency", G_TYPE_UINT64, min_latency,
-      "max-latency", G_TYPE_UINT64, max_latency, NULL);
+  gst_structure_id_set (structure,
+      GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
+      GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
+      GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
 }
 
 /**
@@ -687,13 +661,15 @@
 
   structure = gst_query_get_structure (query);
   if (live)
-    *live = g_value_get_boolean (gst_structure_get_value (structure, "live"));
+    *live =
+        g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (LIVE)));
   if (min_latency)
-    *min_latency = g_value_get_uint64 (gst_structure_get_value (structure,
-            "min-latency"));
+    *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (MIN_LATENCY)));
   if (max_latency)
-    *max_latency = g_value_get_uint64 (gst_structure_get_value (structure,
-            "max-latency"));
+    *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (MAX_LATENCY)));
 }
 
 /**
@@ -719,14 +695,11 @@
   GstQuery *query;
   GstStructure *structure;
 
-  g_return_val_if_fail (value >= 0, NULL);
-
-  structure = gst_structure_empty_new ("GstQueryConvert");
-  gst_structure_id_set (structure,
+  structure = gst_structure_id_new (GST_QUARK (QUERY_CONVERT),
       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
       GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
-      GST_QUARK (DEST_VALUE), G_TYPE_INT64, (gint64) - 1, NULL);
+      GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new (GST_QUERY_CONVERT, structure);
 
@@ -760,7 +733,7 @@
       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
       GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
-      GST_QUARK (DEST_VALUE), G_TYPE_INT64, (gint64) dest_value, NULL);
+      GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
 }
 
 /**
@@ -821,12 +794,11 @@
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_empty_new ("GstQuerySegment");
-  gst_structure_id_set (structure,
+  structure = gst_structure_id_new (GST_QUARK (QUERY_SEGMENT),
       GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (START_VALUE), G_TYPE_INT64, (gint64) - 1,
-      GST_QUARK (STOP_VALUE), G_TYPE_INT64, (gint64) - 1, NULL);
+      GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new (GST_QUERY_SEGMENT, structure);
 
@@ -958,7 +930,7 @@
 }
 
 /**
- * gst_query_new_seeking (GstFormat *format)
+ * gst_query_new_seeking:
  * @format: the default #GstFormat for the new query
  *
  * Constructs a new query object for querying seeking properties of
@@ -968,19 +940,19 @@
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
+
 GstQuery *
 gst_query_new_seeking (GstFormat format)
 {
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_empty_new ("GstQuerySeeking");
-  gst_structure_id_set (structure,
+  structure = gst_structure_id_new (GST_QUARK (QUERY_SEEKING),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
-      GST_QUARK (SEGMENT_START), G_TYPE_INT64, (gint64) - 1,
-      GST_QUARK (SEGMENT_END), G_TYPE_INT64, (gint64) - 1, NULL);
+      GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new (GST_QUERY_SEEKING, structure);
 
@@ -1076,7 +1048,7 @@
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new ("GstQueryFormats", NULL);
+  structure = gst_structure_id_empty_new (GST_QUARK (QUERY_FORMATS));
   query = gst_query_new (GST_QUERY_FORMATS, structure);
 
   return query;
@@ -1235,3 +1207,322 @@
     }
   }
 }
+
+/**
+ * gst_query_new_buffering
+ * @format: the default #GstFormat for the new query
+ *
+ * Constructs a new query object for querying the buffering status of
+ * a stream.
+ *
+ * Returns: A #GstQuery
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstQuery *
+gst_query_new_buffering (GstFormat format)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  /* by default, we configure the answer as no buffering with a 100% buffering
+   * progress */
+  structure = gst_structure_id_new (GST_QUARK (QUERY_BUFFERING),
+      GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
+      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
+      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
+      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
+      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
+      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
+      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+
+  query = gst_query_new (GST_QUERY_BUFFERING, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_set_buffering_percent
+ * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
+ * @busy: if buffering is busy
+ * @percent: a buffering percent
+ *
+ * Set the percentage of buffered data. This is a value between 0 and 100.
+ * The @busy indicator is %TRUE when the buffering is in progress.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+  g_return_if_fail (percent >= 0 && percent <= 100);
+
+  gst_structure_id_set (query->structure,
+      GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
+      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
+}
+
+/**
+ * gst_query_parse_buffering_percent
+ * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
+ * @busy: if buffering is busy
+ * @percent: a buffering percent
+ *
+ * Get the percentage of buffered data. This is a value between 0 and 100.
+ * The @busy indicator is %TRUE when the buffering is in progress.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
+    gint * percent)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  if (busy)
+    *busy = g_value_get_boolean (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUSY)));
+  if (percent)
+    *percent = g_value_get_int (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUFFER_PERCENT)));
+}
+
+/**
+ * gst_query_set_buffering_stats:
+ * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
+ * @mode: a buffering mode 
+ * @avg_in: the average input rate
+ * @avg_out: the average output rate
+ * @buffering_left: amount of buffering time left
+ *
+ * Configures the buffering stats values in @query.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
+    gint avg_in, gint avg_out, gint64 buffering_left)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  gst_structure_id_set (query->structure,
+      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
+      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
+      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
+      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+}
+
+/**
+ * gst_query_parse_buffering_stats:
+ * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
+ * @mode: a buffering mode 
+ * @avg_in: the average input rate
+ * @avg_out: the average output rate
+ * @buffering_left: amount of buffering time left
+ *
+ * Extracts the buffering stats values from @query.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_parse_buffering_stats (GstQuery * query,
+    GstBufferingMode * mode, gint * avg_in, gint * avg_out,
+    gint64 * buffering_left)
+{
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  if (mode)
+    *mode = g_value_get_enum (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUFFERING_MODE)));
+  if (avg_in)
+    *avg_in = g_value_get_int (gst_structure_id_get_value (query->structure,
+            GST_QUARK (AVG_IN_RATE)));
+  if (avg_out)
+    *avg_out = g_value_get_int (gst_structure_id_get_value (query->structure,
+            GST_QUARK (AVG_OUT_RATE)));
+  if (buffering_left)
+    *buffering_left =
+        g_value_get_int64 (gst_structure_id_get_value (query->structure,
+            GST_QUARK (BUFFERING_LEFT)));
+}
+
+
+/**
+ * gst_query_set_buffering_range:
+ * @query: a #GstQuery
+ * @format: the format to set for the @start and @stop values
+ * @start: the start to set
+ * @stop: the stop to set
+ * @estimated_total: estimated total amount of download time
+ *
+ * Set the available query result fields in @query. 
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_set_buffering_range (GstQuery * query, GstFormat format,
+    gint64 start, gint64 stop, gint64 estimated_total)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  structure = gst_query_get_structure (query);
+  gst_structure_id_set (structure,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (START_VALUE), G_TYPE_INT64, start,
+      GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
+      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
+}
+
+/**
+ * gst_query_parse_buffering_range:
+ * @query: a GST_QUERY_SEEKING type query #GstQuery
+ * @format: the format to set for the @segment_start and @segment_end values
+ * @start: the start to set
+ * @stop: the stop to set
+ * @estimated_total: estimated total amount of download time
+ *
+ * Parse an available query, writing the format into @format, and 
+ * other results into the passed parameters, if the respective parameters
+ * are non-NULL
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
+    gint64 * start, gint64 * stop, gint64 * estimated_total)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+
+  structure = gst_query_get_structure (query);
+  if (format)
+    *format = g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
+  if (start)
+    *start = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (START_VALUE)));
+  if (stop)
+    *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (STOP_VALUE)));
+  if (estimated_total)
+    *estimated_total =
+        g_value_get_int64 (gst_structure_id_get_value (structure,
+            GST_QUARK (ESTIMATED_TOTAL)));
+}
+
+/**
+ * gst_query_new_uri:
+ *
+ * Constructs a new query URI query object. Use gst_query_unref()
+ * when done with it. An URI query is used to query the current URI
+ * that is used by the source or sink.
+ *
+ * Returns: A #GstQuery
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstQuery *
+gst_query_new_uri (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (QUERY_URI),
+      GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
+
+  query = gst_query_new (GST_QUERY_URI, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_set_uri:
+ * @query: a #GstQuery with query type GST_QUERY_URI
+ * @uri: the URI to set
+ *
+ * Answer a URI query by setting the requested URI.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_set_uri (GstQuery * query, const gchar * uri)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
+  g_return_if_fail (gst_uri_is_valid (uri));
+
+  structure = gst_query_get_structure (query);
+  gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
+}
+
+/**
+ * gst_query_parse_uri:
+ * @query: a #GstQuery
+ * @uri: the storage for the current URI (may be NULL)
+ *
+ * Parse an URI query, writing the URI into @uri as a newly
+ * allocated string, if the respective parameters are non-NULL.
+ * Free the string with g_free() after usage.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_query_parse_uri (GstQuery * query, gchar ** uri)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
+
+  structure = gst_query_get_structure (query);
+  if (uri)
+    *uri = g_value_dup_string (gst_structure_id_get_value (structure,
+            GST_QUARK (URI)));
+}
--- a/gstreamer_core/gst/gstquery.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstquery.h	Fri Apr 16 15:15:52 2010 +0300
@@ -46,6 +46,11 @@
  * @GST_QUERY_SEGMENT: segment start/stop positions
  * @GST_QUERY_CONVERT: convert values between formats
  * @GST_QUERY_FORMATS: query supported formats for convert
+ * @GST_QUERY_BUFFERING: query available media for efficient seeking. Since
+ * 0.10.20.
+ * @GST_QUERY_CUSTOM: a custom application or element defined query. Since
+ * 0.10.22.
+ * @GST_QUERY_URI: query the URI of the source or sink. Since 0.10.22.
  *
  * Standard predefined Query types
  */
@@ -61,9 +66,28 @@
   GST_QUERY_SEEKING,
   GST_QUERY_SEGMENT,
   GST_QUERY_CONVERT,
-  GST_QUERY_FORMATS
+  GST_QUERY_FORMATS,
+  GST_QUERY_BUFFERING,
+  GST_QUERY_CUSTOM,
+  GST_QUERY_URI
 } GstQueryType;
 
+/**
+ * GstBufferingMode:
+ * @GST_BUFFERING_STREAM: a small amount of data is buffered
+ * @GST_BUFFERING_DOWNLOAD: the stream is being downloaded
+ * @GST_BUFFERING_TIMESHIFT: the stream is being downloaded in a ringbuffer
+ * @GST_BUFFERING_LIVE: the stream is a live stream
+ *
+ * The different types of buffering methods.
+ */
+typedef enum {
+  GST_BUFFERING_STREAM,
+  GST_BUFFERING_DOWNLOAD,
+  GST_BUFFERING_TIMESHIFT,
+  GST_BUFFERING_LIVE
+} GstBufferingMode;
+
 typedef struct _GstQueryTypeDefinition GstQueryTypeDefinition;
 typedef struct _GstQuery GstQuery;
 typedef struct _GstQueryClass GstQueryClass;
@@ -90,8 +114,10 @@
 #define GST_IS_QUERY_CLASS(klass)              (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_QUERY))
 #define GST_QUERY_GET_CLASS(obj)               (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QUERY, GstQueryClass))
 #define GST_QUERY(obj)                         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QUERY, GstQuery))
+#define GST_QUERY_CAST(obj)                    ((GstQuery*)(obj)) /* only since 0.10.23 */
 #define GST_QUERY_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QUERY, GstQueryClass))
 
+
 /**
  * GST_QUERY_TYPE:
  * @query: the query to query
@@ -128,14 +154,14 @@
 
   GstStructure *structure;
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved;
 };
 
 struct _GstQueryClass {
   GstMiniObjectClass mini_object_class;
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 #ifdef __SYMBIAN32__
@@ -197,8 +223,19 @@
  * @q: a #GstQuery to increase the refcount of.
  *
  * Increases the refcount of the given query by one.
+ *
+ * Returns: @q
  */
-#define         gst_query_ref(q)		GST_QUERY (gst_mini_object_ref (GST_MINI_OBJECT (q)))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstQuery * gst_query_ref (GstQuery * q);
+#endif
+
+static inline GstQuery *
+gst_query_ref (GstQuery * q)
+{
+  return GST_QUERY (gst_mini_object_ref (GST_MINI_OBJECT_CAST (q)));
+}
+
 /**
  * gst_query_unref:
  * @q: a #GstQuery to decrease the refcount of.
@@ -206,7 +243,15 @@
  * Decreases the refcount of the query. If the refcount reaches 0, the query
  * will be freed.
  */
-#define         gst_query_unref(q)		gst_mini_object_unref (GST_MINI_OBJECT (q))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_query_unref (GstQuery * q);
+#endif
+
+static inline void
+gst_query_unref (GstQuery * q)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (q));
+}
 
 /* copy query */
 /**
@@ -215,8 +260,19 @@
  *
  * Copies the given query using the copy function of the parent #GstData
  * structure.
+ *
+ * Returns: a new copy of @q.
  */
-#define         gst_query_copy(q)		GST_QUERY (gst_mini_object_copy (GST_MINI_OBJECT (q)))
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstQuery * gst_query_copy (const GstQuery * q);
+#endif
+
+static inline GstQuery *
+gst_query_copy (const GstQuery * q)
+{
+  return GST_QUERY (gst_mini_object_copy (GST_MINI_OBJECT_CAST (q)));
+}
+
 /**
  * gst_query_make_writable:
  * @q: a #GstQuery to make writable
@@ -377,6 +433,69 @@
 
 void            gst_query_parse_formats_nth     (GstQuery *query, guint nth, GstFormat *format);
 
+/* buffering query */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstQuery*       gst_query_new_buffering           (GstFormat format);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_query_set_buffering_percent   (GstQuery *query, gboolean busy, gint percent);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_query_parse_buffering_percent (GstQuery *query, gboolean *busy, gint *percent);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void            gst_query_set_buffering_stats     (GstQuery *query, GstBufferingMode mode,
+                                                   gint avg_in, gint avg_out, 
+						   gint64 buffering_left);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+ 
+void            gst_query_parse_buffering_stats    (GstQuery *query, GstBufferingMode *mode,
+                                                   gint *avg_in, gint *avg_out, 
+						   gint64 *buffering_left);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+ 
+
+void            gst_query_set_buffering_range     (GstQuery *query, GstFormat format,
+                                                   gint64 start, gint64 stop,
+						   gint64 estimated_total);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_query_parse_buffering_range   (GstQuery *query, GstFormat *format,
+                                                   gint64 *start, gint64 *stop,
+						   gint64 *estimated_total);
+/* URI query */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstQuery *      gst_query_new_uri                 (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_query_parse_uri               (GstQuery *query, gchar **uri);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_query_set_uri                 (GstQuery *query, const gchar *uri);
+
 G_END_DECLS
 
 #endif /* __GST_QUERY_H__ */
--- a/gstreamer_core/gst/gstregistry.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstregistry.c	Fri Apr 16 15:15:52 2010 +0300
@@ -27,7 +27,6 @@
  * @see_also: #GstPlugin, #GstPluginFeature
  *
  * One registry holds the metadata of a set of plugins.
- * All registries build the #GstRegistryPool.
  *
  * <emphasis role="bold">Design:</emphasis>
  *
@@ -101,6 +100,8 @@
 #include <stdio.h>
 #include <string.h>
 
+/* For g_stat () */
+#include <glib/gstdio.h>
 
 #include "gstinfo.h"
 #include "gstregistry.h"
@@ -109,7 +110,7 @@
 
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
-#include "helpfile.h" 
+#include "helpfile.h"
 #endif
 
 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
@@ -249,8 +250,7 @@
   g_static_mutex_lock (&_gst_registry_mutex);
   if (G_UNLIKELY (!_gst_registry_default)) {
     _gst_registry_default = g_object_new (GST_TYPE_REGISTRY, NULL);
-    gst_object_ref (GST_OBJECT_CAST (_gst_registry_default));
-    gst_object_sink (GST_OBJECT_CAST (_gst_registry_default));
+    gst_object_ref_sink (GST_OBJECT_CAST (_gst_registry_default));
   }
   registry = _gst_registry_default;
   g_static_mutex_unlock (&_gst_registry_mutex);
@@ -373,14 +373,12 @@
 
   registry->plugins = g_list_prepend (registry->plugins, plugin);
 
-  gst_object_ref (plugin);
-  gst_object_sink (plugin);
+  gst_object_ref_sink (plugin);
   GST_OBJECT_UNLOCK (registry);
 
   GST_LOG_OBJECT (registry, "emitting plugin-added for filename \"%s\"",
       GST_STR_NULL (plugin->filename));
-  g_signal_emit (G_OBJECT (registry), gst_registry_signals[PLUGIN_ADDED], 0,
-      plugin);
+  g_signal_emit (registry, gst_registry_signals[PLUGIN_ADDED], 0, plugin);
 
   return TRUE;
 }
@@ -390,20 +388,22 @@
     GstPlugin * plugin)
 {
   GList *f;
+  const gchar *name;
 
   g_return_if_fail (GST_IS_REGISTRY (registry));
   g_return_if_fail (GST_IS_PLUGIN (plugin));
 
+  name = gst_plugin_get_name (plugin);
+
   /* Remove all features for this plugin */
   f = registry->features;
   while (f != NULL) {
     GList *next = g_list_next (f);
     GstPluginFeature *feature = f->data;
 
-    if (feature && !strcmp (feature->plugin_name, gst_plugin_get_name (plugin))) {
+    if (G_UNLIKELY (feature && !strcmp (feature->plugin_name, name))) {
       GST_DEBUG_OBJECT (registry, "removing feature %p (%s) for plugin %s",
-          feature, gst_plugin_feature_get_name (feature),
-          gst_plugin_get_name (plugin));
+          feature, gst_plugin_feature_get_name (feature), name);
 
       registry->features = g_list_delete_link (registry->features, f);
       g_hash_table_remove (registry->feature_hash, feature->name);
@@ -475,7 +475,8 @@
     GST_DEBUG_OBJECT (registry, "replacing existing feature %p (%s)",
         existing_feature, feature->name);
     /* Remove the existing feature from the list now, before we insert the new
-     * one, but don't unref yet because the hash is still storing a reference to     * it. */
+     * one, but don't unref yet because the hash is still storing a reference to
+     * it. */
     registry->features = g_list_remove (registry->features, existing_feature);
   }
 
@@ -485,17 +486,16 @@
   g_hash_table_replace (registry->feature_hash, feature->name, feature);
 
   if (G_UNLIKELY (existing_feature)) {
-    /* We unref now. No need to remove the feature name from the hash table, it      * got replaced by the new feature */
+    /* We unref now. No need to remove the feature name from the hash table, it
+     * got replaced by the new feature */
     gst_object_unref (existing_feature);
   }
 
-  gst_object_ref (feature);
-  gst_object_sink (feature);
+  gst_object_ref_sink (feature);
   GST_OBJECT_UNLOCK (registry);
 
   GST_LOG_OBJECT (registry, "emitting feature-added for %s", feature->name);
-  g_signal_emit (G_OBJECT (registry), gst_registry_signals[FEATURE_ADDED], 0,
-      feature);
+  g_signal_emit (registry, gst_registry_signals[FEATURE_ADDED], 0, feature);
 
   return TRUE;
 }
@@ -582,7 +582,8 @@
  * If the first flag is set, only the first match is
  * returned (as a list with a single object).
  *
- * Returns: a GList of plugin features, gst_plugin_feature_list_free after use.
+ * Returns: a #GList of #GstPluginFeature. Use gst_plugin_feature_list_free()
+ * after usage.
  *
  * MT safe.
  */
@@ -701,8 +702,8 @@
  *
  * Retrieves a #GList of #GstPluginFeature of @type.
  *
- * Returns: a #GList of #GstPluginFeature of @type. gst_plugin_feature_list_free
- * after usage.
+ * Returns: a #GList of #GstPluginFeature of @type. Use
+ * gst_plugin_feature_list_free() after usage.
  *
  * MT safe.
  */
@@ -733,7 +734,7 @@
  * Get a copy of all plugins registered in the given registry. The refcount
  * of each element in the list in incremented.
  *
- * Returns: a #GList of #GstPlugin. gst_plugin_list_free after use.
+ * Returns: a #GList of #GstPlugin. Use gst_plugin_list_free() after usage.
  *
  * MT safe.
  */
@@ -815,7 +816,8 @@
   /* FIXME: use GTree speed up lookups */
   for (g = registry->plugins; g; g = g_list_next (g)) {
     plugin = GST_PLUGIN_CAST (g->data);
-    if (plugin->basename && strcmp (basename, plugin->basename) == 0) {
+    if (G_UNLIKELY (plugin->basename
+            && strcmp (basename, plugin->basename) == 0)) {
       g_free (basename);
       return plugin;
     }
@@ -861,7 +863,6 @@
 gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
     int level)
 {
-  GDir *directory[2];
   GDir *dir;
   const gchar *dirent;
   gchar *filename;
@@ -872,96 +873,108 @@
 #ifdef __SYMBIAN32__  
   GMappedFile *mapped = NULL; 
   gchar *contents = NULL;  
-  gchar** arglist=NULL;  
+  gchar** arglist=NULL, **arglistbackup = NULL;  
   GError *err = NULL;  
   char* file;
-  gint i = 2;
 #endif
-  directory[0] = g_dir_open ( PLUGIN_LIST, 0, NULL );
-  directory[1] = g_dir_open ( PLUGIN_LIST_IN_ROM, 0, NULL );
-  while( i ){
-   --i; 
-    dir = directory[i];
-    if (!dir)
-        continue;
+  
+  dir = g_dir_open (path, 0, NULL);
+  if (!dir)
+    return FALSE;
+
+  while ((dirent = g_dir_read_name (dir))) {
+    struct stat file_status;
 
-  while ((dirent = g_dir_read_name (dir))) 
-  {    
+    filename = g_build_filename (path, dirent, NULL);
 #ifdef __SYMBIAN32__
+    /// check the extention..
+    if (!g_str_has_suffix (dirent, GSTREAMER_TXT_FILE_SUFFIX)){
+            continue;
+    }
+    //filename = g_strjoin ("\\", PLUGIN_LIST, dirent, NULL);
+    mapped = g_mapped_file_new (filename, FALSE, &err);
+    if( !mapped )
+    {
+        return FALSE;
+    }
+        
     
-   if( i == 1 )
-        filename = g_strjoin ("\\", PLUGIN_LIST_IN_ROM, dirent, NULL);
-    else
-        filename = g_strjoin ("\\", PLUGIN_LIST, dirent, NULL);
-    mapped = g_mapped_file_new (filename, FALSE, &err);
     contents = g_mapped_file_get_contents (mapped);
     arglist = g_strsplit(contents, "\r\n", -1 );
-    
-    g_free (filename);
-     
+    //g_free (contents); 
+    g_free (filename);  
+    arglistbackup = arglist;
     while( *arglist )
     {
-      filename = *arglist;
-      // trim white spaces from start
-      while(*filename ==' ' )
-          filename++;
-      
-      file = filename;
-      
-      // trim white spaces from last
-      while(*file != ' ' && *file != '\0')
-          file++;
-      *file = '\0';
-      
-      arglist++;
-      /// get the full path of DLL 
-      filename = libgstreamer_get_dll_path( filename );
+    dirent = *arglist;
+    filename = *arglist;
+    // trim white spaces from start
+    while(*filename ==' ' )
+        filename++;
+    
+    file = filename;
+    
+    // trim white spaces from last
+    while(*file != ' ' && *file != '\0')
+        file++;
+    *file = '\0';
+    
+    arglist++;
+    /// get the full path of DLL 
+    filename = libgstreamer_get_dll_path( filename );    
+#endif    
+    if (g_stat (filename, &file_status) < 0) {
+      /* Plugin will be removed from cache after the scan completes if it
+       * is still marked 'cached' */
+      g_free (filename);
+      continue;
+    }
 
-#else
-      
-	  filename = g_strjoin ("\\", path, dirent, NULL);
-#endif      
-    GST_LOG_OBJECT (registry, "examining file: %s", filename);
-
-    if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
+    if (file_status.st_mode & S_IFDIR) {
+      /* skip the .debug directory, these contain elf files that are not
+       * useful or worse, can crash dlopen () */
+      if (g_str_equal (dirent, ".debug") || g_str_equal (dirent, ".git")) {
+        GST_LOG_OBJECT (registry, "ignoring .debug or .git directory");
+        g_free (filename);
+        continue;
+      }
+      /* FIXME 0.11: Don't recurse into directories, this behaviour
+       * is inconsistent with other PATH environment variables
+       */
       if (level > 0) {
-        GST_LOG_OBJECT (registry, "found directory, recursing");
+        GST_LOG_OBJECT (registry, "recursing into directory %s", filename);
         changed |= gst_registry_scan_path_level (registry, filename, level - 1);
       } else {
-        GST_LOG_OBJECT (registry,
-            "found directory, but recursion level is too deep");
+        GST_LOG_OBJECT (registry, "not recursing into directory %s, "
+            "recursion level too deep", filename);
       }
       g_free (filename);
       continue;
     }
-      if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
-        GST_LOG_OBJECT (registry, "not a regular file, ignoring");
-        g_free (filename);
-        continue;
-      }
-    if (!g_str_has_suffix (filename, ".so") &&
-        !g_str_has_suffix (filename, ".sl") &&
-        !g_str_has_suffix (filename, ".dll") &&
-        !g_str_has_suffix (filename, ".dynlib")) {
-      GST_LOG_OBJECT (registry,
-          "extension is not recognized as module file, ignoring");
+    if (!(file_status.st_mode & S_IFREG)) {
+      GST_LOG_OBJECT (registry, "%s is not a regular file, ignoring", filename);
       g_free (filename);
       continue;
     }
+    if (!g_str_has_suffix (dirent, G_MODULE_SUFFIX)
+#ifdef GST_EXTRA_MODULE_SUFFIX
+        && !g_str_has_suffix (dirent, GST_EXTRA_MODULE_SUFFIX)
+#endif
+        ) {
+      GST_LOG_OBJECT (registry, "extension is not recognized as module file, "
+          "ignoring file %s", filename);
+      g_free (filename);
+      continue;
+    }
+
+    GST_LOG_OBJECT (registry, "file %s looks like a possible module", filename);
 
     /* plug-ins are considered unique by basename; if the given name
      * was already seen by the registry, we ignore it */
     plugin = gst_registry_lookup (registry, filename);
     if (plugin) {
-      struct stat file_status;
+      gboolean env_vars_changed, deps_changed = FALSE;
 
-      if (stat (filename, &file_status)) {
-        /* Plugin will be removed from cache after the scan completes if it
-         * is still marked 'cached' */
-        g_free (filename);
-        gst_object_unref (plugin);
-        continue;
-      }
       if (plugin->registered) {
         GST_DEBUG_OBJECT (registry,
             "plugin already registered from path \"%s\"",
@@ -970,8 +983,12 @@
         gst_object_unref (plugin);
         continue;
       }
+
+      env_vars_changed = _priv_plugin_deps_env_vars_changed (plugin);
+
       if (plugin->file_mtime == file_status.st_mtime &&
-          plugin->file_size == file_status.st_size) {
+          plugin->file_size == file_status.st_size && !env_vars_changed &&
+          !(deps_changed = _priv_plugin_deps_files_changed (plugin))) {
         GST_LOG_OBJECT (registry, "file %s cached", filename);
         plugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
         GST_LOG_OBJECT (registry, "marking plugin %p as registered as %s",
@@ -987,11 +1004,13 @@
       } else {
         GST_INFO_OBJECT (registry, "cached info for %s is stale", filename);
         GST_DEBUG_OBJECT (registry, "mtime %ld != %ld or size %"
-            G_GINT64_FORMAT " != %"
-            G_GINT64_FORMAT, plugin->file_mtime, file_status.st_mtime,
-            (gint64) plugin->file_size, (gint64) file_status.st_size);
+            G_GINT64_FORMAT " != %" G_GINT64_FORMAT " or external dependency "
+            "env_vars changed: %d or external dependencies changed: %d",
+            plugin->file_mtime, file_status.st_mtime,
+            (gint64) plugin->file_size, (gint64) file_status.st_size,
+            env_vars_changed, deps_changed);
         gst_registry_remove_plugin (gst_registry_get_default (), plugin);
-        /* We don't use a GError here because a failure to load some shared
+        /* We don't use a GError here because a failure to load some shared 
          * objects as plugins is normal (particularly in the uninstalled case)
          */
         newplugin = gst_plugin_load_file (filename, NULL);
@@ -1016,23 +1035,26 @@
     }
 
     g_free (filename);
+#ifdef __SYMBIAN32__
   }
-#ifdef __SYMBIAN32__          
- }  
+  /// delete arglist
+  g_strfreev(arglistbackup); 
 #endif
+  }
+
+
   g_dir_close (dir);
-}
+
   return changed;
 }
 
 /**
  * gst_registry_scan_path:
- * @registry: the registry to add the path to
- * @path: the path to add to the registry
+ * @registry: the registry to add found plugins to
+ * @path: the path to scan
  *
- * Add the given path to the registry. The syntax of the
- * path is specific to the registry. If the path has already been
- * added, do nothing.
+ * Scan the given path for plugins to add to the registry. The syntax of the
+ * path is specific to the registry.
  *
  * Returns: %TRUE if registry changed
  */
@@ -1110,7 +1132,8 @@
  *
  * Retrieves a #GList of features of the plugin with name @name.
  *
- * Returns: a #GList of #GstPluginFeature. gst_plugin_feature_list_free() after usage.
+ * Returns: a #GList of #GstPluginFeature. Use gst_plugin_feature_list_free()
+ * after usage.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
--- a/gstreamer_core/gst/gstregistrybinary.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstregistrybinary.c	Fri Apr 16 15:15:52 2010 +0300
@@ -2,6 +2,7 @@
  * Copyright (C) 2006 Josep Torra <josep@fluendo.com>
  *               2006 Mathieu Garcia <matthieu@fluendo.com>
  *               2006,2007 Stefan Kost <ensonic@users.sf.net>
+ *               2008 Sebastian Dröge <slomo@circular-chaos.org>
  *
  * gstregistrybinary.c: GstRegistryBinary object, support routines
  *
@@ -22,22 +23,21 @@
  */
 
 /* FIXME:
- * - Add random key to libgstreamer during build and only accept registry,
- *   if key matches (or is the version check enough)
  * - keep registry binary blob and reference strings
- *   - don't free/unmmap contents when leaving gst_registry_binary_read_cache()
+ *   - don't free/
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+unmmap contents when leaving gst_registry_binary_read_cache()
  *     - free at gst_deinit() / _priv_gst_registry_cleanup() ?
  *   - GstPlugin:
  *     - GST_PLUGIN_FLAG_CONST
- *   -GstPluginFeature, GstIndexFactory, GstElementFactory
+ *   - GstPluginFeature, GstIndexFactory, GstElementFactory
  *     - needs Flags (GST_PLUGIN_FEATURE_FLAG_CONST)
  *     - can we turn loaded into flag?
  * - why do we collect a list of binary chunks and not write immediately
  *   - because we need to process subchunks, before we can set e.g. nr_of_items
  *     in parent chunk
- * - need more robustness
- *   - don't parse beyond mem-block size
- *   - include md5-sum ?
  */
 
 #ifdef HAVE_CONFIG_H
@@ -74,62 +74,263 @@
 
 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
 
-/* macros */
+/* count string length, but return -1 if we hit the eof */
+static gint
+_strnlen (const gchar * str, gint maxlen)
+{
+  gint len = 0;
+
+  if (G_UNLIKELY (len == maxlen))
+    return -1;
 
-#define unpack_element(_inptr, _outptr, _element)  \
-  _outptr = (_element *)_inptr; \
-  _inptr += sizeof (_element)
+  while (*str++ != '\0') {
+    len++;
+    if (G_UNLIKELY (len == maxlen))
+      return -1;
+  }
+  return len;
+}
 
-#define unpack_const_string(_inptr, _outptr) \
-  _outptr = g_intern_string ((const gchar *)_inptr); \
-  _inptr += strlen(_outptr) + 1
+/* reading macros */
 
-#define unpack_string(_inptr, _outptr)  \
-  _outptr = g_strdup ((gchar *)_inptr); \
-  _inptr += strlen(_outptr) + 1
+#define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \
+  if (inptr + sizeof(element) >= endptr) \
+    goto error_label; \
+  outptr = (element *) inptr; \
+  inptr += sizeof (element); \
+}G_STMT_END
 
-#if !GST_HAVE_UNALIGNED_ACCESS
-#  define alignment32(_address)  (gsize)_address%4
-#  define align32(_ptr)          _ptr += (( alignment32(_ptr) == 0) ? 0 : 4-alignment32(_ptr))
-#else
-#  define alignment32(_address)  0
-#  define align32(_ptr)          do {} while(0)
-#endif
+#define unpack_const_string(inptr, outptr, endptr, error_label) G_STMT_START{\
+  gint _len = _strnlen (inptr, (endptr-inptr)); \
+  if (_len == -1) \
+    goto error_label; \
+  outptr = g_intern_string ((const gchar *)inptr); \
+  inptr += _len + 1; \
+}G_STMT_END
 
+#define unpack_string(inptr, outptr, endptr, error_label)  G_STMT_START{\
+  gint _len = _strnlen (inptr, (endptr-inptr)); \
+  if (_len == -1) \
+    goto error_label; \
+  outptr = g_memdup ((gconstpointer)inptr, _len + 1); \
+  inptr += _len + 1; \
+}G_STMT_END
+
+#define ALIGNMENT            (sizeof (void *))
+#define alignment(_address)  (gsize)_address%ALIGNMENT
+#define align(_ptr)          _ptr += (( alignment(_ptr) == 0) ? 0 : ALIGNMENT-alignment(_ptr))
 
 /* Registry saving */
 
+#ifdef G_OS_WIN32
+/* On win32, we can't use g_mkstmp(), because of cross-DLL file I/O problems.
+ * So, we just create the entire binary registry in memory, then write it out
+ * with g_file_set_contents(), which creates a temporary file internally
+ */
+
+typedef struct BinaryRegistryCache
+{
+  const char *location;
+  guint8 *mem;
+  gssize len;
+} BinaryRegistryCache;
+
+static BinaryRegistryCache *
+gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
+{
+  BinaryRegistryCache *cache = g_new0 (BinaryRegistryCache, 1);
+  cache->location = location;
+  return cache;
+}
+
+static int
+gst_registry_binary_cache_write (GstRegistry * registry,
+    BinaryRegistryCache * cache, unsigned long offset,
+    const void *data, int length)
+{
+  cache->len = MAX (offset + length, cache->len);
+  cache->mem = g_realloc (cache->mem, cache->len);
+
+  memcpy (cache->mem + offset, data, length);
+
+  return length;
+}
+
+static gboolean
+gst_registry_binary_cache_finish (GstRegistry * registry,
+    BinaryRegistryCache * cache, gboolean success)
+{
+  gboolean ret = TRUE;
+  GError *error = NULL;
+  if (!g_file_set_contents (cache->location, (const gchar *) cache->mem,
+          cache->len, &error)) {
+    /* Probably the directory didn't exist; create it */
+    gchar *dir;
+    dir = g_path_get_dirname (cache->location);
+    g_mkdir_with_parents (dir, 0777);
+    g_free (dir);
+
+    g_error_free (error);
+    error = NULL;
+
+    if (!g_file_set_contents (cache->location, (const gchar *) cache->mem,
+            cache->len, &error)) {
+      GST_ERROR ("Failed to write to cache file: %s", error->message);
+      g_error_free (error);
+      ret = FALSE;
+    }
+  }
+
+  g_free (cache->mem);
+  g_free (cache);
+  return ret;
+}
+
+#else
+typedef struct BinaryRegistryCache
+{
+  const char *location;
+  char *tmp_location;
+  unsigned long currentoffset;
+} BinaryRegistryCache;
+
+static BinaryRegistryCache *
+gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
+{
+  BinaryRegistryCache *cache = g_new0 (BinaryRegistryCache, 1);
+
+  cache->location = location;
+  cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
+  registry->cache_file = g_mkstemp (cache->tmp_location);
+  if (registry->cache_file == -1) {
+    gchar *dir;
+
+    /* oops, I bet the directory doesn't exist */
+    dir = g_path_get_dirname (location);
+    g_mkdir_with_parents (dir, 0777);
+    g_free (dir);
+
+    /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
+    g_free (cache->tmp_location);
+    cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
+    registry->cache_file = g_mkstemp (cache->tmp_location);
+
+    if (registry->cache_file == -1) {
+      GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
+      g_free (cache->tmp_location);
+      g_free (cache);
+      return NULL;
+    }
+  }
+
+  return cache;
+}
+
+static int
+gst_registry_binary_cache_write (GstRegistry * registry,
+    BinaryRegistryCache * cache, unsigned long offset,
+    const void *data, int length)
+{
+  long written;
+  if (offset != cache->currentoffset) {
+    if (lseek (registry->cache_file, offset, SEEK_SET) != 0) {
+      GST_ERROR ("Seeking to new offset failed");
+      return FALSE;
+    }
+    cache->currentoffset = offset;
+  }
+
+  written = write (registry->cache_file, data, length);
+  if (written != length) {
+    GST_ERROR ("Failed to write to cache file");
+  }
+  cache->currentoffset += written;
+
+  return written;
+}
+
+static gboolean
+gst_registry_binary_cache_finish (GstRegistry * registry,
+    BinaryRegistryCache * cache, gboolean success)
+{
+  /* only fsync if we're actually going to use and rename the file below */
+  if (success && fsync (registry->cache_file) < 0)
+    goto fsync_failed;
+
+  if (close (registry->cache_file) < 0)
+    goto close_failed;
+
+  if (success) {
+    /* Only do the rename if we wrote the entire file successfully */
+    if (g_rename (cache->tmp_location, cache->location) < 0)
+      goto rename_failed;
+  }
+
+  g_free (cache->tmp_location);
+  g_free (cache);
+  GST_INFO ("Wrote binary registry cache");
+  return TRUE;
+
+/* ERRORS */
+fail_after_close:
+  {
+    g_unlink (cache->tmp_location);
+    g_free (cache->tmp_location);
+    g_free (cache);
+    return FALSE;
+  }
+fsync_failed:
+  {
+    GST_ERROR ("fsync() failed: %s", g_strerror (errno));
+    goto fail_after_close;
+  }
+close_failed:
+  {
+    GST_ERROR ("close() failed: %s", g_strerror (errno));
+    goto fail_after_close;
+  }
+rename_failed:
+  {
+    GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
+    goto fail_after_close;
+  }
+}
+#endif
+
 /*
- * gst_registry_binary_write:
+ * gst_registry_binary_write_chunk:
  *
  * Write from a memory location to the registry cache file
  *
  * Returns: %TRUE for success
  */
 inline static gboolean
-gst_registry_binary_write (GstRegistry * registry, const void *mem,
+gst_registry_binary_write_chunk (GstRegistry * registry,
+    BinaryRegistryCache * cache, const void *mem,
     const gssize size, unsigned long *file_position, gboolean align)
 {
-#if !GST_HAVE_UNALIGNED_ACCESS
-  gchar padder[] = { 0, 0, 0, 0 };
+  gchar padder[ALIGNMENT] = { 0, };
   int padsize = 0;
 
   /* Padding to insert the struct that requiere word alignment */
-  if ((align) && (alignment32 (*file_position) != 0)) {
-    padsize = 4 - alignment32 (*file_position);
-    if (write (registry->cache_file, padder, padsize) != padsize) {
+  if ((align) && (alignment (*file_position) != 0)) {
+    padsize = ALIGNMENT - alignment (*file_position);
+    if (gst_registry_binary_cache_write (registry, cache, *file_position,
+            padder, padsize) != padsize) {
       GST_ERROR ("Failed to write binary registry padder");
       return FALSE;
     }
-    *file_position = *file_position + padsize;
+    *file_position += padsize;
   }
-#endif
 
-  if (write (registry->cache_file, mem, size) != size) {
+  if (gst_registry_binary_cache_write (registry, cache, *file_position,
+          mem, size) != size) {
     GST_ERROR ("Failed to write binary registry element");
     return FALSE;
   }
-  *file_position = *file_position + size;
+
+  *file_position += size;
+
   return TRUE;
 }
 
@@ -143,12 +344,16 @@
 inline static gboolean
 gst_registry_binary_initialize_magic (GstBinaryRegistryMagic * m)
 {
+  memset (m, 0, sizeof (GstBinaryRegistryMagic));
+
   if (!strncpy (m->magic, GST_MAGIC_BINARY_REGISTRY_STR,
           GST_MAGIC_BINARY_REGISTRY_LEN)
-      || !strncpy (m->version, GST_MAJORMINOR, GST_MAGIC_BINARY_VERSION_LEN)) {
+      || !strncpy (m->version, GST_MAGIC_BINARY_VERSION_STR,
+          GST_MAGIC_BINARY_VERSION_LEN)) {
     GST_ERROR ("Failed to write magic to the registry magic structure");
     return FALSE;
   }
+
   return TRUE;
 }
 
@@ -165,6 +370,11 @@
 {
   GstBinaryChunk *chunk;
 
+  if (G_UNLIKELY (str == NULL)) {
+    GST_ERROR ("unexpected NULL string in plugin or plugin feature data");
+    str = "";
+  }
+
   chunk = g_malloc (sizeof (GstBinaryChunk));
   chunk->data = (gpointer) str;
   chunk->size = strlen ((gchar *) chunk->data) + 1;
@@ -231,7 +441,7 @@
   GstBinaryPadTemplate *pt;
   GstBinaryChunk *chk;
 
-  pt = g_malloc (sizeof (GstBinaryPadTemplate));
+  pt = g_malloc0 (sizeof (GstBinaryPadTemplate));
   chk = gst_registry_binary_make_data (pt, sizeof (GstBinaryPadTemplate));
 
   pt->presence = template->presence;
@@ -272,7 +482,7 @@
     GstBinaryElementFactory *ef;
     GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
 
-    ef = g_malloc (sizeof (GstBinaryElementFactory));
+    ef = g_malloc0 (sizeof (GstBinaryElementFactory));
     chk = gst_registry_binary_make_data (ef, sizeof (GstBinaryElementFactory));
     ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0;
     pf = (GstBinaryPluginFeature *) ef;
@@ -285,7 +495,7 @@
     GST_DEBUG ("Saved %d Interfaces", ef->ninterfaces);
     /* save uritypes */
     if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
-      if (factory->uri_protocols) {
+      if (factory->uri_protocols && *factory->uri_protocols) {
         GstBinaryChunk *subchk;
         gchar **protocol;
 
@@ -326,13 +536,8 @@
   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
     GstBinaryTypeFindFactory *tff;
     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
-    gchar *str;
 
-    /* we copy the caps here so we can simplify them before saving. This is a lot
-     * faster when loading them later on */
-    GstCaps *copy = gst_caps_copy (factory->caps);
-
-    tff = g_malloc (sizeof (GstBinaryTypeFindFactory));
+    tff = g_malloc0 (sizeof (GstBinaryTypeFindFactory));
     chk =
         gst_registry_binary_make_data (tff, sizeof (GstBinaryTypeFindFactory));
     tff->nextensions = 0;
@@ -346,24 +551,31 @@
       }
     }
     /* save caps */
-    gst_caps_do_simplify (copy);
-    str = gst_caps_to_string (copy);
-    gst_caps_unref (copy);
-    gst_registry_binary_save_string (list, str);
-  }
-#ifndef GST_DISABLE_INDEX
-  else if (GST_IS_INDEX_FACTORY (feature)) {
+    if (factory->caps) {
+      GstCaps *copy = gst_caps_copy (factory->caps);
+      gchar *str;
+
+      /* we copy the caps here so we can simplify them
+       * before saving. This is a lot faster when loading
+       * them later on */
+      gst_caps_do_simplify (copy);
+      str = gst_caps_to_string (copy);
+      gst_caps_unref (copy);
+      gst_registry_binary_save_string (list, str);
+    } else {
+      gst_registry_binary_save_const_string (list, "");
+    }
+
+  } else if (GST_IS_INDEX_FACTORY (feature)) {
     GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
 
-    pf = g_malloc (sizeof (GstBinaryPluginFeature));
+    pf = g_malloc0 (sizeof (GstBinaryPluginFeature));
     chk = gst_registry_binary_make_data (pf, sizeof (GstBinaryPluginFeature));
     pf->rank = feature->rank;
 
     /* pack element factory strings */
     gst_registry_binary_save_const_string (list, factory->longdesc);
-  }
-#endif
-  else {
+  } else {
     GST_WARNING ("unhandled feature type '%s'", type_name);
   }
 
@@ -385,6 +597,38 @@
   return FALSE;
 }
 
+static gboolean
+gst_registry_binary_save_plugin_dep (GList ** list, GstPluginDep * dep)
+{
+  GstBinaryDep *ed;
+  GstBinaryChunk *chk;
+  gchar **s;
+
+  ed = g_new0 (GstBinaryDep, 1);
+  chk = gst_registry_binary_make_data (ed, sizeof (GstBinaryDep));
+
+  ed->flags = dep->flags;
+  ed->n_env_vars = 0;
+  ed->n_paths = 0;
+  ed->n_names = 0;
+
+  ed->env_hash = dep->env_hash;
+  ed->stat_hash = dep->stat_hash;
+
+  for (s = dep->env_vars; s != NULL && *s != NULL; ++s, ++ed->n_env_vars)
+    gst_registry_binary_save_string (list, g_strdup (*s));
+
+  for (s = dep->paths; s != NULL && *s != NULL; ++s, ++ed->n_paths)
+    gst_registry_binary_save_string (list, g_strdup (*s));
+
+  for (s = dep->names; s != NULL && *s != NULL; ++s, ++ed->n_names)
+    gst_registry_binary_save_string (list, g_strdup (*s));
+
+  *list = g_list_prepend (*list, chk);
+
+  GST_LOG ("Saved external plugin dependency");
+  return TRUE;
+}
 
 /*
  * gst_registry_binary_save_plugin:
@@ -401,13 +645,23 @@
   GList *plugin_features = NULL;
   GList *walk;
 
-  pe = g_malloc (sizeof (GstBinaryPluginElement));
+  pe = g_malloc0 (sizeof (GstBinaryPluginElement));
   chk = gst_registry_binary_make_data (pe, sizeof (GstBinaryPluginElement));
 
   pe->file_size = plugin->file_size;
   pe->file_mtime = plugin->file_mtime;
+  pe->n_deps = 0;
   pe->nfeatures = 0;
 
+  /* pack external deps */
+  for (walk = plugin->priv->deps; walk != NULL; walk = walk->next) {
+    if (!gst_registry_binary_save_plugin_dep (list, walk->data)) {
+      GST_ERROR ("Could not save external plugin dependency, aborting.");
+      goto fail;
+    }
+    ++pe->n_deps;
+  }
+
   /* pack plugin features */
   plugin_features =
       gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name);
@@ -419,11 +673,19 @@
       goto fail;
     }
   }
-  GST_DEBUG ("Save plugin '%s' with %d features", plugin->desc.name,
+  GST_DEBUG ("Save plugin '%s' with %d feature(s)", plugin->desc.name,
       pe->nfeatures);
 
   gst_plugin_feature_list_free (plugin_features);
 
+  /* pack cache data */
+  if (plugin->priv->cache_data) {
+    gchar *cache_str = gst_structure_to_string (plugin->priv->cache_data);
+    gst_registry_binary_save_string (list, cache_str);
+  } else {
+    gst_registry_binary_save_const_string (list, "");
+  }
+
   /* pack plugin element strings */
   gst_registry_binary_save_const_string (list, plugin->desc.origin);
   gst_registry_binary_save_const_string (list, plugin->desc.package);
@@ -448,7 +710,6 @@
   return FALSE;
 }
 
-
 /**
  * gst_registry_binary_write_cache:
  * @registry: a #GstRegistry
@@ -466,47 +727,18 @@
 gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
 {
   GList *walk;
-  gchar *tmp_location;
-  GstBinaryRegistryMagic *magic;
-  GstBinaryChunk *magic_chunk;
+  GstBinaryRegistryMagic magic;
   GList *to_write = NULL;
   unsigned long file_position = 0;
+  BinaryRegistryCache *cache;
 
   GST_INFO ("Building binary registry cache image");
 
   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
-  tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
-  registry->cache_file = g_mkstemp (tmp_location);
-  if (registry->cache_file == -1) {
-    gchar *dir;
 
-    /* oops, I bet the directory doesn't exist */
-    dir = g_path_get_dirname (location);
-    g_mkdir_with_parents (dir, 0777);
-    g_free (dir);
-
-    /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
-    g_free (tmp_location);
-    tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
-    registry->cache_file = g_mkstemp (tmp_location);
-
-    if (registry->cache_file == -1) {
-      GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
-      g_free (tmp_location);
-      return FALSE;
-    }
-  }
-
-  magic = g_malloc (sizeof (GstBinaryRegistryMagic));
-  if (!gst_registry_binary_initialize_magic (magic))
+  if (!gst_registry_binary_initialize_magic (&magic))
     goto fail;
 
-  magic_chunk = g_malloc (sizeof (GstBinaryChunk));
-  magic_chunk->data = magic;
-  magic_chunk->size = sizeof (GstBinaryRegistryMagic);
-  magic_chunk->flags = GST_BINARY_REGISTRY_FLAG_NONE;
-  magic_chunk->align = TRUE;
-
   /* iterate trough the list of plugins and fit them into binary structures */
   for (walk = registry->plugins; walk; walk = g_list_next (walk)) {
     GstPlugin *plugin = GST_PLUGIN (walk->data);
@@ -515,11 +747,9 @@
       continue;
 
     if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
-      int ret;
       struct stat statbuf;
 
-      ret = g_stat (plugin->filename, &statbuf);
-      if ((ret = g_stat (plugin->filename, &statbuf)) < 0 ||
+      if (g_stat (plugin->filename, &statbuf) < 0 ||
           plugin->file_mtime != statbuf.st_mtime ||
           plugin->file_size != statbuf.st_size)
         continue;
@@ -530,66 +760,61 @@
           plugin->filename);
     }
   }
-  to_write = g_list_prepend (to_write, magic_chunk);
 
   GST_INFO ("Writing binary registry cache");
 
+  cache = gst_registry_binary_cache_init (registry, location);
+  if (!cache)
+    goto fail_free_list;
+
+  /* write magic */
+  if (gst_registry_binary_cache_write (registry, cache, file_position,
+          &magic, sizeof (GstBinaryRegistryMagic)) !=
+      sizeof (GstBinaryRegistryMagic)) {
+    GST_ERROR ("Failed to write binary registry magic");
+    goto fail_free_list;
+  }
+  file_position += sizeof (GstBinaryRegistryMagic);
+
   /* write out data chunks */
   for (walk = to_write; walk; walk = g_list_next (walk)) {
     GstBinaryChunk *cur = walk->data;
 
-    if (!gst_registry_binary_write (registry, cur->data, cur->size,
+    if (!gst_registry_binary_write_chunk (registry, cache, cur->data, cur->size,
             &file_position, cur->align)) {
-      if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
-        g_free (cur->data);
-      g_free (cur);
-      g_list_free (to_write);
-      goto fail;
+      goto fail_free_list;
     }
     if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
       g_free (cur->data);
     g_free (cur);
+    walk->data = NULL;
   }
   g_list_free (to_write);
 
-  if (close (registry->cache_file) < 0)
-    goto close_failed;
+  if (!gst_registry_binary_cache_finish (registry, cache, TRUE))
+    return FALSE;
 
-  if (g_file_test (tmp_location, G_FILE_TEST_EXISTS)) {
-#ifdef WIN32
-    g_remove (location);
-#endif
-    if (g_rename (tmp_location, location) < 0)
-      goto rename_failed;
-  } else {
-    /* FIXME: shouldn't we return FALSE here? */
-  }
-
-  g_free (tmp_location);
-  GST_INFO ("Wrote binary registry cache");
   return TRUE;
 
   /* Errors */
-fail:
+fail_free_list:
   {
-    (void) close (registry->cache_file);
+    for (walk = to_write; walk; walk = g_list_next (walk)) {
+      GstBinaryChunk *cur = walk->data;
+
+      if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
+        g_free (cur->data);
+      g_free (cur);
+    }
+    g_list_free (to_write);
+
+    if (cache)
+      (void) gst_registry_binary_cache_finish (registry, cache, FALSE);
     /* fall through */
   }
-fail_after_close:
-  {
-    g_remove (tmp_location);
-    g_free (tmp_location);
-    return FALSE;
-  }
-close_failed:
+fail:
   {
-    GST_ERROR ("close() failed: %s", g_strerror (errno));
-    goto fail_after_close;
-  }
-rename_failed:
-  {
-    GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
-    goto fail_after_close;
+    return FALSE;
   }
 }
 
@@ -600,21 +825,19 @@
  * gst_registry_binary_check_magic:
  *
  * Check GstBinaryRegistryMagic validity.
- * Return FALSE if something is wrong
+ * Return < 0 if something is wrong, -2 means
+ * that just the version of the registry is out of
+ * date, -1 is a general failure.
  */
-static gboolean
-gst_registry_binary_check_magic (gchar ** in)
+static gint
+gst_registry_binary_check_magic (gchar ** in, gsize size)
 {
   GstBinaryRegistryMagic *m;
 
-  align32 (*in);
+  align (*in);
   GST_DEBUG ("Reading/casting for GstBinaryRegistryMagic at address %p", *in);
-  unpack_element (*in, m, GstBinaryRegistryMagic);
+  unpack_element (*in, m, GstBinaryRegistryMagic, (*in + size), fail);
 
-  if (m == NULL || m->magic == NULL || m->version == NULL) {
-    GST_WARNING ("Binary registry magic structure is broken");
-    return FALSE;
-  }
   if (strncmp (m->magic, GST_MAGIC_BINARY_REGISTRY_STR,
           GST_MAGIC_BINARY_REGISTRY_LEN) != 0) {
     GST_WARNING
@@ -624,14 +847,20 @@
         GST_MAGIC_BINARY_REGISTRY_STR[2] & 0xff,
         GST_MAGIC_BINARY_REGISTRY_STR[3] & 0xff, m->magic[0] & 0xff,
         m->magic[1] & 0xff, m->magic[2] & 0xff, m->magic[3] & 0xff);
-    return FALSE;
+    return -1;
   }
-  if (strncmp (m->version, GST_MAJORMINOR, GST_MAGIC_BINARY_VERSION_LEN)) {
+  if (strncmp (m->version, GST_MAGIC_BINARY_VERSION_STR,
+          GST_MAGIC_BINARY_VERSION_LEN)) {
     GST_WARNING ("Binary registry magic version is different : %s != %s",
-        GST_MAJORMINOR, m->version);
-    return FALSE;
+        GST_MAGIC_BINARY_VERSION_STR, m->version);
+    return -2;
   }
-  return TRUE;
+
+  return 0;
+
+fail:
+  GST_WARNING ("Not enough data for binary registry magic structure");
+  return -1;
 }
 
 
@@ -643,27 +872,33 @@
  * Returns: new GstStaticPadTemplate
  */
 static gboolean
-gst_registry_binary_load_pad_template (GstElementFactory * factory, gchar ** in)
+gst_registry_binary_load_pad_template (GstElementFactory * factory, gchar ** in,
+    gchar * end)
 {
   GstBinaryPadTemplate *pt;
-  GstStaticPadTemplate *template;
+  GstStaticPadTemplate *template = NULL;
 
-  align32 (*in);
+  align (*in);
   GST_DEBUG ("Reading/casting for GstBinaryPadTemplate at address %p", *in);
-  unpack_element (*in, pt, GstBinaryPadTemplate);
+  unpack_element (*in, pt, GstBinaryPadTemplate, end, fail);
 
   template = g_new0 (GstStaticPadTemplate, 1);
   template->presence = pt->presence;
   template->direction = pt->direction;
 
   /* unpack pad template strings */
-  unpack_const_string (*in, template->name_template);
-  unpack_string (*in, template->static_caps.string);
+  unpack_const_string (*in, template->name_template, end, fail);
+  unpack_string (*in, template->static_caps.string, end, fail);
 
   __gst_element_factory_add_static_pad_template (factory, template);
   GST_DEBUG ("Added pad_template %s", template->name_template);
 
   return TRUE;
+
+fail:
+  GST_INFO ("Reading pad template failed");
+  g_free (template);
+  return FALSE;
 }
 
 
@@ -676,99 +911,109 @@
  */
 static gboolean
 gst_registry_binary_load_feature (GstRegistry * registry, gchar ** in,
-    const gchar * plugin_name)
+    gchar * end, const gchar * plugin_name)
 {
   GstBinaryPluginFeature *pf = NULL;
-  GstPluginFeature *feature;
+  GstPluginFeature *feature = NULL;
   gchar *type_name = NULL, *str;
   GType type;
   guint i;
 
   /* unpack plugin feature strings */
-  unpack_string (*in, type_name);
+  unpack_string (*in, type_name, end, fail);
 
-  if (!type_name || !*(type_name))
+  if (G_UNLIKELY (!type_name)) {
+    GST_ERROR ("No feature type name");
     return FALSE;
+  }
 
   GST_DEBUG ("Plugin '%s' feature typename : '%s'", plugin_name, type_name);
 
-  if (!(type = g_type_from_name (type_name))) {
+  if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) {
     GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name,
         plugin_name);
+    g_free (type_name);
     return FALSE;
   }
-  if ((feature = g_object_new (type, NULL)) == NULL) {
+  if (G_UNLIKELY ((feature = g_object_new (type, NULL)) == NULL)) {
     GST_ERROR ("Can't create feature from type");
+    g_free (type_name);
     return FALSE;
   }
 
-  if (!GST_IS_PLUGIN_FEATURE (feature)) {
-    GST_ERROR ("typename : '%s' is not a plgin feature", type_name);
+  if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
+    GST_ERROR ("typename : '%s' is not a plugin feature", type_name);
     goto fail;
   }
 
   /* unpack more plugin feature strings */
-  unpack_string (*in, feature->name);
+  unpack_string (*in, feature->name, end, fail);
 
   if (GST_IS_ELEMENT_FACTORY (feature)) {
     GstBinaryElementFactory *ef;
-    GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
+    guint n;
+    GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature);
 
-    align32 (*in);
+    align (*in);
     GST_LOG ("Reading/casting for GstBinaryElementFactory at address %p", *in);
-    unpack_element (*in, ef, GstBinaryElementFactory);
+    unpack_element (*in, ef, GstBinaryElementFactory, end, fail);
     pf = (GstBinaryPluginFeature *) ef;
 
     /* unpack element factory strings */
-    unpack_string (*in, factory->details.longname);
-    unpack_string (*in, factory->details.klass);
-    unpack_string (*in, factory->details.description);
-    unpack_string (*in, factory->details.author);
+    unpack_string (*in, factory->details.longname, end, fail);
+    unpack_string (*in, factory->details.klass, end, fail);
+    unpack_string (*in, factory->details.description, end, fail);
+    unpack_string (*in, factory->details.author, end, fail);
+    n = ef->npadtemplates;
     GST_DEBUG ("Element factory : '%s' with npadtemplates=%d",
-        factory->details.longname, ef->npadtemplates);
+        factory->details.longname, n);
 
     /* load pad templates */
-    for (i = 0; i < ef->npadtemplates; i++) {
-      if (!gst_registry_binary_load_pad_template (factory, in)) {
+    for (i = 0; i < n; i++) {
+      if (G_UNLIKELY (!gst_registry_binary_load_pad_template (factory, in,
+                  end))) {
         GST_ERROR ("Error while loading binary pad template");
         goto fail;
       }
     }
 
     /* load uritypes */
-    if (ef->nuriprotocols) {
-      GST_DEBUG ("Reading %d UriTypes at address %p", ef->nuriprotocols, *in);
+    if (G_UNLIKELY ((n = ef->nuriprotocols))) {
+      GST_DEBUG ("Reading %d UriTypes at address %p", n, *in);
 
-      align32 (*in);
+      align (*in);
       factory->uri_type = *((guint *) * in);
       *in += sizeof (factory->uri_type);
-      //unpack_element(*in, &factory->uri_type, factory->uri_type);
+      /*unpack_element(*in, &factory->uri_type, factory->uri_type, end, fail); */
 
-      factory->uri_protocols = g_new0 (gchar *, ef->nuriprotocols + 1);
-      for (i = 0; i < ef->nuriprotocols; i++) {
-        unpack_string (*in, str);
+      factory->uri_protocols = g_new0 (gchar *, n + 1);
+      for (i = 0; i < n; i++) {
+        unpack_string (*in, str, end, fail);
         factory->uri_protocols[i] = str;
       }
     }
+
     /* load interfaces */
-    GST_DEBUG ("Reading %d Interfaces at address %p", ef->ninterfaces, *in);
-    for (i = 0; i < ef->ninterfaces; i++) {
-      unpack_string (*in, str);
-      __gst_element_factory_add_interface (factory, str);
-      g_free (str);
+    if (G_UNLIKELY ((n = ef->ninterfaces))) {
+      GST_DEBUG ("Reading %d Interfaces at address %p", n, *in);
+      for (i = 0; i < n; i++) {
+        unpack_string (*in, str, end, fail);
+        __gst_element_factory_add_interface (factory, str);
+        g_free (str);
+      }
     }
   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
     GstBinaryTypeFindFactory *tff;
     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
 
-    align32 (*in);
+    align (*in);
     GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in);
-    unpack_element (*in, tff, GstBinaryTypeFindFactory);
+    unpack_element (*in, tff, GstBinaryTypeFindFactory, end, fail);
     pf = (GstBinaryPluginFeature *) tff;
 
     /* load caps */
-    unpack_string (*in, str);
-    factory->caps = gst_caps_from_string (str);
+    unpack_string (*in, str, end, fail);
+    factory->caps = (str && *str) ? gst_caps_from_string (str) : NULL;
     g_free (str);
     /* load extensions */
     if (tff->nextensions) {
@@ -776,23 +1021,23 @@
           tff->nextensions, *in);
       factory->extensions = g_new0 (gchar *, tff->nextensions + 1);
       for (i = 0; i < tff->nextensions; i++) {
-        unpack_string (*in, str);
+        unpack_string (*in, str, end, fail);
         factory->extensions[i] = str;
       }
     }
-  }
-#ifndef GST_DISABLE_INDEX
-  else if (GST_IS_INDEX_FACTORY (feature)) {
+  } else if (GST_IS_INDEX_FACTORY (feature)) {
     GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
 
-    align32 (*in);
+    align (*in);
     GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in);
-    unpack_element (*in, pf, GstBinaryPluginFeature);
+    unpack_element (*in, pf, GstBinaryPluginFeature, end, fail);
 
     /* unpack index factory strings */
-    unpack_string (*in, factory->longdesc);
+    unpack_string (*in, factory->longdesc, end, fail);
+  } else {
+    GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
+    goto fail;
   }
-#endif
 
   feature->rank = pf->rank;
 
@@ -807,14 +1052,76 @@
 
   /* Errors */
 fail:
+  GST_INFO ("Reading plugin feature failed");
   g_free (type_name);
-  if (GST_IS_OBJECT (feature))
-    gst_object_unref (feature);
-  else
-    g_object_unref (feature);
+  if (feature) {
+    if (GST_IS_OBJECT (feature))
+      gst_object_unref (feature);
+    else
+      g_object_unref (feature);
+  }
   return FALSE;
 }
 
+static gchar **
+gst_registry_binary_load_plugin_dep_strv (gchar ** in, gchar * end, guint n)
+{
+  gchar **arr;
+
+  if (n == 0)
+    return NULL;
+
+  arr = g_new0 (gchar *, n + 1);
+  while (n > 0) {
+    unpack_string (*in, arr[n - 1], end, fail);
+    --n;
+  }
+  return arr;
+fail:
+  GST_INFO ("Reading plugin dependency strings failed");
+  return NULL;
+}
+
+static gboolean
+gst_registry_binary_load_plugin_dep (GstPlugin * plugin, gchar ** in,
+    gchar * end)
+{
+  GstPluginDep *dep;
+  GstBinaryDep *d;
+  gchar **s;
+
+  align (*in);
+  GST_LOG_OBJECT (plugin, "Unpacking GstBinaryDep from %p", *in);
+  unpack_element (*in, d, GstBinaryDep, end, fail);
+
+  dep = g_new0 (GstPluginDep, 1);
+
+  dep->env_hash = d->env_hash;
+  dep->stat_hash = d->stat_hash;
+
+  dep->flags = d->flags;
+
+  dep->names = gst_registry_binary_load_plugin_dep_strv (in, end, d->n_names);
+  dep->paths = gst_registry_binary_load_plugin_dep_strv (in, end, d->n_paths);
+  dep->env_vars =
+      gst_registry_binary_load_plugin_dep_strv (in, end, d->n_env_vars);
+
+  plugin->priv->deps = g_list_append (plugin->priv->deps, dep);
+
+  GST_DEBUG_OBJECT (plugin, "Loaded external plugin dependency from registry: "
+      "env_hash: %08x, stat_hash: %08x", dep->env_hash, dep->stat_hash);
+  for (s = dep->env_vars; s != NULL && *s != NULL; ++s)
+    GST_LOG_OBJECT (plugin, " evar: %s", *s);
+  for (s = dep->paths; s != NULL && *s != NULL; ++s)
+    GST_LOG_OBJECT (plugin, " path: %s", *s);
+  for (s = dep->names; s != NULL && *s != NULL; ++s)
+    GST_LOG_OBJECT (plugin, " name: %s", *s);
+
+  return TRUE;
+fail:
+  GST_INFO ("Reading plugin dependency failed");
+  return FALSE;
+}
 
 /*
  * gst_registry_binary_load_plugin:
@@ -824,25 +1131,17 @@
  * GstBinaryPluginElement structure.
  */
 static gboolean
-gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in)
+gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in,
+    gchar * end)
 {
   GstBinaryPluginElement *pe;
   GstPlugin *plugin = NULL;
-  guint i;
-
-  align32 (*in);
-  GST_LOG ("Reading/casting for GstBinaryPluginElement at address %p", *in);
-  unpack_element (*in, pe, GstBinaryPluginElement);
+  gchar *cache_str = NULL;
+  guint i, n;
 
-  if (pe->nfeatures < 0) {
-    GST_ERROR ("The number of feature structure is not valid !");
-    return FALSE;
-  }
-
-  if (pe->file_mtime < 0 || pe->file_size < 0) {
-    GST_ERROR ("Plugin time or file size is not valid !");
-    return FALSE;
-  }
+  align (*in);
+  GST_LOG ("Reading/casting for GstBinaryPluginElement at address %p", *in);
+  unpack_element (*in, pe, GstBinaryPluginElement, end, fail);
 
   plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
 
@@ -852,23 +1151,53 @@
   plugin->file_size = pe->file_size;
 
   /* unpack plugin element strings */
-  unpack_const_string (*in, plugin->desc.name);
-  unpack_string (*in, plugin->desc.description);
-  unpack_string (*in, plugin->filename);
-  unpack_const_string (*in, plugin->desc.version);
-  unpack_const_string (*in, plugin->desc.license);
-  unpack_const_string (*in, plugin->desc.source);
-  unpack_const_string (*in, plugin->desc.package);
-  unpack_const_string (*in, plugin->desc.origin);
-  GST_LOG ("read strings for '%s'", plugin->desc.name);
+  unpack_const_string (*in, plugin->desc.name, end, fail);
+  unpack_string (*in, plugin->desc.description, end, fail);
+  unpack_string (*in, plugin->filename, end, fail);
+  unpack_const_string (*in, plugin->desc.version, end, fail);
+  unpack_const_string (*in, plugin->desc.license, end, fail);
+  unpack_const_string (*in, plugin->desc.source, end, fail);
+  unpack_const_string (*in, plugin->desc.package, end, fail);
+  unpack_const_string (*in, plugin->desc.origin, end, fail);
+  GST_LOG ("read strings for name='%s'", plugin->desc.name);
+  GST_LOG ("  desc.description='%s'", plugin->desc.description);
+  GST_LOG ("  filename='%s'", plugin->filename);
+  GST_LOG ("  desc.version='%s'", plugin->desc.version);
+  GST_LOG ("  desc.license='%s'", plugin->desc.license);
+  GST_LOG ("  desc.source='%s'", plugin->desc.source);
+  GST_LOG ("  desc.package='%s'", plugin->desc.package);
+  GST_LOG ("  desc.origin='%s'", plugin->desc.origin);
+
+  /* unpack cache data */
+  unpack_string (*in, cache_str, end, fail);
+  if (*cache_str) {
+    plugin->priv->cache_data = gst_structure_from_string (cache_str, NULL);
+  }
+  g_free (cache_str);
 
   plugin->basename = g_path_get_basename (plugin->filename);
+
+  /* Takes ownership of plugin */
   gst_registry_add_plugin (registry, plugin);
-  GST_INFO ("Added plugin '%s' plugin with %d features from binary registry",
-      plugin->desc.name, pe->nfeatures);
-  for (i = 0; i < pe->nfeatures; i++) {
-    if (!gst_registry_binary_load_feature (registry, in, plugin->desc.name)) {
+  n = pe->nfeatures;
+  GST_DEBUG ("Added plugin '%s' plugin with %d features from binary registry",
+      plugin->desc.name, n);
+
+  /* Load plugin features */
+  for (i = 0; i < n; i++) {
+    if (G_UNLIKELY (!gst_registry_binary_load_feature (registry, in, end,
+                plugin->desc.name))) {
       GST_ERROR ("Error while loading binary feature");
+      gst_registry_remove_plugin (registry, plugin);
+      goto fail;
+    }
+  }
+
+  /* Load external plugin dependencies */
+  for (i = 0; i < pe->n_deps; ++i) {
+    if (G_UNLIKELY (!gst_registry_binary_load_plugin_dep (plugin, in, end))) {
+      GST_ERROR_OBJECT (plugin, "Could not read external plugin dependency");
+      gst_registry_remove_plugin (registry, plugin);
       goto fail;
     }
   }
@@ -877,7 +1206,7 @@
 
   /* Errors */
 fail:
-  gst_object_unref (plugin);
+  GST_INFO ("Reading plugin failed");
   return FALSE;
 }
 
@@ -894,30 +1223,32 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 gboolean
 gst_registry_binary_read_cache (GstRegistry * registry, const char *location)
 {
   GMappedFile *mapped = NULL;
-  GTimer *timer = NULL;
   gchar *contents = NULL;
   gchar *in = NULL;
-  gdouble seconds;
   gsize size;
   GError *err = NULL;
   gboolean res = FALSE;
+  gint check_magic_result;
+#ifndef GST_DISABLE_GST_DEBUG
+  GTimer *timer = NULL;
+  gdouble seconds;
+#endif
 
   /* make sure these types exist */
   GST_TYPE_ELEMENT_FACTORY;
   GST_TYPE_TYPE_FIND_FACTORY;
-#ifndef GST_DISABLE_INDEX
   GST_TYPE_INDEX_FACTORY;
+
+#ifndef GST_DISABLE_GST_DEBUG
+  timer = g_timer_new ();
 #endif
 
-  timer = g_timer_new ();
-
   mapped = g_mapped_file_new (location, FALSE, &err);
-  if (err != NULL) {
+  if (G_UNLIKELY (err != NULL)) {
     GST_INFO ("Unable to mmap file %s : %s", location, err->message);
     g_error_free (err);
     err = NULL;
@@ -925,63 +1256,75 @@
     g_file_get_contents (location, &contents, &size, &err);
     if (err != NULL) {
       GST_INFO ("Unable to read file %s : %s", location, err->message);
+#ifndef GST_DISABLE_GST_DEBUG
       g_timer_destroy (timer);
+#endif
       g_error_free (err);
       return FALSE;
     }
   } else {
-    if ((contents = g_mapped_file_get_contents (mapped)) == NULL) {
+    if (G_UNLIKELY ((contents = g_mapped_file_get_contents (mapped)) == NULL)) {
       GST_ERROR ("Can't load file %s : %s", location, g_strerror (errno));
       goto Error;
     }
     /* check length for header */
     size = g_mapped_file_get_length (mapped);
   }
+
   /* in is a cursor pointer, we initialize it with the begin of registry and is updated on each read */
   in = contents;
   GST_DEBUG ("File data at address %p", in);
-  if (size < sizeof (GstBinaryRegistryMagic)) {
+  if (G_UNLIKELY (size < sizeof (GstBinaryRegistryMagic))) {
     GST_ERROR ("No or broken registry header");
     goto Error;
   }
+
   /* check if header is valid */
-  if (!gst_registry_binary_check_magic (&in)) {
-    GST_ERROR
-        ("Binary registry type not recognized (invalid magic) for file at %s",
-        location);
+  if (G_UNLIKELY ((check_magic_result =
+              gst_registry_binary_check_magic (&in, size)) < 0)) {
+
+    if (check_magic_result == -1)
+      GST_ERROR
+          ("Binary registry type not recognized (invalid magic) for file at %s",
+          location);
     goto Error;
   }
 
   /* check if there are plugins in the file */
-
-  if (!(((gsize) in + sizeof (GstBinaryPluginElement)) <
-          (gsize) contents + size)) {
+  if (G_UNLIKELY (!(((gsize) in + sizeof (GstBinaryPluginElement)) <
+              (gsize) contents + size))) {
     GST_INFO ("No binary plugins structure to read");
     /* empty file, this is not an error */
   } else {
+    gchar *end = contents + size;
+    /* read as long as we still have space for a GstBinaryPluginElement */
     for (;
         ((gsize) in + sizeof (GstBinaryPluginElement)) <
         (gsize) contents + size;) {
       GST_DEBUG ("reading binary registry %" G_GSIZE_FORMAT "(%x)/%"
           G_GSIZE_FORMAT, (gsize) in - (gsize) contents,
           (guint) ((gsize) in - (gsize) contents), size);
-      if (!gst_registry_binary_load_plugin (registry, &in)) {
-        GST_ERROR ("Problem while reading binary registry");
+      if (!gst_registry_binary_load_plugin (registry, &in, end)) {
+        GST_ERROR ("Problem while reading binary registry %s", location);
         goto Error;
       }
     }
   }
 
+#ifndef GST_DISABLE_GST_DEBUG
   g_timer_stop (timer);
   seconds = g_timer_elapsed (timer, NULL);
+#endif
 
   GST_INFO ("loaded %s in %lf seconds", location, seconds);
 
   res = TRUE;
-  /* TODO: once we re-use the pointers to registry contents return here */
+  /* TODO: once we re-use the pointers to registry contents, return here */
 
 Error:
+#ifndef GST_DISABLE_GST_DEBUG
   g_timer_destroy (timer);
+#endif
   if (mapped) {
     g_mapped_file_free (mapped);
   } else {
--- a/gstreamer_core/gst/gstregistrybinary.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstregistrybinary.h	Fri Apr 16 15:15:52 2010 +0300
@@ -45,6 +45,16 @@
  * length of the header tag.
  */
 #define GST_MAGIC_BINARY_REGISTRY_LEN (4)
+
+/*
+ * GST_MAGIC_BINARY_VERSION_STR:
+ *
+ * The current version of the binary registry format.
+ * This _must_ be updated whenever the registry format changes,
+ * we currently use the core version where this change happened.
+ */
+#define GST_MAGIC_BINARY_VERSION_STR ("0.10.23.1")
+
 /*
  * GST_MAGIC_BINARY_VERSION_LEN:
  *
@@ -94,9 +104,23 @@
   gulong file_size;
   gulong file_mtime;
 
+  guint n_deps;
+
   guint nfeatures;
 } GstBinaryPluginElement;
 
+/* GstBinaryDep:
+ */
+typedef struct _GstBinaryDep
+{
+  guint flags;
+  guint n_env_vars;
+  guint n_paths;
+  guint n_names;
+
+  guint env_hash;
+  guint stat_hash;
+} GstBinaryDep;
 
 /*
  * GstBinaryPluginFeature:
--- a/gstreamer_core/gst/gstregistryxml.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,964 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *                    2005 David A. Schleef <ds@schleef.org>
- *
- * gstregistryxml.c: GstRegistry object, support routines
- *
- * This library is free software; you can redistribute it and/or
- * modify it ulnder 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <fcntl.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <gst/gst_private.h>
-#include <gst/gstelement.h>
-#include <gst/gsttypefind.h>
-#include <gst/gsttypefindfactory.h>
-#include <gst/gsturi.h>
-#include <gst/gstinfo.h>
-#include <gst/gstenumtypes.h>
-#include <gst/gstregistry.h>
-
-#include <libxml/xmlreader.h>
-
-#include "glib-compat-private.h"
-#include <glib/gstdio.h>
-
-#define BLOCK_SIZE 1024*10
-
-#define GST_CAT_DEFAULT GST_CAT_REGISTRY
-
-#define CLASS(registry)  GST_XML_REGISTRY_CLASS (G_OBJECT_GET_CLASS (registry))
-
-static gboolean
-gst_registry_save (GstRegistry * registry, gchar * format, ...)
-{
-  va_list var_args;
-  gsize written, len;
-  gboolean ret;
-  char *str;
-
-  va_start (var_args, format);
-  str = g_strdup_vprintf (format, var_args);
-  va_end (var_args);
-
-  len = strlen (str);
-
-  written = write (registry->cache_file, str, len);
-
-  if (len == written)
-    ret = TRUE;
-  else {
-    ret = FALSE;
-    GST_ERROR ("Failed to write registry to temporary file: %s",
-        g_strerror (errno));
-  }
-
-  g_free (str);
-
-  return ret;
-}
-
-static void
-add_to_char_array (gchar *** array, gchar * value)
-{
-  gchar **new;
-  gchar **old = *array;
-  gint i = 0;
-
-  /* expensive, but cycles are cheap... */
-  if (old)
-    while (old[i])
-      i++;
-  new = g_new0 (gchar *, i + 2);
-  new[i] = value;
-  while (i > 0) {
-    i--;
-    new[i] = old[i];
-  }
-  g_free (old);
-  *array = new;
-}
-
-/* read a string and copy it into the given location */
-static gboolean
-read_string (xmlTextReaderPtr reader, gchar ** write_to, gboolean allow_blank)
-{
-  int depth = xmlTextReaderDepth (reader);
-  gboolean found = FALSE;
-
-  while (xmlTextReaderRead (reader) == 1) {
-    if (xmlTextReaderDepth (reader) == depth) {
-      if (allow_blank && !found &&
-          xmlTextReaderNodeType (reader) == XML_READER_TYPE_END_ELEMENT) {
-        /* Allow blank strings */
-        *write_to = g_strdup ("");
-        found = TRUE;
-      }
-      return found;
-    }
-    if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_TEXT) {
-      xmlChar *value;
-
-      if (found)
-        return FALSE;
-
-      value = xmlTextReaderValue (reader);
-      *write_to = g_strdup ((gchar *) value);
-      xmlFree (value);
-
-      found = TRUE;
-    }
-  }
-  return FALSE;
-}
-
-static gboolean
-read_const_interned_string (xmlTextReaderPtr reader, const gchar ** write_to,
-    gboolean allow_blank)
-{
-  gchar *s = NULL;
-
-  if (!read_string (reader, &s, allow_blank))
-    return FALSE;
-
-  *write_to = g_intern_string (s);
-  g_free (s);
-  return TRUE;
-}
-
-static gboolean
-read_uint (xmlTextReaderPtr reader, guint * write_to)
-{
-  int depth = xmlTextReaderDepth (reader);
-  gboolean found = FALSE;
-
-  while (xmlTextReaderRead (reader) == 1) {
-    if (xmlTextReaderDepth (reader) == depth)
-      return found;
-    if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_TEXT) {
-      gchar *ret;
-      const gchar *s;
-
-      if (found) {
-        GST_DEBUG ("failed to read uint, multiple text nodes");
-        return FALSE;
-      }
-      s = (const gchar *) xmlTextReaderConstValue (reader);
-      *write_to = strtol (s, &ret, 0);
-      if (s == ret) {
-        GST_DEBUG ("failed to read uint, text didn't convert to int");
-        return FALSE;
-      }
-      found = TRUE;
-    }
-  }
-  GST_DEBUG ("failed to read uint, no text node");
-  return FALSE;
-}
-
-static gboolean
-read_enum (xmlTextReaderPtr reader, GType enum_type, guint * write_to)
-{
-  int depth = xmlTextReaderDepth (reader);
-  gboolean found = FALSE;
-
-  if (*write_to)
-    return FALSE;
-  while (xmlTextReaderRead (reader) == 1) {
-    if (xmlTextReaderDepth (reader) == depth)
-      return found;
-    if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_TEXT) {
-      GEnumClass *enum_class;
-      GEnumValue *value;
-
-      if (found)
-        return FALSE;
-      enum_class = g_type_class_ref (enum_type);
-      if (!enum_class)
-        return FALSE;
-      value =
-          g_enum_get_value_by_nick (enum_class,
-          (gchar *) xmlTextReaderConstValue (reader));
-      if (value) {
-        *write_to = value->value;
-        found = TRUE;
-      }
-      g_type_class_unref (enum_class);
-    }
-  }
-  return FALSE;
-}
-
-static GstStaticPadTemplate *
-load_pad_template (xmlTextReaderPtr reader)
-{
-  int ret;
-  int depth = xmlTextReaderDepth (reader);
-  const gchar *name = NULL;
-  gchar *caps_str = NULL;
-  guint direction = 0, presence = 0;
-
-  while ((ret = xmlTextReaderRead (reader)) == 1) {
-    if (xmlTextReaderDepth (reader) == depth) {
-      GstStaticPadTemplate *template;
-
-      template = g_new0 (GstStaticPadTemplate, 1);
-      template->name_template = name;   /* must be an interned string! */
-      template->presence = presence;
-      template->direction = direction;
-      template->static_caps.string = caps_str;
-
-      return template;
-    }
-    if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT &&
-        xmlTextReaderDepth (reader) == depth + 1) {
-      const gchar *tag = (gchar *) xmlTextReaderConstName (reader);
-
-      if (g_str_equal (tag, "nametemplate")) {
-        read_const_interned_string (reader, &name, FALSE);
-      } else if (g_str_equal (tag, "direction")) {
-        read_enum (reader, GST_TYPE_PAD_DIRECTION, &direction);
-      } else if (g_str_equal (tag, "presence")) {
-        read_enum (reader, GST_TYPE_PAD_PRESENCE, &presence);
-      } else if (!strncmp (tag, "caps", 4)) {
-        read_string (reader, &caps_str, FALSE);
-      }
-    }
-  }
-  g_free (caps_str);
-
-  return NULL;
-}
-
-static GstPluginFeature *
-load_feature (xmlTextReaderPtr reader)
-{
-  int ret;
-  int depth;
-  xmlChar *feature_name;
-  GstPluginFeature *feature;
-  GType type;
-
-  depth = xmlTextReaderDepth (reader);
-  feature_name = xmlTextReaderGetAttribute (reader, BAD_CAST "typename");
-
-  GST_LOG ("loading feature '%s'", GST_STR_NULL ((const char *) feature_name));
-
-  if (!feature_name)
-    return NULL;
-
-  type = g_type_from_name ((const char *) feature_name);
-  xmlFree (feature_name);
-  feature_name = NULL;
-
-  if (!type) {
-    return NULL;
-  }
-  feature = g_object_new (type, NULL);
-  if (!feature) {
-    return NULL;
-  }
-  if (!GST_IS_PLUGIN_FEATURE (feature)) {
-    /* don't really know what it is */
-    if (GST_IS_OBJECT (feature))
-      gst_object_unref (feature);
-    else
-      g_object_unref (feature);
-    return NULL;
-  }
-  while ((ret = xmlTextReaderRead (reader)) == 1) {
-    if (xmlTextReaderDepth (reader) == depth) {
-      GST_LOG ("loaded feature %p with name %s", feature, feature->name);
-      return feature;
-    }
-    if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT &&
-        xmlTextReaderDepth (reader) == depth + 1) {
-      const gchar *tag = (gchar *) xmlTextReaderConstName (reader);
-
-      if (g_str_equal (tag, "name"))
-        read_string (reader, &feature->name, FALSE);
-      else if (g_str_equal (tag, "rank"))
-        read_uint (reader, &feature->rank);
-
-      if (GST_IS_ELEMENT_FACTORY (feature)) {
-        GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature);
-
-        if (g_str_equal (tag, "longname")) {
-          int ret;
-
-          ret = read_string (reader, &factory->details.longname, TRUE);
-          GST_LOG ("longname ret=%d, name=%s", ret, factory->details.longname);
-        } else if (g_str_equal (tag, "class")) {
-          read_string (reader, &factory->details.klass, TRUE);
-        } else if (g_str_equal (tag, "description")) {
-          read_string (reader, &factory->details.description, TRUE);
-        } else if (g_str_equal (tag, "author")) {
-          read_string (reader, &factory->details.author, TRUE);
-        } else if (g_str_equal (tag, "uri_type")) {
-          gchar *s = NULL;
-
-          if (read_string (reader, &s, FALSE)) {
-            if (g_ascii_strncasecmp (s, "sink", 4) == 0) {
-              factory->uri_type = GST_URI_SINK;
-            } else if (g_ascii_strncasecmp (s, "source", 5) == 0) {
-              factory->uri_type = GST_URI_SRC;
-            }
-            g_free (s);
-          }
-        } else if (g_str_equal (tag, "uri_protocol")) {
-          gchar *s = NULL;
-
-          if (read_string (reader, &s, FALSE))
-            add_to_char_array (&factory->uri_protocols, s);
-        } else if (g_str_equal (tag, "interface")) {
-          gchar *s = NULL;
-
-          if (read_string (reader, &s, FALSE)) {
-            __gst_element_factory_add_interface (factory, s);
-            /* add_interface strdup's s */
-            g_free (s);
-          }
-        } else if (g_str_equal (tag, "padtemplate")) {
-          GstStaticPadTemplate *template = load_pad_template (reader);
-
-          if (template) {
-            GST_LOG ("adding template %s to factory %s",
-                GST_STR_NULL (GST_PAD_TEMPLATE_NAME_TEMPLATE (template)),
-                GST_PLUGIN_FEATURE_NAME (feature));
-            __gst_element_factory_add_static_pad_template (factory, template);
-          }
-        }
-      } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
-        GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
-
-        if (g_str_equal (tag, "extension")) {
-          gchar *s = NULL;
-
-          if (read_string (reader, &s, TRUE))
-            add_to_char_array (&factory->extensions, s);
-        } else if (g_str_equal (tag, "caps")) {
-          gchar *s = NULL;
-
-          if (read_string (reader, &s, FALSE)) {
-            factory->caps = gst_caps_from_string (s);
-            g_free (s);
-          }
-        }
-#ifndef GST_DISABLE_INDEX
-      } else if (GST_IS_INDEX_FACTORY (feature)) {
-        GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
-
-        if (g_str_equal (tag, "longdesc"))
-          read_string (reader, &factory->longdesc, TRUE);
-#endif
-      }
-    }
-  }
-
-  GST_WARNING ("Error reading feature from registry: registry corrupt?");
-  return NULL;
-}
-
-static GstPlugin *
-load_plugin (xmlTextReaderPtr reader, GList ** feature_list)
-{
-  int ret;
-  GstPlugin *plugin;
-
-  *feature_list = NULL;
-
-  GST_LOG ("creating new plugin and parsing");
-
-  plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
-
-  plugin->flags |= GST_PLUGIN_FLAG_CACHED;
-  while ((ret = xmlTextReaderRead (reader)) == 1) {
-    if (xmlTextReaderDepth (reader) == 1) {
-      return plugin;
-    }
-    if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT &&
-        xmlTextReaderDepth (reader) == 2) {
-      const gchar *tag = (gchar *) xmlTextReaderConstName (reader);
-
-      if (g_str_equal (tag, "name")) {
-        int ret;
-
-        ret = read_const_interned_string (reader, &plugin->desc.name, FALSE);
-        GST_LOG ("name ret=%d, name=%s", ret, plugin->desc.name);
-        if (!ret)
-          break;
-      } else if (g_str_equal (tag, "description")) {
-        if (!read_string (reader, &plugin->desc.description, TRUE)) {
-          GST_WARNING ("description field was invalid in registry");
-          break;
-        }
-        GST_LOG ("description %s", plugin->desc.description);
-      } else if (g_str_equal (tag, "filename")) {
-        if (!read_string (reader, &plugin->filename, FALSE)) {
-          GST_WARNING ("filename field was invalid in registry");
-          break;
-        }
-        GST_LOG ("filename %s", plugin->filename);
-        plugin->basename = g_path_get_basename (plugin->filename);
-      } else if (g_str_equal (tag, "version")) {
-        if (!read_const_interned_string (reader, &plugin->desc.version, TRUE)) {
-          GST_WARNING ("version field was invalid in registry");
-          break;
-        }
-        GST_LOG ("version %s", plugin->desc.version);
-      } else if (g_str_equal (tag, "license")) {
-        if (!read_const_interned_string (reader, &plugin->desc.license, TRUE)) {
-          GST_WARNING ("license field was invalid in registry");
-          break;
-        }
-        GST_LOG ("license %s", plugin->desc.license);
-      } else if (g_str_equal (tag, "source")) {
-        if (!read_const_interned_string (reader, &plugin->desc.source, TRUE)) {
-          GST_WARNING ("source field was invalid in registry");
-          break;
-        }
-        GST_LOG ("source %s", plugin->desc.source);
-      } else if (g_str_equal (tag, "package")) {
-        if (!read_const_interned_string (reader, &plugin->desc.package, TRUE)) {
-          GST_WARNING ("package field was invalid in registry");
-          break;
-        }
-        GST_LOG ("package %s", plugin->desc.package);
-      } else if (g_str_equal (tag, "origin")) {
-        if (!read_const_interned_string (reader, &plugin->desc.origin, TRUE)) {
-          GST_WARNING ("failed to read origin");
-          break;
-        }
-      } else if (g_str_equal (tag, "m32p")) {
-        char *s;
-
-        if (!read_string (reader, &s, FALSE)) {
-          GST_WARNING ("failed to read mtime");
-          break;
-        }
-        plugin->file_mtime = strtol (s, NULL, 0);
-        GST_LOG ("mtime %d", (int) plugin->file_mtime);
-        g_free (s);
-      } else if (g_str_equal (tag, "size")) {
-        unsigned int x;
-
-        if (read_uint (reader, &x)) {
-          plugin->file_size = x;
-          GST_LOG ("file_size %" G_GINT64_FORMAT, (gint64) plugin->file_size);
-        } else {
-          GST_WARNING ("failed to read size");
-        }
-      } else if (g_str_equal (tag, "feature")) {
-        GstPluginFeature *feature = load_feature (reader);
-
-        if (feature) {
-          feature->plugin_name = plugin->desc.name;     /* interned string */
-          *feature_list = g_list_prepend (*feature_list, feature);
-        }
-      } else {
-        GST_WARNING ("unknown tag %s", tag);
-      }
-    }
-  }
-  gst_object_unref (plugin);
-
-  GST_WARNING ("problem reading plugin");
-
-  return NULL;
-}
-
-/**
- * gst_registry_xml_read_cache:
- * @registry: a #GstRegistry
- * @location: a filename
- *
- * Read the contents of the XML cache file at @location into @registry.
- *
- * Returns: %TRUE on success.
- */
-gboolean
-gst_registry_xml_read_cache (GstRegistry * registry, const char *location)
-{
-  GMappedFile *mapped = NULL;
-  GTimer *timer;
-  gdouble seconds;
-  xmlTextReaderPtr reader = NULL;
-  int ret;
-  gboolean in_registry = FALSE;
-  FILE *file = NULL;
-
-  /* make sure these types exist */
-  GST_TYPE_ELEMENT_FACTORY;
-  GST_TYPE_TYPE_FIND_FACTORY;
-#ifndef GST_DISABLE_INDEX
-  GST_TYPE_INDEX_FACTORY;
-#endif
-
-  timer = g_timer_new ();
-
-  mapped = g_mapped_file_new (location, FALSE, NULL);
-  if (mapped) {
-    reader = xmlReaderForMemory (g_mapped_file_get_contents (mapped),
-        g_mapped_file_get_length (mapped), NULL, NULL, 0);
-    if (reader == NULL) {
-      g_mapped_file_free (mapped);
-      mapped = NULL;
-    }
-  }
-
-  if (reader == NULL) {
-    file = fopen (location, "r");
-    if (file == NULL) {
-      g_timer_destroy (timer);
-      return FALSE;
-    }
-
-    reader = xmlReaderForFd (fileno (file), NULL, NULL, 0);
-    if (!reader) {
-      fclose (file);
-      g_timer_destroy (timer);
-      return FALSE;
-    }
-  }
-
-  while ((ret = xmlTextReaderRead (reader)) == 1) {
-    if (xmlTextReaderDepth (reader) == 0) {
-      in_registry = xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT &&
-          g_str_equal ("GST-PluginRegistry", xmlTextReaderConstName (reader));
-    } else if (in_registry) {
-      if (xmlTextReaderDepth (reader) == 1 &&
-          xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT) {
-        const gchar *tag = (const gchar *) xmlTextReaderConstName (reader);
-
-        if (g_str_equal (tag, "plugin")) {
-          GList *feature_list;
-          GstPlugin *plugin = load_plugin (reader, &feature_list);
-
-          if (plugin) {
-            GList *g;
-
-            gst_registry_add_plugin (registry, plugin);
-            for (g = feature_list; g; g = g_list_next (g)) {
-              gst_registry_add_feature (registry,
-                  GST_PLUGIN_FEATURE_CAST (g->data));
-            }
-            g_list_free (feature_list);
-          }
-        }
-      }
-    }
-  }
-  xmlFreeTextReader (reader);
-  if (ret != 0) {
-    GST_ERROR ("parsing registry cache: %s", location);
-    if (mapped)
-      g_mapped_file_free (mapped);
-    if (file)
-      fclose (file);
-    g_timer_destroy (timer);
-    return FALSE;
-  }
-
-  g_timer_stop (timer);
-  seconds = g_timer_elapsed (timer, NULL);
-  g_timer_destroy (timer);
-
-  GST_INFO ("loaded %s in %lf seconds", location, seconds);
-
-  if (mapped)
-    g_mapped_file_free (mapped);
-
-  if (file)
-    fclose (file);
-
-  return TRUE;
-}
-
-/*
- * Save
- */
-static gboolean
-gst_registry_save_escaped (GstRegistry * registry, const char *prefix,
-    const char *tag, const char *value)
-{
-  gboolean ret = TRUE;
-
-  if (value) {
-    gchar *v;
-
-    if (g_utf8_validate (value, -1, NULL)) {
-      v = g_markup_escape_text (value, -1);
-    } else {
-      g_warning ("Invalid UTF-8 while saving registry tag '%s'", tag);
-      v = g_strdup ("[ERROR: invalid UTF-8]");
-    }
-
-    ret = gst_registry_save (registry, "%s<%s>%s</%s>\n", prefix, tag, v, tag);
-    g_free (v);
-  }
-
-  return ret;
-}
-
-
-static gboolean
-gst_registry_xml_save_caps (GstRegistry * registry, const GstCaps * caps)
-{
-  /* we copy the caps here so we can simplify them before saving. This is a lot
-   * faster when loading them later on */
-  char *s;
-  GstCaps *copy = gst_caps_copy (caps);
-  gboolean ret;
-
-  gst_caps_do_simplify (copy);
-  s = gst_caps_to_string (copy);
-  gst_caps_unref (copy);
-
-  ret = gst_registry_save_escaped (registry, "  ", "caps", s);
-  g_free (s);
-  return ret;
-}
-
-static gboolean
-gst_registry_xml_save_pad_template (GstRegistry * registry,
-    GstStaticPadTemplate * template)
-{
-  gchar *presence;
-
-  if (!gst_registry_save_escaped (registry, "   ", "nametemplate",
-          template->name_template))
-    return FALSE;
-
-  if (!gst_registry_save (registry,
-          "   <direction>%s</direction>\n",
-          (template->direction == GST_PAD_SINK ? "sink" : "src")))
-    return FALSE;
-
-  switch (template->presence) {
-    case GST_PAD_ALWAYS:
-      presence = "always";
-      break;
-    case GST_PAD_SOMETIMES:
-      presence = "sometimes";
-      break;
-    case GST_PAD_REQUEST:
-      presence = "request";
-      break;
-    default:
-      presence = "unknown";
-      break;
-  }
-  if (!gst_registry_save (registry, "   <presence>%s</presence>\n", presence))
-    return FALSE;
-
-  if (template->static_caps.string) {
-    if (!gst_registry_save (registry, "   <caps>%s</caps>\n",
-            template->static_caps.string))
-      return FALSE;
-  }
-  return TRUE;
-}
-
-static gboolean
-gst_registry_xml_save_feature (GstRegistry * registry,
-    GstPluginFeature * feature)
-{
-  if (!gst_registry_save_escaped (registry, "  ", "name", feature->name))
-    return FALSE;
-
-  if (feature->rank > 0) {
-    gint rank = feature->rank;
-
-    if (!gst_registry_save (registry, "  <rank>%d</rank>\n", rank))
-      return FALSE;
-  }
-
-  if (GST_IS_ELEMENT_FACTORY (feature)) {
-    GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
-    GList *walk;
-
-    if (!gst_registry_save_escaped (registry, "  ", "longname",
-            factory->details.longname))
-      return FALSE;
-    if (!gst_registry_save_escaped (registry, "  ", "class",
-            factory->details.klass))
-      return FALSE;
-    if (!gst_registry_save_escaped (registry, "  ", "description",
-            factory->details.description))
-      return FALSE;
-    if (!gst_registry_save_escaped (registry, "  ", "author",
-            factory->details.author))
-      return FALSE;
-
-    walk = factory->staticpadtemplates;
-
-    while (walk) {
-      GstStaticPadTemplate *template = walk->data;
-
-      if (!gst_registry_save (registry, "  <padtemplate>\n"))
-        return FALSE;
-      if (!gst_registry_xml_save_pad_template (registry, template))
-        return FALSE;
-      if (!gst_registry_save (registry, "  </padtemplate>\n"))
-        return FALSE;
-
-      walk = g_list_next (walk);
-    }
-
-    walk = factory->interfaces;
-    while (walk) {
-      if (!gst_registry_save_escaped (registry, "  ", "interface",
-              (gchar *) walk->data))
-        return FALSE;
-      walk = g_list_next (walk);
-    }
-
-    if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
-      if (!gst_registry_save_escaped (registry, "  ", "uri_type",
-              factory->uri_type == GST_URI_SINK ? "sink" : "source"))
-        return FALSE;
-      if (factory->uri_protocols) {
-        gchar **protocol;
-
-        protocol = factory->uri_protocols;
-        while (*protocol) {
-          if (!gst_registry_save_escaped (registry, "  ", "uri_protocol",
-                  *protocol))
-            return FALSE;
-          protocol++;
-        }
-      } else {
-        g_warning ("GStreamer feature '%s' is URI handler but does not provide"
-            " any protocols it can handle", feature->name);
-      }
-    }
-  } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
-    GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
-    gint i = 0;
-
-    if (factory->caps) {
-      if (!gst_registry_xml_save_caps (registry, factory->caps))
-        return FALSE;
-    }
-    if (factory->extensions) {
-      while (factory->extensions[i]) {
-        if (!gst_registry_save_escaped (registry, "  ", "extension",
-                factory->extensions[i]))
-          return FALSE;
-        i++;
-      }
-    }
-#ifndef GST_DISABLE_INDEX
-  } else if (GST_IS_INDEX_FACTORY (feature)) {
-    if (!gst_registry_save_escaped (registry, "  ", "longdesc",
-            GST_INDEX_FACTORY (feature)->longdesc))
-      return FALSE;
-#endif
-  }
-  return TRUE;
-}
-
-static gboolean
-gst_registry_xml_save_plugin (GstRegistry * registry, GstPlugin * plugin)
-{
-  GList *list;
-  GList *walk;
-  char s[100];
-
-  if (!gst_registry_save_escaped (registry, " ", "name", plugin->desc.name))
-    return FALSE;
-  if (!gst_registry_save_escaped (registry, " ", "description",
-          plugin->desc.description))
-    return FALSE;
-  if (!gst_registry_save_escaped (registry, " ", "filename", plugin->filename))
-    return FALSE;
-
-  sprintf (s, "%d", (int) plugin->file_size);
-  if (!gst_registry_save_escaped (registry, " ", "size", s))
-    return FALSE;
-
-  sprintf (s, "%d", (int) plugin->file_mtime);
-  if (!gst_registry_save_escaped (registry, " ", "m32p", s))
-    return FALSE;
-
-  if (!gst_registry_save_escaped (registry, " ", "version",
-          plugin->desc.version))
-    return FALSE;
-  if (!gst_registry_save_escaped (registry, " ", "license",
-          plugin->desc.license))
-    return FALSE;
-  if (!gst_registry_save_escaped (registry, " ", "source", plugin->desc.source))
-    return FALSE;
-  if (!gst_registry_save_escaped (registry, " ", "package",
-          plugin->desc.package))
-    return FALSE;
-  if (!gst_registry_save_escaped (registry, " ", "origin", plugin->desc.origin))
-    return FALSE;
-
-  list = gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name);
-
-  for (walk = list; walk; walk = g_list_next (walk)) {
-    GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data);
-
-    if (!gst_registry_save (registry,
-            " <feature typename=\"%s\">\n",
-            g_type_name (G_OBJECT_TYPE (feature))))
-      goto fail;
-    if (!gst_registry_xml_save_feature (registry, feature))
-      goto fail;
-    if (!gst_registry_save (registry, " </feature>\n"))
-      goto fail;
-  }
-
-  gst_plugin_feature_list_free (list);
-  return TRUE;
-
-fail:
-  gst_plugin_feature_list_free (list);
-  return FALSE;
-
-}
-
-/**
- * gst_registry_xml_write_cache:
- * @registry: a #GstRegistry
- * @location: a filename
- *
- * Write @registry in an XML format at the location given by
- * @location. Directories are automatically created.
- *
- * Returns: TRUE on success.
- */
-gboolean
-gst_registry_xml_write_cache (GstRegistry * registry, const char *location)
-{
-  GList *walk;
-  char *tmp_location;
-
-  g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
-
-  tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
-  registry->cache_file = g_mkstemp (tmp_location);
-  if (registry->cache_file == -1) {
-    char *dir;
-
-    /* oops, I bet the directory doesn't exist */
-    dir = g_path_get_dirname (location);
-    g_mkdir_with_parents (dir, 0777);
-    g_free (dir);
-
-    /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
-    g_free (tmp_location);
-    tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
-    registry->cache_file = g_mkstemp (tmp_location);
-
-    if (registry->cache_file == -1) {
-      GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
-      g_free (tmp_location);
-      return FALSE;
-    }
-  }
-
-  if (!gst_registry_save (registry, "<?xml version=\"1.0\"?>\n"))
-    goto fail;
-  if (!gst_registry_save (registry, "<GST-PluginRegistry>\n"))
-    goto fail;
-
-
-  for (walk = g_list_last (registry->plugins); walk;
-      walk = g_list_previous (walk)) {
-    GstPlugin *plugin = GST_PLUGIN_CAST (walk->data);
-
-    if (!plugin->filename)
-      continue;
-
-    if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
-      int ret;
-      struct stat statbuf;
-
-      ret = g_stat (plugin->filename, &statbuf);
-      if (ret < 0)
-        continue;
-      if (plugin->file_mtime != statbuf.st_mtime ||
-          plugin->file_size != statbuf.st_size) {
-        continue;
-      }
-    }
-
-    if (!gst_registry_save (registry, "<plugin>\n"))
-      goto fail;
-    if (!gst_registry_xml_save_plugin (registry, plugin))
-      goto fail;
-    if (!gst_registry_save (registry, "</plugin>\n"))
-      goto fail;
-  }
-  if (!gst_registry_save (registry, "</GST-PluginRegistry>\n"))
-    goto fail;
-
-  /* check return value of close(), write errors may only get reported here */
-  if (close (registry->cache_file) < 0)
-    goto close_failed;
-
-  if (g_file_test (tmp_location, G_FILE_TEST_EXISTS)) {
-#ifdef WIN32
-    g_remove (location);
-#endif
-    if (g_rename (tmp_location, location) < 0)
-      goto rename_failed;
-  } else {
-    /* FIXME: shouldn't we return FALSE here? */
-  }
-
-  g_free (tmp_location);
-  GST_INFO ("Wrote XML registry cache");
-  return TRUE;
-
-/* ERRORS */
-fail:
-  {
-    (void) close (registry->cache_file);
-    /* fall through */
-  }
-fail_after_close:
-  {
-    g_remove (tmp_location);
-    g_free (tmp_location);
-    return FALSE;
-  }
-close_failed:
-  {
-    GST_ERROR ("close() failed: %s", g_strerror (errno));
-    goto fail_after_close;
-  }
-rename_failed:
-  {
-    GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
-    goto fail_after_close;
-  }
-}
--- a/gstreamer_core/gst/gstsegment.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstsegment.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,8 +19,9 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include "gst_private.h"
 
-#include "gst_private.h"
+#include <math.h>
 
 #include "gstutils.h"
 #include "gstsegment.h"
@@ -83,14 +84,27 @@
  * Last reviewed on 2007-05-17 (0.10.13)
  */
 
-static GstSegment *
+/**
+ * gst_segment_copy:
+ * @segment: a #GstSegment
+ *
+ * Create a copy of given @segment.
+ *
+ * Returns: a new #GstSegment, free with gst_segment_free().
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstSegment *
 gst_segment_copy (GstSegment * segment)
 {
   GstSegment *result = NULL;
 
   if (segment) {
-    result = gst_segment_new ();
-    memcpy (result, segment, sizeof (GstSegment));
+    result = (GstSegment *) g_slice_copy (sizeof (GstSegment), segment);
   }
   return result;
 }
@@ -129,7 +143,7 @@
 {
   GstSegment *result;
 
-  result = g_new0 (GstSegment, 1);
+  result = g_slice_new0 (GstSegment);
   gst_segment_init (result, GST_FORMAT_UNDEFINED);
 
   return result;
@@ -148,7 +162,7 @@
 void
 gst_segment_free (GstSegment * segment)
 {
-  g_free (segment);
+  g_slice_free (GstSegment, segment);
 }
 
 /**
@@ -464,12 +478,18 @@
     gdouble rate, gdouble applied_rate, GstFormat format, gint64 start,
     gint64 stop, gint64 time)
 {
-  gint64 duration;
+  gint64 duration, last_stop;
 
   g_return_if_fail (rate != 0.0);
   g_return_if_fail (applied_rate != 0.0);
   g_return_if_fail (segment != NULL);
 
+  GST_DEBUG ("configuring segment update %d, rate %lf, format %s, "
+      "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
+      G_GINT64_FORMAT, update, rate, gst_format_get_name (format), start,
+      stop, time);
+  GST_DEBUG ("old segment was: %" GST_SEGMENT_FORMAT, segment);
+
   if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
     segment->format = format;
 
@@ -486,7 +506,7 @@
   g_return_if_fail (segment->format == format);
 
   if (update) {
-    if (segment->rate > 0.0) {
+    if (G_LIKELY (segment->rate > 0.0)) {
       /* an update to the current segment is done, elapsed time is
        * difference between the old start and new start. */
       if (start > segment->start)
@@ -501,12 +521,18 @@
       else
         duration = 0;
     }
+    /* update last_stop to be a valid value in the updated segment */
+    if (start > segment->last_stop)
+      last_stop = start;
+    else if (stop != -1 && stop < segment->last_stop)
+      last_stop = stop;
+    else
+      last_stop = segment->last_stop;
   } else {
     /* the new segment has to be aligned with the old segment.
      * We first update the accumulated time of the previous
      * segment. the accumulated time is used when syncing to the
-     * clock. 
-     */
+     * clock. */
     if (segment->stop != -1) {
       duration = segment->stop - segment->start;
     } else if (segment->last_stop != -1) {
@@ -518,9 +544,15 @@
       g_warning ("closing segment of unknown duration, assuming duration of 0");
       duration = 0;
     }
+    /* position the last_stop to the next expected position in the new segment,
+     * which is the start or the stop of the segment */
+    if (rate > 0.0)
+      last_stop = start;
+    else
+      last_stop = stop;
   }
   /* use previous rate to calculate duration */
-  if (segment->abs_rate != 1.0)
+  if (G_LIKELY (segment->abs_rate != 1.0))
     duration /= segment->abs_rate;
 
   /* accumulate duration */
@@ -531,7 +563,7 @@
   segment->abs_rate = ABS (rate);
   segment->applied_rate = applied_rate;
   segment->start = start;
-  segment->last_stop = start;
+  segment->last_stop = last_stop;
   segment->stop = stop;
   segment->time = time;
 }
@@ -578,7 +610,7 @@
 
   /* if we have the position for the same format as the segment, we can compare
    * the start and stop values, otherwise we assume 0 and -1 */
-  if (segment->format == format) {
+  if (G_LIKELY (segment->format == format)) {
     start = segment->start;
     stop = segment->stop;
     time = segment->time;
@@ -606,18 +638,18 @@
   abs_applied_rate = ABS (segment->applied_rate);
 
   /* correct for applied rate if needed */
-  if (abs_applied_rate != 1.0)
+  if (G_UNLIKELY (abs_applied_rate != 1.0))
     result *= abs_applied_rate;
 
   /* add or subtract from segment time based on applied rate */
-  if (segment->applied_rate > 0.0) {
+  if (G_LIKELY (segment->applied_rate > 0.0)) {
     /* correct for segment time */
     result += time;
   } else {
     /* correct for segment time, clamp at 0. Streams with a negative
      * applied_rate have timestamps between start and stop, as usual, but have
      * the time member starting high and going backwards.  */
-    if (time > result)
+    if (G_LIKELY (time > result))
       result = time - result;
     else
       result = 0;
@@ -667,7 +699,7 @@
 
   /* if we have the position for the same format as the segment, we can compare
    * the start and stop values, otherwise we assume 0 and -1 */
-  if (segment->format == format) {
+  if (G_LIKELY (segment->format == format)) {
     start = segment->start;
     stop = segment->stop;
     accum = segment->accum;
@@ -681,7 +713,7 @@
   if (G_UNLIKELY (position < start))
     return -1;
 
-  if (segment->rate > 0.0) {
+  if (G_LIKELY (segment->rate > 0.0)) {
     /* outside of the segment boundary stop */
     if (G_UNLIKELY (stop != -1 && position > stop))
       return -1;
@@ -700,7 +732,7 @@
 
   /* scale based on the rate, avoid division by and conversion to 
    * float when not needed */
-  if (segment->abs_rate != 1.0)
+  if (G_UNLIKELY (segment->abs_rate != 1.0))
     result /= segment->abs_rate;
 
   /* correct for accumulated segments */
@@ -782,3 +814,137 @@
 
   return TRUE;
 }
+
+/**
+ * gst_segment_to_position:
+ * @segment: a #GstSegment structure.
+ * @format: the format of the segment.
+ * @running_time: the running_time in the segment
+ *
+ * Convert @running_time into a position in the segment so that
+ * gst_segment_to_running_time() with that position returns @running_time.
+ *
+ * Returns: the position in the segment for @running_time. This function returns
+ * -1 when @running_time is -1 or when it is not inside @segment.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gint64
+gst_segment_to_position (GstSegment * segment, GstFormat format,
+    gint64 running_time)
+{
+  gint64 result;
+  gint64 start, stop, accum;
+
+  g_return_val_if_fail (segment != NULL, -1);
+
+  if (G_UNLIKELY (running_time == -1))
+    return -1;
+
+  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
+    segment->format = format;
+
+  /* if we have the position for the same format as the segment, we can compare
+   * the start and stop values, otherwise we assume 0 and -1 */
+  if (G_LIKELY (segment->format == format)) {
+    start = segment->start;
+    stop = segment->stop;
+    accum = segment->accum;
+  } else {
+    start = 0;
+    stop = -1;
+    accum = 0;
+  }
+
+  /* this running_time was for a previous segment */
+  if (running_time < accum)
+    return -1;
+
+  /* start by subtracting the accumulated time */
+  result = running_time - accum;
+
+  /* move into the segment at the right rate */
+  if (G_UNLIKELY (segment->abs_rate != 1.0))
+    result = ceil (result * segment->abs_rate);
+
+  if (G_LIKELY (segment->rate > 0.0)) {
+    /* bring to corrected position in segment */
+    result += start;
+
+    /* outside of the segment boundary stop */
+    if (G_UNLIKELY (stop != -1 && result > stop))
+      return -1;
+  } else {
+    /* cannot continue if no stop position set or outside of
+     * the segment. */
+    if (G_UNLIKELY (stop == -1 || result + start > stop))
+      return -1;
+
+    /* bring to corrected position in segment */
+    result = stop - result;
+  }
+  return result;
+}
+
+
+/**
+ * gst_segment_set_running_time:
+ * @segment: a #GstSegment structure.
+ * @format: the format of the segment.
+ * @running_time: the running_time in the segment
+ *
+ * Adjust the start/stop and accum values of @segment such that the next valid
+ * buffer will be one with @running_time.
+ *
+ * Returns: %TRUE if the segment could be updated successfully. If %FALSE is
+ * returned, @running_time is -1 or not in @segment.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_segment_set_running_time (GstSegment * segment, GstFormat format,
+    gint64 running_time)
+{
+  gint64 position;
+  gint64 start, stop, last_stop;
+
+  /* start by bringing the running_time into the segment position */
+  position = gst_segment_to_position (segment, format, running_time);
+
+  /* we must have a valid position now */
+  if (G_UNLIKELY (position == -1))
+    return FALSE;
+
+  start = segment->start;
+  stop = segment->stop;
+  last_stop = segment->last_stop;
+
+  if (G_LIKELY (segment->rate > 0.0)) {
+    /* update the start/last_stop and time values */
+    start = position;
+    if (last_stop < start)
+      last_stop = start;
+  } else {
+    /* reverse, update stop */
+    stop = position;
+    /* if we were past the position, go back */
+    if (last_stop > stop)
+      last_stop = stop;
+  }
+  /* and accumulated time is exactly the running time */
+  segment->time = gst_segment_to_stream_time (segment, format, start);
+  segment->start = start;
+  segment->stop = stop;
+  segment->last_stop = last_stop;
+  segment->accum = running_time;
+
+  return TRUE;
+}
--- a/gstreamer_core/gst/gstsegment.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstsegment.h	Fri Apr 16 15:15:52 2010 +0300
@@ -86,6 +86,11 @@
 IMPORT_C
 #endif
 
+GstSegment * gst_segment_copy                (GstSegment *segment);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void         gst_segment_free                (GstSegment *segment);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -143,9 +148,21 @@
 IMPORT_C
 #endif
 
+gint64       gst_segment_to_position         (GstSegment *segment, GstFormat format, gint64 running_time);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 gboolean     gst_segment_clip                (GstSegment *segment, GstFormat format, gint64 start,
                                               gint64 stop, gint64 *clip_start, gint64 *clip_stop);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean     gst_segment_set_running_time    (GstSegment *segment, GstFormat format, gint64 running_time);
+
 
 G_END_DECLS
 
--- a/gstreamer_core/gst/gststructure.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gststructure.c	Fri Apr 16 15:15:52 2010 +0300
@@ -49,7 +49,10 @@
  * Fields can be removed with gst_structure_remove_field() or
  * gst_structure_remove_fields().
  *
- * Last reviewed on 2007-10-16 (0.10.15)
+ * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are
+ * not allowed. Strings must not be empty either, but may be NULL.
+ *
+ * Last reviewed on 2009-06-08 (0.10.23)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -59,6 +62,7 @@
 #include <string.h>
 
 #include "gst_private.h"
+#include "gstquark.h"
 #include <gst/gst.h>
 #include <gobject/gvaluecollector.h>
 
@@ -81,6 +85,9 @@
     (!(structure)->parent_refcount || \
      g_atomic_int_get ((structure)->parent_refcount) == 1)
 
+#define IS_TAGLIST(structure) \
+    (structure->name == GST_QUARK (TAGLIST))
+
 static void gst_structure_set_field (GstStructure * structure,
     GstStructureField * field);
 static GstStructureField *gst_structure_get_field (const GstStructure *
@@ -121,11 +128,12 @@
 {
   GstStructure *structure;
 
-  structure = g_new0 (GstStructure, 1);
+  structure = g_slice_new (GstStructure);
   structure->type = gst_structure_get_type ();
   structure->name = quark;
+  structure->parent_refcount = NULL;
   structure->fields =
-      g_array_sized_new (FALSE, TRUE, sizeof (GstStructureField), prealloc);
+      g_array_sized_new (FALSE, FALSE, sizeof (GstStructureField), prealloc);
 
   return structure;
 }
@@ -150,6 +158,7 @@
   return gst_structure_id_empty_new_with_size (quark, 0);
 }
 
+#ifndef G_DISABLE_CHECKS
 static gboolean
 gst_structure_validate_name (const gchar * name)
 {
@@ -158,7 +167,7 @@
   g_return_val_if_fail (name != NULL, FALSE);
 
   /* FIXME 0.11: use g_ascii_isalpha() */
-  if (!g_ascii_isalnum (*name)) {
+  if (G_UNLIKELY (!g_ascii_isalnum (*name))) {
     GST_WARNING ("Invalid character '%c' at offset 0 in structure name: %s",
         *name, name);
     return FALSE;
@@ -169,7 +178,7 @@
   s = &name[1];
   while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+ ", *s) != NULL))
     s++;
-  if (*s != '\0') {
+  if (G_UNLIKELY (*s != '\0')) {
     GST_WARNING ("Invalid character '%c' at offset %lu in structure name: %s",
         *s, ((gulong) s - (gulong) name), name);
     return FALSE;
@@ -177,6 +186,7 @@
 
   return TRUE;
 }
+#endif
 
 /**
  * gst_structure_empty_new:
@@ -282,7 +292,7 @@
 #endif
 
 void
-gst_structure_set_parent_refcount (GstStructure * structure, int *refcount)
+gst_structure_set_parent_refcount (GstStructure * structure, gint * refcount)
 {
   g_return_if_fail (structure != NULL);
 
@@ -313,7 +323,7 @@
 {
   GstStructure *new_structure;
   GstStructureField *field;
-  guint i;
+  guint i, len;
 
   g_return_val_if_fail (structure != NULL, NULL);
 
@@ -321,7 +331,8 @@
       gst_structure_id_empty_new_with_size (structure->name,
       structure->fields->len);
 
-  for (i = 0; i < structure->fields->len; i++) {
+  len = structure->fields->len;
+  for (i = 0; i < len; i++) {
     GstStructureField new_field = { 0 };
 
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -349,12 +360,13 @@
 gst_structure_free (GstStructure * structure)
 {
   GstStructureField *field;
-  guint i;
+  guint i, len;
 
   g_return_if_fail (structure != NULL);
   g_return_if_fail (structure->parent_refcount == NULL);
 
-  for (i = 0; i < structure->fields->len; i++) {
+  len = structure->fields->len;
+  for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
     if (G_IS_VALUE (&field->value)) {
@@ -365,7 +377,7 @@
 #ifdef USE_POISONING
   memset (structure, 0xff, sizeof (GstStructure));
 #endif
-  g_free (structure);
+  g_slice_free (GstStructure, structure);
 }
 
 /**
@@ -484,17 +496,6 @@
   g_return_if_fail (G_IS_VALUE (value));
   g_return_if_fail (IS_MUTABLE (structure));
 
-  if (G_VALUE_HOLDS_STRING (value)) {
-    const gchar *s;
-
-    s = g_value_get_string (value);
-    if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) {
-      g_warning ("Trying to set string field '%s' on structure, but string is "
-          "not valid UTF-8. Please file a bug.", g_quark_to_string (field));
-      return;
-    }
-  }
-
   gsfield.name = field;
   gst_value_init_and_copy (&gsfield.value, value);
 
@@ -540,7 +541,7 @@
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
 void
 gst_structure_set (GstStructure * structure, const gchar * field, ...)
 {
@@ -584,14 +585,14 @@
 
     type = va_arg (varargs, GType);
 
-    if (type == G_TYPE_DATE) {
+    if (G_UNLIKELY (type == G_TYPE_DATE)) {
       g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
       type = GST_TYPE_DATE;
     }
 
     g_value_init (&field.value, type);
     G_VALUE_COLLECT (&field.value, varargs, 0, &err);
-    if (err) {
+    if (G_UNLIKELY (err)) {
       g_critical ("%s", err);
       return;
     }
@@ -662,14 +663,14 @@
 
     type = va_arg (varargs, GType);
 
-    if (type == G_TYPE_DATE) {
+    if (G_UNLIKELY (type == G_TYPE_DATE)) {
       g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
       type = GST_TYPE_DATE;
     }
 
     g_value_init (&field.value, type);
     G_VALUE_COLLECT (&field.value, varargs, 0, &err);
-    if (err) {
+    if (G_UNLIKELY (err)) {
       g_critical ("%s", err);
       return;
     }
@@ -679,6 +680,51 @@
   }
 }
 
+/**
+ * gst_structure_id_new:
+ * @name_quark: name of new structure
+ * @field_quark: the GQuark for the name of the field to set
+ * @...: variable arguments
+ *
+ * Creates a new #GstStructure with the given name as a GQuark, followed by
+ * fieldname quark, GType, argument(s) "triplets" in the same format as
+ * gst_structure_id_set(). Basically a convenience wrapper around
+ * gst_structure_id_empty_new() and gst_structure_id_set().
+ *
+ * The last variable argument must be NULL (or 0).
+ *
+ * Returns: a new #GstStructure
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstStructure *
+gst_structure_id_new (GQuark name_quark, GQuark field_quark, ...)
+{
+  GstStructure *s;
+  va_list varargs;
+
+  g_return_val_if_fail (name_quark != 0, NULL);
+  g_return_val_if_fail (field_quark != 0, NULL);
+
+  s = gst_structure_id_empty_new (name_quark);
+
+  va_start (varargs, field_quark);
+  gst_structure_id_set_valist (s, field_quark, varargs);
+  va_end (varargs);
+
+  return s;
+}
+
+#if GST_VERSION_NANO == 1
+#define GIT_G_WARNING g_warning
+#else
+#define GIT_G_WARNING GST_WARNING
+#endif
+
 /* If the structure currently contains a field with the same name, it is
  * replaced with the provided field. Otherwise, the field is added to the
  * structure. The field's value is not deeply copied.
@@ -687,12 +733,41 @@
 gst_structure_set_field (GstStructure * structure, GstStructureField * field)
 {
   GstStructureField *f;
-  guint i;
-
-  for (i = 0; i < structure->fields->len; i++) {
+  guint i, len = structure->fields->len;
+
+  if (G_UNLIKELY (G_VALUE_HOLDS_STRING (&field->value))) {
+    const gchar *s;
+
+    s = g_value_get_string (&field->value);
+    /* only check for NULL strings in taglists, as they are allowed in message
+     * structs, e.g. error message debug strings */
+    if (G_UNLIKELY (IS_TAGLIST (structure) && (s == NULL || *s == '\0'))) {
+      if (s == NULL) {
+        GIT_G_WARNING ("Trying to set NULL string on field '%s' on taglist. "
+            "Please file a bug.", g_quark_to_string (field->name));
+        g_value_unset (&field->value);
+        return;
+      } else {
+        /* empty strings never make sense */
+        GIT_G_WARNING ("Trying to set empty string on taglist field '%s'. "
+            "Please file a bug.", g_quark_to_string (field->name));
+        g_value_unset (&field->value);
+        return;
+      }
+    } else if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) {
+      g_warning ("Trying to set string on %s field '%s', but string is not "
+          "valid UTF-8. Please file a bug.",
+          IS_TAGLIST (structure) ? "taglist" : "structure",
+          g_quark_to_string (field->name));
+      g_value_unset (&field->value);
+      return;
+    }
+  }
+
+  for (i = 0; i < len; i++) {
     f = GST_STRUCTURE_FIELD (structure, i);
 
-    if (f->name == field->name) {
+    if (G_UNLIKELY (f->name == field->name)) {
       g_value_unset (&f->value);
       memcpy (f, field, sizeof (GstStructureField));
       return;
@@ -708,14 +783,15 @@
 gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
 {
   GstStructureField *field;
-  guint i;
-
+  guint i, len;
+
+  len = structure->fields->len;
   g_return_val_if_fail (structure != NULL, NULL);
 
-  for (i = 0; i < structure->fields->len; i++) {
+  for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    if (field->name == field_id)
+    if (G_UNLIKELY (field->name == field_id))
       return field;
   }
 
@@ -809,15 +885,16 @@
 {
   GstStructureField *field;
   GQuark id;
-  guint i;
+  guint i, len;
 
   g_return_if_fail (structure != NULL);
   g_return_if_fail (fieldname != NULL);
   g_return_if_fail (IS_MUTABLE (structure));
 
   id = g_quark_from_string (fieldname);
-
-  for (i = 0; i < structure->fields->len; i++) {
+  len = structure->fields->len;
+
+  for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
     if (field->name == id) {
@@ -1014,18 +1091,20 @@
 gst_structure_foreach (const GstStructure * structure,
     GstStructureForeachFunc func, gpointer user_data)
 {
-  guint i;
+  guint i, len;
   GstStructureField *field;
   gboolean ret;
 
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (func != NULL, FALSE);
 
-  for (i = 0; i < structure->fields->len; i++) {
+  len = structure->fields->len;
+
+  for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
     ret = func (field->name, &field->value, user_data);
-    if (!ret)
+    if (G_UNLIKELY (!ret))
       return FALSE;
   }
 
@@ -1053,15 +1132,16 @@
 gst_structure_map_in_place (GstStructure * structure,
     GstStructureMapFunc func, gpointer user_data)
 {
-  guint i;
+  guint i, len;
   GstStructureField *field;
   gboolean ret;
 
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
   g_return_val_if_fail (func != NULL, FALSE);
-
-  for (i = 0; i < structure->fields->len; i++) {
+  len = structure->fields->len;
+
+  for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
     ret = func (field->name, &field->value, user_data);
@@ -1303,6 +1383,11 @@
  * given field.  Caller is responsible for making sure the field exists
  * and has the correct type.
  *
+ * On success @value will point to a newly-allocated copy of the date which
+ * should be freed with g_date_free() when no longer needed (note: this is
+ * inconsistent with e.g. gst_structure_get_string() which doesn't return a
+ * copy of the string).
+ *
  * Returns: TRUE if the value could be set correctly. If there was no field
  * with @fieldname or the existing field did not contain a data, this function
  * returns FALSE.
@@ -1328,6 +1413,7 @@
   if (!GST_VALUE_HOLDS_DATE (&field->value))
     return FALSE;
 
+  /* FIXME: 0.11 g_value_dup_boxed() -> g_value_get_boxed() */
   *value = g_value_dup_boxed (&field->value);
 
   return TRUE;
@@ -1540,7 +1626,7 @@
 
 typedef struct _GstStructureAbbreviation
 {
-  char *type_name;
+  gchar *type_name;
   GType type;
 }
 GstStructureAbbreviation;
@@ -1555,7 +1641,7 @@
 
   if (abbrs == NULL) {
     /* dynamically generate the array */
-    #ifdef __SYMBIAN32__
+#ifdef __SYMBIAN32__
 
       GstStructureAbbreviation dyn_abbrs[] = {
 
@@ -1715,27 +1801,23 @@
   }
   return G_VALUE_TYPE (val);
 }
-
-/* keep in sync with gstvalue.c */
-#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
-      ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
-      ((c) == '.'))
-
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
+
 gboolean
 priv_gst_structure_append_to_gstring (const GstStructure * structure,
     GString * s)
 {
   GstStructureField *field;
-  guint i;
+  guint i, len;
 
   g_return_val_if_fail (s != NULL, FALSE);
 
   g_string_append (s, g_quark_to_string (structure->name));
-  for (i = 0; i < structure->fields->len; i++) {
+  len = structure->fields->len;
+  for (i = 0; i < len; i++) {
     char *t;
     GType type;
 
@@ -1750,7 +1832,7 @@
     g_string_append_len (s, "=(", 2);
     g_string_append (s, gst_structure_to_abbr (type));
     g_string_append_c (s, ')');
-    g_string_append (s, GST_STR_NULL (t));
+    g_string_append (s, t == NULL ? "NULL" : t);
     g_free (t);
   }
 
@@ -1764,13 +1846,18 @@
  *
  * Converts @structure to a human-readable string representation.
  *
+ * For debugging purposes its easier to do something like this:
+ * |[
+ * GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
+ * ]|
+ * This prints the structure in human readble form.
+ *
  * Returns: a pointer to string allocated by g_malloc(). g_free() after
  * usage.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
-
 gchar *
 gst_structure_to_string (const GstStructure * structure)
 {
@@ -1799,7 +1886,8 @@
  * THIS FUNCTION MODIFIES THE STRING AND DETECTS INSIDE A NONTERMINATED STRING
  */
 static gboolean
-gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next)
+gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next,
+    gboolean unescape)
 {
   gchar *w;
 
@@ -1815,21 +1903,32 @@
     return ret;
   }
 
-  w = s;
-  s++;
-  while (*s != '"') {
-    if (*s == 0)
-      return FALSE;
-
-    if (*s == '\\') {
+  if (unescape) {
+    w = s;
+    s++;
+    while (*s != '"') {
+      if (G_UNLIKELY (*s == 0))
+        return FALSE;
+      if (G_UNLIKELY (*s == '\\'))
+        s++;
+      *w = *s;
+      w++;
       s++;
     }
-
-    *w = *s;
-    w++;
+    s++;
+  } else {
+    /* Find the closing quotes */
     s++;
+    while (*s != '"') {
+      if (G_UNLIKELY (*s == 0))
+        return FALSE;
+      if (G_UNLIKELY (*s == '\\'))
+        s++;
+      s++;
+    }
+    s++;
+    w = s;
   }
-  s++;
 
   *end = w;
   *next = s;
@@ -1976,7 +2075,7 @@
 {
   char *s = str;
 
-  while (GST_ASCII_IS_STRING (*s)) {
+  while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
     s++;
   }
 
@@ -1999,23 +2098,24 @@
   while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
     s++;
   name = s;
-  if (!gst_structure_parse_simple_string (s, &name_end))
+  if (G_UNLIKELY (!gst_structure_parse_simple_string (s, &name_end)))
     return FALSE;
 
   s = name_end;
   while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
     s++;
 
-  if (*s != '=')
+  if (G_UNLIKELY (*s != '='))
     return FALSE;
   s++;
 
   c = *name_end;
-  *name_end = 0;
+  *name_end = '\0';
   field->name = g_quark_from_string (name);
   *name_end = c;
 
-  if (!gst_structure_parse_value (s, &s, &field->value, G_TYPE_INVALID))
+  if (G_UNLIKELY (!gst_structure_parse_value (s, &s, &field->value,
+              G_TYPE_INVALID)))
     return FALSE;
 
   *after = s;
@@ -2038,7 +2138,6 @@
   #endif
   GType type = default_type;
 
-
   s = str;
   while (g_ascii_isspace (*s))
     s++;
@@ -2046,18 +2145,16 @@
   /* check if there's a (type_name) 'cast' */
   type_name = NULL;
   if (*s == '(') {
-    type = G_TYPE_INVALID;
-
     s++;
     while (g_ascii_isspace (*s))
       s++;
     type_name = s;
-    if (!gst_structure_parse_simple_string (s, &type_end))
+    if (G_UNLIKELY (!gst_structure_parse_simple_string (s, &type_end)))
       return FALSE;
     s = type_end;
     while (g_ascii_isspace (*s))
       s++;
-    if (*s != ')')
+    if (G_UNLIKELY (*s != ')'))
       return FALSE;
     s++;
     while (g_ascii_isspace (*s))
@@ -2068,7 +2165,7 @@
     type = gst_structure_gtype_from_abbr (type_name);
     *type_end = c;
 
-    if (type == G_TYPE_INVALID)
+    if (G_UNLIKELY (type == G_TYPE_INVALID))
       return FALSE;
   }
 
@@ -2082,12 +2179,8 @@
     ret = gst_structure_parse_array (s, &s, value, type);
   } else {
     value_s = s;
-    if (!gst_structure_parse_string (s, &value_end, &s))
-      return FALSE;
-
-    c = *value_end;
-    *value_end = 0;
-    if (type == G_TYPE_INVALID) {
+
+    if (G_UNLIKELY (type == G_TYPE_INVALID)) {
     #ifdef __SYMBIAN32__
          GType try_types[] =
          { G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_INVALID, G_TYPE_STRING };
@@ -2099,6 +2192,12 @@
 
          int i;
         #endif
+      if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s, TRUE)))
+        return FALSE;
+      /* Set NULL terminator for deserialization */
+      c = *value_end;
+      *value_end = '\0';
+
       for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
         g_value_init (value, try_types[i]);
         ret = gst_value_deserialize (value, value_s);
@@ -2109,7 +2208,16 @@
     } else {
       g_value_init (value, type);
 
+      if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s,
+                  (type != G_TYPE_STRING))))
+        return FALSE;
+      /* Set NULL terminator for deserialization */
+      c = *value_end;
+      *value_end = '\0';
+
       ret = gst_value_deserialize (value, value_s);
+      if (G_UNLIKELY (!ret))
+        g_value_unset (value);
     }
     *value_end = c;
   }
@@ -2144,7 +2252,7 @@
   char *r;
   char save;
   GstStructure *structure = NULL;
-  GstStructureField field = { 0 };
+  GstStructureField field;
 
   g_return_val_if_fail (string != NULL, NULL);
 
@@ -2157,17 +2265,17 @@
     r++;
 
   name = r;
-  if (!gst_structure_parse_string (r, &w, &r)) {
+  if (G_UNLIKELY (!gst_structure_parse_string (r, &w, &r, TRUE))) {
     GST_WARNING ("Failed to parse structure string");
     goto error;
   }
 
   save = *w;
-  *w = 0;
+  *w = '\0';
   structure = gst_structure_empty_new (name);
   *w = save;
 
-  if (structure == NULL)
+  if (G_UNLIKELY (structure == NULL))
     goto error;
 
   do {
@@ -2183,7 +2291,7 @@
       /* accept \0 as end delimiter */
       break;
     }
-    if (*r != ',') {
+    if (G_UNLIKELY (*r != ',')) {
       GST_WARNING ("Failed to find delimiter, r=%s", r);
       goto error;
     }
@@ -2193,10 +2301,9 @@
       r++;
 
     memset (&field, 0, sizeof (field));
-    if (!gst_structure_parse_field (r, &r, &field))
+    if (G_UNLIKELY (!gst_structure_parse_field (r, &r, &field)))
       goto error;
     gst_structure_set_field (structure, &field);
-
   } while (TRUE);
 
   if (end)
@@ -2483,16 +2590,13 @@
     const GValue *list_value;
     int i, n;
     const GValue *best = NULL;
-    GValue best_diff = { 0 };
-    GValue cur_diff = { 0 };
-    GValue target = { 0 };
-    gboolean res = FALSE;
-
-    g_value_init (&best_diff, GST_TYPE_FRACTION);
-    g_value_init (&cur_diff, GST_TYPE_FRACTION);
-    g_value_init (&target, GST_TYPE_FRACTION);
-
-    gst_value_set_fraction (&target, target_numerator, target_denominator);
+    gdouble target;
+    gdouble cur_diff;
+    gdouble best_diff = G_MAXDOUBLE;
+
+    target = (gdouble) target_numerator / (gdouble) target_denominator;
+
+    GST_DEBUG ("target %g, best %g", target, best_diff);
 
     best = NULL;
 
@@ -2500,28 +2604,295 @@
     for (i = 0; i < n; i++) {
       list_value = gst_value_list_get_value (value, i);
       if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) {
-
-        if (gst_value_compare (list_value, &target) == GST_VALUE_LESS_THAN)
-          gst_value_fraction_subtract (&cur_diff, &target, list_value);
-        else
-          gst_value_fraction_subtract (&cur_diff, list_value, &target);
-
-        if (!best
-            || gst_value_compare (&cur_diff,
-                &best_diff) == GST_VALUE_LESS_THAN) {
+        gint num, denom;
+        gdouble list_double;
+
+        num = gst_value_get_fraction_numerator (list_value);
+        denom = gst_value_get_fraction_denominator (list_value);
+
+        list_double = ((gdouble) num / (gdouble) denom);
+        cur_diff = target - list_double;
+
+        GST_DEBUG ("curr diff %g, list %g", cur_diff, list_double);
+
+        if (cur_diff < 0)
+          cur_diff = -cur_diff;
+
+        if (!best || cur_diff < best_diff) {
+          GST_DEBUG ("new best %g", list_double);
           best = list_value;
-          g_value_copy (&cur_diff, &best_diff);
+          best_diff = cur_diff;
         }
       }
     }
     if (best != NULL) {
       gst_structure_set_value (structure, field_name, best);
-      res = TRUE;
+      return TRUE;
     }
-    g_value_unset (&best_diff);
-    g_value_unset (&cur_diff);
-    g_value_unset (&target);
-    return res;
   }
+
   return FALSE;
 }
+
+/* our very own version of G_VALUE_LCOPY that allows NULL return locations
+ * (useful for message parsing functions where the return location is user
+ * supplied and the user may pass NULL if the value isn't of interest) */
+#define GST_VALUE_LCOPY(value, var_args, flags, __error, fieldname)           \
+G_STMT_START {                                                                \
+  const GValue *_value = (value);                                             \
+  guint _flags = (flags);                                                     \
+  GType _value_type = G_VALUE_TYPE (_value);                                  \
+  GTypeValueTable *_vtable = g_type_value_table_peek (_value_type);           \
+  gchar *_lcopy_format = _vtable->lcopy_format;                               \
+  GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, };      \
+  guint _n_values = 0;                                                        \
+                                                                              \
+  while (*_lcopy_format != '\0') {                                            \
+    g_assert (*_lcopy_format == G_VALUE_COLLECT_POINTER);                     \
+    _cvalues[_n_values++].v_pointer = va_arg ((var_args), gpointer);          \
+    _lcopy_format++;                                                          \
+  }                                                                           \
+  if (_n_values == 2 && !!_cvalues[0].v_pointer != !!_cvalues[1].v_pointer) { \
+    *(__error) = g_strdup_printf ("either all or none of the return "         \
+        "locations for field '%s' need to be NULL", fieldname);               \
+  } else if (_cvalues[0].v_pointer != NULL) {                                 \
+    *(__error) = _vtable->lcopy_value (_value, _n_values, _cvalues, _flags);  \
+  }                                                                           \
+} G_STMT_END
+
+/**
+ * gst_structure_get_valist:
+ * @structure: a #GstStructure
+ * @first_fieldname: the name of the first field to read
+ * @args: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * valist-variant of gst_structure_get(). Look at the documentation of
+ * gst_structure_get() for more details.
+ *
+ * Returns: TRUE, or FALSE if there was a problem reading any of the fields
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_structure_get_valist (GstStructure * structure,
+    const char *first_fieldname, va_list args)
+{
+  const char *field_name;
+  GType expected_type = G_TYPE_INVALID;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+  g_return_val_if_fail (first_fieldname != NULL, FALSE);
+
+  field_name = first_fieldname;
+  while (field_name) {
+    const GValue *val = NULL;
+    gchar *err = NULL;
+
+    expected_type = va_arg (args, GType);
+
+    val = gst_structure_get_value (structure, field_name);
+
+    if (val == NULL)
+      goto no_such_field;
+
+    if (G_VALUE_TYPE (val) != expected_type)
+      goto wrong_type;
+
+    GST_VALUE_LCOPY (val, args, 0, &err, field_name);
+    if (err) {
+      g_warning ("%s: %s", G_STRFUNC, err);
+      g_free (err);
+      return FALSE;
+    }
+
+    field_name = va_arg (args, const gchar *);
+  }
+
+  return TRUE;
+
+/* ERRORS */
+no_such_field:
+  {
+    GST_WARNING ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
+        field_name, structure);
+    return FALSE;
+  }
+wrong_type:
+  {
+    GST_WARNING ("Expected field '%s' in structure to be of type '%s', but "
+        "field was of type '%s': %" GST_PTR_FORMAT, field_name,
+        GST_STR_NULL (g_type_name (expected_type)),
+        G_VALUE_TYPE_NAME (gst_structure_get_value (structure, field_name)),
+        structure);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_structure_id_get_valist:
+ * @structure: a #GstStructure
+ * @first_field_id: the quark of the first field to read
+ * @args: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * valist-variant of gst_structure_id_get(). Look at the documentation of
+ * gst_structure_id_get() for more details.
+ *
+ * Returns: TRUE, or FALSE if there was a problem reading any of the fields
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_structure_id_get_valist (GstStructure * structure, GQuark first_field_id,
+    va_list args)
+{
+  GQuark field_id;
+  GType expected_type = G_TYPE_INVALID;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+  g_return_val_if_fail (first_field_id != 0, FALSE);
+
+  field_id = first_field_id;
+  while (field_id) {
+    const GValue *val = NULL;
+    gchar *err = NULL;
+
+    expected_type = va_arg (args, GType);
+
+    val = gst_structure_id_get_value (structure, field_id);
+
+    if (val == NULL)
+      goto no_such_field;
+
+    if (G_VALUE_TYPE (val) != expected_type)
+      goto wrong_type;
+
+    GST_VALUE_LCOPY (val, args, 0, &err, g_quark_to_string (field_id));
+    if (err) {
+      g_warning ("%s: %s", G_STRFUNC, err);
+      g_free (err);
+      return FALSE;
+    }
+
+    field_id = va_arg (args, GQuark);
+  }
+
+  return TRUE;
+
+/* ERRORS */
+no_such_field:
+  {
+    GST_WARNING ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
+        GST_STR_NULL (g_quark_to_string (field_id)), structure);
+    return FALSE;
+  }
+wrong_type:
+  {
+    GST_WARNING ("Expected field '%s' in structure to be of type '%s', but "
+        "field was of type '%s': %" GST_PTR_FORMAT,
+        g_quark_to_string (field_id),
+        GST_STR_NULL (g_type_name (expected_type)),
+        G_VALUE_TYPE_NAME (gst_structure_id_get_value (structure, field_id)),
+        structure);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_structure_get:
+ * @structure: a #GstStructure
+ * @first_fieldname: the name of the first field to read
+ * @...: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * Variable arguments should be in the form field name, field type
+ * (as a GType), pointer(s) to a variable(s) to hold the return value(s).
+ * The last variable argument should be NULL.
+ *
+ * For refcounted (mini)objects you will acquire your own reference which
+ * you must release with a suitable _unref() when no longer needed. For
+ * strings and boxed types you will acquire a copy which you will need to
+ * release with either g_free() or the suiteable function for the boxed type.
+ *
+ * Returns: FALSE if there was a problem reading any of the fields (e.g.
+ *     because the field requested did not exist, or was of a type other
+ *     than the type specified), otherwise TRUE.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_structure_get (GstStructure * structure, const char *first_fieldname, ...)
+{
+  gboolean ret;
+  va_list args;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+  g_return_val_if_fail (first_fieldname != NULL, FALSE);
+
+  va_start (args, first_fieldname);
+  ret = gst_structure_get_valist (structure, first_fieldname, args);
+  va_end (args);
+
+  return ret;
+}
+
+/**
+ * gst_structure_id_get:
+ * @structure: a #GstStructure
+ * @first_field_id: the quark of the first field to read
+ * @...: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * Variable arguments should be in the form field id quark, field type
+ * (as a GType), pointer(s) to a variable(s) to hold the return value(s).
+ * The last variable argument should be NULL (technically it should be a
+ * 0 quark, but we require NULL so compilers that support it can check for
+ * the NULL terminator and warn if it's not there).
+ *
+ * This function is just like gst_structure_get() only that it is slightly
+ * more efficient since it saves the string-to-quark lookup in the global
+ * quark hashtable.
+ *
+ * For refcounted (mini)objects you will acquire your own reference which
+ * you must release with a suitable _unref() when no longer needed. For
+ * strings and boxed types you will acquire a copy which you will need to
+ * release with either g_free() or the suiteable function for the boxed type.
+ *
+ * Returns: FALSE if there was a problem reading any of the fields (e.g.
+ *     because the field requested did not exist, or was of a type other
+ *     than the type specified), otherwise TRUE.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_structure_id_get (GstStructure * structure, GQuark first_field_id, ...)
+{
+  gboolean ret;
+  va_list args;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+  g_return_val_if_fail (first_field_id != 0, FALSE);
+
+  va_start (args, first_field_id);
+  ret = gst_structure_id_get_valist (structure, first_field_id, args);
+  va_end (args);
+
+  return ret;
+}
--- a/gstreamer_core/gst/gststructure.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gststructure.h	Fri Apr 16 15:15:52 2010 +0300
@@ -119,6 +119,13 @@
 IMPORT_C
 #endif
 
+GstStructure *          gst_structure_id_new               (GQuark                   name_quark,
+                                                            GQuark                   field_quark,
+                                                            ...);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstStructure *          gst_structure_copy                 (const GstStructure      *structure);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -205,6 +212,37 @@
 #endif
 
 
+gboolean                gst_structure_get_valist           (GstStructure            *structure,
+                                                            const char              *first_fieldname,
+                                                            va_list                  args);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean                gst_structure_get                  (GstStructure            *structure,
+                                                            const char              *first_fieldname,
+                                                            ...) G_GNUC_NULL_TERMINATED;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean                gst_structure_id_get_valist        (GstStructure            *structure,
+                                                            GQuark                   first_field_id,
+                                                            va_list                  args);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean                gst_structure_id_get               (GstStructure            *structure,
+                                                            GQuark                   first_field_id,
+                                                            ...) G_GNUC_NULL_TERMINATED;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 G_CONST_RETURN GValue * gst_structure_id_get_value         (const GstStructure      *structure,
 							    GQuark                   field);
--- a/gstreamer_core/gst/gstsystemclock.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstsystemclock.c	Fri Apr 16 15:15:52 2010 +0300
@@ -40,8 +40,11 @@
 
 #include "gst_private.h"
 #include "gstinfo.h"
+#include "gstsystemclock.h"
+#include "gstenumtypes.h"
+#include "gstpoll.h"
 
-#include "gstsystemclock.h"
+#include <errno.h>
 
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
@@ -50,12 +53,45 @@
 /* Define this to get some extra debug about jitter from each clock_wait */
 #undef WAIT_DEBUGGING
 
+struct _GstSystemClockPrivate
+{
+  GstClockType clock_type;
+  GstPoll *timer;
+  gint wakeup_count;            /* the number of entries with a pending wakeup */
+  gboolean async_wakeup;        /* if the wakeup was because of a async list change */
+};
+
+#define GST_SYSTEM_CLOCK_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_SYSTEM_CLOCK, \
+        GstSystemClockPrivate))
+
+#ifdef HAVE_POSIX_TIMERS
+# ifdef HAVE_MONOTONIC_CLOCK
+#  define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC
+# else
+#  define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME
+# endif
+#else
+#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME
+#endif
+
+enum
+{
+  PROP_0,
+  PROP_CLOCK_TYPE,
+  /* FILL ME */
+};
+
 /* the one instance of the systemclock */
 static GstClock *_the_system_clock = NULL;
 
 static void gst_system_clock_class_init (GstSystemClockClass * klass);
 static void gst_system_clock_init (GstSystemClock * clock);
 static void gst_system_clock_dispose (GObject * object);
+static void gst_system_clock_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_system_clock_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
 static GstClockTime gst_system_clock_get_internal_time (GstClock * clock);
 static guint64 gst_system_clock_get_resolution (GstClock * clock);
@@ -70,56 +106,37 @@
     GstClockEntry * entry);
 static void gst_system_clock_async_thread (GstClock * clock);
 static gboolean gst_system_clock_start_async (GstSystemClock * clock);
+static void gst_system_clock_add_wakeup (GstSystemClock * sysclock);
 
 static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
 
 static GstClockClass *parent_class = NULL;
 
 /* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_system_clock_get_type (void)
-{
-  static GType clock_type = 0;
-
-  if (G_UNLIKELY (clock_type == 0)) {
-    static const GTypeInfo clock_info = {
-      sizeof (GstSystemClockClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_system_clock_class_init,
-      NULL,
-      NULL,
-      sizeof (GstSystemClock),
-      0,
-      (GInstanceInitFunc) gst_system_clock_init,
-      NULL
-    };
-
-    clock_type = g_type_register_static (GST_TYPE_CLOCK, "GstSystemClock",
-        &clock_info, 0);
-  }
-  return clock_type;
-}
+G_DEFINE_TYPE (GstSystemClock, gst_system_clock, GST_TYPE_CLOCK);
 
 static void
 gst_system_clock_class_init (GstSystemClockClass * klass)
 {
   GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
   GstClockClass *gstclock_class;
 
   gobject_class = (GObjectClass *) klass;
-  gstobject_class = (GstObjectClass *) klass;
   gstclock_class = (GstClockClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
+  g_type_class_add_private (klass, sizeof (GstSystemClockPrivate));
+
   gobject_class->dispose = gst_system_clock_dispose;
+  gobject_class->set_property = gst_system_clock_set_property;
+  gobject_class->get_property = gst_system_clock_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE,
+      g_param_spec_enum ("clock-type", "Clock type",
+          "The type of underlying clock implementation used",
+          GST_TYPE_CLOCK_TYPE, DEFAULT_CLOCK_TYPE, G_PARAM_READWRITE));
 
   gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
   gstclock_class->get_resolution = gst_system_clock_get_resolution;
@@ -137,11 +154,16 @@
       GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
       GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
 
+  clock->priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
+
+  clock->priv->clock_type = DEFAULT_CLOCK_TYPE;
+  clock->priv->timer = gst_poll_new_timer ();
+
 #if 0
   /* Uncomment this to start the async clock thread straight away */
-  GST_CLOCK_LOCK (clock);
+  GST_OBJECT_LOCK (clock);
   gst_system_clock_start_async (clock);
-  GST_CLOCK_UNLOCK (clock);
+  GST_OBJECT_UNLOCK (clock);
 #endif
 }
 
@@ -149,8 +171,7 @@
 gst_system_clock_dispose (GObject * object)
 {
   GstClock *clock = (GstClock *) object;
-
-  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
   GList *entries;
 
   /* else we have to stop the thread */
@@ -166,6 +187,7 @@
   g_list_free (clock->entries);
   clock->entries = NULL;
   GST_CLOCK_BROADCAST (clock);
+  gst_system_clock_add_wakeup (sysclock);
   GST_OBJECT_UNLOCK (clock);
 
   if (sysclock->thread)
@@ -173,6 +195,8 @@
   sysclock->thread = NULL;
   GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
 
+  gst_poll_free (sysclock->priv->timer);
+
   G_OBJECT_CLASS (parent_class)->dispose (object);
 
   if (_the_system_clock == clock) {
@@ -181,6 +205,40 @@
   }
 }
 
+static void
+gst_system_clock_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object);
+
+  switch (prop_id) {
+    case PROP_CLOCK_TYPE:
+      sysclock->priv->clock_type = g_value_get_enum (value);
+      GST_CAT_DEBUG (GST_CAT_CLOCK, "clock-type set to %d",
+          sysclock->priv->clock_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_system_clock_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object);
+
+  switch (prop_id) {
+    case PROP_CLOCK_TYPE:
+      g_value_set_enum (value, sysclock->priv->clock_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
 /**
  * gst_system_clock_obtain:
  *
@@ -211,8 +269,7 @@
 
     /* we created the global clock; take ownership so
      * we can hand out instances later */
-    gst_object_ref (clock);
-    gst_object_sink (GST_OBJECT (clock));
+    gst_object_ref_sink (clock);
 
     _the_system_clock = clock;
     g_static_mutex_unlock (&_gst_sysclock_mutex);
@@ -226,6 +283,49 @@
   return clock;
 }
 
+static void
+gst_system_clock_remove_wakeup (GstSystemClock * sysclock)
+{
+  g_return_if_fail (sysclock->priv->wakeup_count > 0);
+
+  sysclock->priv->wakeup_count--;
+  if (sysclock->priv->wakeup_count == 0) {
+    /* read the control socket byte when we removed the last wakeup count */
+    GST_CAT_DEBUG (GST_CAT_CLOCK, "reading control");
+    while (!gst_poll_read_control (sysclock->priv->timer)) {
+      g_warning ("gstsystemclock: read control failed, trying again\n");
+    }
+    GST_CLOCK_BROADCAST (sysclock);
+  }
+  GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
+      sysclock->priv->wakeup_count);
+}
+
+static void
+gst_system_clock_add_wakeup (GstSystemClock * sysclock)
+{
+  /* only write the control socket for the first wakeup */
+  if (sysclock->priv->wakeup_count == 0) {
+    GST_CAT_DEBUG (GST_CAT_CLOCK, "writing control");
+    while (!gst_poll_write_control (sysclock->priv->timer)) {
+      g_warning
+          ("gstsystemclock: write control failed in wakeup_async, trying again : %d:%s\n",
+          errno, g_strerror (errno));
+    }
+  }
+  sysclock->priv->wakeup_count++;
+  GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
+      sysclock->priv->wakeup_count);
+}
+
+static void
+gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
+{
+  while (sysclock->priv->wakeup_count > 0) {
+    GST_CLOCK_WAIT (sysclock);
+  }
+}
+
 /* this thread reads the sorted clock entries from the queue.
  *
  * It waits on each of them and fires the callback when the timeout occurs.
@@ -241,7 +341,7 @@
 static void
 gst_system_clock_async_thread (GstClock * clock)
 {
-  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
 
   GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
   GST_OBJECT_LOCK (clock);
@@ -264,6 +364,14 @@
         goto exit;
     }
 
+    /* see if we have a pending wakeup because the order of the list
+     * changed. */
+    if (sysclock->priv->async_wakeup) {
+      GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
+      gst_system_clock_remove_wakeup (sysclock);
+      sysclock->priv->async_wakeup = FALSE;
+    }
+
     /* pick the next entry */
     entry = clock->entries->data;
     /* if it was unscheduled, just move on to the next entry */
@@ -289,7 +397,7 @@
       {
         /* entry timed out normally, fire the callback and move to the next
          * entry */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unlocked", entry);
+        GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p timed out", entry);
         if (entry->func) {
           /* unlock before firing the callback */
           GST_OBJECT_UNLOCK (clock);
@@ -298,6 +406,7 @@
           GST_OBJECT_LOCK (clock);
         }
         if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "updating periodic entry %p", entry);
           /* adjust time now */
           entry->time = requested + entry->interval;
           /* and resort the list now */
@@ -306,6 +415,7 @@
           /* and restart */
           continue;
         } else {
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "moving to next entry");
           goto next_entry;
         }
       }
@@ -315,6 +425,11 @@
          * was canceled. Whatever it is, pick the head entry of the list and
          * continue waiting. */
         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p needs restart", entry);
+
+        /* we set the entry back to the OK state. This is needed so that the
+         * _unschedule() code can see if an entry is currently being waited
+         * on (when its state is BUSY). */
+        entry->status = GST_CLOCK_OK;
         continue;
       default:
         GST_CAT_DEBUG (GST_CAT_CLOCK,
@@ -335,21 +450,60 @@
   GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
 }
 
+#ifdef HAVE_POSIX_TIMERS
+static inline clockid_t
+clock_type_to_posix_id (GstClockType clock_type)
+{
+#ifdef HAVE_MONOTONIC_CLOCK
+  if (clock_type == GST_CLOCK_TYPE_MONOTONIC)
+    return CLOCK_MONOTONIC;
+  else
+#endif
+    return CLOCK_REALTIME;
+}
+#endif
+
 /* MT safe */
 static GstClockTime
 gst_system_clock_get_internal_time (GstClock * clock)
 {
+#ifdef HAVE_POSIX_TIMERS
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+  clockid_t ptype;
+  struct timespec ts;
+
+  ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
+
+  if (G_UNLIKELY (clock_gettime (ptype, &ts)))
+    return GST_CLOCK_TIME_NONE;
+
+  return GST_TIMESPEC_TO_TIME (ts);
+#else
   GTimeVal timeval;
 
   g_get_current_time (&timeval);
 
   return GST_TIMEVAL_TO_TIME (timeval);
+#endif
 }
 
 static guint64
 gst_system_clock_get_resolution (GstClock * clock)
 {
+#ifdef HAVE_POSIX_TIMERS
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+  clockid_t ptype;
+  struct timespec ts;
+
+  ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
+
+  if (G_UNLIKELY (clock_getres (ptype, &ts)))
+    return GST_CLOCK_TIME_NONE;
+
+  return GST_TIMESPEC_TO_TIME (ts);
+#else
   return 1 * GST_USECOND;
+#endif
 }
 
 /* synchronously wait on the given GstClockEntry.
@@ -372,81 +526,115 @@
 gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
     GstClockEntry * entry, GstClockTimeDiff * jitter, gboolean restart)
 {
-  GstClockTime entryt, real, now, target;
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+  GstClockTime entryt, real, now;
   GstClockTimeDiff diff;
 
   /* need to call the overridden method because we want to sync against the time
    * of the clock, whatever the subclass uses as a clock. */
   real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
+  now = gst_clock_adjust_unlocked (clock, real);
+
+  /* get the time of the entry */
   entryt = GST_CLOCK_ENTRY_TIME (entry);
 
-  now = gst_clock_adjust_unlocked (clock, real);
   if (jitter) {
     *jitter = GST_CLOCK_DIFF (entryt, now);
   }
   /* the diff of the entry with the clock is the amount of time we have to
    * wait */
   diff = entryt - now;
-  /* Our GCond implementation expects an absolute time against the system clock
-   * as a timeout value. We use our internal time to get the system time and add
-   * the expected timeout to it, this gives us the absolute time of the
-   * timeout. */
-  target = gst_system_clock_get_internal_time (clock) + diff;
 
   GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p"
-      " target %" GST_TIME_FORMAT
-      " entry %" GST_TIME_FORMAT
+      " time %" GST_TIME_FORMAT
       " now %" GST_TIME_FORMAT
       " real %" GST_TIME_FORMAT
-      " diff (entry-now) %" G_GINT64_FORMAT,
+      " diff (time-now) %" G_GINT64_FORMAT,
       entry,
-      GST_TIME_ARGS (target),
       GST_TIME_ARGS (entryt), GST_TIME_ARGS (now), GST_TIME_ARGS (real), diff);
 
   if (diff > 0) {
-    GTimeVal tv;
-
 #ifdef WAIT_DEBUGGING
-    GstClockTime result, final;
+    GstClockTime final;
 #endif
 
-    GST_TIME_TO_TIMEVAL (target, tv);
+    while (entry->status != GST_CLOCK_UNSCHEDULED) {
+      gint pollret;
+
+      /* mark the entry as busy */
+      entry->status = GST_CLOCK_BUSY;
+      GST_OBJECT_UNLOCK (clock);
+
+      /* now wait on the entry, it either times out or the fd is written. */
+      pollret = gst_poll_wait (sysclock->priv->timer, diff);
+
+      /* another thread can read the fd before we get the lock */
+      GST_OBJECT_LOCK (clock);
+      if (entry->status == GST_CLOCK_UNSCHEDULED) {
+        GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked", entry);
+        gst_system_clock_remove_wakeup (sysclock);
+      } else {
+        if (pollret != 0) {
+          /* some other id got unlocked */
+          if (!restart) {
+            /* this can happen if the entry got unlocked because of an async
+             * entry was added to the head of the async queue. */
+            GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup waiting for entry %p", entry);
+            break;
+          }
+
+          /* mark ourselves as EARLY, we release the lock and we could be
+           * unscheduled ourselves but we don't want the unscheduling thread
+           * to write on the control socket (it does that when an entry has a
+           * BUSY status). */
+          entry->status = GST_CLOCK_EARLY;
 
-    while (TRUE) {
-      /* now wait on the entry, it either times out or the cond is signaled. */
-      if (!GST_CLOCK_TIMED_WAIT (clock, &tv)) {
-        /* timeout, this is fine, we can report success now */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout", entry);
-        entry->status = GST_CLOCK_OK;
+          /* wait till all the entries got woken up */
+          gst_system_clock_wait_wakeup (sysclock);
+
+          /* we released the lock in the wait, recheck our status, we don't need
+           * to remove the wakeup count because we marked the entry as EARLY
+           * before releasing the object lock. */
+          if (entry->status == GST_CLOCK_UNSCHEDULED) {
+            GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p got unscheduled", entry);
+            break;
+          }
+
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p needs to be restarted",
+              entry);
+        } else {
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout",
+              entry);
+        }
+
+        /* reschedule if gst_poll_wait returned early or we have to reschedule after
+         * an unlock*/
+        real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
+        now = gst_clock_adjust_unlocked (clock, real);
+        diff = entryt - now;
+
+        if (diff <= 0) {
+          /* timeout, this is fine, we can report success now */
+          entry->status = GST_CLOCK_OK;
+
+          GST_CAT_DEBUG (GST_CAT_CLOCK,
+              "entry %p finished, diff %" G_GINT64_FORMAT, entry, diff);
 
 #ifdef WAIT_DEBUGGING
-        real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
-        result = gst_clock_adjust_unlocked (clock, real);
-        final = gst_system_clock_get_internal_time (clock);
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT
-            " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT
-            " %g target-offset %" G_GINT64_FORMAT " %g", entryt, result,
-            result - entryt,
-            (double) (GstClockTimeDiff) (result - entryt) / GST_SECOND,
-            (final - target),
-            ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND);
+          final = gst_system_clock_get_internal_time (clock);
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT
+              " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT
+              " %g target-offset %" G_GINT64_FORMAT " %g", entryt, now,
+              now - entryt,
+              (double) (GstClockTimeDiff) (now - entryt) / GST_SECOND,
+              (final - target),
+              ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND);
 #endif
-        break;
-      } else {
-        /* the waiting is interrupted because the GCond was signaled. This can
-         * be because this or some other entry was unscheduled. */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked with signal", entry);
-        /* if the entry is unscheduled, we can stop waiting for it, else we
-         * continue our while loop. */
-        if (entry->status == GST_CLOCK_UNSCHEDULED)
           break;
-        /* else restart if we must */
-        if (!restart)
-          break;
-
-        /* this can happen if the entry got unlocked because of an async entry
-         * was added to the head of the async queue. */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "continue waiting for entry %p", entry);
+        } else {
+          GST_CAT_DEBUG (GST_CAT_CLOCK,
+              "entry %p restart, diff %" G_GINT64_FORMAT, entry, diff);
+        }
       }
     }
   } else if (diff == 0) {
@@ -464,10 +652,20 @@
   GstClockReturn ret;
 
   GST_OBJECT_LOCK (clock);
+  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
+    goto was_unscheduled;
+
   ret = gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter, TRUE);
   GST_OBJECT_UNLOCK (clock);
 
   return ret;
+
+  /* ERRORS */
+was_unscheduled:
+  {
+    GST_OBJECT_UNLOCK (clock);
+    return GST_CLOCK_UNSCHEDULED;
+  }
 }
 
 /* Start the async clock thread. Must be called with the object lock
@@ -477,12 +675,12 @@
 {
   GError *error = NULL;
 
-  if (clock->thread != NULL)
+  if (G_LIKELY (clock->thread != NULL))
     return TRUE;                /* Thread already running. Nothing to do */
 
   clock->thread = g_thread_create ((GThreadFunc) gst_system_clock_async_thread,
       clock, TRUE, &error);
-  if (error)
+  if (G_UNLIKELY (error))
     goto no_thread;
 
   /* wait for it to spin up */
@@ -494,6 +692,7 @@
 no_thread:
   {
     g_warning ("could not create async clock thread: %s", error->message);
+    g_error_free (error);
   }
   return FALSE;
 }
@@ -508,13 +707,25 @@
 static GstClockReturn
 gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
 {
+  GstSystemClock *sysclock;
+  GstClockEntry *head;
+
+  sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+
   GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
 
   GST_OBJECT_LOCK (clock);
+  /* Start the clock async thread if needed */
+  if (G_UNLIKELY (!gst_system_clock_start_async (sysclock)))
+    goto thread_error;
 
-  /* Start the clock async thread if needed */
-  if (!gst_system_clock_start_async (GST_SYSTEM_CLOCK (clock)))
-    goto thread_error;
+  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
+    goto was_unscheduled;
+
+  if (clock->entries)
+    head = clock->entries->data;
+  else
+    head = NULL;
 
   /* need to take a ref */
   gst_clock_id_ref ((GstClockID) entry);
@@ -526,21 +737,40 @@
    * front, else the thread is just waiting for another entry and
    * will get to this entry automatically. */
   if (clock->entries->data == entry) {
-    GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head, sending signal");
-    /* this will wake up _all_ entries waiting for the clock because we have
-     * only one cond for all entries (makes allocation faster). Entries that
-     * have not timed out will have their status set to BUSY and should continue
-     * to wait. In the case of the async ones, the new head entry should be
-     * taken and waited for. */
-    GST_CLOCK_BROADCAST (clock);
+    GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head");
+    if (head == NULL) {
+      /* the list was empty before, signal the cond so that the async thread can
+       * start taking a look at the queue */
+      GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
+      GST_CLOCK_BROADCAST (clock);
+    } else {
+      if (head->status == GST_CLOCK_BUSY) {
+        /* the async thread was waiting for an entry, unlock the wait so that it
+         * looks at the new head entry instead, we only need to do this once */
+        if (!sysclock->priv->async_wakeup) {
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
+          sysclock->priv->async_wakeup = TRUE;
+          gst_system_clock_add_wakeup (sysclock);
+        }
+      }
+    }
   }
   GST_OBJECT_UNLOCK (clock);
 
   return GST_CLOCK_OK;
 
+  /* ERRORS */
 thread_error:
-  /* Could not start the async clock thread */
-  return GST_CLOCK_ERROR;
+  {
+    /* Could not start the async clock thread */
+    GST_OBJECT_UNLOCK (clock);
+    return GST_CLOCK_ERROR;
+  }
+was_unscheduled:
+  {
+    GST_OBJECT_UNLOCK (clock);
+    return GST_CLOCK_UNSCHEDULED;
+  }
 }
 
 /* unschedule an entry. This will set the state of the entry to GST_CLOCK_UNSCHEDULED
@@ -553,14 +783,22 @@
 static void
 gst_system_clock_id_unschedule (GstClock * clock, GstClockEntry * entry)
 {
+  GstSystemClock *sysclock;
+
+  sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+
   GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
 
   GST_OBJECT_LOCK (clock);
-  /* mark entry as unscheduled, then wake up all entries. The entries that did
-   * not timeout will be woken up but immediatly go to sleep again because their
-   * status would still be busy. */
+  if (entry->status == GST_CLOCK_BUSY) {
+    /* the entry was being busy, wake up all entries so that they recheck their
+     * status. We cannot wake up just one entry because allocating such a
+     * datastructure for each entry would be too heavy and unlocking an entry
+     * is usually done when shutting down or some other exceptional case. */
+    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was BUSY, doing wakeup");
+    gst_system_clock_add_wakeup (sysclock);
+  }
+  /* when it leaves the poll, it'll detect the unscheduled */
   entry->status = GST_CLOCK_UNSCHEDULED;
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "sending signal");
-  GST_CLOCK_BROADCAST (clock);
   GST_OBJECT_UNLOCK (clock);
 }
--- a/gstreamer_core/gst/gstsystemclock.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstsystemclock.h	Fri Apr 16 15:15:52 2010 +0300
@@ -31,6 +31,7 @@
 
 #define GST_TYPE_SYSTEM_CLOCK 			(gst_system_clock_get_type ())
 #define GST_SYSTEM_CLOCK(obj) 			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SYSTEM_CLOCK, GstSystemClock))
+#define GST_SYSTEM_CLOCK_CAST(obj)		((GstSystemClock *)(obj))
 #define GST_IS_SYSTEM_CLOCK(obj) 		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SYSTEM_CLOCK))
 #define GST_SYSTEM_CLOCK_CLASS(klass) 		(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SYSTEM_CLOCK, GstSystemClockClass))
 #define GST_IS_SYSTEM_CLOCK_CLASS(klass) 	(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SYSTEM_CLOCK))
@@ -39,6 +40,20 @@
 
 typedef struct _GstSystemClock GstSystemClock;
 typedef struct _GstSystemClockClass GstSystemClockClass;
+typedef struct _GstSystemClockPrivate GstSystemClockPrivate;
+
+/**
+ * GstClockType:
+ * @GST_CLOCK_TYPE_REALTIME: time since Epoch
+ * @GST_CLOCK_TYPE_MONOTONIC: monotonic time since some unspecified starting
+ *                            point
+ *
+ * The different kind of clocks.
+ */
+typedef enum {
+  GST_CLOCK_TYPE_REALTIME	= 0,
+  GST_CLOCK_TYPE_MONOTONIC	= 1
+} GstClockType;
 
 /**
  * GstSystemClock:
@@ -53,7 +68,10 @@
   GThread	*thread;	/* thread for async notify */
   gboolean 	 stopping;
 
-  gpointer _gst_reserved[GST_PADDING];
+  /* ABI added */
+  GstSystemClockPrivate *priv;
+
+  gpointer _gst_reserved[GST_PADDING - 1];
 };
 
 struct _GstSystemClockClass {
--- a/gstreamer_core/gst/gsttaglist.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttaglist.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,7 +25,9 @@
  *
  * List of tags and values used to describe media metadata.
  *
- * Last reviewed on 2005-11-23 (0.9.5)
+ * Strings must be in ASCII or UTF-8 encoding. No other encodings are allowed.
+ *
+ * Last reviewed on 2009-06-09 (0.10.23)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -38,6 +40,7 @@
 #include "gstinfo.h"
 #include "gstvalue.h"
 #include "gstbuffer.h"
+#include "gstquark.h"
 
 #include <gobject/gvaluecollector.h>
 #include <string.h>
@@ -64,9 +67,8 @@
 }
 GstTagInfo;
 
-#define TAGLIST "taglist"
-static GQuark gst_tag_list_quark;
 static GMutex *__tag_mutex;
+
 static GHashTable *__tags;
 
 #define TAG_LOCK g_mutex_lock (__tag_mutex)
@@ -75,6 +77,7 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 GType
 gst_tag_list_get_type (void)
 {
@@ -100,7 +103,6 @@
 void
 _gst_tag_initialize (void)
 {
-  gst_tag_list_quark = g_quark_from_static_string (TAGLIST);
   __tag_mutex = g_mutex_new ();
   __tags = g_hash_table_new (g_direct_hash, g_direct_equal);
   gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META,
@@ -162,18 +164,21 @@
   gst_tag_register (GST_TAG_LOCATION, GST_TAG_FLAG_META,
       G_TYPE_STRING,
       _("location"),
-      _("original location of file as a URI"),
+      _
+      ("Origin of media as a URI (location, where the original of the file or stream is hosted)"),
       gst_tag_merge_strings_with_comma);
-  gst_tag_register (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META,
+  gst_tag_register (GST_TAG_HOMEPAGE, GST_TAG_FLAG_META,
       G_TYPE_STRING,
-      _("description"),
-      _("short text describing the content of the data"),
+      _("homepage"),
+      _
+      ("Homepage for this media (i.e. artist or movie homepage)"),
       gst_tag_merge_strings_with_comma);
-  gst_tag_register (GST_TAG_VERSION, GST_TAG_FLAG_META,
-      G_TYPE_STRING, _("version"), _("version of this data"), NULL);
-  gst_tag_register (GST_TAG_ISRC, GST_TAG_FLAG_META,
-      G_TYPE_STRING,
-      _("ISRC"),
+  gst_tag_register (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META, G_TYPE_STRING,
+      _("description"), _("short text describing the content of the data"),
+      gst_tag_merge_strings_with_comma);
+  gst_tag_register (GST_TAG_VERSION, GST_TAG_FLAG_META, G_TYPE_STRING,
+      _("version"), _("version of this data"), NULL);
+  gst_tag_register (GST_TAG_ISRC, GST_TAG_FLAG_META, G_TYPE_STRING, _("ISRC"),
       _
       ("International Standard Recording Code - see http://www.ifpi.org/isrc/"),
       NULL);
@@ -214,6 +219,12 @@
   gst_tag_register (GST_TAG_AUDIO_CODEC, GST_TAG_FLAG_ENCODED,
       G_TYPE_STRING,
       _("audio codec"), _("codec the audio data is stored in"), NULL);
+  gst_tag_register (GST_TAG_SUBTITLE_CODEC, GST_TAG_FLAG_ENCODED,
+      G_TYPE_STRING,
+      _("subtitle codec"), _("codec the subtitle data is stored in"), NULL);
+  gst_tag_register (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED,
+      G_TYPE_STRING, _("container format"),
+      _("container format the data is stored in"), NULL);
   gst_tag_register (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED,
       G_TYPE_UINT, _("bitrate"), _("exact or average bitrate in bits/s"), NULL);
   gst_tag_register (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED,
@@ -249,9 +260,34 @@
       _("image"), _("image related to this stream"), gst_tag_merge_use_first);
   gst_tag_register (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
       _("preview image"), _("preview image related to this stream"), NULL);
+  gst_tag_register (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
+      _("attachment"), _("file attached to this stream"),
+      gst_tag_merge_use_first);
   gst_tag_register (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META, G_TYPE_DOUBLE,
       _("beats per minute"), _("number of beats per minute in audio"), NULL);
-
+  gst_tag_register (GST_TAG_KEYWORDS, GST_TAG_FLAG_META, G_TYPE_STRING,
+      _("keywords"), _("comma separated keywords describing the content"),
+      gst_tag_merge_strings_with_comma);
+  gst_tag_register (GST_TAG_GEO_LOCATION_NAME, GST_TAG_FLAG_META, G_TYPE_STRING,
+      _("geo location name"),
+      _
+      ("human readable descriptive location of where the media has been recorded or produced"),
+      NULL);
+  gst_tag_register (GST_TAG_GEO_LOCATION_LATITUDE, GST_TAG_FLAG_META,
+      G_TYPE_DOUBLE, _("geo location latitude"),
+      _
+      ("geo latitude location of where the media has been recorded or produced in degrees according to WGS84 (zero at the equator, negative values for southern latitudes)"),
+      NULL);
+  gst_tag_register (GST_TAG_GEO_LOCATION_LONGITUDE, GST_TAG_FLAG_META,
+      G_TYPE_DOUBLE, _("geo location longitude"),
+      _
+      ("geo longitude location of where the media has been recorded or produced in degrees according to WGS84 (zero at the prime meridian in Greenwich/UK,  negative values for western longitudes)"),
+      NULL);
+  gst_tag_register (GST_TAG_GEO_LOCATION_ELEVATION, GST_TAG_FLAG_META,
+      G_TYPE_DOUBLE, _("geo location elevation"),
+      _
+      ("geo elevation of where the media has been recorded or produced in meters according to WGS84 (zero is average sea level)"),
+      NULL);
 }
 
 /**
@@ -292,6 +328,7 @@
 gst_tag_merge_strings_with_comma (GValue * dest, const GValue * src)
 {
   GString *str;
+
   gint i, count;
 
   count = gst_value_list_get_size (src);
@@ -305,9 +342,10 @@
   }
 
   g_value_init (dest, G_TYPE_STRING);
-  g_value_set_string_take_ownership (dest, str->str);
+  g_value_take_string (dest, str->str);
   g_string_free (str, FALSE);
 }
+
 static GstTagInfo *
 gst_tag_lookup (GQuark entry)
 {
@@ -360,6 +398,7 @@
     const gchar * nick, const gchar * blurb, GstTagMergeFunc func)
 {
   GQuark key;
+
   GstTagInfo *info;
 
   g_return_if_fail (name != NULL);
@@ -544,7 +583,76 @@
 GstTagList *
 gst_tag_list_new (void)
 {
-  return GST_TAG_LIST (gst_structure_new (TAGLIST, NULL));
+  return GST_TAG_LIST (gst_structure_id_empty_new (GST_QUARK (TAGLIST)));
+}
+
+/**
+ * gst_tag_list_new_full:
+ * @tag: tag
+ * @...: NULL-terminated list of values to set
+ *
+ * Creates a new taglist and appends the values for the given tags. It expects
+ * tag-value pairs like gst_tag_list_add(), and a NULL terminator after the
+ * last pair. The type of the values is implicit and is documented in the API
+ * reference, but can also be queried at runtime with gst_tag_get_type(). It
+ * is an error to pass a value of a type not matching the tag type into this
+ * function. The tag list will make copies of any arguments passed
+ * (e.g. strings, buffers).
+ *
+ * Returns: a new #GstTagList. Free with gst_tag_list_free() when no longer
+ *     needed.
+ *
+ * Since: 0.10.24
+ */
+/* FIXME 0.11: rename gst_tag_list_new_full to _new and _new to _new_empty */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstTagList *
+gst_tag_list_new_full (const gchar * tag, ...)
+{
+  GstTagList *list;
+  va_list args;
+
+  g_return_val_if_fail (tag != NULL, NULL);
+
+  list = gst_tag_list_new ();
+  va_start (args, tag);
+  gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, args);
+  va_end (args);
+
+  return list;
+}
+
+/**
+ * gst_tag_list_new_full_valist:
+ * @var_args: tag / value pairs to set
+ *
+ * Just like gst_tag_list_new_full(), only that it takes a va_list argument.
+ * Useful mostly for language bindings.
+ *
+ * Returns: a new #GstTagList. Free with gst_tag_list_free() when no longer
+ *     needed.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstTagList *
+gst_tag_list_new_full_valist (va_list var_args)
+{
+  GstTagList *list;
+  const gchar *tag;
+
+  list = gst_tag_list_new ();
+
+  tag = va_arg (var_args, gchar *);
+  gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, var_args);
+
+  return list;
 }
 
 /**
@@ -589,19 +697,22 @@
 
   g_return_val_if_fail (p != NULL, FALSE);
 
-  return (GST_IS_STRUCTURE (s) && s->name == gst_tag_list_quark);
+  return (GST_IS_STRUCTURE (s) && s->name == GST_QUARK (TAGLIST));
 }
+
 typedef struct
 {
   GstStructure *list;
   GstTagMergeMode mode;
 }
 GstTagCopyData;
+
 static void
 gst_tag_list_add_value_internal (GstStructure * list, GstTagMergeMode mode,
     GQuark tag, const GValue * value)
 {
   GstTagInfo *info = gst_tag_lookup (tag);
+
   const GValue *value2;
 
   g_assert (info != NULL);
@@ -652,6 +763,7 @@
     }
   }
 }
+
 static gboolean
 gst_tag_list_copy_foreach (GQuark tag, const GValue * value, gpointer user_data)
 {
@@ -668,7 +780,7 @@
  * @from: list to merge from
  * @mode: the mode to use
  *
- * Inserts the tags of the second list into the first list using the given mode.
+ * Inserts the tags of the @from list into the first list using the given mode.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -732,23 +844,28 @@
 gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2,
     GstTagMergeMode mode)
 {
+  GstTagList *list1_cp;
+  const GstTagList *list2_cp;
+
   g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
   g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
   g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
 
+  /* nothing to merge */
   if (!list1 && !list2) {
     return NULL;
-  } else if (!list1) {
-    return gst_tag_list_copy (list2);
-  } else if (!list2) {
-    return gst_tag_list_copy (list1);
-  } else {
-    GstTagList *ret;
+  }
+
+  /* create empty list, we need to do this to correctly handling merge modes */
+  list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new ();
+  list2_cp = (list2) ? list2 : gst_tag_list_new ();
 
-    ret = gst_tag_list_copy (list1);
-    gst_tag_list_insert (ret, list2, mode);
-    return ret;
-  }
+  gst_tag_list_insert (list1_cp, list2_cp, mode);
+
+  if (!list2)
+    gst_tag_list_free ((GstTagList *) list2_cp);
+
+  return list1_cp;
 }
 
 /**
@@ -878,6 +995,10 @@
   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
   g_return_if_fail (tag != NULL);
 
+  if (mode == GST_TAG_MERGE_REPLACE_ALL) {
+    gst_structure_remove_all_fields (list);
+  }
+
   while (tag != NULL) {
     GValue value = { 0, };
 
@@ -919,17 +1040,19 @@
 gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
     const gchar * tag, va_list var_args)
 {
-  GstTagInfo *info;
   GQuark quark;
 
   g_return_if_fail (GST_IS_TAG_LIST (list));
   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
   g_return_if_fail (tag != NULL);
 
+  if (mode == GST_TAG_MERGE_REPLACE_ALL) {
+    gst_structure_remove_all_fields (list);
+  }
+
   while (tag != NULL) {
     quark = g_quark_from_string (tag);
-    info = gst_tag_lookup (quark);
-    g_return_if_fail (info != NULL);
+    g_return_if_fail (gst_tag_lookup (quark) != NULL);
     gst_tag_list_add_value_internal (list, mode, quark, va_arg (var_args,
             GValue *));
     tag = va_arg (var_args, gchar *);
@@ -937,6 +1060,33 @@
 }
 
 /**
+ * gst_tag_list_add_value:
+ * @list: list to set tags in
+ * @mode: the mode to use
+ * @tag: tag
+ * @value: GValue for this tag
+ *
+ * Sets the GValue for a given tag using the specified mode.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_tag_list_add_value (GstTagList * list, GstTagMergeMode mode,
+    const gchar * tag, const GValue * value)
+{
+  g_return_if_fail (GST_IS_TAG_LIST (list));
+  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
+  g_return_if_fail (tag != NULL);
+
+  gst_tag_list_add_value_internal (list, mode, g_quark_from_string (tag),
+      value);
+}
+
+/**
  * gst_tag_list_remove_tag:
  * @list: list to remove tag from
  * @tag: tag to remove
@@ -955,6 +1105,7 @@
 
   gst_structure_remove_field ((GstStructure *) list, tag);
 }
+
 typedef struct
 {
   GstTagForeachFunc func;
@@ -962,6 +1113,7 @@
   gpointer data;
 }
 TagForeachData;
+
 static int
 structure_foreach_wrapper (GQuark field_id, const GValue * value,
     gpointer user_data)
@@ -1077,6 +1229,9 @@
   if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
     GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
 
+    if (!info)
+      return FALSE;
+
     /* must be there or lists aren't allowed */
     g_assert (info->merge_func);
     info->merge_func (dest, src);
@@ -1098,7 +1253,7 @@
 
 /***** evil macros to get all the gst_tag_list_get_*() functions right *****/
 
-#define TAG_MERGE_FUNCS(name,type)                                      \
+#define TAG_MERGE_FUNCS(name,type,ret)                                  \
 gboolean                                                                \
 __declspec(dllexport)	gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag,    \
                            type *value)                                 \
@@ -1113,7 +1268,7 @@
       return FALSE;                                                     \
   *value = COPY_FUNC (g_value_get_ ## name (&v));                       \
   g_value_unset (&v);                                                   \
-  return TRUE;                                                          \
+  return ret;                                                           \
 }                                                                       \
                                                                         \
 __declspec(dllexport)	gboolean                                                                \
@@ -1130,7 +1285,7 @@
   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)    \
       return FALSE;                                                     \
   *value = COPY_FUNC (g_value_get_ ## name (v));                        \
-  return TRUE;                                                          \
+  return ret;                                                           \
 }
 
 /* FIXME 0.11: maybe get rid of _get_char*(), _get_uchar*(), _get_long*(),
@@ -1163,7 +1318,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (char, gchar)
+TAG_MERGE_FUNCS (char, gchar, TRUE)
 /**
  * gst_tag_list_get_uchar:
  * @list: a #GstTagList to get the tag from
@@ -1189,7 +1344,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (uchar, guchar)
+TAG_MERGE_FUNCS (uchar, guchar, TRUE)
 /**
  * gst_tag_list_get_boolean:
  * @list: a #GstTagList to get the tag from
@@ -1215,7 +1370,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (boolean, gboolean)
+TAG_MERGE_FUNCS (boolean, gboolean, TRUE)
 /**
  * gst_tag_list_get_int:
  * @list: a #GstTagList to get the tag from
@@ -1241,7 +1396,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (int, gint)
+TAG_MERGE_FUNCS (int, gint, TRUE)
 /**
  * gst_tag_list_get_uint:
  * @list: a #GstTagList to get the tag from
@@ -1267,7 +1422,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (uint, guint)
+TAG_MERGE_FUNCS (uint, guint, TRUE)
 /**
  * gst_tag_list_get_long:
  * @list: a #GstTagList to get the tag from
@@ -1293,7 +1448,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (long, glong)
+TAG_MERGE_FUNCS (long, glong, TRUE)
 /**
  * gst_tag_list_get_ulong:
  * @list: a #GstTagList to get the tag from
@@ -1319,7 +1474,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (ulong, gulong)
+TAG_MERGE_FUNCS (ulong, gulong, TRUE)
 /**
  * gst_tag_list_get_int64:
  * @list: a #GstTagList to get the tag from
@@ -1345,7 +1500,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (int64, gint64)
+TAG_MERGE_FUNCS (int64, gint64, TRUE)
 /**
  * gst_tag_list_get_uint64:
  * @list: a #GstTagList to get the tag from
@@ -1371,7 +1526,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (uint64, guint64)
+TAG_MERGE_FUNCS (uint64, guint64, TRUE)
 /**
  * gst_tag_list_get_float:
  * @list: a #GstTagList to get the tag from
@@ -1397,7 +1552,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (float, gfloat)
+TAG_MERGE_FUNCS (float, gfloat, TRUE)
 /**
  * gst_tag_list_get_double:
  * @list: a #GstTagList to get the tag from
@@ -1423,7 +1578,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (double, gdouble)
+TAG_MERGE_FUNCS (double, gdouble, TRUE)
 /**
  * gst_tag_list_get_pointer:
  * @list: a #GstTagList to get the tag from
@@ -1449,7 +1604,7 @@
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (pointer, gpointer)
+TAG_MERGE_FUNCS (pointer, gpointer, (*value != NULL))
 #undef COPY_FUNC
 #define COPY_FUNC g_strdup
 /**
@@ -1465,7 +1620,8 @@
  * to retrieve the first string associated with this tag unmodified.
  *
  * The resulting string in @value will be in UTF-8 encoding and should be
- * freed by the caller using g_free when no longer needed.
+ * freed by the caller using g_free when no longer needed. Since 0.10.24 the
+ * returned string is also guaranteed to be non-NULL and non-empty.
  *
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
@@ -1481,23 +1637,25 @@
  * list.
  *
  * The resulting string in @value will be in UTF-8 encoding and should be
- * freed by the caller using g_free when no longer needed.
+ * freed by the caller using g_free when no longer needed. Since 0.10.24 the
+ * returned string is also guaranteed to be non-NULL and non-empty.
  *
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list.
  */
-TAG_MERGE_FUNCS (string, gchar *)
+TAG_MERGE_FUNCS (string, gchar *, (*value != NULL && **value != '\0'))
 
 /**
  * gst_tag_list_get_date:
  * @list: a #GstTagList to get the tag from
  * @tag: tag to read out
- * @value: location for the result
+ * @value: address of a GDate pointer variable to store the result into
  *
- * Copies the contents for the given tag into the value, merging multiple values
- * into one if multiple values are associated with the tag.
+ * Copies the first date for the given tag in the taglist into the variable
+ * pointed to by @value. Free the date with g_date_free() when it is no longer
+ * needed.
  *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
+ * Returns: TRUE, if a date was copied, FALSE if the tag didn't exist in the
  *              given list or if it was #NULL.
  */
 #ifdef __SYMBIAN32__
@@ -1528,8 +1686,9 @@
  * @index: number of entry to read out
  * @value: location for the result
  *
- * Gets the value that is at the given index for the given tag in the given
- * list.
+ * Gets the date that is at the given index for the given tag in the given
+ * list and copies it into the variable pointed to by @value. Free the date
+ * with g_date_free() when it is no longer needed.
  *
  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
  *              given list or if it was #NULL.
@@ -1553,3 +1712,75 @@
   *value = (GDate *) g_value_dup_boxed (v);
   return (*value != NULL);
 }
+
+/**
+ * gst_tag_list_get_buffer:
+ * @list: a #GstTagList to get the tag from
+ * @tag: tag to read out
+ * @value: address of a GstBuffer pointer variable to store the result into
+ *
+ * Copies the first buffer for the given tag in the taglist into the variable
+ * pointed to by @value. Free the buffer with gst_buffer_unref() when it is
+ * no longer needed.
+ *
+ * Returns: TRUE, if a buffer was copied, FALSE if the tag didn't exist in the
+ *              given list or if it was #NULL.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_tag_list_get_buffer (const GstTagList * list, const gchar * tag,
+    GstBuffer ** value)
+{
+  GValue v = { 0, };
+
+  g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
+  g_return_val_if_fail (tag != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  if (!gst_tag_list_copy_value (&v, list, tag))
+    return FALSE;
+  *value = (GstBuffer *) gst_value_dup_mini_object (&v);
+  g_value_unset (&v);
+  return (*value != NULL);
+}
+
+/**
+ * gst_tag_list_get_buffer_index:
+ * @list: a #GstTagList to get the tag from
+ * @tag: tag to read out
+ * @index: number of entry to read out
+ * @value: address of a GstBuffer pointer variable to store the result into
+ *
+ * Gets the buffer that is at the given index for the given tag in the given
+ * list and copies it into the variable pointed to by @value. Free the buffer
+ * with gst_buffer_unref() when it is no longer needed.
+ *
+ * Returns: TRUE, if a buffer was copied, FALSE if the tag didn't exist in the
+ *              given list or if it was #NULL.
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_tag_list_get_buffer_index (const GstTagList * list,
+    const gchar * tag, guint index, GstBuffer ** value)
+{
+  const GValue *v;
+
+  g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
+  g_return_val_if_fail (tag != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
+    return FALSE;
+  *value = (GstBuffer *) gst_value_dup_mini_object (v);
+  return (*value != NULL);
+}
--- a/gstreamer_core/gst/gsttaglist.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttaglist.h	Fri Apr 16 15:15:52 2010 +0300
@@ -23,6 +23,7 @@
 #ifndef __GST_TAGLIST_H__
 #define __GST_TAGLIST_H__
 
+#include <gst/gstbuffer.h>
 #include <gst/gststructure.h>
 #include <gst/glib-compat.h>
 
@@ -40,12 +41,12 @@
  * @GST_TAG_MERGE_COUNT: the number of merge modes
  *
  * The different tag merging modes are basically replace, overwrite and append,
- * but they can be seen from two directions.
- * Given two taglists: A - the one that are supplied to
- * gst_tag_setter_merge_tags() or gst_tag_setter_add_tags() and B - the tags
- * already in the element, how are the tags merged? In the table below this is
- * shown for the cases that a tag exists in the list (A) or does not exists (!A)
- * and combination thereof.
+ * but they can be seen from two directions. Given two taglists: (A) the tags
+ * already in the element and (B) the ones that are supplied to the element (
+ * e.g. via gst_tag_setter_merge_tags() / gst_tag_setter_add_tags() or a
+ * %GST_EVENT_TAG), how are these tags merged?
+ * In the table below this is shown for the cases that a tag exists in the list
+ * (A) or does not exists (!A) and combinations thereof.
  *
  * <table frame="all" colsep="1" rowsep="1">
  *   <title>merge mode</title>
@@ -245,6 +246,17 @@
 IMPORT_C
 #endif
 
+GstTagList * gst_tag_list_new_full          (const gchar * tag, ...);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstTagList * gst_tag_list_new_full_valist   (va_list var_args);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 gboolean     gst_is_tag_list                (gconstpointer p);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -317,6 +329,14 @@
 IMPORT_C
 #endif
 
+void         gst_tag_list_add_value         (GstTagList       * list,
+                                             GstTagMergeMode    mode,
+                                             const gchar      * tag,
+                                             const GValue     * value);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void         gst_tag_list_remove_tag        (GstTagList       * list,
                                              const gchar      * tag);
 #ifdef __SYMBIAN32__
@@ -554,6 +574,21 @@
                                              const gchar      * tag,
                                              guint              index,
                                              GDate           ** value);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean     gst_tag_list_get_buffer        (const GstTagList * list,
+                                             const gchar      * tag,
+                                             GstBuffer       ** value);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean     gst_tag_list_get_buffer_index  (const GstTagList * list,
+                                             const gchar      * tag,
+                                             guint              index,
+                                             GstBuffer       ** value);
 
 /* GStreamer core tags */
 /**
@@ -681,10 +716,19 @@
 /**
  * GST_TAG_LOCATION:
  *
- * original location of file as a URI (string)
+ * Origin of media as a URI (location, where the original of the file or stream
+ * is hosted) (string)
  */
 #define GST_TAG_LOCATION               "location"
 /**
+ * GST_TAG_HOMEPAGE:
+ *
+ * Homepage for this media (i.e. artist or movie homepage) (string)
+ *
+ * Since: 0.10.23
+ */
+#define GST_TAG_HOMEPAGE               "homepage"
+/**
  * GST_TAG_DESCRIPTION:
  *
  * short text describing the content of the data (string)
@@ -773,6 +817,22 @@
  */
 #define GST_TAG_AUDIO_CODEC            "audio-codec"
 /**
+ * GST_TAG_SUBTITLE_CODEC:
+ *
+ * codec/format the subtitle data is stored in (string)
+ *
+ * Since: 0.10.23
+ */
+#define GST_TAG_SUBTITLE_CODEC         "subtitle-codec"
+/**
+ * GST_TAG_CONTAINER_FORMAT:
+ *
+ * container format the data is stored in (string)
+ *
+ * Since: 0.10.24
+ */
+#define GST_TAG_CONTAINER_FORMAT       "container-format"
+/**
  * GST_TAG_BITRATE:
  *
  * exact or average bitrate in bits/s (unsigned integer)
@@ -849,13 +909,14 @@
 /**
  * GST_TAG_LANGUAGE_CODE:
  *
- * Language code (ISO-639-1) (string)
+ * Language code (ISO-639-1) (string) of the content
  */
 #define GST_TAG_LANGUAGE_CODE          "language-code"
 /**
  * GST_TAG_IMAGE:
  *
- * image (buffer) (buffer caps should specify the content type)
+ * image (buffer) (buffer caps should specify the content type and preferably
+ * also set "image-type" field as #GstTagImageType)
  *
  * Since: 0.10.6
  */
@@ -863,12 +924,24 @@
 /**
  * GST_TAG_PREVIEW_IMAGE:
  *
- * image that is meant for preview purposes (buffer)
- * (buffer caps should specify the content type)
+ * image that is meant for preview purposes, e.g. small icon-sized version
+ * (buffer) (buffer caps should specify the content type)
  *
  * Since: 0.10.7
  */
 #define GST_TAG_PREVIEW_IMAGE          "preview-image"
+
+/**
+ * GST_TAG_ATTACHMENT:
+ *
+ * generic file attachment (buffer) (buffer caps should specify the content
+ * type and if possible set "filename" to the file name of the
+ * attachment)
+ *
+ * Since: 0.10.21
+ */
+#define GST_TAG_ATTACHMENT             "attachment"
+
 /**
  * GST_TAG_BEATS_PER_MINUTE:
  *
@@ -878,6 +951,57 @@
  */
 #define GST_TAG_BEATS_PER_MINUTE       "beats-per-minute"
 
+/**
+ * GST_TAG_KEYWORDS:
+ *
+ * comma separated keywords describing the content (string).
+ *
+ * Since: 0.10.21
+ */
+#define GST_TAG_KEYWORDS               "keywords"
+
+/**
+ * GST_TAG_GEO_LOCATION_NAME:
+ *
+ * human readable descriptive location of where the media has been recorded or
+ * produced. (string).
+ *
+ * Since: 0.10.21
+ */
+#define GST_TAG_GEO_LOCATION_NAME               "geo-location-name"
+
+/**
+ * GST_TAG_GEO_LOCATION_LATITUDE:
+ *
+ * geo latitude location of where the media has been recorded or produced in
+ * degrees according to WGS84 (zero at the equator, negative values for southern
+ * latitudes) (double).
+ *
+ * Since: 0.10.21
+ */
+#define GST_TAG_GEO_LOCATION_LATITUDE               "geo-location-latitude"
+
+/**
+ * GST_TAG_GEO_LOCATION_LONGITUDE:
+ *
+ * geo longitude location of where the media has been recorded or produced in
+ * degrees according to WGS84 (zero at the prime meridian in Greenwich/UK,
+ * negative values for western longitudes). (double).
+ *
+ * Since: 0.10.21
+ */
+#define GST_TAG_GEO_LOCATION_LONGITUDE               "geo-location-longitude"
+
+/**
+ * GST_TAG_GEO_LOCATION_ELEVATION:
+ *
+ * geo elevation of where the media has been recorded or produced in meters
+ * according to WGS84 (zero is average sea level) (double).
+ *
+ * Since: 0.10.21
+ */
+#define GST_TAG_GEO_LOCATION_ELEVATION               "geo-location-elevation"
+
 G_END_DECLS
 
 #endif /* __GST_TAGLIST_H__ */
--- a/gstreamer_core/gst/gsttagsetter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttagsetter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,30 +24,26 @@
  * @short_description: Element interface that allows setting and retrieval
  *                     of media metadata
  *
- * <refsect2>
- * <para>
  * Element interface that allows setting of media metadata.
- * </para>
- * <para>
+ *
  * Elements that support changing a stream's metadata will implement this
  * interface. Examples of such elements are 'vorbisenc', 'theoraenc' and
  * 'id3v2mux'.
- * </para>
- * <para>
+ * 
  * If you just want to retrieve metadata in your application then all you
  * need to do is watch for tag messages on your pipeline's bus. This
  * interface is only for setting metadata, not for extracting it. To set tags
  * from the application, find tagsetter elements and set tags using e.g.
- * gst_tag_setter_merge_tags() or gst_tag_setter_add_tags(). The application
- * should do that before the element goes to %GST_STATE_PAUSED.
- * </para>
- * <para>
+ * gst_tag_setter_merge_tags() or gst_tag_setter_add_tags(). Also consider
+ * setting the #GstTagMergeMode that is used for tag events that arrive at the
+ * tagsetter element (default mode is to keep existing tags).
+ * The application should do that before the element goes to %GST_STATE_PAUSED.
+ * 
  * Elements implementing the #GstTagSetter interface often have to merge
  * any tags received from upstream and the tags set by the application via
  * the interface. This can be done like this:
- * </para>
- * <para>
- * <programlisting>
+ *
+ * |[
  * GstTagMergeMode merge_mode;
  * const GstTagList *application_tags;
  * const GstTagList *event_tags;
@@ -57,7 +53,7 @@
  * tagsetter = GST_TAG_SETTER (element);
  *  
  * merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter);
- * tagsetter_tags = gst_tag_setter_get_tag_list (tagsetter);
+ * application_tags = gst_tag_setter_get_tag_list (tagsetter);
  * event_tags = (const GstTagList *) element->event_tags;
  *  
  * GST_LOG_OBJECT (tagsetter, "merging tags, merge mode = %d", merge_mode);
@@ -67,12 +63,9 @@
  * result = gst_tag_list_merge (application_tags, event_tags, merge_mode);
  *  
  * GST_LOG_OBJECT (tagsetter, "final tags: %" GST_PTR_FORMAT, result);
- * </programlisting>
- * </para>
- * <para>
+ * ]|
+ * 
  * Last reviewed on 2006-05-18 (0.10.6)
- * </para>
- * </refsect2>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -93,8 +86,7 @@
 {
   GstTagMergeMode mode;
   GstTagList *list;
-}
-GstTagData;
+} GstTagData;
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -103,9 +95,10 @@
 GType
 gst_tag_setter_get_type (void)
 {
-  static GType tag_setter_type = 0;
+  static volatile gsize tag_setter_type = 0;
 
-  if (G_UNLIKELY (tag_setter_type == 0)) {
+  if (g_once_init_enter (&tag_setter_type)) {
+    GType _type;
     static const GTypeInfo tag_setter_info = {
       sizeof (GstTagSetterIFace),       /* class_size */
       NULL,                     /* base_init */
@@ -121,16 +114,18 @@
     GST_DEBUG_CATEGORY_INIT (gst_tag_interface_debug, "GstTagInterface", 0,
         "interfaces for tagging");
 
-    tag_setter_type = g_type_register_static (G_TYPE_INTERFACE, "GstTagSetter",
+    _type = g_type_register_static (G_TYPE_INTERFACE, "GstTagSetter",
         &tag_setter_info, 0);
 
-    g_type_interface_add_prerequisite (tag_setter_type, GST_TYPE_ELEMENT);
+    g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT);
 
     gst_tag_key = g_quark_from_static_string ("GST_TAG_SETTER");
+    g_once_init_leave (&tag_setter_type, _type);
   }
 
   return tag_setter_type;
 }
+
 static void
 gst_tag_data_free (gpointer p)
 {
@@ -141,6 +136,7 @@
 
   g_free (data);
 }
+
 static GstTagData *
 gst_tag_setter_get_data (GstTagSetter * setter)
 {
@@ -159,6 +155,33 @@
 }
 
 /**
+ * gst_tag_setter_reset_tags:
+ * @setter: a #GstTagSetter
+ *
+ * Reset the internal taglist. Elements should call this from within the
+ * state-change handler.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_tag_setter_reset_tags (GstTagSetter * setter)
+{
+  GstTagData *data;
+
+  g_return_if_fail (GST_IS_TAG_SETTER (setter));
+
+  data = gst_tag_setter_get_data (setter);
+  if (data->list) {
+    gst_tag_list_free (data->list);
+    data->list = NULL;
+  }
+}
+
+/**
  * gst_tag_setter_merge_tags:
  * @setter: a #GstTagSetter
  * @list: a tag list to merge from
@@ -181,8 +204,9 @@
   g_return_if_fail (GST_IS_TAG_LIST (list));
 
   data = gst_tag_setter_get_data (setter);
-  if (!data->list) {
-    data->list = gst_tag_list_copy (list);
+  if (data->list == NULL) {
+    if (mode != GST_TAG_MERGE_KEEP_ALL)
+      data->list = gst_tag_list_copy (list);
   } else {
     gst_tag_list_insert (data->list, list, mode);
   }
@@ -305,6 +329,37 @@
 }
 
 /**
+ * gst_tag_setter_add_tag_value:
+ * @setter: a #GstTagSetter
+ * @mode: the mode to use
+ * @tag: tag to set
+ * @value: GValue to set for the tag
+ *
+ * Adds the given tag / GValue pair on the setter using the given merge mode.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_tag_setter_add_tag_value (GstTagSetter * setter,
+    GstTagMergeMode mode, const gchar * tag, const GValue * value)
+{
+  GstTagData *data;
+
+  g_return_if_fail (GST_IS_TAG_SETTER (setter));
+  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
+
+  data = gst_tag_setter_get_data (setter);
+  if (!data->list)
+    data->list = gst_tag_list_new ();
+
+  gst_tag_list_add_value (data->list, mode, tag, value);
+}
+
+/**
  * gst_tag_setter_get_tag_list:
  * @setter: a #GstTagSetter
  *
--- a/gstreamer_core/gst/gsttagsetter.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttagsetter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -66,6 +66,12 @@
 #endif
 
 
+void		gst_tag_setter_reset_tags             (GstTagSetter * setter);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 void		gst_tag_setter_merge_tags	    (GstTagSetter *	setter,
 						     const GstTagList *	list,
 						     GstTagMergeMode	mode);
@@ -109,6 +115,15 @@
 #endif
 
 
+void		gst_tag_setter_add_tag_value	    (GstTagSetter *	setter,
+						     GstTagMergeMode	mode,
+						     const gchar *	tag,
+						     const GValue *     value);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 G_CONST_RETURN GstTagList *
 		gst_tag_setter_get_tag_list	     (GstTagSetter *	setter);
 #ifdef __SYMBIAN32__
--- a/gstreamer_core/gst/gsttask.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttask.c	Fri Apr 16 15:15:52 2010 +0300
@@ -42,13 +42,14 @@
  * gst_task_set_lock().
  *
  * The task can be started, paused and stopped with gst_task_start(), gst_task_pause()
- * and gst_task_stop() respectively.
+ * and gst_task_stop() respectively or with the gst_task_set_state() function.
  *
- * A #GstTask will repeadedly call the #GstTaskFunction with the user data
- * that was provided when creating the task with gst_task_create(). Before calling
- * the function it will acquire the provided lock.
+ * A #GstTask will repeatedly call the #GstTaskFunction with the user data
+ * that was provided when creating the task with gst_task_create(). While calling
+ * the function it will acquire the provided lock. The provided lock is released
+ * when the task pauses or stops.
  *
- * Stopping a task with gst_task_stop() will not immediatly make sure the task is
+ * Stopping a task with gst_task_stop() will not immediately make sure the task is
  * not running anymore. Use gst_task_join() to make sure the task is completely
  * stopped and the thread is stopped.
  *
@@ -70,45 +71,53 @@
 GST_DEBUG_CATEGORY_STATIC (task_debug);
 #define GST_CAT_DEFAULT (task_debug)
 
+#define GST_TASK_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_TASK, GstTaskPrivate))
+
+struct _GstTaskPrivate
+{
+  /* callbacks for managing the thread of this task */
+  GstTaskThreadCallbacks thr_callbacks;
+  gpointer thr_user_data;
+  GDestroyNotify thr_notify;
+
+  gboolean prio_set;
+  GThreadPriority priority;
+
+  /* configured pool */
+  GstTaskPool *pool;
+
+  /* remember the pool and id that is currently running. */
+  gpointer id;
+  GstTaskPool *pool_id;
+};
+
 static void gst_task_class_init (GstTaskClass * klass);
 static void gst_task_init (GstTask * task);
 static void gst_task_finalize (GObject * object);
 
-static void gst_task_func (GstTask * task, GstTaskClass * tclass);
-
-static GstObjectClass *parent_class = NULL;
+static void gst_task_func (GstTask * task);
 
 static GStaticMutex pool_lock = G_STATIC_MUTEX_INIT;
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
 
-GType
-gst_task_get_type (void)
-{
-  static GType _gst_task_type = 0;
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (task_debug, "task", 0, "Processing tasks"); \
+}
+
+G_DEFINE_TYPE_WITH_CODE (GstTask, gst_task, GST_TYPE_OBJECT, _do_init);
 
-  if (G_UNLIKELY (_gst_task_type == 0)) {
-    static const GTypeInfo task_info = {
-      sizeof (GstTaskClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_task_class_init,
-      NULL,
-      NULL,
-      sizeof (GstTask),
-      0,
-      (GInstanceInitFunc) gst_task_init,
-      NULL
-    };
-
-    _gst_task_type =
-        g_type_register_static (GST_TYPE_OBJECT, "GstTask", &task_info, 0);
-
-    GST_DEBUG_CATEGORY_INIT (task_debug, "task", 0, "Processing tasks");
+static void
+init_klass_pool (GstTaskClass * klass)
+{
+  g_static_mutex_lock (&pool_lock);
+  if (klass->pool) {
+    gst_task_pool_cleanup (klass->pool);
+    gst_object_unref (klass->pool);
   }
-  return _gst_task_type;
+  klass->pool = gst_task_pool_new ();
+  gst_task_pool_prepare (klass->pool, NULL);
+  g_static_mutex_unlock (&pool_lock);
 }
 
 static void
@@ -118,44 +127,66 @@
 
   gobject_class = (GObjectClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
+  g_type_class_add_private (klass, sizeof (GstTaskPrivate));
 
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_task_finalize);
 
-  klass->pool = g_thread_pool_new (
-      (GFunc) gst_task_func, klass, -1, FALSE, NULL);
+  init_klass_pool (klass);
 }
 
 static void
 gst_task_init (GstTask * task)
 {
+  GstTaskClass *klass;
+
+  klass = GST_TASK_GET_CLASS (task);
+
+  task->priv = GST_TASK_GET_PRIVATE (task);
   task->running = FALSE;
   task->abidata.ABI.thread = NULL;
   task->lock = NULL;
   task->cond = g_cond_new ();
   task->state = GST_TASK_STOPPED;
+  task->priv->prio_set = FALSE;
+
+  /* use the default klass pool for this task, users can
+   * override this later */
+  g_static_mutex_lock (&pool_lock);
+  task->priv->pool = gst_object_ref (klass->pool);
+  g_static_mutex_unlock (&pool_lock);
 }
 
 static void
 gst_task_finalize (GObject * object)
 {
   GstTask *task = GST_TASK (object);
+  GstTaskPrivate *priv = task->priv;
 
   GST_DEBUG ("task %p finalize", task);
 
+  if (priv->thr_notify)
+    priv->thr_notify (priv->thr_user_data);
+  priv->thr_notify = NULL;
+  priv->thr_user_data = NULL;
+
+  gst_object_unref (priv->pool);
+
   /* task thread cannot be running here since it holds a ref
    * to the task so that the finalize could not have happened */
   g_cond_free (task->cond);
   task->cond = NULL;
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gst_task_parent_class)->finalize (object);
 }
 
 static void
-gst_task_func (GstTask * task, GstTaskClass * tclass)
+gst_task_func (GstTask * task)
 {
   GStaticRecMutex *lock;
   GThread *tself;
+  GstTaskPrivate *priv;
+
+  priv = task->priv;
 
   tself = g_thread_self ();
 
@@ -171,8 +202,15 @@
   if (G_UNLIKELY (lock == NULL))
     goto no_lock;
   task->abidata.ABI.thread = tself;
+  /* only update the priority when it was changed */
+  if (priv->prio_set)
+    g_thread_set_priority (tself, priv->priority);
   GST_OBJECT_UNLOCK (task);
 
+  /* fire the enter_thread callback when we need to */
+  if (priv->thr_callbacks.enter_thread)
+    priv->thr_callbacks.enter_thread (task, tself, priv->thr_user_data);
+
   /* locking order is TASK_LOCK, LOCK */
   g_static_rec_mutex_lock (lock);
   GST_OBJECT_LOCK (task);
@@ -209,6 +247,17 @@
   task->abidata.ABI.thread = NULL;
 
 exit:
+  if (priv->thr_callbacks.leave_thread) {
+    /* fire the leave_thread callback when we need to. We need to do this before
+     * we signal the task and with the task lock released. */
+    GST_OBJECT_UNLOCK (task);
+    priv->thr_callbacks.leave_thread (task, tself, priv->thr_user_data);
+    GST_OBJECT_LOCK (task);
+  } else {
+    /* restore normal priority when releasing back into the pool, we will not
+     * touch the priority when a custom callback has been installed. */
+    g_thread_set_priority (tself, G_THREAD_PRIORITY_NORMAL);
+  }
   /* now we allow messing with the lock again by setting the running flag to
    * FALSE. Together with the SIGNAL this is the sign for the _join() to 
    * complete. 
@@ -236,7 +285,7 @@
  * gst_task_cleanup_all:
  *
  * Wait for all tasks to be stopped. This is mainly used internally
- * to ensure proper cleanup of internal datastructures in testsuites.
+ * to ensure proper cleanup of internal data structures in test suites.
  *
  * MT safe.
  */
@@ -250,18 +299,7 @@
   GstTaskClass *klass;
 
   if ((klass = g_type_class_peek (GST_TYPE_TASK))) {
-    g_static_mutex_lock (&pool_lock);
-    if (klass->pool) {
-      /* Shut down all the threads, we still process the ones scheduled
-       * because the unref happens in the thread function.
-       * Also wait for currently running ones to finish. */
-      g_thread_pool_free (klass->pool, FALSE, TRUE);
-      /* create new pool, so we can still do something after this
-       * call. */
-      klass->pool = g_thread_pool_new (
-          (GFunc) gst_task_func, klass, -1, FALSE, NULL);
-    }
-    g_static_mutex_unlock (&pool_lock);
+    init_klass_pool (klass);
   }
 }
 
@@ -270,12 +308,19 @@
  * @func: The #GstTaskFunction to use
  * @data: User data to pass to @func
  *
- * Create a new Task that will repeadedly call the provided @func
+ * Create a new Task that will repeatedly call the provided @func
  * with @data as a parameter. Typically the task will run in
  * a new thread.
  *
  * The function cannot be changed after the task has been created. You
- * must create a new GstTask to change the function.
+ * must create a new #GstTask to change the function.
+ *
+ * This function will not yet create and start a thread. Use gst_task_start() or
+ * gst_task_pause() to create and start the GThread.
+ *
+ * Before the task can be used, a #GStaticRecMutex must be configured using the
+ * gst_task_set_lock() function. This lock will always be acquired while
+ * @func is called.
  *
  * Returns: A new #GstTask.
  *
@@ -302,7 +347,7 @@
 /**
  * gst_task_set_lock:
  * @task: The #GstTask to use
- * @mutex: The GMutex to use
+ * @mutex: The #GMutex to use
  *
  * Set the mutex used by the task. The mutex will be acquired before
  * calling the #GstTaskFunction.
@@ -335,6 +380,175 @@
   }
 }
 
+/**
+ * gst_task_set_priority:
+ * @task: a #GstTask
+ * @priority: a new priority for @task
+ *
+ * Changes the priority of @task to @priority.
+ *
+ * Note: try not to depend on task priorities.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_task_set_priority (GstTask * task, GThreadPriority priority)
+{
+  GstTaskPrivate *priv;
+  GThread *thread;
+
+  g_return_if_fail (GST_IS_TASK (task));
+
+  priv = task->priv;
+
+  GST_OBJECT_LOCK (task);
+  priv->prio_set = TRUE;
+  priv->priority = priority;
+  thread = task->abidata.ABI.thread;
+  if (thread != NULL) {
+    /* if this task already has a thread, we can configure the priority right
+     * away, else we do that when we assign a thread to the task. */
+    g_thread_set_priority (thread, priority);
+  }
+  GST_OBJECT_UNLOCK (task);
+}
+
+/**
+ * gst_task_get_pool:
+ * @task: a #GstTask
+ *
+ * Get the #GstTaskPool that this task will use for its streaming
+ * threads.
+ *
+ * MT safe.
+ *
+ * Returns: the #GstTaskPool used by @task. gst_object_unref()
+ * after usage.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstTaskPool *
+gst_task_get_pool (GstTask * task)
+{
+  GstTaskPool *result;
+  GstTaskPrivate *priv;
+
+  g_return_val_if_fail (GST_IS_TASK (task), NULL);
+
+  priv = task->priv;
+
+  GST_OBJECT_LOCK (task);
+  result = gst_object_ref (priv->pool);
+  GST_OBJECT_UNLOCK (task);
+
+  return result;
+}
+
+/**
+ * gst_task_set_pool:
+ * @task: a #GstTask
+ * @pool: a #GstTaskPool
+ *
+ * Set @pool as the new GstTaskPool for @task. Any new streaming threads that
+ * will be created by @task will now use @pool.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_task_set_pool (GstTask * task, GstTaskPool * pool)
+{
+  GstTaskPool *old;
+  GstTaskPrivate *priv;
+
+  g_return_if_fail (GST_IS_TASK (task));
+  g_return_if_fail (GST_IS_TASK_POOL (pool));
+
+  priv = task->priv;
+
+  GST_OBJECT_LOCK (task);
+  if (priv->pool != pool) {
+    old = priv->pool;
+    priv->pool = gst_object_ref (pool);
+  } else
+    old = NULL;
+  GST_OBJECT_UNLOCK (task);
+
+  if (old)
+    gst_object_unref (old);
+}
+
+
+/**
+ * gst_task_set_thread_callbacks:
+ * @task: The #GstTask to use
+ * @callbacks: a #GstTaskThreadCallbacks pointer
+ * @user_data: user data passed to the callbacks
+ * @notify: called when @user_data is no longer referenced
+ *
+ * Set callbacks which will be executed when a new thread is needed, the thread
+ * function is entered and left and when the thread is joined.
+ *
+ * By default a thread for @task will be created from a default thread pool.
+ *
+ * Objects can use custom GThreads or can perform additional configuration of
+ * the threads (such as changing the thread priority) by installing callbacks.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_task_set_thread_callbacks (GstTask * task,
+    GstTaskThreadCallbacks * callbacks, gpointer user_data,
+    GDestroyNotify notify)
+{
+  GDestroyNotify old_notify;
+
+  g_return_if_fail (task != NULL);
+  g_return_if_fail (GST_IS_TASK (task));
+  g_return_if_fail (callbacks != NULL);
+
+  GST_OBJECT_LOCK (task);
+  old_notify = task->priv->thr_notify;
+
+  if (old_notify) {
+    gpointer old_data;
+
+    old_data = task->priv->thr_user_data;
+
+    task->priv->thr_user_data = NULL;
+    task->priv->thr_notify = NULL;
+    GST_OBJECT_UNLOCK (task);
+
+    old_notify (old_data);
+
+    GST_OBJECT_LOCK (task);
+  }
+  task->priv->thr_callbacks = *callbacks;
+  task->priv->thr_user_data = user_data;
+  task->priv->thr_notify = notify;
+  GST_OBJECT_UNLOCK (task);
+}
 
 /**
  * gst_task_get_state:
@@ -364,14 +578,122 @@
   return result;
 }
 
+/* make sure the task is running and start a thread if it's not.
+ * This function must be called with the task LOCK. */
+static gboolean
+start_task (GstTask * task)
+{
+  gboolean res = TRUE;
+  GstTaskClass *tclass;
+  GError *error = NULL;
+  GstTaskPrivate *priv;
+
+  priv = task->priv;
+
+  /* new task, We ref before so that it remains alive while
+   * the thread is running. */
+  gst_object_ref (task);
+  /* mark task as running so that a join will wait until we schedule
+   * and exit the task function. */
+  task->running = TRUE;
+
+  tclass = GST_TASK_GET_CLASS (task);
+
+  /* push on the thread pool, we remember the original pool because the user
+   * could change it later on and then we join to the wrong pool. */
+  priv->pool_id = gst_object_ref (priv->pool);
+  priv->id =
+      gst_task_pool_push (priv->pool_id, (GstTaskPoolFunction) gst_task_func,
+      task, &error);
+
+  if (error != NULL) {
+    g_warning ("failed to create thread: %s", error->message);
+    g_error_free (error);
+    res = FALSE;
+  }
+  return res;
+}
+
+
+/**
+ * gst_task_set_state:
+ * @task: a #GstTask
+ * @state: the new task state
+ *
+ * Sets the state of @task to @state.
+ *
+ * The @task must have a lock associated with it using
+ * gst_task_set_lock() when going to GST_TASK_STARTED or GST_TASK_PAUSED or
+ * this function will return %FALSE.
+ *
+ * MT safe.
+ *
+ * Returns: %TRUE if the state could be changed.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_task_set_state (GstTask * task, GstTaskState state)
+{
+  GstTaskState old;
+  gboolean res = TRUE;
+
+  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
+
+  GST_DEBUG_OBJECT (task, "Changing task %p to state %d", task, state);
+
+  GST_OBJECT_LOCK (task);
+  if (state != GST_TASK_STOPPED)
+    if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL))
+      goto no_lock;
+
+  /* if the state changed, do our thing */
+  old = task->state;
+  if (old != state) {
+    task->state = state;
+    switch (old) {
+      case GST_TASK_STOPPED:
+        /* If the task already has a thread scheduled we don't have to do
+         * anything. */
+        if (G_UNLIKELY (!task->running))
+          res = start_task (task);
+        break;
+      case GST_TASK_PAUSED:
+        /* when we are paused, signal to go to the new state */
+        GST_TASK_SIGNAL (task);
+        break;
+      case GST_TASK_STARTED:
+        /* if we were started, we'll go to the new state after the next
+         * iteration. */
+        break;
+    }
+  }
+  GST_OBJECT_UNLOCK (task);
+
+  return res;
+
+  /* ERRORS */
+no_lock:
+  {
+    GST_WARNING_OBJECT (task, "state %d set on task without a lock", state);
+    GST_OBJECT_UNLOCK (task);
+    g_warning ("task without a lock can't be set to state %d", state);
+    return FALSE;
+  }
+}
+
 /**
  * gst_task_start:
  * @task: The #GstTask to start
  *
  * Starts @task. The @task must have a lock associated with it using
- * gst_task_set_lock() or thsi function will return FALSE.
+ * gst_task_set_lock() or this function will return %FALSE.
  *
- * Returns: TRUE if the task could be started.
+ * Returns: %TRUE if the task could be started.
  *
  * MT safe.
  */
@@ -382,62 +704,7 @@
 gboolean
 gst_task_start (GstTask * task)
 {
-  GstTaskState old;
-
-  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
-
-  GST_DEBUG_OBJECT (task, "Starting task %p", task);
-
-  GST_OBJECT_LOCK (task);
-  if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL))
-    goto no_lock;
-
-  old = task->state;
-  task->state = GST_TASK_STARTED;
-  switch (old) {
-    case GST_TASK_STOPPED:
-    {
-      GstTaskClass *tclass;
-
-      /* If the task already has a thread scheduled we don't have to do
-       * anything. */
-      if (task->running)
-        break;
-
-      /* new task, push on threadpool. We ref before so
-       * that it remains alive while on the threadpool. */
-      gst_object_ref (task);
-      /* mark task as running so that a join will wait until we schedule
-       * and exit the task function. */
-      task->running = TRUE;
-
-      tclass = GST_TASK_GET_CLASS (task);
-
-      g_static_mutex_lock (&pool_lock);
-      g_thread_pool_push (tclass->pool, task, NULL);
-      g_static_mutex_unlock (&pool_lock);
-      break;
-    }
-    case GST_TASK_PAUSED:
-      /* PAUSE to PLAY, signal */
-      GST_TASK_SIGNAL (task);
-      break;
-    case GST_TASK_STARTED:
-      /* was OK */
-      break;
-  }
-  GST_OBJECT_UNLOCK (task);
-
-  return TRUE;
-
-  /* ERRORS */
-no_lock:
-  {
-    GST_WARNING_OBJECT (task, "starting task without a lock");
-    GST_OBJECT_UNLOCK (task);
-    g_warning ("starting task without a lock");
-    return FALSE;
-  }
+  return gst_task_set_state (task, GST_TASK_STARTED);
 }
 
 /**
@@ -448,7 +715,7 @@
  * will not wait for the task to have completely stopped. Use
  * gst_task_join() to stop and wait for completion.
  *
- * Returns: TRUE if the task could be stopped.
+ * Returns: %TRUE if the task could be stopped.
  *
  * MT safe.
  */
@@ -459,30 +726,7 @@
 gboolean
 gst_task_stop (GstTask * task)
 {
-  GstTaskClass *tclass;
-  GstTaskState old;
-
-  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
-
-  tclass = GST_TASK_GET_CLASS (task);
-
-  GST_DEBUG_OBJECT (task, "Stopping task %p", task);
-
-  GST_OBJECT_LOCK (task);
-  old = task->state;
-  task->state = GST_TASK_STOPPED;
-  switch (old) {
-    case GST_TASK_STOPPED:
-      break;
-    case GST_TASK_PAUSED:
-      GST_TASK_SIGNAL (task);
-      break;
-    case GST_TASK_STARTED:
-      break;
-  }
-  GST_OBJECT_UNLOCK (task);
-
-  return TRUE;
+  return gst_task_set_state (task, GST_TASK_STOPPED);
 }
 
 /**
@@ -494,63 +738,17 @@
  * in the paused state. This function does not wait for the task to complete
  * the paused state.
  *
- * Returns: TRUE if the task could be paused.
+ * Returns: %TRUE if the task could be paused.
  *
  * MT safe.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
 gboolean
 gst_task_pause (GstTask * task)
 {
-  GstTaskState old;
-
-  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
-
-  GST_DEBUG_OBJECT (task, "Pausing task %p", task);
-
-  GST_OBJECT_LOCK (task);
-  if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL))
-    goto no_lock;
-
-  old = task->state;
-  task->state = GST_TASK_PAUSED;
-  switch (old) {
-    case GST_TASK_STOPPED:
-    {
-      GstTaskClass *tclass;
-
-      if (task->running)
-        break;
-
-      gst_object_ref (task);
-      task->running = TRUE;
-
-      tclass = GST_TASK_GET_CLASS (task);
-
-      g_static_mutex_lock (&pool_lock);
-      g_thread_pool_push (tclass->pool, task, NULL);
-      g_static_mutex_unlock (&pool_lock);
-      break;
-    }
-    case GST_TASK_PAUSED:
-      break;
-    case GST_TASK_STARTED:
-      break;
-  }
-  GST_OBJECT_UNLOCK (task);
-
-  return TRUE;
-
-  /* ERRORS */
-no_lock:
-  {
-    GST_WARNING_OBJECT (task, "pausing task without a lock");
-    GST_OBJECT_UNLOCK (task);
-    g_warning ("pausing task without a lock");
-    return FALSE;
-  }
+  return gst_task_set_state (task, GST_TASK_PAUSED);
 }
 
 /**
@@ -566,7 +764,7 @@
  * would cause a deadlock. The function will detect this and print a 
  * g_warning.
  *
- * Returns: TRUE if the task could be joined.
+ * Returns: %TRUE if the task could be joined.
  *
  * MT safe.
  */
@@ -578,6 +776,11 @@
 gst_task_join (GstTask * task)
 {
   GThread *tself;
+  GstTaskPrivate *priv;
+  gpointer id;
+  GstTaskPool *pool = NULL;
+
+  priv = task->priv;
 
   g_return_val_if_fail (GST_IS_TASK (task), FALSE);
 
@@ -586,20 +789,33 @@
   GST_DEBUG_OBJECT (task, "Joining task %p, thread %p", task, tself);
 
   /* we don't use a real thread join here because we are using
-   * threadpools */
+   * thread pools */
   GST_OBJECT_LOCK (task);
   if (G_UNLIKELY (tself == task->abidata.ABI.thread))
     goto joining_self;
   task->state = GST_TASK_STOPPED;
   /* signal the state change for when it was blocked in PAUSED. */
   GST_TASK_SIGNAL (task);
-  /* we set the running flag when pushing the task on the threadpool. 
+  /* we set the running flag when pushing the task on the thread pool.
    * This means that the task function might not be called when we try
    * to join it here. */
   while (G_LIKELY (task->running))
     GST_TASK_WAIT (task);
+  /* clean the thread */
+  task->abidata.ABI.thread = NULL;
+  /* get the id and pool to join */
+  pool = priv->pool_id;
+  id = priv->id;
+  priv->pool_id = NULL;
+  priv->id = NULL;
   GST_OBJECT_UNLOCK (task);
 
+  if (pool) {
+    if (id)
+      gst_task_pool_join (pool, id);
+    gst_object_unref (pool);
+  }
+
   GST_DEBUG_OBJECT (task, "Joined task %p", task);
 
   return TRUE;
--- a/gstreamer_core/gst/gsttask.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttask.h	Fri Apr 16 15:15:52 2010 +0300
@@ -24,6 +24,7 @@
 #define __GST_TASK_H__
 
 #include <gst/gstobject.h>
+#include <gst/gsttaskpool.h>
 
 G_BEGIN_DECLS
 
@@ -31,8 +32,8 @@
  * GstTaskFunction:
  * @data: user data passed to the function
  *
- * A function that will repeadedly be called in the thread created by
- * a GstTask. 
+ * A function that will repeatedly be called in the thread created by
+ * a #GstTask.
  */
 typedef void         (*GstTaskFunction)          (void *data);
 
@@ -47,11 +48,12 @@
 
 typedef struct _GstTask GstTask;
 typedef struct _GstTaskClass GstTaskClass;
+typedef struct _GstTaskPrivate GstTaskPrivate;
 
 /**
  * GstTaskState:
  * @GST_TASK_STARTED: the task is started and running
- * @GST_TASK_STOPPED:  the task is stopped
+ * @GST_TASK_STOPPED: the task is stopped
  * @GST_TASK_PAUSED: the task is paused
  *
  * The different states a task can be in
@@ -108,13 +110,32 @@
 #define GST_TASK_GET_LOCK(task)		(GST_TASK_CAST(task)->lock)
 
 /**
+ * GstTaskThreadCallbacks:
+ * @enter_thread: a thread is entered, this callback is called when the new
+ *   thread enters its function.
+ * @leave_thread: a thread is exiting, this is called when the thread is about
+ *   to leave its function
+ *
+ * Custom GstTask thread callback functions that can be installed. 
+ *
+ * Since: 0.10.24
+ */
+typedef struct {
+  /* manage the lifetime of the thread */
+  void      (*enter_thread)     (GstTask *task, GThread *thread, gpointer user_data);
+  void      (*leave_thread)     (GstTask *task, GThread *thread, gpointer user_data);
+  /*< private >*/
+  gpointer     _gst_reserved[GST_PADDING];
+} GstTaskThreadCallbacks;
+
+/**
  * GstTask:
  * @state: the state of the task
  * @cond: used to pause/resume the task
- * @lock: The lock taken when iterating the taskfunction
+ * @lock: The lock taken when iterating the task function
  * @func: the function executed by this task
  * @data: data passed to the task function
- * @running: a flag indicating that the task is running.
+ * @running: a flag indicating that the task is running
  *
  * The #GstTask object.
  */
@@ -138,17 +159,17 @@
       /* thread this task is currently running in */
       GThread  *thread;
     } ABI;
-    /* adding + 0 to mark ABI change to be undone later */
-    gpointer _gst_reserved[GST_PADDING + 0];
+    gpointer _gst_reserved[GST_PADDING - 1];
   } abidata;
 
+  GstTaskPrivate *priv;
 };
 
 struct _GstTaskClass {
   GstObjectClass parent_class;
 
   /*< private >*/
-  GThreadPool *pool;
+  GstTaskPool *pool;
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -180,12 +201,42 @@
 IMPORT_C
 #endif
 
+void		gst_task_set_priority	(GstTask *task, GThreadPriority priority);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstTaskPool *   gst_task_get_pool       (GstTask *task);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_task_set_pool       (GstTask *task, GstTaskPool *pool);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void            gst_task_set_thread_callbacks  (GstTask *task,
+                                                GstTaskThreadCallbacks *callbacks,
+						gpointer user_data,
+						GDestroyNotify notify);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GstTaskState	gst_task_get_state	(GstTask *task);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+gboolean        gst_task_set_state      (GstTask *task, GstTaskState state);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 gboolean	gst_task_start		(GstTask *task);
 #ifdef __SYMBIAN32__
@@ -208,4 +259,3 @@
 G_END_DECLS
 
 #endif /* __GST_TASK_H__ */
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/gst/gsttaskpool.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,292 @@
+/* GStreamer
+ * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * gsttaskpool.c: Pool for streaming threads
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:gsttaskpool
+ * @short_description: Pool of GStreamer streaming threads
+ * @see_also: #GstTask, #GstPad
+ *
+ * This object provides an abstraction for creating threads. The default
+ * implementation uses a regular GThreadPool to start tasks.
+ *
+ * Subclasses can be made to create custom threads.
+ *
+ * Last reviewed on 2009-04-23 (0.10.24)
+ */
+
+#include "gst_private.h"
+
+#include "gstinfo.h"
+#include "gsttaskpool.h"
+#ifdef __SYMBIAN32__
+#include <glib_global.h>
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (taskpool_debug);
+#define GST_CAT_DEFAULT (taskpool_debug)
+
+static void gst_task_pool_class_init (GstTaskPoolClass * klass);
+static void gst_task_pool_init (GstTaskPool * pool);
+static void gst_task_pool_finalize (GObject * object);
+
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (taskpool_debug, "taskpool", 0, "Thread pool"); \
+}
+
+G_DEFINE_TYPE_WITH_CODE (GstTaskPool, gst_task_pool, GST_TYPE_OBJECT, _do_init);
+
+typedef struct
+{
+  GstTaskPoolFunction func;
+  gpointer user_data;
+} TaskData;
+
+static void
+default_func (TaskData * tdata, GstTaskPool * pool)
+{
+  GstTaskPoolFunction func;
+  gpointer user_data;
+
+  func = tdata->func;
+  user_data = tdata->user_data;
+  g_slice_free (TaskData, tdata);
+
+  func (user_data);
+}
+
+static void
+default_prepare (GstTaskPool * pool, GError ** error)
+{
+  GST_OBJECT_LOCK (pool);
+  pool->pool = g_thread_pool_new ((GFunc) default_func, pool, -1, FALSE, NULL);
+  GST_OBJECT_UNLOCK (pool);
+}
+
+static void
+default_cleanup (GstTaskPool * pool)
+{
+  GST_OBJECT_LOCK (pool);
+  if (pool->pool) {
+    /* Shut down all the threads, we still process the ones scheduled
+     * because the unref happens in the thread function.
+     * Also wait for currently running ones to finish. */
+    g_thread_pool_free (pool->pool, FALSE, TRUE);
+    pool->pool = NULL;
+  }
+  GST_OBJECT_UNLOCK (pool);
+}
+
+static gpointer
+default_push (GstTaskPool * pool, GstTaskPoolFunction func,
+    gpointer user_data, GError ** error)
+{
+  TaskData *tdata;
+
+  tdata = g_slice_new (TaskData);
+  tdata->func = func;
+  tdata->user_data = user_data;
+
+  GST_OBJECT_LOCK (pool);
+  if (pool->pool)
+    g_thread_pool_push (pool->pool, tdata, error);
+  else {
+    g_slice_free (TaskData, tdata);
+  }
+  GST_OBJECT_UNLOCK (pool);
+
+  return NULL;
+}
+
+static void
+default_join (GstTaskPool * pool, gpointer id)
+{
+  /* we do nothing here, we can't join from the pools */
+}
+
+static void
+gst_task_pool_class_init (GstTaskPoolClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstTaskPoolClass *gsttaskpool_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gsttaskpool_class = (GstTaskPoolClass *) klass;
+
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_task_pool_finalize);
+
+  gsttaskpool_class->prepare = default_prepare;
+  gsttaskpool_class->cleanup = default_cleanup;
+  gsttaskpool_class->push = default_push;
+  gsttaskpool_class->join = default_join;
+}
+
+static void
+gst_task_pool_init (GstTaskPool * pool)
+{
+}
+
+static void
+gst_task_pool_finalize (GObject * object)
+{
+  GST_DEBUG ("taskpool %p finalize", object);
+
+  G_OBJECT_CLASS (gst_task_pool_parent_class)->finalize (object);
+}
+
+/**
+ * gst_task_pool_new:
+ *
+ * Create a new default task pool. The default task pool will use a regular
+ * GThreadPool for threads.
+ *
+ * Returns: a new #GstTaskPool. gst_object_unref() after usage.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstTaskPool *
+gst_task_pool_new (void)
+{
+  GstTaskPool *pool;
+
+  pool = g_object_new (GST_TYPE_TASK_POOL, NULL);
+
+  return pool;
+}
+
+/**
+ * gst_task_pool_prepare:
+ * @pool: a #GstTaskPool
+ * @error: an error return location
+ *
+ * Prepare the taskpool for accepting gst_task_pool_push() operations.
+ *
+ * MT safe.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_task_pool_prepare (GstTaskPool * pool, GError ** error)
+{
+  GstTaskPoolClass *klass;
+
+  g_return_if_fail (GST_IS_TASK_POOL (pool));
+
+  klass = GST_TASK_POOL_GET_CLASS (pool);
+
+  if (klass->prepare)
+    klass->prepare (pool, error);
+}
+
+/**
+ * gst_task_pool_cleanup:
+ * @pool: a #GstTaskPool
+ *
+ * Wait for all tasks to be stopped. This is mainly used internally
+ * to ensure proper cleanup of internal data structures in test suites.
+ *
+ * MT safe.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_task_pool_cleanup (GstTaskPool * pool)
+{
+  GstTaskPoolClass *klass;
+
+  g_return_if_fail (GST_IS_TASK_POOL (pool));
+
+  klass = GST_TASK_POOL_GET_CLASS (pool);
+
+  if (klass->cleanup)
+    klass->cleanup (pool);
+}
+
+/**
+ * gst_task_pool_push:
+ * @pool: a #GstTaskPool
+ * @func: the function to call
+ * @user_data: data to pass to @func
+ * @error: return location for an error
+ *
+ * Start the execution of a new thread from @pool.
+ *
+ * Returns: a pointer that should be used for the gst_task_pool_join
+ * function. This pointer can be NULL, you must check @error to detect
+ * errors.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gpointer
+gst_task_pool_push (GstTaskPool * pool, GstTaskPoolFunction func,
+    gpointer user_data, GError ** error)
+{
+  GstTaskPoolClass *klass;
+
+  g_return_val_if_fail (GST_IS_TASK_POOL (pool), NULL);
+
+  klass = GST_TASK_POOL_GET_CLASS (pool);
+
+  if (klass->push == NULL)
+    goto not_supported;
+
+  return klass->push (pool, func, user_data, error);
+
+  /* ERRORS */
+not_supported:
+  {
+    g_warning ("pushing tasks on pool %p is not supported", pool);
+    return NULL;
+  }
+}
+
+/**
+ * gst_task_pool_join:
+ * @pool: a #GstTaskPool
+ * @id: the id
+ *
+ * Join a task and/or return it to the pool. @id is the id obtained from 
+ * gst_task_pool_push().
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_task_pool_join (GstTaskPool * pool, gpointer id)
+{
+  GstTaskPoolClass *klass;
+
+  g_return_if_fail (GST_IS_TASK_POOL (pool));
+
+  klass = GST_TASK_POOL_GET_CLASS (pool);
+
+  if (klass->join)
+    klass->join (pool, id);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/gst/gsttaskpool.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,119 @@
+/* GStreamer
+ * Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * gsttaskpool.h: Pool for creating streaming threads
+ *
+ * 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_TASK_POOL_H__
+#define __GST_TASK_POOL_H__
+
+#include <gst/gstobject.h>
+
+G_BEGIN_DECLS
+
+/* --- standard type macros --- */
+#define GST_TYPE_TASK_POOL             (gst_task_pool_get_type ())
+#define GST_TASK_POOL(pool)            (G_TYPE_CHECK_INSTANCE_CAST ((pool), GST_TYPE_TASK_POOL, GstTaskPool))
+#define GST_IS_TASK_POOL(pool)         (G_TYPE_CHECK_INSTANCE_TYPE ((pool), GST_TYPE_TASK_POOL))
+#define GST_TASK_POOL_CLASS(pclass)    (G_TYPE_CHECK_CLASS_CAST ((pclass), GST_TYPE_TASK_POOL, GstTaskPoolClass))
+#define GST_IS_TASK_POOL_CLASS(pclass) (G_TYPE_CHECK_CLASS_TYPE ((pclass), GST_TYPE_TASK_POOL))
+#define GST_TASK_POOL_GET_CLASS(pool)  (G_TYPE_INSTANCE_GET_CLASS ((pool), GST_TYPE_TASK_POOL, GstTaskPoolClass))
+#define GST_TASK_POOL_CAST(pool)       ((GstTaskPool*)(pool))
+
+typedef struct _GstTaskPool GstTaskPool;
+typedef struct _GstTaskPoolClass GstTaskPoolClass;
+
+typedef void   (*GstTaskPoolFunction)          (void *data);
+
+/**
+ * GstTaskPool:
+ *
+ * The #GstTaskPool object.
+ */
+struct _GstTaskPool {
+  GstObject      object;
+
+  /*< private >*/
+  GThreadPool   *pool;
+
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstTaskPoolClass:
+ * @parent_class: the parent class structure
+ * @prepare: prepare the threadpool
+ * @cleanup: make sure all threads are stopped
+ * @push: start a new thread
+ * @join: join a thread
+ *
+ * The #GstTaskPoolClass object.
+ */
+struct _GstTaskPoolClass {
+  GstObjectClass parent_class;
+
+  /*< public >*/
+  void      (*prepare)  (GstTaskPool *pool, GError **error);
+  void      (*cleanup)  (GstTaskPool *pool);
+
+  gpointer  (*push)     (GstTaskPool *pool, GstTaskPoolFunction func,
+                         gpointer user_data, GError **error);
+  void      (*join)     (GstTaskPool *pool, gpointer id);
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GType           gst_task_pool_get_type    (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstTaskPool *   gst_task_pool_new         (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_task_pool_prepare     (GstTaskPool *pool, GError **error);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gpointer        gst_task_pool_push        (GstTaskPool *pool, GstTaskPoolFunction func, 
+                                           gpointer user_data, GError **error);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void            gst_task_pool_join        (GstTaskPool *pool, gpointer id);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void		gst_task_pool_cleanup     (GstTaskPool *pool);
+
+G_END_DECLS
+
+#endif /* __GST_TASK_POOL_H__ */
--- a/gstreamer_core/gst/gsttrace.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttrace.c	Fri Apr 16 15:15:52 2010 +0300
@@ -65,6 +65,8 @@
 
 #include "gsttrace.h"
 
+GStaticMutex _gst_trace_mutex = G_STATIC_MUTEX_INIT;
+
 static
 #ifdef __inline__
   __inline__
--- a/gstreamer_core/gst/gsttrace.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttrace.h	Fri Apr 16 15:15:52 2010 +0300
@@ -92,8 +92,6 @@
 #endif
 
 
-
-
 GstTrace*	gst_trace_new			(gchar *filename, gint size);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -146,12 +144,14 @@
 
 
 void 		gst_trace_read_tsc		(gint64 *dst);
+
+
+extern GStaticMutex     _gst_trace_mutex;
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
-
 gboolean		gst_alloc_trace_available	(void);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -220,11 +220,15 @@
  */
 #define	gst_alloc_trace_new(trace, mem) 		\
 G_STMT_START {						\
-  if ((trace)->flags & GST_ALLOC_TRACE_LIVE) 		\
-    (trace)->live++;					\
-  if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE) 	\
-    (trace)->mem_live = 				\
-      g_slist_prepend ((trace)->mem_live, mem);		\
+  if (G_UNLIKELY ((trace)->flags)) {                    \
+    g_static_mutex_lock (&_gst_trace_mutex);            \
+    if ((trace)->flags & GST_ALLOC_TRACE_LIVE) 		\
+      (trace)->live++;					\
+    if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE) 	\
+      (trace)->mem_live = 				\
+        g_slist_prepend ((trace)->mem_live, mem);	\
+    g_static_mutex_unlock (&_gst_trace_mutex);          \
+  }                                                     \
 } G_STMT_END
 
 /**
@@ -236,11 +240,15 @@
  */
 #define	gst_alloc_trace_free(trace, mem) 		\
 G_STMT_START {						\
-  if ((trace)->flags & GST_ALLOC_TRACE_LIVE) 		\
-    (trace)->live--;					\
-  if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE) 	\
-    (trace)->mem_live = 				\
-      g_slist_remove ((trace)->mem_live, mem); 		\
+  if (G_UNLIKELY ((trace)->flags)) {                    \
+    g_static_mutex_lock (&_gst_trace_mutex);            \
+    if ((trace)->flags & GST_ALLOC_TRACE_LIVE) 		\
+      (trace)->live--;					\
+    if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE) 	\
+      (trace)->mem_live = 				\
+        g_slist_remove ((trace)->mem_live, mem); 	\
+    g_static_mutex_unlock (&_gst_trace_mutex);          \
+  }                                                     \
 } G_STMT_END
 
 #else
--- a/gstreamer_core/gst/gsttypefind.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttypefind.c	Fri Apr 16 15:15:52 2010 +0300
@@ -85,20 +85,20 @@
   GstTypeFindFactory *factory;
 
   g_return_val_if_fail (name != NULL, FALSE);
-  g_return_val_if_fail (func != NULL, FALSE);
 
   GST_INFO ("registering typefind function for %s", name);
 
   factory = g_object_new (GST_TYPE_TYPE_FIND_FACTORY, NULL);
   GST_DEBUG_OBJECT (factory, "using new typefind factory for %s", name);
   g_assert (GST_IS_TYPE_FIND_FACTORY (factory));
-  gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name);
 
+  gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name);
   gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
+
   if (factory->extensions)
     g_strfreev (factory->extensions);
+  factory->extensions = g_strdupv (extensions);
 
-  factory->extensions = g_strdupv (extensions);
   gst_caps_replace (&factory->caps, (GstCaps *) possible_caps);
   factory->function = func;
   factory->user_data = data;
@@ -172,6 +172,61 @@
 }
 
 /**
+ * gst_type_find_suggest_simple:
+ * @find: The #GstTypeFind object the function was called with
+ * @probability: The probability in percent that the suggestion is right
+ * @media_type: the media type of the suggested caps
+ * @fieldname: first field of the suggested caps, or NULL
+ * @...: additional arguments to the suggested caps in the same format as the
+ *     arguments passed to gst_structure_new() (ie. triplets of field name,
+ *     field GType and field value)
+ *
+ * If a #GstTypeFindFunction calls this function it suggests the caps with the
+ * given probability. A #GstTypeFindFunction may supply different suggestions
+ * in one call. It is up to the caller of the #GstTypeFindFunction to interpret
+ * these values.
+ *
+ * This function is similar to gst_type_find_suggest(), only that instead of
+ * passing a #GstCaps argument you can create the caps on the fly in the same
+ * way as you can with gst_caps_new_simple().
+ *
+ * Make sure you terminate the list of arguments with a NULL argument and that
+ * the values passed have the correct type (in terms of width in bytes when
+ * passed to the vararg function - this applies particularly to gdouble and
+ * guint64 arguments).
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_type_find_suggest_simple (GstTypeFind * find, guint probability,
+    const char *media_type, const char *fieldname, ...)
+{
+  GstStructure *structure;
+  va_list var_args;
+  GstCaps *caps;
+
+  g_return_if_fail (find->suggest != NULL);
+  g_return_if_fail (probability <= 100);
+  g_return_if_fail (media_type != NULL);
+
+  caps = gst_caps_new_empty ();
+
+  va_start (var_args, fieldname);
+  structure = gst_structure_new_valist (media_type, fieldname, var_args);
+  va_end (var_args);
+
+  gst_caps_append_structure (caps, structure);
+  g_return_if_fail (gst_caps_is_fixed (caps));
+
+  find->suggest (find->data, probability, caps);
+  gst_caps_unref (caps);
+}
+
+/**
  * gst_type_find_get_length:
  * @find: The #GstTypeFind the function was called with
  *
--- a/gstreamer_core/gst/gsttypefind.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttypefind.h	Fri Apr 16 15:15:52 2010 +0300
@@ -29,7 +29,7 @@
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_TYPE_FIND	(gst_type_find_get_type())
+#define GST_TYPE_TYPE_FIND  (gst_type_find_get_type())
 
 typedef struct _GstTypeFind GstTypeFind;
 
@@ -72,17 +72,18 @@
  */
 struct _GstTypeFind {
   /* private to the caller of the typefind function */
-  guint8 *	(* peek)	(gpointer		data,
-				 gint64	         	offset,
-				 guint			size);
-  void		(* suggest)	(gpointer		data,
-				 guint			probability,
-				 const GstCaps *	caps);
+  guint8 *  (* peek)       (gpointer         data,
+                            gint64           offset,
+                            guint            size);
 
-  gpointer	data;
+  void      (* suggest)    (gpointer         data,
+                            guint            probability,
+                            const GstCaps *  caps);
+
+  gpointer     data;
 
   /* optional */
-  guint64	(* get_length)	(gpointer		data);
+  guint64   (* get_length) (gpointer data);
 
   /* <private> */
   gpointer _gst_reserved[GST_PADDING];
@@ -92,42 +93,53 @@
 #endif
 
 
-GType		gst_type_find_get_type			(void);
+GType     gst_type_find_get_type   (void);
 
 /* typefind function interface */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-guint8 *	gst_type_find_peek			(GstTypeFind *		find,
-							 gint64			offset,
-							 guint			size);
+guint8 *  gst_type_find_peek       (GstTypeFind   * find,
+                                    gint64          offset,
+                                    guint           size);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-void		gst_type_find_suggest			(GstTypeFind *		find,
-							 guint			probability,
-							 const GstCaps *     	caps);
+
+void      gst_type_find_suggest    (GstTypeFind   * find,
+                                    guint           probability,
+                                    const GstCaps * caps);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-guint64		gst_type_find_get_length		(GstTypeFind *		find);
+
+void      gst_type_find_suggest_simple (GstTypeFind * find,
+                                        guint         probability,
+                                        const char  * media_type,
+                                        const char  * fieldname, ...);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+guint64   gst_type_find_get_length (GstTypeFind   * find);
 
 /* registration interface */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gboolean	gst_type_find_register			(GstPlugin *		plugin,
-							 const gchar *		name,
-							 guint			rank,
-							 GstTypeFindFunction	func,
-							 gchar **		extensions,
-							 const GstCaps *	possible_caps,
-							 gpointer		data,
-							 GDestroyNotify		data_notify);
+gboolean  gst_type_find_register   (GstPlugin            * plugin,
+                                    const gchar          * name,
+                                    guint                  rank,
+                                    GstTypeFindFunction    func,
+                                    gchar               ** extensions,
+                                    const GstCaps        * possible_caps,
+                                    gpointer               data,
+                                    GDestroyNotify         data_notify);
 
 G_END_DECLS
 
--- a/gstreamer_core/gst/gsttypefindfactory.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsttypefindfactory.c	Fri Apr 16 15:15:52 2010 +0300
@@ -89,61 +89,32 @@
 GST_DEBUG_CATEGORY (type_find_debug);
 #define GST_CAT_DEFAULT type_find_debug
 
-static void gst_type_find_factory_class_init (gpointer g_class,
-    gpointer class_data);
-static void gst_type_find_factory_init (GTypeInstance * instance,
-    gpointer g_class);
 static void gst_type_find_factory_dispose (GObject * object);
 
 static GstPluginFeatureClass *parent_class = NULL;
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-
-GType
-gst_type_find_factory_get_type (void)
-{
-  static GType typefind_type = 0;
-
-  if (G_UNLIKELY (typefind_type == 0)) {
-    static const GTypeInfo typefind_info = {
-      sizeof (GstTypeFindFactoryClass),
-      NULL,
-      NULL,
-      gst_type_find_factory_class_init,
-      NULL,
-      NULL,
-      sizeof (GstTypeFindFactory),
-      0,
-      gst_type_find_factory_init,
-      NULL
-    };
-
-    typefind_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
-        "GstTypeFindFactory", &typefind_info, 0);
-    GST_DEBUG_CATEGORY_INIT (type_find_debug, "GST_TYPEFIND",
-        GST_DEBUG_FG_GREEN, "typefinding subsystem");
-  }
-
-  return typefind_type;
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (type_find_debug, "GST_TYPEFIND", \
+      GST_DEBUG_FG_GREEN, "typefinding subsystem"); \
 }
 
+G_DEFINE_TYPE_WITH_CODE (GstTypeFindFactory, gst_type_find_factory,
+    GST_TYPE_PLUGIN_FEATURE, _do_init);
+
 static void
-gst_type_find_factory_class_init (gpointer g_class, gpointer class_data)
+gst_type_find_factory_class_init (GstTypeFindFactoryClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (g_class);
+  parent_class = g_type_class_peek_parent (klass);
 
   object_class->dispose = gst_type_find_factory_dispose;
 }
 
 static void
-gst_type_find_factory_init (GTypeInstance * instance, gpointer g_class)
+gst_type_find_factory_init (GstTypeFindFactory * factory)
 {
-  GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (instance);
-
   factory->user_data = factory;
   factory->user_data_notify = NULL;
 }
@@ -258,9 +229,8 @@
       GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
           (factory)));
   if (new_factory) {
-    g_assert (new_factory->function != NULL);
-
-    new_factory->function (find, new_factory->user_data);
+    if (new_factory->function)
+      new_factory->function (find, new_factory->user_data);
     gst_object_unref (new_factory);
   }
 }
--- a/gstreamer_core/gst/gsturi.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsturi.c	Fri Apr 16 15:15:52 2010 +0300
@@ -64,9 +64,10 @@
 GType
 gst_uri_handler_get_type (void)
 {
-  static GType urihandler_type = 0;
+  static volatile gsize urihandler_type = 0;
 
-  if (G_UNLIKELY (urihandler_type == 0)) {
+  if (g_once_init_enter (&urihandler_type)) {
+    GType _type;
     static const GTypeInfo urihandler_info = {
       sizeof (GstURIHandlerInterface),
       gst_uri_handler_base_init,
@@ -80,14 +81,16 @@
       NULL
     };
 
-    urihandler_type = g_type_register_static (G_TYPE_INTERFACE,
+    _type = g_type_register_static (G_TYPE_INTERFACE,
         "GstURIHandler", &urihandler_info, 0);
 
     GST_DEBUG_CATEGORY_INIT (gst_uri_handler_debug, "GST_URI", GST_DEBUG_BOLD,
         "handling of URIs");
+    g_once_init_leave (&urihandler_type, _type);
   }
   return urihandler_type;
 }
+
 static void
 gst_uri_handler_base_init (gpointer g_class)
 {
@@ -239,7 +242,7 @@
     return -1;
   }
 
-  second_digit = hex_to_int (*scanner++);
+  second_digit = hex_to_int (*scanner);
   if (second_digit < 0) {
     return -1;
   }
@@ -309,7 +312,8 @@
 
   if (g_ascii_isalpha (*check)) {
     check++;
-    while (g_ascii_isalnum (*check))
+    while (g_ascii_isalnum (*check) || *check == '+'
+        || *check == '-' || *check == '.')
       check++;
   }
 
@@ -321,7 +325,8 @@
  * @protocol: A string
  *
  * Tests if the given string is a valid protocol identifier. Protocols
- * must consist of alphanumeric characters and not start with a number.
+ * must consist of alphanumeric characters, '+', '-' and '.' and must
+ * start with a alphabetic character. See RFC 3986 Section 3.1.
  *
  * Returns: TRUE if the string is a valid protocol identifier, FALSE otherwise.
  */
@@ -346,7 +351,7 @@
  * @uri: A URI string
  *
  * Tests if the given string is a valid URI identifier. URIs start with a valid
- * protocol followed by "://" and maybe a string identifying the location.
+ * scheme followed by ":" and maybe a string identifying the location.
  *
  * Returns: TRUE if the string is a valid URI
  */
@@ -363,7 +368,7 @@
 
   gst_uri_protocol_check_internal (uri, &endptr);
 
-  return (*endptr == ':' && *(endptr + 1) == '/' && *(endptr + 2) == '/');
+  return *endptr == ':';
 }
 
 /**
@@ -387,9 +392,9 @@
   g_return_val_if_fail (uri != NULL, NULL);
   g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
 
-  colon = strstr (uri, "://");
+  colon = strstr (uri, ":");
 
-  return g_strdown (g_strndup (uri, colon - uri));
+  return g_ascii_strdown (uri, colon - uri);
 }
 
 /**
@@ -416,12 +421,12 @@
   g_return_val_if_fail (protocol != NULL, FALSE);
   g_return_val_if_fail (gst_uri_is_valid (uri), FALSE);
 
-  colon = strstr (uri, "://");
+  colon = strstr (uri, ":");
 
   if (colon == NULL)
     return FALSE;
 
-  return (strncmp (uri, protocol, (gsize) (colon - uri)) == 0);
+  return (g_ascii_strncasecmp (uri, protocol, (gsize) (colon - uri)) == 0);
 }
 
 /**
@@ -450,6 +455,8 @@
   g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
 
   colon = strstr (uri, "://");
+  if (!colon)
+    return NULL;
 
   unescaped = unescape_string (colon + 3, "/");
 
@@ -468,7 +475,7 @@
 #endif
 
   GST_LOG ("extracted location '%s' from URI '%s'", GST_STR_NULL (unescaped),
-      uri);;
+      uri);
   return unescaped;
 }
 
@@ -489,15 +496,17 @@
 gchar *
 gst_uri_construct (const gchar * protocol, const gchar * location)
 {
-  char *escaped;
+  char *escaped, *proto_lowercase;
   char *retval;
 
   g_return_val_if_fail (gst_uri_protocol_is_valid (protocol), NULL);
   g_return_val_if_fail (location != NULL, NULL);
 
+  proto_lowercase = g_ascii_strdown (protocol, -1);
   escaped = escape_string (location);
-  retval = g_strdup_printf ("%s://%s", protocol, escaped);
+  retval = g_strdup_printf ("%s://%s", proto_lowercase, escaped);
   g_free (escaped);
+  g_free (proto_lowercase);
 
   return retval;
 }
@@ -678,8 +687,13 @@
 
   iface = GST_URI_HANDLER_GET_INTERFACE (handler);
   g_return_val_if_fail (iface != NULL, GST_URI_UNKNOWN);
-  g_return_val_if_fail (iface->get_type != NULL, GST_URI_UNKNOWN);
-  ret = iface->get_type ();
+  g_return_val_if_fail (iface->get_type != NULL
+      || iface->get_type_full != NULL, GST_URI_UNKNOWN);
+
+  if (iface->get_type != NULL)
+    ret = iface->get_type ();
+  else
+    ret = iface->get_type_full (G_OBJECT_TYPE (handler));
   g_return_val_if_fail (GST_URI_TYPE_IS_VALID (ret), GST_URI_UNKNOWN);
 
   return ret;
@@ -772,6 +786,8 @@
 gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
 {
   GstURIHandlerInterface *iface;
+  gboolean ret;
+  gchar *new_uri, *protocol, *location, *colon;
 
   g_return_val_if_fail (GST_IS_URI_HANDLER (handler), FALSE);
   g_return_val_if_fail (gst_uri_is_valid (uri), FALSE);
@@ -779,7 +795,21 @@
   iface = GST_URI_HANDLER_GET_INTERFACE (handler);
   g_return_val_if_fail (iface != NULL, FALSE);
   g_return_val_if_fail (iface->set_uri != NULL, FALSE);
-  return iface->set_uri (handler, uri);
+
+  protocol = gst_uri_get_protocol (uri);
+
+  colon = strstr (uri, ":");
+  location = g_strdup (colon);
+
+  new_uri = g_strdup_printf ("%s%s", protocol, location);
+
+  ret = iface->set_uri (handler, uri);
+
+  g_free (new_uri);
+  g_free (location);
+  g_free (protocol);
+
+  return ret;
 }
 
 /**
--- a/gstreamer_core/gst/gsturi.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gsturi.h	Fri Apr 16 15:15:52 2010 +0300
@@ -58,7 +58,6 @@
 #define GST_URI_HANDLER(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
 #define GST_IS_URI_HANDLER(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_URI_HANDLER))
 #define GST_URI_HANDLER_GET_INTERFACE(obj)	(G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerInterface))
-#define GST_URI_HANDLER_CLASS(obj)	(G_TYPE_CHECK_CLASS_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
 
 /**
  * GstURIHandler:
--- a/gstreamer_core/gst/gstutils.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstutils.c	Fri Apr 16 15:15:52 2010 +0300
@@ -3,7 +3,7 @@
  *                    2000 Wim Taymans <wtay@chello.be>
  *                    2002 Thomas Vander Stichele <thomas@apestaart.org>
  *
- * gstutils.c: Utility functions: gtk_get_property stuff, etc.
+ * gstutils.c: Utility functions
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -37,8 +37,16 @@
 #include "gsterror.h"
 #include "gstinfo.h"
 #include "gstparse.h"
+#include "gstvalue.h"
 #include "gst-i18n-lib.h"
 
+/**
+ * gst_util_dump_mem:
+ * @mem: a pointer to the memory to dump
+ * @size: the size of the memory block to dump
+ *
+ * Dumps the memory block into a hex representation. Useful for debugging.
+ */
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #include <gobject_global.h>
@@ -95,6 +103,9 @@
  *
  * Converts the string to the type of the value and
  * sets the value with it.
+ *
+ * Note that this function is dangerous as it does not return any indication
+ * if the conversion worked or not.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -103,7 +114,7 @@
 void
 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
 {
-  gint sscanf_ret;
+  gboolean res;
 
   g_return_if_fail (value != NULL);
   g_return_if_fail (value_str != NULL);
@@ -111,86 +122,13 @@
   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
       g_type_name (G_VALUE_TYPE (value)));
 
-  switch (G_VALUE_TYPE (value)) {
-    case G_TYPE_STRING:
-      g_value_set_string (value, value_str);
-      break;
-    case G_TYPE_ENUM:
-    case G_TYPE_INT:{
-      gint i;
-
-      sscanf_ret = sscanf (value_str, "%d", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_int (value, i);
-      break;
-    }
-    case G_TYPE_UINT:{
-      guint i;
-
-      sscanf_ret = sscanf (value_str, "%u", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_uint (value, i);
-      break;
-    }
-    case G_TYPE_LONG:{
-      glong i;
-
-      sscanf_ret = sscanf (value_str, "%ld", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_long (value, i);
-      break;
-    }
-    case G_TYPE_ULONG:{
-      gulong i;
-
-      sscanf_ret = sscanf (value_str, "%lu", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_ulong (value, i);
-      break;
-    }
-    case G_TYPE_BOOLEAN:{
-      gboolean i = FALSE;
-
-      if (!g_ascii_strncasecmp ("true", value_str, 4))
-        i = TRUE;
-      g_value_set_boolean (value, i);
-      break;
-    }
-    case G_TYPE_CHAR:{
-      gchar i;
-
-      sscanf_ret = sscanf (value_str, "%c", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_char (value, i);
-      break;
-    }
-    case G_TYPE_UCHAR:{
-      guchar i;
-
-      sscanf_ret = sscanf (value_str, "%c", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_uchar (value, i);
-      break;
-    }
-    case G_TYPE_FLOAT:{
-      gfloat i;
-
-      sscanf_ret = sscanf (value_str, "%f", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_float (value, i);
-      break;
-    }
-    case G_TYPE_DOUBLE:{
-      gfloat i;
-
-      sscanf_ret = sscanf (value_str, "%g", &i);
-      g_return_if_fail (sscanf_ret == 1);
-      g_value_set_double (value, (gdouble) i);
-      break;
-    }
-    default:
-      break;
+  res = gst_value_deserialize (value, value_str);
+  if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
+    /* backwards compat, all booleans that fail to parse are false */
+    g_value_set_boolean (value, FALSE);
+    res = TRUE;
   }
+  g_return_if_fail (res);
 }
 
 /**
@@ -201,6 +139,9 @@
  *
  * Convertes the string value to the type of the objects argument and
  * sets the argument with it.
+ *
+ * Note that this function silently returns if @object has no property named
+ * @name or when @value cannot be converted to the type of the property.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -210,111 +151,41 @@
 gst_util_set_object_arg (GObject * object, const gchar * name,
     const gchar * value)
 {
-  gboolean sscanf_ret;
-
-  if (name && value) {
-    GParamSpec *paramspec;
-
-    paramspec =
-        g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
-
-    if (!paramspec) {
-      return;
-    }
-
-    GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d",
-        paramspec->flags, (gint) paramspec->value_type);
-
-    if (paramspec->flags & G_PARAM_WRITABLE) {
-      switch (paramspec->value_type) {
-        case G_TYPE_STRING:
-          g_object_set (G_OBJECT (object), name, value, NULL);
-          break;
-        case G_TYPE_ENUM:
-        case G_TYPE_INT:{
-          gint i;
-
-          sscanf_ret = sscanf (value, "%d", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_UINT:{
-          guint i;
-
-          sscanf_ret = sscanf (value, "%u", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_LONG:{
-          glong i;
-
-          sscanf_ret = sscanf (value, "%ld", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_ULONG:{
-          gulong i;
-
-          sscanf_ret = sscanf (value, "%lu", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_BOOLEAN:{
-          gboolean i = FALSE;
-
-          if (!g_ascii_strncasecmp ("true", value, 4))
-            i = TRUE;
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_CHAR:{
-          gchar i;
-
-          sscanf_ret = sscanf (value, "%c", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_UCHAR:{
-          guchar i;
-
-          sscanf_ret = sscanf (value, "%c", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_FLOAT:{
-          gfloat i;
-
-          sscanf_ret = sscanf (value, "%f", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, i, NULL);
-          break;
-        }
-        case G_TYPE_DOUBLE:{
-          gfloat i;
-
-          sscanf_ret = sscanf (value, "%g", &i);
-          g_return_if_fail (sscanf_ret == 1);
-          g_object_set (G_OBJECT (object), name, (gdouble) i, NULL);
-          break;
-        }
-        default:
-          if (G_IS_PARAM_SPEC_ENUM (paramspec)) {
-            gint i;
-
-            sscanf_ret = sscanf (value, "%d", &i);
-            g_return_if_fail (sscanf_ret == 1);
-            g_object_set (G_OBJECT (object), name, i, NULL);
-          }
-          break;
-      }
-    }
+  GParamSpec *pspec;
+  GType value_type;
+  GValue v = { 0, };
+
+  g_return_if_fail (G_IS_OBJECT (object));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (value != NULL);
+
+  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
+  if (!pspec)
+    return;
+
+  value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+
+  GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s",
+      pspec->flags, g_type_name (value_type));
+
+  if (!(pspec->flags & G_PARAM_WRITABLE))
+    return;
+
+  g_value_init (&v, value_type);
+
+  /* special case for element <-> xml (de)serialisation */
+  if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) {
+    g_value_set_boxed (&v, NULL);
+    goto done;
   }
+
+  if (!gst_value_deserialize (&v, value))
+    return;
+
+done:
+
+  g_object_set_property (object, pspec->name, &v);
+  g_value_unset (&v);
 }
 
 /* work around error C2520: conversion from unsigned __int64 to double
@@ -435,7 +306,7 @@
 }
 
 static guint64
-gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
+gst_util_uint64_scale_int64_unchecked (guint64 val, guint64 num, guint64 denom)
 {
   GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
   GstUInt64 v, n;
@@ -467,7 +338,7 @@
   c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
 
   /* if high bits bigger than denom, we overflow */
-  if (c1.ll >= denom)
+  if (G_UNLIKELY (c1.ll >= denom))
     goto overflow;
 
   /* shortcut for division by 1, c1.ll should be 0 because of the
@@ -497,6 +368,36 @@
   }
 }
 
+static inline guint64
+gst_util_uint64_scale_int_unchecked (guint64 val, gint num, gint denom)
+{
+  GstUInt64 result;
+  GstUInt64 low, high;
+
+  /* do 96 bits mult/div */
+  low.ll = val;
+  result.ll = ((guint64) low.l.low) * num;
+  high.ll = ((guint64) low.l.high) * num + (result.l.high);
+
+  low.ll = high.ll / denom;
+  result.l.high = high.ll % denom;
+  result.ll /= denom;
+
+  /* avoid overflow */
+  if (G_UNLIKELY (low.ll + result.l.high > G_MAXUINT32))
+    goto overflow;
+
+  result.l.high += low.l.low;
+
+  return result.ll;
+
+overflow:
+  {
+    return G_MAXUINT64;
+  }
+}
+
+
 /**
  * gst_util_uint64_scale:
  * @val: the number to scale
@@ -519,33 +420,33 @@
 {
   g_return_val_if_fail (denom != 0, G_MAXUINT64);
 
-  if (num == 0)
+  if (G_UNLIKELY (num == 0))
     return 0;
 
-  if (num == 1 && denom == 1)
+  if (G_UNLIKELY (num == denom))
     return val;
 
   /* if the denom is high, we need to do a 64 muldiv */
-  if (denom > G_MAXINT32)
+  if (G_UNLIKELY (denom > G_MAXINT32))
     goto do_int64;
 
   /* if num and denom are low we can do a 32 bit muldiv */
-  if (num <= G_MAXINT32)
+  if (G_LIKELY (num <= G_MAXINT32))
     goto do_int32;
 
   /* val and num are high, we need 64 muldiv */
-  if (val > G_MAXINT32)
+  if (G_UNLIKELY (val > G_MAXINT32))
     goto do_int64;
 
   /* val is low and num is high, we can swap them and do 32 muldiv */
-  return gst_util_uint64_scale_int (num, (gint) val, (gint) denom);
+  return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom);
 
 do_int32:
-  return gst_util_uint64_scale_int (val, (gint) num, (gint) denom);
+  return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom);
 
 do_int64:
   /* to the more heavy implementations... */
-  return gst_util_uint64_scale_int64 (val, num, denom);
+  return gst_util_uint64_scale_int64_unchecked (val, num, denom);
 }
 
 /**
@@ -569,43 +470,71 @@
 guint64
 gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
 {
-  GstUInt64 result;
-  GstUInt64 low, high;
-
   g_return_val_if_fail (denom > 0, G_MAXUINT64);
   g_return_val_if_fail (num >= 0, G_MAXUINT64);
 
-  if (num == 0)
+  if (G_UNLIKELY (num == 0))
     return 0;
 
-  if (num == 1 && denom == 1)
+  if (G_UNLIKELY (num == denom))
     return val;
 
   if (val <= G_MAXUINT32)
     /* simple case */
     return val * num / denom;
 
-  /* do 96 bits mult/div */
-  low.ll = val;
-  result.ll = ((guint64) low.l.low) * num;
-  high.ll = ((guint64) low.l.high) * num + (result.l.high);
-
-  low.ll = high.ll / denom;
-  result.l.high = high.ll % denom;
-  result.ll /= denom;
-
-  /* avoid overflow */
-  if (low.ll + result.l.high > G_MAXUINT32)
-    goto overflow;
-
-  result.l.high += low.l.low;
-
-  return result.ll;
-
-overflow:
-  {
-    return G_MAXUINT64;
-  }
+  return gst_util_uint64_scale_int_unchecked (val, num, denom);
+}
+
+/**
+ * gst_util_seqnum_next:
+ *
+ * Return a constantly incrementing sequence number.
+ *
+ * This function is used internally to GStreamer to be able to determine which
+ * events and messages are "the same". For example, elements may set the seqnum
+ * on a segment-done message to be the same as that of the last seek event, to
+ * indicate that event and the message correspond to the same segment.
+ *
+ * Returns: A constantly incrementing 32-bit unsigned integer, which might
+ * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure
+ * you handle wraparound correctly.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint32
+gst_util_seqnum_next (void)
+{
+  static gint counter = 0;
+  return g_atomic_int_exchange_and_add (&counter, 1);
+}
+
+/**
+ * gst_util_seqnum_compare:
+ * @s1: A sequence number.
+ * @s2: Another sequence number.
+ *
+ * Compare two sequence numbers, handling wraparound.
+ * 
+ * The current implementation just returns (gint32)(@s1 - @s2).
+ *
+ * Returns: A negative number if @s1 is before @s2, 0 if they are equal, or a
+ * positive number if @s1 is after @s2.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gint32
+gst_util_seqnum_compare (guint32 s1, guint32 s2)
+{
+  return (gint32) (s1 - s2);
 }
 
 /* -----------------------------------------------------
@@ -928,6 +857,60 @@
   return pad;
 }
 
+/*
+ * Checks if the source pad and the sink pad can be linked.
+ * Both @srcpad and @sinkpad must be unlinked and have a parent.
+ */
+static gboolean
+gst_pad_check_link (GstPad * srcpad, GstPad * sinkpad)
+{
+  /* FIXME This function is gross.  It's almost a direct copy of
+   * gst_pad_link_filtered().  Any decent programmer would attempt
+   * to merge the two functions, which I will do some day. --ds
+   */
+
+  /* generic checks */
+  g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
+  g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
+
+  GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
+      GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+
+  /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
+  if (GST_PAD_PEER (srcpad) != NULL) {
+    GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
+        GST_DEBUG_PAD_NAME (srcpad));
+    return FALSE;
+  }
+  if (GST_PAD_PEER (sinkpad) != NULL) {
+    GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
+        GST_DEBUG_PAD_NAME (sinkpad));
+    return FALSE;
+  }
+  if (!GST_PAD_IS_SRC (srcpad)) {
+    GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
+        GST_DEBUG_PAD_NAME (srcpad));
+    return FALSE;
+  }
+  if (!GST_PAD_IS_SINK (sinkpad)) {
+    GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
+        GST_DEBUG_PAD_NAME (sinkpad));
+    return FALSE;
+  }
+  if (GST_PAD_PARENT (srcpad) == NULL) {
+    GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
+        GST_DEBUG_PAD_NAME (srcpad));
+    return FALSE;
+  }
+  if (GST_PAD_PARENT (sinkpad) == NULL) {
+    GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
+        GST_DEBUG_PAD_NAME (srcpad));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
 /**
  * gst_element_get_compatible_pad:
  * @element: a #GstElement in which the pad should be found.
@@ -955,8 +938,6 @@
   GstPad *foundpad = NULL;
   gboolean done;
 
-  /* FIXME check for caps compatibility */
-
   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
@@ -985,22 +966,47 @@
 
         peer = gst_pad_get_peer (current);
 
-        if (peer == NULL && gst_pad_can_link (pad, current)) {
-
+        if (peer == NULL && gst_pad_check_link (pad, current)) {
+          GstCaps *temp, *temp2, *intersection;
+
+          /* Now check if the two pads' caps are compatible */
+          temp = gst_pad_get_caps (pad);
+          if (caps) {
+            intersection = gst_caps_intersect (temp, caps);
+            gst_caps_unref (temp);
+          } else {
+            intersection = temp;
+          }
+
+          temp = gst_pad_get_caps (current);
+          temp2 = gst_caps_intersect (temp, intersection);
+          gst_caps_unref (temp);
+          gst_caps_unref (intersection);
+
+          intersection = temp2;
+
+          if (!gst_caps_is_empty (intersection)) {
+            gst_caps_unref (intersection);
+
+            GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
+                "found existing unlinked compatible pad %s:%s",
+                GST_DEBUG_PAD_NAME (current));
+            gst_iterator_free (pads);
+
+            return current;
+          } else {
+            GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads");
+          }
+          gst_caps_unref (intersection);
+        } else {
           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
-              "found existing unlinked pad %s:%s",
-              GST_DEBUG_PAD_NAME (current));
-
-          gst_iterator_free (pads);
-
-          return current;
-        } else {
-          GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
-
-          gst_object_unref (current);
-          if (peer)
-            gst_object_unref (peer);
+              "already linked or cannot be linked (peer = %p)", peer);
         }
+        GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
+
+        gst_object_unref (current);
+        if (peer)
+          gst_object_unref (peer);
         break;
       }
       case GST_ITERATOR_DONE:
@@ -1016,12 +1022,18 @@
   }
   gst_iterator_free (pads);
 
+  GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
+      "Could not find a compatible unlinked always pad to link to %s:%s, now checking request pads",
+      GST_DEBUG_PAD_NAME (pad));
+
   /* try to create a new one */
   /* requesting is a little crazy, we need a template. Let's create one */
+  /* FIXME: why not gst_pad_get_pad_template (pad); */
   templcaps = gst_pad_get_caps (pad);
 
   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
+
   foundpad = gst_element_request_compatible_pad (element, templ);
   gst_object_unref (templ);
 
@@ -1160,8 +1172,8 @@
     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
 
     if (template->direction == GST_PAD_SRC) {
-      if (gst_caps_is_always_compatible (gst_static_caps_get (&template->
-                  static_caps), caps))
+      if (gst_caps_is_always_compatible (gst_static_caps_get
+              (&template->static_caps), caps))
         return TRUE;
     }
     templates = g_list_next (templates);
@@ -1437,7 +1449,8 @@
   /* get a src pad */
   if (srcpadname) {
     /* name specified, look it up */
-    srcpad = gst_element_get_pad (src, srcpadname);
+    if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
+      srcpad = gst_element_get_request_pad (src, srcpadname);
     if (!srcpad) {
       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
           GST_ELEMENT_NAME (src), srcpadname);
@@ -1470,7 +1483,8 @@
   /* get a destination pad */
   if (destpadname) {
     /* name specified, look it up */
-    destpad = gst_element_get_pad (dest, destpadname);
+    if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
+      destpad = gst_element_get_request_pad (dest, destpadname);
     if (!destpad) {
       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
           GST_ELEMENT_NAME (dest), destpadname);
@@ -1775,6 +1789,7 @@
 gboolean
 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
 {
+  gboolean res = TRUE;
   va_list args;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
@@ -1783,8 +1798,10 @@
   va_start (args, element_2);
 
   while (element_2) {
-    if (!gst_element_link (element_1, element_2))
-      return FALSE;
+    if (!gst_element_link (element_1, element_2)) {
+      res = FALSE;
+      break;
+    }
 
     element_1 = element_2;
     element_2 = va_arg (args, GstElement *);
@@ -1792,7 +1809,7 @@
 
   va_end (args);
 
-  return TRUE;
+  return res;
 }
 
 /**
@@ -1841,6 +1858,9 @@
     GstElement * dest, const gchar * destpadname)
 {
   GstPad *srcpad, *destpad;
+  gboolean srcrequest, destrequest;
+
+  srcrequest = destrequest = FALSE;
 
   g_return_if_fail (src != NULL);
   g_return_if_fail (GST_IS_ELEMENT (src));
@@ -1850,23 +1870,33 @@
   g_return_if_fail (destpadname != NULL);
 
   /* obtain the pads requested */
-  srcpad = gst_element_get_pad (src, srcpadname);
+  if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
+    if ((srcpad = gst_element_get_request_pad (src, srcpadname)))
+      srcrequest = TRUE;
   if (srcpad == NULL) {
     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
     return;
   }
-  destpad = gst_element_get_pad (dest, destpadname);
+  if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
+    if ((destpad = gst_element_get_request_pad (dest, destpadname)))
+      destrequest = TRUE;
   if (destpad == NULL) {
     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
         destpadname);
-    gst_object_unref (srcpad);
-    return;
+    goto free_src;
   }
 
   /* we're satisified they can be unlinked, let's do it */
   gst_pad_unlink (srcpad, destpad);
+
+  if (destrequest)
+    gst_element_release_request_pad (dest, destpad);
+  gst_object_unref (destpad);
+
+free_src:
+  if (srcrequest)
+    gst_element_release_request_pad (src, srcpad);
   gst_object_unref (srcpad);
-  gst_object_unref (destpad);
 }
 
 /**
@@ -1940,8 +1970,7 @@
         if (GST_PAD_IS_SRC (pad)) {
           GstPad *peerpad = gst_pad_get_peer (pad);
 
-          /* see if the pad is connected and is really a pad
-           * of dest */
+          /* see if the pad is linked and is really a pad of dest */
           if (peerpad) {
             GstElement *peerelem;
 
@@ -2135,70 +2164,6 @@
 }
 
 /**
- * gst_pad_can_link:
- * @srcpad: the source #GstPad to link.
- * @sinkpad: the sink #GstPad to link.
- *
- * Checks if the source pad and the sink pad can be linked.
- * Both @srcpad and @sinkpad must be unlinked.
- *
- * Returns: TRUE if the pads can be linked, FALSE otherwise.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gboolean
-gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
-{
-  /* FIXME This function is gross.  It's almost a direct copy of
-   * gst_pad_link_filtered().  Any decent programmer would attempt
-   * to merge the two functions, which I will do some day. --ds
-   */
-
-  /* generic checks */
-  g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
-  g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
-
-  GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
-      GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-
-  /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
-  if (GST_PAD_PEER (srcpad) != NULL) {
-    GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
-        GST_DEBUG_PAD_NAME (srcpad));
-    return FALSE;
-  }
-  if (GST_PAD_PEER (sinkpad) != NULL) {
-    GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
-        GST_DEBUG_PAD_NAME (sinkpad));
-    return FALSE;
-  }
-  if (!GST_PAD_IS_SRC (srcpad)) {
-    GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
-        GST_DEBUG_PAD_NAME (srcpad));
-    return FALSE;
-  }
-  if (!GST_PAD_IS_SINK (sinkpad)) {
-    GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
-        GST_DEBUG_PAD_NAME (sinkpad));
-    return FALSE;
-  }
-  if (GST_PAD_PARENT (srcpad) == NULL) {
-    GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
-        GST_DEBUG_PAD_NAME (srcpad));
-    return FALSE;
-  }
-  if (GST_PAD_PARENT (sinkpad) == NULL) {
-    GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
-        GST_DEBUG_PAD_NAME (srcpad));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/**
  * gst_pad_use_fixed_caps:
  * @pad: the pad to use
  *
@@ -2249,9 +2214,7 @@
         "using pad caps %p %" GST_PTR_FORMAT, result, result);
 
     result = gst_caps_ref (result);
-    goto done;
-  }
-  if (GST_PAD_PAD_TEMPLATE (pad)) {
+  } else if (GST_PAD_PAD_TEMPLATE (pad)) {
     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
 
     result = GST_PAD_TEMPLATE_CAPS (templ);
@@ -2260,12 +2223,10 @@
         result);
 
     result = gst_caps_ref (result);
-    goto done;
+  } else {
+    GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
+    result = gst_caps_new_empty ();
   }
-  GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
-  result = gst_caps_new_empty ();
-
-done:
   GST_OBJECT_UNLOCK (pad);
 
   return result;
@@ -2559,6 +2520,11 @@
  * If the buffers point to contiguous areas of memory, the buffer
  * is created without copying the data.
  *
+ * This is a convenience function for C programmers. See also 
+ * gst_buffer_merge(), which does the same thing without 
+ * unreffing the input parameters. Language bindings without 
+ * explicit reference counting should not wrap this function.
+ *
  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
  */
 #ifdef __SYMBIAN32__
@@ -2606,6 +2572,7 @@
 static gboolean
 intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
 {
+  /* skip the pad, the request came from */
   if (pad != orig) {
     GstCaps *peercaps, *existing;
 
@@ -2649,7 +2616,8 @@
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
+  GST_CAT_DEBUG (GST_CAT_PADS, "proxying getcaps for %s:%s",
+      GST_DEBUG_PAD_NAME (pad));
 
   element = gst_pad_get_parent_element (pad);
   if (element == NULL)
@@ -2757,7 +2725,8 @@
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (caps != NULL, FALSE);
 
-  GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
+  GST_CAT_DEBUG (GST_CAT_PADS, "proxying pad link for %s:%s",
+      GST_DEBUG_PAD_NAME (pad));
 
   element = gst_pad_get_parent_element (pad);
   if (element == NULL)
@@ -2957,7 +2926,6 @@
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (src_val >= 0, FALSE);
   g_return_val_if_fail (dest_format != NULL, FALSE);
   g_return_val_if_fail (dest_val != NULL, FALSE);
 
@@ -3024,7 +2992,11 @@
  * @value: value to set
  *
  * Unconditionally sets the atomic integer to @value.
+ * 
+ * Deprecated: Use g_atomic_int_set().
+ *
  */
+#ifndef GST_REMOVE_DEPRECATED
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -3032,12 +3004,9 @@
 void
 gst_atomic_int_set (gint * atomic_int, gint value)
 {
-  int ignore;
-
-  *atomic_int = value;
-  /* read acts as a memory barrier */
-  ignore = g_atomic_int_get (atomic_int);
+  g_atomic_int_set (atomic_int, value);
 }
+#endif
 
 /**
  * gst_pad_add_data_probe:
@@ -3076,17 +3045,68 @@
 gulong
 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
 {
+  return gst_pad_add_data_probe_full (pad, handler, data, NULL);
+}
+
+/**
+ * gst_pad_add_data_probe_full:
+ * @pad: pad to add the data probe handler to
+ * @handler: function to call when data is passed over pad
+ * @data: data to pass along with the handler
+ * @notify: function to call when the probe is disconnected, or NULL
+ *
+ * Adds a "data probe" to a pad. This function will be called whenever data
+ * passes through a pad. In this case data means both events and buffers. The
+ * probe will be called with the data as an argument, meaning @handler should
+ * have the same callback signature as the #GstPad::have-data signal.
+ * Note that the data will have a reference count greater than 1, so it will
+ * be immutable -- you must not change it.
+ *
+ * For source pads, the probe will be called after the blocking function, if any
+ * (see gst_pad_set_blocked_async()), but before looking up the peer to chain
+ * to. For sink pads, the probe function will be called before configuring the
+ * sink with new caps, if any, and before calling the pad's chain function.
+ *
+ * Your data probe should return TRUE to let the data continue to flow, or FALSE
+ * to drop it. Dropping data is rarely useful, but occasionally comes in handy
+ * with events.
+ *
+ * Although probes are implemented internally by connecting @handler to the
+ * have-data signal on the pad, if you want to remove a probe it is insufficient
+ * to only call g_signal_handler_disconnect on the returned handler id. To
+ * remove a probe, use the appropriate function, such as
+ * gst_pad_remove_data_probe().
+ *
+ * The @notify function is called when the probe is disconnected and usually
+ * used to free @data.
+ *
+ * Returns: The handler id.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gulong
+gst_pad_add_data_probe_full (GstPad * pad, GCallback handler,
+    gpointer data, GDestroyNotify notify)
+{
   gulong sigid;
 
   g_return_val_if_fail (GST_IS_PAD (pad), 0);
   g_return_val_if_fail (handler != NULL, 0);
 
   GST_OBJECT_LOCK (pad);
-  sigid = g_signal_connect (pad, "have-data", handler, data);
+
+  /* we only expose a GDestroyNotify in our API because that's less confusing */
+  sigid = g_signal_connect_data (pad, "have-data", handler, data,
+      (GClosureNotify) notify, 0);
+
   GST_PAD_DO_EVENT_SIGNALS (pad)++;
   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
-  GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes",
-      GST_DEBUG_PAD_NAME (pad),
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
+      "adding data probe, now %d data, %d event probes",
       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
@@ -3111,16 +3131,48 @@
 gulong
 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
 {
+  return gst_pad_add_event_probe_full (pad, handler, data, NULL);
+}
+
+/**
+ * gst_pad_add_event_probe_full:
+ * @pad: pad to add the event probe handler to
+ * @handler: function to call when events are passed over pad
+ * @data: data to pass along with the handler, or NULL
+ * @notify: function to call when probe is disconnected, or NULL
+ *
+ * Adds a probe that will be called for all events passing through a pad. See
+ * gst_pad_add_data_probe() for more information.
+ *
+ * The @notify function is called when the probe is disconnected and usually
+ * used to free @data.
+ *
+ * Returns: The handler id
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gulong
+gst_pad_add_event_probe_full (GstPad * pad, GCallback handler,
+    gpointer data, GDestroyNotify notify)
+{
   gulong sigid;
 
   g_return_val_if_fail (GST_IS_PAD (pad), 0);
   g_return_val_if_fail (handler != NULL, 0);
 
   GST_OBJECT_LOCK (pad);
-  sigid = g_signal_connect (pad, "have-data::event", handler, data);
+
+  /* we only expose a GDestroyNotify in our API because that's less confusing */
+  sigid = g_signal_connect_data (pad, "have-data::event", handler, data,
+      (GClosureNotify) notify, 0);
+
   GST_PAD_DO_EVENT_SIGNALS (pad)++;
-  GST_DEBUG ("adding event probe to pad %s:%s, now %d probes",
-      GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes",
+      GST_PAD_DO_EVENT_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
   return sigid;
@@ -3144,16 +3196,48 @@
 gulong
 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
 {
+  return gst_pad_add_buffer_probe_full (pad, handler, data, NULL);
+}
+
+/**
+ * gst_pad_add_buffer_probe_full:
+ * @pad: pad to add the buffer probe handler to
+ * @handler: function to call when buffer are passed over pad
+ * @data: data to pass along with the handler
+ * @notify: function to call when the probe is disconnected, or NULL
+ *
+ * Adds a probe that will be called for all buffers passing through a pad. See
+ * gst_pad_add_data_probe() for more information.
+ *
+ * The @notify function is called when the probe is disconnected and usually
+ * used to free @data.
+ *
+ * Returns: The handler id
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gulong
+gst_pad_add_buffer_probe_full (GstPad * pad, GCallback handler,
+    gpointer data, GDestroyNotify notify)
+{
   gulong sigid;
 
   g_return_val_if_fail (GST_IS_PAD (pad), 0);
   g_return_val_if_fail (handler != NULL, 0);
 
   GST_OBJECT_LOCK (pad);
-  sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
+
+  /* we only expose a GDestroyNotify in our API because that's less confusing */
+  sigid = g_signal_connect_data (pad, "have-data::buffer", handler, data,
+      (GClosureNotify) notify, 0);
+
   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
-  GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes",
-      GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes",
+      GST_PAD_DO_BUFFER_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
   return sigid;
@@ -3180,10 +3264,9 @@
   g_signal_handler_disconnect (pad, handler_id);
   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
   GST_PAD_DO_EVENT_SIGNALS (pad)--;
-  GST_DEBUG
-      ("removed data probe from pad %s:%s, now %d event, %d buffer probes",
-      GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad),
-      GST_PAD_DO_BUFFER_SIGNALS (pad));
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
+      "removed data probe, now %d event, %d buffer probes",
+      GST_PAD_DO_EVENT_SIGNALS (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
 }
@@ -3208,8 +3291,9 @@
   GST_OBJECT_LOCK (pad);
   g_signal_handler_disconnect (pad, handler_id);
   GST_PAD_DO_EVENT_SIGNALS (pad)--;
-  GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
-      GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
+      "removed event probe, now %d event probes",
+      GST_PAD_DO_EVENT_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 }
 
@@ -3233,8 +3317,9 @@
   GST_OBJECT_LOCK (pad);
   g_signal_handler_disconnect (pad, handler_id);
   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
-  GST_DEBUG ("removed buffer probe from pad %s:%s, now %d buffer probes",
-      GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
+      "removed buffer probe, now %d buffer probes",
+      GST_PAD_DO_BUFFER_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
 }
@@ -3264,8 +3349,9 @@
   g_return_if_fail (list != NULL);
 
   gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
+  /* FIXME 0.11: Set the pad as source. */
   gst_element_post_message (element,
-      gst_message_new_tag (GST_OBJECT (element), list));
+      gst_message_new_tag_full (GST_OBJECT (element), pad, list));
 }
 
 static void
@@ -3311,10 +3397,10 @@
 }
 
 static GstPad *
-element_find_unconnected_pad (GstElement * element, GstPadDirection direction)
+element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
 {
   GstIterator *iter;
-  GstPad *unconnected_pad = NULL;
+  GstPad *unlinked_pad = NULL;
   gboolean done;
 
   switch (direction) {
@@ -3341,11 +3427,11 @@
 
         peer = gst_pad_get_peer (GST_PAD (pad));
         if (peer == NULL) {
-          unconnected_pad = pad;
+          unlinked_pad = pad;
           done = TRUE;
           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
               "found existing unlinked pad %s:%s",
-              GST_DEBUG_PAD_NAME (unconnected_pad));
+              GST_DEBUG_PAD_NAME (unlinked_pad));
         } else {
           gst_object_unref (pad);
           gst_object_unref (peer);
@@ -3366,30 +3452,30 @@
 
   gst_iterator_free (iter);
 
-  return unconnected_pad;
+  return unlinked_pad;
 }
 
 /**
- * gst_bin_find_unconnected_pad:
- * @bin: bin in which to look for elements with unconnected pads
- * @direction: whether to look for an unconnected source or sink pad
+ * gst_bin_find_unlinked_pad:
+ * @bin: bin in which to look for elements with unlinked pads
+ * @direction: whether to look for an unlinked source or sink pad
  *
- * Recursively looks for elements with an unconnected pad of the given
- * direction within the specified bin and returns an unconnected pad
+ * Recursively looks for elements with an unlinked pad of the given
+ * direction within the specified bin and returns an unlinked pad
  * if one is found, or NULL otherwise. If a pad is found, the caller
  * owns a reference to it and should use gst_object_unref() on the
  * pad when it is not needed any longer.
  *
- * Returns: unconnected pad of the given direction, or NULL.
+ * Returns: unlinked pad of the given direction, or NULL.
  *
- * Since: 0.10.3
+ * Since: 0.10.20
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 GstPad *
-gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
+gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
 {
   GstIterator *iter;
   gboolean done;
@@ -3405,7 +3491,7 @@
 
     switch (gst_iterator_next (iter, &element)) {
       case GST_ITERATOR_OK:
-        pad = element_find_unconnected_pad (GST_ELEMENT (element), direction);
+        pad = element_find_unlinked_pad (GST_ELEMENT (element), direction);
         gst_object_unref (element);
         if (pad != NULL)
           done = TRUE;
@@ -3428,20 +3514,48 @@
 }
 
 /**
+ * gst_bin_find_unconnected_pad:
+ * @bin: bin in which to look for elements with unlinked pads
+ * @direction: whether to look for an unlinked source or sink pad
+ *
+ * Recursively looks for elements with an unlinked pad of the given
+ * direction within the specified bin and returns an unlinked pad
+ * if one is found, or NULL otherwise. If a pad is found, the caller
+ * owns a reference to it and should use gst_object_unref() on the
+ * pad when it is not needed any longer.
+ *
+ * Returns: unlinked pad of the given direction, or NULL.
+ *
+ * Since: 0.10.3
+ *
+ * Deprecated: use gst_bin_find_unlinked_pad() instead.
+ */
+#ifndef GST_REMOVE_DEPRECATED
+
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+GstPad *
+gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
+{
+  return gst_bin_find_unlinked_pad (bin, direction);
+}
+#endif
+
+/**
  * gst_parse_bin_from_description:
  * @bin_description: command line describing the bin
- * @ghost_unconnected_pads: whether to automatically create ghost pads
- *                          for unconnected source or sink pads within
- *                          the bin
+ * @ghost_unlinked_pads: whether to automatically create ghost pads
+ *     for unlinked source or sink pads within the bin
  * @err: where to store the error message in case of an error, or NULL
  *
  * This is a convenience wrapper around gst_parse_launch() to create a
  * #GstBin from a gst-launch-style pipeline description. See
  * gst_parse_launch() and the gst-launch man page for details about the
- * syntax. Ghost pads on the bin for unconnected source or sink pads
+ * syntax. Ghost pads on the bin for unlinked source or sink pads
  * within the bin can automatically be created (but only a maximum of
  * one ghost pad for each direction will be created; if you expect
- * multiple unconnected source pads or multiple unconnected sink pads
+ * multiple unlinked source pads or multiple unlinked sink pads
  * and want them all ghosted, you will have to create the ghost pads
  * yourself).
  *
@@ -3455,7 +3569,43 @@
 
 GstElement *
 gst_parse_bin_from_description (const gchar * bin_description,
-    gboolean ghost_unconnected_pads, GError ** err)
+    gboolean ghost_unlinked_pads, GError ** err)
+{
+  return gst_parse_bin_from_description_full (bin_description,
+      ghost_unlinked_pads, NULL, 0, err);
+}
+
+/**
+ * gst_parse_bin_from_description_full:
+ * @bin_description: command line describing the bin
+ * @ghost_unlinked_pads: whether to automatically create ghost pads
+ *     for unlinked source or sink pads within the bin
+ * @context: a parse context allocated with gst_parse_context_new(), or %NULL
+ * @flags: parsing options, or #GST_PARSE_FLAG_NONE
+ * @err: where to store the error message in case of an error, or NULL
+ *
+ * This is a convenience wrapper around gst_parse_launch() to create a
+ * #GstBin from a gst-launch-style pipeline description. See
+ * gst_parse_launch() and the gst-launch man page for details about the
+ * syntax. Ghost pads on the bin for unlinked source or sink pads
+ * within the bin can automatically be created (but only a maximum of
+ * one ghost pad for each direction will be created; if you expect
+ * multiple unlinked source pads or multiple unlinked sink pads
+ * and want them all ghosted, you will have to create the ghost pads
+ * yourself).
+ *
+ * Returns: a newly-created bin, or NULL if an error occurred.
+ *
+ * Since: 0.10.20
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstElement *
+gst_parse_bin_from_description_full (const gchar * bin_description,
+    gboolean ghost_unlinked_pads, GstParseContext * context,
+    GstParseFlags flags, GError ** err)
 {
 #ifndef GST_DISABLE_PARSE
   GstPad *pad = NULL;
@@ -3469,7 +3619,7 @@
 
   /* parse the pipeline to a bin */
   desc = g_strdup_printf ("bin.( %s )", bin_description);
-  bin = (GstBin *) gst_parse_launch (desc, err);
+  bin = (GstBin *) gst_parse_launch_full (desc, context, flags, err);
   g_free (desc);
 
   if (bin == NULL || (err && *err != NULL)) {
@@ -3479,12 +3629,12 @@
   }
 
   /* find pads and ghost them if necessary */
-  if (ghost_unconnected_pads) {
-    if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) {
+  if (ghost_unlinked_pads) {
+    if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) {
       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
       gst_object_unref (pad);
     }
-    if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) {
+    if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) {
       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
       gst_object_unref (pad);
     }
@@ -3494,7 +3644,7 @@
 #else
   gchar *msg;
 
-  GST_WARNING ("Disabled API called: gst_parse_bin_from_description()");
+  GST_WARNING ("Disabled API called");
 
   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
   g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
@@ -3607,3 +3757,95 @@
   return GST_TIMEVAL_TO_TIME (now);
 #endif
 }
+
+/**
+ * gst_util_array_binary_search:
+ * @array: the sorted input array
+ * @num_elements: number of elements in the array
+ * @element_size: size of every element in bytes
+ * @search_func: function to compare two elements, @search_data will always be passed as second argument
+ * @mode: search mode that should be used
+ * @search_data: element that should be found
+ * @user_data: data to pass to @search_func
+ *
+ * Searches inside @array for @search_data by using the comparison function
+ * @search_func. @array must be sorted ascending.
+ *
+ * As @search_data is always passed as second argument to @search_func it's
+ * not required that @search_data has the same type as the array elements.
+ *
+ * The complexity of this search function is O(log (num_elements)).
+ *
+ * Returns: The address of the found element or %NULL if nothing was found
+ *
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gpointer
+gst_util_array_binary_search (gpointer array, guint num_elements,
+    gsize element_size, GCompareDataFunc search_func, GstSearchMode mode,
+    gconstpointer search_data, gpointer user_data)
+{
+  glong left = 0, right = num_elements - 1, m;
+  gint ret;
+  guint8 *data = (guint8 *) array;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (element_size > 0, NULL);
+  g_return_val_if_fail (search_func != NULL, NULL);
+
+  /* 0. No elements => return NULL */
+  if (num_elements == 0)
+    return NULL;
+
+  /* 1. If search_data is before the 0th element return the 0th element */
+  ret = search_func (data, search_data, user_data);
+  if ((ret >= 0 && mode == GST_SEARCH_MODE_AFTER) || ret == 0)
+    return data;
+  else if (ret > 0)
+    return NULL;
+
+  /* 2. If search_data is after the last element return the last element */
+  ret =
+      search_func (data + (num_elements - 1) * element_size, search_data,
+      user_data);
+  if ((ret <= 0 && mode == GST_SEARCH_MODE_BEFORE) || ret == 0)
+    return data + (num_elements - 1) * element_size;
+  else if (ret < 0)
+    return NULL;
+
+  /* 3. else binary search */
+  while (TRUE) {
+    m = left + (right - left) / 2;
+
+    ret = search_func (data + m * element_size, search_data, user_data);
+
+    if (ret == 0) {
+      return data + m * element_size;
+    } else if (ret < 0) {
+      left = m + 1;
+    } else {
+      right = m - 1;
+    }
+
+    /* No exact match found */
+    if (right < left) {
+      if (mode == GST_SEARCH_MODE_EXACT) {
+        return NULL;
+      } else if (mode == GST_SEARCH_MODE_AFTER) {
+        if (ret < 0)
+          return (m < num_elements) ? data + (m + 1) * element_size : NULL;
+        else
+          return data + m * element_size;
+      } else {
+        if (ret < 0)
+          return data + m * element_size;
+        else
+          return (m > 0) ? data + (m - 1) * element_size : NULL;
+      }
+    }
+  }
+}
--- a/gstreamer_core/gst/gstutils.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstutils.h	Fri Apr 16 15:15:52 2010 +0300
@@ -27,6 +27,7 @@
 
 #include <glib.h>
 #include <gst/gstbin.h>
+#include <gst/gstparse.h>
 
 G_BEGIN_DECLS
 
@@ -46,12 +47,12 @@
 #endif
 
 
-guint64         gst_util_gdouble_to_guint64     (gdouble value);
+guint64         gst_util_gdouble_to_guint64     (gdouble value)  G_GNUC_PURE;
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gdouble         gst_util_guint64_to_gdouble     (guint64 value);
+gdouble         gst_util_guint64_to_gdouble     (guint64 value)  G_GNUC_PURE;
 
 /**
  * gst_guint64_to_gdouble:
@@ -78,13 +79,24 @@
 #define         gst_guint64_to_gdouble(value)   ((gdouble) (value))
 #endif
 
-guint64		gst_util_uint64_scale		(guint64 val, guint64 num, guint64 denom);
+guint64		gst_util_uint64_scale		(guint64 val, guint64 num, guint64 denom) G_GNUC_PURE;
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
-guint64         gst_util_uint64_scale_int       (guint64 val, gint num, gint denom);
+guint64         gst_util_uint64_scale_int       (guint64 val, gint num, gint denom) G_GNUC_PURE;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+guint32         gst_util_seqnum_next            (void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gint32          gst_util_seqnum_compare         (guint32 s1, guint32 s2);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
@@ -160,10 +172,15 @@
 __declspec(dllexport) GType									\
 type_as_function ## _get_type (void)					\
 {									\
-  static GType object_type = 0;						\
-  if (G_UNLIKELY (object_type == 0)) {					\
-    object_type = gst_type_register_static_full (parent_type_macro, #type,	\
-	sizeof (type ## Class),					\
+  /* The typedef for GType may be gulong or gsize, depending on the	\
+   * system and whether the compiler is c++ or not. The g_once_init_*	\
+   * functions always take a gsize * though ... */			\
+  static volatile gsize gonce_data = 0;					\
+  if (g_once_init_enter (&gonce_data)) {				\
+    GType _type;							\
+    _type = gst_type_register_static_full (parent_type_macro,           \
+        g_intern_static_string (#type),					\
+	sizeof (type ## Class),						\
         type_as_function ## _base_init,					\
         NULL,		  /* base_finalize */				\
         type_as_function ## _class_init_trampoline,			\
@@ -174,9 +191,10 @@
         (GInstanceInitFunc) type_as_function ## _init,                  \
         NULL,                                                           \
         (GTypeFlags) 0);				                \
-    additional_initializations (object_type);				\
+    additional_initializations (_type);				        \
+    g_once_init_leave (&gonce_data, (gsize) _type);			\
   }									\
-  return object_type;							\
+  return (GType) gonce_data;						\
 }
 
 #define __GST_DO_NOTHING(type)	/* NOP */
@@ -288,12 +306,12 @@
 	((parent_class_cast(parent_class)->name != NULL) ?		\
 	 parent_class_cast(parent_class)->name args : def_return)
 
-/* Define possibly unaligned memory access method whether the type of
- * architecture. */
-#if GST_HAVE_UNALIGNED_ACCESS
+/* Define PUT and GET functions for unaligned memory */
+#define _GST_GET(__data, __idx, __size, __shift) \
+    (((guint##__size) (((guint8 *) (__data))[__idx])) << (__shift))
 
-#define _GST_GET(__data, __size, __end) \
-    (GUINT##__size##_FROM_##__end (* ((guint##__size *) (__data))))
+#define _GST_PUT(__data, __idx, __size, __shift, __num) \
+    (((guint8 *) (__data))[__idx] = (((guint##__size) (__num)) >> (__shift)) & 0xff)
 
 /**
  * GST_READ_UINT64_BE:
@@ -301,115 +319,6 @@
  *
  * Read a 64 bit unsigned integer value in big endian format from the memory buffer.
  */
-#define GST_READ_UINT64_BE(data)	_GST_GET (data, 64, BE)
-/**
- * GST_READ_UINT64_LE:
- * @data: memory location
- *
- * Read a 64 bit unsigned integer value in little endian format from the memory buffer.
- */
-#define GST_READ_UINT64_LE(data)	_GST_GET (data, 64, LE)
-/**
- * GST_READ_UINT32_BE:
- * @data: memory location
- *
- * Read a 32 bit unsigned integer value in big endian format from the memory buffer.
- */
-#define GST_READ_UINT32_BE(data)	_GST_GET (data, 32, BE)
-/**
- * GST_READ_UINT32_LE:
- * @data: memory location
- *
- * Read a 32 bit unsigned integer value in little endian format from the memory buffer.
- */
-#define GST_READ_UINT32_LE(data)        _GST_GET (data, 32, LE)
-/**
- * GST_READ_UINT16_BE:
- * @data: memory location
- *
- * Read a 16 bit unsigned integer value in big endian format from the memory buffer.
- */
-#define GST_READ_UINT16_BE(data)        _GST_GET (data, 16, BE)
-/**
- * GST_READ_UINT16_LE:
- * @data: memory location
- *
- * Read a 16 bit unsigned integer value in little endian format from the memory buffer.
- */
-#define GST_READ_UINT16_LE(data)        _GST_GET (data, 16, LE)
-/**
- * GST_READ_UINT8:
- * @data: memory location
- *
- * Read an 8 bit unsigned integer value from the memory buffer.
- */
-#define GST_READ_UINT8(data)		(* ((guint8 *) (data)))
-
-#define _GST_PUT(__data, __size, __end, __num) \
-    ((* (guint##__size *) (__data)) = GUINT##__size##_TO_##__end (__num))
-
-/**
- * GST_WRITE_UINT64_BE:
- * @data: memory location
- * @num: value to store
- *
- * Store a 64 bit unsigned integer value in big endian format into the memory buffer.
- */
-#define GST_WRITE_UINT64_BE(data, num)	_GST_PUT(data, 64, BE, num)
-/**
- * GST_WRITE_UINT64_LE:
- * @data: memory location
- * @num: value to store
- *
- * Store a 64 bit unsigned integer value in little endian format into the memory buffer.
- */
-#define GST_WRITE_UINT64_LE(data, num)  _GST_PUT(data, 64, LE, num)
-/**
- * GST_WRITE_UINT32_BE:
- * @data: memory location
- * @num: value to store
- *
- * Store a 32 bit unsigned integer value in big endian format into the memory buffer.
- */
-#define GST_WRITE_UINT32_BE(data, num)  _GST_PUT(data, 32, BE, num)
-/**
- * GST_WRITE_UINT32_LE:
- * @data: memory location
- * @num: value to store
- *
- * Store a 32 bit unsigned integer value in little endian format into the memory buffer.
- */
-#define GST_WRITE_UINT32_LE(data, num)  _GST_PUT(data, 32, LE, num)
-/**
- * GST_WRITE_UINT16_BE:
- * @data: memory location
- * @num: value to store
- *
- * Store a 16 bit unsigned integer value in big endian format into the memory buffer.
- */
-#define GST_WRITE_UINT16_BE(data, num)  _GST_PUT(data, 16, BE, num)
-/**
- * GST_WRITE_UINT16_LE:
- * @data: memory location
- * @num: value to store
- *
- * Store a 16 bit unsigned integer value in little endian format into the memory buffer.
- */
-#define GST_WRITE_UINT16_LE(data, num)  _GST_PUT(data, 16, LE, num)
-/**
- * GST_WRITE_UINT8:
- * @data: memory location
- * @num: value to store
- *
- * Store an 8 bit unsigned integer value into the memory buffer.
- */
-#define GST_WRITE_UINT8(data, num)	((* (guint8 *) (data)) = (num))
-
-#else /* GST_HAVE_UNALIGNED_ACCESS */
-
-#define _GST_GET(__data, __idx, __size, __shift) \
-    (((guint##__size) (((guint8 *) (__data))[__idx])) << __shift)
-
 #define GST_READ_UINT64_BE(data)	(_GST_GET (data, 0, 64, 56) | \
 					 _GST_GET (data, 1, 64, 48) | \
 					 _GST_GET (data, 2, 64, 40) | \
@@ -419,6 +328,12 @@
 					 _GST_GET (data, 6, 64,  8) | \
 					 _GST_GET (data, 7, 64,  0))
 
+/**
+ * GST_READ_UINT64_LE:
+ * @data: memory location
+ *
+ * Read a 64 bit unsigned integer value in little endian format from the memory buffer.
+ */
 #define GST_READ_UINT64_LE(data)	(_GST_GET (data, 7, 64, 56) | \
 					 _GST_GET (data, 6, 64, 48) | \
 					 _GST_GET (data, 5, 64, 40) | \
@@ -428,27 +343,85 @@
 					 _GST_GET (data, 1, 64,  8) | \
 					 _GST_GET (data, 0, 64,  0))
 
+/**
+ * GST_READ_UINT32_BE:
+ * @data: memory location
+ *
+ * Read a 32 bit unsigned integer value in big endian format from the memory buffer.
+ */
 #define GST_READ_UINT32_BE(data)	(_GST_GET (data, 0, 32, 24) | \
 					 _GST_GET (data, 1, 32, 16) | \
 					 _GST_GET (data, 2, 32,  8) | \
 					 _GST_GET (data, 3, 32,  0))
 
+/**
+ * GST_READ_UINT32_LE:
+ * @data: memory location
+ *
+ * Read a 32 bit unsigned integer value in little endian format from the memory buffer.
+ */
 #define GST_READ_UINT32_LE(data)	(_GST_GET (data, 3, 32, 24) | \
 					 _GST_GET (data, 2, 32, 16) | \
 					 _GST_GET (data, 1, 32,  8) | \
 					 _GST_GET (data, 0, 32,  0))
 
+/**
+ * GST_READ_UINT24_BE:
+ * @data: memory location
+ *
+ * Read a 24 bit unsigned integer value in big endian format from the memory buffer.
+ *
+ * Since: 0.10.22
+ */
+#define GST_READ_UINT24_BE(data)	(_GST_GET (data, 0, 32, 16) | \
+					 _GST_GET (data, 1, 32,  8) | \
+					 _GST_GET (data, 2, 32,  0))
+
+/**
+ * GST_READ_UINT24_LE:
+ * @data: memory location
+ *
+ * Read a 24 bit unsigned integer value in little endian format from the memory buffer.
+ *
+ * Since: 0.10.22
+ */
+#define GST_READ_UINT24_LE(data)	(_GST_GET (data, 2, 32, 16) | \
+					 _GST_GET (data, 1, 32,  8) | \
+					 _GST_GET (data, 0, 32,  0))
+
+/**
+ * GST_READ_UINT16_BE:
+ * @data: memory location
+ *
+ * Read a 16 bit unsigned integer value in big endian format from the memory buffer.
+ */
 #define GST_READ_UINT16_BE(data)	(_GST_GET (data, 0, 16,  8) | \
 					 _GST_GET (data, 1, 16,  0))
 
+/**
+ * GST_READ_UINT16_LE:
+ * @data: memory location
+ *
+ * Read a 16 bit unsigned integer value in little endian format from the memory buffer.
+ */
 #define GST_READ_UINT16_LE(data)	(_GST_GET (data, 1, 16,  8) | \
 					 _GST_GET (data, 0, 16,  0))
 
+/**
+ * GST_READ_UINT8:
+ * @data: memory location
+ *
+ * Read an 8 bit unsigned integer value from the memory buffer.
+ */
 #define GST_READ_UINT8(data)		(_GST_GET (data, 0,  8,  0))
 
-#define _GST_PUT(__data, __idx, __size, __shift, __num) \
-    (((guint8 *) (__data))[__idx] = (((guint##__size) __num) >> __shift) & 0xff)
-
+/**
+ * GST_WRITE_UINT64_BE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 64 bit unsigned integer value in big endian format into the memory buffer.
+ */
 #define GST_WRITE_UINT64_BE(data, num)	do { \
 					  _GST_PUT (data, 0, 64, 56, num); \
 					  _GST_PUT (data, 1, 64, 48, num); \
@@ -460,6 +433,13 @@
 					  _GST_PUT (data, 7, 64,  0, num); \
 					} while (0)
 
+/**
+ * GST_WRITE_UINT64_LE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 64 bit unsigned integer value in little endian format into the memory buffer.
+ */
 #define GST_WRITE_UINT64_LE(data, num)	do { \
 					  _GST_PUT (data, 0, 64,  0, num); \
 					  _GST_PUT (data, 1, 64,  8, num); \
@@ -471,6 +451,13 @@
 					  _GST_PUT (data, 7, 64, 56, num); \
 					} while (0)
 
+/**
+ * GST_WRITE_UINT32_BE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 32 bit unsigned integer value in big endian format into the memory buffer.
+ */
 #define GST_WRITE_UINT32_BE(data, num)	do { \
 					  _GST_PUT (data, 0, 32, 24, num); \
 					  _GST_PUT (data, 1, 32, 16, num); \
@@ -478,6 +465,13 @@
 					  _GST_PUT (data, 3, 32,  0, num); \
 					} while (0)
 
+/**
+ * GST_WRITE_UINT32_LE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 32 bit unsigned integer value in little endian format into the memory buffer.
+ */
 #define GST_WRITE_UINT32_LE(data, num)	do { \
 					  _GST_PUT (data, 0, 32,  0, num); \
 					  _GST_PUT (data, 1, 32,  8, num); \
@@ -485,22 +479,457 @@
 					  _GST_PUT (data, 3, 32, 24, num); \
 					} while (0)
 
+/**
+ * GST_WRITE_UINT24_BE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 24 bit unsigned integer value in big endian format into the memory buffer.
+ *
+ * Since: 0.10.22
+ */
+#define GST_WRITE_UINT24_BE(data, num)	do { \
+					  _GST_PUT (data, 0, 32,  16, num); \
+					  _GST_PUT (data, 1, 32,  8, num); \
+					  _GST_PUT (data, 2, 32,  0, num); \
+					} while (0)
+
+/**
+ * GST_WRITE_UINT24_LE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 24 bit unsigned integer value in little endian format into the memory buffer.
+ *
+ * Since: 0.10.22
+ */
+#define GST_WRITE_UINT24_LE(data, num)	do { \
+					  _GST_PUT (data, 0, 32,  0, num); \
+					  _GST_PUT (data, 1, 32,  8, num); \
+					  _GST_PUT (data, 2, 32,  16, num); \
+					} while (0)
+
+/**
+ * GST_WRITE_UINT16_BE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 16 bit unsigned integer value in big endian format into the memory buffer.
+ */
 #define GST_WRITE_UINT16_BE(data, num)	do { \
 					  _GST_PUT (data, 0, 16,  8, num); \
 					  _GST_PUT (data, 1, 16,  0, num); \
 					} while (0)
 
+/**
+ * GST_WRITE_UINT16_LE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 16 bit unsigned integer value in little endian format into the memory buffer.
+ */
 #define GST_WRITE_UINT16_LE(data, num)	do { \
 					  _GST_PUT (data, 0, 16,  0, num); \
 					  _GST_PUT (data, 1, 16,  8, num); \
 					} while (0)
 
+/**
+ * GST_WRITE_UINT8:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store an 8 bit unsigned integer value into the memory buffer.
+ */
 #define GST_WRITE_UINT8(data, num)	do { \
 					  _GST_PUT (data, 0,  8,  0, num); \
 					} while (0)
 
-#endif /* GST_HAVE_UNALIGNED_ACCESS */
+/* Float endianess conversion macros */
+
+/* FIXME: Remove this once we depend on a GLib version with this */
+#ifndef GFLOAT_FROM_LE
+/**
+ * GFLOAT_SWAP_LE_BE:
+ * @in: input value
+ *
+ * Swap byte order of a 32-bit floating point value (float).
+ *
+ * Returns: @in byte-swapped.
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gfloat GFLOAT_SWAP_LE_BE (gfloat in);
+#endif
+
+inline static gfloat
+GFLOAT_SWAP_LE_BE(gfloat in)
+{
+  union
+  {
+    guint32 i;
+    gfloat f;
+  } u;
+
+  u.f = in;
+  u.i = GUINT32_SWAP_LE_BE (u.i);
+  return u.f;
+}
+
+/**
+ * GDOUBLE_SWAP_LE_BE:
+ * @in: input value
+ *
+ * Swap byte order of a 64-bit floating point value (double).
+ *
+ * Returns: @in byte-swapped.
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gdouble GDOUBLE_SWAP_LE_BE (gdouble in);
+#endif
+
+inline static gdouble
+GDOUBLE_SWAP_LE_BE(gdouble in)
+{
+  union
+  {
+    guint64 i;
+    gdouble d;
+  } u;
+
+  u.d = in;
+  u.i = GUINT64_SWAP_LE_BE (u.i);
+  return u.d;
+}
+
+/**
+ * GDOUBLE_TO_LE:
+ * @val: value
+ *
+ * Convert 64-bit floating point value (double) from native byte order into
+ * little endian byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+/**
+ * GDOUBLE_TO_BE:
+ * @val: value
+ *
+ * Convert 64-bit floating point value (double) from native byte order into
+ * big endian byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+/**
+ * GDOUBLE_FROM_LE:
+ * @val: value
+ *
+ * Convert 64-bit floating point value (double) from little endian byte order
+ * into native byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+/**
+ * GDOUBLE_FROM_BE:
+ * @val: value
+ *
+ * Convert 64-bit floating point value (double) from big endian byte order
+ * into native byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+
+/**
+ * GFLOAT_TO_LE:
+ * @val: value
+ *
+ * Convert 32-bit floating point value (float) from native byte order into
+ * little endian byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+/**
+ * GFLOAT_TO_BE:
+ * @val: value
+ *
+ * Convert 32-bit floating point value (float) from native byte order into
+ * big endian byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+/**
+ * GFLOAT_FROM_LE:
+ * @val: value
+ *
+ * Convert 32-bit floating point value (float) from little endian byte order
+ * into native byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+/**
+ * GFLOAT_FROM_BE:
+ * @val: value
+ *
+ * Convert 32-bit floating point value (float) from big endian byte order
+ * into native byte order.
+ *
+ * Since: 0.10.22
+ *
+ */
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define GFLOAT_TO_LE(val)    ((gfloat) (val))
+#define GFLOAT_TO_BE(val)    (GFLOAT_SWAP_LE_BE (val))
+#define GDOUBLE_TO_LE(val)   ((gdouble) (val))
+#define GDOUBLE_TO_BE(val)   (GDOUBLE_SWAP_LE_BE (val))
+
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+#define GFLOAT_TO_LE(val)    (GFLOAT_SWAP_LE_BE (val))
+#define GFLOAT_TO_BE(val)    ((gfloat) (val))
+#define GDOUBLE_TO_LE(val)   (GDOUBLE_SWAP_LE_BE (val))
+#define GDOUBLE_TO_BE(val)   ((gdouble) (val))
+
+#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+#error unknown ENDIAN type
+#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+
+#define GFLOAT_FROM_LE(val)  (GFLOAT_TO_LE (val))
+#define GFLOAT_FROM_BE(val)  (GFLOAT_TO_BE (val))
+#define GDOUBLE_FROM_LE(val) (GDOUBLE_TO_LE (val))
+#define GDOUBLE_FROM_BE(val) (GDOUBLE_TO_BE (val))
+
+#endif /* !defined(GFLOAT_FROM_LE) */
+
+/**
+ * GST_READ_FLOAT_LE:
+ * @data: memory location
+ *
+ * Read a 32 bit float value in little endian format from the memory buffer.
+ *
+ * Returns: The floating point value read from @data
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gfloat GST_READ_FLOAT_LE (const guint8 *data);
+#endif
+
+inline static gfloat
+GST_READ_FLOAT_LE(const guint8 *data)
+{
+  union
+  {
+    guint32 i;
+    gfloat f;
+  } u;
 
+  u.i = GST_READ_UINT32_LE (data);
+  return u.f;
+}
+
+/**
+ * GST_READ_FLOAT_BE:
+ * @data: memory location
+ *
+ * Read a 32 bit float value in big endian format from the memory buffer.
+ *
+ * Returns: The floating point value read from @data
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gfloat GST_READ_FLOAT_BE (const guint8 *data);
+#endif
+
+inline static gfloat
+GST_READ_FLOAT_BE(const guint8 *data)
+{
+  union
+  {
+    guint32 i;
+    gfloat f;
+  } u;
+
+  u.i = GST_READ_UINT32_BE (data);
+  return u.f;
+}
+
+/**
+ * GST_READ_DOUBLE_LE:
+ * @data: memory location
+ *
+ * Read a 64 bit double value in little endian format from the memory buffer.
+ *
+ * Returns: The double-precision floating point value read from @data
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gdouble GST_READ_DOUBLE_LE (const guint8 *data);
+#endif
+
+inline static gdouble
+GST_READ_DOUBLE_LE(const guint8 *data)
+{
+  union
+  {
+    guint64 i;
+    gdouble d;
+  } u;
+
+  u.i = GST_READ_UINT64_LE (data);
+  return u.d;
+}
+
+/**
+ * GST_READ_DOUBLE_BE:
+ * @data: memory location
+ *
+ * Read a 64 bit double value in big endian format from the memory buffer.
+ *
+ * Returns: The double-precision floating point value read from @data
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gdouble GST_READ_DOUBLE_BE (const guint8 *data);
+#endif
+
+inline static gdouble
+GST_READ_DOUBLE_BE(const guint8 *data)
+{
+  union
+  {
+    guint64 i;
+    gdouble d;
+  } u;
+
+  u.i = GST_READ_UINT64_BE (data);
+  return u.d;
+}
+
+/**
+ * GST_WRITE_FLOAT_LE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 32 bit float value in little endian format into the memory buffer.
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void GST_WRITE_FLOAT_LE (guint8 *data, gfloat num);
+#endif
+
+inline static void
+GST_WRITE_FLOAT_LE(guint8 *data, gfloat num)
+{
+  union
+  {
+    guint32 i;
+    gfloat f;
+  } u;
+
+  u.f = num;
+  GST_WRITE_UINT32_LE (data, u.i);
+}
+
+/**
+ * GST_WRITE_FLOAT_BE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 32 bit float value in big endian format into the memory buffer.
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void GST_WRITE_FLOAT_BE (guint8 *data, gfloat num);
+#endif
+
+inline static void
+GST_WRITE_FLOAT_BE(guint8 *data, gfloat num)
+{
+  union
+  {
+    guint32 i;
+    gfloat f;
+  } u;
+
+  u.f = num;
+  GST_WRITE_UINT32_BE (data, u.i);
+}
+
+/**
+ * GST_WRITE_DOUBLE_LE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 64 bit double value in little endian format into the memory buffer.
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void GST_WRITE_DOUBLE_LE (guint8 *data, gdouble num);
+#endif
+
+inline static void
+GST_WRITE_DOUBLE_LE(guint8 *data, gdouble num)
+{
+  union
+  {
+    guint64 i;
+    gdouble d;
+  } u;
+
+  u.d = num;
+  GST_WRITE_UINT64_LE (data, u.i);
+}
+
+/**
+ * GST_WRITE_DOUBLE_BE:
+ * @data: memory location
+ * @num: value to store
+ *
+ * Store a 64 bit double value in big endian format into the memory buffer.
+ *
+ * Since: 0.10.22
+ *
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void GST_WRITE_DOUBLE_BE (guint8 *data, gdouble num);
+#endif
+
+inline static void
+GST_WRITE_DOUBLE_BE(guint8 *data, gdouble num)
+{
+  union
+  {
+    guint64 i;
+    gdouble d;
+  } u;
+
+  u.d = num;
+  GST_WRITE_UINT64_BE (data, u.i);
+}
 
 /* Miscellaneous utility macros */
 
@@ -690,10 +1119,10 @@
 #endif
 
 
-gboolean        gst_element_seek_simple (GstElement   *element,
-                                         GstFormat     format,
-                                         GstSeekFlags  seek_flags,
-                                         gint64        seek_pos);
+gboolean                gst_element_seek_simple         (GstElement   *element,
+                                                         GstFormat     format,
+                                                         GstSeekFlags  seek_flags,
+                                                         gint64        seek_pos);
 
 /* util elementfactory functions */
 #ifdef __SYMBIAN32__
@@ -740,12 +1169,6 @@
 IMPORT_C
 #endif
 
-gboolean                gst_pad_can_link                (GstPad *srcpad, GstPad *sinkpad);
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-
-
 void			gst_pad_use_fixed_caps		(GstPad *pad);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -823,7 +1246,10 @@
 IMPORT_C
 #endif
 
+GstPad *                gst_bin_find_unlinked_pad       (GstBin *bin, GstPadDirection direction);
+#ifndef GST_DISABLE_DEPRECATED
 GstPad *                gst_bin_find_unconnected_pad    (GstBin *bin, GstPadDirection direction);
+#endif
 
 /* buffer functions */
 #ifdef __SYMBIAN32__
@@ -841,48 +1267,78 @@
 #endif /* GST_DISABLE_DEPRECATED */
 
 /* atomic functions */
-#ifdef __SYMBIAN32__
-IMPORT_C
+#ifndef GST_DISABLE_DEPRECATED
+void                    gst_atomic_int_set              (gint * atomic_int, gint value);
 #endif
 
-void                    gst_atomic_int_set              (gint * atomic_int, gint value);
-
 /* probes */
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gulong			gst_pad_add_data_probe		(GstPad * pad,
-							 GCallback handler,
-							 gpointer data);
+gulong			gst_pad_add_data_probe		(GstPad   * pad,
+							 GCallback  handler,
+							 gpointer   data);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+
+gulong			gst_pad_add_data_probe_full	(GstPad       * pad,
+							 GCallback      handler,
+							 gpointer       data,
+							 GDestroyNotify notify);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 void			gst_pad_remove_data_probe	(GstPad * pad, guint handler_id);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gulong			gst_pad_add_event_probe		(GstPad * pad,
-							 GCallback handler,
-							 gpointer data);
+
+gulong			gst_pad_add_event_probe		(GstPad   * pad,
+							 GCallback  handler,
+							 gpointer   data);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+
+gulong			gst_pad_add_event_probe_full	(GstPad       * pad,
+							 GCallback      handler,
+							 gpointer       data,
+							 GDestroyNotify notify);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 void			gst_pad_remove_event_probe	(GstPad * pad, guint handler_id);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-gulong			gst_pad_add_buffer_probe	(GstPad * pad,
-							 GCallback handler,
-							 gpointer data);
+
+gulong			gst_pad_add_buffer_probe	(GstPad   * pad,
+							 GCallback  handler,
+							 gpointer   data);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+
+gulong			gst_pad_add_buffer_probe_full	(GstPad       * pad,
+							 GCallback      handler,
+							 gpointer       data,
+							 GDestroyNotify notify);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
 void			gst_pad_remove_buffer_probe	(GstPad * pad, guint handler_id);
 
 /* tag emission utility functions */
@@ -905,15 +1361,50 @@
 IMPORT_C
 #endif
 
-GstElement *            gst_parse_bin_from_description  (const gchar * bin_description,
-                                                         gboolean ghost_unconnected_pads,
-                                                         GError ** err);
+GstElement *            gst_parse_bin_from_description      (const gchar     * bin_description,
+                                                             gboolean          ghost_unlinked_pads,
+                                                             GError         ** err);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstElement *            gst_parse_bin_from_description_full (const gchar     * bin_description,
+                                                             gboolean          ghost_unlinked_pads,
+                                                             GstParseContext * context,
+                                                             GstParseFlags     flags,
+                                                             GError         ** err);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
 
-GstClockTime gst_util_get_timestamp (void);
+GstClockTime            gst_util_get_timestamp          (void);
+
+/**
+ * GstSearchMode:
+ * @GST_SEARCH_MODE_EXACT : Only search for exact matches.
+ * @GST_SEARCH_MODE_BEFORE: Search for an exact match or the element just before.
+ * @GST_SEARCH_MODE_AFTER : Search for an exact match or the element just after.
+ *
+ * The different search modes.
+ *
+ * Since: 0.10.23
+ */
+typedef enum {
+  GST_SEARCH_MODE_EXACT = 0,
+  GST_SEARCH_MODE_BEFORE,
+  GST_SEARCH_MODE_AFTER
+} GstSearchMode;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gpointer                gst_util_array_binary_search      (gpointer array, guint num_elements,
+                                                           gsize element_size, GCompareDataFunc search_func,
+							   GstSearchMode mode, gconstpointer search_data,
+							   gpointer user_data);
 
 G_END_DECLS
 
--- a/gstreamer_core/gst/gstvalue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstvalue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -19,15 +19,15 @@
 
 /**
  * SECTION:gstvalue
- * @short_description: GValue and GParamSpec implementations specific
+ * @short_description: GValue implementations specific
  * to GStreamer
  *
- * GValue and GParamSpec implementations specific to GStreamer.
+ * GValue implementations specific to GStreamer.
  *
  * Note that operations on the same GstValue (or GValue) from multiple
  * threads may lead to undefined behaviour. 
  *
- * Last reviewed on 2006-03-07 (0.10.4)
+ * Last reviewed on 2008-03-11 (0.10.18)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -71,7 +71,14 @@
   GstValueSubtractFunc func;
 };
 
+#define FUNDAMENTAL_TYPE_ID_MAX \
+    (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
+#define FUNDAMENTAL_TYPE_ID(type) \
+    ((type) >> G_TYPE_FUNDAMENTAL_SHIFT)
+
 static GArray *gst_value_table;
+static GHashTable *gst_value_hash;
+static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1];
 static GArray *gst_value_union_funcs;
 static GArray *gst_value_intersect_funcs;
 static GArray *gst_value_subtract_funcs;
@@ -84,6 +91,28 @@
 static gint gst_value_compare_with_func (const GValue * value1,
     const GValue * value2, GstValueCompareFunc compare);
 
+static gchar *gst_string_wrap (const gchar * s);
+static gchar *gst_string_take_and_wrap (gchar * s);
+static gchar *gst_string_unwrap (const gchar * s);
+
+static inline GstValueTable *
+gst_value_hash_lookup_type (GType type)
+{
+  if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type)))
+    return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)];
+  else
+    return g_hash_table_lookup (gst_value_hash, (gpointer) type);
+}
+
+static void
+gst_value_hash_add_type (GType type, const GstValueTable * table)
+{
+  if (G_TYPE_IS_FUNDAMENTAL (type))
+    gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table;
+
+  g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table);
+}
+
 /********
  * list *
  ********/
@@ -100,16 +129,17 @@
   GString *s;
   GValue *v;
   gchar *s_val;
+  guint alen = array->len;
 
   /* estimate minimum string length to minimise re-allocs in GString */
-  s = g_string_sized_new (2 + (6 * array->len) + 2);
+  s = g_string_sized_new (2 + (6 * alen) + 2);
   g_string_append (s, begin);
-  for (i = 0; i < array->len; i++) {
+  for (i = 0; i < alen; i++) {
     v = &g_array_index (array, GValue, i);
     s_val = gst_value_serialize (v);
     g_string_append (s, s_val);
     g_free (s_val);
-    if (i < array->len - 1) {
+    if (i < alen - 1) {
       g_string_append_len (s, ", ", 2);
     }
   }
@@ -126,13 +156,15 @@
   GString *s;
   guint i;
   gchar *list_s;
+  guint alen;
 
   array = src_value->data[0].v_pointer;
+  alen = array->len;
 
   /* estimate minimum string length to minimise re-allocs in GString */
-  s = g_string_sized_new (2 + (10 * array->len) + 2);
+  s = g_string_sized_new (2 + (10 * alen) + 2);
   g_string_append (s, begin);
-  for (i = 0; i < array->len; i++) {
+  for (i = 0; i < alen; i++) {
     list_value = &g_array_index (array, GValue, i);
 
     if (i != 0) {
@@ -152,20 +184,25 @@
  * there. Do not export, since it doesn't work for types where the content
  * decides the fixedness (e.g. GST_TYPE_ARRAY).
  */
-
 static gboolean
 gst_type_is_fixed (GType type)
 {
+  /* the basic int, string, double types */
+  if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
+    return TRUE;
+  }
+  /* our fundamental types that are certainly not fixed */
   if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
-      type == GST_TYPE_LIST) {
+      type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE) {
     return FALSE;
   }
-  if (G_TYPE_FUNDAMENTAL (type) <=
-      G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
+  /* other (boxed) types that are fixed */
+  if (type == GST_TYPE_BUFFER) {
     return TRUE;
   }
-  if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC
-      || type == GST_TYPE_ARRAY || type == GST_TYPE_FRACTION) {
+  /* heavy checks */
+  if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <=
+      G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
     return TRUE;
   }
 
@@ -183,11 +220,12 @@
 copy_garray_of_gstvalue (const GArray * src)
 {
   GArray *dest;
-  guint i;
-
-  dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
-  g_array_set_size (dest, src->len);
-  for (i = 0; i < src->len; i++) {
+  guint i, len;
+
+  len = src->len;
+  dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
+  g_array_set_size (dest, len);
+  for (i = 0; i < len; i++) {
     gst_value_init_and_copy (&g_array_index (dest, GValue, i),
         &g_array_index (src, GValue, i));
   }
@@ -205,11 +243,12 @@
 static void
 gst_value_free_list_or_array (GValue * value)
 {
-  guint i;
+  guint i, len;
   GArray *src = (GArray *) value->data[0].v_pointer;
+  len = src->len;
 
   if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
-    for (i = 0; i < src->len; i++) {
+    for (i = 0; i < len; i++) {
       g_value_unset (&g_array_index (src, GValue, i));
     }
     g_array_free (src, TRUE);
@@ -560,13 +599,14 @@
   guint i;
   GArray *array1 = value1->data[0].v_pointer;
   GArray *array2 = value2->data[0].v_pointer;
+  guint len = array1->len;
   GValue *v1;
   GValue *v2;
 
-  if (array1->len != array2->len)
+  if (len != array2->len)
     return GST_VALUE_UNORDERED;
 
-  for (i = 0; i < array1->len; i++) {
+  for (i = 0; i < len; i++) {
     v1 = &g_array_index (array1, GValue, i);
     v2 = &g_array_index (array2, GValue, i);
     if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
@@ -958,7 +998,7 @@
  *
  * Gets the minimum of the range specified by @value.
  *
- * Returns: the minumum of the range
+ * Returns: the minimum of the range
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1040,10 +1080,13 @@
 gst_value_init_fraction_range (GValue * value)
 {
   GValue *vals;
-
-  value->data[0].v_pointer = vals = g_new0 (GValue, 2);
-  g_value_init (&vals[0], GST_TYPE_FRACTION);
-  g_value_init (&vals[1], GST_TYPE_FRACTION);
+  GType ftype;
+
+  ftype = GST_TYPE_FRACTION;
+
+  value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue));
+  g_value_init (&vals[0], ftype);
+  g_value_init (&vals[1], ftype);
 }
 
 static void
@@ -1054,7 +1097,7 @@
   if (vals != NULL) {
     g_value_unset (&vals[0]);
     g_value_unset (&vals[1]);
-    g_free (vals);
+    g_slice_free1 (2 * sizeof (GValue), vals);
     value->data[0].v_pointer = NULL;
   }
 }
@@ -1066,12 +1109,9 @@
   GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
 
   if (vals == NULL) {
-    dest_value->data[0].v_pointer = vals = g_new0 (GValue, 2);
-    g_return_if_fail (vals != NULL);
-    g_value_init (&vals[0], GST_TYPE_FRACTION);
-    g_value_init (&vals[1], GST_TYPE_FRACTION);
+    gst_value_init_fraction_range (dest_value);
+    vals = dest_value->data[0].v_pointer;
   }
-
   if (src_vals != NULL) {
     g_value_copy (&src_vals[0], &vals[0]);
     g_value_copy (&src_vals[1], &vals[1]);
@@ -1088,12 +1128,8 @@
     return g_strdup_printf ("not enough value locations for `%s' passed",
         G_VALUE_TYPE_NAME (value));
   if (vals == NULL) {
-    value->data[0].v_pointer = vals = g_new0 (GValue, 2);
-    if (vals == NULL)
-      return g_strdup_printf ("Could not initialise`%s' during collect",
-          G_VALUE_TYPE_NAME (value));
-    g_value_init (&vals[0], GST_TYPE_FRACTION);
-    g_value_init (&vals[1], GST_TYPE_FRACTION);
+    gst_value_init_fraction_range (value);
+    vals = value->data[0].v_pointer;
   }
 
   gst_value_set_fraction (&vals[0], collect_values[0].v_int,
@@ -1112,26 +1148,26 @@
   int *dest_values[4];
   GValue *vals = (GValue *) value->data[0].v_pointer;
 
-  if (n_collect_values != 4)
+  if (G_UNLIKELY (n_collect_values != 4))
     return g_strdup_printf ("not enough value locations for `%s' passed",
         G_VALUE_TYPE_NAME (value));
 
   for (i = 0; i < 4; i++) {
-    if (collect_values[i].v_pointer == NULL) {
+    if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
       return g_strdup_printf ("value location for `%s' passed as NULL",
           G_VALUE_TYPE_NAME (value));
     }
     dest_values[i] = collect_values[i].v_pointer;
   }
 
-  if (vals == NULL) {
+  if (G_UNLIKELY (vals == NULL)) {
     return g_strdup_printf ("Uninitialised `%s' passed",
         G_VALUE_TYPE_NAME (value));
   }
 
   dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
   dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
-  dest_values[2][0] = gst_value_get_fraction_denominator (&vals[1]);
+  dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]);
   dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
   return NULL;
 }
@@ -1158,11 +1194,9 @@
 
   vals = (GValue *) value->data[0].v_pointer;
   if (vals == NULL) {
-    value->data[0].v_pointer = vals = g_new0 (GValue, 2);
-    g_value_init (&vals[0], GST_TYPE_FRACTION);
-    g_value_init (&vals[1], GST_TYPE_FRACTION);
+    gst_value_init_fraction_range (value);
+    vals = value->data[0].v_pointer;
   }
-
   g_value_copy (start, &vals[0]);
   g_value_copy (end, &vals[1]);
 }
@@ -1207,7 +1241,7 @@
  *
  * Gets the minimum of the range specified by @value.
  *
- * Returns: the minumum of the range
+ * Returns: the minimum of the range
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1376,7 +1410,7 @@
   caps = gst_caps_from_string (s);
 
   if (caps) {
-    g_value_set_boxed (dest, caps);
+    g_value_take_boxed (dest, caps);
     return TRUE;
   }
   return FALSE;
@@ -1434,7 +1468,7 @@
 {
   GstStructure *structure = g_value_get_boxed (value);
 
-  return gst_structure_to_string (structure);
+  return gst_string_take_and_wrap (gst_structure_to_string (structure));
 }
 
 static gboolean
@@ -1442,10 +1476,20 @@
 {
   GstStructure *structure;
 
-  structure = gst_structure_from_string (s, NULL);
-
-  if (structure) {
-    g_value_set_boxed (dest, structure);
+  if (*s != '"') {
+    structure = gst_structure_from_string (s, NULL);
+  } else {
+    gchar *str = gst_string_unwrap (s);
+
+    if (G_UNLIKELY (!str))
+      return FALSE;
+
+    structure = gst_structure_from_string (str, NULL);
+    g_free (str);
+  }
+
+  if (G_LIKELY (structure)) {
+    g_value_take_boxed (dest, structure);
     return TRUE;
   }
   return FALSE;
@@ -1863,71 +1907,110 @@
 static gint
 gst_value_compare_string (const GValue * value1, const GValue * value2)
 {
-  int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
-
-  if (x < 0)
-    return GST_VALUE_LESS_THAN;
-  if (x > 0)
-    return GST_VALUE_GREATER_THAN;
+  if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
+    /* if only one is NULL, no match - otherwise both NULL == EQUAL */
+    if (value1->data[0].v_pointer != value2->data[0].v_pointer)
+      return GST_VALUE_UNORDERED;
+  } else {
+    int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
+
+    if (x < 0)
+      return GST_VALUE_LESS_THAN;
+    if (x > 0)
+      return GST_VALUE_GREATER_THAN;
+  }
+
   return GST_VALUE_EQUAL;
 }
 
-/* keep in sync with gststructure.c */
-#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
-    ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
-    ((c) == '.'))
-
-static gchar *
-gst_string_wrap (const gchar * s)
+static int
+gst_string_measure_wrapping (const gchar * s)
 {
-  const gchar *t;
   int len;
-  gchar *d, *e;
   gboolean wrap = FALSE;
 
+  if (G_UNLIKELY (s == NULL))
+    return -1;
+
+  /* Special case: the actual string NULL needs wrapping */
+  if (G_UNLIKELY (strcmp (s, "NULL") == 0))
+    return 4;
+
   len = 0;
-  t = s;
-  if (!s)
-    return NULL;
-  while (*t) {
-    if (GST_ASCII_IS_STRING (*t)) {
+  while (*s) {
+    if (GST_ASCII_IS_STRING (*s)) {
       len++;
-    } else if (*t < 0x20 || *t >= 0x7f) {
+    } else if (*s < 0x20 || *s >= 0x7f) {
       wrap = TRUE;
       len += 4;
     } else {
       wrap = TRUE;
       len += 2;
     }
-    t++;
+    s++;
   }
 
-  if (!wrap)
-    return g_strdup (s);
+  /* Wrap the string if we found something that needs
+   * wrapping, or the empty string (len == 0) */
+  return (wrap || len == 0) ? len : -1;
+}
+
+static gchar *
+gst_string_wrap_inner (const gchar * s, int len)
+{
+  gchar *d, *e;
 
   e = d = g_malloc (len + 3);
 
   *e++ = '\"';
-  t = s;
-  while (*t) {
-    if (GST_ASCII_IS_STRING (*t)) {
-      *e++ = *t++;
-    } else if (*t < 0x20 || *t >= 0x7f) {
+  while (*s) {
+    if (GST_ASCII_IS_STRING (*s)) {
+      *e++ = *s++;
+    } else if (*s < 0x20 || *s >= 0x7f) {
       *e++ = '\\';
-      *e++ = '0' + ((*(guchar *) t) >> 6);
-      *e++ = '0' + (((*t) >> 3) & 0x7);
-      *e++ = '0' + ((*t++) & 0x7);
+      *e++ = '0' + ((*(guchar *) s) >> 6);
+      *e++ = '0' + (((*s) >> 3) & 0x7);
+      *e++ = '0' + ((*s++) & 0x7);
     } else {
       *e++ = '\\';
-      *e++ = *t++;
+      *e++ = *s++;
     }
   }
   *e++ = '\"';
   *e = 0;
 
+  g_assert (e - d <= len + 3);
   return d;
 }
 
+/* Do string wrapping/escaping */
+static gchar *
+gst_string_wrap (const gchar * s)
+{
+  int len = gst_string_measure_wrapping (s);
+
+  if (G_LIKELY (len < 0))
+    return g_strdup (s);
+
+  return gst_string_wrap_inner (s, len);
+}
+
+/* Same as above, but take ownership of the string */
+static gchar *
+gst_string_take_and_wrap (gchar * s)
+{
+  gchar *out;
+  int len = gst_string_measure_wrapping (s);
+
+  if (G_LIKELY (len < 0))
+    return s;
+
+  out = gst_string_wrap_inner (s, len);
+  g_free (s);
+
+  return out;
+}
+
 /*
  * This function takes a string delimited with double quotes (")
  * and unescapes any \xxx octal numbers.
@@ -2005,7 +2088,7 @@
     goto beach;
 
   /* null terminate result string and return */
-  *write++ = '\0';
+  *write = '\0';
   return ret;
 
 beach:
@@ -2022,15 +2105,17 @@
 static gboolean
 gst_value_deserialize_string (GValue * dest, const gchar * s)
 {
-  if (*s != '"') {
+  if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
+    g_value_set_string (dest, NULL);
+    return TRUE;
+  } else if (G_LIKELY (*s != '"')) {
     if (!g_utf8_validate (s, -1, NULL))
       return FALSE;
     g_value_set_string (dest, s);
     return TRUE;
   } else {
     gchar *str = gst_string_unwrap (s);
-
-    if (!str)
+    if (G_UNLIKELY (!str))
       return FALSE;
     g_value_take_string (dest, str);
   }
@@ -2450,8 +2535,8 @@
 }
 
 static gboolean
-    gst_value_intersect_fraction_range_fraction_range
-    (GValue * dest, const GValue * src1, const GValue * src2)
+gst_value_intersect_fraction_range_fraction_range (GValue * dest,
+    const GValue * src1, const GValue * src2)
 {
   GValue *min;
   GValue *max;
@@ -2693,6 +2778,9 @@
   guint i, size;
   GValue subtraction = { 0, };
   gboolean ret = FALSE;
+  GType ltype;
+
+  ltype = gst_value_list_get_type ();
 
   size = gst_value_list_get_size (minuend);
   for (i = 0; i < size; i++) {
@@ -2702,15 +2790,8 @@
       if (!ret) {
         gst_value_init_and_copy (dest, &subtraction);
         ret = TRUE;
-      } else if (GST_VALUE_HOLDS_LIST (dest)
-          && GST_VALUE_HOLDS_LIST (&subtraction)) {
-        /* unroll */
-        GValue unroll = { 0, };
-
-        gst_value_init_and_copy (&unroll, dest);
-        g_value_unset (dest);
-        gst_value_list_concat (dest, &unroll, &subtraction);
-      } else if (GST_VALUE_HOLDS_LIST (dest)) {
+      } else if (G_VALUE_HOLDS (dest, ltype)
+          && !G_VALUE_HOLDS (&subtraction, ltype)) {
         gst_value_list_append_value (dest, &subtraction);
       } else {
         GValue temp = { 0, };
@@ -2857,6 +2938,46 @@
  * comparison *
  **************/
 
+/*
+ * gst_value_get_compare_func:
+ * @value1: a value to get the compare function for
+ *
+ * Determines the compare function to be used with values of the same type as
+ * @value1. The function can be given to gst_value_compare_with_func().
+ *
+ * Returns: A #GstValueCompareFunc value
+ */
+static GstValueCompareFunc
+gst_value_get_compare_func (const GValue * value1)
+{
+  GstValueTable *table, *best = NULL;
+  guint i;
+  GType type1;
+
+  type1 = G_VALUE_TYPE (value1);
+
+  /* this is a fast check */
+  best = gst_value_hash_lookup_type (type1);
+
+  /* slower checks */
+  if (G_UNLIKELY (!best || !best->compare)) {
+    guint len = gst_value_table->len;
+
+    best = NULL;
+    for (i = 0; i < len; i++) {
+      table = &g_array_index (gst_value_table, GstValueTable, i);
+      if (table->compare && g_type_is_a (type1, table->type)) {
+        if (!best || g_type_is_a (table->type, best->type))
+          best = table;
+      }
+    }
+  }
+  if (G_LIKELY (best))
+    return best->compare;
+
+  return NULL;
+}
+
 /**
  * gst_value_can_compare:
  * @value1: a value to compare
@@ -2873,51 +2994,10 @@
 gboolean
 gst_value_can_compare (const GValue * value1, const GValue * value2)
 {
-  GstValueTable *table;
-  guint i;
-
   if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
     return FALSE;
 
-  for (i = 0; i < gst_value_table->len; i++) {
-    table = &g_array_index (gst_value_table, GstValueTable, i);
-    if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare)
-      return TRUE;
-  }
-
-  return FALSE;
-}
-
-/*
- * gst_value_get_compare_func:
- * @value1: a value to get the compare function for
- *
- * Determines the compare function to be used with values of the same type as
- * @value1. The function can be given to gst_value_compare_with_func().
- *
- * Returns: A #GstValueCompareFunc value
- */
-static GstValueCompareFunc
-gst_value_get_compare_func (const GValue * value1)
-{
-  GstValueTable *table, *best = NULL;
-  guint i;
-
-  for (i = 0; i < gst_value_table->len; i++) {
-    table = &g_array_index (gst_value_table, GstValueTable, i);
-    if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) {
-      best = table;
-      break;
-    }
-    if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) {
-      if (!best || g_type_is_a (table->type, best->type))
-        best = table;
-    }
-  }
-  if (best) {
-    return best->compare;
-  }
-  return NULL;
+  return gst_value_get_compare_func (value1) != NULL;
 }
 
 /**
@@ -2935,7 +3015,8 @@
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
-#endif 
+#endif
+
 gint
 gst_value_compare (const GValue * value1, const GValue * value2)
 {
@@ -3004,9 +3085,11 @@
 gst_value_can_union (const GValue * value1, const GValue * value2)
 {
   GstValueUnionInfo *union_info;
-  guint i;
-
-  for (i = 0; i < gst_value_union_funcs->len; i++) {
+  guint i, len;
+
+  len = gst_value_union_funcs->len;
+
+  for (i = 0; i < len; i++) {
     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
     if (union_info->type1 == G_VALUE_TYPE (value1) &&
         union_info->type2 == G_VALUE_TYPE (value2))
@@ -3038,9 +3121,11 @@
 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
 {
   GstValueUnionInfo *union_info;
-  guint i;
-
-  for (i = 0; i < gst_value_union_funcs->len; i++) {
+  guint i, len;
+
+  len = gst_value_union_funcs->len;
+
+  for (i = 0; i < len; i++) {
     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
     if (union_info->type1 == G_VALUE_TYPE (value1) &&
         union_info->type2 == G_VALUE_TYPE (value2)) {
@@ -3111,20 +3196,31 @@
 gst_value_can_intersect (const GValue * value1, const GValue * value2)
 {
   GstValueIntersectInfo *intersect_info;
-  guint i;
+  guint i, len;
+  GType ltype, type1, type2;
+
+  ltype = gst_value_list_get_type ();
 
   /* special cases */
-  if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
+  if (G_VALUE_HOLDS (value1, ltype) || G_VALUE_HOLDS (value2, ltype))
     return TRUE;
 
-  for (i = 0; i < gst_value_intersect_funcs->len; i++) {
+  type1 = G_VALUE_TYPE (value1);
+  type2 = G_VALUE_TYPE (value2);
+
+  /* practically all GstValue types have a compare function (_can_compare=TRUE)
+   * GstStructure and GstCaps have npot, but are intersectable */
+  if (type1 == type2)
+    return TRUE;
+
+  /* check registered intersect functions */
+  len = gst_value_intersect_funcs->len;
+  for (i = 0; i < len; i++) {
     intersect_info = &g_array_index (gst_value_intersect_funcs,
         GstValueIntersectInfo, i);
-    if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
-        intersect_info->type2 == G_VALUE_TYPE (value2))
-      if (intersect_info->type2 == G_VALUE_TYPE (value1) &&
-          intersect_info->type1 == G_VALUE_TYPE (value2))
-        return TRUE;
+    if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
+        (intersect_info->type1 == type2 && intersect_info->type2 == type1))
+      return TRUE;
   }
 
   return gst_value_can_compare (value1, value2);
@@ -3153,36 +3249,37 @@
     const GValue * value2)
 {
   GstValueIntersectInfo *intersect_info;
-  guint i;
-  gboolean ret = FALSE;
+  guint i, len;
+  GType ltype, type1, type2;
+
+  ltype = gst_value_list_get_type ();
 
   /* special cases first */
-  if (GST_VALUE_HOLDS_LIST (value1))
+  if (G_VALUE_HOLDS (value1, ltype))
     return gst_value_intersect_list (dest, value1, value2);
-  if (GST_VALUE_HOLDS_LIST (value2))
+  if (G_VALUE_HOLDS (value2, ltype))
     return gst_value_intersect_list (dest, value2, value1);
 
-  for (i = 0; i < gst_value_intersect_funcs->len; i++) {
-    intersect_info = &g_array_index (gst_value_intersect_funcs,
-        GstValueIntersectInfo, i);
-    if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
-        intersect_info->type2 == G_VALUE_TYPE (value2)) {
-      ret = intersect_info->func (dest, value1, value2);
-      return ret;
-    }
-    if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
-        intersect_info->type2 == G_VALUE_TYPE (value1)) {
-      ret = intersect_info->func (dest, value2, value1);
-      return ret;
-    }
-  }
-
   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
     gst_value_init_and_copy (dest, value1);
-    ret = TRUE;
+    return TRUE;
   }
 
-  return ret;
+  type1 = G_VALUE_TYPE (value1);
+  type2 = G_VALUE_TYPE (value2);
+
+  len = gst_value_intersect_funcs->len;
+  for (i = 0; i < len; i++) {
+    intersect_info = &g_array_index (gst_value_intersect_funcs,
+        GstValueIntersectInfo, i);
+    if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
+      return intersect_info->func (dest, value1, value2);
+    }
+    if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
+      return intersect_info->func (dest, value2, value1);
+    }
+  }
+  return FALSE;
 }
 
 /**
@@ -3239,18 +3336,24 @@
     const GValue * subtrahend)
 {
   GstValueSubtractInfo *info;
-  guint i;
+  guint i, len;
+  GType ltype, mtype, stype;
+
+  ltype = gst_value_list_get_type ();
 
   /* special cases first */
-  if (GST_VALUE_HOLDS_LIST (minuend))
+  if (G_VALUE_HOLDS (minuend, ltype))
     return gst_value_subtract_from_list (dest, minuend, subtrahend);
-  if (GST_VALUE_HOLDS_LIST (subtrahend))
+  if (G_VALUE_HOLDS (subtrahend, ltype))
     return gst_value_subtract_list (dest, minuend, subtrahend);
 
-  for (i = 0; i < gst_value_subtract_funcs->len; i++) {
+  mtype = G_VALUE_TYPE (minuend);
+  stype = G_VALUE_TYPE (subtrahend);
+
+  len = gst_value_subtract_funcs->len;
+  for (i = 0; i < len; i++) {
     info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
-    if (info->minuend == G_VALUE_TYPE (minuend) &&
-        info->subtrahend == G_VALUE_TYPE (subtrahend)) {
+    if (info->minuend == mtype && info->subtrahend == stype) {
       return info->func (dest, minuend, subtrahend);
     }
   }
@@ -3294,16 +3397,22 @@
 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
 {
   GstValueSubtractInfo *info;
-  guint i;
+  guint i, len;
+  GType ltype, mtype, stype;
+
+  ltype = gst_value_list_get_type ();
 
   /* special cases */
-  if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend))
+  if (G_VALUE_HOLDS (minuend, ltype) || G_VALUE_HOLDS (subtrahend, ltype))
     return TRUE;
 
-  for (i = 0; i < gst_value_subtract_funcs->len; i++) {
+  mtype = G_VALUE_TYPE (minuend);
+  stype = G_VALUE_TYPE (subtrahend);
+
+  len = gst_value_subtract_funcs->len;
+  for (i = 0; i < len; i++) {
     info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
-    if (info->minuend == G_VALUE_TYPE (minuend) &&
-        info->subtrahend == G_VALUE_TYPE (subtrahend))
+    if (info->minuend == mtype && info->subtrahend == stype)
       return TRUE;
   }
 
@@ -3349,7 +3458,7 @@
  * @table: structure containing functions to register
  *
  * Registers functions to perform calculations on #GValues of a given
- * type.
+ * type. Each type can only be added once.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -3358,7 +3467,17 @@
 void
 gst_value_register (const GstValueTable * table)
 {
+  GstValueTable *found;
+
   g_array_append_val (gst_value_table, *table);
+
+  found = gst_value_hash_lookup_type (table->type);
+  if (found)
+    g_warning ("adding type %s multiple times", g_type_name (table->type));
+
+  /* FIXME: we're not really doing the const justice, we assume the table is
+   * static */
+  gst_value_hash_add_type (table->type, table);
 }
 
 /**
@@ -3396,27 +3515,30 @@
 gchar *
 gst_value_serialize (const GValue * value)
 {
-  guint i;
+  guint i, len;
   GValue s_val = { 0 };
-  GstValueTable *table, *best = NULL;
+  GstValueTable *table, *best;
   char *s;
+  GType type;
 
   g_return_val_if_fail (G_IS_VALUE (value), NULL);
 
-  for (i = 0; i < gst_value_table->len; i++) {
-    table = &g_array_index (gst_value_table, GstValueTable, i);
-    if (table->serialize == NULL)
-      continue;
-    if (table->type == G_VALUE_TYPE (value)) {
-      best = table;
-      break;
-    }
-    if (g_type_is_a (G_VALUE_TYPE (value), table->type)) {
-      if (!best || g_type_is_a (table->type, best->type))
-        best = table;
+  type = G_VALUE_TYPE (value);
+
+  best = gst_value_hash_lookup_type (type);
+
+  if (G_UNLIKELY (!best || !best->serialize)) {
+    len = gst_value_table->len;
+    best = NULL;
+    for (i = 0; i < len; i++) {
+      table = &g_array_index (gst_value_table, GstValueTable, i);
+      if (table->serialize && g_type_is_a (type, table->type)) {
+        if (!best || g_type_is_a (table->type, best->type))
+          best = table;
+      }
     }
   }
-  if (best)
+  if (G_LIKELY (best))
     return best->serialize (value);
 
   g_value_init (&s_val, G_TYPE_STRING);
@@ -3447,30 +3569,29 @@
 gboolean
 gst_value_deserialize (GValue * dest, const gchar * src)
 {
-  GstValueTable *table, *best = NULL;
-  guint i;
+  GstValueTable *table, *best;
+  guint i, len;
+  GType type;
 
   g_return_val_if_fail (src != NULL, FALSE);
   g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
 
-  for (i = 0; i < gst_value_table->len; i++) {
-    table = &g_array_index (gst_value_table, GstValueTable, i);
-    if (table->serialize == NULL)
-      continue;
-
-    if (table->type == G_VALUE_TYPE (dest)) {
-      best = table;
-      break;
-    }
-
-    if (g_type_is_a (G_VALUE_TYPE (dest), table->type)) {
-      if (!best || g_type_is_a (table->type, best->type))
-        best = table;
+  type = G_VALUE_TYPE (dest);
+
+  best = gst_value_hash_lookup_type (type);
+  if (G_UNLIKELY (!best || !best->deserialize)) {
+    len = gst_value_table->len;
+    best = NULL;
+    for (i = 0; i < len; i++) {
+      table = &g_array_index (gst_value_table, GstValueTable, i);
+      if (table->deserialize && g_type_is_a (type, table->type)) {
+        if (!best || g_type_is_a (table->type, best->type))
+          best = table;
+      }
     }
   }
-  if (best) {
+  if (G_LIKELY (best))
     return best->deserialize (dest, src);
-  }
 
   return FALSE;
 }
@@ -3496,6 +3617,11 @@
 {
   GType type = G_VALUE_TYPE (value);
 
+  /* the most common types are just basic plain glib types */
+  if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
+    return TRUE;
+  }
+
   if (type == GST_TYPE_ARRAY) {
     gint size, n;
     const GValue *kid;
@@ -3509,7 +3635,6 @@
     }
     return TRUE;
   }
-
   return gst_type_is_fixed (type);
 }
 
@@ -4083,9 +4208,15 @@
   gchar *str;
 
   obj = g_value_get_object (src_value);
-  str = obj ? GST_OBJECT_NAME (obj) : "NULL";
-
-  dest_value->data[0].v_pointer = g_strdup (str);
+  if (obj) {
+    str =
+        g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
+        GST_OBJECT_NAME (obj));
+  } else {
+    str = g_strdup ("NULL");
+  }
+
+  dest_value->data[0].v_pointer = str;
 }
 
 static GTypeInfo _info = {
@@ -4242,6 +4373,7 @@
 _gst_value_initialize (void)
 {
   gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
+  gst_value_hash = g_hash_table_new (NULL, NULL);
   gst_value_union_funcs = g_array_new (FALSE, FALSE,
       sizeof (GstValueUnionInfo));
   gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
@@ -4317,7 +4449,7 @@
       gst_value_deserialize_array,
     };
 
-    gst_value.type = gst_value_array_get_type ();;
+    gst_value.type = gst_value_array_get_type ();
     gst_value_register (&gst_value);
   }
 
--- a/gstreamer_core/gst/gstvalue.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstvalue.h	Fri Apr 16 15:15:52 2010 +0300
@@ -41,7 +41,7 @@
  * </programlisting>
  * </informalexample>
  */
-#define GST_MAKE_FOURCC(a,b,c,d)        (guint32)((a)|(b)<<8|(c)<<16|(d)<<24)
+#define GST_MAKE_FOURCC(a,b,c,d)        ((guint32)((a)|(b)<<8|(c)<<16|(d)<<24))
 
 /**
  * GST_STR_FOURCC:
@@ -57,7 +57,7 @@
  * </programlisting>
  * </informalexample>
  */
-#define GST_STR_FOURCC(f)               (guint32)(((f)[0])|((f)[1]<<8)|((f)[2]<<16)|((f)[3]<<24))
+#define GST_STR_FOURCC(f)               ((guint32)(((f)[0])|((f)[1]<<8)|((f)[2]<<16)|((f)[3]<<24)))
 
 /**
  * GST_FOURCC_FORMAT:
@@ -91,7 +91,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_FOURCC value.
  */
-#define GST_VALUE_HOLDS_FOURCC(x)       (G_VALUE_HOLDS(x, gst_fourcc_get_type ()))
+#define GST_VALUE_HOLDS_FOURCC(x)       (G_VALUE_HOLDS((x), gst_fourcc_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_INT_RANGE:
@@ -99,7 +99,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_INT_RANGE value.
  */
-#define GST_VALUE_HOLDS_INT_RANGE(x)    (G_VALUE_HOLDS(x, gst_int_range_get_type ()))
+#define GST_VALUE_HOLDS_INT_RANGE(x)    (G_VALUE_HOLDS((x), gst_int_range_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_DOUBLE_RANGE:
@@ -107,7 +107,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_DOUBLE_RANGE value.
  */
-#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_HOLDS(x, gst_double_range_get_type ()))
+#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_HOLDS((x), gst_double_range_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_FRACTION_RANGE:
@@ -115,7 +115,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_FRACTION_RANGE value.
  */
-#define GST_VALUE_HOLDS_FRACTION_RANGE(x)    (G_VALUE_HOLDS(x, gst_fraction_range_get_type ()))
+#define GST_VALUE_HOLDS_FRACTION_RANGE(x)    (G_VALUE_HOLDS((x), gst_fraction_range_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_LIST:
@@ -123,7 +123,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_LIST value.
  */
-#define GST_VALUE_HOLDS_LIST(x)		(G_VALUE_HOLDS(x, gst_value_list_get_type ()))
+#define GST_VALUE_HOLDS_LIST(x)		(G_VALUE_HOLDS((x), gst_value_list_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_ARRAY:
@@ -131,7 +131,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_ARRAY value.
  */
-#define GST_VALUE_HOLDS_ARRAY(x)	(G_VALUE_HOLDS(x, gst_value_array_get_type ()))
+#define GST_VALUE_HOLDS_ARRAY(x)	(G_VALUE_HOLDS((x), gst_value_array_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_CAPS:
@@ -139,7 +139,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_CAPS value.
  */
-#define GST_VALUE_HOLDS_CAPS(x)		(G_VALUE_HOLDS(x, GST_TYPE_CAPS))
+#define GST_VALUE_HOLDS_CAPS(x)		(G_VALUE_HOLDS((x), GST_TYPE_CAPS))
 
 /**
  * GST_VALUE_HOLDS_STRUCTURE:
@@ -149,7 +149,7 @@
  *
  * Since: 0.10.15
  */
-#define GST_VALUE_HOLDS_STRUCTURE(x)		(G_VALUE_HOLDS(x, GST_TYPE_STRUCTURE))
+#define GST_VALUE_HOLDS_STRUCTURE(x)		(G_VALUE_HOLDS((x), GST_TYPE_STRUCTURE))
 
 /**
  * GST_VALUE_HOLDS_BUFFER:
@@ -157,7 +157,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_BUFFER value.
  */
-#define GST_VALUE_HOLDS_BUFFER(x)       (G_VALUE_HOLDS(x, GST_TYPE_BUFFER))
+#define GST_VALUE_HOLDS_BUFFER(x)       (G_VALUE_HOLDS((x), GST_TYPE_BUFFER))
 
 /**
  * GST_VALUE_HOLDS_FRACTION:
@@ -165,7 +165,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_FRACTION value.
  */
-#define GST_VALUE_HOLDS_FRACTION(x)	(G_VALUE_HOLDS(x, gst_fraction_get_type ()))
+#define GST_VALUE_HOLDS_FRACTION(x)	(G_VALUE_HOLDS((x), gst_fraction_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_DATE:
@@ -173,7 +173,7 @@
  *
  * Checks if the given #GValue contains a #GST_TYPE_DATE value.
  */
-#define GST_VALUE_HOLDS_DATE(x)         (G_VALUE_HOLDS(x, gst_date_get_type ()))
+#define GST_VALUE_HOLDS_DATE(x)         (G_VALUE_HOLDS((x), gst_date_get_type ()))
 
 /**
  * GST_TYPE_FOURCC:
--- a/gstreamer_core/gst/gstversion.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstversion.h	Fri Apr 16 15:15:52 2010 +0300
@@ -57,15 +57,32 @@
  *
  * The micro version of GStreamer at compile time:
  */
-#define GST_VERSION_MICRO (19) //rj
+#define GST_VERSION_MICRO (24)
 /**
  * GST_VERSION_NANO:
  *
  * The nano version of GStreamer at compile time:
- * Actual releases have 0, CVS versions have 1, prerelease versions have 2-...
+ * Actual releases have 0, GIT versions have 1, prerelease versions have 2-...
  */
 #define GST_VERSION_NANO (0)
 
+/**
+ * GST_CHECK_VERSION:
+ * @major: a number indicating the major version
+ * @minor: a number indicating the minor version
+ * @micro: a number indicating the micro version
+ *
+ * Check whether a GStreamer version equal to or greater than
+ * major.minor.micro is present.
+ *
+ * Since: 0.10.18
+ */
+#define	GST_CHECK_VERSION(major,minor,micro)	\
+    (GST_VERSION_MAJOR > (major) || \
+     (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR > (minor)) || \
+     (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR == (minor) && \
+      GST_VERSION_MICRO >= (micro)))
+
 G_END_DECLS
 
 #endif /* __GST_VERSION_H__ */
--- a/gstreamer_core/gst/gstxml.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/gstxml.c	Fri Apr 16 15:15:52 2010 +0300
@@ -30,8 +30,8 @@
  * Additionally one can load saved pipelines into the gst-editor to inspect the
  * graph.
  *
- * #GstElement implementations need to override gst_object_save_thyself() and
- * gst_object_restore_thyself().
+ * #GstElement implementations need to override the save_thyself() and
+ * restore_thyself() virtual functions of #GstObject.
  */
 
 #include "gst_private.h"
@@ -57,36 +57,12 @@
 static GstObjectClass *parent_class = NULL;
 static guint gst_xml_signals[LAST_SIGNAL] = { 0 };
 
-GType
-gst_xml_get_type (void)
-{
-  static GType xml_type = 0;
-
-  if (G_UNLIKELY (xml_type == 0)) {
-    static const GTypeInfo xml_info = {
-      sizeof (GstXMLClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_xml_class_init,
-      NULL,
-      NULL,
-      sizeof (GstXML),
-      0,
-      (GInstanceInitFunc) gst_xml_init,
-      NULL
-    };
-
-    xml_type = g_type_register_static (GST_TYPE_OBJECT, "GstXML", &xml_info, 0);
-  }
-  return xml_type;
-}
+G_DEFINE_TYPE (GstXML, gst_xml, GST_TYPE_OBJECT);
 
 static void
 gst_xml_class_init (GstXMLClass * klass)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = (GObjectClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
--- a/gstreamer_core/gst/helpfile.cpp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/helpfile.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -25,50 +25,32 @@
 #include <e32std.h> 
 #include <pls.h> // For emulator WSD API 
 #include <glib.h>
+#include <config.h>
+#include <stdlib.h> 
 
 extern "C" char* libgstreamer_get_dll_path(char* dllName)
 {
-    TUint ch = TUint('A');
-    char* fullPath = dllName;
-    #ifdef __WINSCW__ 
-    char* dllPath = "z:\\sys\\bin\\plugins";
-    fullPath = g_strjoin ("\\", dllPath,dllName, NULL);
-    #else
-    char* dllPath = "sys\\bin";
-    
-    char* filename;
-    TInt i; 
+    char* dllFullPath = NULL;
     RFs fs;
-    TDriveList driveList;
-    //err = fs.Connect();
+    CDir* directory=NULL;
     if( !(fs.Connect()) )
     {
-        //err = fs.DriveList(driveList);
-        if( !(fs.DriveList(driveList)) )
+        TFindFile findFile(fs);
+        TFileName file;
+        TPtrC8 filename;
+        filename.Set( reinterpret_cast<TUint8*>( dllName ) );
+        file.Copy( filename );
+        if( ! findFile.FindWildByDir(file,KResFileNamePath,directory) )
         {
-            for( i = 0; i< KMaxDrives; i++ )
-            {
-            
-                if( driveList[i] != 0 )
-                {
-                    char temp[3];
-                    temp[0]= char(ch);
-                    temp[1]= ':';
-                    temp[2]= '\0';
-                    
-                    filename = g_strjoin ("\\", temp,dllPath,dllName, NULL);
-                    if (g_file_test (filename, G_FILE_TEST_EXISTS))
-                    {
-                        fullPath = filename;
-                        break;
-                    }
-                }
-                ch++;
-            }
+            TBuf8<KMaxFileName> fileName;
+            fileName.Copy( findFile.File() );
+            TInt length = fileName.Size() + 1;
+            dllFullPath = (char*)malloc( length );
+            memcpy( dllFullPath, fileName.PtrZ(), length );
+            delete directory;
         }
         fs.Close();
     }
-    #endif
-    return fullPath;
+    return dllFullPath;
 }
 
--- a/gstreamer_core/gst/parse/grammar.tab.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/parse/grammar.tab.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,12 +1,6 @@
 #ifdef HAVE_CONFIG_H
-#ifdef __SYMBIAN32__
-#include "config.h"
-#else
 #include <config.h>
 #endif
-#endif
-
-
 /* A Bison parser, made by GNU Bison 2.3.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
@@ -112,6 +106,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#ifdef __SYMBIAN32__
+#include <glib_global.h>
+#endif
 
 #include "../gst_private.h"
 #include "../gst-i18n-lib.h"
@@ -120,6 +117,7 @@
 #include "../gstparse.h"
 #include "../gstinfo.h"
 #include "../gsterror.h"
+#include "../gststructure.h"
 #include "../gsturi.h"
 #include "../gstutils.h"
 #include "../gstvalue.h"
@@ -235,7 +233,7 @@
 } G_STMT_END
 
 #  define ERROR(type, ...) \
-  SET_ERROR (((graph_t *) graph)->error, (type), __VA_ARGS__ )
+  SET_ERROR (graph->error, (type), __VA_ARGS__ )
 
 #elif defined(G_HAVE_GNUC_VARARGS)
 
@@ -248,7 +246,7 @@
 } G_STMT_END
 
 #  define ERROR(type, args...) \
-  SET_ERROR (((graph_t *) graph)->error,(type) , args )
+  SET_ERROR (graph->error,(type) , args )
 
 #else
 
@@ -321,13 +319,19 @@
 
 #endif /* GST_DISABLE_GST_DEBUG */
 
+#define ADD_MISSING_ELEMENT(graph,name) G_STMT_START {                      \
+    if ((graph)->ctx) {                                                     \
+      (graph)->ctx->missing_elements =                                      \
+          g_list_append ((graph)->ctx->missing_elements, g_strdup (name));  \
+    } } G_STMT_END
+
 #define GST_BIN_MAKE(res, type, chainval, assign, free_string) \
 G_STMT_START { \
   chain_t *chain = chainval; \
   GSList *walk; \
   GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \
   if (!chain) { \
-    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY_BIN, \
+    SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN, \
         _("specified empty bin \"%s\", not allowed"), type); \
     g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
     g_slist_free (assign); \
@@ -336,7 +340,8 @@
       gst_parse_strfree (type); /* Need to clean up the string */ \
     YYERROR; \
   } else if (!bin) { \
-    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \
+    ADD_MISSING_ELEMENT(graph, type); \
+    SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \
         _("no bin \"%s\", skipping"), type); \
     g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
     g_slist_free (assign); \
@@ -390,29 +395,46 @@
   GType value_type;
 
   if (gst_child_proxy_lookup (GST_OBJECT (set->parent), set->name, &target, &pspec)) { 
+    gboolean got_value = FALSE;
+
     value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
 
     GST_CAT_LOG (GST_CAT_PIPELINE, "parsing delayed property %s as a %s from %s", pspec->name,
       g_type_name (value_type), set->value_str);
     g_value_init (&v, value_type);
-    if (gst_value_deserialize (&v, set->value_str)) {
-      g_object_set_property (G_OBJECT (target), pspec->name, &v);
+    if (gst_value_deserialize (&v, set->value_str))
+      got_value = TRUE;
+    else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) {
+       GstElement *bin;
+       
+       bin = gst_parse_bin_from_description (set->value_str, TRUE, NULL);
+       if (bin) {
+         g_value_set_object (&v, bin);
+         got_value = TRUE;
+       }
     }
     g_signal_handler_disconnect (child_proxy, set->signal_id);
     g_free(set->name);
     g_free(set->value_str);
     g_free(set);
+    if (!got_value)
+      goto error;
+    g_object_set_property (G_OBJECT (target), pspec->name, &v);
   }
 
+out:
   if (G_IS_VALUE (&v))
     g_value_unset (&v);
   if (target)
     gst_object_unref (target);
   return;
+
+error:
+  GST_CAT_ERROR (GST_CAT_PIPELINE, "could not set property \"%s\" in element \"%s\"",
+	 pspec->name, GST_ELEMENT_NAME (target));
+  goto out;
 }
-#ifdef __SYMBIAN32__
-#include<glib_global.h>
-#endif
+
 
 static void
 gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
@@ -423,6 +445,10 @@
   GstObject *target = NULL;
   GType value_type;
 
+  /* do nothing if assignment is for missing element */
+  if (element == NULL)
+    goto out;
+
   /* parse the string, so the property name is null-terminated an pos points
      to the beginning of the value */
   while (!g_ascii_isspace (*pos) && (*pos != '=')) pos++; 
@@ -442,11 +468,25 @@
   gst_parse_unescape (pos);
 
   if (gst_child_proxy_lookup (GST_OBJECT (element), value, &target, &pspec)) { 
+    gboolean got_value = FALSE;
+
     value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); 
+
     GST_CAT_LOG (GST_CAT_PIPELINE, "parsing property %s as a %s", pspec->name,
       g_type_name (value_type));
     g_value_init (&v, value_type);
-    if (!gst_value_deserialize (&v, pos))
+    if (gst_value_deserialize (&v, pos))
+      got_value = TRUE;
+    else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) {
+       GstElement *bin;
+       
+       bin = gst_parse_bin_from_description (pos, TRUE, NULL);
+       if (bin) {
+         g_value_set_object (&v, bin);
+         got_value = TRUE;
+       }
+    }
+    if (!got_value)
       goto error;
     g_object_set_property (G_OBJECT (target), pspec->name, &v);
   } else { 
@@ -460,7 +500,7 @@
       data->signal_id = g_signal_connect(GST_OBJECT (element),"child-added", G_CALLBACK (gst_parse_new_child), data);
     }
     else {
-      SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
+      SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
           _("no property \"%s\" in element \"%s\""), value, \
           GST_ELEMENT_NAME (element));
     }
@@ -475,7 +515,7 @@
   return;
   
 error:
-  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+  SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
          _("could not set property \"%s\" in element \"%s\" to \"%s\""), 
 	 value, GST_ELEMENT_NAME (element), pos); 
   goto out;
@@ -617,7 +657,7 @@
   return 0;
   
 error:
-  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
+  SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
       _("could not link %s to %s"), GST_ELEMENT_NAME (src),
       GST_ELEMENT_NAME (sink));
   gst_parse_free_link (link);
@@ -648,7 +688,7 @@
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 521 "./grammar.y"
+#line 566 "./grammar.y"
 {
     gchar *s;
     chain_t *c;
@@ -658,7 +698,7 @@
     graph_t *g;
 }
 /* Line 187 of yacc.c.  */
-#line 651 "grammar.tab.c"
+#line 696 "grammar.tab.c"
 	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -671,7 +711,7 @@
 
 
 /* Line 216 of yacc.c.  */
-#line 664 "grammar.tab.c"
+#line 709 "grammar.tab.c"
 
 #ifdef short
 # undef short
@@ -964,10 +1004,10 @@
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   556,   556,   564,   568,   569,   571,   572,   575,   578,
-     583,   584,   588,   589,   592,   593,   596,   597,   598,   601,
-     614,   615,   616,   619,   624,   625,   660,   688,   689,   703,
-     723,   748,   751
+       0,   601,   601,   615,   619,   620,   622,   623,   626,   629,
+     634,   635,   639,   640,   643,   644,   647,   648,   649,   652,
+     665,   666,   667,   670,   675,   676,   711,   739,   740,   754,
+     774,   799,   802
 };
 #endif
 
@@ -1934,114 +1974,120 @@
   switch (yyn)
     {
         case 2:
-#line 556 "./grammar.y"
+#line 601 "./grammar.y"
     { (yyval.e) = gst_element_factory_make ((yyvsp[(1) - (1)].s), NULL); 
 						if ((yyval.e) == NULL) {
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), (yyvsp[(1) - (1)].s));
-						  gst_parse_strfree ((yyvsp[(1) - (1)].s));
-						  YYERROR;
+						  ADD_MISSING_ELEMENT (graph, (yyvsp[(1) - (1)].s));
+						  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), (yyvsp[(1) - (1)].s));
+						  /* if FATAL_ERRORS flag is set, we don't have to worry about backwards
+						   * compatibility and can continue parsing and check for other missing
+						   * elements */
+						  if ((graph->flags & GST_PARSE_FLAG_FATAL_ERRORS) == 0) {
+						    gst_parse_strfree ((yyvsp[(1) - (1)].s));
+						    YYERROR;
+						  }
 						}
 						gst_parse_strfree ((yyvsp[(1) - (1)].s));
                                               ;}
     break;
 
   case 3:
-#line 564 "./grammar.y"
+#line 615 "./grammar.y"
     { gst_parse_element_set ((yyvsp[(2) - (2)].s), (yyvsp[(1) - (2)].e), graph);
 						(yyval.e) = (yyvsp[(1) - (2)].e);
 	                                      ;}
     break;
 
   case 4:
-#line 568 "./grammar.y"
+#line 619 "./grammar.y"
     { (yyval.p) = NULL; ;}
     break;
 
   case 5:
-#line 569 "./grammar.y"
+#line 620 "./grammar.y"
     { (yyval.p) = g_slist_prepend ((yyvsp[(1) - (2)].p), (yyvsp[(2) - (2)].s)); ;}
     break;
 
   case 6:
-#line 571 "./grammar.y"
+#line 622 "./grammar.y"
     { GST_BIN_MAKE ((yyval.c), "bin", (yyvsp[(3) - (4)].c), (yyvsp[(2) - (4)].p), FALSE); ;}
     break;
 
   case 7:
-#line 572 "./grammar.y"
+#line 623 "./grammar.y"
     { GST_BIN_MAKE ((yyval.c), (yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].c), (yyvsp[(2) - (4)].p), TRUE); 
 						gst_parse_strfree ((yyvsp[(1) - (4)].s));
 					      ;}
     break;
 
   case 8:
-#line 575 "./grammar.y"
+#line 626 "./grammar.y"
     { GST_BIN_MAKE ((yyval.c), (yyvsp[(1) - (3)].s), NULL, (yyvsp[(2) - (3)].p), TRUE); 
 						gst_parse_strfree ((yyvsp[(1) - (3)].s));
 					      ;}
     break;
 
   case 9:
-#line 578 "./grammar.y"
+#line 629 "./grammar.y"
     { GST_BIN_MAKE ((yyval.c), (yyvsp[(1) - (4)].s), NULL, (yyvsp[(2) - (4)].p), TRUE); 
 						gst_parse_strfree ((yyvsp[(1) - (4)].s));
 					      ;}
     break;
 
   case 10:
-#line 583 "./grammar.y"
+#line 634 "./grammar.y"
     { (yyval.p) = g_slist_prepend (NULL, (yyvsp[(1) - (1)].s)); ;}
     break;
 
   case 11:
-#line 584 "./grammar.y"
+#line 635 "./grammar.y"
     { (yyval.p) = (yyvsp[(2) - (2)].p);
 						(yyval.p) = g_slist_prepend ((yyval.p), (yyvsp[(1) - (2)].s));
 					      ;}
     break;
 
   case 12:
-#line 588 "./grammar.y"
+#line 639 "./grammar.y"
     { (yyval.p) = g_slist_prepend (NULL, (yyvsp[(2) - (2)].s)); ;}
     break;
 
   case 13:
-#line 589 "./grammar.y"
+#line 640 "./grammar.y"
     { (yyval.p) = g_slist_prepend ((yyvsp[(3) - (3)].p), (yyvsp[(2) - (3)].s)); ;}
     break;
 
   case 14:
-#line 592 "./grammar.y"
+#line 643 "./grammar.y"
     { MAKE_REF ((yyval.l), (yyvsp[(1) - (1)].s), NULL); ;}
     break;
 
   case 15:
-#line 593 "./grammar.y"
+#line 644 "./grammar.y"
     { MAKE_REF ((yyval.l), (yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].p)); ;}
     break;
 
   case 16:
-#line 596 "./grammar.y"
+#line 647 "./grammar.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 17:
-#line 597 "./grammar.y"
+#line 648 "./grammar.y"
     { MAKE_REF ((yyval.l), NULL, (yyvsp[(1) - (1)].p)); ;}
     break;
 
   case 18:
-#line 598 "./grammar.y"
+#line 649 "./grammar.y"
     { MAKE_REF ((yyval.l), NULL, NULL); ;}
     break;
 
   case 19:
-#line 601 "./grammar.y"
+#line 652 "./grammar.y"
     { (yyval.l) = (yyvsp[(1) - (3)].l);
 						if ((yyvsp[(2) - (3)].s)) {
 						  (yyval.l)->caps = gst_caps_from_string ((yyvsp[(2) - (3)].s));
 						  if ((yyval.l)->caps == NULL)
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), (yyvsp[(2) - (3)].s));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), (yyvsp[(2) - (3)].s));
 						  gst_parse_strfree ((yyvsp[(2) - (3)].s));
 						}
 						(yyval.l)->sink_name = (yyvsp[(3) - (3)].l)->src_name;
@@ -2051,22 +2097,22 @@
     break;
 
   case 20:
-#line 614 "./grammar.y"
+#line 665 "./grammar.y"
     { (yyval.p) = g_slist_prepend (NULL, (yyvsp[(1) - (1)].l)); ;}
     break;
 
   case 21:
-#line 615 "./grammar.y"
+#line 666 "./grammar.y"
     { (yyval.p) = g_slist_prepend ((yyvsp[(2) - (2)].p), (yyvsp[(1) - (2)].l)); ;}
     break;
 
   case 22:
-#line 616 "./grammar.y"
+#line 667 "./grammar.y"
     { (yyval.p) = (yyvsp[(1) - (2)].p); ;}
     break;
 
   case 23:
-#line 619 "./grammar.y"
+#line 670 "./grammar.y"
     { (yyval.c) = gst_parse_chain_new ();
 						(yyval.c)->first = (yyval.c)->last = (yyvsp[(1) - (1)].e);
 						(yyval.c)->front = (yyval.c)->back = NULL;
@@ -2075,24 +2121,24 @@
     break;
 
   case 24:
-#line 624 "./grammar.y"
+#line 675 "./grammar.y"
     { (yyval.c) = (yyvsp[(1) - (1)].c); ;}
     break;
 
   case 25:
-#line 625 "./grammar.y"
+#line 676 "./grammar.y"
     { if ((yyvsp[(1) - (2)].c)->back && (yyvsp[(2) - (2)].c)->front) {
 						  if (!(yyvsp[(1) - (2)].c)->back->sink_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
 						    gst_parse_free_link ((yyvsp[(1) - (2)].c)->back);
 						  } else {
-						    ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, (yyvsp[(1) - (2)].c)->back);
+						    graph->links = g_slist_prepend (graph->links, (yyvsp[(1) - (2)].c)->back);
 						  }
 						  if (!(yyvsp[(2) - (2)].c)->front->src_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
 						    gst_parse_free_link ((yyvsp[(2) - (2)].c)->front);
 						  } else {
-						    ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, (yyvsp[(2) - (2)].c)->front);
+						    graph->links = g_slist_prepend (graph->links, (yyvsp[(2) - (2)].c)->front);
 						  }
 						  (yyvsp[(1) - (2)].c)->back = NULL;
 						} else if ((yyvsp[(1) - (2)].c)->back) {
@@ -2107,7 +2153,7 @@
 						}
 						
 						if ((yyvsp[(1) - (2)].c)->back) {
-						  ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, (yyvsp[(1) - (2)].c)->back);
+						  graph->links = g_slist_prepend (graph->links, (yyvsp[(1) - (2)].c)->back);
 						}
 						(yyvsp[(1) - (2)].c)->last = (yyvsp[(2) - (2)].c)->last;
 						(yyvsp[(1) - (2)].c)->back = (yyvsp[(2) - (2)].c)->back;
@@ -2119,7 +2165,7 @@
     break;
 
   case 26:
-#line 660 "./grammar.y"
+#line 711 "./grammar.y"
     { GSList *walk;
 						if ((yyvsp[(1) - (2)].c)->back) {
 						  (yyvsp[(2) - (2)].p) = g_slist_prepend ((yyvsp[(2) - (2)].p), (yyvsp[(1) - (2)].c)->back);
@@ -2132,14 +2178,14 @@
 						for (walk = (yyvsp[(2) - (2)].p); walk; walk = walk->next) {
 						  link_t *link = (link_t *) walk->data;
 						  if (!link->sink_name && walk->next) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
 						    gst_parse_free_link (link);
 						  } else if (!link->src_name && !link->src) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
 						    gst_parse_free_link (link);
 						  } else {
 						    if (walk->next) {
-						      ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, link);
+						      graph->links = g_slist_prepend (graph->links, link);
 						    } else {
 						      (yyvsp[(1) - (2)].c)->back = link;
 						    }
@@ -2151,18 +2197,18 @@
     break;
 
   case 27:
-#line 688 "./grammar.y"
+#line 739 "./grammar.y"
     { (yyval.c) = (yyvsp[(1) - (2)].c); ;}
     break;
 
   case 28:
-#line 689 "./grammar.y"
+#line 740 "./grammar.y"
     { if ((yyvsp[(2) - (2)].c)->front) {
 						  if (!(yyvsp[(2) - (2)].c)->front->src_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
 						    gst_parse_free_link ((yyvsp[(2) - (2)].c)->front);
 						  } else {
-						    ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, (yyvsp[(2) - (2)].c)->front);
+						    graph->links = g_slist_prepend (graph->links, (yyvsp[(2) - (2)].c)->front);
 						  }
 						}
 						if (!(yyvsp[(1) - (2)].l)->sink_name) {
@@ -2174,23 +2220,23 @@
     break;
 
   case 29:
-#line 703 "./grammar.y"
+#line 754 "./grammar.y"
     { (yyval.c) = (yyvsp[(2) - (2)].c);
 						if ((yyval.c)->front) {
 						  GstElement *element = 
 							  gst_element_make_from_uri (GST_URI_SRC, (yyvsp[(1) - (2)].s), NULL);
 						  if (!element) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
 							    _("no source element for URI \"%s\""), (yyvsp[(1) - (2)].s));
 						  } else {
 						    (yyval.c)->front->src = element;
-						    ((graph_t *) graph)->links = g_slist_prepend (
-							    ((graph_t *) graph)->links, (yyval.c)->front);
+						    graph->links = g_slist_prepend (
+							    graph->links, (yyval.c)->front);
 						    (yyval.c)->front = NULL;
 						    (yyval.c)->elements = g_slist_prepend ((yyval.c)->elements, element);
 						  }
 						} else {
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, 
+						  SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, 
 							  _("no element to link URI \"%s\" to"), (yyvsp[(1) - (2)].s));
 						}
 						g_free ((yyvsp[(1) - (2)].s));
@@ -2198,18 +2244,18 @@
     break;
 
   case 30:
-#line 723 "./grammar.y"
+#line 774 "./grammar.y"
     { GstElement *element =
 							  gst_element_make_from_uri (GST_URI_SINK, (yyvsp[(2) - (2)].s), NULL);
 						if (!element) {
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
+						  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
 							  _("no sink element for URI \"%s\""), (yyvsp[(2) - (2)].s));
 						  gst_parse_link_free ((yyvsp[(1) - (2)].l));
 						  g_free ((yyvsp[(2) - (2)].s));
 						  YYERROR;
 						} else if ((yyvsp[(1) - (2)].l)->sink_name || (yyvsp[(1) - (2)].l)->sink_pads) {
                                                   gst_object_unref (element);
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, 
+						  SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, 
 							  _("could not link sink element for URI \"%s\""), (yyvsp[(2) - (2)].s));
 						  gst_parse_link_free ((yyvsp[(1) - (2)].l));
 						  g_free ((yyvsp[(2) - (2)].s));
@@ -2226,18 +2272,18 @@
     break;
 
   case 31:
-#line 748 "./grammar.y"
-    { SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
-						(yyval.g) = (graph_t *) graph;
+#line 799 "./grammar.y"
+    { SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
+						(yyval.g) = graph;
 					      ;}
     break;
 
   case 32:
-#line 751 "./grammar.y"
-    { (yyval.g) = (graph_t *) graph;
+#line 802 "./grammar.y"
+    { (yyval.g) = graph;
 						if ((yyvsp[(1) - (1)].c)->front) {
 						  if (!(yyvsp[(1) - (1)].c)->front->src_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
 						    gst_parse_free_link ((yyvsp[(1) - (1)].c)->front);
 						  } else {
 						    (yyval.g)->links = g_slist_prepend ((yyval.g)->links, (yyvsp[(1) - (1)].c)->front);
@@ -2246,7 +2292,7 @@
 						}
 						if ((yyvsp[(1) - (1)].c)->back) {
 						  if (!(yyvsp[(1) - (1)].c)->back->sink_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
+						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
 						    gst_parse_free_link ((yyvsp[(1) - (1)].c)->back);
 						  } else {
 						    (yyval.g)->links = g_slist_prepend ((yyval.g)->links, (yyvsp[(1) - (1)].c)->back);
@@ -2259,7 +2305,7 @@
 
 
 /* Line 1267 of yacc.c.  */
-#line 2252 "grammar.tab.c"
+#line 2303 "grammar.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2473,7 +2519,7 @@
 }
 
 
-#line 774 "./grammar.y"
+#line 825 "./grammar.y"
 
 
 
@@ -2487,7 +2533,8 @@
 
 
 GstElement *
-_gst_parse_launch (const gchar *str, GError **error)
+_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
+    GstParseFlags flags)
 {
   graph_t g;
   gchar *dstr;
@@ -2497,10 +2544,13 @@
   yyscan_t scanner;
 
   g_return_val_if_fail (str != NULL, NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
   g.chain = NULL;
   g.links = NULL;
   g.error = error;
+  g.ctx = ctx;
+  g.flags = flags;
   
 #ifdef __GST_PARSE_TRACE
   GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
@@ -2533,10 +2583,10 @@
   
   if (!g.chain) {
     ret = NULL;
-  } else if (!(((chain_t *) g.chain)->elements->next)) {
+  } else if (!g.chain->elements->next) {
     /* only one toplevel element */  
-    ret = (GstElement *) ((chain_t *) g.chain)->elements->data;
-    g_slist_free (((chain_t *) g.chain)->elements);
+    ret = (GstElement *) g.chain->elements->data;
+    g_slist_free (g.chain->elements);
     if (GST_IS_BIN (ret))
       bin = GST_BIN (ret);
     gst_parse_chain_free (g.chain);
@@ -2569,8 +2619,12 @@
         }
       }
       if (!l->src) {
-        SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            "No element named \"%s\" - omitting link", l->src_name);
+        if (l->src_name) {
+          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+              "No element named \"%s\" - omitting link", l->src_name);
+        } else {
+          /* probably a missing element which we've handled already */
+        }
         gst_parse_free_link (l);
         continue;
       }
@@ -2586,8 +2640,12 @@
         }
       }
       if (!l->sink) {
-        SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            "No element named \"%s\" - omitting link", l->sink_name);
+        if (l->sink_name) {
+          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+              "No element named \"%s\" - omitting link", l->sink_name);
+        } else {
+          /* probably a missing element which we've handled already */
+        }
         gst_parse_free_link (l);
         continue;
       }
--- a/gstreamer_core/gst/parse/grammar.tab.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/parse/grammar.tab.h	Fri Apr 16 15:15:52 2010 +0300
@@ -62,7 +62,7 @@
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 521 "./grammar.y"
+#line 566 "./grammar.y"
 {
     gchar *s;
     chain_t *c;
--- a/gstreamer_core/gst/parse/grammar.tab.pre.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2706 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#ifndef __SYMBIAN32__
-#include "config.h"
-#else
-#include "config.h"
-#endif
-#endif
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-/* Substitute the variable and function names.  */
-#define yyparse _gst_parse_yyparse
-#define yylex   _gst_parse_yylex
-#define yyerror _gst_parse_yyerror
-#define yylval  _gst_parse_yylval
-#define yychar  _gst_parse_yychar
-#define yydebug _gst_parse_yydebug
-#define yynerrs _gst_parse_yynerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-enum yytokentype
-{
-  PARSE_URL = 258,
-  IDENTIFIER = 259,
-  BINREF = 260,
-  PADREF = 261,
-  REF = 262,
-  ASSIGNMENT = 263,
-  LINK = 264
-};
-#endif
-/* Tokens.  */
-#define PARSE_URL 258
-#define IDENTIFIER 259
-#define BINREF 260
-#define PADREF 261
-#define REF 262
-#define ASSIGNMENT 263
-#define LINK 264
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "./grammar.y"
-
-#include <glib-object.h>
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "../gst_private.h"
-#include "../gst-i18n-lib.h"
-
-#include "../gstconfig.h"
-#include "../gstparse.h"
-#include "../gstinfo.h"
-#include "../gsterror.h"
-#include "../gsturi.h"
-#include "../gstutils.h"
-#include "../gstvalue.h"
-#include "../gstchildproxy.h"
-#include "types.h"
-
-/* All error messages in this file are user-visible and need to be translated.
- * Don't start the message with a capital, and don't end them with a period,
- * as they will be presented inside a sentence/error.
- */
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-#define YYERROR_VERBOSE 1
-#define YYLEX_PARAM scanner
-
-typedef void *yyscan_t;
-
-int _gst_parse_yylex (void *yylval_param, yyscan_t yyscanner);
-int _gst_parse_yylex_init (yyscan_t scanner);
-int _gst_parse_yylex_destroy (yyscan_t scanner);
-struct yy_buffer_state *_gst_parse_yy_scan_string (char *, yyscan_t);
-void _gst_parse_yypush_buffer_state (void *new_buffer, yyscan_t yyscanner);
-void _gst_parse_yypop_buffer_state (yyscan_t yyscanner);
-
-
-#ifdef __GST_PARSE_TRACE
-static guint __strings;
-static guint __links;
-static guint __chains;
-gchar *
-__gst_parse_strdup (gchar * org)
-{
-  gchar *ret;
-
-  __strings++;
-  ret = g_strdup (org);
-  /* g_print ("ALLOCATED STR   (%3u): %p %s\n", __strings, ret, ret); */
-  return ret;
-}
-
-void
-__gst_parse_strfree (gchar * str)
-{
-  if (str) {
-    /* g_print ("FREEING STR     (%3u): %p %s\n", __strings - 1, str, str); */
-    g_free (str);
-    g_return_if_fail (__strings > 0);
-    __strings--;
-  }
-}
-link_t *
-__gst_parse_link_new ()
-{
-  link_t *ret;
-
-  __links++;
-  ret = g_new0 (link_t, 1);
-  /* g_print ("ALLOCATED LINK  (%3u): %p\n", __links, ret); */
-  return ret;
-}
-
-void
-__gst_parse_link_free (link_t * data)
-{
-  if (data) {
-    /* g_print ("FREEING LINK    (%3u): %p\n", __links - 1, data); */
-    g_free (data);
-    g_return_if_fail (__links > 0);
-    __links--;
-  }
-}
-chain_t *
-__gst_parse_chain_new ()
-{
-  chain_t *ret;
-
-  __chains++;
-  ret = g_new0 (chain_t, 1);
-  /* g_print ("ALLOCATED CHAIN (%3u): %p\n", __chains, ret); */
-  return ret;
-}
-
-void
-__gst_parse_chain_free (chain_t * data)
-{
-  /* g_print ("FREEING CHAIN   (%3u): %p\n", __chains - 1, data); */
-  g_free (data);
-  g_return_if_fail (__chains > 0);
-  __chains--;
-}
-
-#endif /* __GST_PARSE_TRACE */
-
-typedef struct
-{
-  gchar *src_pad;
-  gchar *sink_pad;
-  GstElement *sink;
-  GstCaps *caps;
-  gulong signal_id;
-  /* FIXME: need to connect to "disposed" signal to clean up,
-   * but there is no such signal */
-} DelayedLink;
-
-typedef struct
-{
-  GstElement *parent;
-  gchar *name;
-  gchar *value_str;
-  gulong signal_id;
-} DelayedSet;
-
-/*** define SET_ERROR and ERROR macros/functions */
-
-#ifdef G_HAVE_ISO_VARARGS
-
-#  define SET_ERROR(error, type, ...) \
-G_STMT_START { \
-  GST_CAT_ERROR (GST_CAT_PIPELINE, __VA_ARGS__); \
-  if ((error) && !*(error)) { \
-    g_set_error ((error), GST_PARSE_ERROR, (type), __VA_ARGS__); \
-  } \
-} G_STMT_END
-
-#  define ERROR(type, ...) \
-  SET_ERROR (((graph_t *) graph)->error, (type), __VA_ARGS__ )
-
-#elif defined(G_HAVE_GNUC_VARARGS)
-
-#  define SET_ERROR(error, type, args...) \
-G_STMT_START { \
-  GST_CAT_ERROR (GST_CAT_PIPELINE, args ); \
-  if ((error) && !*(error)) { \
-    g_set_error ((error), GST_PARSE_ERROR, (type), args ); \
-  } \
-} G_STMT_END
-
-#  define ERROR(type, args...) \
-  SET_ERROR (((graph_t *) graph)->error,(type) , args )
-
-#else
-
-static inline void
-SET_ERROR (GError ** error, gint type, const char *format, ...)
-{
-  if (error) {
-    if (*error) {
-      g_warning ("error while parsing");
-    } else {
-      va_list varargs;
-      char *string;
-
-      va_start (varargs, format);
-      string = g_strdup_vprintf (format, varargs);
-      va_end (varargs);
-
-      g_set_error (error, GST_PARSE_ERROR, type, string);
-
-      g_free (string);
-    }
-  }
-}
-
-#endif /* G_HAVE_ISO_VARARGS */
-
-/*** define YYPRINTF macro/function if we're debugging */
-
-/* bison 1.35 calls this macro with side effects, we need to make sure the
-   side effects work - crappy bison */
-
-#ifndef GST_DISABLE_GST_DEBUG
-#  define YYDEBUG 1
-
-#  ifdef G_HAVE_ISO_VARARGS
-
-/* #  define YYFPRINTF(a, ...) GST_CAT_DEBUG (GST_CAT_PIPELINE, __VA_ARGS__) */
-#    define YYFPRINTF(a, ...) \
-G_STMT_START { \
-     gchar *temp = g_strdup_printf (__VA_ARGS__); \
-     GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
-     g_free (temp); \
-} G_STMT_END
-
-#  elif defined(G_HAVE_GNUC_VARARGS)
-
-#    define YYFPRINTF(a, args...) \
-G_STMT_START { \
-     gchar *temp = g_strdup_printf ( args ); \
-     GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
-     g_free (temp); \
-} G_STMT_END
-
-#  else
-
-static inline void
-YYPRINTF (const char *format, ...)
-{
-  va_list varargs;
-  gchar *temp;
-
-  va_start (varargs, format);
-  temp = g_strdup_vprintf (format, varargs);
-  GST_CAT_LOG (GST_CAT_PIPELINE, "%s", temp);
-  g_free (temp);
-  va_end (varargs);
-}
-
-#  endif /* G_HAVE_ISO_VARARGS */
-
-#endif /* GST_DISABLE_GST_DEBUG */
-
-#define GST_BIN_MAKE(res, type, chainval, assign, free_string) \
-G_STMT_START { \
-  chain_t *chain = chainval; \
-  GSList *walk; \
-  GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \
-  if (!chain) { \
-    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY_BIN, \
-        _("specified empty bin \"%s\", not allowed"), type); \
-    g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
-    g_slist_free (assign); \
-    gst_object_unref (bin); \
-    if (free_string) \
-      gst_parse_strfree (type); /* Need to clean up the string */ \
-    YYERROR; \
-  } else if (!bin) { \
-    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \
-        _("no bin \"%s\", skipping"), type); \
-    g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
-    g_slist_free (assign); \
-    res = chain; \
-  } else { \
-    for (walk = chain->elements; walk; walk = walk->next ) \
-      gst_bin_add (bin, GST_ELEMENT (walk->data)); \
-    g_slist_free (chain->elements); \
-    chain->elements = g_slist_prepend (NULL, bin); \
-    res = chain; \
-    /* set the properties now */ \
-    for (walk = assign; walk; walk = walk->next) \
-      gst_parse_element_set ((gchar *) walk->data, GST_ELEMENT (bin), graph); \
-    g_slist_free (assign); \
-  } \
-} G_STMT_END
-
-#define MAKE_LINK(link, _src, _src_name, _src_pads, _sink, _sink_name, _sink_pads) \
-G_STMT_START { \
-  link = gst_parse_link_new (); \
-  link->src = _src; \
-  link->sink = _sink; \
-  link->src_name = _src_name; \
-  link->sink_name = _sink_name; \
-  link->src_pads = _src_pads; \
-  link->sink_pads = _sink_pads; \
-  link->caps = NULL; \
-} G_STMT_END
-
-#define MAKE_REF(link, _src, _pads) \
-G_STMT_START { \
-  gchar *padname = _src; \
-  GSList *pads = _pads; \
-  if (padname) { \
-    while (*padname != '.') padname++; \
-    *padname = '\0'; \
-    padname++; \
-    if (*padname != '\0') \
-      pads = g_slist_prepend (pads, gst_parse_strdup (padname)); \
-  } \
-  MAKE_LINK (link, NULL, _src, pads, NULL, NULL, NULL); \
-} G_STMT_END
-
-static void
-gst_parse_new_child (GstChildProxy * child_proxy, GObject * object,
-    gpointer data)
-{
-  DelayedSet *set = (DelayedSet *) data;
-  GParamSpec *pspec;
-  GValue v = { 0, };
-  GstObject *target = NULL;
-  GType value_type;
-
-  if (gst_child_proxy_lookup (GST_OBJECT (set->parent), set->name, &target,
-          &pspec)) {
-    value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-
-    GST_CAT_LOG (GST_CAT_PIPELINE,
-        "parsing delayed property %s as a %s from %s", pspec->name,
-        g_type_name (value_type), set->value_str);
-    g_value_init (&v, value_type);
-    if (gst_value_deserialize (&v, set->value_str)) {
-      g_object_set_property (G_OBJECT (target), pspec->name, &v);
-    }
-    g_signal_handler_disconnect (child_proxy, set->signal_id);
-    g_free (set->name);
-    g_free (set->value_str);
-    g_free (set);
-  }
-
-  if (G_IS_VALUE (&v))
-    g_value_unset (&v);
-  if (target)
-    gst_object_unref (target);
-  return;
-}
-
-
-static void
-gst_parse_element_set (gchar * value, GstElement * element, graph_t * graph)
-{
-  GParamSpec *pspec;
-  gchar *pos = value;
-  GValue v = { 0, };
-  GstObject *target = NULL;
-  GType value_type;
-
-  /* parse the string, so the property name is null-terminated an pos points
-     to the beginning of the value */
-  while (!g_ascii_isspace (*pos) && (*pos != '='))
-    pos++;
-  if (*pos == '=') {
-    *pos = '\0';
-  } else {
-    *pos = '\0';
-    pos++;
-    while (g_ascii_isspace (*pos))
-      pos++;
-  }
-  pos++;
-  while (g_ascii_isspace (*pos))
-    pos++;
-  if (*pos == '"') {
-    pos++;
-    pos[strlen (pos) - 1] = '\0';
-  }
-  gst_parse_unescape (pos);
-
-  if (gst_child_proxy_lookup (GST_OBJECT (element), value, &target, &pspec)) {
-    value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-    GST_CAT_LOG (GST_CAT_PIPELINE, "parsing property %s as a %s", pspec->name,
-        g_type_name (value_type));
-    g_value_init (&v, value_type);
-    if (!gst_value_deserialize (&v, pos))
-      goto error;
-    g_object_set_property (G_OBJECT (target), pspec->name, &v);
-  } else {
-    /* do a delayed set */
-    if (GST_IS_CHILD_PROXY (element)) {
-      DelayedSet *data = g_new (DelayedSet, 1);
-
-      data->parent = element;
-      data->name = g_strdup (value);
-      data->value_str = g_strdup (pos);
-      data->signal_id =
-          g_signal_connect (GST_OBJECT (element), "child-added",
-          G_CALLBACK (gst_parse_new_child), data);
-    } else {
-      SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY,
-          _("no property \"%s\" in element \"%s\""), value,
-          GST_ELEMENT_NAME (element));
-    }
-  }
-
-out:
-  gst_parse_strfree (value);
-  if (G_IS_VALUE (&v))
-    g_value_unset (&v);
-  if (target)
-    gst_object_unref (target);
-  return;
-
-error:
-  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
-      _("could not set property \"%s\" in element \"%s\" to \"%s\""),
-      value, GST_ELEMENT_NAME (element), pos);
-  goto out;
-}
-static inline void
-gst_parse_free_link (link_t * link)
-{
-  gst_parse_strfree (link->src_name);
-  gst_parse_strfree (link->sink_name);
-  g_slist_foreach (link->src_pads, (GFunc) gst_parse_strfree, NULL);
-  g_slist_foreach (link->sink_pads, (GFunc) gst_parse_strfree, NULL);
-  g_slist_free (link->src_pads);
-  g_slist_free (link->sink_pads);
-  if (link->caps)
-    gst_caps_unref (link->caps);
-  gst_parse_link_free (link);
-}
-
-static void
-gst_parse_found_pad (GstElement * src, GstPad * pad, gpointer data)
-{
-  DelayedLink *link = (DelayedLink *) data;
-
-  GST_CAT_INFO (GST_CAT_PIPELINE, "trying delayed linking %s:%s to %s:%s",
-      GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
-      GST_STR_NULL (GST_ELEMENT_NAME (link->sink)),
-      GST_STR_NULL (link->sink_pad));
-
-  if (gst_element_link_pads_filtered (src, link->src_pad, link->sink,
-          link->sink_pad, link->caps)) {
-    /* do this here, we don't want to get any problems later on when
-     * unlocking states */
-    GST_CAT_DEBUG (GST_CAT_PIPELINE, "delayed linking %s:%s to %s:%s worked",
-        GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
-        GST_STR_NULL (GST_ELEMENT_NAME (link->sink)),
-        GST_STR_NULL (link->sink_pad));
-    g_signal_handler_disconnect (src, link->signal_id);
-    g_free (link->src_pad);
-    g_free (link->sink_pad);
-    if (link->caps)
-      gst_caps_unref (link->caps);
-    g_free (link);
-  }
-}
-
-/* both padnames and the caps may be NULL */
-static gboolean
-gst_parse_perform_delayed_link (GstElement * src, const gchar * src_pad,
-    GstElement * sink, const gchar * sink_pad, GstCaps * caps)
-{
-  GList *templs =
-      gst_element_class_get_pad_template_list (GST_ELEMENT_GET_CLASS (src));
-
-  for (; templs; templs = templs->next) {
-    GstPadTemplate *templ = (GstPadTemplate *) templs->data;
-
-    if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) &&
-        (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES)) {
-      DelayedLink *data = g_new (DelayedLink, 1);
-
-      /* TODO: maybe we should check if src_pad matches this template's names */
-
-      GST_CAT_DEBUG (GST_CAT_PIPELINE, "trying delayed link %s:%s to %s:%s",
-          GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (src_pad),
-          GST_STR_NULL (GST_ELEMENT_NAME (sink)), GST_STR_NULL (sink_pad));
-
-      data->src_pad = g_strdup (src_pad);
-      data->sink = sink;
-      data->sink_pad = g_strdup (sink_pad);
-      if (caps) {
-        data->caps = gst_caps_copy (caps);
-      } else {
-        data->caps = NULL;
-      }
-      data->signal_id = g_signal_connect (G_OBJECT (src), "pad-added",
-          G_CALLBACK (gst_parse_found_pad), data);
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-/*
- * performs a link and frees the struct. src and sink elements must be given
- * return values   0 - link performed
- *                 1 - link delayed
- *                <0 - error
- */
-static gint
-gst_parse_perform_link (link_t * link, graph_t * graph)
-{
-  GstElement *src = link->src;
-  GstElement *sink = link->sink;
-  GSList *srcs = link->src_pads;
-  GSList *sinks = link->sink_pads;
-
-  g_assert (GST_IS_ELEMENT (src));
-  g_assert (GST_IS_ELEMENT (sink));
-
-  GST_CAT_INFO (GST_CAT_PIPELINE,
-      "linking %s:%s to %s:%s (%u/%u) with caps \"%" GST_PTR_FORMAT "\"",
-      GST_ELEMENT_NAME (src), link->src_name ? link->src_name : "(any)",
-      GST_ELEMENT_NAME (sink), link->sink_name ? link->sink_name : "(any)",
-      g_slist_length (srcs), g_slist_length (sinks), link->caps);
-
-  if (!srcs || !sinks) {
-    if (gst_element_link_pads_filtered (src,
-            srcs ? (const gchar *) srcs->data : NULL, sink,
-            sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
-      goto success;
-    } else {
-      if (gst_parse_perform_delayed_link (src,
-              srcs ? (const gchar *) srcs->data : NULL,
-              sink, sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
-        goto success;
-      } else {
-        goto error;
-      }
-    }
-  }
-  if (g_slist_length (link->src_pads) != g_slist_length (link->src_pads)) {
-    goto error;
-  }
-  while (srcs && sinks) {
-    const gchar *src_pad = (const gchar *) srcs->data;
-    const gchar *sink_pad = (const gchar *) sinks->data;
-
-    srcs = g_slist_next (srcs);
-    sinks = g_slist_next (sinks);
-    if (gst_element_link_pads_filtered (src, src_pad, sink, sink_pad,
-            link->caps)) {
-      continue;
-    } else {
-      if (gst_parse_perform_delayed_link (src, src_pad,
-              sink, sink_pad, link->caps)) {
-        continue;
-      } else {
-        goto error;
-      }
-    }
-  }
-
-success:
-  gst_parse_free_link (link);
-  return 0;
-
-error:
-  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-      _("could not link %s to %s"), GST_ELEMENT_NAME (src),
-      GST_ELEMENT_NAME (sink));
-  gst_parse_free_link (link);
-  return -1;
-}
-
-
-static int yyerror (void *scanner, graph_t * graph, const char *s);
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 521 "./grammar.y"
-{
-  gchar *s;
-  chain_t *c;
-  link_t *l;
-  GstElement *e;
-  GSList *p;
-  graph_t *g;
-}
-/* Line 187 of yacc.c.  */
-#line 651 "grammar.tab.c"
-YYSTYPE;
-
-# define yystype YYSTYPE        /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 664 "grammar.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h>           /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h>         /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e)               /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-     int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h>         /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h>         /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h>        /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032   /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
-#   include <stdlib.h>          /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T);        /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *);             /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  YYSIZE_T yyi;				\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)					\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack, Stack, yysize);				\
-	Stack = &yyptr->Stack;						\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  29
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   176
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  16
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  12
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  32
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  43
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   264
-
-#define YYTRANSLATE(YYX)						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] = {
-  0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 14, 2, 2, 2, 2, 2, 2,
-  10, 11, 2, 2, 12, 2, 13, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 15, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
-  5, 6, 7, 8, 9
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint8 yyprhs[] = {
-  0, 0, 3, 5, 8, 9, 12, 17, 22, 26,
-  31, 33, 36, 39, 43, 45, 48, 50, 52, 53,
-  57, 59, 62, 65, 67, 69, 72, 75, 78, 81,
-  84, 87, 88
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] = {
-  27, 0, -1, 4, -1, 17, 8, -1, -1, 18,
-  8, -1, 10, 18, 26, 11, -1, 5, 18, 26,
-  11, -1, 5, 18, 11, -1, 5, 18, 1, 11,
-  -1, 6, -1, 6, 21, -1, 12, 4, -1, 12,
-  4, 21, -1, 7, -1, 7, 21, -1, 22, -1,
-  20, -1, -1, 23, 9, 23, -1, 24, -1, 24,
-  25, -1, 25, 1, -1, 17, -1, 19, -1, 26,
-  26, -1, 26, 25, -1, 26, 1, -1, 24, 26,
-  -1, 3, 26, -1, 24, 3, -1, -1, 26, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] = {
-  0, 556, 556, 564, 568, 569, 571, 572, 575, 578,
-  583, 584, 588, 589, 592, 593, 596, 597, 598, 601,
-  614, 615, 616, 619, 624, 625, 660, 688, 689, 703,
-  723, 748, 751
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] = {
-  "$end", "error", "$undefined", "PARSE_URL", "IDENTIFIER", "BINREF",
-  "PADREF", "REF", "ASSIGNMENT", "LINK", "'('", "')'", "','", "'.'", "'!'",
-  "'='", "$accept", "element", "assignments", "bin", "pads", "padlist",
-  "reference", "linkpart", "link", "linklist", "chain", "graph", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] = {
-  0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
-  40, 41, 44, 46, 33, 61
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] = {
-  0, 16, 17, 17, 18, 18, 19, 19, 19, 19,
-  20, 20, 21, 21, 22, 22, 23, 23, 23, 24,
-  25, 25, 25, 26, 26, 26, 26, 26, 26, 26,
-  26, 27, 27
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] = {
-  0, 2, 1, 2, 0, 2, 4, 4, 3, 4,
-  1, 2, 2, 3, 1, 2, 1, 1, 0, 3,
-  1, 2, 2, 1, 1, 2, 2, 2, 2, 2,
-  2, 0, 1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] = {
-  18, 18, 2, 4, 10, 14, 4, 23, 24, 17,
-  16, 0, 18, 0, 0, 0, 0, 0, 11, 15,
-  18, 3, 18, 30, 0, 27, 20, 0, 0, 1,
-  0, 5, 8, 0, 12, 0, 19, 0, 22, 9,
-  7, 13, 6
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] = {
-  -1, 7, 16, 8, 9, 18, 10, 11, 26, 27,
-  28, 14
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -6
-static const yytype_int16 yypact[] = {
-  134, 158, -6, -6, -1, -1, -6, 6, -6, -6,
-  -6, 7, 166, 101, 18, 30, 89, 16, -6, -6,
-  2, -6, 129, 142, 42, -6, 150, 54, 66, -6,
-  11, -6, -6, 111, -1, 122, -6, 78, -6, -6,
-  -6, -6, -6
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] = {
-  -6, -6, 19, -6, -6, -5, -6, 10, 3, 12,
-  1, -6
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -33
-static const yytype_int8 yytable[] = {
-  19, 13, 15, 12, 12, 1, 2, 3, 4, 5,
-  31, 17, 6, 24, 21, 12, 22, 33, 29, 12,
-  34, 35, 39, 12, 15, 20, 12, 24, 0, 41,
-  -29, 25, 36, 1, 2, 3, 4, 5, 37, -18,
-  6, -29, -28, 25, 0, 1, 2, 3, 4, 5,
-  0, -18, 6, -28, -26, 38, 0, -26, -26, -26,
-  -26, -26, 0, -26, -26, -26, -25, 25, 0, 1,
-  2, 3, 4, 5, 0, -18, 6, -25, -21, 38,
-  0, -21, -21, -21, -21, -21, 0, -21, -21, -21,
-  30, 0, 1, 2, 3, 4, 5, 31, -18, 6,
-  32, -32, 25, 0, 1, 2, 3, 4, 5, 0,
-  -18, 6, 25, 0, 1, 2, 3, 4, 5, 0,
-  -18, 6, 40, 25, 0, 1, 2, 3, 4, 5,
-  0, -18, 6, 42, -31, 4, 5, 1, 2, 3,
-  4, 5, 0, 0, 6, 1, 2, 3, 4, 5,
-  0, -18, 6, 23, 2, 3, 4, 5, 0, -18,
-  6, 1, 2, 3, 4, 5, 0, 0, 6, 23,
-  2, 3, 4, 5, 0, 0, 6
-};
-
-static const yytype_int8 yycheck[] = {
-  5, 0, 1, 0, 1, 3, 4, 5, 6, 7,
-  8, 12, 10, 12, 8, 12, 9, 16, 0, 16,
-  4, 20, 11, 20, 23, 6, 23, 26, -1, 34,
-  0, 1, 22, 3, 4, 5, 6, 7, 26, 9,
-  10, 11, 0, 1, -1, 3, 4, 5, 6, 7,
-  -1, 9, 10, 11, 0, 1, -1, 3, 4, 5,
-  6, 7, -1, 9, 10, 11, 0, 1, -1, 3,
-  4, 5, 6, 7, -1, 9, 10, 11, 0, 1,
-  -1, 3, 4, 5, 6, 7, -1, 9, 10, 11,
-  1, -1, 3, 4, 5, 6, 7, 8, 9, 10,
-  11, 0, 1, -1, 3, 4, 5, 6, 7, -1,
-  9, 10, 1, -1, 3, 4, 5, 6, 7, -1,
-  9, 10, 11, 1, -1, 3, 4, 5, 6, 7,
-  -1, 9, 10, 11, 0, 6, 7, 3, 4, 5,
-  6, 7, -1, -1, 10, 3, 4, 5, 6, 7,
-  -1, 9, 10, 3, 4, 5, 6, 7, -1, 9,
-  10, 3, 4, 5, 6, 7, -1, -1, 10, 3,
-  4, 5, 6, 7, -1, -1, 10
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] = {
-  0, 3, 4, 5, 6, 7, 10, 17, 19, 20,
-  22, 23, 24, 26, 27, 26, 18, 12, 21, 21,
-  18, 8, 9, 3, 26, 1, 24, 25, 26, 0,
-  1, 8, 11, 26, 4, 26, 23, 25, 1, 11,
-  11, 21, 11
-};
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL		goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK (1);						\
-      goto yybackup;						\
-    }								\
-  else								\
-    {								\
-      yyerror (scanner, graph, YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)			\
-     fprintf (File, "%d.%d-%d.%d",			\
-	      (Loc).first_line, (Loc).first_column,	\
-	      (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h>            /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value, scanner, graph); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
- /*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-    static void
-yy_symbol_value_print (FILE * yyoutput, int yytype,
-    YYSTYPE const *const yyvaluep, void *scanner, graph_t * graph)
-#else
-    static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, graph)
-     FILE *yyoutput;
-     int yytype;
-     YYSTYPE const *const yyvaluep;
-     void *scanner;
-     graph_t *graph;
-#endif
-{
-  if (!yyvaluep)
-    return;
-  YYUSE (scanner);
-  YYUSE (graph);
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype) {
-    default:
-      break;
-  }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE * yyoutput, int yytype, YYSTYPE const *const yyvaluep,
-    void *scanner, graph_t * graph)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, scanner, graph)
-     FILE *yyoutput;
-     int yytype;
-     YYSTYPE const *const yyvaluep;
-     void *scanner;
-     graph_t *graph;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, graph);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 * bottom, yytype_int16 * top)
-#else
-static void
-yy_stack_print (bottom, top)
-     yytype_int16 *bottom;
-     yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE * yyvsp, int yyrule, void *scanner, graph_t * graph)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule, scanner, graph)
-     YYSTYPE *yyvsp;
-     int yyrule;
-     void *scanner;
-     graph_t *graph;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-      yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++) {
-    fprintf (stderr, "   $%d = ", yyi + 1);
-    yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-        &(yyvsp[(yyi + 1) - (yynrhs)])
-        , scanner, graph);
-    fprintf (stderr, "\n");
-  }
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule, scanner, graph); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-     const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-     char *yydest;
-     const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"') {
-    YYSIZE_T yyn = 0;
-    char const *yyp = yystr;
-
-    for (;;)
-      switch (*++yyp) {
-        case '\'':
-        case ',':
-          goto do_not_strip_quotes;
-
-        case '\\':
-          if (*++yyp != '\\')
-            goto do_not_strip_quotes;
-          /* Fall through.  */
-        default:
-          if (yyres)
-            yyres[yyn] = *yyp;
-          yyn++;
-          break;
-
-        case '"':
-          if (yyres)
-            yyres[yyn] = '\0';
-          return yyn;
-      }
-  do_not_strip_quotes:;
-  }
-
-  if (!yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (!(YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else {
-    int yytype = YYTRANSLATE (yychar);
-    YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-    YYSIZE_T yysize = yysize0;
-    YYSIZE_T yysize1;
-    int yysize_overflow = 0;
-    enum
-    { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-    char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-    int yyx;
-
-# if 0
-    /* This is so xgettext sees the translatable formats that are
-       constructed on the fly.  */
-    YY_ ("syntax error, unexpected %s");
-    YY_ ("syntax error, unexpected %s, expecting %s");
-    YY_ ("syntax error, unexpected %s, expecting %s or %s");
-    YY_ ("syntax error, unexpected %s, expecting %s or %s or %s");
-    YY_ ("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-    char *yyfmt;
-    char const *yyf;
-    static char const yyunexpected[] = "syntax error, unexpected %s";
-    static char const yyexpecting[] = ", expecting %s";
-    static char const yyor[] = " or %s";
-    char yyformat[sizeof yyunexpected
-        + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-            * (sizeof yyor - 1))];
-    char const *yyprefix = yyexpecting;
-
-    /* Start YYX at -YYN if negative to avoid negative indexes in
-       YYCHECK.  */
-    int yyxbegin = yyn < 0 ? -yyn : 0;
-
-    /* Stay within bounds of both yycheck and yytname.  */
-    int yychecklim = YYLAST - yyn + 1;
-    int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-    int yycount = 1;
-
-    yyarg[0] = yytname[yytype];
-    yyfmt = yystpcpy (yyformat, yyunexpected);
-
-    for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-      if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) {
-        if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) {
-          yycount = 1;
-          yysize = yysize0;
-          yyformat[sizeof yyunexpected - 1] = '\0';
-          break;
-        }
-        yyarg[yycount++] = yytname[yyx];
-        yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-        yysize_overflow |= (yysize1 < yysize);
-        yysize = yysize1;
-        yyfmt = yystpcpy (yyfmt, yyprefix);
-        yyprefix = yyor;
-      }
-
-    yyf = YY_ (yyformat);
-    yysize1 = yysize + yystrlen (yyf);
-    yysize_overflow |= (yysize1 < yysize);
-    yysize = yysize1;
-
-    if (yysize_overflow)
-      return YYSIZE_MAXIMUM;
-
-    if (yyresult) {
-      /* Avoid sprintf, as that infringes on the user's name space.
-         Don't have undefined behavior even if the translation
-         produced a string with the wrong number of "%s"s.  */
-      char *yyp = yyresult;
-      int yyi = 0;
-
-      while ((*yyp = *yyf) != '\0') {
-        if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyf += 2;
-        } else {
-          yyp++;
-          yyf++;
-        }
-      }
-    }
-    return yysize;
-  }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
- /*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-    static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE * yyvaluep, void *scanner,
-    graph_t * graph)
-#else
-    static void
-yydestruct (yymsg, yytype, yyvaluep, scanner, graph)
-     const char *yymsg;
-     int yytype;
-     YYSTYPE *yyvaluep;
-     void *scanner;
-     graph_t *graph;
-#endif
-{
-  YYUSE (yyvaluep);
-  YYUSE (scanner);
-  YYUSE (graph);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype) {
-
-    default:
-      break;
-  }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *scanner, graph_t * graph);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-     void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *scanner, graph_t * graph)
-#else
-int
-yyparse (scanner, graph)
-     void *scanner;
-     graph_t *graph;
-#endif
-#endif
-{
-  /* The look-ahead symbol.  */
-  int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-  YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-  int yynerrs;
-
-  int yystate;
-  int yyn;
-  int yyresult;
-
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;             /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
-yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
-yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp) {
-    /* Get the current used size of the three stacks, in elements.  */
-    YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-    {
-      /* Give user a chance to reallocate the stack.  Use copies of
-         these so that the &'s don't force the real ones into
-         memory.  */
-      YYSTYPE *yyvs1 = yyvs;
-      yytype_int16 *yyss1 = yyss;
-
-
-      /* Each stack pointer address is followed by the size of the
-         data in use in that stack, in bytes.  This used to be a
-         conditional around just the two extra args, but that might
-         be undefined if yyoverflow is a macro.  */
-      yyoverflow (YY_ ("memory exhausted"),
-          &yyss1, yysize * sizeof (*yyssp),
-          &yyvs1, yysize * sizeof (*yyvsp), &yystacksize);
-
-      yyss = yyss1;
-      yyvs = yyvs1;
-    }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-    goto yyexhaustedlab;
-# else
-    /* Extend the stack our own way.  */
-    if (YYMAXDEPTH <= yystacksize)
-      goto yyexhaustedlab;
-    yystacksize *= 2;
-    if (YYMAXDEPTH < yystacksize)
-      yystacksize = YYMAXDEPTH;
-
-    {
-      yytype_int16 *yyss1 = yyss;
-      union yyalloc *yyptr =
-          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-      if (!yyptr)
-        goto yyexhaustedlab;
-      YYSTACK_RELOCATE (yyss);
-      YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-      if (yyss1 != yyssa)
-        YYSTACK_FREE (yyss1);
-    }
-# endif
-#endif /* no yyoverflow */
-
-    yyssp = yyss + yysize - 1;
-    yyvsp = yyvs + yysize - 1;
-
-
-    YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-            (unsigned long int) yystacksize));
-
-    if (yyss + yystacksize - 1 <= yyssp)
-      YYABORT;
-  }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY) {
-    YYDPRINTF ((stderr, "Reading a token: "));
-    yychar = YYLEX;
-  }
-
-  if (yychar <= YYEOF) {
-    yychar = yytoken = YYEOF;
-    YYDPRINTF ((stderr, "Now at end of input.\n"));
-  } else {
-    yytoken = YYTRANSLATE (yychar);
-    YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-  }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0) {
-    if (yyn == 0 || yyn == YYTABLE_NINF)
-      goto yyerrlab;
-    yyn = -yyn;
-    goto yyreduce;
-  }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1 - yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn) {
-    case 2:
-#line 556 "./grammar.y"
-    {
-      (yyval.e) = gst_element_factory_make ((yyvsp[(1) - (1)].s), NULL);
-      if ((yyval.e) == NULL) {
-        SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            _("no element \"%s\""), (yyvsp[(1) - (1)].s));
-        gst_parse_strfree ((yyvsp[(1) - (1)].s));
-        YYERROR;
-      }
-      gst_parse_strfree ((yyvsp[(1) - (1)].s));
-      ;
-    }
-      break;
-
-    case 3:
-#line 564 "./grammar.y"
-    {
-      gst_parse_element_set ((yyvsp[(2) - (2)].s), (yyvsp[(1) - (2)].e), graph);
-      (yyval.e) = (yyvsp[(1) - (2)].e);
-      ;
-    }
-      break;
-
-    case 4:
-#line 568 "./grammar.y"
-    {
-      (yyval.p) = NULL;;
-    }
-      break;
-
-    case 5:
-#line 569 "./grammar.y"
-    {
-      (yyval.p) = g_slist_prepend ((yyvsp[(1) - (2)].p), (yyvsp[(2) - (2)].s));;
-    }
-      break;
-
-    case 6:
-#line 571 "./grammar.y"
-    {
-      GST_BIN_MAKE ((yyval.c), "bin", (yyvsp[(3) - (4)].c),
-          (yyvsp[(2) - (4)].p), FALSE);;
-    }
-      break;
-
-    case 7:
-#line 572 "./grammar.y"
-    {
-      GST_BIN_MAKE ((yyval.c), (yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].c),
-          (yyvsp[(2) - (4)].p), TRUE);
-      gst_parse_strfree ((yyvsp[(1) - (4)].s));
-      ;
-    }
-      break;
-
-    case 8:
-#line 575 "./grammar.y"
-    {
-      GST_BIN_MAKE ((yyval.c), (yyvsp[(1) - (3)].s), NULL, (yyvsp[(2) - (3)].p),
-          TRUE);
-      gst_parse_strfree ((yyvsp[(1) - (3)].s));
-      ;
-    }
-      break;
-
-    case 9:
-#line 578 "./grammar.y"
-    {
-      GST_BIN_MAKE ((yyval.c), (yyvsp[(1) - (4)].s), NULL, (yyvsp[(2) - (4)].p),
-          TRUE);
-      gst_parse_strfree ((yyvsp[(1) - (4)].s));
-      ;
-    }
-      break;
-
-    case 10:
-#line 583 "./grammar.y"
-    {
-      (yyval.p) = g_slist_prepend (NULL, (yyvsp[(1) - (1)].s));;
-    }
-      break;
-
-    case 11:
-#line 584 "./grammar.y"
-    {
-      (yyval.p) = (yyvsp[(2) - (2)].p);
-      (yyval.p) = g_slist_prepend ((yyval.p), (yyvsp[(1) - (2)].s));
-      ;
-    }
-      break;
-
-    case 12:
-#line 588 "./grammar.y"
-    {
-      (yyval.p) = g_slist_prepend (NULL, (yyvsp[(2) - (2)].s));;
-    }
-      break;
-
-    case 13:
-#line 589 "./grammar.y"
-    {
-      (yyval.p) = g_slist_prepend ((yyvsp[(3) - (3)].p), (yyvsp[(2) - (3)].s));;
-    }
-      break;
-
-    case 14:
-#line 592 "./grammar.y"
-    {
-      MAKE_REF ((yyval.l), (yyvsp[(1) - (1)].s), NULL);;
-    }
-      break;
-
-    case 15:
-#line 593 "./grammar.y"
-    {
-      MAKE_REF ((yyval.l), (yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].p));;
-    }
-      break;
-
-    case 16:
-#line 596 "./grammar.y"
-    {
-      (yyval.l) = (yyvsp[(1) - (1)].l);;
-    }
-      break;
-
-    case 17:
-#line 597 "./grammar.y"
-    {
-      MAKE_REF ((yyval.l), NULL, (yyvsp[(1) - (1)].p));;
-    }
-      break;
-
-    case 18:
-#line 598 "./grammar.y"
-    {
-      MAKE_REF ((yyval.l), NULL, NULL);;
-    }
-      break;
-
-    case 19:
-#line 601 "./grammar.y"
-    {
-      (yyval.l) = (yyvsp[(1) - (3)].l);
-      if ((yyvsp[(2) - (3)].s)) {
-        (yyval.l)->caps = gst_caps_from_string ((yyvsp[(2) - (3)].s));
-        if ((yyval.l)->caps == NULL)
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("could not parse caps \"%s\""), (yyvsp[(2) - (3)].s));
-        gst_parse_strfree ((yyvsp[(2) - (3)].s));
-      }
-      (yyval.l)->sink_name = (yyvsp[(3) - (3)].l)->src_name;
-      (yyval.l)->sink_pads = (yyvsp[(3) - (3)].l)->src_pads;
-      gst_parse_link_free ((yyvsp[(3) - (3)].l));
-      ;
-    }
-      break;
-
-    case 20:
-#line 614 "./grammar.y"
-    {
-      (yyval.p) = g_slist_prepend (NULL, (yyvsp[(1) - (1)].l));;
-    }
-      break;
-
-    case 21:
-#line 615 "./grammar.y"
-    {
-      (yyval.p) = g_slist_prepend ((yyvsp[(2) - (2)].p), (yyvsp[(1) - (2)].l));;
-    }
-      break;
-
-    case 22:
-#line 616 "./grammar.y"
-    {
-      (yyval.p) = (yyvsp[(1) - (2)].p);;
-    }
-      break;
-
-    case 23:
-#line 619 "./grammar.y"
-    {
-      (yyval.c) = gst_parse_chain_new ();
-      (yyval.c)->first = (yyval.c)->last = (yyvsp[(1) - (1)].e);
-      (yyval.c)->front = (yyval.c)->back = NULL;
-      (yyval.c)->elements = g_slist_prepend (NULL, (yyvsp[(1) - (1)].e));
-      ;
-    }
-      break;
-
-    case 24:
-#line 624 "./grammar.y"
-    {
-      (yyval.c) = (yyvsp[(1) - (1)].c);;
-    }
-      break;
-
-    case 25:
-#line 625 "./grammar.y"
-    {
-      if ((yyvsp[(1) - (2)].c)->back && (yyvsp[(2) - (2)].c)->front) {
-        if (!(yyvsp[(1) - (2)].c)->back->sink_name) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without source element"));
-          gst_parse_free_link ((yyvsp[(1) - (2)].c)->back);
-        } else {
-          ((graph_t *) graph)->links =
-              g_slist_prepend (((graph_t *) graph)->links,
-              (yyvsp[(1) - (2)].c)->back);
-        }
-        if (!(yyvsp[(2) - (2)].c)->front->src_name) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without sink element"));
-          gst_parse_free_link ((yyvsp[(2) - (2)].c)->front);
-        } else {
-          ((graph_t *) graph)->links =
-              g_slist_prepend (((graph_t *) graph)->links,
-              (yyvsp[(2) - (2)].c)->front);
-        }
-        (yyvsp[(1) - (2)].c)->back = NULL;
-      } else if ((yyvsp[(1) - (2)].c)->back) {
-        if (!(yyvsp[(1) - (2)].c)->back->sink_name) {
-          (yyvsp[(1) - (2)].c)->back->sink = (yyvsp[(2) - (2)].c)->first;
-        }
-      } else if ((yyvsp[(2) - (2)].c)->front) {
-        if (!(yyvsp[(2) - (2)].c)->front->src_name) {
-          (yyvsp[(2) - (2)].c)->front->src = (yyvsp[(1) - (2)].c)->last;
-        }
-        (yyvsp[(1) - (2)].c)->back = (yyvsp[(2) - (2)].c)->front;
-      }
-
-      if ((yyvsp[(1) - (2)].c)->back) {
-        ((graph_t *) graph)->links =
-            g_slist_prepend (((graph_t *) graph)->links,
-            (yyvsp[(1) - (2)].c)->back);
-      }
-      (yyvsp[(1) - (2)].c)->last = (yyvsp[(2) - (2)].c)->last;
-      (yyvsp[(1) - (2)].c)->back = (yyvsp[(2) - (2)].c)->back;
-      (yyvsp[(1) - (2)].c)->elements =
-          g_slist_concat ((yyvsp[(1) - (2)].c)->elements,
-          (yyvsp[(2) - (2)].c)->elements);
-      if ((yyvsp[(2) - (2)].c))
-        gst_parse_chain_free ((yyvsp[(2) - (2)].c));
-      (yyval.c) = (yyvsp[(1) - (2)].c);
-      ;
-    }
-      break;
-
-    case 26:
-#line 660 "./grammar.y"
-    {
-      GSList *walk;
-
-      if ((yyvsp[(1) - (2)].c)->back) {
-        (yyvsp[(2) - (2)].p) =
-            g_slist_prepend ((yyvsp[(2) - (2)].p), (yyvsp[(1) - (2)].c)->back);
-        (yyvsp[(1) - (2)].c)->back = NULL;
-      } else {
-        if (!((link_t *) (yyvsp[(2) - (2)].p)->data)->src_name) {
-          ((link_t *) (yyvsp[(2) - (2)].p)->data)->src =
-              (yyvsp[(1) - (2)].c)->last;
-        }
-      }
-      for (walk = (yyvsp[(2) - (2)].p); walk; walk = walk->next) {
-        link_t *link = (link_t *) walk->data;
-
-        if (!link->sink_name && walk->next) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without sink element"));
-          gst_parse_free_link (link);
-        } else if (!link->src_name && !link->src) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without source element"));
-          gst_parse_free_link (link);
-        } else {
-          if (walk->next) {
-            ((graph_t *) graph)->links =
-                g_slist_prepend (((graph_t *) graph)->links, link);
-          } else {
-            (yyvsp[(1) - (2)].c)->back = link;
-          }
-        }
-      }
-      g_slist_free ((yyvsp[(2) - (2)].p));
-      (yyval.c) = (yyvsp[(1) - (2)].c);
-      ;
-    }
-      break;
-
-    case 27:
-#line 688 "./grammar.y"
-    {
-      (yyval.c) = (yyvsp[(1) - (2)].c);;
-    }
-      break;
-
-    case 28:
-#line 689 "./grammar.y"
-    {
-      if ((yyvsp[(2) - (2)].c)->front) {
-        if (!(yyvsp[(2) - (2)].c)->front->src_name) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without source element"));
-          gst_parse_free_link ((yyvsp[(2) - (2)].c)->front);
-        } else {
-          ((graph_t *) graph)->links =
-              g_slist_prepend (((graph_t *) graph)->links,
-              (yyvsp[(2) - (2)].c)->front);
-        }
-      }
-      if (!(yyvsp[(1) - (2)].l)->sink_name) {
-        (yyvsp[(1) - (2)].l)->sink = (yyvsp[(2) - (2)].c)->first;
-      }
-      (yyvsp[(2) - (2)].c)->front = (yyvsp[(1) - (2)].l);
-      (yyval.c) = (yyvsp[(2) - (2)].c);
-      ;
-    }
-      break;
-
-    case 29:
-#line 703 "./grammar.y"
-    {
-      (yyval.c) = (yyvsp[(2) - (2)].c);
-      if ((yyval.c)->front) {
-        GstElement *element =
-            gst_element_make_from_uri (GST_URI_SRC, (yyvsp[(1) - (2)].s), NULL);
-        if (!element) {
-          SET_ERROR (((graph_t *) graph)->error,
-              GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-              _("no source element for URI \"%s\""), (yyvsp[(1) - (2)].s));
-        } else {
-          (yyval.c)->front->src = element;
-          ((graph_t *) graph)->links = g_slist_prepend (
-              ((graph_t *) graph)->links, (yyval.c)->front);
-          (yyval.c)->front = NULL;
-          (yyval.c)->elements = g_slist_prepend ((yyval.c)->elements, element);
-        }
-      } else {
-        SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-            _("no element to link URI \"%s\" to"), (yyvsp[(1) - (2)].s));
-      }
-      g_free ((yyvsp[(1) - (2)].s));
-      ;
-    }
-      break;
-
-    case 30:
-#line 723 "./grammar.y"
-    {
-      GstElement *element =
-          gst_element_make_from_uri (GST_URI_SINK, (yyvsp[(2) - (2)].s), NULL);
-      if (!element) {
-        SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            _("no sink element for URI \"%s\""), (yyvsp[(2) - (2)].s));
-        gst_parse_link_free ((yyvsp[(1) - (2)].l));
-        g_free ((yyvsp[(2) - (2)].s));
-        YYERROR;
-      } else if ((yyvsp[(1) - (2)].l)->sink_name
-          || (yyvsp[(1) - (2)].l)->sink_pads) {
-        gst_object_unref (element);
-        SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-            _("could not link sink element for URI \"%s\""),
-            (yyvsp[(2) - (2)].s));
-        gst_parse_link_free ((yyvsp[(1) - (2)].l));
-        g_free ((yyvsp[(2) - (2)].s));
-        YYERROR;
-      } else {
-        (yyval.c) = gst_parse_chain_new ();
-        (yyval.c)->first = (yyval.c)->last = element;
-        (yyval.c)->front = (yyvsp[(1) - (2)].l);
-        (yyval.c)->front->sink = element;
-        (yyval.c)->elements = g_slist_prepend (NULL, element);
-      }
-      g_free ((yyvsp[(2) - (2)].s));
-      ;
-    }
-      break;
-
-    case 31:
-#line 748 "./grammar.y"
-    {
-      SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY,
-          _("empty pipeline not allowed"));
-      (yyval.g) = (graph_t *) graph;
-      ;
-    }
-      break;
-
-    case 32:
-#line 751 "./grammar.y"
-    {
-      (yyval.g) = (graph_t *) graph;
-      if ((yyvsp[(1) - (1)].c)->front) {
-        if (!(yyvsp[(1) - (1)].c)->front->src_name) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without source element"));
-          gst_parse_free_link ((yyvsp[(1) - (1)].c)->front);
-        } else {
-          (yyval.g)->links =
-              g_slist_prepend ((yyval.g)->links, (yyvsp[(1) - (1)].c)->front);
-        }
-        (yyvsp[(1) - (1)].c)->front = NULL;
-      }
-      if ((yyvsp[(1) - (1)].c)->back) {
-        if (!(yyvsp[(1) - (1)].c)->back->sink_name) {
-          SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-              _("link without sink element"));
-          gst_parse_free_link ((yyvsp[(1) - (1)].c)->back);
-        } else {
-          (yyval.g)->links =
-              g_slist_prepend ((yyval.g)->links, (yyvsp[(1) - (1)].c)->back);
-        }
-        (yyvsp[(1) - (1)].c)->back = NULL;
-      }
-      (yyval.g)->chain = (yyvsp[(1) - (1)].c);
-      ;
-    }
-      break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 2252 "grammar.tab.c"
-    default:
-      break;
-  }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus) {
-    ++yynerrs;
-#if ! YYERROR_VERBOSE
-    yyerror (scanner, graph, YY_ ("syntax error"));
-#else
-    {
-      YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-
-      if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) {
-        YYSIZE_T yyalloc = 2 * yysize;
-
-        if (!(yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-          yyalloc = YYSTACK_ALLOC_MAXIMUM;
-        if (yymsg != yymsgbuf)
-          YYSTACK_FREE (yymsg);
-        yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-        if (yymsg)
-          yymsg_alloc = yyalloc;
-        else {
-          yymsg = yymsgbuf;
-          yymsg_alloc = sizeof yymsgbuf;
-        }
-      }
-
-      if (0 < yysize && yysize <= yymsg_alloc) {
-        (void) yysyntax_error (yymsg, yystate, yychar);
-        yyerror (scanner, graph, yymsg);
-      } else {
-        yyerror (scanner, graph, YY_ ("syntax error"));
-        if (yysize != 0)
-          goto yyexhaustedlab;
-      }
-    }
-#endif
-  }
-
-
-
-  if (yyerrstatus == 3) {
-    /* If just tried and failed to reuse look-ahead token after an
-       error, discard it.  */
-
-    if (yychar <= YYEOF) {
-      /* Return failure if at end of input.  */
-      if (yychar == YYEOF)
-        YYABORT;
-    } else {
-      yydestruct ("Error: discarding", yytoken, &yylval, scanner, graph);
-      yychar = YYEMPTY;
-    }
-  }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if ( /*CONSTCOND*/ 0)
-    goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;              /* Each real token shifted decrements this.  */
-
-  for (;;) {
-    yyn = yypact[yystate];
-    if (yyn != YYPACT_NINF) {
-      yyn += YYTERROR;
-      if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) {
-        yyn = yytable[yyn];
-        if (0 < yyn)
-          break;
-      }
-    }
-
-    /* Pop the current state because it cannot handle the error token.  */
-    if (yyssp == yyss)
-      YYABORT;
-
-
-    yydestruct ("Error: popping", yystos[yystate], yyvsp, scanner, graph);
-    YYPOPSTACK (1);
-    yystate = *yyssp;
-    YY_STACK_PRINT (yyss, yyssp);
-  }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (scanner, graph, YY_ ("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-    yydestruct ("Cleanup: discarding lookahead",
-        yytoken, &yylval, scanner, graph);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss) {
-    yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, scanner, graph);
-    YYPOPSTACK (1);
-  }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-#line 774 "./grammar.y"
-
-
-
-static int
-yyerror (void *scanner, graph_t * graph, const char *s)
-{
-  /* FIXME: This should go into the GError somehow, but how? */
-  GST_WARNING ("Error during parsing: %s", s);
-  return -1;
-}
-
-
-GstElement *
-_gst_parse_launch (const gchar * str, GError ** error)
-{
-  graph_t g;
-  gchar *dstr;
-  GSList *walk;
-  GstBin *bin = NULL;
-  GstElement *ret;
-  yyscan_t scanner;
-
-  g_return_val_if_fail (str != NULL, NULL);
-
-  g.chain = NULL;
-  g.links = NULL;
-  g.error = error;
-
-#ifdef __GST_PARSE_TRACE
-  GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
-  __strings = __chains = __links = 0;
-#endif /* __GST_PARSE_TRACE */
-
-  dstr = g_strdup (str);
-  _gst_parse_yylex_init (&scanner);
-  _gst_parse_yy_scan_string (dstr, scanner);
-
-#ifndef YYDEBUG
-  yydebug = 1;
-#endif
-
-  if (yyparse (scanner, &g) != 0) {
-    SET_ERROR (error, GST_PARSE_ERROR_SYNTAX,
-        "Unrecoverable syntax error while parsing pipeline %s", str);
-
-    _gst_parse_yylex_destroy (scanner);
-    g_free (dstr);
-
-    goto error1;
-  }
-  _gst_parse_yylex_destroy (scanner);
-  g_free (dstr);
-
-  GST_CAT_DEBUG (GST_CAT_PIPELINE, "got %u elements and %u links",
-      g.chain ? g_slist_length (g.chain->elements) : 0,
-      g_slist_length (g.links));
-
-  if (!g.chain) {
-    ret = NULL;
-  } else if (!(((chain_t *) g.chain)->elements->next)) {
-    /* only one toplevel element */
-    ret = (GstElement *) ((chain_t *) g.chain)->elements->data;
-    g_slist_free (((chain_t *) g.chain)->elements);
-    if (GST_IS_BIN (ret))
-      bin = GST_BIN (ret);
-    gst_parse_chain_free (g.chain);
-  } else {
-    /* put all elements in our bin */
-    bin = GST_BIN (gst_element_factory_make ("pipeline", NULL));
-    g_assert (bin);
-
-    for (walk = g.chain->elements; walk; walk = walk->next) {
-      if (walk->data != NULL)
-        gst_bin_add (bin, GST_ELEMENT (walk->data));
-    }
-
-    g_slist_free (g.chain->elements);
-    ret = GST_ELEMENT (bin);
-    gst_parse_chain_free (g.chain);
-  }
-
-  /* remove links */
-  for (walk = g.links; walk; walk = walk->next) {
-    link_t *l = (link_t *) walk->data;
-
-    if (!l->src) {
-      if (l->src_name) {
-        if (bin) {
-          l->src = gst_bin_get_by_name_recurse_up (bin, l->src_name);
-          if (l->src)
-            gst_object_unref (l->src);
-        } else {
-          l->src =
-              strcmp (GST_ELEMENT_NAME (ret), l->src_name) == 0 ? ret : NULL;
-        }
-      }
-      if (!l->src) {
-        SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            "No element named \"%s\" - omitting link", l->src_name);
-        gst_parse_free_link (l);
-        continue;
-      }
-    }
-    if (!l->sink) {
-      if (l->sink_name) {
-        if (bin) {
-          l->sink = gst_bin_get_by_name_recurse_up (bin, l->sink_name);
-          if (l->sink)
-            gst_object_unref (l->sink);
-        } else {
-          l->sink =
-              strcmp (GST_ELEMENT_NAME (ret), l->sink_name) == 0 ? ret : NULL;
-        }
-      }
-      if (!l->sink) {
-        SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            "No element named \"%s\" - omitting link", l->sink_name);
-        gst_parse_free_link (l);
-        continue;
-      }
-    }
-    gst_parse_perform_link (l, &g);
-  }
-  g_slist_free (g.links);
-
-out:
-#ifdef __GST_PARSE_TRACE
-  GST_CAT_DEBUG (GST_CAT_PIPELINE,
-      "TRACE: %u strings, %u chains and %u links left", __strings, __chains,
-      __links);
-  if (__strings || __chains || __links) {
-    g_warning ("TRACE: %u strings, %u chains and %u links left", __strings,
-        __chains, __links);
-  }
-#endif /* __GST_PARSE_TRACE */
-
-  return ret;
-
-error1:
-  if (g.chain) {
-    g_slist_foreach (g.chain->elements, (GFunc) gst_object_unref, NULL);
-    g_slist_free (g.chain->elements);
-    gst_parse_chain_free (g.chain);
-  }
-
-  g_slist_foreach (g.links, (GFunc) gst_parse_free_link, NULL);
-  g_slist_free (g.links);
-
-  if (error)
-    g_assert (*error);
-  ret = NULL;
-
-  goto out;
-}
--- a/gstreamer_core/gst/parse/grammar.tab.pre.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     PARSE_URL = 258,
-     IDENTIFIER = 259,
-     BINREF = 260,
-     PADREF = 261,
-     REF = 262,
-     ASSIGNMENT = 263,
-     LINK = 264
-   };
-#endif
-/* Tokens.  */
-#define PARSE_URL 258
-#define IDENTIFIER 259
-#define BINREF 260
-#define PADREF 261
-#define REF 262
-#define ASSIGNMENT 263
-#define LINK 264
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 521 "./grammar.y"
-{
-    gchar *s;
-    chain_t *c;
-    link_t *l;
-    GstElement *e;
-    GSList *p;
-    graph_t *g;
-}
-/* Line 1489 of yacc.c.  */
-#line 76 "grammar.tab.h"
-	YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
--- a/gstreamer_core/gst/parse/lex._gst_parse_yy.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/parse/lex._gst_parse_yy.c	Fri Apr 16 15:15:52 2010 +0300
@@ -15,7 +15,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 33
+#define YY_FLEX_SUBMINOR_VERSION 35
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -37,7 +37,7 @@
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
-#if __STDC_VERSION__ >= 199901L
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
 /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
  * if you want the limit (max/min) macros for int types. 
@@ -60,7 +60,6 @@
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -91,6 +90,8 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#endif /* ! C99 */
+
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -100,11 +101,12 @@
 
 #else	/* ! __cplusplus */
 
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
 
 #define YY_USE_CONST
 
-#endif	/* __STDC__ */
+#endif	/* defined (__STDC__) */
 #endif	/* ! __cplusplus */
 
 #ifdef YY_USE_CONST
@@ -140,8 +142,6 @@
 #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
 #define yy_flex_debug yyg->yy_flex_debug_r
 
-int _gst_parse_yylex_init (yyscan_t* scanner);
-
 /* Enter a start condition.  This macro really ought to take a parameter,
  * but we do it the disgusting crufty way forced on us by the ()-less
  * definition of BEGIN.
@@ -165,7 +165,15 @@
 
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
 #define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
 #endif
 
 /* The state buf must be large enough to hold one state per character in the main buffer.
@@ -199,14 +207,9 @@
 
 #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
 
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
 #ifndef YY_TYPEDEF_YY_SIZE_T
 #define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
+typedef size_t yy_size_t;
 #endif
 
 #ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -846,7 +849,7 @@
 /* links */
 
 #define YY_NO_INPUT 1
-#line 838 "lex._gst_parse_yy.c"
+#line 841 "lex._gst_parse_yy.c"
 
 #define INITIAL 0
 #define value 1
@@ -905,6 +908,10 @@
      * from bison output in section 1.*/
     #    define yylval yyg->yylval_r
     
+int _gst_parse_yylex_init (yyscan_t* scanner);
+
+int _gst_parse_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
 /* Accessor methods to globals.
    These are made visible to non-reentrant scanners for convenience. */
 
@@ -970,7 +977,12 @@
 
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
 #define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
 #endif
 
 /* Copy whatever the last rule matched to the standard output. */
@@ -978,7 +990,7 @@
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -1043,9 +1055,11 @@
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int _gst_parse_yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+extern int _gst_parse_yylex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
 
-#define YY_DECL int _gst_parse_yylex (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#define YY_DECL int _gst_parse_yylex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
 #endif /* !YY_DECL */
 
 /* Code executed at the beginning of each rule, after yytext and yyleng
@@ -1075,7 +1089,7 @@
 #line 71 "parse.l"
 
 
-#line 1067 "lex._gst_parse_yy.c"
+#line 1081 "lex._gst_parse_yy.c"
 
     yylval = yylval_param;
 
@@ -1221,7 +1235,7 @@
     gchar *c = yytext;
     PRINT ("LINK: %s", yytext);
     c++;
-    /*if (*c) {
+    if (*c) {
       while (g_ascii_isspace (*c)) c++;
       c = yylval->s = gst_parse_strdup (c);
       while (*c) c++;
@@ -1231,7 +1245,7 @@
       *++c = '\0';
     } else {
       yylval->s = NULL;
-    }*/
+    }
     BEGIN (INITIAL);
     return LINK;
 }
@@ -1272,7 +1286,7 @@
 #line 148 "parse.l"
 ECHO;
 	YY_BREAK
-#line 1264 "lex._gst_parse_yy.c"
+#line 1278 "lex._gst_parse_yy.c"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(value):
 	yyterminate();
@@ -1506,7 +1520,7 @@
 
 		/* Read in more data. */
 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
+			yyg->yy_n_chars, (size_t) num_to_read );
 
 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
 		}
@@ -1530,6 +1544,14 @@
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _gst_parse_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
 	yyg->yy_n_chars += number_to_move;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
@@ -1916,7 +1938,9 @@
 		yyg->yy_buffer_stack = (struct yy_buffer_state**)_gst_parse_yyalloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
-		
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in _gst_parse_yyensure_buffer_stack()" );
+								  
 		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 				
 		yyg->yy_buffer_stack_max = num_to_alloc;
@@ -1934,6 +1958,8 @@
 								(yyg->yy_buffer_stack,
 								num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in _gst_parse_yyensure_buffer_stack()" );
 
 		/* zero only the new slots.*/
 		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1978,7 +2004,7 @@
 
 /** Setup the input buffer state to scan a string. The next call to _gst_parse_yylex() will
  * scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
+ * @param yystr a NUL-terminated string to scan
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
@@ -1992,8 +2018,8 @@
 
 /** Setup the input buffer state to scan the given bytes. The next call to _gst_parse_yylex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  */
@@ -2240,6 +2266,42 @@
     return yy_init_globals ( *ptr_yy_globals );
 }
 
+/* _gst_parse_yylex_init_extra has the same functionality as _gst_parse_yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to _gst_parse_yyalloc in
+ * the yyextra field.
+ */
+
+int _gst_parse_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    _gst_parse_yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) _gst_parse_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    _gst_parse_yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
 static int yy_init_globals (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2418,7 +2480,7 @@
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 521 "./grammar.y"
+#line 566 "./grammar.y"
 {
     gchar *s;
     chain_t *c;
--- a/gstreamer_core/gst/parse/lex._gst_parse_yy.pre.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2528 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#ifdef __SYMBIAN32__
-#include "config.h"
-#else
-#include <config.h>
-#endif
-#endif
-
-
-#line 3 "lex._gst_parse_yy.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 34
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void *yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE _gst_parse_yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-#define YY_LESS_LINENO(n)
-
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = yyg->yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- * Given that the standard has decreed that size_t exists since 1989,
- * I guess we can afford to depend on it. Manoj.
- */
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-{
-  FILE *yy_input_file;
-
-  char *yy_ch_buf;              /* input buffer */
-  char *yy_buf_pos;             /* current position in input buffer */
-
-  /* Size of input buffer in bytes, not including room for EOB
-   * characters.
-   */
-  yy_size_t yy_buf_size;
-
-  /* Number of characters read into yy_ch_buf, not including EOB
-   * characters.
-   */
-  int yy_n_chars;
-
-  /* Whether we "own" the buffer - i.e., we know we created it,
-   * and can realloc() it to grow it, and should free() it to
-   * delete it.
-   */
-  int yy_is_our_buffer;
-
-  /* Whether this is an "interactive" input source; if so, and
-   * if we're using stdio for input, then we want to use getc()
-   * instead of fread(), to make sure we stop fetching input after
-   * each newline.
-   */
-  int yy_is_interactive;
-
-  /* Whether we're considered to be at the beginning of a line.
-   * If so, '^' rules will be active on the next match, otherwise
-   * not.
-   */
-  int yy_at_bol;
-
-  int yy_bs_lineno;   /**< The line count. */
-  int yy_bs_column;   /**< The column count. */
-
-  /* Whether to try to fill the input buffer when we reach the
-   * end of it.
-   */
-  int yy_fill_buffer;
-
-  int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-  /* When an EOF's been seen but there's still some text to process
-   * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-   * shouldn't try reading from the input source any more.  We might
-   * still have a bunch of tokens to match, though, because of
-   * possible backing-up.
-   *
-   * When we actually see the EOF, we change the status to "new"
-   * (via _gst_parse_yyrestart()), so that the user can continue scanning by
-   * just pointing yyin at a new input file.
-   */
-#define YY_BUFFER_EOF_PENDING 2
-
-};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-
-void _gst_parse_yyrestart (FILE * input_file, yyscan_t yyscanner);
-void _gst_parse_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer,
-    yyscan_t yyscanner);
-YY_BUFFER_STATE _gst_parse_yy_create_buffer (FILE * file, int size,
-    yyscan_t yyscanner);
-void _gst_parse_yy_delete_buffer (YY_BUFFER_STATE b, yyscan_t yyscanner);
-void _gst_parse_yy_flush_buffer (YY_BUFFER_STATE b, yyscan_t yyscanner);
-void _gst_parse_yypush_buffer_state (YY_BUFFER_STATE new_buffer,
-    yyscan_t yyscanner);
-void _gst_parse_yypop_buffer_state (yyscan_t yyscanner);
-
-static void _gst_parse_yyensure_buffer_stack (yyscan_t yyscanner);
-static void _gst_parse_yy_load_buffer_state (yyscan_t yyscanner);
-static void _gst_parse_yy_init_buffer (YY_BUFFER_STATE b, FILE * file,
-    yyscan_t yyscanner);
-
-#define YY_FLUSH_BUFFER _gst_parse_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE _gst_parse_yy_scan_buffer (char *base, yy_size_t size,
-    yyscan_t yyscanner);
-YY_BUFFER_STATE _gst_parse_yy_scan_string (yyconst char *yy_str,
-    yyscan_t yyscanner);
-YY_BUFFER_STATE _gst_parse_yy_scan_bytes (yyconst char *bytes, int len,
-    yyscan_t yyscanner);
-
-void *_gst_parse_yyalloc (yy_size_t, yyscan_t yyscanner);
-void *_gst_parse_yyrealloc (void *, yy_size_t, yyscan_t yyscanner);
-void _gst_parse_yyfree (void *, yyscan_t yyscanner);
-
-#define yy_new_buffer _gst_parse_yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        _gst_parse_yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            _gst_parse_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        _gst_parse_yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            _gst_parse_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define _gst_parse_yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner);
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state,
-    yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner);
-static void yy_fatal_error (yyconst char msg[], yyscan_t yyscanner);
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yyg->yytext_ptr = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
-	yyg->yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 11
-#define YY_END_OF_BUFFER 12
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-{
-  flex_int32_t yy_verify;
-  flex_int32_t yy_nxt;
-};
-static yyconst flex_int16_t yy_accept[177] = { 0,
-  0, 0, 0, 0, 12, 10, 9, 9, 6, 10,
-  8, 8, 10, 5, 5, 8, 11, 9, 0, 0,
-  0, 2, 7, 7, 7, 7, 0, 5, 0, 5,
-  3, 5, 0, 0, 2, 7, 0, 7, 7, 7,
-  0, 7, 7, 7, 0, 3, 0, 0, 4, 3,
-  0, 1, 0, 1, 1, 1, 0, 7, 0, 7,
-  7, 7, 0, 7, 7, 7, 3, 3, 3, 3,
-  7, 1, 0, 1, 1, 0, 1, 1, 1, 0,
-  0, 6, 0, 0, 0, 0, 7, 7, 7, 7,
-  7, 7, 1, 0, 1, 1, 0, 1, 1, 0,
-
-  0, 0, 0, 0, 0, 0, 0, 0, 6, 0,
-  0, 0, 7, 0, 7, 7, 0, 7, 7, 7,
-  1, 1, 0, 0, 0, 7, 0, 7, 7, 0,
-  7, 7, 0, 0, 7, 7, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0
-};
-
-static yyconst flex_int32_t yy_ec[256] = { 0,
-  1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
-  2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 2, 4, 5, 1, 1, 6, 1, 7, 8,
-  9, 1, 10, 11, 12, 13, 14, 12, 12, 12,
-  12, 12, 12, 12, 12, 12, 12, 15, 16, 1,
-  17, 1, 1, 1, 18, 18, 18, 18, 18, 18,
-  18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-  18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-  1, 19, 1, 1, 20, 1, 18, 18, 18, 21,
-
-  21, 21, 18, 18, 21, 18, 18, 18, 18, 21,
-  18, 18, 18, 21, 18, 21, 18, 18, 18, 18,
-  18, 18, 22, 1, 22, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1
-};
-
-static yyconst flex_int32_t yy_meta[23] = { 0,
-  1, 2, 3, 1, 1, 4, 1, 1, 1, 5,
-  5, 6, 7, 8, 9, 1, 10, 6, 1, 4,
-  6, 1
-};
-
-static yyconst flex_int16_t yy_base[216] = { 0,
-  0, 0, 0, 0, 203, 1331, 21, 23, 25, 180,
-  1331, 15, 25, 43, 167, 152, 1331, 32, 35, 149,
-  43, 0, 126, 63, 81, 38, 99, 115, 125, 0,
-  131, 151, 167, 55, 0, 185, 66, 105, 203, 221,
-  24, 239, 95, 40, 67, 257, 89, 78, 1331, 273,
-  81, 75, 293, 311, 329, 70, 348, 1331, 74, 369,
-  387, 405, 32, 423, 441, 459, 0, 0, 0, 60,
-  85, 477, 86, 94, 495, 80, 104, 106, 96, 108,
-  109, 1331, 513, 0, 108, 531, 117, 112, 33, 549,
-  567, 136, 1331, 132, 585, 154, 128, 603, 156, 159,
-
-  164, 621, 639, 659, 158, 33, 171, 179, 181, 0,
-  0, 0, 677, 143, 176, 695, 177, 207, 22, 148,
-  193, 194, 0, 213, 199, 1331, 202, 713, 216, 218,
-  731, 228, 227, 750, 224, 225, 772, 243, 245, 793,
-  0, 811, 250, 255, 829, 0, 847, 269, 285, 865,
-  883, 903, 287, 289, 297, 0, 0, 0, 299, 307,
-  921, 939, 959, 317, 321, 322, 0, 0, 0, 0,
-  373, 0, 377, 0, 0, 1331, 978, 987, 993, 998,
-  1003, 1012, 1022, 1032, 1041, 1047, 1056, 1066, 1076, 1086,
-  1096, 1106, 1116, 1126, 1133, 1142, 1152, 1162, 1172, 1182,
-
-  1192, 1201, 1207, 1217, 1227, 1237, 1242, 1250, 1260, 1270,
-  1280, 1290, 1300, 1310, 1320
-};
-
-static yyconst flex_int16_t yy_def[216] = { 0,
-  176, 1, 177, 177, 176, 176, 176, 176, 178, 176,
-  176, 176, 179, 176, 14, 176, 176, 176, 178, 180,
-  179, 181, 179, 182, 183, 184, 176, 185, 186, 14,
-  176, 185, 187, 176, 181, 182, 188, 179, 189, 183,
-  190, 191, 179, 184, 176, 176, 176, 176, 176, 176,
-  176, 187, 187, 192, 193, 194, 176, 176, 188, 182,
-  182, 189, 190, 183, 183, 191, 195, 195, 50, 195,
-  196, 192, 197, 198, 193, 199, 200, 187, 194, 57,
-  57, 176, 201, 57, 202, 203, 188, 190, 196, 204,
-  205, 206, 176, 197, 192, 198, 199, 193, 200, 57,
-
-  57, 201, 57, 203, 202, 207, 57, 57, 57, 102,
-  103, 104, 204, 208, 209, 205, 210, 211, 196, 206,
-  197, 199, 103, 103, 176, 176, 208, 204, 209, 210,
-  205, 211, 57, 176, 208, 210, 176, 134, 134, 212,
-  134, 213, 137, 137, 214, 137, 215, 134, 134, 212,
-  134, 213, 134, 134, 134, 150, 151, 152, 137, 137,
-  214, 137, 215, 137, 137, 137, 161, 162, 163, 151,
-  151, 162, 162, 134, 137, 0, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176
-};
-
-static yyconst flex_int16_t yy_nxt[1354] = { 0,
-  6, 7, 8, 9, 10, 6, 6, 11, 11, 6,
-  11, 6, 12, 13, 6, 11, 11, 14, 6, 10,
-  15, 16, 18, 18, 18, 18, 19, 19, 21, 24,
-  58, 25, 22, 18, 18, 22, 19, 19, 88, 23,
-  92, 23, 63, 26, 27, 27, 125, 24, 28, 25,
-  63, 92, 29, 29, 30, 31, 44, 32, 44, 33,
-  30, 26, 28, 30, 37, 37, 57, 38, 48, 48,
-  58, 52, 57, 51, 49, 57, 176, 176, 87, 48,
-  48, 39, 41, 41, 59, 49, 93, 38, 79, 90,
-  93, 91, 59, 56, 71, 72, 73, 52, 97, 42,
-
-  27, 27, 51, 92, 94, 75, 76, 176, 176, 105,
-  105, 45, 96, 26, 79, 33, 27, 27, 58, 80,
-  80, 58, 99, 26, 56, 80, 80, 46, 80, 80,
-  63, 33, 48, 48, 122, 59, 121, 89, 49, 47,
-  29, 29, 29, 29, 26, 47, 97, 126, 50, 89,
-  94, 50, 27, 27, 120, 72, 73, 75, 76, 105,
-  105, 127, 34, 46, 51, 21, 120, 33, 53, 53,
-  80, 54, 96, 55, 99, 80, 80, 113, 114, 80,
-  21, 80, 80, 126, 80, 56, 37, 37, 80, 38,
-  80, 80, 80, 21, 129, 130, 80, 93, 80, 80,
-
-  93, 80, 176, 39, 36, 37, 135, 61, 116, 117,
-  134, 94, 97, 176, 81, 81, 134, 113, 114, 134,
-  127, 62, 41, 41, 136, 132, 133, 38, 126, 116,
-  117, 126, 176, 176, 129, 176, 130, 176, 137, 42,
-  40, 41, 127, 130, 137, 65, 132, 137, 176, 176,
-  176, 176, 176, 176, 138, 176, 138, 66, 48, 48,
-  138, 143, 138, 138, 49, 138, 143, 143, 176, 176,
-  143, 176, 143, 176, 67, 143, 176, 67, 68, 176,
-  138, 176, 29, 29, 69, 29, 138, 70, 176, 138,
-  69, 176, 68, 69, 53, 53, 138, 54, 138, 55,
-
-  138, 176, 138, 176, 138, 138, 138, 138, 138, 138,
-  143, 56, 73, 73, 138, 52, 143, 138, 143, 143,
-  176, 176, 176, 176, 143, 176, 176, 143, 143, 74,
-  76, 76, 143, 143, 143, 52, 176, 143, 143, 143,
-  176, 143, 143, 176, 176, 176, 176, 77, 80, 81,
-  81, 82, 80, 80, 80, 80, 80, 80, 83, 84,
-  80, 80, 80, 85, 80, 84, 86, 80, 84, 80,
-  37, 37, 176, 38, 139, 139, 176, 176, 144, 144,
-  176, 176, 176, 176, 176, 176, 174, 39, 37, 37,
-  175, 38, 176, 176, 176, 176, 176, 176, 176, 176,
-
-  176, 176, 176, 176, 176, 39, 36, 37, 176, 61,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 62, 41, 41, 176, 176, 176, 38,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 42, 41, 41, 176, 176, 176, 38, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 42,
-  40, 41, 176, 176, 176, 65, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 66, 73, 73,
-  176, 52, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 74, 76, 76, 176, 176,
-
-  176, 52, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 77, 101, 101, 82, 176, 176, 176,
-  176, 176, 176, 102, 176, 176, 176, 176, 103, 176,
-  176, 104, 108, 81, 109, 176, 176, 176, 176, 176,
-  176, 110, 176, 176, 176, 176, 111, 176, 176, 112,
-  114, 114, 176, 89, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 115, 117, 117,
-  176, 176, 176, 89, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 118, 73, 73, 176, 52,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-
-  176, 176, 176, 74, 76, 76, 176, 176, 176, 52,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 77, 101, 101, 82, 176, 176, 176, 176, 176,
-  176, 102, 176, 176, 176, 176, 103, 176, 176, 104,
-  123, 123, 176, 176, 176, 176, 176, 176, 176, 176,
-  124, 176, 176, 176, 176, 176, 124, 176, 176, 124,
-  108, 81, 109, 176, 176, 176, 176, 176, 176, 110,
-  176, 176, 176, 176, 111, 176, 176, 112, 114, 114,
-  176, 89, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 115, 117, 117, 176, 176,
-
-  176, 89, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 118, 114, 114, 176, 89, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 115, 117, 117, 176, 176, 176, 89, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 118,
-  138, 139, 139, 82, 138, 138, 138, 138, 138, 138,
-  140, 141, 138, 138, 138, 85, 138, 141, 142, 138,
-  141, 138, 143, 144, 144, 82, 143, 143, 143, 143,
-  143, 143, 145, 146, 143, 143, 143, 85, 143, 146,
-  147, 143, 146, 143, 149, 149, 82, 176, 176, 176,
-
-  176, 176, 176, 150, 176, 176, 176, 176, 151, 176,
-  176, 152, 154, 139, 155, 176, 176, 176, 176, 176,
-  176, 156, 176, 176, 176, 176, 157, 176, 176, 158,
-  160, 160, 82, 176, 176, 176, 176, 176, 176, 161,
-  176, 176, 176, 176, 162, 176, 176, 163, 165, 144,
-  166, 176, 176, 176, 176, 176, 176, 167, 176, 176,
-  176, 176, 168, 176, 176, 169, 149, 149, 82, 176,
-  176, 176, 176, 176, 176, 150, 176, 176, 176, 176,
-  151, 176, 176, 152, 170, 170, 176, 176, 176, 176,
-  176, 176, 176, 176, 171, 176, 176, 176, 176, 176,
-
-  171, 176, 176, 171, 154, 139, 155, 176, 176, 176,
-  176, 176, 176, 156, 176, 176, 176, 176, 157, 176,
-  176, 158, 160, 160, 82, 176, 176, 176, 176, 176,
-  176, 161, 176, 176, 176, 176, 162, 176, 176, 163,
-  172, 172, 176, 176, 176, 176, 176, 176, 176, 176,
-  173, 176, 176, 176, 176, 176, 173, 176, 176, 173,
-  165, 144, 166, 176, 176, 176, 176, 176, 176, 167,
-  176, 176, 176, 176, 168, 176, 176, 169, 17, 17,
-  17, 17, 17, 17, 17, 17, 17, 17, 20, 20,
-  176, 176, 20, 23, 176, 176, 23, 23, 23, 23,
-
-  23, 23, 23, 20, 176, 20, 35, 176, 35, 176,
-  176, 35, 36, 36, 36, 36, 36, 36, 36, 36,
-  36, 36, 40, 40, 40, 40, 40, 40, 40, 40,
-  40, 40, 43, 43, 176, 43, 43, 43, 43, 43,
-  43, 43, 28, 28, 28, 176, 28, 28, 176, 28,
-  28, 29, 29, 29, 176, 29, 52, 52, 52, 52,
-  52, 52, 52, 52, 52, 52, 37, 37, 37, 37,
-  37, 37, 37, 37, 37, 37, 60, 60, 60, 60,
-  60, 60, 60, 60, 60, 60, 41, 41, 41, 41,
-  41, 41, 41, 41, 41, 41, 64, 64, 64, 64,
-
-  64, 64, 64, 64, 64, 64, 72, 72, 72, 72,
-  72, 72, 72, 72, 72, 72, 75, 75, 75, 75,
-  75, 75, 75, 75, 75, 75, 78, 78, 176, 78,
-  78, 78, 78, 78, 78, 78, 68, 176, 68, 176,
-  176, 68, 89, 176, 176, 89, 89, 89, 89, 89,
-  89, 89, 73, 73, 73, 73, 73, 73, 73, 73,
-  73, 73, 95, 95, 95, 95, 95, 95, 95, 95,
-  95, 95, 76, 76, 76, 76, 76, 76, 76, 76,
-  76, 76, 98, 98, 98, 98, 98, 98, 98, 98,
-  98, 98, 100, 100, 100, 100, 100, 100, 100, 100,
-
-  100, 100, 106, 106, 176, 176, 106, 107, 107, 107,
-  107, 107, 107, 107, 107, 107, 107, 113, 113, 113,
-  113, 113, 113, 113, 113, 113, 113, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 119, 119, 176,
-  119, 119, 119, 119, 119, 119, 119, 106, 176, 106,
-  114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
-  128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-  117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
-  131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
-  148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
-
-  153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
-  159, 159, 159, 159, 159, 159, 159, 159, 159, 159,
-  164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
-  5, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176
-};
-
-static yyconst flex_int16_t yy_chk[1354] = { 0,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  1, 1, 7, 7, 8, 8, 9, 9, 12, 13,
-  41, 13, 12, 18, 18, 12, 19, 19, 63, 26,
-  119, 44, 41, 13, 14, 14, 106, 21, 14, 21,
-  63, 89, 14, 14, 14, 14, 26, 14, 44, 14,
-  14, 21, 14, 14, 24, 24, 34, 24, 45, 45,
-  37, 56, 34, 70, 45, 34, 52, 52, 59, 48,
-  48, 24, 25, 25, 37, 48, 76, 25, 56, 71,
-  73, 71, 59, 52, 51, 74, 74, 79, 76, 25,
-
-  27, 27, 47, 71, 73, 77, 77, 78, 78, 85,
-  85, 27, 74, 43, 79, 27, 28, 28, 88, 80,
-  81, 87, 77, 38, 78, 80, 81, 28, 80, 81,
-  88, 28, 31, 31, 97, 87, 94, 92, 31, 29,
-  31, 31, 31, 31, 23, 31, 97, 114, 31, 120,
-  94, 31, 32, 32, 92, 96, 96, 99, 99, 105,
-  105, 114, 20, 32, 32, 16, 120, 32, 33, 33,
-  100, 33, 96, 33, 99, 101, 100, 115, 115, 100,
-  15, 101, 107, 117, 101, 33, 36, 36, 107, 36,
-  108, 107, 109, 10, 115, 117, 108, 121, 109, 108,
-
-  122, 109, 5, 36, 39, 39, 127, 39, 118, 118,
-  125, 121, 122, 0, 124, 124, 125, 129, 129, 125,
-  127, 39, 40, 40, 130, 118, 124, 40, 135, 132,
-  132, 136, 0, 0, 129, 0, 130, 0, 133, 40,
-  42, 42, 135, 136, 133, 42, 132, 133, 0, 0,
-  0, 0, 0, 0, 138, 0, 139, 42, 46, 46,
-  138, 143, 139, 138, 46, 139, 144, 143, 0, 0,
-  143, 0, 144, 0, 46, 144, 0, 46, 50, 0,
-  148, 0, 50, 50, 50, 50, 148, 50, 0, 148,
-  50, 0, 50, 50, 53, 53, 149, 53, 153, 53,
-
-  154, 0, 149, 0, 153, 149, 154, 153, 155, 154,
-  159, 53, 54, 54, 155, 54, 159, 155, 160, 159,
-  0, 0, 0, 0, 160, 0, 0, 160, 164, 54,
-  55, 55, 165, 166, 164, 55, 0, 164, 165, 166,
-  0, 165, 166, 0, 0, 0, 0, 55, 57, 57,
-  57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-  57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-  60, 60, 0, 60, 171, 171, 0, 0, 173, 173,
-  0, 0, 0, 0, 0, 0, 171, 60, 61, 61,
-  173, 61, 0, 0, 0, 0, 0, 0, 0, 0,
-
-  0, 0, 0, 0, 0, 61, 62, 62, 0, 62,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 62, 64, 64, 0, 0, 0, 64,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 64, 65, 65, 0, 0, 0, 65, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 65,
-  66, 66, 0, 0, 0, 66, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 66, 72, 72,
-  0, 72, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 72, 75, 75, 0, 0,
-
-  0, 75, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 75, 83, 83, 83, 0, 0, 0,
-  0, 0, 0, 83, 0, 0, 0, 0, 83, 0,
-  0, 83, 86, 86, 86, 0, 0, 0, 0, 0,
-  0, 86, 0, 0, 0, 0, 86, 0, 0, 86,
-  90, 90, 0, 90, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 90, 91, 91,
-  0, 0, 0, 91, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 91, 95, 95, 0, 95,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-  0, 0, 0, 95, 98, 98, 0, 0, 0, 98,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 98, 102, 102, 102, 0, 0, 0, 0, 0,
-  0, 102, 0, 0, 0, 0, 102, 0, 0, 102,
-  103, 103, 0, 0, 0, 0, 0, 0, 0, 0,
-  103, 0, 0, 0, 0, 0, 103, 0, 0, 103,
-  104, 104, 104, 0, 0, 0, 0, 0, 0, 104,
-  0, 0, 0, 0, 104, 0, 0, 104, 113, 113,
-  0, 113, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 113, 116, 116, 0, 0,
-
-  0, 116, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 116, 128, 128, 0, 128, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 128, 131, 131, 0, 0, 0, 131, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 131,
-  134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
-  134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
-  134, 134, 137, 137, 137, 137, 137, 137, 137, 137,
-  137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
-  137, 137, 137, 137, 140, 140, 140, 0, 0, 0,
-
-  0, 0, 0, 140, 0, 0, 0, 0, 140, 0,
-  0, 140, 142, 142, 142, 0, 0, 0, 0, 0,
-  0, 142, 0, 0, 0, 0, 142, 0, 0, 142,
-  145, 145, 145, 0, 0, 0, 0, 0, 0, 145,
-  0, 0, 0, 0, 145, 0, 0, 145, 147, 147,
-  147, 0, 0, 0, 0, 0, 0, 147, 0, 0,
-  0, 0, 147, 0, 0, 147, 150, 150, 150, 0,
-  0, 0, 0, 0, 0, 150, 0, 0, 0, 0,
-  150, 0, 0, 150, 151, 151, 0, 0, 0, 0,
-  0, 0, 0, 0, 151, 0, 0, 0, 0, 0,
-
-  151, 0, 0, 151, 152, 152, 152, 0, 0, 0,
-  0, 0, 0, 152, 0, 0, 0, 0, 152, 0,
-  0, 152, 161, 161, 161, 0, 0, 0, 0, 0,
-  0, 161, 0, 0, 0, 0, 161, 0, 0, 161,
-  162, 162, 0, 0, 0, 0, 0, 0, 0, 0,
-  162, 0, 0, 0, 0, 0, 162, 0, 0, 162,
-  163, 163, 163, 0, 0, 0, 0, 0, 0, 163,
-  0, 0, 0, 0, 163, 0, 0, 163, 177, 177,
-  177, 177, 177, 177, 177, 177, 177, 177, 178, 178,
-  0, 0, 178, 179, 0, 0, 179, 179, 179, 179,
-
-  179, 179, 179, 180, 0, 180, 181, 0, 181, 0,
-  0, 181, 182, 182, 182, 182, 182, 182, 182, 182,
-  182, 182, 183, 183, 183, 183, 183, 183, 183, 183,
-  183, 183, 184, 184, 0, 184, 184, 184, 184, 184,
-  184, 184, 185, 185, 185, 0, 185, 185, 0, 185,
-  185, 186, 186, 186, 0, 186, 187, 187, 187, 187,
-  187, 187, 187, 187, 187, 187, 188, 188, 188, 188,
-  188, 188, 188, 188, 188, 188, 189, 189, 189, 189,
-  189, 189, 189, 189, 189, 189, 190, 190, 190, 190,
-  190, 190, 190, 190, 190, 190, 191, 191, 191, 191,
-
-  191, 191, 191, 191, 191, 191, 192, 192, 192, 192,
-  192, 192, 192, 192, 192, 192, 193, 193, 193, 193,
-  193, 193, 193, 193, 193, 193, 194, 194, 0, 194,
-  194, 194, 194, 194, 194, 194, 195, 0, 195, 0,
-  0, 195, 196, 0, 0, 196, 196, 196, 196, 196,
-  196, 196, 197, 197, 197, 197, 197, 197, 197, 197,
-  197, 197, 198, 198, 198, 198, 198, 198, 198, 198,
-  198, 198, 199, 199, 199, 199, 199, 199, 199, 199,
-  199, 199, 200, 200, 200, 200, 200, 200, 200, 200,
-  200, 200, 201, 201, 201, 201, 201, 201, 201, 201,
-
-  201, 201, 202, 202, 0, 0, 202, 203, 203, 203,
-  203, 203, 203, 203, 203, 203, 203, 204, 204, 204,
-  204, 204, 204, 204, 204, 204, 204, 205, 205, 205,
-  205, 205, 205, 205, 205, 205, 205, 206, 206, 0,
-  206, 206, 206, 206, 206, 206, 206, 207, 0, 207,
-  208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-  209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
-  210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
-  211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
-  212, 212, 212, 212, 212, 212, 212, 212, 212, 212,
-
-  213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
-  214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
-  215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-  176, 176, 176
-};
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "parse.l"
-#line 2 "parse.l"
-#include <math.h>
-#include <string.h>
-
-#include <glib/gprintf.h>
-
-#include "../gst_private.h"
-
-#include "types.h"
-#include "../gstinfo.h"
-#include "../gsturi.h"
-#include "grammar.tab.h"
-
-/* Override the default ECHO so as to avoid fortify warnings. Ignore the
-   embedded-NUL case for now. We know yytext is NUL-terminated. */
-#define ECHO g_fprintf(yyout, "%s", yytext)
-
-#ifdef G_HAVE_ISO_VARARGS
-#define PRINT(...) GST_CAT_DEBUG (GST_CAT_PIPELINE, "flex: " __VA_ARGS__)
-#elif defined(G_HAVE_GNUC_VARARGS)
-#define PRINT(args...) GST_CAT_DEBUG (GST_CAT_PIPELINE, "flex: " args)
-#else
-static inline void
-PRINT (const char *format, ...)
-{
-  va_list varargs;
-
-  va_start (varargs, format);
-  GST_CAT_LEVEL_LOG_valist (GST_CAT_PIPELINE, GST_LEVEL_DEBUG, NULL,
-      format, varargs);
-  va_end (varargs);
-}
-#endif
-
-/* we must do this here, because nearly everything matches a {_string} */
-/* get pad/element references and stuff with dots right */
-/* links */
-
-#define YY_NO_INPUT 1
-#line 839 "lex._gst_parse_yy.c"
-
-#define INITIAL 0
-#define value 1
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-{
-
-  /* User-defined. Not touched by flex. */
-  YY_EXTRA_TYPE yyextra_r;
-
-  /* The rest are the same as the globals declared in the non-reentrant scanner. */
-  FILE *yyin_r, *yyout_r;
-  size_t yy_buffer_stack_top;   /**< index of top of stack. */
-  size_t yy_buffer_stack_max;   /**< capacity of stack. */
-  YY_BUFFER_STATE *yy_buffer_stack;    /**< Stack as an array. */
-  char yy_hold_char;
-  int yy_n_chars;
-  int yyleng_r;
-  char *yy_c_buf_p;
-  int yy_init;
-  int yy_start;
-  int yy_did_buffer_switch_on_eof;
-  int yy_start_stack_ptr;
-  int yy_start_stack_depth;
-  int *yy_start_stack;
-  yy_state_type yy_last_accepting_state;
-  char *yy_last_accepting_cpos;
-
-  int yylineno_r;
-  int yy_flex_debug_r;
-
-  char *yytext_r;
-  int yy_more_flag;
-  int yy_more_len;
-
-  YYSTYPE *yylval_r;
-
-};                              /* end struct yyguts_t */
-#ifdef __SYMBIAN32__
-#include<glib_global.h>
-#endif
-
-static int yy_init_globals (yyscan_t yyscanner);
-
-    /* This must go here because YYSTYPE and YYLTYPE are included
-     * from bison output in section 1.*/
-#    define yylval yyg->yylval_r
-
-int _gst_parse_yylex_init (yyscan_t * scanner);
-
-int _gst_parse_yylex_init_extra (YY_EXTRA_TYPE user_defined,
-    yyscan_t * scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int _gst_parse_yylex_destroy (yyscan_t yyscanner);
-
-int _gst_parse_yyget_debug (yyscan_t yyscanner);
-
-void _gst_parse_yyset_debug (int debug_flag, yyscan_t yyscanner);
-
-YY_EXTRA_TYPE _gst_parse_yyget_extra (yyscan_t yyscanner);
-
-void _gst_parse_yyset_extra (YY_EXTRA_TYPE user_defined, yyscan_t yyscanner);
-
-FILE *_gst_parse_yyget_in (yyscan_t yyscanner);
-
-void _gst_parse_yyset_in (FILE * in_str, yyscan_t yyscanner);
-
-FILE *_gst_parse_yyget_out (yyscan_t yyscanner);
-
-void _gst_parse_yyset_out (FILE * out_str, yyscan_t yyscanner);
-
-int _gst_parse_yyget_leng (yyscan_t yyscanner);
-
-char *_gst_parse_yyget_text (yyscan_t yyscanner);
-
-int _gst_parse_yyget_lineno (yyscan_t yyscanner);
-
-void _gst_parse_yyset_lineno (int line_number, yyscan_t yyscanner);
-
-YYSTYPE *_gst_parse_yyget_lval (yyscan_t yyscanner);
-
-void _gst_parse_yyset_lval (YYSTYPE * yylval_param, yyscan_t yyscanner);
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int _gst_parse_yywrap (yyscan_t yyscanner);
-#else
-extern int _gst_parse_yywrap (yyscan_t yyscanner);
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *, yyconst char *, int, yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char *, yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner);
-#else
-static int input (yyscan_t yyscanner);
-#endif
-
-#endif
-
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		int n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int _gst_parse_yylex (YYSTYPE * yylval_param, yyscan_t yyscanner);
-
-#define YY_DECL int _gst_parse_yylex \
-               (YYSTYPE * yylval_param , yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL {
-  register yy_state_type yy_current_state;
-  register char *yy_cp, *yy_bp;
-  register int yy_act;
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-#line 71 "parse.l"
-
-
-#line 1074 "lex._gst_parse_yy.c"
-
-  yylval = yylval_param;
-
-  if (!yyg->yy_init) {
-    yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-    YY_USER_INIT;
-#endif
-
-    if (!yyg->yy_start)
-      yyg->yy_start = 1;        /* first start state */
-
-    if (!yyin)
-      yyin = stdin;
-
-    if (!yyout)
-      yyout = stdout;
-
-    if (!YY_CURRENT_BUFFER) {
-      _gst_parse_yyensure_buffer_stack (yyscanner);
-      YY_CURRENT_BUFFER_LVALUE =
-          _gst_parse_yy_create_buffer (yyin, YY_BUF_SIZE, yyscanner);
-    }
-
-    _gst_parse_yy_load_buffer_state (yyscanner);
-  }
-
-  while (1) {                   /* loops until end-of-file is reached */
-    yy_cp = yyg->yy_c_buf_p;
-
-    /* Support of yytext. */
-    *yy_cp = yyg->yy_hold_char;
-
-    /* yy_bp points to the position in yy_ch_buf of the start of
-     * the current run.
-     */
-    yy_bp = yy_cp;
-
-    yy_current_state = yyg->yy_start;
-  yy_match:
-    do {
-      register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI (*yy_cp)];
-
-      if (yy_accept[yy_current_state]) {
-        yyg->yy_last_accepting_state = yy_current_state;
-        yyg->yy_last_accepting_cpos = yy_cp;
-      }
-      while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
-        yy_current_state = (int) yy_def[yy_current_state];
-        if (yy_current_state >= 177)
-          yy_c = yy_meta[(unsigned int) yy_c];
-      }
-      yy_current_state =
-          yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-      ++yy_cp;
-    }
-    while (yy_current_state != 176);
-    yy_cp = yyg->yy_last_accepting_cpos;
-    yy_current_state = yyg->yy_last_accepting_state;
-
-  yy_find_action:
-    yy_act = yy_accept[yy_current_state];
-
-    YY_DO_BEFORE_ACTION;
-
-  do_action:                   /* This label is used only to access EOF actions. */
-
-    switch (yy_act) {           /* beginning of action switch */
-      case 0:                  /* must back up */
-        /* undo the effects of YY_DO_BEFORE_ACTION */
-        *yy_cp = yyg->yy_hold_char;
-        yy_cp = yyg->yy_last_accepting_cpos;
-        yy_current_state = yyg->yy_last_accepting_state;
-        goto yy_find_action;
-
-      case 1:
-/* rule 1 can match eol */
-        YY_RULE_SETUP
-#line 73 "parse.l"
-      {
-        /* "=" */
-        PRINT ("ASSIGNMENT: %s", yytext);
-        yylval->s = gst_parse_strdup (yytext);
-        BEGIN (INITIAL);
-        return ASSIGNMENT;
-      }
-        YY_BREAK case 2:YY_RULE_SETUP
-#line 81 "parse.l"
-      {
-        yytext++;
-        PRINT ("PADREF: %s", yytext);
-        yylval->s = gst_parse_strdup (yytext);
-        BEGIN (INITIAL);
-        return PADREF;
-      }
-        YY_BREAK case 3:YY_RULE_SETUP
-#line 89 "parse.l"
-      {
-        PRINT ("REF: %s", yytext);
-        yylval->s = gst_parse_strdup (yytext);
-        BEGIN (INITIAL);
-        return REF;
-      }
-        YY_BREAK case 4:
-/* rule 4 can match eol */
-          YY_RULE_SETUP
-#line 96 "parse.l"
-      {
-        gchar *pos = yytext;
-
-        while (!g_ascii_isspace (*pos) && (*pos != '.'))
-            pos++;
-         *pos = '\0';
-          PRINT ("BINREF: %s", yytext);
-          yylval->s = gst_parse_strdup (yytext);
-          BEGIN (INITIAL);
-          return BINREF;
-      }
-        YY_BREAK case 5:YY_RULE_SETUP
-#line 106 "parse.l"
-      {
-        PRINT ("IDENTIFIER: %s", yytext);
-        yylval->s = gst_parse_strdup (yytext);
-        BEGIN (INITIAL);
-        return IDENTIFIER;
-      }
-        YY_BREAK case 6:
-/* rule 6 can match eol */
-          YY_RULE_SETUP
-#line 113 "parse.l"
-      {
-        gchar *c = yytext;
-
-          PRINT ("LINK: %s", yytext);
-          c++;
-        if (*c)
-        {
-          while (g_ascii_isspace (*c))
-            c++;
-          c = yylval->s = gst_parse_strdup (c);
-          while (*c)
-            c++;
-          if (*--c != '!')
-            g_assert_not_reached ();
-          while (g_ascii_isspace (*--c));
-          *++c = '\0';
-        } else
-        {
-          yylval->s = NULL;
-        }
-        BEGIN (INITIAL);
-        return LINK;
-      }
-        YY_BREAK case 7:
-/* rule 7 can match eol */
-          YY_RULE_SETUP
-#line 131 "parse.l"
-      {
-        PRINT ("URL: %s", yytext);
-        yylval->s = g_strdup (yytext);
-        gst_parse_unescape (yylval->s);
-        BEGIN (INITIAL);
-        return PARSE_URL;
-      }
-        YY_BREAK case 8:YY_RULE_SETUP
-#line 139 "parse.l"
-      {
-        PRINT ("OPERATOR: [%s]", yytext);
-        return *yytext;
-      }
-        YY_BREAK case 9:
-/* rule 9 can match eol */
-          YY_RULE_SETUP
-#line 141 "parse.l"
-      {
-        PRINT ("SPACE: [%s]", yytext);
-      }
-        YY_BREAK case 10:YY_RULE_SETUP
-#line 143 "parse.l"
-      {
-        PRINT ("Invalid Lexer element: %s\n", yytext);
-        return *yytext;
-      }
-        YY_BREAK case 11:YY_RULE_SETUP
-#line 148 "parse.l"
-          ECHO;
-
-        YY_BREAK
-#line 1271 "lex._gst_parse_yy.c"
-      case YY_STATE_EOF (INITIAL):
-      case YY_STATE_EOF (value):
-        yyterminate ();
-
-      case YY_END_OF_BUFFER:
-      {
-        /* Amount of text matched not including the EOB char. */
-        int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-        /* Undo the effects of YY_DO_BEFORE_ACTION. */
-        *yy_cp = yyg->yy_hold_char;
-        YY_RESTORE_YY_MORE_OFFSET
-            if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW) {
-          /* We're scanning a new file or input source.  It's
-           * possible that this happened because the user
-           * just pointed yyin at a new source and called
-           * _gst_parse_yylex().  If so, then we have to assure
-           * consistency between YY_CURRENT_BUFFER and our
-           * globals.  Here is the right place to do so, because
-           * this is the first action (other than possibly a
-           * back-up) that will match for the new input source.
-           */
-          yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-          YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-          YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-        }
-
-        /* Note that here we test for yy_c_buf_p "<=" to the position
-         * of the first EOB in the buffer, since yy_c_buf_p will
-         * already have been incremented past the NUL character
-         * (since all states make transitions on EOB to the
-         * end-of-buffer state).  Contrast this with the test
-         * in input().
-         */
-        if (yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]) { /* This was really a NUL. */
-          yy_state_type yy_next_state;
-
-          yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-          yy_current_state = yy_get_previous_state (yyscanner);
-
-          /* Okay, we're now positioned to make the NUL
-           * transition.  We couldn't have
-           * yy_get_previous_state() go ahead and do it
-           * for us because it doesn't know how to deal
-           * with the possibility of jamming (and we don't
-           * want to build jamming into it because then it
-           * will run more slowly).
-           */
-
-          yy_next_state = yy_try_NUL_trans (yy_current_state, yyscanner);
-
-          yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-          if (yy_next_state) {
-            /* Consume the NUL. */
-            yy_cp = ++yyg->yy_c_buf_p;
-            yy_current_state = yy_next_state;
-            goto yy_match;
-          }
-
-          else {
-            yy_cp = yyg->yy_last_accepting_cpos;
-            yy_current_state = yyg->yy_last_accepting_state;
-            goto yy_find_action;
-          }
-        }
-
-        else
-          switch (yy_get_next_buffer (yyscanner)) {
-            case EOB_ACT_END_OF_FILE:
-            {
-              yyg->yy_did_buffer_switch_on_eof = 0;
-
-              if (_gst_parse_yywrap (yyscanner)) {
-                /* Note: because we've taken care in
-                 * yy_get_next_buffer() to have set up
-                 * yytext, we can now set up
-                 * yy_c_buf_p so that if some total
-                 * hoser (like flex itself) wants to
-                 * call the scanner after we return the
-                 * YY_NULL, it'll still work - another
-                 * YY_NULL will get returned.
-                 */
-                yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-                yy_act = YY_STATE_EOF (YY_START);
-                goto do_action;
-              }
-
-              else {
-                if (!yyg->yy_did_buffer_switch_on_eof)
-                  YY_NEW_FILE;
-              }
-              break;
-            }
-
-            case EOB_ACT_CONTINUE_SCAN:
-              yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-              yy_current_state = yy_get_previous_state (yyscanner);
-
-              yy_cp = yyg->yy_c_buf_p;
-              yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-              goto yy_match;
-
-            case EOB_ACT_LAST_MATCH:
-              yyg->yy_c_buf_p =
-                  &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-              yy_current_state = yy_get_previous_state (yyscanner);
-
-              yy_cp = yyg->yy_c_buf_p;
-              yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-              goto yy_find_action;
-          }
-        break;
-      }
-
-      default:
-        YY_FATAL_ERROR ("fatal flex scanner internal error--no action found");
-    }                           /* end of action switch */
-  }                             /* end of scanning one token */
-}                               /* end of _gst_parse_yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int
-yy_get_next_buffer (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-  register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-  register char *source = yyg->yytext_ptr;
-  register int number_to_move, i;
-  int ret_val;
-
-  if (yyg->yy_c_buf_p >
-      &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1])
-    YY_FATAL_ERROR ("fatal flex scanner internal error--end of buffer missed");
-
-  if (YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0) {  /* Don't try to fill the buffer, so this is an EOF. */
-    if (yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1) {
-      /* We matched a single character, the EOB, so
-       * treat this as a final EOF.
-       */
-      return EOB_ACT_END_OF_FILE;
-    }
-
-    else {
-      /* We matched some text prior to the EOB, first
-       * process it.
-       */
-      return EOB_ACT_LAST_MATCH;
-    }
-  }
-
-  /* Try to read more data. */
-
-  /* First move last chars to start of buffer. */
-  number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-  for (i = 0; i < number_to_move; ++i)
-    *(dest++) = *(source++);
-
-  if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING)
-    /* don't do the read, it's not guaranteed to return an EOF,
-     * just force an EOF
-     */
-    YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-  else {
-    int num_to_read =
-        YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-    while (num_to_read <= 0) {  /* Not enough room in the buffer - grow it. */
-
-      /* just a shorter name for the current buffer */
-      YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-      int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-      if (b->yy_is_our_buffer) {
-        int new_size = b->yy_buf_size * 2;
-
-        if (new_size <= 0)
-          b->yy_buf_size += b->yy_buf_size / 8;
-        else
-          b->yy_buf_size *= 2;
-
-        b->yy_ch_buf = (char *)
-            /* Include room in for 2 EOB chars. */
-            _gst_parse_yyrealloc ((void *) b->yy_ch_buf, b->yy_buf_size + 2,
-            yyscanner);
-      } else
-        /* Can't grow it, we don't own it. */
-        b->yy_ch_buf = 0;
-
-      if (!b->yy_ch_buf)
-        YY_FATAL_ERROR ("fatal error - scanner input buffer overflow");
-
-      yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-      num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-    }
-
-    if (num_to_read > YY_READ_BUF_SIZE)
-      num_to_read = YY_READ_BUF_SIZE;
-
-    /* Read in more data. */
-    YY_INPUT ((&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-        yyg->yy_n_chars, (size_t) num_to_read);
-
-    YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-  }
-
-  if (yyg->yy_n_chars == 0) {
-    if (number_to_move == YY_MORE_ADJ) {
-      ret_val = EOB_ACT_END_OF_FILE;
-      _gst_parse_yyrestart (yyin, yyscanner);
-    }
-
-    else {
-      ret_val = EOB_ACT_LAST_MATCH;
-      YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING;
-    }
-  }
-
-  else
-    ret_val = EOB_ACT_CONTINUE_SCAN;
-
-  if ((yy_size_t) (yyg->yy_n_chars + number_to_move) >
-      YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-    /* Extend the array by 50%, plus the number we really need. */
-    yy_size_t new_size =
-        yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-    YY_CURRENT_BUFFER_LVALUE->yy_ch_buf =
-        (char *) _gst_parse_yyrealloc ((void *) YY_CURRENT_BUFFER_LVALUE->
-        yy_ch_buf, new_size, yyscanner);
-    if (!YY_CURRENT_BUFFER_LVALUE->yy_ch_buf)
-      YY_FATAL_ERROR ("out of dynamic memory in yy_get_next_buffer()");
-  }
-
-  yyg->yy_n_chars += number_to_move;
-  YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-  YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] =
-      YY_END_OF_BUFFER_CHAR;
-
-  yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-  return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-static yy_state_type
-yy_get_previous_state (yyscan_t yyscanner)
-{
-  register yy_state_type yy_current_state;
-  register char *yy_cp;
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yy_current_state = yyg->yy_start;
-
-  for (yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp) {
-    register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI (*yy_cp)] : 1);
-
-    if (yy_accept[yy_current_state]) {
-      yyg->yy_last_accepting_state = yy_current_state;
-      yyg->yy_last_accepting_cpos = yy_cp;
-    }
-    while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
-      yy_current_state = (int) yy_def[yy_current_state];
-      if (yy_current_state >= 177)
-        yy_c = yy_meta[(unsigned int) yy_c];
-    }
-    yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-  }
-
-  return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-static yy_state_type
-yy_try_NUL_trans (yy_state_type yy_current_state, yyscan_t yyscanner)
-{
-  register int yy_is_jam;
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* This var may be unused depending upon options. */
-  register char *yy_cp = yyg->yy_c_buf_p;
-
-  register YY_CHAR yy_c = 1;
-
-  if (yy_accept[yy_current_state]) {
-    yyg->yy_last_accepting_state = yy_current_state;
-    yyg->yy_last_accepting_cpos = yy_cp;
-  }
-  while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
-    yy_current_state = (int) yy_def[yy_current_state];
-    if (yy_current_state >= 177)
-      yy_c = yy_meta[(unsigned int) yy_c];
-  }
-  yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-  yy_is_jam = (yy_current_state == 176);
-
-  return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int
-yyinput (yyscan_t yyscanner)
-#else
-static int
-input (yyscan_t yyscanner)
-#endif
-{
-  int c;
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  *yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-  if (*yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR) {
-    /* yy_c_buf_p now points to the character we want to return.
-     * If this occurs *before* the EOB characters, then it's a
-     * valid NUL; if not, then we've hit the end of the buffer.
-     */
-    if (yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars])
-      /* This was really a NUL. */
-      *yyg->yy_c_buf_p = '\0';
-
-    else {                      /* need more input */
-      int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-
-      ++yyg->yy_c_buf_p;
-
-      switch (yy_get_next_buffer (yyscanner)) {
-        case EOB_ACT_LAST_MATCH:
-          /* This happens because yy_g_n_b()
-           * sees that we've accumulated a
-           * token and flags that we need to
-           * try matching the token before
-           * proceeding.  But for input(),
-           * there's no matching to consider.
-           * So convert the EOB_ACT_LAST_MATCH
-           * to EOB_ACT_END_OF_FILE.
-           */
-
-          /* Reset buffer status. */
-          _gst_parse_yyrestart (yyin, yyscanner);
-
-         /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE:
-        {
-          if (_gst_parse_yywrap (yyscanner))
-            return EOF;
-
-          if (!yyg->yy_did_buffer_switch_on_eof)
-            YY_NEW_FILE;
-#ifdef __cplusplus
-          return yyinput (yyscanner);
-#else
-          return input (yyscanner);
-#endif
-        }
-
-        case EOB_ACT_CONTINUE_SCAN:
-          yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-          break;
-      }
-    }
-  }
-
-  c = *(unsigned char *) yyg->yy_c_buf_p;       /* cast for 8-bit char's */
-  *yyg->yy_c_buf_p = '\0';      /* preserve yytext */
-  yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-  return c;
-}
-#endif /* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-void
-_gst_parse_yyrestart (FILE * input_file, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!YY_CURRENT_BUFFER) {
-    _gst_parse_yyensure_buffer_stack (yyscanner);
-    YY_CURRENT_BUFFER_LVALUE =
-        _gst_parse_yy_create_buffer (yyin, YY_BUF_SIZE, yyscanner);
-  }
-
-  _gst_parse_yy_init_buffer (YY_CURRENT_BUFFER, input_file, yyscanner);
-  _gst_parse_yy_load_buffer_state (yyscanner);
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-void
-_gst_parse_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  /* TODO. We should be able to replace this entire function body
-   * with
-   *              _gst_parse_yypop_buffer_state();
-   *              _gst_parse_yypush_buffer_state(new_buffer);
-   */
-  _gst_parse_yyensure_buffer_stack (yyscanner);
-  if (YY_CURRENT_BUFFER == new_buffer)
-    return;
-
-  if (YY_CURRENT_BUFFER) {
-    /* Flush out information for old buffer. */
-    *yyg->yy_c_buf_p = yyg->yy_hold_char;
-    YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-    YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-  }
-
-  YY_CURRENT_BUFFER_LVALUE = new_buffer;
-  _gst_parse_yy_load_buffer_state (yyscanner);
-
-  /* We don't actually know whether we did this switch during
-   * EOF (_gst_parse_yywrap()) processing, but the only time this flag
-   * is looked at is after _gst_parse_yywrap() is called, so it's safe
-   * to go ahead and always set it.
-   */
-  yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void
-_gst_parse_yy_load_buffer_state (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-  yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-  yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-  yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-YY_BUFFER_STATE
-_gst_parse_yy_create_buffer (FILE * file, int size, yyscan_t yyscanner)
-{
-  YY_BUFFER_STATE b;
-
-  b = (YY_BUFFER_STATE) _gst_parse_yyalloc (sizeof (struct yy_buffer_state),
-      yyscanner);
-  if (!b)
-    YY_FATAL_ERROR ("out of dynamic memory in _gst_parse_yy_create_buffer()");
-
-  b->yy_buf_size = size;
-
-  /* yy_ch_buf has to be 2 characters longer than the size given because
-   * we need to put in 2 end-of-buffer characters.
-   */
-  b->yy_ch_buf = (char *) _gst_parse_yyalloc (b->yy_buf_size + 2, yyscanner);
-  if (!b->yy_ch_buf)
-    YY_FATAL_ERROR ("out of dynamic memory in _gst_parse_yy_create_buffer()");
-
-  b->yy_is_our_buffer = 1;
-
-  _gst_parse_yy_init_buffer (b, file, yyscanner);
-
-  return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with _gst_parse_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
-void
-_gst_parse_yy_delete_buffer (YY_BUFFER_STATE b, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!b)
-    return;
-
-  if (b == YY_CURRENT_BUFFER)   /* Not sure if we should pop here. */
-    YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-  if (b->yy_is_our_buffer)
-    _gst_parse_yyfree ((void *) b->yy_ch_buf, yyscanner);
-
-  _gst_parse_yyfree ((void *) b, yyscanner);
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a _gst_parse_yyrestart() or at EOF.
- */
-static void
-_gst_parse_yy_init_buffer (YY_BUFFER_STATE b, FILE * file, yyscan_t yyscanner)
-{
-  int oerrno = errno;
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  _gst_parse_yy_flush_buffer (b, yyscanner);
-
-  b->yy_input_file = file;
-  b->yy_fill_buffer = 1;
-
-  /* If b is the current buffer, then _gst_parse_yy_init_buffer was _probably_
-   * called from _gst_parse_yyrestart() or through yy_get_next_buffer.
-   * In that case, we don't want to reset the lineno or column.
-   */
-  if (b != YY_CURRENT_BUFFER) {
-    b->yy_bs_lineno = 1;
-    b->yy_bs_column = 0;
-  }
-
-  b->yy_is_interactive = 0;
-
-  errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-void
-_gst_parse_yy_flush_buffer (YY_BUFFER_STATE b, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!b)
-    return;
-
-  b->yy_n_chars = 0;
-
-  /* We always need two end-of-buffer characters.  The first causes
-   * a transition to the end-of-buffer state.  The second causes
-   * a jam in that state.
-   */
-  b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-  b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-  b->yy_buf_pos = &b->yy_ch_buf[0];
-
-  b->yy_at_bol = 1;
-  b->yy_buffer_status = YY_BUFFER_NEW;
-
-  if (b == YY_CURRENT_BUFFER)
-    _gst_parse_yy_load_buffer_state (yyscanner);
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void
-_gst_parse_yypush_buffer_state (YY_BUFFER_STATE new_buffer, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (new_buffer == NULL)
-    return;
-
-  _gst_parse_yyensure_buffer_stack (yyscanner);
-
-  /* This block is copied from _gst_parse_yy_switch_to_buffer. */
-  if (YY_CURRENT_BUFFER) {
-    /* Flush out information for old buffer. */
-    *yyg->yy_c_buf_p = yyg->yy_hold_char;
-    YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-    YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-  }
-
-  /* Only push if top exists. Otherwise, replace top. */
-  if (YY_CURRENT_BUFFER)
-    yyg->yy_buffer_stack_top++;
-  YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-  /* copied from _gst_parse_yy_switch_to_buffer. */
-  _gst_parse_yy_load_buffer_state (yyscanner);
-  yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void
-_gst_parse_yypop_buffer_state (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!YY_CURRENT_BUFFER)
-    return;
-
-  _gst_parse_yy_delete_buffer (YY_CURRENT_BUFFER, yyscanner);
-  YY_CURRENT_BUFFER_LVALUE = NULL;
-  if (yyg->yy_buffer_stack_top > 0)
-    --yyg->yy_buffer_stack_top;
-
-  if (YY_CURRENT_BUFFER) {
-    _gst_parse_yy_load_buffer_state (yyscanner);
-    yyg->yy_did_buffer_switch_on_eof = 1;
-  }
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void
-_gst_parse_yyensure_buffer_stack (yyscan_t yyscanner)
-{
-  int num_to_alloc;
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!yyg->yy_buffer_stack) {
-
-    /* First allocation is just for 2 elements, since we don't know if this
-     * scanner will even need a stack. We use 2 instead of 1 to avoid an
-     * immediate realloc on the next call.
-     */
-    num_to_alloc = 1;
-    yyg->yy_buffer_stack = (struct yy_buffer_state **) _gst_parse_yyalloc
-        (num_to_alloc * sizeof (struct yy_buffer_state *)
-        , yyscanner);
-    if (!yyg->yy_buffer_stack)
-      YY_FATAL_ERROR
-          ("out of dynamic memory in _gst_parse_yyensure_buffer_stack()");
-
-    memset (yyg->yy_buffer_stack, 0,
-        num_to_alloc * sizeof (struct yy_buffer_state *));
-
-    yyg->yy_buffer_stack_max = num_to_alloc;
-    yyg->yy_buffer_stack_top = 0;
-    return;
-  }
-
-  if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1) {
-
-    /* Increase the buffer to prepare for a possible push. */
-    int grow_size = 8 /* arbitrary grow size */ ;
-
-    num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-    yyg->yy_buffer_stack = (struct yy_buffer_state **) _gst_parse_yyrealloc
-        (yyg->yy_buffer_stack, num_to_alloc * sizeof (struct yy_buffer_state *)
-        , yyscanner);
-    if (!yyg->yy_buffer_stack)
-      YY_FATAL_ERROR
-          ("out of dynamic memory in _gst_parse_yyensure_buffer_stack()");
-
-    /* zero only the new slots. */
-    memset (yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0,
-        grow_size * sizeof (struct yy_buffer_state *));
-    yyg->yy_buffer_stack_max = num_to_alloc;
-  }
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE
-_gst_parse_yy_scan_buffer (char *base, yy_size_t size, yyscan_t yyscanner)
-{
-  YY_BUFFER_STATE b;
-
-  if (size < 2 ||
-      base[size - 2] != YY_END_OF_BUFFER_CHAR ||
-      base[size - 1] != YY_END_OF_BUFFER_CHAR)
-    /* They forgot to leave room for the EOB's. */
-    return 0;
-
-  b = (YY_BUFFER_STATE) _gst_parse_yyalloc (sizeof (struct yy_buffer_state),
-      yyscanner);
-  if (!b)
-    YY_FATAL_ERROR ("out of dynamic memory in _gst_parse_yy_scan_buffer()");
-
-  b->yy_buf_size = size - 2;    /* "- 2" to take care of EOB's */
-  b->yy_buf_pos = b->yy_ch_buf = base;
-  b->yy_is_our_buffer = 0;
-  b->yy_input_file = 0;
-  b->yy_n_chars = b->yy_buf_size;
-  b->yy_is_interactive = 0;
-  b->yy_at_bol = 1;
-  b->yy_fill_buffer = 0;
-  b->yy_buffer_status = YY_BUFFER_NEW;
-
-  _gst_parse_yy_switch_to_buffer (b, yyscanner);
-
-  return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to _gst_parse_yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       _gst_parse_yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE
-_gst_parse_yy_scan_string (yyconst char *yystr, yyscan_t yyscanner)
-{
-
-  return _gst_parse_yy_scan_bytes (yystr, strlen (yystr), yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to _gst_parse_yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE
-_gst_parse_yy_scan_bytes (yyconst char *yybytes, int _yybytes_len,
-    yyscan_t yyscanner)
-{
-  YY_BUFFER_STATE b;
-  char *buf;
-  yy_size_t n;
-  int i;
-
-  /* Get memory for full buffer, including space for trailing EOB's. */
-  n = _yybytes_len + 2;
-  buf = (char *) _gst_parse_yyalloc (n, yyscanner);
-  if (!buf)
-    YY_FATAL_ERROR ("out of dynamic memory in _gst_parse_yy_scan_bytes()");
-
-  for (i = 0; i < _yybytes_len; ++i)
-    buf[i] = yybytes[i];
-
-  buf[_yybytes_len] = buf[_yybytes_len + 1] = YY_END_OF_BUFFER_CHAR;
-
-  b = _gst_parse_yy_scan_buffer (buf, n, yyscanner);
-  if (!b)
-    YY_FATAL_ERROR ("bad buffer in _gst_parse_yy_scan_bytes()");
-
-  /* It's okay to grow etc. this buffer, and we should throw it
-   * away when we're done.
-   */
-  b->yy_is_our_buffer = 1;
-
-  return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void
-yy_fatal_error (yyconst char *msg, yyscan_t yyscanner)
-{
-  (void) fprintf (stderr, "%s\n", msg);
-  exit (YY_EXIT_FAILURE);
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = yyg->yy_hold_char; \
-		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-		*yyg->yy_c_buf_p = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE
-_gst_parse_yyget_extra (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int
-_gst_parse_yyget_lineno (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!YY_CURRENT_BUFFER)
-    return 0;
-
-  return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int
-_gst_parse_yyget_column (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  if (!YY_CURRENT_BUFFER)
-    return 0;
-
-  return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *
-_gst_parse_yyget_in (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *
-_gst_parse_yyget_out (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int
-_gst_parse_yyget_leng (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *
-_gst_parse_yyget_text (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void
-_gst_parse_yyset_extra (YY_EXTRA_TYPE user_defined, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yyextra = user_defined;
-}
-
-/** Set the current line number.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void
-_gst_parse_yyset_lineno (int line_number, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  /* lineno is only valid if an input buffer exists. */
-  if (!YY_CURRENT_BUFFER)
-    yy_fatal_error ("_gst_parse_yyset_lineno called with no buffer", yyscanner);
-
-  yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void
-_gst_parse_yyset_column (int column_no, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  /* column is only valid if an input buffer exists. */
-  if (!YY_CURRENT_BUFFER)
-    yy_fatal_error ("_gst_parse_yyset_column called with no buffer", yyscanner);
-
-  yycolumn = column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see _gst_parse_yy_switch_to_buffer
- */
-void
-_gst_parse_yyset_in (FILE * in_str, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yyin = in_str;
-}
-
-void
-_gst_parse_yyset_out (FILE * out_str, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yyout = out_str;
-}
-
-int
-_gst_parse_yyget_debug (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yy_flex_debug;
-}
-
-void
-_gst_parse_yyset_debug (int bdebug, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yy_flex_debug = bdebug;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-YYSTYPE *
-_gst_parse_yyget_lval (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  return yylval;
-}
-
-void
-_gst_parse_yyset_lval (YYSTYPE * yylval_param, yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  yylval = yylval_param;
-}
-
-/* User-visible API */
-
-/* _gst_parse_yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int
-_gst_parse_yylex_init (yyscan_t * ptr_yy_globals)
-{
-  if (ptr_yy_globals == NULL) {
-    errno = EINVAL;
-    return 1;
-  }
-
-  *ptr_yy_globals =
-      (yyscan_t) _gst_parse_yyalloc (sizeof (struct yyguts_t), NULL);
-
-  if (*ptr_yy_globals == NULL) {
-    errno = ENOMEM;
-    return 1;
-  }
-
-  /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-  memset (*ptr_yy_globals, 0x00, sizeof (struct yyguts_t));
-
-  return yy_init_globals (*ptr_yy_globals);
-}
-
-/* _gst_parse_yylex_init_extra has the same functionality as _gst_parse_yylex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to _gst_parse_yyalloc in
- * the yyextra field.
- */
-
-int
-_gst_parse_yylex_init_extra (YY_EXTRA_TYPE yy_user_defined,
-    yyscan_t * ptr_yy_globals)
-{
-  struct yyguts_t dummy_yyguts;
-
-  _gst_parse_yyset_extra (yy_user_defined, &dummy_yyguts);
-
-  if (ptr_yy_globals == NULL) {
-    errno = EINVAL;
-    return 1;
-  }
-
-  *ptr_yy_globals =
-      (yyscan_t) _gst_parse_yyalloc (sizeof (struct yyguts_t), &dummy_yyguts);
-
-  if (*ptr_yy_globals == NULL) {
-    errno = ENOMEM;
-    return 1;
-  }
-
-  /* By setting to 0xAA, we expose bugs in
-     yy_init_globals. Leave at 0x00 for releases. */
-  memset (*ptr_yy_globals, 0x00, sizeof (struct yyguts_t));
-
-  _gst_parse_yyset_extra (yy_user_defined, *ptr_yy_globals);
-
-  return yy_init_globals (*ptr_yy_globals);
-}
-
-static int
-yy_init_globals (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  /* Initialization is the same as for the non-reentrant scanner.
-   * This function is called from _gst_parse_yylex_destroy(), so don't allocate here.
-   */
-
-  yyg->yy_buffer_stack = 0;
-  yyg->yy_buffer_stack_top = 0;
-  yyg->yy_buffer_stack_max = 0;
-  yyg->yy_c_buf_p = (char *) 0;
-  yyg->yy_init = 0;
-  yyg->yy_start = 0;
-
-  yyg->yy_start_stack_ptr = 0;
-  yyg->yy_start_stack_depth = 0;
-  yyg->yy_start_stack = NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-  yyin = stdin;
-  yyout = stdout;
-#else
-  yyin = (FILE *) 0;
-  yyout = (FILE *) 0;
-#endif
-
-  /* For future reference: Set errno on error, since we are called by
-   * _gst_parse_yylex_init()
-   */
-  return 0;
-}
-
-/* _gst_parse_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int
-_gst_parse_yylex_destroy (yyscan_t yyscanner)
-{
-  struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
-
-  /* Pop the buffer stack, destroying each element. */
-  while (YY_CURRENT_BUFFER) {
-    _gst_parse_yy_delete_buffer (YY_CURRENT_BUFFER, yyscanner);
-    YY_CURRENT_BUFFER_LVALUE = NULL;
-    _gst_parse_yypop_buffer_state (yyscanner);
-  }
-
-  /* Destroy the stack itself. */
-  _gst_parse_yyfree (yyg->yy_buffer_stack, yyscanner);
-  yyg->yy_buffer_stack = NULL;
-
-  /* Destroy the start condition stack. */
-  _gst_parse_yyfree (yyg->yy_start_stack, yyscanner);
-  yyg->yy_start_stack = NULL;
-
-  /* Reset the globals. This is important in a non-reentrant scanner so the next time
-   * _gst_parse_yylex() is called, initialization will occur. */
-  yy_init_globals (yyscanner);
-
-  /* Destroy the main struct (reentrant only). */
-  _gst_parse_yyfree (yyscanner, yyscanner);
-  yyscanner = NULL;
-  return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void
-yy_flex_strncpy (char *s1, yyconst char *s2, int n, yyscan_t yyscanner)
-{
-  register int i;
-
-  for (i = 0; i < n; ++i)
-    s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int
-yy_flex_strlen (yyconst char *s, yyscan_t yyscanner)
-{
-  register int n;
-
-  for (n = 0; s[n]; ++n);
-
-  return n;
-}
-#endif
-
-void *
-_gst_parse_yyalloc (yy_size_t size, yyscan_t yyscanner)
-{
-  return (void *) malloc (size);
-}
-
-void *
-_gst_parse_yyrealloc (void *ptr, yy_size_t size, yyscan_t yyscanner)
-{
-  /* The cast to (char *) in the following accommodates both
-   * implementations that use char* generic pointers, and those
-   * that use void* generic pointers.  It works with the latter
-   * because both ANSI C and C++ allow castless assignment from
-   * any pointer type to void*, and deal with argument conversions
-   * as though doing an assignment.
-   */
-  return (void *) realloc ((char *) ptr, size);
-}
-
-void
-_gst_parse_yyfree (void *ptr, yyscan_t yyscanner)
-{
-  free ((char *) ptr);          /* see _gst_parse_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 148 "parse.l"
-
-
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-enum yytokentype
-{
-  PARSE_URL = 258,
-  IDENTIFIER = 259,
-  BINREF = 260,
-  PADREF = 261,
-  REF = 262,
-  ASSIGNMENT = 263,
-  LINK = 264
-};
-#endif
-/* Tokens.  */
-#define PARSE_URL 258
-#define IDENTIFIER 259
-#define BINREF 260
-#define PADREF 261
-#define REF 262
-#define ASSIGNMENT 263
-#define LINK 264
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 521 "./grammar.y"
-{
-  gchar *s;
-  chain_t *c;
-  link_t *l;
-  GstElement *e;
-  GSList *p;
-  graph_t *g;
-}
-/* Line 1489 of yacc.c.  */
-#line 76 "grammar.tab.h"
-YYSTYPE;
-
-# define yystype YYSTYPE        /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
--- a/gstreamer_core/gst/parse/parse.l	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/parse/parse.l	Fri Apr 16 15:15:52 2010 +0300
@@ -1,5 +1,4 @@
 %{
-
 #include <math.h>
 #include <string.h>
 
@@ -12,11 +11,6 @@
 #include "../gsturi.h"
 #include "grammar.tab.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-#endif
-
 /* Override the default ECHO so as to avoid fortify warnings. Ignore the
    embedded-NUL case for now. We know yytext is NUL-terminated. */
 #define ECHO g_fprintf(yyout, "%s", yytext)
--- a/gstreamer_core/gst/parse/types.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/gst/parse/types.h	Fri Apr 16 15:15:52 2010 +0300
@@ -3,6 +3,7 @@
 
 #include <glib-object.h>
 #include "../gstelement.h"
+#include "../gstparse.h"
 
 typedef struct {
   GstElement *src;
@@ -27,6 +28,8 @@
   chain_t *chain; /* links are supposed to be done now */
   GSList *links;
   GError **error;
+  GstParseContext *ctx; /* may be NULL */
+  GstParseFlags flags;
 };
 
 
--- a/gstreamer_core/libs/gst/base/gstadapter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstadapter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -36,6 +36,10 @@
  * in chunks of the desired size using gst_adapter_peek(). After the data is
  * processed, it is freed using gst_adapter_flush().
  *
+ * Other methods such as gst_adapter_take() and gst_adapter_take_buffer()
+ * combine gst_adapter_peek() and gst_adapter_flush() in one method and are
+ * potentially more convenient for some use cases. 
+ *
  * For example, a sink pad's chain function that needs to pass data to a library
  * in 512-byte chunks could be implemented like this:
  * <programlisting>
@@ -74,11 +78,22 @@
  * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might
  * need to clear the adapter after a discontinuity.
  *
+ * Since 0.10.24, the adapter will keep track of the timestamps of the buffers
+ * that were pushed. The last seen timestamp before the current position
+ * can be queried with gst_adapter_prev_timestamp(). This function can
+ * optionally return the amount of bytes between the start of the buffer that
+ * carried the timestamp and the current adapter position. The distance is
+ * useful when dealing with, for example, raw audio samples because it allows
+ * you to calculate the timestamp of the current adapter position by using the
+ * last seen timestamp and the amount of bytes since.
+ *
  * A last thing to note is that while GstAdapter is pretty optimized,
- * merging buffers still might be an operation that requires a memcpy()
- * operation, and this operation is not the fastest. Because of this, some
- * functions like gst_adapter_available_fast() are provided to help speed up
- * such cases should you want to.
+ * merging buffers still might be an operation that requires a malloc() and
+ * memcpy() operation, and these operations are not the fastest. Because of
+ * this, some functions like gst_adapter_available_fast() are provided to help
+ * speed up such cases should you want to. To avoid repeated memory allocations,
+ * gst_adapter_copy() can be used to copy data into a (statically allocated)
+ * user provided buffer.
  *
  * GstAdapter is not MT safe. All operations on an adapter must be serialized by
  * the caller. This is not normally a problem, however, as the normal use case
@@ -90,22 +105,31 @@
  * access the buffer later. The adapter will never modify the data in the
  * buffer pushed in it.
  *
- * Last reviewed on 2006-04-04 (0.10.6).
+ * Last reviewed on 2009-05-13 (0.10.24).
  */
 
+#include <gst/gst_private.h>
 #ifdef __SYMBIAN32__
 #include <gst_global.h>
 #endif
-
 #include "gstadapter.h"
 #include <string.h>
 
 /* default size for the assembled data buffer */
-#define DEFAULT_SIZE 16
+#define DEFAULT_SIZE 4096
 
 GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
 #define GST_CAT_DEFAULT gst_adapter_debug
 
+#define GST_ADAPTER_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_ADAPTER, GstAdapterPrivate))
+
+struct _GstAdapterPrivate
+{
+  GstClockTime timestamp;
+  guint64 distance;
+};
+
 #define _do_init(thing) \
   GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")
 GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT,
@@ -125,6 +149,8 @@
 {
   GObjectClass *object = G_OBJECT_CLASS (klass);
 
+  g_type_class_add_private (klass, sizeof (GstAdapterPrivate));
+
   object->dispose = gst_adapter_dispose;
   object->finalize = gst_adapter_finalize;
 }
@@ -132,8 +158,11 @@
 static void
 gst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class)
 {
+  adapter->priv = GST_ADAPTER_GET_PRIVATE (adapter);
   adapter->assembled_data = g_malloc (DEFAULT_SIZE);
   adapter->assembled_size = DEFAULT_SIZE;
+  adapter->priv->timestamp = GST_CLOCK_TIME_NONE;
+  adapter->priv->distance = 0;
 }
 
 static void
@@ -195,6 +224,58 @@
   adapter->size = 0;
   adapter->skip = 0;
   adapter->assembled_len = 0;
+  adapter->priv->timestamp = GST_CLOCK_TIME_NONE;
+  adapter->priv->distance = 0;
+}
+
+static inline void
+update_timestamp (GstAdapter * adapter, GstBuffer * buf)
+{
+  GstClockTime timestamp;
+
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    GST_LOG_OBJECT (adapter, "new timestamp %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (timestamp));
+    adapter->priv->timestamp = timestamp;
+    adapter->priv->distance = 0;
+  }
+}
+
+/* copy data into @dest, skipping @skip bytes from the head buffers */
+static void
+copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
+    guint size)
+{
+  GSList *g;
+  GstBuffer *buf;
+  guint bsize, csize;
+
+  /* first step, do skipping */
+  g = adapter->buflist;
+  buf = g->data;
+  bsize = GST_BUFFER_SIZE (buf);
+  while (G_UNLIKELY (skip >= bsize)) {
+    skip -= bsize;
+    g = g_slist_next (g);
+    buf = g->data;
+    bsize = GST_BUFFER_SIZE (buf);
+  }
+  /* copy partial buffer */
+  csize = MIN (bsize - skip, size);
+  memcpy (dest, GST_BUFFER_DATA (buf) + skip, csize);
+  size -= csize;
+  dest += csize;
+
+  /* second step, copy remainder */
+  while (size > 0) {
+    g = g_slist_next (g);
+    buf = g->data;
+    csize = MIN (GST_BUFFER_SIZE (buf), size);
+    memcpy (dest, GST_BUFFER_DATA (buf), csize);
+    size -= csize;
+    dest += csize;
+  }
 }
 
 /**
@@ -204,6 +285,8 @@
  *
  * Adds the data from @buf to the data stored inside @adapter and takes
  * ownership of the buffer.
+ * Empty buffers will be automatically dereferenced and not stored in the
+ * @adapter.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -212,46 +295,33 @@
 void
 gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
 {
+  guint size;
+
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (GST_IS_BUFFER (buf));
 
-  adapter->size += GST_BUFFER_SIZE (buf);
+  size = GST_BUFFER_SIZE (buf);
 
-  /* Note: merging buffers at this point is premature. */
-  if (G_UNLIKELY (adapter->buflist == NULL)) {
-    adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
+  if (G_UNLIKELY (size == 0)) {
+    /* we can't have empty buffers, several parts in this file rely on it, this
+     * has some problems for the timestamp tracking. */
+    GST_LOG_OBJECT (adapter, "discarding empty buffer");
+    gst_buffer_unref (buf);
   } else {
-    /* Otherwise append to the end, and advance our end pointer */
-    adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
-    adapter->buflist_end = g_slist_next (adapter->buflist_end);
-  }
-}
+    adapter->size += size;
 
-/* Internal function that copies data into the given buffer, size must be 
- * bigger than the first buffer */
-static void
-gst_adapter_peek_into (GstAdapter * adapter, guint8 * data, guint size)
-{
-  GstBuffer *cur;
-  GSList *cur_list;
-  guint copied, to_copy;
-
-  /* The first buffer might be partly consumed, so need to handle
-   * 'skipped' bytes. */
-  cur = adapter->buflist->data;
-  copied = to_copy = MIN (GST_BUFFER_SIZE (cur) - adapter->skip, size);
-  memcpy (data, GST_BUFFER_DATA (cur) + adapter->skip, copied);
-  data += copied;
-
-  cur_list = g_slist_next (adapter->buflist);
-  while (copied < size) {
-    g_assert (cur_list);
-    cur = cur_list->data;
-    cur_list = g_slist_next (cur_list);
-    to_copy = MIN (GST_BUFFER_SIZE (cur), size - copied);
-    memcpy (data, GST_BUFFER_DATA (cur), to_copy);
-    data += to_copy;
-    copied += to_copy;
+    /* Note: merging buffers at this point is premature. */
+    if (G_UNLIKELY (adapter->buflist == NULL)) {
+      GST_LOG_OBJECT (adapter, "pushing first %u bytes", size);
+      adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
+      update_timestamp (adapter, buf);
+    } else {
+      /* Otherwise append to the end, and advance our end pointer */
+      GST_LOG_OBJECT (adapter, "pushing %u bytes at end, size now %u", size,
+          adapter->size);
+      adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
+      adapter->buflist_end = g_slist_next (adapter->buflist_end);
+    }
   }
 }
 
@@ -328,6 +398,7 @@
 gst_adapter_peek (GstAdapter * adapter, guint size)
 {
   GstBuffer *cur;
+  guint skip;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (size > 0, NULL);
@@ -344,29 +415,33 @@
 
   /* our head buffer has enough data left, return it */
   cur = adapter->buflist->data;
-  if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
-    return GST_BUFFER_DATA (cur) + adapter->skip;
+  skip = adapter->skip;
+  if (GST_BUFFER_SIZE (cur) >= size + skip)
+    return GST_BUFFER_DATA (cur) + skip;
 
   /* We may be able to efficiently merge buffers in our pool to 
    * gather a big enough chunk to return it from the head buffer directly */
   if (gst_adapter_try_to_merge_up (adapter, size)) {
     /* Merged something! Check if there's enough avail now */
     cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
-      return GST_BUFFER_DATA (cur) + adapter->skip;
+    if (GST_BUFFER_SIZE (cur) >= size + skip)
+      return GST_BUFFER_DATA (cur) + skip;
   }
 
   /* Gonna need to copy stuff out */
-  if (adapter->assembled_size < size) {
+  if (G_UNLIKELY (adapter->assembled_size < size)) {
     adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE;
-    GST_DEBUG_OBJECT (adapter, "setting size of internal buffer to %u",
+    GST_DEBUG_OBJECT (adapter, "resizing internal buffer to %u",
         adapter->assembled_size);
+    /* no g_realloc to avoid a memcpy that is not desired here since we are
+     * going to copy new data into the area below */
     g_free (adapter->assembled_data);
     adapter->assembled_data = g_malloc (adapter->assembled_size);
   }
   adapter->assembled_len = size;
 
-  gst_adapter_peek_into (adapter, adapter->assembled_data, size);
+  GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy data from adapter");
+  copy_into_unchecked (adapter, adapter->assembled_data, skip, size);
 
   return adapter->assembled_data;
 }
@@ -394,37 +469,11 @@
 void
 gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size)
 {
-  GSList *g;
-  int skip;
-
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (size > 0);
-
-  /* we don't have enough data, return. This is unlikely
-   * as one usually does an _available() first instead of copying a
-   * random size. */
-  if (G_UNLIKELY (offset + size > adapter->size))
-    return;
-
-  skip = adapter->skip;
-  for (g = adapter->buflist; g && size > 0; g = g_slist_next (g)) {
-    GstBuffer *buf;
+  g_return_if_fail (offset + size <= adapter->size);
 
-    buf = g->data;
-    if (offset < GST_BUFFER_SIZE (buf) - skip) {
-      int n;
-
-      n = MIN (GST_BUFFER_SIZE (buf) - skip - offset, size);
-      memcpy (dest, GST_BUFFER_DATA (buf) + skip + offset, n);
-
-      dest += n;
-      offset = 0;
-      size -= n;
-    } else {
-      offset -= GST_BUFFER_SIZE (buf) - skip;
-    }
-    skip = 0;
-  }
+  copy_into_unchecked (adapter, dest, offset + adapter->skip, size);
 }
 
 /**
@@ -445,29 +494,56 @@
 gst_adapter_flush (GstAdapter * adapter, guint flush)
 {
   GstBuffer *cur;
+  guint size;
+  GstAdapterPrivate *priv;
+  GSList *g;
 
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (flush <= adapter->size);
 
   GST_LOG_OBJECT (adapter, "flushing %u bytes", flush);
+
+  /* flushing out 0 bytes will do nothing */
+  if (G_UNLIKELY (flush == 0))
+    return;
+
+  priv = adapter->priv;
+
+  /* clear state */
   adapter->size -= flush;
   adapter->assembled_len = 0;
-  while (flush > 0) {
-    cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) <= flush + adapter->skip) {
-      /* can skip whole buffer */
-      flush -= GST_BUFFER_SIZE (cur) - adapter->skip;
-      adapter->skip = 0;
-      adapter->buflist =
-          g_slist_delete_link (adapter->buflist, adapter->buflist);
-      if (G_UNLIKELY (adapter->buflist == NULL))
-        adapter->buflist_end = NULL;
-      gst_buffer_unref (cur);
-    } else {
-      adapter->skip += flush;
+
+  /* take skip into account */
+  flush += adapter->skip;
+  /* distance is always at least the amount of skipped bytes */
+  priv->distance -= adapter->skip;
+
+  g = adapter->buflist;
+  cur = g->data;
+  size = GST_BUFFER_SIZE (cur);
+  while (flush >= size) {
+    /* can skip whole buffer */
+    GST_LOG_OBJECT (adapter, "flushing out head buffer");
+    priv->distance += size;
+    flush -= size;
+
+    gst_buffer_unref (cur);
+    g = g_slist_delete_link (g, g);
+
+    if (G_UNLIKELY (g == NULL)) {
+      GST_LOG_OBJECT (adapter, "adapter empty now");
+      adapter->buflist_end = NULL;
       break;
     }
+    /* there is a new head buffer, update the timestamp */
+    cur = g->data;
+    update_timestamp (adapter, cur);
+    size = GST_BUFFER_SIZE (cur);
   }
+  adapter->buflist = g;
+  /* account for the remaining bytes */
+  adapter->skip = flush;
+  adapter->priv->distance += flush;
 }
 
 /**
@@ -500,15 +576,18 @@
   if (G_UNLIKELY (nbytes > adapter->size))
     return NULL;
 
-  data = g_malloc (nbytes);
-
-  /* we have enough assembled data, copy from there */
+  /* we have enough assembled data, take from there */
   if (adapter->assembled_len >= nbytes) {
     GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
-    memcpy (data, adapter->assembled_data, nbytes);
+    data = adapter->assembled_data;
+    /* allocate new data, assembled_len will be set to 0 in the flush below */
+    adapter->assembled_data = g_malloc (adapter->assembled_size);
   } else {
+    /* we need to allocate and copy. We could potentially copy bytes from the
+     * assembled data before doing the copy_into */
     GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
-    gst_adapter_peek_into (adapter, data, nbytes);
+    data = g_malloc (nbytes);
+    copy_into_unchecked (adapter, data, adapter->skip, nbytes);
   }
 
   gst_adapter_flush (adapter, nbytes);
@@ -543,6 +622,7 @@
 {
   GstBuffer *buffer;
   GstBuffer *cur;
+  guint hsize, skip;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (nbytes > 0, NULL);
@@ -555,43 +635,52 @@
   if (G_UNLIKELY (nbytes > adapter->size))
     return NULL;
 
+  cur = adapter->buflist->data;
+  skip = adapter->skip;
+  hsize = GST_BUFFER_SIZE (cur);
+
   /* our head buffer has enough data left, return it */
-  cur = adapter->buflist->data;
-  if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
+  if (skip == 0 && hsize == nbytes) {
+    GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
+        nbytes);
+    buffer = gst_buffer_ref (cur);
+    goto done;
+  } else if (hsize >= nbytes + skip) {
     GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
         nbytes);
-    buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
-
-    gst_adapter_flush (adapter, nbytes);
-
-    return buffer;
+    buffer = gst_buffer_create_sub (cur, skip, nbytes);
+    goto done;
   }
 
   if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
     /* Merged something, let's try again for sub-buffering */
     cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
+    if (GST_BUFFER_SIZE (cur) >= nbytes + skip) {
       GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
           nbytes);
-      buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
-
-      gst_adapter_flush (adapter, nbytes);
-
-      return buffer;
+      buffer = gst_buffer_create_sub (cur, skip, nbytes);
+      goto done;
     }
   }
 
-  buffer = gst_buffer_new_and_alloc (nbytes);
-
   /* we have enough assembled data, copy from there */
   if (adapter->assembled_len >= nbytes) {
     GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
-    memcpy (GST_BUFFER_DATA (buffer), adapter->assembled_data, nbytes);
+    buffer = gst_buffer_new ();
+    GST_BUFFER_SIZE (buffer) = nbytes;
+    GST_BUFFER_DATA (buffer) = adapter->assembled_data;
+    GST_BUFFER_MALLOCDATA (buffer) = adapter->assembled_data;
+    /* flush will set the assembled_len to 0 */
+    adapter->assembled_data = g_malloc (adapter->assembled_size);
   } else {
+    /* we need to allocate and copy. We could potentially copy bytes from the
+     * assembled data before doing the copy_into */
+    buffer = gst_buffer_new_and_alloc (nbytes);
     GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
-    gst_adapter_peek_into (adapter, GST_BUFFER_DATA (buffer), nbytes);
+    copy_into_unchecked (adapter, GST_BUFFER_DATA (buffer), skip, nbytes);
   }
 
+done:
   gst_adapter_flush (adapter, nbytes);
 
   return buffer;
@@ -637,6 +726,9 @@
 guint
 gst_adapter_available_fast (GstAdapter * adapter)
 {
+  GstBuffer *first;
+  guint size;
+
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
 
   /* no buffers, we have no data */
@@ -647,9 +739,153 @@
   if (adapter->assembled_len)
     return adapter->assembled_len;
 
-  /* we cannot have skipped more than the first buffer */
-  g_assert (GST_BUFFER_SIZE (adapter->buflist->data) > adapter->skip);
+  /* take the first buffer and its size */
+  first = GST_BUFFER_CAST (adapter->buflist->data);
+  size = GST_BUFFER_SIZE (first);
+
+  /* we can quickly get the (remaining) data of the first buffer */
+  return size - adapter->skip;
+}
+
+/**
+ * gst_adapter_prev_timestamp:
+ * @adapter: a #GstAdapter
+ * @distance: pointer to location for distance or NULL
+ *
+ * Get the timestamp that was before the current byte in the adapter. When
+ * @distance is given, the amount of bytes between the timestamp and the current
+ * position is returned.
+ *
+ * The timestamp is reset to GST_CLOCK_TIME_NONE when the adapter is first
+ * created or when it is cleared.
+ *
+ * Returns: The previously seen timestamp.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstClockTime
+gst_adapter_prev_timestamp (GstAdapter * adapter, guint64 * distance)
+{
+  g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
+
+  if (distance)
+    *distance = adapter->priv->distance;
+
+  return adapter->priv->timestamp;
+}
 
-  /* we can quickly get the data of the first buffer */
-  return GST_BUFFER_SIZE (adapter->buflist->data) - adapter->skip;
+/**
+ * gst_adapter_masked_scan_uint32:
+ * @adapter: a #GstAdapter
+ * @mask: mask to apply to data before matching against @pattern
+ * @pattern: pattern to match (after mask is applied)
+ * @offset: offset into the adapter data from which to start scanning, returns
+ *          the last scanned position.
+ * @size: number of bytes to scan from offset
+ *
+ * Scan for pattern @pattern with applied mask @mask in the adapter data,
+ * starting from offset @offset. 
+ *
+ * The bytes in @pattern and @mask are interpreted left-to-right, regardless
+ * of endianness.  All four bytes of the pattern must be present in the
+ * adapter for it to match, even if the first or last bytes are masked out.
+ *
+ * It is an error to call this function without making sure that there is
+ * enough data (offset+size bytes) in the adapter.
+ *
+ * Returns: offset of the first match, or -1 if no match was found.
+ *
+ * Example:
+ * <programlisting>
+ * // Assume the adapter contains 0x00 0x01 0x02 ... 0xfe 0xff
+ * 
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 0, 256);
+ * // -> returns 0
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 1, 255);
+ * // -> returns -1
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 1, 255);
+ * // -> returns 1
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0001, 0, 256);
+ * // -> returns -1
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0203, 0, 256);
+ * // -> returns 0
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 256);
+ * // -> returns 2
+ * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 4);
+ * // -> returns -1
+ * </programlisting>
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
+    guint32 pattern, guint offset, guint size)
+{
+  GSList *g;
+  guint skip, bsize, i;
+  guint32 state;
+  guint8 *bdata;
+  GstBuffer *buf;
+
+  g_return_val_if_fail (size > 0, -1);
+  g_return_val_if_fail (offset + size <= adapter->size, -1);
+
+  /* we can't find the pattern with less than 4 bytes */
+  if (G_UNLIKELY (size < 4))
+    return -1;
+
+  skip = offset + adapter->skip;
+
+  /* first step, do skipping and position on the first buffer */
+  g = adapter->buflist;
+  buf = g->data;
+  bsize = GST_BUFFER_SIZE (buf);
+  while (G_UNLIKELY (skip >= bsize)) {
+    skip -= bsize;
+    g = g_slist_next (g);
+    buf = g->data;
+    bsize = GST_BUFFER_SIZE (buf);
+  }
+  /* get the data now */
+  bsize -= skip;
+  bdata = GST_BUFFER_DATA (buf) + skip;
+  skip = 0;
+
+  /* set the state to something that does not match */
+  state = ~pattern;
+
+  /* now find data */
+  do {
+    bsize = MIN (bsize, size);
+    for (i = 0; i < bsize; i++) {
+      state = ((state << 8) | bdata[i]);
+      if (G_UNLIKELY ((state & mask) == pattern)) {
+        /* we have a match but we need to have skipped at
+         * least 4 bytes to fill the state. */
+        if (G_LIKELY (skip + i >= 3))
+          return offset + skip + i - 3;
+      }
+    }
+    size -= bsize;
+    if (size == 0)
+      break;
+
+    /* nothing found yet, go to next buffer */
+    skip += bsize;
+    g = g_slist_next (g);
+    buf = g->data;
+    bsize = GST_BUFFER_SIZE (buf);
+    bdata = GST_BUFFER_DATA (buf);
+  } while (TRUE);
+
+  /* nothing found */
+  return -1;
 }
--- a/gstreamer_core/libs/gst/base/gstadapter.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstadapter.h	Fri Apr 16 15:15:52 2010 +0300
@@ -40,6 +40,7 @@
 
 typedef struct _GstAdapter GstAdapter;
 typedef struct _GstAdapterClass GstAdapterClass;
+typedef struct _GstAdapterPrivate GstAdapterPrivate;
 
 /**
  * GstAdapter:
@@ -60,10 +61,14 @@
   guint		assembled_size;
   guint		assembled_len;
 
+  /* ABI added */
   /* Remember where the end of our buffer list is to
    * speed up the push */
   GSList *buflist_end;
-  gpointer _gst_reserved[GST_PADDING - 1];
+
+  GstAdapterPrivate *priv;
+
+  gpointer _gst_reserved[GST_PADDING - 2];
 };
 
 struct _GstAdapterClass {
@@ -76,6 +81,11 @@
 IMPORT_C
 #endif
 
+GType			gst_adapter_get_type		(void);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 
 GstAdapter *		gst_adapter_new			(void);
 #ifdef __SYMBIAN32__
@@ -129,7 +139,14 @@
 IMPORT_C
 #endif
 
-GType			gst_adapter_get_type		(void);
+GstClockTime            gst_adapter_prev_timestamp      (GstAdapter *adapter, guint64 *distance);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint                   gst_adapter_masked_scan_uint32  (GstAdapter * adapter, guint32 mask,
+                                                         guint32 pattern, guint offset, guint size);
+
 
 G_END_DECLS
 
--- a/gstreamer_core/libs/gst/base/gstbasesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstbasesink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -163,6 +163,26 @@
 #define GST_BASE_SINK_GET_PRIVATE(obj)  \
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SINK, GstBaseSinkPrivate))
 
+#define GST_FLOW_STEP GST_FLOW_CUSTOM_ERROR
+
+typedef struct
+{
+  gboolean valid;               /* if this info is valid */
+  guint32 seqnum;               /* the seqnum of the STEP event */
+  GstFormat format;             /* the format of the amount */
+  guint64 amount;               /* the total amount of data to skip */
+  guint64 position;             /* the position in the stepped data */
+  guint64 duration;             /* the duration in time of the skipped data */
+  guint64 start;                /* running_time of the start */
+  gdouble rate;                 /* rate of skipping */
+  gdouble start_rate;           /* rate before skipping */
+  guint64 start_start;          /* start position skipping */
+  guint64 start_stop;           /* stop position skipping */
+  gboolean flush;               /* if this was a flushing step */
+  gboolean intermediate;        /* if this is an intermediate step */
+  gboolean need_preroll;        /* if we need preroll after this step */
+} GstStepInfo;
+
 /* FIXME, some stuff in ABI.data and other in Private...
  * Make up your mind please.
  */
@@ -171,6 +191,7 @@
   gint qos_enabled;             /* ATOMIC */
   gboolean async_enabled;
   GstClockTimeDiff ts_offset;
+  GstClockTime render_delay;
 
   /* start, stop of current buffer, stream time, used to report position */
   GstClockTime current_sstart;
@@ -221,6 +242,24 @@
 
   /* the last buffer we prerolled or rendered. Useful for making snapshots */
   GstBuffer *last_buffer;
+
+  /* caps for pull based scheduling */
+  GstCaps *pull_caps;
+
+  /* blocksize for pulling */
+  guint blocksize;
+
+  gboolean discont;
+
+  /* seqnum of the stream */
+  guint32 seqnum;
+
+  gboolean call_preroll;
+  gboolean step_unlock;
+
+  /* we have a pending and a current step operation */
+  GstStepInfo current_step;
+  GstStepInfo pending_step;
 };
 
 #define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
@@ -236,7 +275,6 @@
 
 /* BaseSink properties */
 
-#define DEFAULT_SIZE 1024
 #define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */
 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
 
@@ -246,6 +284,8 @@
 #define DEFAULT_QOS			FALSE
 #define DEFAULT_ASYNC			TRUE
 #define DEFAULT_TS_OFFSET		0
+#define DEFAULT_BLOCKSIZE 		4096
+#define DEFAULT_RENDER_DELAY 		0
 
 enum
 {
@@ -257,6 +297,8 @@
   PROP_ASYNC,
   PROP_TS_OFFSET,
   PROP_LAST_BUFFER,
+  PROP_BLOCKSIZE,
+  PROP_RENDER_DELAY,
   PROP_LAST
 };
 
@@ -273,9 +315,10 @@
 GType
 gst_base_sink_get_type (void)
 {
-  static GType base_sink_type = 0;
-
-  if (G_UNLIKELY (base_sink_type == 0)) {
+  static volatile gsize base_sink_type = 0;
+
+  if (g_once_init_enter (&base_sink_type)) {
+    GType _type;
     static const GTypeInfo base_sink_info = {
       sizeof (GstBaseSinkClass),
       NULL,
@@ -288,8 +331,9 @@
       (GInstanceInitFunc) gst_base_sink_init,
     };
 
-    base_sink_type = g_type_register_static (GST_TYPE_ELEMENT,
+    _type = g_type_register_static (GST_TYPE_ELEMENT,
         "GstBaseSink", &base_sink_info, G_TYPE_FLAG_ABSTRACT);
+    g_once_init_leave (&base_sink_type, _type);
   }
   return base_sink_type;
 }
@@ -313,11 +357,18 @@
     GstPad * pad, gboolean flushing);
 static gboolean gst_base_sink_default_activate_pull (GstBaseSink * basesink,
     gboolean active);
+static gboolean gst_base_sink_default_do_seek (GstBaseSink * sink,
+    GstSegment * segment);
+static gboolean gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
+    GstEvent * event, GstSegment * segment);
 
 static GstStateChangeReturn gst_base_sink_change_state (GstElement * element,
     GstStateChange transition);
 
 static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
+static GstFlowReturn gst_base_sink_chain_list (GstPad * pad,
+    GstBufferList * list);
+
 static void gst_base_sink_loop (GstPad * pad);
 static gboolean gst_base_sink_pad_activate (GstPad * pad);
 static gboolean gst_base_sink_pad_activate_push (GstPad * pad, gboolean active);
@@ -325,10 +376,14 @@
 static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);
 static gboolean gst_base_sink_peer_query (GstBaseSink * sink, GstQuery * query);
 
+static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink);
+
 /* check if an object was too late */
 static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink,
     GstMiniObject * obj, GstClockTime start, GstClockTime stop,
     GstClockReturn status, GstClockTimeDiff jitter);
+static GstFlowReturn gst_base_sink_preroll_object (GstBaseSink * basesink,
+    gboolean is_list, GstMiniObject * obj);
 
 static void
 gst_base_sink_class_init (GstBaseSinkClass * klass)
@@ -355,22 +410,23 @@
   g_object_class_install_property (gobject_class, PROP_PREROLL_QUEUE_LEN,
       g_param_spec_uint ("preroll-queue-len", "Preroll queue length",
           "Number of buffers to queue during preroll", 0, G_MAXUINT,
-          DEFAULT_PREROLL_QUEUE_LEN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+          DEFAULT_PREROLL_QUEUE_LEN,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_SYNC,
       g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_MAX_LATENESS,
       g_param_spec_int64 ("max-lateness", "Max Lateness",
           "Maximum number of nanoseconds that a buffer can be late before it "
           "is dropped (-1 unlimited)", -1, G_MAXINT64, DEFAULT_MAX_LATENESS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_QOS,
       g_param_spec_boolean ("qos", "Qos",
           "Generate Quality-of-Service events upstream", DEFAULT_QOS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstBaseSink:async
    *
@@ -383,7 +439,8 @@
    */
   g_object_class_install_property (gobject_class, PROP_ASYNC,
       g_param_spec_boolean ("async", "Async",
-          "Go asynchronously to PAUSED", DEFAULT_ASYNC, G_PARAM_READWRITE));
+          "Go asynchronously to PAUSED", DEFAULT_ASYNC,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstBaseSink:ts-offset
    *
@@ -396,8 +453,7 @@
   g_object_class_install_property (gobject_class, PROP_TS_OFFSET,
       g_param_spec_int64 ("ts-offset", "TS Offset",
           "Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64,
-          DEFAULT_TS_OFFSET, G_PARAM_READWRITE));
-
+          DEFAULT_TS_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstBaseSink:last-buffer
    *
@@ -410,7 +466,31 @@
   g_object_class_install_property (gobject_class, PROP_LAST_BUFFER,
       gst_param_spec_mini_object ("last-buffer", "Last Buffer",
           "The last buffer received in the sink", GST_TYPE_BUFFER,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstBaseSink:blocksize
+   *
+   * The amount of bytes to pull when operating in pull mode.
+   *
+   * Since: 0.10.22
+   */
+  g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
+      g_param_spec_uint ("blocksize", "Block size",
+          "Size in bytes to pull per buffer (0 = default)", 0, G_MAXUINT,
+          DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstBaseSink:render-delay
+   *
+   * The additional delay between synchronisation and actual rendering of the
+   * media. This property will add additional latency to the device in order to
+   * make other sinks compensate for the delay.
+   *
+   * Since: 0.10.22
+   */
+  g_object_class_install_property (gobject_class, PROP_RENDER_DELAY,
+      g_param_spec_uint64 ("render-delay", "Render Delay",
+          "Additional render delay of the sink in nanoseconds", 0, G_MAXUINT64,
+          DEFAULT_RENDER_DELAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
@@ -434,16 +514,27 @@
 
   bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
   bclass = GST_BASE_SINK_GET_CLASS (bsink);
-  if (bclass->get_caps)
-    caps = bclass->get_caps (bsink);
-
+
+  if (bsink->pad_mode == GST_ACTIVATE_PULL) {
+    /* if we are operating in pull mode we only accept the negotiated caps */
+    GST_OBJECT_LOCK (pad);
+    if ((caps = GST_PAD_CAPS (pad)))
+      gst_caps_ref (caps);
+    GST_OBJECT_UNLOCK (pad);
+  }
   if (caps == NULL) {
-    GstPadTemplate *pad_template;
-
-    pad_template =
-        gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
-    if (pad_template != NULL) {
-      caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
+    if (bclass->get_caps)
+      caps = bclass->get_caps (bsink);
+
+    if (caps == NULL) {
+      GstPadTemplate *pad_template;
+
+      pad_template =
+          gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass),
+          "sink");
+      if (pad_template != NULL) {
+        caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
+      }
     }
   }
   gst_object_unref (bsink);
@@ -461,18 +552,6 @@
   bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
   bclass = GST_BASE_SINK_GET_CLASS (bsink);
 
-  if (bsink->pad_mode == GST_ACTIVATE_PULL) {
-    GstPad *peer = gst_pad_get_peer (pad);
-
-    if (peer)
-      res = gst_pad_set_caps (peer, caps);
-    else
-      res = FALSE;
-
-    if (!res)
-      GST_DEBUG_OBJECT (bsink, "peer setcaps() failed");
-  }
-
   if (res && bclass->set_caps)
     res = bclass->set_caps (bsink, caps);
 
@@ -549,6 +628,8 @@
       GST_DEBUG_FUNCPTR (gst_base_sink_event));
   gst_pad_set_chain_function (basesink->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_sink_chain));
+  gst_pad_set_chain_list_function (basesink->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_base_sink_chain_list));
   gst_element_add_pad (GST_ELEMENT_CAST (basesink), basesink->sinkpad);
 
   basesink->pad_mode = GST_ACTIVATE_NONE;
@@ -561,9 +642,11 @@
 
   basesink->sync = DEFAULT_SYNC;
   basesink->abidata.ABI.max_lateness = DEFAULT_MAX_LATENESS;
-  gst_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS);
+  g_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS);
   priv->async_enabled = DEFAULT_ASYNC;
   priv->ts_offset = DEFAULT_TS_OFFSET;
+  priv->render_delay = DEFAULT_RENDER_DELAY;
+  priv->blocksize = DEFAULT_BLOCKSIZE;
 
   GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
 }
@@ -712,7 +795,7 @@
 {
   g_return_if_fail (GST_IS_BASE_SINK (sink));
 
-  gst_atomic_int_set (&sink->priv->qos_enabled, enabled);
+  g_atomic_int_set (&sink->priv->qos_enabled, enabled);
 }
 
 /**
@@ -765,6 +848,7 @@
 
   GST_PAD_PREROLL_LOCK (sink->sinkpad);
   sink->priv->async_enabled = enabled;
+  GST_LOG_OBJECT (sink, "set async enabled to %d", enabled);
   GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
 }
 
@@ -821,6 +905,7 @@
 
   GST_OBJECT_LOCK (sink);
   sink->priv->ts_offset = offset;
+  GST_LOG_OBJECT (sink, "set time offset to %" G_GINT64_FORMAT, offset);
   GST_OBJECT_UNLOCK (sink);
 }
 
@@ -891,15 +976,21 @@
 {
   GstBuffer *old;
 
-  if (buffer)
-    gst_buffer_ref (buffer);
-
   GST_OBJECT_LOCK (sink);
   old = sink->priv->last_buffer;
-  sink->priv->last_buffer = buffer;
+  if (G_LIKELY (old != buffer)) {
+    GST_DEBUG_OBJECT (sink, "setting last buffer to %p", buffer);
+    if (G_LIKELY (buffer))
+      gst_buffer_ref (buffer);
+    sink->priv->last_buffer = buffer;
+  } else {
+    old = NULL;
+  }
   GST_OBJECT_UNLOCK (sink);
 
-  if (old)
+  /* avoid unreffing with the lock because cleanup code might want to take the
+   * lock too */
+  if (G_LIKELY (old))
     gst_buffer_unref (old);
 }
 
@@ -962,7 +1053,7 @@
     GstClockTime * max_latency)
 {
   gboolean l, us_live, res, have_latency;
-  GstClockTime min, max;
+  GstClockTime min, max, render_delay;
   GstQuery *query;
   GstClockTime us_min, us_max;
 
@@ -970,6 +1061,7 @@
   GST_OBJECT_LOCK (sink);
   l = sink->sync;
   have_latency = sink->priv->have_latency;
+  render_delay = sink->priv->render_delay;
   GST_OBJECT_UNLOCK (sink);
 
   /* assume no latency */
@@ -977,19 +1069,16 @@
   max = -1;
   us_live = FALSE;
 
-  /* we are live */
-  if (l) {
-    if (have_latency) {
-      /* we are live and ready for a latency query */
-      query = gst_query_new_latency ();
-
-      /* ask the peer for the latency */
-      if (!(res = gst_base_sink_peer_query (sink, query)))
-        goto query_failed;
-
+  if (have_latency) {
+    GST_DEBUG_OBJECT (sink, "we are ready for LATENCY query");
+    /* we are ready for a latency query this is when we preroll or when we are
+     * not async. */
+    query = gst_query_new_latency ();
+
+    /* ask the peer for the latency */
+    if ((res = gst_base_sink_peer_query (sink, query))) {
       /* get upstream min and max latency */
       gst_query_parse_latency (query, &us_live, &us_min, &us_max);
-      gst_query_unref (query);
 
       if (us_live) {
         /* upstream live, use its latency, subclasses should use these
@@ -997,37 +1086,170 @@
         min = us_min;
         max = us_max;
       }
-    } else {
-      /* we are live but are not yet ready for a latency query */
-      res = FALSE;
+      if (l) {
+        /* we need to add the render delay if we are live */
+        if (min != -1)
+          min += render_delay;
+        if (max != -1)
+          max += render_delay;
+      }
     }
+    gst_query_unref (query);
   } else {
-    /* not live, result is always TRUE */
-    res = TRUE;
+    GST_DEBUG_OBJECT (sink, "we are not yet ready for LATENCY query");
+    res = FALSE;
+  }
+
+  /* not live, we tried to do the query, if it failed we return TRUE anyway */
+  if (!res) {
+    if (!l) {
+      res = TRUE;
+      GST_DEBUG_OBJECT (sink, "latency query failed but we are not live");
+    } else {
+      GST_DEBUG_OBJECT (sink, "latency query failed and we are live");
+    }
+  }
+
+  if (res) {
+    GST_DEBUG_OBJECT (sink, "latency query: live: %d, have_latency %d,"
+        " upstream: %d, min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, l,
+        have_latency, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+
+    if (live)
+      *live = l;
+    if (upstream_live)
+      *upstream_live = us_live;
+    if (min_latency)
+      *min_latency = min;
+    if (max_latency)
+      *max_latency = max;
   }
-
-  GST_DEBUG_OBJECT (sink, "latency query: live: %d, have_latency %d,"
-      " upstream: %d, min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, l,
-      have_latency, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (max));
-
-  if (live)
-    *live = l;
-  if (upstream_live)
-    *upstream_live = us_live;
-  if (min_latency)
-    *min_latency = min;
-  if (max_latency)
-    *max_latency = max;
+  return res;
+}
+
+/**
+ * gst_base_sink_set_render_delay:
+ * @sink: a #GstBaseSink
+ * @delay: the new delay
+ *
+ * Set the render delay in @sink to @delay. The render delay is the time 
+ * between actual rendering of a buffer and its synchronisation time. Some
+ * devices might delay media rendering which can be compensated for with this
+ * function. 
+ *
+ * After calling this function, this sink will report additional latency and
+ * other sinks will adjust their latency to delay the rendering of their media.
+ *
+ * This function is usually called by subclasses.
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_base_sink_set_render_delay (GstBaseSink * sink, GstClockTime delay)
+{
+  GstClockTime old_render_delay;
+
+  g_return_if_fail (GST_IS_BASE_SINK (sink));
+
+  GST_OBJECT_LOCK (sink);
+  old_render_delay = sink->priv->render_delay;
+  sink->priv->render_delay = delay;
+  GST_LOG_OBJECT (sink, "set render delay to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (delay));
+  GST_OBJECT_UNLOCK (sink);
+
+  if (delay != old_render_delay) {
+    GST_DEBUG_OBJECT (sink, "posting latency changed");
+    gst_element_post_message (GST_ELEMENT_CAST (sink),
+        gst_message_new_latency (GST_OBJECT_CAST (sink)));
+  }
+}
+
+/**
+ * gst_base_sink_get_render_delay:
+ * @sink: a #GstBaseSink
+ *
+ * Get the render delay of @sink. see gst_base_sink_set_render_delay() for more
+ * information about the render delay.
+ *
+ * Returns: the render delay of @sink.
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstClockTime
+gst_base_sink_get_render_delay (GstBaseSink * sink)
+{
+  GstClockTimeDiff res;
+
+  g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
+
+  GST_OBJECT_LOCK (sink);
+  res = sink->priv->render_delay;
+  GST_OBJECT_UNLOCK (sink);
 
   return res;
-
-  /* ERRORS */
-query_failed:
-  {
-    GST_DEBUG_OBJECT (sink, "latency query failed");
-    gst_query_unref (query);
-    return FALSE;
-  }
+}
+
+/**
+ * gst_base_sink_set_blocksize:
+ * @sink: a #GstBaseSink
+ * @blocksize: the blocksize in bytes
+ *
+ * Set the number of bytes that the sink will pull when it is operating in pull
+ * mode.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_base_sink_set_blocksize (GstBaseSink * sink, guint blocksize)
+{
+  g_return_if_fail (GST_IS_BASE_SINK (sink));
+
+  GST_OBJECT_LOCK (sink);
+  sink->priv->blocksize = blocksize;
+  GST_LOG_OBJECT (sink, "set blocksize to %u", blocksize);
+  GST_OBJECT_UNLOCK (sink);
+}
+
+/**
+ * gst_base_sink_get_blocksize:
+ * @sink: a #GstBaseSink
+ *
+ * Get the number of bytes that the sink will pull when it is operating in pull
+ * mode.
+ *
+ * Returns: the number of bytes @sink will pull in pull mode.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_base_sink_get_blocksize (GstBaseSink * sink)
+{
+  guint res;
+
+  g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
+
+  GST_OBJECT_LOCK (sink);
+  res = sink->priv->blocksize;
+  GST_OBJECT_UNLOCK (sink);
+
+  return res;
 }
 
 static void
@@ -1058,6 +1280,12 @@
     case PROP_TS_OFFSET:
       gst_base_sink_set_ts_offset (sink, g_value_get_int64 (value));
       break;
+    case PROP_BLOCKSIZE:
+      gst_base_sink_set_blocksize (sink, g_value_get_uint (value));
+      break;
+    case PROP_RENDER_DELAY:
+      gst_base_sink_set_render_delay (sink, g_value_get_uint64 (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1094,6 +1322,12 @@
     case PROP_LAST_BUFFER:
       gst_value_take_buffer (value, gst_base_sink_get_last_buffer (sink));
       break;
+    case PROP_BLOCKSIZE:
+      g_value_set_uint (value, gst_base_sink_get_blocksize (sink));
+      break;
+    case PROP_RENDER_DELAY:
+      g_value_set_uint64 (value, gst_base_sink_get_render_delay (sink));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1136,6 +1370,7 @@
   basesink->eos = FALSE;
   basesink->priv->received_eos = FALSE;
   basesink->have_preroll = FALSE;
+  basesink->priv->step_unlock = FALSE;
   basesink->eos_queued = FALSE;
   basesink->preroll_queued = 0;
   basesink->buffers_queued = 0;
@@ -1204,7 +1439,6 @@
   gboolean post_paused = FALSE;
   gboolean post_async_done = FALSE;
   gboolean post_playing = FALSE;
-  gboolean sync;
 
   /* we are certainly not playing async anymore now */
   basesink->playing_async = FALSE;
@@ -1214,7 +1448,6 @@
   next = GST_STATE_NEXT (basesink);
   pending = GST_STATE_PENDING (basesink);
   post_pending = pending;
-  sync = basesink->sync;
 
   switch (pending) {
     case GST_STATE_PLAYING:
@@ -1237,6 +1470,7 @@
 
       /* make sure we notify the subclass of async playing */
       if (bclass->async_play) {
+        GST_WARNING_OBJECT (basesink, "deprecated async_play");
         ret = bclass->async_play (basesink);
         if (ret == GST_STATE_CHANGE_FAILURE)
           goto async_failed;
@@ -1334,6 +1568,227 @@
   }
 }
 
+static void
+start_stepping (GstBaseSink * sink, GstSegment * segment,
+    GstStepInfo * pending, GstStepInfo * current)
+{
+  gint64 end;
+  GstMessage *message;
+
+  GST_DEBUG_OBJECT (sink, "update pending step");
+
+  GST_OBJECT_LOCK (sink);
+  memcpy (current, pending, sizeof (GstStepInfo));
+  pending->valid = FALSE;
+  GST_OBJECT_UNLOCK (sink);
+
+  /* post message first */
+  message =
+      gst_message_new_step_start (GST_OBJECT (sink), TRUE, current->format,
+      current->amount, current->rate, current->flush, current->intermediate);
+  gst_message_set_seqnum (message, current->seqnum);
+  gst_element_post_message (GST_ELEMENT (sink), message);
+
+  /* get the running time of where we paused and remember it */
+  current->start = gst_element_get_start_time (GST_ELEMENT_CAST (sink));
+  gst_segment_set_running_time (segment, GST_FORMAT_TIME, current->start);
+
+  /* set the new rate for the remainder of the segment */
+  current->start_rate = segment->rate;
+  segment->rate *= current->rate;
+  segment->abs_rate = ABS (segment->rate);
+
+  /* save values */
+  if (segment->rate > 0.0)
+    current->start_stop = segment->stop;
+  else
+    current->start_start = segment->start;
+
+  if (current->format == GST_FORMAT_TIME) {
+    end = current->start + current->amount;
+    if (!current->flush) {
+      /* update the segment clipping regions for non-flushing seeks */
+      if (segment->rate > 0.0) {
+        segment->stop = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
+        segment->last_stop = segment->stop;
+      } else {
+        gint64 position;
+
+        position = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
+        segment->time = position;
+        segment->start = position;
+        segment->last_stop = position;
+      }
+    }
+  }
+
+  GST_DEBUG_OBJECT (sink,
+      "segment now rate %lf, applied rate %lf, "
+      "format GST_FORMAT_TIME, "
+      "%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
+      ", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
+      segment->rate, segment->applied_rate, GST_TIME_ARGS (segment->start),
+      GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
+      GST_TIME_ARGS (segment->accum));
+
+  GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (current->start));
+
+  if (current->amount == -1) {
+    GST_DEBUG_OBJECT (sink, "step amount == -1, stop stepping");
+    current->valid = FALSE;
+  } else {
+    GST_DEBUG_OBJECT (sink, "step amount: %" G_GUINT64_FORMAT ", format: %s, "
+        "rate: %f", current->amount, gst_format_get_name (current->format),
+        current->rate);
+  }
+}
+
+static void
+stop_stepping (GstBaseSink * sink, GstSegment * segment,
+    GstStepInfo * current, gint64 rstart, gint64 rstop, gboolean eos)
+{
+  gint64 stop, position;
+  GstMessage *message;
+
+  GST_DEBUG_OBJECT (sink, "step complete");
+
+  if (segment->rate > 0.0)
+    stop = rstart;
+  else
+    stop = rstop;
+
+  GST_DEBUG_OBJECT (sink,
+      "step stop at running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (stop));
+
+  if (stop == -1)
+    current->duration = current->position;
+  else
+    current->duration = stop - current->start;
+
+  GST_DEBUG_OBJECT (sink, "step elapsed running_time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (current->duration));
+
+  position = current->start + current->duration;
+
+  /* now move the segment to the new running time */
+  gst_segment_set_running_time (segment, GST_FORMAT_TIME, position);
+
+  if (current->flush) {
+    /* and remove the accumulated time we flushed, start time did not change */
+    segment->accum = current->start;
+  } else {
+    /* start time is now the stepped position */
+    gst_element_set_start_time (GST_ELEMENT_CAST (sink), position);
+  }
+
+  /* restore the previous rate */
+  segment->rate = current->start_rate;
+  segment->abs_rate = ABS (segment->rate);
+
+  if (segment->rate > 0.0)
+    segment->stop = current->start_stop;
+  else
+    segment->start = current->start_start;
+
+  /* the clip segment is used for position report in paused... */
+  memcpy (sink->abidata.ABI.clip_segment, segment, sizeof (GstSegment));
+
+  /* post the step done when we know the stepped duration in TIME */
+  message =
+      gst_message_new_step_done (GST_OBJECT_CAST (sink), current->format,
+      current->amount, current->rate, current->flush, current->intermediate,
+      current->duration, eos);
+  gst_message_set_seqnum (message, current->seqnum);
+  gst_element_post_message (GST_ELEMENT_CAST (sink), message);
+
+  if (!current->intermediate)
+    sink->need_preroll = current->need_preroll;
+
+  /* and the current step info finished and becomes invalid */
+  current->valid = FALSE;
+}
+
+static gboolean
+handle_stepping (GstBaseSink * sink, GstSegment * segment,
+    GstStepInfo * current, gint64 * cstart, gint64 * cstop, gint64 * rstart,
+    gint64 * rstop)
+{
+  GstBaseSinkPrivate *priv;
+  gboolean step_end = FALSE;
+
+  priv = sink->priv;
+
+  /* see if we need to skip this buffer because of stepping */
+  switch (current->format) {
+    case GST_FORMAT_TIME:
+    {
+      guint64 end;
+      gint64 first, last;
+
+      if (segment->rate > 0.0) {
+        first = *rstart;
+        last = *rstop;
+      } else {
+        first = *rstop;
+        last = *rstart;
+      }
+
+      end = current->start + current->amount;
+      current->position = first - current->start;
+
+      if (G_UNLIKELY (segment->abs_rate != 1.0))
+        current->position /= segment->abs_rate;
+
+      GST_DEBUG_OBJECT (sink,
+          "buffer: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
+          GST_TIME_ARGS (first), GST_TIME_ARGS (last));
+      GST_DEBUG_OBJECT (sink,
+          "got time step %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "/%"
+          GST_TIME_FORMAT, GST_TIME_ARGS (current->position),
+          GST_TIME_ARGS (last - current->start),
+          GST_TIME_ARGS (current->amount));
+
+      if ((current->flush && current->position >= current->amount)
+          || last >= end) {
+        GST_DEBUG_OBJECT (sink, "step ended, we need clipping");
+        step_end = TRUE;
+        if (segment->rate > 0.0) {
+          *rstart = end;
+          *cstart = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
+        } else {
+          *rstop = end;
+          *cstop = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
+        }
+      }
+      GST_DEBUG_OBJECT (sink,
+          "cstart %" GST_TIME_FORMAT ", rstart %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (*cstart), GST_TIME_ARGS (*rstart));
+      GST_DEBUG_OBJECT (sink,
+          "cstop %" GST_TIME_FORMAT ", rstop %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (*cstop), GST_TIME_ARGS (*rstop));
+      break;
+    }
+    case GST_FORMAT_BUFFERS:
+      GST_DEBUG_OBJECT (sink,
+          "got default step %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
+          current->position, current->amount);
+
+      if (current->position < current->amount) {
+        current->position++;
+      } else {
+        step_end = TRUE;
+      }
+      break;
+    case GST_FORMAT_DEFAULT:
+    default:
+      GST_DEBUG_OBJECT (sink,
+          "got unknown step %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
+          current->position, current->amount);
+      break;
+  }
+  return step_end;
+}
 
 /* with STREAM_LOCK, PREROLL_LOCK
  *
@@ -1347,7 +1802,8 @@
 gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
     GstClockTime * rsstart, GstClockTime * rsstop,
     GstClockTime * rrstart, GstClockTime * rrstop, gboolean * do_sync,
-    GstSegment * segment)
+    gboolean * stepped, GstSegment * segment, GstStepInfo * step,
+    gboolean * step_end)
 {
   GstBaseSinkClass *bclass;
   GstBuffer *buffer;
@@ -1357,11 +1813,12 @@
   GstClockTime sstart, sstop;   /* clipped timestamps converted to stream time */
   GstFormat format;
   GstBaseSinkPrivate *priv;
+  gboolean eos;
 
   priv = basesink->priv;
 
   /* start with nothing */
-  start = stop = sstart = sstop = rstart = rstop = -1;
+  start = stop = -1;
 
   if (G_UNLIKELY (GST_IS_EVENT (obj))) {
     GstEvent *event = GST_EVENT_CAST (obj);
@@ -1369,33 +1826,58 @@
     switch (GST_EVENT_TYPE (event)) {
         /* EOS event needs syncing */
       case GST_EVENT_EOS:
-        sstart = sstop = priv->current_sstop;
+      {
+        if (basesink->segment.rate >= 0.0) {
+          sstart = sstop = priv->current_sstop;
+          if (sstart == -1) {
+            /* we have not seen a buffer yet, use the segment values */
+            sstart = sstop = gst_segment_to_stream_time (&basesink->segment,
+                basesink->segment.format, basesink->segment.stop);
+          }
+        } else {
+          sstart = sstop = priv->current_sstart;
+          if (sstart == -1) {
+            /* we have not seen a buffer yet, use the segment values */
+            sstart = sstop = gst_segment_to_stream_time (&basesink->segment,
+                basesink->segment.format, basesink->segment.start);
+          }
+        }
+
         rstart = rstop = priv->eos_rtime;
         *do_sync = rstart != -1;
         GST_DEBUG_OBJECT (basesink, "sync times for EOS %" GST_TIME_FORMAT,
             GST_TIME_ARGS (rstart));
-        goto done;
+        /* if we are stepping, we end now */
+        *step_end = step->valid;
+        eos = TRUE;
+        goto eos_done;
+      }
+      default:
         /* other events do not need syncing */
         /* FIXME, maybe NEWSEGMENT might need synchronisation
          * since the POSITION query depends on accumulated times and
          * we cannot accumulate the current segment before the previous
          * one completed.
          */
-      default:
         return FALSE;
     }
   }
 
+  eos = FALSE;
+
   /* else do buffer sync code */
   buffer = GST_BUFFER_CAST (obj);
 
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
-  /* just get the times to see if we need syncing */
+  /* just get the times to see if we need syncing, if the start returns -1 we
+   * don't sync. */
   if (bclass->get_times)
     bclass->get_times (basesink, buffer, &start, &stop);
 
   if (start == -1) {
+    /* we don't need to sync but we still want to get the timestamps for
+     * tracking the position */
     gst_base_sink_get_times (basesink, buffer, &start, &stop);
     *do_sync = FALSE;
   } else {
@@ -1409,19 +1891,33 @@
   /* collect segment and format for code clarity */
   format = segment->format;
 
-  /* no timestamp clipping if we did not * get a TIME segment format */
+  /* no timestamp clipping if we did not get a TIME segment format */
   if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
     cstart = start;
     cstop = stop;
     /* do running and stream time in TIME format */
     format = GST_FORMAT_TIME;
+    GST_LOG_OBJECT (basesink, "not time format, don't clip");
     goto do_times;
   }
 
-  /* clip */
+  /* clip, only when we know about time */
   if (G_UNLIKELY (!gst_segment_clip (segment, GST_FORMAT_TIME,
-              (gint64) start, (gint64) stop, &cstart, &cstop)))
+              (gint64) start, (gint64) stop, &cstart, &cstop))) {
+    if (step->valid) {
+      GST_DEBUG_OBJECT (basesink, "step out of segment");
+      /* when we are stepping, pretend we're at the end of the segment */
+      if (segment->rate > 0.0) {
+        cstart = segment->stop;
+        cstop = segment->stop;
+      } else {
+        cstart = segment->start;
+        cstop = segment->start;
+      }
+      goto do_times;
+    }
     goto out_of_segment;
+  }
 
   if (G_UNLIKELY (start != cstart || stop != cstop)) {
     GST_DEBUG_OBJECT (basesink, "clipped to: start %" GST_TIME_FORMAT
@@ -1430,17 +1926,35 @@
   }
 
   /* set last stop position */
-  gst_segment_set_last_stop (segment, GST_FORMAT_TIME, cstop);
+  if (G_LIKELY (cstop != GST_CLOCK_TIME_NONE))
+    gst_segment_set_last_stop (segment, GST_FORMAT_TIME, cstop);
+  else
+    gst_segment_set_last_stop (segment, GST_FORMAT_TIME, cstart);
 
 do_times:
+  rstart = gst_segment_to_running_time (segment, format, cstart);
+  rstop = gst_segment_to_running_time (segment, format, cstop);
+
+  if (G_UNLIKELY (step->valid)) {
+    if (!(*step_end = handle_stepping (basesink, segment, step, &cstart, &cstop,
+                &rstart, &rstop))) {
+      /* step is still busy, we discard data when we are flushing */
+      *stepped = step->flush;
+    }
+  }
   /* this can produce wrong values if we accumulated non-TIME segments. If this happens,
    * upstream is behaving very badly */
   sstart = gst_segment_to_stream_time (segment, format, cstart);
   sstop = gst_segment_to_stream_time (segment, format, cstop);
-  rstart = gst_segment_to_running_time (segment, format, cstart);
-  rstop = gst_segment_to_running_time (segment, format, cstop);
-
-done:
+
+eos_done:
+  /* eos_done label only called when doing EOS, we also stop stepping then */
+  if (*step_end && step->flush) {
+    GST_DEBUG_OBJECT (basesink, "flushing step ended");
+    stop_stepping (basesink, segment, step, rstart, rstop, eos);
+    *step_end = FALSE;
+  }
+
   /* save times */
   *rsstart = sstart;
   *rsstop = sstop;
@@ -1453,49 +1967,25 @@
   /* special cases */
 out_of_segment:
   {
-    /* should not happen since we clip them in the chain function already, 
-     * we return FALSE so that we don't try to sync on it. */
-    GST_ELEMENT_WARNING (basesink, STREAM, FAILED,
-        (NULL), ("unexpected buffer out of segment found."));
+    /* we usually clip in the chain function already but stepping could cause
+     * the segment to be updated later. we return FALSE so that we don't try
+     * to sync on it. */
     GST_LOG_OBJECT (basesink, "buffer skipped, not in segment");
     return FALSE;
   }
 }
 
-/* with STREAM_LOCK, PREROLL_LOCK
- *
- * Waits for the clock to reach @time. If @time is not valid, no
- * synchronisation is done and BADTIME is returned. 
- * If synchronisation is disabled in the element or there is no
- * clock, no synchronisation is done and BADTIME is returned.
- *
- * Else a blocking wait is performed on the clock. We save the ClockID
- * so we can unlock the entry at any time. While we are blocking, we 
- * release the PREROLL_LOCK so that other threads can interrupt the entry.
- *
- * @time is expressed in running time.
- */
-static GstClockReturn
-gst_base_sink_wait_clock (GstBaseSink * basesink, GstClockTime time,
-    GstClockTimeDiff * jitter)
+/* with STREAM_LOCK, PREROLL_LOCK, LOCK
+ * adjust a timestamp with the latency and timestamp offset */
+static GstClockTime
+gst_base_sink_adjust_time (GstBaseSink * basesink, GstClockTime time)
 {
-  GstClockID id;
-  GstClockReturn ret;
-  GstClock *clock;
   GstClockTimeDiff ts_offset;
 
+  /* don't do anything funny with invalid timestamps */
   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time)))
-    goto invalid_time;
-
-  GST_OBJECT_LOCK (basesink);
-  if (G_UNLIKELY (!basesink->sync))
-    goto no_sync;
-
-  if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (basesink)) == NULL))
-    goto no_clock;
-
-  /* add base time and latency */
-  time += GST_ELEMENT_CAST (basesink)->base_time;
+    return time;
+
   time += basesink->priv->latency;
 
   /* apply offset, be carefull for underflows */
@@ -1509,37 +1999,94 @@
   } else
     time += ts_offset;
 
+  return time;
+}
+
+/**
+ * gst_base_sink_wait_clock:
+ * @sink: the sink
+ * @time: the running_time to be reached
+ * @jitter: the jitter to be filled with time diff (can be NULL)
+ *
+ * This function will block until @time is reached. It is usually called by
+ * subclasses that use their own internal synchronisation.
+ *
+ * If @time is not valid, no sycnhronisation is done and #GST_CLOCK_BADTIME is
+ * returned. Likewise, if synchronisation is disabled in the element or there
+ * is no clock, no synchronisation is done and #GST_CLOCK_BADTIME is returned.
+ *
+ * This function should only be called with the PREROLL_LOCK held, like when
+ * receiving an EOS event in the ::event vmethod or when receiving a buffer in
+ * the ::render vmethod.
+ *
+ * The @time argument should be the running_time of when this method should
+ * return and is not adjusted with any latency or offset configured in the
+ * sink.
+ *
+ * Since 0.10.20
+ *
+ * Returns: #GstClockReturn
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstClockReturn
+gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
+    GstClockTimeDiff * jitter)
+{
+  GstClockID id;
+  GstClockReturn ret;
+  GstClock *clock;
+
+  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time)))
+    goto invalid_time;
+
+  GST_OBJECT_LOCK (sink);
+  if (G_UNLIKELY (!sink->sync))
+    goto no_sync;
+
+  if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (sink)) == NULL))
+    goto no_clock;
+
+  /* add base_time to running_time to get the time against the clock */
+  time += GST_ELEMENT_CAST (sink)->base_time;
+
   id = gst_clock_new_single_shot_id (clock, time);
-  GST_OBJECT_UNLOCK (basesink);
-
-  basesink->clock_id = id;
+  GST_OBJECT_UNLOCK (sink);
+
+  /* A blocking wait is performed on the clock. We save the ClockID
+   * so we can unlock the entry at any time. While we are blocking, we 
+   * release the PREROLL_LOCK so that other threads can interrupt the
+   * entry. */
+  sink->clock_id = id;
   /* release the preroll lock while waiting */
-  GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+  GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
 
   ret = gst_clock_id_wait (id, jitter);
 
-  GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+  GST_PAD_PREROLL_LOCK (sink->sinkpad);
   gst_clock_id_unref (id);
-  basesink->clock_id = NULL;
+  sink->clock_id = NULL;
 
   return ret;
 
   /* no syncing needed */
 invalid_time:
   {
-    GST_DEBUG_OBJECT (basesink, "time not valid, no sync needed");
+    GST_DEBUG_OBJECT (sink, "time not valid, no sync needed");
     return GST_CLOCK_BADTIME;
   }
 no_sync:
   {
-    GST_DEBUG_OBJECT (basesink, "sync disabled");
-    GST_OBJECT_UNLOCK (basesink);
+    GST_DEBUG_OBJECT (sink, "sync disabled");
+    GST_OBJECT_UNLOCK (sink);
     return GST_CLOCK_BADTIME;
   }
 no_clock:
   {
-    GST_DEBUG_OBJECT (basesink, "no clock, can't sync");
-    GST_OBJECT_UNLOCK (basesink);
+    GST_DEBUG_OBJECT (sink, "no clock, can't sync");
+    GST_OBJECT_UNLOCK (sink);
     return GST_CLOCK_BADTIME;
   }
 }
@@ -1557,6 +2104,9 @@
  * to a state change to READY or a FLUSH event (in which case this function
  * returns #GST_FLOW_WRONG_STATE).
  *
+ * This function should only be called with the PREROLL_LOCK held, like in the
+ * render function.
+ *
  * Since: 0.10.11
  *
  * Returns: #GST_FLOW_OK if the preroll completed and processing can
@@ -1576,6 +2126,8 @@
   sink->have_preroll = FALSE;
   if (G_UNLIKELY (sink->flushing))
     goto stopping;
+  if (G_UNLIKELY (sink->priv->step_unlock))
+    goto step_unlocked;
   GST_DEBUG_OBJECT (sink, "continue after preroll");
 
   return GST_FLOW_OK;
@@ -1583,9 +2135,71 @@
   /* ERRORS */
 stopping:
   {
-    GST_DEBUG_OBJECT (sink, "preroll interrupted");
+    GST_DEBUG_OBJECT (sink, "preroll interrupted because of flush");
     return GST_FLOW_WRONG_STATE;
   }
+step_unlocked:
+  {
+    sink->priv->step_unlock = FALSE;
+    GST_DEBUG_OBJECT (sink, "preroll interrupted because of step");
+    return GST_FLOW_STEP;
+  }
+}
+
+/**
+ * gst_base_sink_do_preroll:
+ * @sink: the sink
+ * @obj: the object that caused the preroll
+ *
+ * If the @sink spawns its own thread for pulling buffers from upstream it
+ * should call this method after it has pulled a buffer. If the element needed
+ * to preroll, this function will perform the preroll and will then block
+ * until the element state is changed.
+ *
+ * This function should be called with the PREROLL_LOCK held.
+ *
+ * Since 0.10.22
+ *
+ * Returns: #GST_FLOW_OK if the preroll completed and processing can
+ * continue. Any other return value should be returned from the render vmethod.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstFlowReturn
+gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
+{
+  GstFlowReturn ret;
+
+  while (G_UNLIKELY (sink->need_preroll)) {
+    GST_DEBUG_OBJECT (sink, "prerolling object %p", obj);
+
+    ret = gst_base_sink_preroll_object (sink, FALSE, obj);
+    if (ret != GST_FLOW_OK)
+      goto preroll_failed;
+
+    /* need to recheck here because the commit state could have
+     * made us not need the preroll anymore */
+    if (G_LIKELY (sink->need_preroll)) {
+      /* block until the state changes, or we get a flush, or something */
+      ret = gst_base_sink_wait_preroll (sink);
+      if (ret != GST_FLOW_OK) {
+        if (ret == GST_FLOW_STEP)
+          ret = GST_FLOW_OK;
+        else
+          goto preroll_failed;
+      }
+    }
+  }
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+preroll_failed:
+  {
+    GST_DEBUG_OBJECT (sink, "preroll failed %d", ret);
+    return ret;
+  }
 }
 
 /**
@@ -1601,6 +2215,9 @@
  * This function should only be called with the PREROLL_LOCK held, like when
  * receiving an EOS event in the ::event vmethod.
  *
+ * The @time argument should be the running_time of when the EOS should happen
+ * and will be adjusted with any latency and offset configured in the sink.
+ *
  * Since 0.10.15
  *
  * Returns: #GstFlowReturn
@@ -1617,22 +2234,32 @@
   GstFlowReturn ret;
 
   do {
+    GstClockTime stime;
+
     GST_DEBUG_OBJECT (sink, "checking preroll");
 
     /* first wait for the playing state before we can continue */
     if (G_UNLIKELY (sink->need_preroll)) {
       ret = gst_base_sink_wait_preroll (sink);
-      if (ret != GST_FLOW_OK)
-        goto flushing;
+      if (ret != GST_FLOW_OK) {
+        if (ret == GST_FLOW_STEP)
+          ret = GST_FLOW_OK;
+        else
+          goto flushing;
+      }
     }
 
     /* preroll done, we can sync since we are in PLAYING now. */
     GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %"
         GST_TIME_FORMAT, GST_TIME_ARGS (time));
 
+    /* compensate for latency and ts_offset. We don't adjust for render delay
+     * because we don't interact with the device on EOS normally. */
+    stime = gst_base_sink_adjust_time (sink, time);
+
     /* wait for the clock, this can be interrupted because we got shut down or 
      * we PAUSED. */
-    status = gst_base_sink_wait_clock (sink, time, jitter);
+    status = gst_base_sink_wait_clock (sink, stime, jitter);
 
     GST_DEBUG_OBJECT (sink, "clock returned %d", status);
 
@@ -1684,25 +2311,38 @@
  */
 static GstFlowReturn
 gst_base_sink_do_sync (GstBaseSink * basesink, GstPad * pad,
-    GstMiniObject * obj, gboolean * late)
+    GstMiniObject * obj, gboolean * late, gboolean * step_end)
 {
   GstClockTimeDiff jitter;
   gboolean syncable;
   GstClockReturn status = GST_CLOCK_OK;
-  GstClockTime rstart, rstop, sstart, sstop;
+  GstClockTime rstart, rstop, sstart, sstop, stime;
   gboolean do_sync;
   GstBaseSinkPrivate *priv;
+  GstFlowReturn ret;
+  GstStepInfo *current, *pending;
+  gboolean stepped;
 
   priv = basesink->priv;
 
+do_step:
   sstart = sstop = rstart = rstop = -1;
   do_sync = TRUE;
+  stepped = FALSE;
 
   priv->current_rstart = -1;
 
+  /* get stepping info */
+  current = &priv->current_step;
+  pending = &priv->pending_step;
+
   /* get timing information for this object against the render segment */
   syncable = gst_base_sink_get_sync_times (basesink, obj,
-      &sstart, &sstop, &rstart, &rstop, &do_sync, &basesink->segment);
+      &sstart, &sstop, &rstart, &rstop, &do_sync, &stepped, &basesink->segment,
+      current, step_end);
+
+  if (G_UNLIKELY (stepped))
+    goto step_skipped;
 
   /* a syncable object needs to participate in preroll and
    * clocking. All buffers and EOS are syncable. */
@@ -1712,31 +2352,17 @@
   /* store timing info for current object */
   priv->current_rstart = rstart;
   priv->current_rstop = (rstop != -1 ? rstop : rstart);
+
   /* save sync time for eos when the previous object needed sync */
   priv->eos_rtime = (do_sync ? priv->current_rstop : -1);
 
 again:
   /* first do preroll, this makes sure we commit our state
    * to PAUSED and can continue to PLAYING. We cannot perform
-   * any clock sync in PAUSED because there is no clock. 
-   */
-  while (G_UNLIKELY (basesink->need_preroll)) {
-    GST_DEBUG_OBJECT (basesink, "prerolling object %p", obj);
-
-    if (G_LIKELY (basesink->playing_async)) {
-      /* commit state */
-      if (G_UNLIKELY (!gst_base_sink_commit_state (basesink)))
-        goto stopping;
-    }
-
-    /* need to recheck here because the commit state could have
-     * made us not need the preroll anymore */
-    if (G_LIKELY (basesink->need_preroll)) {
-      /* block until the state changes, or we get a flush, or something */
-      if (gst_base_sink_wait_preroll (basesink) != GST_FLOW_OK)
-        goto flushing;
-    }
-  }
+   * any clock sync in PAUSED because there is no clock. */
+  ret = gst_base_sink_do_preroll (basesink, obj);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto preroll_failed;
 
   /* After rendering we store the position of the last buffer so that we can use
    * it to report the position. We need to take the lock here. */
@@ -1745,16 +2371,35 @@
   priv->current_sstop = (sstop != -1 ? sstop : sstart);
   GST_OBJECT_UNLOCK (basesink);
 
+  /* update the segment with a pending step if the current one is invalid and we
+   * have a new pending one. We only accept new step updates after a preroll */
+  if (G_UNLIKELY (pending->valid && !current->valid)) {
+    start_stepping (basesink, &basesink->segment, pending, current);
+    goto do_step;
+  }
+
   if (!do_sync)
     goto done;
 
+  /* adjust for latency */
+  stime = gst_base_sink_adjust_time (basesink, rstart);
+
+  /* adjust for render-delay, avoid underflows */
+  if (stime != -1) {
+    if (stime > priv->render_delay)
+      stime -= priv->render_delay;
+    else
+      stime = 0;
+  }
+
   /* preroll done, we can sync since we are in PLAYING now. */
   GST_DEBUG_OBJECT (basesink, "possibly waiting for clock to reach %"
-      GST_TIME_FORMAT, GST_TIME_ARGS (rstart));
-
-  /* this function will return immediatly if start == -1, no clock
+      GST_TIME_FORMAT ", adjusted %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (rstart), GST_TIME_ARGS (stime));
+
+  /* This function will return immediatly if start == -1, no clock
    * or sync is disabled with GST_CLOCK_BADTIME. */
-  status = gst_base_sink_wait_clock (basesink, rstart, &jitter);
+  status = gst_base_sink_wait_clock (basesink, stime, &jitter);
 
   GST_DEBUG_OBJECT (basesink, "clock returned %d", status);
 
@@ -1770,6 +2415,7 @@
    * we can try to preroll on the current buffer. */
   if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
     GST_DEBUG_OBJECT (basesink, "unscheduled, waiting some more");
+    priv->call_preroll = TRUE;
     goto again;
   }
 
@@ -1784,6 +2430,12 @@
   return GST_FLOW_OK;
 
   /* ERRORS */
+step_skipped:
+  {
+    GST_DEBUG_OBJECT (basesink, "skipped stepped object %p", obj);
+    *late = TRUE;
+    return GST_FLOW_OK;
+  }
 not_syncable:
   {
     GST_DEBUG_OBJECT (basesink, "non syncable object %p", obj);
@@ -1794,10 +2446,11 @@
     GST_DEBUG_OBJECT (basesink, "we are flushing");
     return GST_FLOW_WRONG_STATE;
   }
-stopping:
+preroll_failed:
   {
-    GST_DEBUG_OBJECT (basesink, "stopping while commiting state");
-    return GST_FLOW_WRONG_STATE;
+    GST_DEBUG_OBJECT (basesink, "preroll failed");
+    *step_end = FALSE;
+    return ret;
   }
 }
 
@@ -1835,6 +2488,9 @@
 
   start = priv->current_rstart;
 
+  if (priv->current_step.valid)
+    return;
+
   /* if Quality-of-Service disabled, do nothing */
   if (!g_atomic_int_get (&priv->qos_enabled) || start == -1)
     return;
@@ -1842,10 +2498,19 @@
   stop = priv->current_rstop;
   jitter = priv->current_jitter;
 
-  /* this is the time the buffer entered the sink */
-  entered = start + jitter;
-  /* this is the time the buffer left the sink */
-  left = start + (jitter < 0 ? 0 : jitter);
+  if (jitter < 0) {
+    /* this is the time the buffer entered the sink */
+    if (start < -jitter)
+      entered = 0;
+    else
+      entered = start + jitter;
+    left = start;
+  } else {
+    /* this is the time the buffer entered the sink */
+    entered = start + jitter;
+    /* this is the time the buffer left the sink */
+    left = start + jitter;
+  }
 
   /* calculate duration of the buffer */
   if (stop != -1)
@@ -1913,8 +2578,14 @@
       GST_TIME_ARGS (priv->avg_pt), priv->avg_rate);
 
 
-  /* if we have a valid rate, start sending QoS messages */
   if (priv->avg_rate >= 0.0) {
+    /* if we have a valid rate, start sending QoS messages */
+    if (priv->current_jitter < 0) {
+      /* make sure we never go below 0 when adding the jitter to the
+       * timestamp. */
+      if (priv->current_rstart < -priv->current_jitter)
+        priv->current_jitter = -priv->current_rstart;
+    }
     gst_base_sink_send_qos (sink, priv->avg_rate, priv->current_rstart,
         priv->current_jitter);
   }
@@ -1990,14 +2661,18 @@
 
   /* if the jitter bigger than duration and lateness we are too late */
   if ((late = start + jitter > max_lateness)) {
-    GST_DEBUG_OBJECT (basesink, "buffer is too late %" GST_TIME_FORMAT
+    GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, basesink,
+        "buffer is too late %" GST_TIME_FORMAT
         " > %" GST_TIME_FORMAT, GST_TIME_ARGS (start + jitter),
         GST_TIME_ARGS (max_lateness));
     /* !!emergency!!, if we did not receive anything valid for more than a 
      * second, render it anyway so the user sees something */
-    if (priv->last_in_time && start - priv->last_in_time > GST_SECOND) {
+    if (priv->last_in_time != -1 && start - priv->last_in_time > GST_SECOND) {
       late = FALSE;
-      GST_DEBUG_OBJECT (basesink,
+      GST_ELEMENT_WARNING (basesink, CORE, CLOCK,
+          (_("A lot of buffers are being dropped.")),
+          ("There may be a timestamping problem, or this computer is too slow."));
+      GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, basesink,
           "**emergency** last buffer at %" GST_TIME_FORMAT " > GST_SECOND",
           GST_TIME_ARGS (priv->last_in_time));
     }
@@ -2032,6 +2707,9 @@
   }
 }
 
+/* called before and after calling the render vmethod. It keeps track of how
+ * much time was spent in the render method and is used to check if we are
+ * flooded */
 static void
 gst_base_sink_do_render_stats (GstBaseSink * basesink, gboolean start)
 {
@@ -2066,53 +2744,88 @@
  */
 static GstFlowReturn
 gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
-    GstMiniObject * obj)
+    gboolean is_list, gpointer obj)
 {
-  GstFlowReturn ret = GST_FLOW_OK;
+  GstFlowReturn ret;
   GstBaseSinkClass *bclass;
-  gboolean late = FALSE;
+  gboolean late, step_end;
+  gpointer sync_obj;
+
   GstBaseSinkPrivate *priv;
 
   priv = basesink->priv;
 
+  if (is_list) {
+    /*
+     * If buffer list, use the first group buffer within the list
+     * for syncing
+     */
+    sync_obj = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
+    g_assert (NULL != sync_obj);
+  } else {
+    sync_obj = obj;
+  }
+
+again:
+  late = FALSE;
+  step_end = FALSE;
+  ret = GST_FLOW_OK;
+
   /* synchronize this object, non syncable objects return OK
    * immediatly. */
-  ret = gst_base_sink_do_sync (basesink, pad, obj, &late);
+  ret = gst_base_sink_do_sync (basesink, pad, sync_obj, &late, &step_end);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto sync_failed;
 
-  /* and now render, event or buffer. */
-  if (G_LIKELY (GST_IS_BUFFER (obj))) {
-    GstBuffer *buf;
-
+  /* and now render, event or buffer/buffer list. */
+  if (G_LIKELY (is_list || GST_IS_BUFFER (obj))) {
     /* drop late buffers unconditionally, let's hope it's unlikely */
     if (G_UNLIKELY (late))
       goto dropped;
 
-    buf = GST_BUFFER_CAST (obj);
-
-    gst_base_sink_set_last_buffer (basesink, buf);
-
     bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
-    if (G_LIKELY (bclass->render)) {
+    if (G_LIKELY ((is_list && bclass->render_list) ||
+            (!is_list && bclass->render))) {
       gint do_qos;
 
       /* read once, to get same value before and after */
       do_qos = g_atomic_int_get (&priv->qos_enabled);
 
-      GST_DEBUG_OBJECT (basesink, "rendering buffer %p", obj);
+      GST_DEBUG_OBJECT (basesink, "rendering object %p", obj);
 
       /* record rendering time for QoS and stats */
       if (do_qos)
         gst_base_sink_do_render_stats (basesink, TRUE);
 
-      ret = bclass->render (basesink, buf);
-
-      priv->rendered++;
+      if (!is_list) {
+        GstBuffer *buf;
+
+        /* For buffer lists do not set last buffer. Creating buffer
+         * with meaningful data can be done only with memcpy which will
+         * significantly affect performance */
+        buf = GST_BUFFER_CAST (obj);
+        gst_base_sink_set_last_buffer (basesink, buf);
+
+        ret = bclass->render (basesink, buf);
+      } else {
+        GstBufferList *buflist;
+
+        buflist = GST_BUFFER_LIST_CAST (obj);
+
+        ret = bclass->render_list (basesink, buflist);
+      }
 
       if (do_qos)
         gst_base_sink_do_render_stats (basesink, FALSE);
+
+      if (ret == GST_FLOW_STEP)
+        goto again;
+
+      if (G_UNLIKELY (basesink->flushing))
+        goto flushing;
+
+      priv->rendered++;
     }
   } else {
     GstEvent *event = GST_EVENT_CAST (obj);
@@ -2129,9 +2842,22 @@
     if (bclass->event)
       event_res = bclass->event (basesink, event);
 
+    /* when we get here we could be flushing again when the event handler calls
+     * _wait_eos(). We have to ignore this object in that case. */
+    if (G_UNLIKELY (basesink->flushing))
+      goto flushing;
+
     if (G_LIKELY (event_res)) {
+      guint32 seqnum;
+
+      seqnum = basesink->priv->seqnum = gst_event_get_seqnum (event);
+      GST_DEBUG_OBJECT (basesink, "Got seqnum #%" G_GUINT32_FORMAT, seqnum);
+
       switch (type) {
         case GST_EVENT_EOS:
+        {
+          GstMessage *message;
+
           /* the EOS event is completely handled so we mark
            * ourselves as being in the EOS state. eos is also 
            * protected by the object lock so we can read it when 
@@ -2139,11 +2865,15 @@
           GST_OBJECT_LOCK (basesink);
           basesink->eos = TRUE;
           GST_OBJECT_UNLOCK (basesink);
+
           /* ok, now we can post the message */
           GST_DEBUG_OBJECT (basesink, "Now posting EOS");
-          gst_element_post_message (GST_ELEMENT_CAST (basesink),
-              gst_message_new_eos (GST_OBJECT_CAST (basesink)));
+
+          message = gst_message_new_eos (GST_OBJECT_CAST (basesink));
+          gst_message_set_seqnum (message, seqnum);
+          gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
           break;
+        }
         case GST_EVENT_NEWSEGMENT:
           /* configure the segment */
           gst_base_sink_configure_segment (basesink, pad, event,
@@ -2156,11 +2886,18 @@
   }
 
 done:
+  if (step_end) {
+    /* the step ended, check if we need to activate a new step */
+    GST_DEBUG_OBJECT (basesink, "step ended");
+    stop_stepping (basesink, &basesink->segment, &priv->current_step,
+        priv->current_rstart, priv->current_rstop, basesink->eos);
+    goto again;
+  }
+
   gst_base_sink_perform_qos (basesink, late);
 
   GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj);
-  gst_mini_object_unref (obj);
-
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
   return ret;
 
   /* ERRORS */
@@ -2175,6 +2912,12 @@
     GST_DEBUG_OBJECT (basesink, "buffer late, dropping");
     goto done;
   }
+flushing:
+  {
+    GST_DEBUG_OBJECT (basesink, "we are flushing, ignore object");
+    gst_mini_object_unref (obj);
+    return GST_FLOW_WRONG_STATE;
+  }
 }
 
 /* with STREAM_LOCK, PREROLL_LOCK
@@ -2186,31 +2929,46 @@
  * function does not take ownership of obj.
  */
 static GstFlowReturn
-gst_base_sink_preroll_object (GstBaseSink * basesink, GstPad * pad,
+gst_base_sink_preroll_object (GstBaseSink * basesink, gboolean is_list,
     GstMiniObject * obj)
 {
   GstFlowReturn ret;
 
-  GST_DEBUG_OBJECT (basesink, "do preroll %p", obj);
+  GST_DEBUG_OBJECT (basesink, "prerolling object %p", obj);
 
   /* if it's a buffer, we need to call the preroll method */
-  if (G_LIKELY (GST_IS_BUFFER (obj))) {
+  if (G_LIKELY (is_list || GST_IS_BUFFER (obj)) && basesink->priv->call_preroll) {
     GstBaseSinkClass *bclass;
     GstBuffer *buf;
     GstClockTime timestamp;
 
-    buf = GST_BUFFER_CAST (obj);
+    if (is_list) {
+      buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
+      g_assert (NULL != buf);
+    } else {
+      buf = GST_BUFFER_CAST (obj);
+    }
+
     timestamp = GST_BUFFER_TIMESTAMP (buf);
 
     GST_DEBUG_OBJECT (basesink, "preroll buffer %" GST_TIME_FORMAT,
         GST_TIME_ARGS (timestamp));
 
-    gst_base_sink_set_last_buffer (basesink, buf);
+    /*
+     * For buffer lists do not set last buffer. Creating buffer
+     * with meaningful data can be done only with memcpy which will
+     * significantly affect performance
+     */
+    if (!is_list) {
+      gst_base_sink_set_last_buffer (basesink, buf);
+    }
 
     bclass = GST_BASE_SINK_GET_CLASS (basesink);
     if (bclass->preroll)
       if ((ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK)
         goto preroll_failed;
+
+    basesink->priv->call_preroll = FALSE;
   }
 
   /* commit state */
@@ -2245,7 +3003,7 @@
  */
 static GstFlowReturn
 gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
-    GstMiniObject * obj, gboolean prerollable)
+    gboolean is_list, gpointer obj, gboolean prerollable)
 {
   GstFlowReturn ret = GST_FLOW_OK;
   gint length;
@@ -2261,7 +3019,7 @@
 
     /* first prerollable item needs to finish the preroll */
     if (length == 1) {
-      ret = gst_base_sink_preroll_object (basesink, pad, obj);
+      ret = gst_base_sink_preroll_object (basesink, is_list, obj);
       if (G_UNLIKELY (ret != GST_FLOW_OK))
         goto preroll_failed;
     }
@@ -2274,7 +3032,6 @@
         goto more_preroll;
     }
   }
-
   /* we can start rendering (or blocking) the queued object
    * if any. */
   q = basesink->preroll_queue;
@@ -2285,13 +3042,13 @@
     GST_DEBUG_OBJECT (basesink, "rendering queued object %p", o);
 
     /* do something with the return value */
-    ret = gst_base_sink_render_object (basesink, pad, o);
+    ret = gst_base_sink_render_object (basesink, pad, FALSE, o);
     if (ret != GST_FLOW_OK)
       goto dequeue_failed;
   }
 
   /* now render the object */
-  ret = gst_base_sink_render_object (basesink, pad, obj);
+  ret = gst_base_sink_render_object (basesink, pad, is_list, obj);
   basesink->preroll_queued = 0;
 
   return ret;
@@ -2301,7 +3058,7 @@
   {
     GST_DEBUG_OBJECT (basesink, "preroll failed, reason %s",
         gst_flow_get_name (ret));
-    gst_mini_object_unref (obj);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     return ret;
   }
 more_preroll:
@@ -2316,7 +3073,7 @@
   {
     GST_DEBUG_OBJECT (basesink, "rendering queued objects failed, reason %s",
         gst_flow_get_name (ret));
-    gst_mini_object_unref (obj);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     return ret;
   }
 }
@@ -2341,7 +3098,9 @@
   if (G_UNLIKELY (basesink->priv->received_eos))
     goto was_eos;
 
-  ret = gst_base_sink_queue_object_unlocked (basesink, pad, obj, prerollable);
+  ret =
+      gst_base_sink_queue_object_unlocked (basesink, pad, FALSE, obj,
+      prerollable);
   GST_PAD_PREROLL_UNLOCK (pad);
 
   return ret;
@@ -2364,6 +3123,55 @@
   }
 }
 
+static void
+gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad)
+{
+  /* make sure we are not blocked on the clock also clear any pending
+   * eos state. */
+  gst_base_sink_set_flushing (basesink, pad, TRUE);
+
+  /* we grab the stream lock but that is not needed since setting the
+   * sink to flushing would make sure no state commit is being done
+   * anymore */
+  GST_PAD_STREAM_LOCK (pad);
+  gst_base_sink_reset_qos (basesink);
+  if (basesink->priv->async_enabled) {
+    /* and we need to commit our state again on the next
+     * prerolled buffer */
+    basesink->playing_async = TRUE;
+    gst_element_lost_state (GST_ELEMENT_CAST (basesink));
+  } else {
+    basesink->priv->have_latency = TRUE;
+    basesink->need_preroll = FALSE;
+  }
+  gst_base_sink_set_last_buffer (basesink, NULL);
+  GST_PAD_STREAM_UNLOCK (pad);
+}
+
+static void
+gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad)
+{
+  /* unset flushing so we can accept new data, this also flushes out any EOS
+   * event. */
+  gst_base_sink_set_flushing (basesink, pad, FALSE);
+
+  /* for position reporting */
+  GST_OBJECT_LOCK (basesink);
+  basesink->priv->current_sstart = -1;
+  basesink->priv->current_sstop = -1;
+  basesink->priv->eos_rtime = -1;
+  basesink->priv->call_preroll = TRUE;
+  basesink->priv->current_step.valid = FALSE;
+  basesink->priv->pending_step.valid = FALSE;
+  if (basesink->pad_mode == GST_ACTIVATE_PUSH) {
+    /* we need new segment info after the flush. */
+    basesink->have_newsegment = FALSE;
+    gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
+    gst_segment_init (basesink->abidata.ABI.clip_segment, GST_FORMAT_UNDEFINED);
+  }
+  GST_OBJECT_UNLOCK (basesink);
+}
+
 static gboolean
 gst_base_sink_event (GstPad * pad, GstEvent * event)
 {
@@ -2393,13 +3201,13 @@
         gst_event_unref (event);
       } else {
         /* we set the received EOS flag here so that we can use it when testing if
-         * we are prerolled and to refure more buffers. */
+         * we are prerolled and to refuse more buffers. */
         basesink->priv->received_eos = TRUE;
 
         /* EOS is a prerollable object, we call the unlocked version because it
          * does not check the received_eos flag. */
         ret = gst_base_sink_queue_object_unlocked (basesink, pad,
-            GST_MINI_OBJECT_CAST (event), TRUE);
+            FALSE, GST_MINI_OBJECT_CAST (event), TRUE);
         if (G_UNLIKELY (ret != GST_FLOW_OK))
           result = FALSE;
       }
@@ -2429,11 +3237,14 @@
 
         ret =
             gst_base_sink_queue_object_unlocked (basesink, pad,
-            GST_MINI_OBJECT_CAST (event), FALSE);
+            FALSE, GST_MINI_OBJECT_CAST (event), FALSE);
         if (G_UNLIKELY (ret != GST_FLOW_OK))
           result = FALSE;
-        else
+        else {
+          GST_OBJECT_LOCK (basesink);
           basesink->have_newsegment = TRUE;
+          GST_OBJECT_UNLOCK (basesink);
+        }
       }
       GST_PAD_PREROLL_UNLOCK (pad);
       break;
@@ -2444,26 +3255,7 @@
 
       GST_DEBUG_OBJECT (basesink, "flush-start %p", event);
 
-      /* make sure we are not blocked on the clock also clear any pending
-       * eos state. */
-      gst_base_sink_set_flushing (basesink, pad, TRUE);
-
-      /* we grab the stream lock but that is not needed since setting the
-       * sink to flushing would make sure no state commit is being done
-       * anymore */
-      GST_PAD_STREAM_LOCK (pad);
-      gst_base_sink_reset_qos (basesink);
-      if (basesink->priv->async_enabled) {
-        /* and we need to commit our state again on the next
-         * prerolled buffer */
-        basesink->playing_async = TRUE;
-        gst_element_lost_state (GST_ELEMENT_CAST (basesink));
-      } else {
-        basesink->priv->have_latency = TRUE;
-        basesink->need_preroll = FALSE;
-      }
-      gst_base_sink_set_last_buffer (basesink, NULL);
-      GST_PAD_STREAM_UNLOCK (pad);
+      gst_base_sink_flush_start (basesink, pad);
 
       gst_event_unref (event);
       break;
@@ -2473,21 +3265,7 @@
 
       GST_DEBUG_OBJECT (basesink, "flush-stop %p", event);
 
-      /* unset flushing so we can accept new data, this also flushes out any EOS
-       * event. */
-      gst_base_sink_set_flushing (basesink, pad, FALSE);
-
-      /* we need new segment info after the flush. */
-      gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
-      gst_segment_init (basesink->abidata.ABI.clip_segment,
-          GST_FORMAT_UNDEFINED);
-      basesink->have_newsegment = FALSE;
-
-      /* for position reporting */
-      GST_OBJECT_LOCK (basesink);
-      basesink->priv->current_sstart = -1;
-      basesink->priv->current_sstop = -1;
-      GST_OBJECT_UNLOCK (basesink);
+      gst_base_sink_flush_stop (basesink, pad);
 
       gst_event_unref (event);
       break;
@@ -2552,7 +3330,8 @@
    *  2) we are syncing on the clock
    */
   is_prerolled = basesink->have_preroll || basesink->priv->received_eos;
-  res = !is_prerolled && basesink->pad_mode != GST_ACTIVATE_PULL;
+  res = !is_prerolled;
+
   GST_DEBUG_OBJECT (basesink, "have_preroll: %d, EOS: %d => needs preroll: %d",
       basesink->have_preroll, basesink->priv->received_eos, res);
 
@@ -2569,11 +3348,13 @@
  */
 static GstFlowReturn
 gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
-    GstBuffer * buf)
+    gboolean is_list, gpointer obj)
 {
+  GstBaseSinkClass *bclass;
   GstFlowReturn result;
   GstClockTime start = GST_CLOCK_TIME_NONE, end = GST_CLOCK_TIME_NONE;
   GstSegment *clip_segment;
+  GstBuffer *time_buf;
 
   if (G_UNLIKELY (basesink->flushing))
     goto flushing;
@@ -2581,6 +3362,13 @@
   if (G_UNLIKELY (basesink->priv->received_eos))
     goto was_eos;
 
+  if (is_list) {
+    time_buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
+    g_assert (NULL != time_buf);
+  } else {
+    time_buf = GST_BUFFER_CAST (obj);
+  }
+
   /* for code clarity */
   clip_segment = basesink->abidata.ABI.clip_segment;
 
@@ -2594,18 +3382,28 @@
           ("Received buffer without a new-segment. Assuming timestamps start from 0."));
     }
 
-    basesink->have_newsegment = TRUE;
     /* this means this sink will assume timestamps start from 0 */
+    GST_OBJECT_LOCK (basesink);
     clip_segment->start = 0;
     clip_segment->stop = -1;
     basesink->segment.start = 0;
     basesink->segment.stop = -1;
+    basesink->have_newsegment = TRUE;
+    GST_OBJECT_UNLOCK (basesink);
   }
 
-  /* check if the buffer needs to be dropped */
-  /* we don't use the subclassed method as it may not return
-   * valid values for our purpose here */
-  gst_base_sink_get_times (basesink, buf, &start, &end);
+  bclass = GST_BASE_SINK_GET_CLASS (basesink);
+
+  /* check if the buffer needs to be dropped, we first ask the subclass for the
+   * start and end */
+  if (bclass->get_times)
+    bclass->get_times (basesink, time_buf, &start, &end);
+
+  if (start == -1) {
+    /* if the subclass does not want sync, we use our own values so that we at
+     * least clip the buffer to the segment */
+    gst_base_sink_get_times (basesink, time_buf, &start, &end);
+  }
 
   GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
       ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
@@ -2621,28 +3419,27 @@
   /* now we can process the buffer in the queue, this function takes ownership
    * of the buffer */
   result = gst_base_sink_queue_object_unlocked (basesink, pad,
-      GST_MINI_OBJECT_CAST (buf), TRUE);
-
+      is_list, obj, TRUE);
   return result;
 
   /* ERRORS */
 flushing:
   {
     GST_DEBUG_OBJECT (basesink, "sink is flushing");
-    gst_buffer_unref (buf);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     return GST_FLOW_WRONG_STATE;
   }
 was_eos:
   {
     GST_DEBUG_OBJECT (basesink,
         "we are EOS, dropping object, return UNEXPECTED");
-    gst_buffer_unref (buf);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     return GST_FLOW_UNEXPECTED;
   }
 out_of_segment:
   {
     GST_DEBUG_OBJECT (basesink, "dropping buffer, out of clipping segment");
-    gst_buffer_unref (buf);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     return GST_FLOW_OK;
   }
 }
@@ -2650,18 +3447,16 @@
 /* with STREAM_LOCK
  */
 static GstFlowReturn
-gst_base_sink_chain (GstPad * pad, GstBuffer * buf)
+gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad,
+    gboolean is_list, gpointer obj)
 {
-  GstBaseSink *basesink;
   GstFlowReturn result;
 
-  basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
-
   if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PUSH))
     goto wrong_mode;
 
   GST_PAD_PREROLL_LOCK (pad);
-  result = gst_base_sink_chain_unlocked (basesink, pad, buf);
+  result = gst_base_sink_chain_unlocked (basesink, pad, is_list, obj);
   GST_PAD_PREROLL_UNLOCK (pad);
 
 done:
@@ -2675,7 +3470,7 @@
         "Push on pad %s:%s, but it was not activated in push mode",
         GST_DEBUG_PAD_NAME (pad));
     GST_OBJECT_UNLOCK (pad);
-    gst_buffer_unref (buf);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     /* we don't post an error message this will signal to the peer
      * pushing that EOS is reached. */
     result = GST_FLOW_UNEXPECTED;
@@ -2683,6 +3478,360 @@
   }
 }
 
+static GstFlowReturn
+gst_base_sink_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstBaseSink *basesink;
+
+  basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
+
+  return gst_base_sink_chain_main (basesink, pad, FALSE, buf);
+}
+
+static GstFlowReturn
+gst_base_sink_chain_list (GstPad * pad, GstBufferList * list)
+{
+  GstBaseSink *basesink;
+  GstBaseSinkClass *bclass;
+  GstFlowReturn result;
+
+  basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
+  bclass = GST_BASE_SINK_GET_CLASS (basesink);
+
+  if (G_LIKELY (bclass->render_list)) {
+    result = gst_base_sink_chain_main (basesink, pad, TRUE, list);
+  } else {
+    GstBufferListIterator *it;
+    GstBuffer *group;
+
+    GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
+
+    it = gst_buffer_list_iterate (list);
+
+    result = GST_FLOW_OK;
+    if (gst_buffer_list_iterator_next_group (it)) {
+      do {
+        group = gst_buffer_list_iterator_merge_group (it);
+        if (group == NULL) {
+          group = gst_buffer_new ();
+          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
+        } else {
+          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
+        }
+        result = gst_base_sink_chain_main (basesink, pad, FALSE, group);
+      } while (result == GST_FLOW_OK
+          && gst_buffer_list_iterator_next_group (it));
+    } else {
+      GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
+      result =
+          gst_base_sink_chain_main (basesink, pad, FALSE, gst_buffer_new ());
+    }
+    gst_buffer_list_iterator_free (it);
+    gst_buffer_list_unref (list);
+  }
+  return result;
+}
+
+
+static gboolean
+gst_base_sink_default_do_seek (GstBaseSink * sink, GstSegment * segment)
+{
+  gboolean res = TRUE;
+
+  /* update our offset if the start/stop position was updated */
+  if (segment->format == GST_FORMAT_BYTES) {
+    segment->time = segment->start;
+  } else if (segment->start == 0) {
+    /* seek to start, we can implement a default for this. */
+    segment->time = 0;
+  } else {
+    res = FALSE;
+    GST_INFO_OBJECT (sink, "Can't do a default seek");
+  }
+
+  return res;
+}
+
+#define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET))
+
+static gboolean
+gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
+    GstEvent * event, GstSegment * segment)
+{
+  /* By default, we try one of 2 things:
+   *   - For absolute seek positions, convert the requested position to our 
+   *     configured processing format and place it in the output segment \
+   *   - For relative seek positions, convert our current (input) values to the
+   *     seek format, adjust by the relative seek offset and then convert back to
+   *     the processing format
+   */
+  GstSeekType cur_type, stop_type;
+  gint64 cur, stop;
+  GstSeekFlags flags;
+  GstFormat seek_format, dest_format;
+  gdouble rate;
+  gboolean update;
+  gboolean res = TRUE;
+
+  gst_event_parse_seek (event, &rate, &seek_format, &flags,
+      &cur_type, &cur, &stop_type, &stop);
+  dest_format = segment->format;
+
+  if (seek_format == dest_format) {
+    gst_segment_set_seek (segment, rate, seek_format, flags,
+        cur_type, cur, stop_type, stop, &update);
+    return TRUE;
+  }
+
+  if (cur_type != GST_SEEK_TYPE_NONE) {
+    /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
+    res =
+        gst_pad_query_convert (sink->sinkpad, seek_format, cur, &dest_format,
+        &cur);
+    cur_type = GST_SEEK_TYPE_SET;
+  }
+
+  if (res && stop_type != GST_SEEK_TYPE_NONE) {
+    /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
+    res =
+        gst_pad_query_convert (sink->sinkpad, seek_format, stop, &dest_format,
+        &stop);
+    stop_type = GST_SEEK_TYPE_SET;
+  }
+
+  /* And finally, configure our output segment in the desired format */
+  gst_segment_set_seek (segment, rate, dest_format, flags, cur_type, cur,
+      stop_type, stop, &update);
+
+  if (!res)
+    goto no_format;
+
+  return res;
+
+no_format:
+  {
+    GST_DEBUG_OBJECT (sink, "undefined format given, seek aborted.");
+    return FALSE;
+  }
+}
+
+/* perform a seek, only executed in pull mode */
+static gboolean
+gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
+{
+  gboolean flush;
+  gdouble rate;
+  GstFormat seek_format, dest_format;
+  GstSeekFlags flags;
+  GstSeekType cur_type, stop_type;
+  gboolean seekseg_configured = FALSE;
+  gint64 cur, stop;
+  gboolean update, res = TRUE;
+  GstSegment seeksegment;
+
+  dest_format = sink->segment.format;
+
+  if (event) {
+    GST_DEBUG_OBJECT (sink, "performing seek with event %p", event);
+    gst_event_parse_seek (event, &rate, &seek_format, &flags,
+        &cur_type, &cur, &stop_type, &stop);
+
+    flush = flags & GST_SEEK_FLAG_FLUSH;
+  } else {
+    GST_DEBUG_OBJECT (sink, "performing seek without event");
+    flush = FALSE;
+  }
+
+  if (flush) {
+    GST_DEBUG_OBJECT (sink, "flushing upstream");
+    gst_pad_push_event (pad, gst_event_new_flush_start ());
+    gst_base_sink_flush_start (sink, pad);
+  } else {
+    GST_DEBUG_OBJECT (sink, "pausing pulling thread");
+  }
+
+  GST_PAD_STREAM_LOCK (pad);
+
+  /* If we configured the seeksegment above, don't overwrite it now. Otherwise
+   * copy the current segment info into the temp segment that we can actually
+   * attempt the seek with. We only update the real segment if the seek suceeds. */
+  if (!seekseg_configured) {
+    memcpy (&seeksegment, &sink->segment, sizeof (GstSegment));
+
+    /* now configure the final seek segment */
+    if (event) {
+      if (sink->segment.format != seek_format) {
+        /* OK, here's where we give the subclass a chance to convert the relative
+         * seek into an absolute one in the processing format. We set up any
+         * absolute seek above, before taking the stream lock. */
+        if (!gst_base_sink_default_prepare_seek_segment (sink, event,
+                &seeksegment)) {
+          GST_DEBUG_OBJECT (sink,
+              "Preparing the seek failed after flushing. " "Aborting seek");
+          res = FALSE;
+        }
+      } else {
+        /* The seek format matches our processing format, no need to ask the
+         * the subclass to configure the segment. */
+        gst_segment_set_seek (&seeksegment, rate, seek_format, flags,
+            cur_type, cur, stop_type, stop, &update);
+      }
+    }
+    /* Else, no seek event passed, so we're just (re)starting the 
+       current segment. */
+  }
+
+  if (res) {
+    GST_DEBUG_OBJECT (sink, "segment configured from %" G_GINT64_FORMAT
+        " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
+        seeksegment.start, seeksegment.stop, seeksegment.last_stop);
+
+    /* do the seek, segment.last_stop contains the new position. */
+    res = gst_base_sink_default_do_seek (sink, &seeksegment);
+  }
+
+
+  if (flush) {
+    GST_DEBUG_OBJECT (sink, "stop flushing upstream");
+    gst_pad_push_event (pad, gst_event_new_flush_stop ());
+    gst_base_sink_flush_stop (sink, pad);
+  } else if (res && sink->abidata.ABI.running) {
+    /* we are running the current segment and doing a non-flushing seek, 
+     * close the segment first based on the last_stop. */
+    GST_DEBUG_OBJECT (sink, "closing running segment %" G_GINT64_FORMAT
+        " to %" G_GINT64_FORMAT, sink->segment.start, sink->segment.last_stop);
+  }
+
+  /* The subclass must have converted the segment to the processing format 
+   * by now */
+  if (res && seeksegment.format != dest_format) {
+    GST_DEBUG_OBJECT (sink, "Subclass failed to prepare a seek segment "
+        "in the correct format. Aborting seek.");
+    res = FALSE;
+  }
+
+  /* if successfull seek, we update our real segment and push
+   * out the new segment. */
+  if (res) {
+    memcpy (&sink->segment, &seeksegment, sizeof (GstSegment));
+
+    if (sink->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+      gst_element_post_message (GST_ELEMENT (sink),
+          gst_message_new_segment_start (GST_OBJECT (sink),
+              sink->segment.format, sink->segment.last_stop));
+    }
+  }
+
+  sink->priv->discont = TRUE;
+  sink->abidata.ABI.running = TRUE;
+
+  GST_PAD_STREAM_UNLOCK (pad);
+
+  return res;
+}
+
+static void
+set_step_info (GstBaseSink * sink, GstStepInfo * current, GstStepInfo * pending,
+    guint seqnum, GstFormat format, guint64 amount, gdouble rate,
+    gboolean flush, gboolean intermediate)
+{
+  GST_OBJECT_LOCK (sink);
+  pending->seqnum = seqnum;
+  pending->format = format;
+  pending->amount = amount;
+  pending->position = 0;
+  pending->rate = rate;
+  pending->flush = flush;
+  pending->intermediate = intermediate;
+  pending->valid = TRUE;
+  /* flush invalidates the current stepping segment */
+  if (flush)
+    current->valid = FALSE;
+  GST_OBJECT_UNLOCK (sink);
+}
+
+static gboolean
+gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
+{
+  GstBaseSinkPrivate *priv;
+  GstBaseSinkClass *bclass;
+  gboolean flush, intermediate;
+  gdouble rate;
+  GstFormat format;
+  guint64 amount;
+  guint seqnum;
+  GstStepInfo *pending, *current;
+  GstMessage *message;
+
+  bclass = GST_BASE_SINK_GET_CLASS (sink);
+  priv = sink->priv;
+
+  GST_DEBUG_OBJECT (sink, "performing step with event %p", event);
+
+  gst_event_parse_step (event, &format, &amount, &rate, &flush, &intermediate);
+  seqnum = gst_event_get_seqnum (event);
+
+  pending = &priv->pending_step;
+  current = &priv->current_step;
+
+  /* post message first */
+  message = gst_message_new_step_start (GST_OBJECT (sink), FALSE, format,
+      amount, rate, flush, intermediate);
+  gst_message_set_seqnum (message, seqnum);
+  gst_element_post_message (GST_ELEMENT (sink), message);
+
+  if (flush) {
+    /* we need to call ::unlock before locking PREROLL_LOCK
+     * since we lock it before going into ::render */
+    if (bclass->unlock)
+      bclass->unlock (sink);
+
+    GST_PAD_PREROLL_LOCK (sink->sinkpad);
+    /* now that we have the PREROLL lock, clear our unlock request */
+    if (bclass->unlock_stop)
+      bclass->unlock_stop (sink);
+
+    /* update the stepinfo and make it valid */
+    set_step_info (sink, current, pending, seqnum, format, amount, rate, flush,
+        intermediate);
+
+    if (sink->priv->async_enabled) {
+      /* and we need to commit our state again on the next
+       * prerolled buffer */
+      sink->playing_async = TRUE;
+      priv->pending_step.need_preroll = TRUE;
+      sink->need_preroll = FALSE;
+      gst_element_lost_state_full (GST_ELEMENT_CAST (sink), FALSE);
+    } else {
+      sink->priv->have_latency = TRUE;
+      sink->need_preroll = FALSE;
+    }
+    priv->current_sstart = -1;
+    priv->current_sstop = -1;
+    priv->eos_rtime = -1;
+    priv->call_preroll = TRUE;
+    gst_base_sink_set_last_buffer (sink, NULL);
+    gst_base_sink_reset_qos (sink);
+
+    if (sink->clock_id) {
+      gst_clock_id_unschedule (sink->clock_id);
+    }
+
+    if (sink->have_preroll) {
+      GST_DEBUG_OBJECT (sink, "signal waiter");
+      priv->step_unlock = TRUE;
+      GST_PAD_PREROLL_SIGNAL (sink->sinkpad);
+    }
+    GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
+  } else {
+    /* update the stepinfo and make it valid */
+    set_step_info (sink, current, pending, seqnum, format, amount, rate, flush,
+        intermediate);
+  }
+
+  return TRUE;
+}
+
 /* with STREAM_LOCK
  */
 static void
@@ -2691,25 +3840,34 @@
   GstBaseSink *basesink;
   GstBuffer *buf = NULL;
   GstFlowReturn result;
+  guint blocksize;
+  guint64 offset;
 
   basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
 
   g_assert (basesink->pad_mode == GST_ACTIVATE_PULL);
 
+  if ((blocksize = basesink->priv->blocksize) == 0)
+    blocksize = -1;
+
+  offset = basesink->segment.last_stop;
+
   GST_DEBUG_OBJECT (basesink, "pulling %" G_GUINT64_FORMAT ", %u",
-      basesink->offset, (guint) DEFAULT_SIZE);
-
-  result = gst_pad_pull_range (pad, basesink->offset, DEFAULT_SIZE, &buf);
+      offset, blocksize);
+
+  result = gst_pad_pull_range (pad, offset, blocksize, &buf);
   if (G_UNLIKELY (result != GST_FLOW_OK))
     goto paused;
 
   if (G_UNLIKELY (buf == NULL))
     goto no_buffer;
 
-  basesink->offset += GST_BUFFER_SIZE (buf);
+  offset += GST_BUFFER_SIZE (buf);
+
+  gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_BYTES, offset);
 
   GST_PAD_PREROLL_LOCK (pad);
-  result = gst_base_sink_chain_unlocked (basesink, pad, buf);
+  result = gst_base_sink_chain_unlocked (basesink, pad, FALSE, buf);
   GST_PAD_PREROLL_UNLOCK (pad);
   if (G_UNLIKELY (result != GST_FLOW_OK))
     goto paused;
@@ -2724,13 +3882,22 @@
     gst_pad_pause_task (pad);
     /* fatal errors and NOT_LINKED cause EOS */
     if (GST_FLOW_IS_FATAL (result) || result == GST_FLOW_NOT_LINKED) {
-      /* FIXME, we shouldn't post EOS when we are operating in segment mode */
-      gst_base_sink_event (pad, gst_event_new_eos ());
-      /* EOS does not cause an ERROR message */
-      if (result != GST_FLOW_UNEXPECTED) {
+      if (result == GST_FLOW_UNEXPECTED) {
+        /* perform EOS logic */
+        if (basesink->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+          gst_element_post_message (GST_ELEMENT_CAST (basesink),
+              gst_message_new_segment_done (GST_OBJECT_CAST (basesink),
+                  basesink->segment.format, basesink->segment.last_stop));
+        } else {
+          gst_base_sink_event (pad, gst_event_new_eos ());
+        }
+      } else {
+        /* for fatal errors we post an error message, post the error
+         * first so the app knows about the error first. */
         GST_ELEMENT_ERROR (basesink, STREAM, FAILED,
             (_("Internal data stream error.")),
             ("stream stopped, reason %s", gst_flow_get_name (result)));
+        gst_base_sink_event (pad, gst_event_new_eos ());
       }
     }
     return;
@@ -2738,6 +3905,8 @@
 no_buffer:
   {
     GST_LOG_OBJECT (basesink, "no buffer, pausing");
+    GST_ELEMENT_ERROR (basesink, STREAM, FAILED,
+        (_("Internal data flow error.")), ("element returned NULL buffer"));
     result = GST_FLOW_ERROR;
     goto paused;
   }
@@ -2774,7 +3943,8 @@
       gst_clock_id_unschedule (basesink->clock_id);
     }
 
-    /* flush out the data thread if it's locked in finish_preroll */
+    /* flush out the data thread if it's locked in finish_preroll, this will
+     * also flush out the EOS state */
     GST_DEBUG_OBJECT (basesink,
         "flushing out data thread, need preroll to TRUE");
     gst_base_sink_preroll_queue_flush (basesink, pad);
@@ -2813,18 +3983,52 @@
 
   gst_base_sink_set_flushing (basesink, pad, FALSE);
 
-  if (basesink->can_activate_pull && gst_pad_check_pull_range (pad)
-      && gst_pad_activate_pull (pad, TRUE)) {
-    GST_DEBUG_OBJECT (basesink, "Success activating pull mode");
-    result = TRUE;
-  } else {
-    GST_DEBUG_OBJECT (basesink, "Falling back to push mode");
-    if (gst_pad_activate_push (pad, TRUE)) {
-      GST_DEBUG_OBJECT (basesink, "Success activating push mode");
-      result = TRUE;
-    }
+  /* we need to have the pull mode enabled */
+  if (!basesink->can_activate_pull) {
+    GST_DEBUG_OBJECT (basesink, "pull mode disabled");
+    goto fallback;
+  }
+
+  /* check if downstreams supports pull mode at all */
+  if (!gst_pad_check_pull_range (pad)) {
+    GST_DEBUG_OBJECT (basesink, "pull mode not supported");
+    goto fallback;
+  }
+
+  /* set the pad mode before starting the task so that it's in the
+   * correct state for the new thread. also the sink set_caps and get_caps
+   * function checks this */
+  basesink->pad_mode = GST_ACTIVATE_PULL;
+
+  /* we first try to negotiate a format so that when we try to activate
+   * downstream, it knows about our format */
+  if (!gst_base_sink_negotiate_pull (basesink)) {
+    GST_DEBUG_OBJECT (basesink, "failed to negotiate in pull mode");
+    goto fallback;
   }
 
+  /* ok activate now */
+  if (!gst_pad_activate_pull (pad, TRUE)) {
+    /* clear any pending caps */
+    GST_OBJECT_LOCK (basesink);
+    gst_caps_replace (&basesink->priv->pull_caps, NULL);
+    GST_OBJECT_UNLOCK (basesink);
+    GST_DEBUG_OBJECT (basesink, "failed to activate in pull mode");
+    goto fallback;
+  }
+
+  GST_DEBUG_OBJECT (basesink, "Success activating pull mode");
+  result = TRUE;
+  goto done;
+
+  /* push mode fallback */
+fallback:
+  GST_DEBUG_OBJECT (basesink, "Falling back to push mode");
+  if ((result = gst_pad_activate_push (pad, TRUE))) {
+    GST_DEBUG_OBJECT (basesink, "Success activating push mode");
+  }
+
+done:
   if (!result) {
     GST_WARNING_OBJECT (basesink, "Could not activate pad in either mode");
     gst_base_sink_set_flushing (basesink, pad, TRUE);
@@ -2871,48 +4075,60 @@
 gst_base_sink_negotiate_pull (GstBaseSink * basesink)
 {
   GstCaps *caps;
-  GstPad *pad;
-
-  GST_OBJECT_LOCK (basesink);
-  pad = basesink->sinkpad;
-  gst_object_ref (pad);
-  GST_OBJECT_UNLOCK (basesink);
-
-  caps = gst_pad_get_allowed_caps (pad);
-  if (gst_caps_is_empty (caps))
+  gboolean result;
+
+  result = FALSE;
+
+  /* this returns the intersection between our caps and the peer caps. If there
+   * is no peer, it returns NULL and we can't operate in pull mode so we can
+   * fail the negotiation. */
+  caps = gst_pad_get_allowed_caps (GST_BASE_SINK_PAD (basesink));
+  if (caps == NULL || gst_caps_is_empty (caps))
     goto no_caps_possible;
 
+  GST_DEBUG_OBJECT (basesink, "allowed caps: %" GST_PTR_FORMAT, caps);
+
   caps = gst_caps_make_writable (caps);
+  /* get the first (prefered) format */
   gst_caps_truncate (caps);
-  gst_pad_fixate_caps (pad, caps);
+  /* try to fixate */
+  gst_pad_fixate_caps (GST_BASE_SINK_PAD (basesink), caps);
+
+  GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
 
   if (gst_caps_is_any (caps)) {
     GST_DEBUG_OBJECT (basesink, "caps were ANY after fixating, "
         "allowing pull()");
     /* neither side has template caps in this case, so they are prepared for
        pull() without setcaps() */
-  } else {
-    if (!gst_pad_set_caps (pad, caps))
+    result = TRUE;
+  } else if (gst_caps_is_fixed (caps)) {
+    if (!gst_pad_set_caps (GST_BASE_SINK_PAD (basesink), caps))
       goto could_not_set_caps;
+
+    GST_OBJECT_LOCK (basesink);
+    gst_caps_replace (&basesink->priv->pull_caps, caps);
+    GST_OBJECT_UNLOCK (basesink);
+
+    result = TRUE;
   }
 
   gst_caps_unref (caps);
-  gst_object_unref (pad);
-
-  return TRUE;
+
+  return result;
 
 no_caps_possible:
   {
     GST_INFO_OBJECT (basesink, "Pipeline could not agree on caps");
     GST_DEBUG_OBJECT (basesink, "get_allowed_caps() returned EMPTY");
-    gst_object_unref (pad);
+    if (caps)
+      gst_caps_unref (caps);
     return FALSE;
   }
 could_not_set_caps:
   {
     GST_INFO_OBJECT (basesink, "Could not set caps: %" GST_PTR_FORMAT, caps);
     gst_caps_unref (caps);
-    gst_object_unref (pad);
     return FALSE;
   }
 }
@@ -2929,47 +4145,40 @@
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
   if (active) {
-    if (!basesink->can_activate_pull) {
-      result = FALSE;
-      basesink->pad_mode = GST_ACTIVATE_NONE;
+    GstFormat format;
+    gint64 duration;
+
+    /* we mark we have a newsegment here because pull based
+     * mode works just fine without having a newsegment before the
+     * first buffer */
+    format = GST_FORMAT_BYTES;
+
+    gst_segment_init (&basesink->segment, format);
+    gst_segment_init (basesink->abidata.ABI.clip_segment, format);
+    GST_OBJECT_LOCK (basesink);
+    basesink->have_newsegment = TRUE;
+    GST_OBJECT_UNLOCK (basesink);
+
+    /* get the peer duration in bytes */
+    result = gst_pad_query_peer_duration (pad, &format, &duration);
+    if (result) {
+      GST_DEBUG_OBJECT (basesink,
+          "setting duration in bytes to %" G_GINT64_FORMAT, duration);
+      gst_segment_set_duration (basesink->abidata.ABI.clip_segment, format,
+          duration);
+      gst_segment_set_duration (&basesink->segment, format, duration);
     } else {
-      GstPad *peer = gst_pad_get_peer (pad);
-
-      if (G_UNLIKELY (peer == NULL)) {
-        g_warning ("Trying to activate pad in pull mode, but no peer");
-        result = FALSE;
-        basesink->pad_mode = GST_ACTIVATE_NONE;
-      } else {
-        if (gst_pad_activate_pull (peer, TRUE)) {
-          /* we mark we have a newsegment here because pull based
-           * mode works just fine without having a newsegment before the
-           * first buffer */
-          gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
-          gst_segment_init (basesink->abidata.ABI.clip_segment,
-              GST_FORMAT_UNDEFINED);
-          basesink->have_newsegment = TRUE;
-
-          /* set the pad mode before starting the task so that it's in the
-             correct state for the new thread. also the sink set_caps function
-             checks this */
-          basesink->pad_mode = GST_ACTIVATE_PULL;
-          if ((result = gst_base_sink_negotiate_pull (basesink))) {
-            if (bclass->activate_pull)
-              result = bclass->activate_pull (basesink, TRUE);
-            else
-              result = FALSE;
-          }
-          /* but if starting the thread fails, set it back */
-          if (!result)
-            basesink->pad_mode = GST_ACTIVATE_NONE;
-        } else {
-          GST_DEBUG_OBJECT (pad, "Failed to activate peer in pull mode");
-          result = FALSE;
-          basesink->pad_mode = GST_ACTIVATE_NONE;
-        }
-        gst_object_unref (peer);
-      }
+      GST_DEBUG_OBJECT (basesink, "unknown duration");
     }
+
+    if (bclass->activate_pull)
+      result = bclass->activate_pull (basesink, TRUE);
+    else
+      result = FALSE;
+
+    if (!result)
+      goto activate_failed;
+
   } else {
     if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PULL)) {
       g_warning ("Internal GStreamer activation error!!!");
@@ -2979,12 +4188,25 @@
       if (bclass->activate_pull)
         result &= bclass->activate_pull (basesink, FALSE);
       basesink->pad_mode = GST_ACTIVATE_NONE;
+      /* clear any pending caps */
+      GST_OBJECT_LOCK (basesink);
+      gst_caps_replace (&basesink->priv->pull_caps, NULL);
+      GST_OBJECT_UNLOCK (basesink);
     }
   }
-
   gst_object_unref (basesink);
 
   return result;
+
+  /* ERRORS */
+activate_failed:
+  {
+    /* reset, as starting the thread failed */
+    basesink->pad_mode = GST_ACTIVATE_NONE;
+
+    GST_ERROR_OBJECT (basesink, "subclass failed to activate in pull mode");
+    return FALSE;
+  }
 }
 
 /* send an event to our sinkpad peer. */
@@ -2994,6 +4216,13 @@
   GstPad *pad;
   GstBaseSink *basesink = GST_BASE_SINK (element);
   gboolean forward, result = TRUE;
+  GstActivateMode mode;
+
+  GST_OBJECT_LOCK (element);
+  /* get the pad and the scheduling mode */
+  pad = gst_object_ref (basesink->sinkpad);
+  mode = basesink->pad_mode;
+  GST_OBJECT_UNLOCK (element);
 
   /* only push UPSTREAM events upstream */
   forward = GST_EVENT_IS_UPSTREAM (event);
@@ -3005,32 +4234,42 @@
 
       gst_event_parse_latency (event, &latency);
 
+      /* store the latency. We use this to adjust the running_time before syncing
+       * it to the clock. */
       GST_OBJECT_LOCK (element);
       basesink->priv->latency = latency;
+      if (!basesink->priv->have_latency)
+        forward = FALSE;
       GST_OBJECT_UNLOCK (element);
       GST_DEBUG_OBJECT (basesink, "latency set to %" GST_TIME_FORMAT,
           GST_TIME_ARGS (latency));
 
-      /* don't forward, yet */
+      /* We forward this event so that all elements know about the global pipeline
+       * latency. This is interesting for an element when it wants to figure out
+       * when a particular piece of data will be rendered. */
+      break;
+    }
+    case GST_EVENT_SEEK:
+      /* in pull mode we will execute the seek */
+      if (mode == GST_ACTIVATE_PULL)
+        result = gst_base_sink_perform_seek (basesink, pad, event);
+      break;
+    case GST_EVENT_STEP:
+      result = gst_base_sink_perform_step (basesink, pad, event);
       forward = FALSE;
       break;
-    }
     default:
       break;
   }
 
   if (forward) {
-    GST_OBJECT_LOCK (element);
-    pad = gst_object_ref (basesink->sinkpad);
-    GST_OBJECT_UNLOCK (element);
-
     result = gst_pad_push_event (pad, event);
-
-    gst_object_unref (pad);
   } else {
     /* not forwarded, unref the event */
     gst_event_unref (event);
   }
+
+  gst_object_unref (pad);
   return result;
 }
 
@@ -3049,29 +4288,74 @@
 
 /* get the end position of the last seen object, this is used
  * for EOS and for making sure that we don't report a position we
- * have not reached yet. */
+ * have not reached yet. With LOCK. */
 static gboolean
-gst_base_sink_get_position_last (GstBaseSink * basesink, gint64 * cur)
+gst_base_sink_get_position_last (GstBaseSink * basesink, GstFormat format,
+    gint64 * cur)
 {
-  /* return last observed stream time */
-  *cur = basesink->priv->current_sstop;
+  GstFormat oformat;
+  GstSegment *segment;
+  gboolean ret = TRUE;
+
+  segment = &basesink->segment;
+  oformat = segment->format;
+
+  if (oformat == GST_FORMAT_TIME) {
+    /* return last observed stream time, we keep the stream time around in the
+     * time format. */
+    *cur = basesink->priv->current_sstop;
+  } else {
+    /* convert last stop to stream time */
+    *cur = gst_segment_to_stream_time (segment, oformat, segment->last_stop);
+  }
+
+  if (*cur != -1 && oformat != format) {
+    GST_OBJECT_UNLOCK (basesink);
+    /* convert to the target format if we need to, release lock first */
+    ret =
+        gst_pad_query_convert (basesink->sinkpad, oformat, *cur, &format, cur);
+    if (!ret)
+      *cur = -1;
+    GST_OBJECT_LOCK (basesink);
+  }
+
   GST_DEBUG_OBJECT (basesink, "POSITION: %" GST_TIME_FORMAT,
       GST_TIME_ARGS (*cur));
-  return TRUE;
+
+  return ret;
 }
 
 /* get the position when we are PAUSED, this is the stream time of the buffer
  * that prerolled. If no buffer is prerolled (we are still flushing), this
- * value will be -1. */
+ * value will be -1. With LOCK. */
 static gboolean
-gst_base_sink_get_position_paused (GstBaseSink * basesink, gint64 * cur)
+gst_base_sink_get_position_paused (GstBaseSink * basesink, GstFormat format,
+    gint64 * cur)
 {
   gboolean res;
   gint64 time;
   GstSegment *segment;
-
-  *cur = basesink->priv->current_sstart;
-  segment = basesink->abidata.ABI.clip_segment;
+  GstFormat oformat;
+
+  /* we don't use the clip segment in pull mode, when seeking we update the
+   * main segment directly with the new segment values without it having to be
+   * activated by the rendering after preroll */
+  if (basesink->pad_mode == GST_ACTIVATE_PUSH)
+    segment = basesink->abidata.ABI.clip_segment;
+  else
+    segment = &basesink->segment;
+  oformat = segment->format;
+
+  if (oformat == GST_FORMAT_TIME) {
+    *cur = basesink->priv->current_sstart;
+    if (segment->rate < 0.0 && basesink->priv->current_sstop != -1) {
+      /* for reverse playback we prefer the stream time stop position if we have
+       * one */
+      *cur = basesink->priv->current_sstop;
+    }
+  } else {
+    *cur = gst_segment_to_stream_time (segment, oformat, segment->last_stop);
+  }
 
   time = segment->time;
 
@@ -3089,118 +4373,142 @@
     } else {
       /* reverse, next expected timestamp is segment->stop. We use the function
        * to get things right for negative applied_rates. */
-      *cur =
-          gst_segment_to_stream_time (segment, GST_FORMAT_TIME, segment->stop);
+      *cur = gst_segment_to_stream_time (segment, oformat, segment->stop);
       GST_DEBUG_OBJECT (basesink, "reverse POSITION: %" GST_TIME_FORMAT,
           GST_TIME_ARGS (*cur));
     }
   }
+
   res = (*cur != -1);
+  if (res && oformat != format) {
+    GST_OBJECT_UNLOCK (basesink);
+    res =
+        gst_pad_query_convert (basesink->sinkpad, oformat, *cur, &format, cur);
+    if (!res)
+      *cur = -1;
+    GST_OBJECT_LOCK (basesink);
+  }
 
   return res;
 }
 
 static gboolean
 gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
-    gint64 * cur)
+    gint64 * cur, gboolean * upstream)
 {
   GstClock *clock;
   gboolean res = FALSE;
-
-  switch (format) {
-      /* we can answer time format */
-    case GST_FORMAT_TIME:
-    {
-      GstClockTime now, base, latency;
-      gint64 time, accum, duration;
-      gdouble rate;
-      gint64 last;
-
-      GST_OBJECT_LOCK (basesink);
-
-      /* can only give answer based on the clock if not EOS */
-      if (G_UNLIKELY (basesink->eos))
-        goto in_eos;
-
-      /* in PAUSE we cannot read from the clock so we
-       * report time based on the last seen timestamp. */
-      if (GST_STATE (basesink) == GST_STATE_PAUSED)
-        goto in_pause;
-
-      /* We get position from clock only in PLAYING, we checked
-       * the PAUSED case above, so this is check is to test 
-       * READY and NULL, where the position is always 0 */
-      if (GST_STATE (basesink) != GST_STATE_PLAYING)
-        goto wrong_state;
-
-      /* we need to sync on the clock. */
-      if (basesink->sync == FALSE)
-        goto no_sync;
-
-      /* and we need a clock */
-      if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (basesink)) == NULL))
-        goto no_sync;
-
-      /* collect all data we need holding the lock */
-      if (GST_CLOCK_TIME_IS_VALID (basesink->segment.time))
-        time = basesink->segment.time;
-      else
-        time = 0;
-
-      if (GST_CLOCK_TIME_IS_VALID (basesink->segment.stop))
-        duration = basesink->segment.stop - basesink->segment.start;
-      else
-        duration = 0;
-
-      base = GST_ELEMENT_CAST (basesink)->base_time;
-      accum = basesink->segment.accum;
-      rate = basesink->segment.rate * basesink->segment.applied_rate;
-      gst_base_sink_get_position_last (basesink, &last);
-      latency = basesink->priv->latency;
-
-      gst_object_ref (clock);
-      /* need to release the object lock before we can get the time, 
-       * a clock might take the LOCK of the provider, which could be
-       * a basesink subclass. */
-      GST_OBJECT_UNLOCK (basesink);
-
-      now = gst_clock_get_time (clock);
-
-      /* subtract base time and accumulated time from the clock time. 
-       * Make sure we don't go negative. This is the current time in
-       * the segment which we need to scale with the combined 
-       * rate and applied rate. */
-      base += accum;
-      base += latency;
-      base = MIN (now, base);
-
-      /* for negative rates we need to count back from from the segment
-       * duration. */
-      if (rate < 0.0)
-        time += duration;
-      *cur = time + gst_guint64_to_gdouble (now - base) * rate;
-
-      /* never report more than last seen position */
-      if (last != -1)
-        *cur = MIN (last, *cur);
-
-      gst_object_unref (clock);
-
-      res = TRUE;
-
-      GST_DEBUG_OBJECT (basesink,
-          "now %" GST_TIME_FORMAT " - base %" GST_TIME_FORMAT " - accum %"
-          GST_TIME_FORMAT " + time %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (now), GST_TIME_ARGS (base),
-          GST_TIME_ARGS (accum), GST_TIME_ARGS (time));
-      break;
-    }
-    default:
-      /* cannot answer other than TIME, we return FALSE, which will
-       * send the query upstream. */
-      break;
+  GstFormat oformat, tformat;
+  GstClockTime now, base, latency;
+  gint64 time, accum, duration;
+  gdouble rate;
+  gint64 last;
+
+  GST_OBJECT_LOCK (basesink);
+  /* our intermediate time format */
+  tformat = GST_FORMAT_TIME;
+  /* get the format in the segment */
+  oformat = basesink->segment.format;
+
+  /* can only give answer based on the clock if not EOS */
+  if (G_UNLIKELY (basesink->eos))
+    goto in_eos;
+
+  /* we can only get the segment when we are not NULL or READY */
+  if (!basesink->have_newsegment)
+    goto wrong_state;
+
+  /* when not in PLAYING or when we're busy with a state change, we
+   * cannot read from the clock so we report time based on the
+   * last seen timestamp. */
+  if (GST_STATE (basesink) != GST_STATE_PLAYING ||
+      GST_STATE_PENDING (basesink) != GST_STATE_VOID_PENDING)
+    goto in_pause;
+
+  /* we need to sync on the clock. */
+  if (basesink->sync == FALSE)
+    goto no_sync;
+
+  /* and we need a clock */
+  if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (basesink)) == NULL))
+    goto no_sync;
+
+  /* collect all data we need holding the lock */
+  if (GST_CLOCK_TIME_IS_VALID (basesink->segment.time))
+    time = basesink->segment.time;
+  else
+    time = 0;
+
+  if (GST_CLOCK_TIME_IS_VALID (basesink->segment.stop))
+    duration = basesink->segment.stop - basesink->segment.start;
+  else
+    duration = 0;
+
+  base = GST_ELEMENT_CAST (basesink)->base_time;
+  accum = basesink->segment.accum;
+  rate = basesink->segment.rate * basesink->segment.applied_rate;
+  latency = basesink->priv->latency;
+
+  gst_object_ref (clock);
+
+  /* this function might release the LOCK */
+  gst_base_sink_get_position_last (basesink, format, &last);
+
+  /* need to release the object lock before we can get the time, 
+   * a clock might take the LOCK of the provider, which could be
+   * a basesink subclass. */
+  GST_OBJECT_UNLOCK (basesink);
+
+  now = gst_clock_get_time (clock);
+
+  if (oformat != tformat) {
+    /* convert accum, time and duration to time */
+    if (!gst_pad_query_convert (basesink->sinkpad, oformat, accum, &tformat,
+            &accum))
+      goto convert_failed;
+    if (!gst_pad_query_convert (basesink->sinkpad, oformat, duration, &tformat,
+            &duration))
+      goto convert_failed;
+    if (!gst_pad_query_convert (basesink->sinkpad, oformat, time, &tformat,
+            &time))
+      goto convert_failed;
   }
 
+  /* subtract base time and accumulated time from the clock time. 
+   * Make sure we don't go negative. This is the current time in
+   * the segment which we need to scale with the combined 
+   * rate and applied rate. */
+  base += accum;
+  base += latency;
+  base = MIN (now, base);
+
+  /* for negative rates we need to count back from from the segment
+   * duration. */
+  if (rate < 0.0)
+    time += duration;
+
+  *cur = time + gst_guint64_to_gdouble (now - base) * rate;
+
+  /* never report more than last seen position */
+  if (last != -1)
+    *cur = MIN (last, *cur);
+
+  gst_object_unref (clock);
+
+  GST_DEBUG_OBJECT (basesink,
+      "now %" GST_TIME_FORMAT " - base %" GST_TIME_FORMAT " - accum %"
+      GST_TIME_FORMAT " + time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (now), GST_TIME_ARGS (base),
+      GST_TIME_ARGS (accum), GST_TIME_ARGS (time));
+
+  if (oformat != format) {
+    /* convert time to final format */
+    if (!gst_pad_query_convert (basesink->sinkpad, tformat, *cur, &format, cur))
+      goto convert_failed;
+  }
+
+  res = TRUE;
+
 done:
   GST_DEBUG_OBJECT (basesink, "res: %d, POSITION: %" GST_TIME_FORMAT,
       res, GST_TIME_ARGS (*cur));
@@ -3210,20 +4518,20 @@
 in_eos:
   {
     GST_DEBUG_OBJECT (basesink, "position in EOS");
-    res = gst_base_sink_get_position_last (basesink, cur);
+    res = gst_base_sink_get_position_last (basesink, format, cur);
     GST_OBJECT_UNLOCK (basesink);
     goto done;
   }
 in_pause:
   {
     GST_DEBUG_OBJECT (basesink, "position in PAUSED");
-    res = gst_base_sink_get_position_paused (basesink, cur);
+    res = gst_base_sink_get_position_paused (basesink, format, cur);
     GST_OBJECT_UNLOCK (basesink);
     goto done;
   }
 wrong_state:
   {
-    /* in NULL or READY we always return 0 */
+    /* in NULL or READY we always return FALSE and -1 */
     GST_DEBUG_OBJECT (basesink, "position in wrong state, return -1");
     res = FALSE;
     *cur = -1;
@@ -3232,15 +4540,23 @@
   }
 no_sync:
   {
-    /* report last seen timestamp if any, else return FALSE so
-     * that upstream can answer */
+    /* report last seen timestamp if any, else ask upstream to answer */
     if ((*cur = basesink->priv->current_sstart) != -1)
       res = TRUE;
+    else
+      *upstream = TRUE;
+
     GST_DEBUG_OBJECT (basesink, "no sync, res %d, POSITION %" GST_TIME_FORMAT,
         res, GST_TIME_ARGS (*cur));
     GST_OBJECT_UNLOCK (basesink);
     return res;
   }
+convert_failed:
+  {
+    GST_DEBUG_OBJECT (basesink, "convert failed, try upstream");
+    *upstream = TRUE;
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -3255,24 +4571,61 @@
     {
       gint64 cur = 0;
       GstFormat format;
+      gboolean upstream = FALSE;
 
       gst_query_parse_position (query, &format, NULL);
 
       GST_DEBUG_OBJECT (basesink, "position format %d", format);
 
       /* first try to get the position based on the clock */
-      if ((res = gst_base_sink_get_position (basesink, format, &cur))) {
+      if ((res =
+              gst_base_sink_get_position (basesink, format, &cur, &upstream))) {
         gst_query_set_position (query, format, cur);
-      } else {
+      } else if (upstream) {
         /* fallback to peer query */
         res = gst_base_sink_peer_query (basesink, query);
       }
       break;
     }
     case GST_QUERY_DURATION:
-      GST_DEBUG_OBJECT (basesink, "duration query");
-      res = gst_base_sink_peer_query (basesink, query);
+    {
+      GstFormat format, uformat;
+      gint64 duration, uduration;
+
+      gst_query_parse_duration (query, &format, NULL);
+
+      GST_DEBUG_OBJECT (basesink, "duration query in format %s",
+          gst_format_get_name (format));
+
+      if (basesink->pad_mode == GST_ACTIVATE_PULL) {
+        uformat = GST_FORMAT_BYTES;
+
+        /* get the duration in bytes, in pull mode that's all we are sure to
+         * know. We have to explicitly get this value from upstream instead of
+         * using our cached value because it might change. Duration caching
+         * should be done at a higher level. */
+        res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat,
+            &uduration);
+        if (res) {
+          gst_segment_set_duration (&basesink->segment, uformat, uduration);
+          if (format != uformat) {
+            /* convert to the requested format */
+            res = gst_pad_query_convert (basesink->sinkpad, uformat, uduration,
+                &format, &duration);
+          } else {
+            duration = uduration;
+          }
+          if (res) {
+            /* set the result */
+            gst_query_set_duration (query, format, duration);
+          }
+        }
+      } else {
+        /* in push mode we simply forward upstream */
+        res = gst_base_sink_peer_query (basesink, query);
+      }
       break;
+    }
     case GST_QUERY_LATENCY:
     {
       gboolean live, us_live;
@@ -3330,12 +4683,13 @@
        * is no data flow in READY so we can safely assume we need to preroll. */
       GST_PAD_PREROLL_LOCK (basesink->sinkpad);
       GST_DEBUG_OBJECT (basesink, "READY to PAUSED");
+      basesink->have_newsegment = FALSE;
       gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
       gst_segment_init (basesink->abidata.ABI.clip_segment,
           GST_FORMAT_UNDEFINED);
-      basesink->have_newsegment = FALSE;
       basesink->offset = 0;
       basesink->have_preroll = FALSE;
+      priv->step_unlock = FALSE;
       basesink->need_preroll = TRUE;
       basesink->playing_async = TRUE;
       priv->current_sstart = -1;
@@ -3346,6 +4700,9 @@
       priv->received_eos = FALSE;
       gst_base_sink_reset_qos (basesink);
       priv->commited = FALSE;
+      priv->call_preroll = TRUE;
+      priv->current_step.valid = FALSE;
+      priv->pending_step.valid = FALSE;
       if (priv->async_enabled) {
         GST_DEBUG_OBJECT (basesink, "doing async state change");
         /* when async enabled, post async-start message and return ASYNC from
@@ -3366,10 +4723,13 @@
         basesink->playing_async = FALSE;
         basesink->need_preroll = FALSE;
         if (basesink->eos) {
+          GstMessage *message;
+
           /* need to post EOS message here */
           GST_DEBUG_OBJECT (basesink, "Now posting EOS");
-          gst_element_post_message (GST_ELEMENT_CAST (basesink),
-              gst_message_new_eos (GST_OBJECT_CAST (basesink)));
+          message = gst_message_new_eos (GST_OBJECT_CAST (basesink));
+          gst_message_set_seqnum (message, basesink->priv->seqnum);
+          gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
         } else {
           GST_DEBUG_OBJECT (basesink, "signal preroll");
           GST_PAD_PREROLL_SIGNAL (basesink->sinkpad);
@@ -3378,6 +4738,7 @@
         GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, we are not prerolled");
         basesink->need_preroll = TRUE;
         basesink->playing_async = TRUE;
+        priv->call_preroll = TRUE;
         priv->commited = FALSE;
         if (priv->async_enabled) {
           GST_DEBUG_OBJECT (basesink, "doing async state change");
@@ -3401,19 +4762,6 @@
   }
 
   switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      /* note that this is the upward case, which doesn't follow most
-         patterns */
-      if (basesink->pad_mode == GST_ACTIVATE_PULL) {
-        GST_DEBUG_OBJECT (basesink, "basesink activated in pull mode, "
-            "returning SUCCESS directly");
-        GST_PAD_PREROLL_LOCK (basesink->sinkpad);
-        gst_element_post_message (GST_ELEMENT_CAST (basesink),
-            gst_message_new_async_done (GST_OBJECT_CAST (basesink)));
-        GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
-        ret = GST_STATE_CHANGE_SUCCESS;
-      }
-      break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED");
       /* FIXME, make sure we cannot enter _render first */
@@ -3450,6 +4798,7 @@
               "PLAYING to PAUSED, we are not prerolled");
           basesink->playing_async = TRUE;
           priv->commited = FALSE;
+          priv->call_preroll = TRUE;
           if (priv->async_enabled) {
             GST_DEBUG_OBJECT (basesink, "doing async state change");
             ret = GST_STATE_CHANGE_ASYNC;
@@ -3467,6 +4816,19 @@
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+      /* start by reseting our position state with the object lock so that the
+       * position query gets the right idea. We do this before we post the
+       * messages so that the message handlers pick this up. */
+      GST_OBJECT_LOCK (basesink);
+      basesink->have_newsegment = FALSE;
+      priv->current_sstart = -1;
+      priv->current_sstop = -1;
+      priv->have_latency = FALSE;
+      GST_OBJECT_UNLOCK (basesink);
+
+      gst_base_sink_set_last_buffer (basesink, NULL);
+      priv->call_preroll = FALSE;
+
       if (!priv->commited) {
         if (priv->async_enabled) {
           GST_DEBUG_OBJECT (basesink, "PAUSED to READY, posting async-done");
@@ -3482,10 +4844,6 @@
       } else {
         GST_DEBUG_OBJECT (basesink, "PAUSED to READY, don't need_preroll");
       }
-      priv->current_sstart = -1;
-      priv->current_sstop = -1;
-      priv->have_latency = FALSE;
-      gst_base_sink_set_last_buffer (basesink, NULL);
       GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -3495,6 +4853,7 @@
         }
       }
       gst_base_sink_set_last_buffer (basesink, NULL);
+      priv->call_preroll = FALSE;
       break;
     default:
       break;
--- a/gstreamer_core/libs/gst/base/gstbasesink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstbasesink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -91,10 +91,11 @@
   /*< private >*/
   union {
     struct {
-      /* segment used for clipping incomming buffers */
+      /* segment used for clipping incoming buffers */
       GstSegment    *clip_segment;
       /* max amount of time a buffer can be late, -1 no limit. */
       gint64	     max_lateness;
+      gboolean       running;
     } ABI;
     gpointer _gst_reserved[GST_PADDING_LARGE - 1];
   } abidata;
@@ -120,6 +121,8 @@
  * @preroll: Called to present the preroll buffer if desired
  * @render: Called when a buffer should be presented or output, at the
  *     correct moment if the #GstBaseSink has been set to sync to the clock.
+ * @render_list: Same as @render but used whith buffer lists instead of
+ *     buffers. Since: 0.10.24
  * @async_play: Subclasses should override this when they need to perform
  *     special processing when changing to the PLAYING state asynchronously.
  *     Called with the OBJECT_LOCK held.
@@ -179,10 +182,13 @@
   /* Clear a previously indicated unlock request not that unlocking is 
    * complete. Sub-classes should clear any command queue or indicator they
    * set during unlock */
-  gboolean      (*unlock_stop)       (GstBaseSink *sink);
+  gboolean      (*unlock_stop)  (GstBaseSink *sink);
+
+  /* Render a BufferList */
+  GstFlowReturn (*render_list)  (GstBaseSink *sink, GstBufferList *buffer_list);
 
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE-4];
+  gpointer       _gst_reserved[GST_PADDING_LARGE-5];
 };
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -195,6 +201,11 @@
 #endif
 
 
+GstFlowReturn	gst_base_sink_do_preroll 	(GstBaseSink *sink, GstMiniObject *obj);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 GstFlowReturn	gst_base_sink_wait_preroll 	(GstBaseSink *sink);
 
 /* synchronizing against the clock */
@@ -276,10 +287,40 @@
 #endif
 
 GstClockTime	gst_base_sink_get_latency 	(GstBaseSink *sink);
+
+/* render delay */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_base_sink_set_render_delay  (GstBaseSink *sink, GstClockTime delay);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
+GstClockTime    gst_base_sink_get_render_delay 	(GstBaseSink *sink);
+
+/* blocksize */
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_base_sink_set_blocksize     (GstBaseSink *sink, guint blocksize);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint           gst_base_sink_get_blocksize 	(GstBaseSink *sink);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstClockReturn  gst_base_sink_wait_clock        (GstBaseSink *sink, GstClockTime time,
+                                                 GstClockTimeDiff * jitter);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
 
 GstFlowReturn   gst_base_sink_wait_eos          (GstBaseSink *sink, GstClockTime time,
                                                  GstClockTimeDiff *jitter);
--- a/gstreamer_core/libs/gst/base/gstbasesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstbasesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,14 +33,11 @@
  *   <listitem><para>live sources</para></listitem>
  * </itemizedlist>
  *
- * <refsect2>
- * <para>
  * The source can be configured to operate in any #GstFormat with the
  * gst_base_src_set_format() method. The currently set format determines 
  * the format of the internal #GstSegment and any #GST_EVENT_NEWSEGMENT 
  * events. The default format for #GstBaseSrc is #GST_FORMAT_BYTES.
- * </para>
- * <para>
+ *
  * #GstBaseSrc always supports push mode scheduling. If the following
  * conditions are met, it also supports pull mode scheduling:
  * <itemizedlist>
@@ -49,12 +46,10 @@
  *   <listitem><para>#GstBaseSrc::is_seekable returns %TRUE.</para>
  *   </listitem>
  * </itemizedlist>
- * </para>
- * <para>
+ * 
  * Since 0.10.9, any #GstBaseSrc can enable pull based scheduling at any 
  * time by overriding #GstBaseSrc::check_get_range so that it returns %TRUE. 
- * </para>
- * <para>
+ * 
  * If all the conditions are met for operating in pull mode, #GstBaseSrc is
  * automatically seekable in push mode as well. The following conditions must 
  * be met to make the element seekable in push mode when the format is not
@@ -71,40 +66,34 @@
  *     #GstBaseSrc::do_seek is implemented, performs the seek and returns %TRUE.
  *   </para></listitem>
  * </itemizedlist>
- * </para>
- * <para>
+ * 
  * When the element does not meet the requirements to operate in pull mode,
  * the offset and length in the #GstBaseSrc::create method should be ignored.
  * It is recommended to subclass #GstPushSrc instead, in this situation. If the
  * element can operate in pull mode but only with specific offsets and
  * lengths, it is allowed to generate an error when the wrong values are passed
  * to the #GstBaseSrc::create function.
- * </para>
- * <para>
+ * 
  * #GstBaseSrc has support for live sources. Live sources are sources that when
  * paused discard data, such as audio or video capture devices. A typical live
  * source also produces data at a fixed rate and thus provides a clock to publish
  * this rate.
  * Use gst_base_src_set_live() to activate the live source mode.
- * </para>
- * <para>
+ * 
  * A live source does not produce data in the PAUSED state. This means that the 
  * #GstBaseSrc::create method will not be called in PAUSED but only in PLAYING.
  * To signal the pipeline that the element will not produce data, the return
  * value from the READY to PAUSED state will be #GST_STATE_CHANGE_NO_PREROLL.
- * </para>
- * <para>
+ * 
  * A typical live source will timestamp the buffers it creates with the 
  * current running time of the pipeline. This is one reason why a live source
  * can only produce data in the PLAYING state, when the clock is actually 
  * distributed and running. 
- * </para>
- * <para>
+ * 
  * Live sources that synchronize and block on the clock (an audio source, for
  * example) can since 0.10.12 use gst_base_src_wait_playing() when the ::create
  * function was interrupted by a state change to PAUSED.
- * </para>
- * <para>
+ * 
  * The #GstBaseSrc::get_times method can be used to implement pseudo-live 
  * sources.
  * It only makes sense to implement the ::get_times function if the source is 
@@ -113,21 +102,17 @@
  * the timestamps are transformed into the current running_time.
  * The base source will then wait for the calculated running_time before pushing
  * out the buffer.
- * </para>
- * <para>
+ * 
  * For live sources, the base class will by default report a latency of 0.
  * For pseudo live sources, the base class will by default measure the difference
  * between the first buffer timestamp and the start time of get_times and will
  * report this value as the latency. 
  * Subclasses should override the query function when this behaviour is not
  * acceptable.
- * </para>
- * <para>
+ * 
  * There is only support in #GstBaseSrc for exactly one source pad, which 
  * should be named "src". A source implementation (subclass of #GstBaseSrc) 
  * should install a pad template in its class_init function, like so:
- * </para>
- * <para>
  * <programlisting>
  * static void
  * my_element_class_init (GstMyElementClass *klass)
@@ -141,7 +126,8 @@
  *   gst_element_class_set_details (gstelement_class, &amp;details);
  * }
  * </programlisting>
- * </para>
+ *
+ * <refsect2>
  * <title>Controlled shutdown of live sources in applications</title>
  * <para>
  * Applications that record from a live source may want to stop recording
@@ -152,22 +138,19 @@
  * event down the pipeline. The application would then wait for an
  * EOS message posted on the pipeline's bus to know when all data has
  * been processed and the pipeline can safely be stopped.
- * </para>
- * <para>
+ * 
  * Since GStreamer 0.10.16 an application may send an EOS event to a source
- * element to make it send an EOS event downstream. This can typically be done
+ * element to make it perform the EOS logic (send EOS event downstream or post a
+ * #GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done
  * with the gst_element_send_event() function on the element or its parent bin.
- * </para>
- * <para>
+ * 
  * After the EOS has been sent to the element, the application should wait for
  * an EOS message to be posted on the pipeline's bus. Once this EOS message is
  * received, it may safely shut down the entire pipeline.
- * </para>
- * <para>
+ * 
  * The old behaviour for controlled shutdown introduced since GStreamer 0.10.3
  * is still available but deprecated as it is dangerous and less flexible.
- * </para>
- * <para>
+ * 
  * Last reviewed on 2007-12-19 (0.10.16)
  * </para>
  * </refsect2>
@@ -243,8 +226,8 @@
   GstEvent *close_segment;
   GstEvent *start_segment;
 
-  /* if EOS is pending */
-  gboolean pending_eos;
+  /* if EOS is pending (atomic) */
+  gint pending_eos;
 
   /* startup latency is the time it takes between going to PLAYING and producing
    * the first BUFFER with running_time 0. This value is included in the latency
@@ -255,6 +238,12 @@
   GstClockTimeDiff ts_offset;
 
   gboolean do_timestamp;
+
+  /* stream sequence number */
+  guint32 seqnum;
+
+  /* pending tags to be pushed in the data stream */
+  GList *pending_tags;
 };
 
 static GstElementClass *parent_class = NULL;
@@ -272,9 +261,10 @@
 GType
 gst_base_src_get_type (void)
 {
-  static GType base_src_type = 0;
-
-  if (G_UNLIKELY (base_src_type == 0)) {
+  static volatile gsize base_src_type = 0;
+
+  if (g_once_init_enter (&base_src_type)) {
+    GType _type;
     static const GTypeInfo base_src_info = {
       sizeof (GstBaseSrcClass),
       (GBaseInitFunc) gst_base_src_base_init,
@@ -287,11 +277,13 @@
       (GInstanceInitFunc) gst_base_src_init,
     };
 
-    base_src_type = g_type_register_static (GST_TYPE_ELEMENT,
+    _type = g_type_register_static (GST_TYPE_ELEMENT,
         "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);
+    g_once_init_leave (&base_src_type, _type);
   }
   return base_src_type;
 }
+
 static GstCaps *gst_base_src_getcaps (GstPad * pad);
 static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
 static void gst_base_src_fixate (GstPad * pad, GstCaps * caps);
@@ -331,6 +323,7 @@
     guint length, GstBuffer ** buf);
 static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
     guint length, GstBuffer ** buf);
+static gboolean gst_base_src_seekable (GstBaseSrc * src);
 
 static void
 gst_base_src_base_init (gpointer g_class)
@@ -357,20 +350,21 @@
 
   g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
       g_param_spec_ulong ("blocksize", "Block size",
-          "Size in bytes to read per buffer (0 = default)", 0, G_MAXULONG,
-          DEFAULT_BLOCKSIZE, G_PARAM_READWRITE));
+          "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG,
+          DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
       g_param_spec_int ("num-buffers", "num-buffers",
-          "Number of buffers to output before sending EOS", -1, G_MAXINT,
-          DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE));
+          "Number of buffers to output before sending EOS (-1 = unlimited)",
+          -1, G_MAXINT, DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE |
+          G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_TYPEFIND,
       g_param_spec_boolean ("typefind", "Typefind",
           "Run typefind before negotiating", DEFAULT_TYPEFIND,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DO_TIMESTAMP,
       g_param_spec_boolean ("do-timestamp", "Do timestamp",
           "Apply current stream time to buffers", DEFAULT_DO_TIMESTAMP,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_src_change_state);
@@ -460,6 +454,11 @@
   event_p = &basesrc->data.ABI.pending_seek;
   gst_event_replace (event_p, NULL);
 
+  if (basesrc->priv->pending_tags) {
+    g_list_foreach (basesrc->priv->pending_tags, (GFunc) gst_event_unref, NULL);
+    g_list_free (basesrc->priv->pending_tags);
+  }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -488,6 +487,8 @@
 GstFlowReturn
 gst_base_src_wait_playing (GstBaseSrc * src)
 {
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), GST_FLOW_ERROR);
+
   /* block until the state changes, or we get a flush, or something */
   GST_DEBUG_OBJECT (src, "live source waiting for running state");
   GST_LIVE_WAIT (src);
@@ -526,6 +527,8 @@
 void
 gst_base_src_set_live (GstBaseSrc * src, gboolean live)
 {
+  g_return_if_fail (GST_IS_BASE_SRC (src));
+
   GST_OBJECT_LOCK (src);
   src->is_live = live;
   GST_OBJECT_UNLOCK (src);
@@ -548,6 +551,8 @@
 {
   gboolean result;
 
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
+
   GST_OBJECT_LOCK (src);
   result = src->is_live;
   GST_OBJECT_UNLOCK (src);
@@ -575,6 +580,8 @@
 void
 gst_base_src_set_format (GstBaseSrc * src, GstFormat format)
 {
+  g_return_if_fail (GST_IS_BASE_SRC (src));
+
   gst_segment_init (&src->segment, format);
 }
 
@@ -606,6 +613,8 @@
 {
   GstClockTime min;
 
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
+
   GST_OBJECT_LOCK (src);
   if (live)
     *live = src->is_live;
@@ -632,6 +641,59 @@
 }
 
 /**
+ * gst_base_src_set_blocksize:
+ * @src: the source
+ * @blocksize: the new blocksize in bytes
+ *
+ * Set the number of bytes that @src will push out with each buffer. When
+ * @blocksize is set to -1, a default length will be used.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize)
+{
+  g_return_if_fail (GST_IS_BASE_SRC (src));
+
+  GST_OBJECT_LOCK (src);
+  src->blocksize = blocksize;
+  GST_OBJECT_UNLOCK (src);
+}
+
+/**
+ * gst_base_src_get_blocksize:
+ * @src: the source
+ *
+ * Get the number of bytes that @src will push out with each buffer.
+ *
+ * Returns: the number of bytes pushed with each buffer.
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gulong
+gst_base_src_get_blocksize (GstBaseSrc * src)
+{
+  gulong res;
+
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), 0);
+
+  GST_OBJECT_LOCK (src);
+  res = src->blocksize;
+  GST_OBJECT_UNLOCK (src);
+
+  return res;
+}
+
+
+/**
  * gst_base_src_set_do_timestamp:
  * @src: the source
  * @timestamp: enable or disable timestamping
@@ -649,6 +711,8 @@
 void
 gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp)
 {
+  g_return_if_fail (GST_IS_BASE_SRC (src));
+
   GST_OBJECT_LOCK (src);
   src->priv->do_timestamp = timestamp;
   GST_OBJECT_UNLOCK (src);
@@ -673,6 +737,8 @@
 {
   gboolean res;
 
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
+
   GST_OBJECT_LOCK (src);
   res = src->priv->do_timestamp;
   GST_OBJECT_UNLOCK (src);
@@ -797,6 +863,7 @@
 
       GST_DEBUG_OBJECT (src, "duration query in format %s",
           gst_format_get_name (format));
+
       switch (format) {
         case GST_FORMAT_PERCENT:
           gst_query_set_duration (query, GST_FORMAT_PERCENT,
@@ -832,9 +899,20 @@
 
     case GST_QUERY_SEEKING:
     {
-      gst_query_set_seeking (query, src->segment.format,
-          src->seekable, 0, src->segment.duration);
-      res = TRUE;
+      GstFormat format;
+
+      gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
+      if (format == src->segment.format) {
+        gst_query_set_seeking (query, src->segment.format,
+            gst_base_src_seekable (src), 0, src->segment.duration);
+        res = TRUE;
+      } else {
+        /* FIXME 0.11: return TRUE + seekable=FALSE for SEEKING query here */
+        /* Don't reply to the query to make up for demuxers which don't
+         * handle the SEEKING query yet. Players like Totem will fall back
+         * to the duration when the SEEKING query isn't answered. */
+        res = FALSE;
+      }
       break;
     }
     case GST_QUERY_SEGMENT:
@@ -899,6 +977,46 @@
     }
     case GST_QUERY_JITTER:
     case GST_QUERY_RATE:
+      res = FALSE;
+      break;
+    case GST_QUERY_BUFFERING:
+    {
+      GstFormat format;
+      gint64 start, stop, estimated;
+
+      gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL);
+
+      GST_DEBUG_OBJECT (src, "buffering query in format %s",
+          gst_format_get_name (format));
+
+      if (src->random_access) {
+        estimated = 0;
+        start = 0;
+        if (format == GST_FORMAT_PERCENT)
+          stop = GST_FORMAT_PERCENT_MAX;
+        else
+          stop = src->segment.duration;
+      } else {
+        estimated = -1;
+        start = -1;
+        stop = -1;
+      }
+      /* convert to required format. When the conversion fails, we can't answer
+       * the query. When the value is unknown, we can don't perform conversion
+       * but report TRUE. */
+      if (format != GST_FORMAT_PERCENT && stop != -1) {
+        res = gst_pad_query_convert (src->srcpad, src->segment.format,
+            stop, &format, &stop);
+      } else {
+        res = TRUE;
+      }
+      if (res && format != GST_FORMAT_PERCENT && start != -1)
+        res = gst_pad_query_convert (src->srcpad, src->segment.format,
+            start, &format, &start);
+
+      gst_query_set_buffering_range (query, format, start, stop, estimated);
+      break;
+    }
     default:
       res = FALSE;
       break;
@@ -940,9 +1058,10 @@
   } else if (segment->start == 0) {
     /* seek to start, we can implement a default for this. */
     segment->time = 0;
-    res = TRUE;
-  } else
+  } else {
     res = FALSE;
+    GST_INFO_OBJECT (src, "Can't do a default seek");
+  }
 
   return res;
 }
@@ -1096,7 +1215,7 @@
 static gboolean
 gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
 {
-  gboolean res = TRUE;
+  gboolean res = TRUE, tres;
   gdouble rate;
   GstFormat seek_format, dest_format;
   GstSeekFlags flags;
@@ -1107,6 +1226,8 @@
   gboolean relative_seek = FALSE;
   gboolean seekseg_configured = FALSE;
   GstSegment seeksegment;
+  guint32 seqnum;
+  GstEvent *tevent;
 
   GST_DEBUG_OBJECT (src, "doing seek");
 
@@ -1122,7 +1243,8 @@
     if (dest_format != seek_format && !relative_seek) {
       /* If we have an ABSOLUTE position (SEEK_SET only), we can convert it
        * here before taking the stream lock, otherwise we must convert it later,
-       * once we have the stream lock and can read the current position */
+       * once we have the stream lock and can read the last configures segment
+       * start and stop positions */
       gst_segment_init (&seeksegment, dest_format);
 
       if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment))
@@ -1132,14 +1254,19 @@
     }
 
     flush = flags & GST_SEEK_FLAG_FLUSH;
+    seqnum = gst_event_get_seqnum (event);
   } else {
     flush = FALSE;
+    /* get next seqnum */
+    seqnum = gst_util_seqnum_next ();
   }
 
   /* send flush start */
-  if (flush)
-    gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
-  else
+  if (flush) {
+    tevent = gst_event_new_flush_start ();
+    gst_event_set_seqnum (tevent, seqnum);
+    gst_pad_push_event (src->srcpad, tevent);
+  } else
     gst_pad_pause_task (src->srcpad);
 
   /* unblock streaming thread. */
@@ -1149,6 +1276,14 @@
    * because the task is paused, our streaming thread stopped 
    * or because our peer is flushing. */
   GST_PAD_STREAM_LOCK (src->srcpad);
+  if (G_UNLIKELY (src->priv->seqnum == seqnum)) {
+    /* we have seen this event before, issue a warning for now */
+    GST_WARNING_OBJECT (src, "duplicate event found %" G_GUINT32_FORMAT,
+        seqnum);
+  } else {
+    src->priv->seqnum = seqnum;
+    GST_DEBUG_OBJECT (src, "seek with seqnum %" G_GUINT32_FORMAT, seqnum);
+  }
 
   gst_base_src_set_flushing (src, FALSE, playing, unlock, NULL);
 
@@ -1191,9 +1326,11 @@
 
   /* and prepare to continue streaming */
   if (flush) {
+    tevent = gst_event_new_flush_stop ();
+    gst_event_set_seqnum (tevent, seqnum);
     /* send flush stop, peer will accept data and events again. We
      * are not yet providing data as we still have the STREAM_LOCK. */
-    gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
+    gst_pad_push_event (src->srcpad, tevent);
   } else if (res && src->data.ABI.running) {
     /* we are running the current segment and doing a non-flushing seek, 
      * close the segment first based on the last_stop. */
@@ -1207,6 +1344,7 @@
         gst_event_new_new_segment_full (TRUE,
         src->segment.rate, src->segment.applied_rate, src->segment.format,
         src->segment.start, src->segment.last_stop, src->segment.time);
+    gst_event_set_seqnum (src->priv->close_segment, seqnum);
   }
 
   /* The subclass must have converted the segment to the processing format 
@@ -1223,9 +1361,13 @@
     memcpy (&src->segment, &seeksegment, sizeof (GstSegment));
 
     if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
-      gst_element_post_message (GST_ELEMENT (src),
-          gst_message_new_segment_start (GST_OBJECT (src),
-              src->segment.format, src->segment.last_stop));
+      GstMessage *message;
+
+      message = gst_message_new_segment_start (GST_OBJECT (src),
+          src->segment.format, src->segment.last_stop);
+      gst_message_set_seqnum (message, seqnum);
+
+      gst_element_post_message (GST_ELEMENT (src), message);
     }
 
     /* for deriving a stop position for the playback segment from the seek
@@ -1247,20 +1389,23 @@
           src->segment.rate, src->segment.applied_rate, src->segment.format,
           src->segment.last_stop, stop, src->segment.time);
     } else {
-      /* reverse, we send data from stop to last_stop */
+      /* reverse, we send data from last_stop to start */
       src->priv->start_segment =
           gst_event_new_new_segment_full (FALSE,
           src->segment.rate, src->segment.applied_rate, src->segment.format,
           src->segment.start, src->segment.last_stop, src->segment.time);
     }
+    gst_event_set_seqnum (src->priv->start_segment, seqnum);
   }
 
   src->priv->discont = TRUE;
   src->data.ABI.running = TRUE;
   /* and restart the task in case it got paused explicitely or by
    * the FLUSH_START event we pushed out. */
-  gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
+  tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
       src->srcpad);
+  if (res && !tres)
+    res = FALSE;
 
   /* and release the lock again so we can continue streaming */
   GST_PAD_STREAM_UNLOCK (src->srcpad);
@@ -1304,6 +1449,8 @@
 
   src = GST_BASE_SRC (element);
 
+  GST_DEBUG_OBJECT (src, "reveived %s event", GST_EVENT_TYPE_NAME (event));
+
   switch (GST_EVENT_TYPE (event)) {
       /* bidirectional events */
     case GST_EVENT_FLUSH_START:
@@ -1314,18 +1461,56 @@
 
       /* downstream serialized events */
     case GST_EVENT_EOS:
-      /* queue EOS and make sure the task or pull function 
-       * performs the EOS actions. */
+    {
+      GstBaseSrcClass *bclass;
+
+      bclass = GST_BASE_SRC_GET_CLASS (src);
+
+      /* queue EOS and make sure the task or pull function performs the EOS
+       * actions. 
+       *
+       * We have two possibilities:
+       *
+       *  - Before we are to enter the _create function, we check the pending_eos
+       *    first and do EOS instead of entering it.
+       *  - If we are in the _create function or we did not manage to set the
+       *    flag fast enough and we are about to enter the _create function,
+       *    we unlock it so that we exit with WRONG_STATE immediatly. We then
+       *    check the EOS flag and do the EOS logic.
+       */
+      g_atomic_int_set (&src->priv->pending_eos, TRUE);
+      GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
+
+      /* unlock the _create function so that we can check the pending_eos flag
+       * and we can do EOS. This will eventually release the LIVE_LOCK again so
+       * that we can grab it and stop the unlock again. We don't take the stream
+       * lock so that this operation is guaranteed to never block. */
+      if (bclass->unlock)
+        bclass->unlock (src);
+
+      GST_DEBUG_OBJECT (src, "unlock called, waiting for LIVE_LOCK");
+
       GST_LIVE_LOCK (src);
-      src->priv->pending_eos = TRUE;
+      GST_DEBUG_OBJECT (src, "LIVE_LOCK acquired, calling unlock_stop");
+      /* now stop the unlock of the streaming thread again. Grabbing the live
+       * lock is enough because that protects the create function. */
+      if (bclass->unlock_stop)
+        bclass->unlock_stop (src);
       GST_LIVE_UNLOCK (src);
+
       result = TRUE;
       break;
+    }
     case GST_EVENT_NEWSEGMENT:
       /* sending random NEWSEGMENT downstream can break sync. */
       break;
     case GST_EVENT_TAG:
-      /* sending tags could be useful, FIXME insert in dataflow */
+      /* Insert tag in the dataflow */
+      GST_OBJECT_LOCK (src);
+      src->priv->pending_tags = g_list_append (src->priv->pending_tags, event);
+      GST_OBJECT_UNLOCK (src);
+      event = NULL;
+      result = TRUE;
       break;
     case GST_EVENT_BUFFERSIZE:
       /* does not seem to make much sense currently */
@@ -1346,6 +1531,7 @@
       GST_OBJECT_UNLOCK (src->srcpad);
 
       if (started) {
+        GST_DEBUG_OBJECT (src, "performing seek");
         /* when we are running in push mode, we can execute the
          * seek right now, we need to unlock. */
         result = gst_base_src_perform_seek (src, event, TRUE);
@@ -1355,6 +1541,7 @@
         /* else we store the event and execute the seek when we
          * get activated */
         GST_OBJECT_LOCK (src);
+        GST_DEBUG_OBJECT (src, "queueing seek");
         event_p = &src->data.ABI.pending_seek;
         gst_event_replace ((GstEvent **) event_p, event);
         GST_OBJECT_UNLOCK (src);
@@ -1408,6 +1595,17 @@
 }
 
 static gboolean
+gst_base_src_seekable (GstBaseSrc * src)
+{
+  GstBaseSrcClass *bclass;
+  bclass = GST_BASE_SRC_GET_CLASS (src);
+  if (bclass->is_seekable)
+    return bclass->is_seekable (src);
+  else
+    return FALSE;
+}
+
+static gboolean
 gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
 {
   gboolean result;
@@ -1415,7 +1613,7 @@
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
       /* is normally called when in push mode */
-      if (!src->seekable)
+      if (!gst_base_src_seekable (src))
         goto not_seekable;
 
       result = gst_base_src_perform_seek (src, event, TRUE);
@@ -1481,7 +1679,7 @@
 
   switch (prop_id) {
     case PROP_BLOCKSIZE:
-      src->blocksize = g_value_get_ulong (value);
+      gst_base_src_set_blocksize (src, g_value_get_ulong (value));
       break;
     case PROP_NUM_BUFFERS:
       src->num_buffers = g_value_get_int (value);
@@ -1490,7 +1688,7 @@
       src->data.ABI.typefind = g_value_get_boolean (value);
       break;
     case PROP_DO_TIMESTAMP:
-      src->priv->do_timestamp = g_value_get_boolean (value);
+      gst_base_src_set_do_timestamp (src, g_value_get_boolean (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1508,7 +1706,7 @@
 
   switch (prop_id) {
     case PROP_BLOCKSIZE:
-      g_value_set_ulong (value, src->blocksize);
+      g_value_set_ulong (value, gst_base_src_get_blocksize (src));
       break;
     case PROP_NUM_BUFFERS:
       g_value_set_int (value, src->num_buffers);
@@ -1517,7 +1715,7 @@
       g_value_set_boolean (value, src->data.ABI.typefind);
       break;
     case PROP_DO_TIMESTAMP:
-      g_value_set_boolean (value, src->priv->do_timestamp);
+      g_value_set_boolean (value, gst_base_src_get_do_timestamp (src));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1810,11 +2008,28 @@
       src->num_buffers_left--;
   }
 
+  /* don't enter the create function if a pending EOS event was set. For the
+   * logic of the pending_eos, check the event function of this class. */
+  if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos)))
+    goto eos;
+
   GST_DEBUG_OBJECT (src,
       "calling create offset %" G_GUINT64_FORMAT " length %u, time %"
       G_GINT64_FORMAT, offset, length, src->segment.time);
 
   ret = bclass->create (src, offset, length, buf);
+
+  /* The create function could be unlocked because we have a pending EOS. It's
+   * possible that we have a valid buffer from create that we need to
+   * discard when the create function returned _OK. */
+  if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos))) {
+    if (ret == GST_FLOW_OK) {
+      gst_buffer_unref (*buf);
+      *buf = NULL;
+    }
+    goto eos;
+  }
+
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto not_ok;
 
@@ -1823,6 +2038,10 @@
       && GST_BUFFER_TIMESTAMP (*buf) == -1)
     GST_BUFFER_TIMESTAMP (*buf) = 0;
 
+  /* set pad caps on the buffer if the buffer had no caps */
+  if (GST_BUFFER_CAPS (*buf) == NULL)
+    gst_buffer_set_caps (*buf, GST_PAD_CAPS (src->srcpad));
+
   /* now sync before pushing the buffer */
   status = gst_base_src_do_sync (src, *buf);
 
@@ -1830,9 +2049,6 @@
   if (G_UNLIKELY (src->priv->flushing))
     goto flushing;
 
-  if (G_UNLIKELY (src->priv->pending_eos))
-    goto eos;
-
   switch (status) {
     case GST_CLOCK_EARLY:
       /* the buffer is too late. We currently don't drop the buffer. */
@@ -1909,8 +2125,6 @@
 eos:
   {
     GST_DEBUG_OBJECT (src, "we are EOS");
-    gst_buffer_unref (*buf);
-    *buf = NULL;
     return GST_FLOW_UNEXPECTED;
   }
 }
@@ -1928,10 +2142,6 @@
   if (G_UNLIKELY (src->priv->flushing))
     goto flushing;
 
-  /* if we're EOS, return right away */
-  if (G_UNLIKELY (src->priv->pending_eos))
-    goto eos;
-
   res = gst_base_src_get_range (src, offset, length, buf);
 
 done:
@@ -1948,12 +2158,6 @@
     res = GST_FLOW_WRONG_STATE;
     goto done;
   }
-eos:
-  {
-    GST_DEBUG_OBJECT (src, "we are EOS");
-    res = GST_FLOW_UNEXPECTED;
-    goto done;
-  }
 }
 
 static gboolean
@@ -2022,19 +2226,17 @@
   gint64 position;
   gboolean eos;
   gulong blocksize;
+  GList *tags, *tmp;
 
   eos = FALSE;
 
   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
 
   GST_LIVE_LOCK (src);
+
   if (G_UNLIKELY (src->priv->flushing))
     goto flushing;
 
-  /* if we're EOS, return right away */
-  if (G_UNLIKELY (src->priv->pending_eos))
-    goto eos;
-
   src->priv->last_sent_eos = FALSE;
 
   blocksize = src->blocksize;
@@ -2056,6 +2258,9 @@
   } else
     position = -1;
 
+  GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %lu",
+      GST_TIME_ARGS (position), blocksize);
+
   ret = gst_base_src_get_range (src, position, blocksize, &buf);
   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
     GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s",
@@ -2077,6 +2282,21 @@
     src->priv->start_segment = NULL;
   }
 
+  GST_OBJECT_LOCK (src);
+  /* take the tags */
+  tags = src->priv->pending_tags;
+  src->priv->pending_tags = NULL;
+  GST_OBJECT_UNLOCK (src);
+
+  /* Push out pending tags if any */
+  if (G_UNLIKELY (tags != NULL)) {
+    for (tmp = tags; tmp; tmp = g_list_next (tmp)) {
+      GstEvent *ev = (GstEvent *) tmp->data;
+      gst_pad_push_event (pad, ev);
+    }
+    g_list_free (tags);
+  }
+
   /* figure out the new position */
   switch (src->segment.format) {
     case GST_FORMAT_BYTES:
@@ -2173,16 +2393,10 @@
     ret = GST_FLOW_WRONG_STATE;
     goto pause;
   }
-eos:
-  {
-    GST_DEBUG_OBJECT (src, "we are EOS");
-    GST_LIVE_UNLOCK (src);
-    ret = GST_FLOW_UNEXPECTED;
-    goto pause;
-  }
 pause:
   {
     const gchar *reason = gst_flow_get_name (ret);
+    GstEvent *event;
 
     GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
     src->data.ABI.running = FALSE;
@@ -2191,20 +2405,27 @@
       if (ret == GST_FLOW_UNEXPECTED) {
         /* perform EOS logic */
         if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
-          gst_element_post_message (GST_ELEMENT_CAST (src),
-              gst_message_new_segment_done (GST_OBJECT_CAST (src),
-                  src->segment.format, src->segment.last_stop));
+          GstMessage *message;
+
+          message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
+              src->segment.format, src->segment.last_stop);
+          gst_message_set_seqnum (message, src->priv->seqnum);
+          gst_element_post_message (GST_ELEMENT_CAST (src), message);
         } else {
-          gst_pad_push_event (pad, gst_event_new_eos ());
+          event = gst_event_new_eos ();
+          gst_event_set_seqnum (event, src->priv->seqnum);
+          gst_pad_push_event (pad, event);
           src->priv->last_sent_eos = TRUE;
         }
       } else {
+        event = gst_event_new_eos ();
+        gst_event_set_seqnum (event, src->priv->seqnum);
         /* for fatal errors we post an error message, post the error
          * first so the app knows about the error first. */
         GST_ELEMENT_ERROR (src, STREAM, FAILED,
             (_("Internal data flow error.")),
             ("streaming task paused, reason %s (%d)", reason, ret));
-        gst_pad_push_event (pad, gst_event_new_eos ());
+        gst_pad_push_event (pad, event);
         src->priv->last_sent_eos = TRUE;
       }
     }
@@ -2241,6 +2462,9 @@
   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
     goto no_nego_needed;
 
+  if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
+    goto no_caps;
+
   /* get the peer caps */
   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
@@ -2275,12 +2499,14 @@
          * nego is not needed */
         result = TRUE;
       } else if (gst_caps_is_fixed (caps)) {
-        /* yay, fixed caps, use those then */
-        gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
-        result = TRUE;
+        /* yay, fixed caps, use those then, it's possible that the subclass does
+         * not accept this caps after all and we have to fail. */
+        result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
       }
     }
     gst_caps_unref (caps);
+  } else {
+    GST_DEBUG_OBJECT (basesrc, "no common caps");
   }
   return result;
 
@@ -2291,6 +2517,15 @@
       gst_caps_unref (thiscaps);
     return TRUE;
   }
+no_caps:
+  {
+    GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
+        ("No supported formats found"),
+        ("This element did not produce valid caps"));
+    if (thiscaps)
+      gst_caps_unref (thiscaps);
+    return TRUE;
+  }
 }
 
 static gboolean
@@ -2313,6 +2548,7 @@
   GstBaseSrcClass *bclass;
   gboolean result;
   guint64 size;
+  gboolean seekable;
 
   if (GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
     return TRUE;
@@ -2357,16 +2593,11 @@
       G_GINT64_FORMAT, basesrc->segment.format, result, size,
       basesrc->segment.duration);
 
-  /* check if we can seek */
-  if (bclass->is_seekable)
-    basesrc->seekable = bclass->is_seekable (basesrc);
-  else
-    basesrc->seekable = FALSE;
-
-  GST_DEBUG_OBJECT (basesrc, "is seekable: %d", basesrc->seekable);
+  seekable = gst_base_src_seekable (basesrc);
+  GST_DEBUG_OBJECT (basesrc, "is seekable: %d", seekable);
 
   /* update for random access flag */
-  basesrc->random_access = basesrc->seekable &&
+  basesrc->random_access = seekable &&
       basesrc->segment.format == GST_FORMAT_BYTES;
 
   GST_DEBUG_OBJECT (basesrc, "is random_access: %d", basesrc->random_access);
@@ -2375,7 +2606,9 @@
   if (basesrc->random_access && basesrc->data.ABI.typefind && size != -1) {
     GstCaps *caps;
 
-    caps = gst_type_find_helper (basesrc->srcpad, size);
+    if (!(caps = gst_type_find_helper (basesrc->srcpad, size)))
+      goto typefind_failed;
+
     gst_pad_set_caps (basesrc->srcpad, caps);
     gst_caps_unref (caps);
   } else {
@@ -2402,6 +2635,14 @@
     gst_base_src_stop (basesrc);
     return FALSE;
   }
+typefind_failed:
+  {
+    GST_DEBUG_OBJECT (basesrc, "could not typefind, stopping");
+    GST_ELEMENT_ERROR (basesrc, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
+    /* we must call stop */
+    gst_base_src_stop (basesrc);
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -2452,8 +2693,9 @@
   if (flushing) {
     /* if we are locked in the live lock, signal it to make it flush */
     basesrc->live_running = TRUE;
+
     /* clear pending EOS if any */
-    basesrc->priv->pending_eos = FALSE;
+    g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
 
     /* step 1, now that we have the LIVE lock, clear our unlock request */
     if (bclass->unlock_stop)
@@ -2696,7 +2938,7 @@
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
     {
-      GstEvent **event_p;
+      GstEvent **event_p, *event;
 
       /* we don't need to unblock anything here, the pad deactivation code
        * already did this */
@@ -2706,10 +2948,12 @@
        * the EOS event to the element */
       if (!basesrc->priv->last_sent_eos) {
         GST_DEBUG_OBJECT (basesrc, "Sending EOS event");
-        gst_pad_push_event (basesrc->srcpad, gst_event_new_eos ());
+        event = gst_event_new_eos ();
+        gst_event_set_seqnum (event, basesrc->priv->seqnum);
+        gst_pad_push_event (basesrc->srcpad, event);
         basesrc->priv->last_sent_eos = TRUE;
       }
-      basesrc->priv->pending_eos = FALSE;
+      g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
       event_p = &basesrc->data.ABI.pending_seek;
       gst_event_replace (event_p, NULL);
       event_p = &basesrc->priv->close_segment;
--- a/gstreamer_core/libs/gst/base/gstbasesrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstbasesrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -85,7 +85,7 @@
   gint		 blocksize;	/* size of buffers when operating push based */
   gboolean	 can_activate_push;	/* some scheduling properties */
   GstActivateMode pad_mode;
-  gboolean       seekable;
+  gboolean       seekable; /* not used anymore */
   gboolean       random_access;
 
   GstClockID     clock_id;	/* for syncing */
@@ -150,7 +150,7 @@
  *   cycles. The default implementation will open and close the resource 
  *   to find out whether get_range is supported, and that is usually 
  *   undesirable. 
- * @fixate: Called during negotation if caps need fixating. Implement instead of
+ * @fixate: Called during negotiation if caps need fixating. Implement instead of
  *   setting a fixate function on the source pad.
  *
  * Subclasses can override any of the available virtual methods or not, as
@@ -213,7 +213,7 @@
    * undesirable. */
   gboolean      (*check_get_range) (GstBaseSrc *src);
 
-  /* called if, in negotation, caps need fixating */
+  /* called if, in negotiation, caps need fixating */
   void		(*fixate)	(GstBaseSrc *src, GstCaps *caps);
 
   /* Clear any pending unlock request, as we succeeded in unlocking */
@@ -269,7 +269,18 @@
 #endif
 
 
-void		gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean live);
+void		gst_base_src_set_blocksize    (GstBaseSrc *src, gulong blocksize);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gulong          gst_base_src_get_blocksize    (GstBaseSrc *src);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void		gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean timestamp);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
--- a/gstreamer_core/libs/gst/base/gstbasetransform.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstbasetransform.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,9 +1,9 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
  *                    2005 Wim Taymans <wim@fluendo.com>
  *                    2005 Andy Wingo <wingo@fluendo.com>
  *                    2005 Thomas Vander Stichele <thomas at apestaart dot org>
+ *                    2008 Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -44,7 +44,9 @@
  *    </para></listitem>
  * </itemizedlist>
  *
- * Use Cases:
+ * <refsect2>
+ * <title>Use Cases</title>
+ * <para>
  * <orderedlist>
  * <listitem>
  *   <itemizedlist><title>Passthrough mode</title>
@@ -158,8 +160,12 @@
  *   </itemizedlist>
  * </listitem>
  * </orderedlist>
- *
- * <itemizedlist><title>Sub-class settable flags on GstBaseTransform</title>
+ * </para>
+ * </refsect2>
+ * <refsect2>
+ * <title>Sub-class settable flags on GstBaseTransform</title>
+ * <para>
+ * <itemizedlist>
  * <listitem><para>
  *   <itemizedlist><title>passthrough</title>
  *     <listitem><para>
@@ -188,8 +194,9 @@
  *   </itemizedlist>
  * </para></listitem>
  * </itemizedlist>
- *
-*/
+ * </para>
+ * </refsect2>
+ */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
@@ -245,6 +252,17 @@
   GstActivateMode pad_mode;
 
   gboolean gap_aware;
+
+  /* caps used for allocating buffers */
+  gboolean proxy_alloc;
+  GstCaps *sink_alloc;
+  GstCaps *src_alloc;
+  /* upstream caps and size suggestions */
+  GstCaps *sink_suggest;
+  guint size_suggest;
+  gboolean suggest_pending;
+
+  gboolean reconfigure;
 };
 
 static GstElementClass *parent_class = NULL;
@@ -253,7 +271,7 @@
 static void gst_base_transform_init (GstBaseTransform * trans,
     GstBaseTransformClass * klass);
 static GstFlowReturn gst_base_transform_prepare_output_buffer (GstBaseTransform
-    * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
+    * trans, GstBuffer * input, GstBuffer ** buf);
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
@@ -262,9 +280,10 @@
 GType
 gst_base_transform_get_type (void)
 {
-  static GType base_transform_type = 0;
+  static volatile gsize base_transform_type = 0;
 
-  if (!base_transform_type) {
+  if (g_once_init_enter (&base_transform_type)) {
+    GType _type;
     static const GTypeInfo base_transform_info = {
       sizeof (GstBaseTransformClass),
       NULL,
@@ -277,8 +296,9 @@
       (GInstanceInitFunc) gst_base_transform_init,
     };
 
-    base_transform_type = g_type_register_static (GST_TYPE_ELEMENT,
+    _type = g_type_register_static (GST_TYPE_ELEMENT,
         "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT);
+    g_once_init_leave (&base_transform_type, _type);
   }
   return base_transform_type;
 }
@@ -309,6 +329,7 @@
 static GstFlowReturn gst_base_transform_chain (GstPad * pad,
     GstBuffer * buffer);
 static GstCaps *gst_base_transform_getcaps (GstPad * pad);
+static gboolean gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps);
 static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
 static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,
     guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
@@ -322,6 +343,7 @@
 
   trans = GST_BASE_TRANSFORM (object);
 
+  gst_caps_replace (&trans->priv->sink_suggest, NULL);
   g_mutex_free (trans->transform_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -337,6 +359,8 @@
   GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0,
       "basetransform element");
 
+  GST_DEBUG ("gst_base_transform_class_init");
+
   g_type_class_add_private (klass, sizeof (GstBaseTransformPrivate));
 
   parent_class = g_type_class_peek_parent (klass);
@@ -348,7 +372,7 @@
 
   g_object_class_install_property (gobject_class, PROP_QOS,
       g_param_spec_boolean ("qos", "QoS", "Handle Quality-of-Service events",
-          DEFAULT_PROP_QOS, G_PARAM_READWRITE));
+          DEFAULT_PROP_QOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_transform_finalize);
 
@@ -373,6 +397,8 @@
   trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
   gst_pad_set_getcaps_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
+  gst_pad_set_acceptcaps_function (trans->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps));
   gst_pad_set_setcaps_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
   gst_pad_set_event_function (trans->sinkpad,
@@ -391,8 +417,8 @@
   trans->srcpad = gst_pad_new_from_template (pad_template, "src");
   gst_pad_set_getcaps_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
-  gst_pad_set_setcaps_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
+  gst_pad_set_acceptcaps_function (trans->srcpad,
+      GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps));
   gst_pad_set_event_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
   gst_pad_set_checkgetrange_function (trans->srcpad,
@@ -404,7 +430,6 @@
   gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
 
   trans->transform_lock = g_mutex_new ();
-  trans->delay_configure = FALSE;
   trans->pending_configure = FALSE;
   trans->priv->qos_enabled = DEFAULT_PROP_QOS;
   trans->cache_caps1 = NULL;
@@ -418,8 +443,10 @@
     GST_DEBUG_OBJECT (trans, "setting in_place TRUE");
     trans->always_in_place = TRUE;
 
-    if (bclass->transform_ip == NULL)
+    if (bclass->transform_ip == NULL) {
+      GST_DEBUG_OBJECT (trans, "setting passthrough TRUE");
       trans->passthrough = TRUE;
+    }
   }
 }
 
@@ -435,6 +462,9 @@
   GstCaps *ret;
   GstBaseTransformClass *klass;
 
+  if (caps == NULL)
+    return NULL;
+
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   /* if there is a custom transform function, use this */
@@ -455,32 +485,36 @@
       temp = gst_caps_make_writable (temp);
       gst_caps_append (ret, temp);
     } else {
+      gint n = gst_caps_get_size (caps);
       /* we send caps with just one structure to the transform
        * function as this is easier for the element */
-      for (i = 0; i < gst_caps_get_size (caps); i++) {
+      for (i = 0; i < n; i++) {
         GstCaps *nth;
 
         nth = gst_caps_copy_nth (caps, i);
-        GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
+        GST_LOG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
         temp = klass->transform_caps (trans, direction, nth);
         gst_caps_unref (nth);
-        GST_DEBUG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);
+        GST_LOG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);
 
         temp = gst_caps_make_writable (temp);
-        /* FIXME: here we need to only append those structures, that are not yet
-         * in there
-         * gst_caps_append (ret, temp);
-         */
+
+        /* here we need to only append those structures, that are not yet
+         * in there, we use the merge function for this */
         gst_caps_merge (ret, temp);
+
+        GST_LOG_OBJECT (trans, "  merged[%d]: %" GST_PTR_FORMAT, i, ret);
       }
-      GST_DEBUG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
-      /* now simplify caps
-         gst_caps_do_simplify (ret);
-         GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret));
+      GST_LOG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
+      /* FIXME: we can't do much simplification here because we don't really want to
+       * change the caps order
+       gst_caps_do_simplify (ret);
+       GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret));
        */
     }
   } else {
-    /* else use the identity transform */
+    GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps);
+    /* no transform function, use the identity transform */
     ret = gst_caps_ref (caps);
   }
 
@@ -490,6 +524,15 @@
   return ret;
 }
 
+/* transform a buffer of @size with @caps on the pad with @direction to
+ * the size of a buffer with @othercaps and store the result in @othersize
+ *
+ * We have two ways of doing this:
+ *  1) use a custom transform size function, this is for complicated custom
+ *     cases with no fixed unit_size.
+ *  2) use the unit_size functions where there is a relationship between the
+ *     caps and the size of a buffer.
+ */
 static gboolean
 gst_base_transform_transform_size (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps,
@@ -505,24 +548,33 @@
       GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",
       size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");
 
-  /* if there is a custom transform function, use this */
   if (klass->transform_size) {
+    /* if there is a custom transform function, use this */
     ret = klass->transform_size (trans, direction, caps, size, othercaps,
         othersize);
   } else {
+    /* there is no transform_size function, we have to use the unit_size
+     * functions. This method assumes there is a fixed unit_size associated with
+     * each caps. We provide the same amount of units on both sides. */
     if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize))
       goto no_in_size;
 
     GST_DEBUG_OBJECT (trans, "input size %d, input unit size %d", size,
         inunitsize);
 
+    /* input size must be a multiple of the unit_size of the input caps */
     if (inunitsize == 0 || (size % inunitsize != 0))
       goto no_multiple;
 
+    /* get the amount of units */
     units = size / inunitsize;
+
+    /* now get the unit size of the output */
     if (!gst_base_transform_get_unit_size (trans, othercaps, &outunitsize))
       goto no_out_size;
 
+    /* the output size is the unit_size times the amount of units on the
+     * input */
     *othersize = units * outunitsize;
     GST_DEBUG_OBJECT (trans, "transformed size to %d", *othersize);
 
@@ -553,6 +605,15 @@
   }
 }
 
+/* get the caps that can be handled by @pad. We perform:
+ *
+ *  - take the caps of peer of otherpad,
+ *  - filter against the padtemplate of otherpad, 
+ *  - calculate all transforms of remaining caps
+ *  - filter against template of @pad
+ *
+ * If there is no peer, we simply return the caps of the padtemplate of pad.
+ */
 static GstCaps *
 gst_base_transform_getcaps (GstPad * pad)
 {
@@ -578,6 +639,7 @@
     temp = gst_caps_intersect (caps, templ);
     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
     gst_caps_unref (caps);
+
     /* then see what we can transform this to */
     caps = gst_base_transform_transform_caps (trans,
         GST_PAD_DIRECTION (otherpad), temp);
@@ -595,7 +657,7 @@
     /* this is what we can do */
     caps = temp;
   } else {
-    /* no peer, our padtemplate is enough then */
+    /* no peer or the peer can do anything, our padtemplate is enough then */
     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
   }
 
@@ -618,10 +680,17 @@
 
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
+  GST_DEBUG_OBJECT (trans, "in caps:  %" GST_PTR_FORMAT, in);
+  GST_DEBUG_OBJECT (trans, "out caps: %" GST_PTR_FORMAT, out);
+
   /* clear the cache */
   gst_caps_replace (&trans->cache_caps1, NULL);
   gst_caps_replace (&trans->cache_caps2, NULL);
 
+  /* figure out same caps state */
+  trans->have_same_caps = gst_caps_is_equal (in, out);
+  GST_DEBUG_OBJECT (trans, "have_same_caps: %d", trans->have_same_caps);
+
   /* If we've a transform_ip method and same input/output caps, set in_place
    * by default. If for some reason the sub-class prefers using a transform
    * function, it can clear the in place flag in the set_caps */
@@ -644,33 +713,90 @@
   return ret;
 }
 
-/* called when new caps arrive on the sink or source pad */
+/* check if caps @in on @pad can be transformed to @out on the other pad.
+ * We don't have a vmethod to test this yet so we have to do a somewhat less
+ * efficient check for this.
+ */
 static gboolean
-gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
+gst_base_transform_can_transform (GstBaseTransform * trans, GstPad * pad,
+    GstCaps * in, GstCaps * out)
 {
-  GstBaseTransform *trans;
+  GstCaps *othercaps;
+
+  /* convert the in caps to all possible out caps */
+  othercaps =
+      gst_base_transform_transform_caps (trans, GST_PAD_DIRECTION (pad), in);
+
+  /* check if transform is empty */
+  if (!othercaps || gst_caps_is_empty (othercaps))
+    goto no_transform;
+
+  /* check if the out caps is a subset of the othercaps */
+  if (!gst_caps_is_subset (out, othercaps))
+    goto no_subset;
+
+  if (othercaps)
+    gst_caps_unref (othercaps);
+
+  GST_DEBUG_OBJECT (trans, "from %" GST_PTR_FORMAT, in);
+  GST_DEBUG_OBJECT (trans, "to   %" GST_PTR_FORMAT, out);
+
+  return TRUE;
+
+  /* ERRORS */
+no_transform:
+  {
+    GST_DEBUG_OBJECT (trans,
+        "transform returned useless %" GST_PTR_FORMAT, othercaps);
+    if (othercaps)
+      gst_caps_unref (othercaps);
+    return FALSE;
+  }
+no_subset:
+  {
+    GST_DEBUG_OBJECT (trans, "no subset");
+    if (othercaps)
+      gst_caps_unref (othercaps);
+    return FALSE;
+  }
+}
+
+/* given a fixed @caps on @pad, create the best possible caps for the
+ * other pad.
+ * @caps must be fixed when calling this function.
+ *
+ * This function calls the transform caps vmethod of the basetransform to figure
+ * out the possible target formats. It then tries to select the best format from
+ * this list by:
+ *
+ * - attempt passthrough if the target caps is a superset of the input caps
+ * - fixating by using peer caps
+ * - fixating with transform fixate function
+ * - fixating with pad fixate functions.
+ *
+ * this function returns a caps that can be transformed into and is accepted by
+ * the peer element.
+ */
+static GstCaps *
+gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
+    GstCaps * caps)
+{
   GstBaseTransformClass *klass;
   GstPad *otherpad, *otherpeer;
-  GstCaps *othercaps = NULL;
-  gboolean ret = TRUE;
+  GstCaps *othercaps;
   gboolean peer_checked = FALSE;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  /* caps must be fixed here, this is a programming error if it's not */
+  g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
+
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
   otherpeer = gst_pad_get_peer (otherpad);
 
-  /* if we get called recursively, we bail out now to avoid an
-   * infinite loop. */
-  if (GST_PAD_IS_IN_SETCAPS (otherpad))
-    goto done;
-
-  /* caps must be fixed here */
-  if (!gst_caps_is_fixed (caps))
-    goto unfixed_caps;
-
-  /* see how we can transform the input caps. */
+  /* see how we can transform the input caps. We need to do this even for
+   * passthrough because it might be possible that this element cannot support
+   * passthrough at all. */
   othercaps = gst_base_transform_transform_caps (trans,
       GST_PAD_DIRECTION (pad), caps);
 
@@ -681,6 +807,9 @@
     const GstCaps *templ_caps;
 
     templ_caps = gst_pad_get_pad_template_caps (otherpad);
+    GST_DEBUG_OBJECT (trans,
+        "intersecting against padtemplate %" GST_PTR_FORMAT, templ_caps);
+
     intersect = gst_caps_intersect (othercaps, templ_caps);
 
     gst_caps_unref (othercaps);
@@ -693,6 +822,8 @@
 
   /* if the othercaps are not fixed, we need to fixate them, first attempt
    * is by attempting passthrough if the othercaps are a superset of caps. */
+  /* FIXME. maybe the caps is not fixed because it has multiple structures of
+   * fixed caps */
   if (!gst_caps_is_fixed (othercaps)) {
     GstCaps *temp;
 
@@ -704,22 +835,28 @@
     temp = gst_caps_intersect (othercaps, caps);
     GST_DEBUG_OBJECT (trans, "intersect returned %" GST_PTR_FORMAT, temp);
     if (temp) {
-      if (!gst_caps_is_empty (temp) && otherpeer) {
+      if (!gst_caps_is_empty (temp)) {
         GST_DEBUG_OBJECT (trans, "try passthrough with %" GST_PTR_FORMAT, caps);
-        /* try passthrough. we know it's fixed, because caps is fixed */
-        if (gst_pad_accept_caps (otherpeer, caps)) {
-          GST_DEBUG_OBJECT (trans, "peer accepted %" GST_PTR_FORMAT, caps);
-          /* peer accepted unmodified caps, we free the original non-fixed
-           * caps and work with the passthrough caps */
+        if (otherpeer) {
+          /* try passthrough. we know it's fixed, because caps is fixed */
+          if (gst_pad_accept_caps (otherpeer, caps)) {
+            GST_DEBUG_OBJECT (trans, "peer accepted %" GST_PTR_FORMAT, caps);
+            /* peer accepted unmodified caps, we free the original non-fixed
+             * caps and work with the passthrough caps */
+            gst_caps_unref (othercaps);
+            othercaps = gst_caps_ref (caps);
+            /* mark that we checked othercaps with the peer, this
+             * makes sure we don't call accept_caps again with these same
+             * caps */
+            peer_checked = TRUE;
+          } else {
+            GST_DEBUG_OBJECT (trans,
+                "peer did not accept %" GST_PTR_FORMAT, caps);
+          }
+        } else {
+          GST_DEBUG_OBJECT (trans, "no peer, doing passthrough");
           gst_caps_unref (othercaps);
           othercaps = gst_caps_ref (caps);
-          /* mark that we checked othercaps with the peer, this
-           * makes sure we don't call accept_caps again with these same
-           * caps */
-          peer_checked = TRUE;
-        } else {
-          GST_DEBUG_OBJECT (trans,
-              "peer did not accept %" GST_PTR_FORMAT, caps);
         }
       }
       gst_caps_unref (temp);
@@ -784,6 +921,18 @@
       gst_pad_fixate_caps (otherpad, othercaps);
     }
     GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
+  } else {
+    /* else caps are fixed but the subclass may want to add fields */
+    if (klass->fixate_caps) {
+      othercaps = gst_caps_make_writable (othercaps);
+
+      GST_DEBUG_OBJECT (trans, "doing fixate %" GST_PTR_FORMAT
+          " using caps %" GST_PTR_FORMAT
+          " on pad %s:%s using fixate_caps vmethod", othercaps, caps,
+          GST_DEBUG_PAD_NAME (otherpad));
+
+      klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
+    }
   }
 
   /* caps should be fixed now, if not we have to fail. */
@@ -798,34 +947,185 @@
   GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT
       ", and got final caps %" GST_PTR_FORMAT, caps, othercaps);
 
-  trans->have_same_caps = gst_caps_is_equal (caps, othercaps);
-  GST_DEBUG_OBJECT (trans, "have_same_caps: %d", trans->have_same_caps);
+  if (otherpeer)
+    gst_object_unref (otherpeer);
+
+  return othercaps;
+
+  /* ERRORS */
+no_transform:
+  {
+    GST_DEBUG_OBJECT (trans,
+        "transform returned useless  %" GST_PTR_FORMAT, othercaps);
+    goto error_cleanup;
+  }
+no_transform_possible:
+  {
+    GST_DEBUG_OBJECT (trans,
+        "transform could not transform %" GST_PTR_FORMAT
+        " in anything we support", caps);
+    goto error_cleanup;
+  }
+could_not_fixate:
+  {
+    GST_DEBUG_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
+    goto error_cleanup;
+  }
+peer_no_accept:
+  {
+    GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT
+        " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
+    goto error_cleanup;
+  }
+error_cleanup:
+  {
+    if (otherpeer)
+      gst_object_unref (otherpeer);
+    if (othercaps)
+      gst_caps_unref (othercaps);
+    return NULL;
+  }
+}
 
-  /* see if we have to configure the element now */
-  if (!trans->delay_configure) {
-    GstCaps *incaps, *outcaps;
+static gboolean
+gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps)
+{
+  GstBaseTransform *trans;
+#if 0
+  GstPad *otherpad;
+  GstCaps *othercaps = NULL;
+#endif
+  gboolean ret = TRUE;
+
+  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+
+#if 0
+  otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
+
+  /* we need fixed caps for the check, fall back to the default implementation
+   * if we don't */
+  if (!gst_caps_is_fixed (caps))
+#endif
+  {
+    GstCaps *allowed, *intersect;
+
+    GST_DEBUG_OBJECT (pad, "non fixed accept caps %" GST_PTR_FORMAT, caps);
+
+    /* get all the formats we can handle on this pad */
+    allowed = gst_pad_get_caps (pad);
+    if (!allowed)
+      goto no_transform_possible;
+
+    /* intersect with the requested format */
+    intersect = gst_caps_intersect (allowed, caps);
+
+    GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect);
+
+    /* we can accept if the intersection is not empty  */
+    ret = !gst_caps_is_empty (intersect);
+    gst_caps_unref (intersect);
+    gst_caps_unref (allowed);
+
+    if (!ret)
+      goto no_transform_possible;
+  }
+#if 0
+  else {
+    GST_DEBUG_OBJECT (pad, "accept caps %" GST_PTR_FORMAT, caps);
 
-    /* make sure in and out caps are correct */
-    if (pad == trans->sinkpad) {
-      incaps = caps;
-      outcaps = othercaps;
-    } else {
-      incaps = othercaps;
-      outcaps = caps;
-    }
-    /* call configure now */
-    if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
-      goto failed_configure;
+    /* find best possible caps for the other pad as a way to see if we can
+     * transform this caps. */
+    othercaps = gst_base_transform_find_transform (trans, pad, caps);
+    if (!othercaps || gst_caps_is_empty (othercaps))
+      goto no_transform_possible;
+
+    GST_DEBUG_OBJECT (pad, "we can transform to %" GST_PTR_FORMAT, othercaps);
+  }
+#endif
+
+done:
+#if 0
+  /* We know it's always NULL since we never use it */
+  if (othercaps)
+    gst_caps_unref (othercaps);
+#endif
+  gst_object_unref (trans);
+
+  return ret;
+
+  /* ERRORS */
+no_transform_possible:
+  {
+    GST_WARNING_OBJECT (trans,
+        "transform could not transform %" GST_PTR_FORMAT
+        " in anything we support", caps);
+    ret = FALSE;
+    goto done;
+  }
+}
+
+/* called when new caps arrive on the sink or source pad,
+ * We try to find the best caps for the other side using our _find_transform()
+ * function. If there are caps, we configure the transform for this new
+ * transformation.
+ *
+ * FIXME, this function is currently commutative but this should not really be
+ * because we never set caps starting from the srcpad.
+ */
+static gboolean
+gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstBaseTransform *trans;
+  GstPad *otherpad, *otherpeer;
+  GstCaps *othercaps = NULL;
+  gboolean ret = TRUE;
+  GstCaps *incaps, *outcaps;
+
+  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+
+  otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
+  otherpeer = gst_pad_get_peer (otherpad);
+
+  /* if we get called recursively, we bail out now to avoid an
+   * infinite loop. */
+  if (GST_PAD_IS_IN_SETCAPS (otherpad))
+    goto done;
+
+  GST_DEBUG_OBJECT (pad, "have new caps %" GST_PTR_FORMAT, caps);
+
+  /* find best possible caps for the other pad */
+  othercaps = gst_base_transform_find_transform (trans, pad, caps);
+  if (!othercaps || gst_caps_is_empty (othercaps))
+    goto no_transform_possible;
+
+  /* configure the element now */
+  /* make sure in and out caps are correct */
+  if (pad == trans->sinkpad) {
+    incaps = caps;
+    outcaps = othercaps;
   } else {
-    /* set pending configure, the configure will happen later with the
-     * caps we set on the pads above. */
-    trans->pending_configure = TRUE;
+    incaps = othercaps;
+    outcaps = caps;
   }
 
+#if 0
+  /* if we have the same caps, we can optimize and reuse the input caps */
+  if (gst_caps_is_equal (incaps, outcaps)) {
+    GST_INFO_OBJECT (trans, "reuse caps");
+    gst_caps_unref (outcaps);
+    outcaps = gst_caps_ref (incaps);
+  }
+#endif
+
+  /* call configure now */
+  if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
+    goto failed_configure;
+
   /* we know this will work, we implement the setcaps */
   gst_pad_set_caps (otherpad, othercaps);
 
   if (pad == trans->srcpad && trans->priv->pad_mode == GST_ACTIVATE_PULL) {
+    /* FIXME hm? */
     ret &= gst_pad_set_caps (otherpeer, othercaps);
     if (!ret) {
       GST_INFO_OBJECT (trans, "otherpeer setcaps(%" GST_PTR_FORMAT ") failed",
@@ -846,43 +1146,17 @@
   return ret;
 
   /* ERRORS */
-unfixed_caps:
-  {
-    GST_DEBUG_OBJECT (trans, "caps are not fixed  %" GST_PTR_FORMAT, caps);
-    ret = FALSE;
-    goto done;
-  }
-no_transform:
-  {
-    GST_DEBUG_OBJECT (trans,
-        "transform returned useless  %" GST_PTR_FORMAT, othercaps);
-    ret = FALSE;
-    goto done;
-  }
 no_transform_possible:
   {
-    GST_DEBUG_OBJECT (trans,
+    GST_WARNING_OBJECT (trans,
         "transform could not transform %" GST_PTR_FORMAT
         " in anything we support", caps);
     ret = FALSE;
     goto done;
   }
-could_not_fixate:
-  {
-    GST_ERROR_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
-    ret = FALSE;
-    goto done;
-  }
-peer_no_accept:
-  {
-    GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT
-        " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
-    ret = FALSE;
-    goto done;
-  }
 failed_configure:
   {
-    GST_DEBUG_OBJECT (trans, "FAILED to configure caps %" GST_PTR_FORMAT
+    GST_WARNING_OBJECT (trans, "FAILED to configure caps %" GST_PTR_FORMAT
         " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
     ret = FALSE;
     goto done;
@@ -891,7 +1165,7 @@
 
 /* Allocate a buffer using gst_pad_alloc_buffer
  *
- * This function does not do renegotiation on the source pad
+ * This function can do renegotiation on the source pad
  *
  * The output buffer is always writable. outbuf can be equal to
  * inbuf, the caller should be prepared for this and perform 
@@ -899,108 +1173,243 @@
  */
 static GstFlowReturn
 gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
-    GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf)
+    GstBuffer * in_buf, GstBuffer ** out_buf)
 {
   GstBaseTransformClass *bclass;
+  GstBaseTransformPrivate *priv;
   GstFlowReturn ret = GST_FLOW_OK;
-  gboolean copy_inbuf = FALSE;
+  guint outsize, newsize, expsize;
+  gboolean discard;
+  GstCaps *incaps, *oldcaps, *newcaps;
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  /* we cannot reconfigure the element yet as we are still processing
-   * the old buffer. We will therefore delay the reconfiguration of the
-   * element until we have processed this last buffer. */
-  trans->delay_configure = TRUE;
+  priv = trans->priv;
+
+  *out_buf = NULL;
+
+  /* figure out how to allocate a buffer based on the current configuration */
+  if (trans->passthrough) {
+    GST_DEBUG_OBJECT (trans, "doing passthrough alloc");
+    /* passthrough, we don't really need to call pad alloc but we still need to
+     * in order to get upstream negotiation. The output size is the same as the
+     * input size. */
+    outsize = GST_BUFFER_SIZE (in_buf);
+    /* we always alloc and discard here */
+    discard = TRUE;
+  } else {
+    gboolean want_in_place = (bclass->transform_ip != NULL)
+        && trans->always_in_place;
 
-  /* out_caps is the caps of the src pad gathered through the GST_PAD_CAPS 
-     macro. If a set_caps occurs during this function this caps will become
-     invalid. We want to keep them during preparation of the output buffer. */
-  if (out_caps)
-    gst_caps_ref (out_caps);
+    if (want_in_place) {
+      GST_DEBUG_OBJECT (trans, "doing inplace alloc");
+      /* we alloc a buffer of the same size as the input */
+      outsize = GST_BUFFER_SIZE (in_buf);
+      /* only discard it when the input was not writable, otherwise, we reuse
+       * the input buffer. */
+      discard = gst_buffer_is_writable (in_buf);
+      GST_DEBUG_OBJECT (trans, "discard: %d", discard);
+    } else {
+      GST_DEBUG_OBJECT (trans, "getting output size for copy transform");
+      /* copy transform, figure out the output size */
+      if (!gst_base_transform_transform_size (trans,
+              GST_PAD_SINK, GST_PAD_CAPS (trans->sinkpad),
+              GST_BUFFER_SIZE (in_buf), GST_PAD_CAPS (trans->srcpad),
+              &outsize)) {
+        goto unknown_size;
+      }
+      /* never discard this buffer, we need it for storing the output */
+      discard = FALSE;
+    }
+  }
 
-  /* see if the subclass wants to alloc a buffer */
+  oldcaps = GST_PAD_CAPS (trans->srcpad);
+
   if (bclass->prepare_output_buffer) {
+    GST_DEBUG_OBJECT (trans,
+        "calling prepare buffer with caps %" GST_PTR_FORMAT, oldcaps);
     ret =
-        bclass->prepare_output_buffer (trans, in_buf, out_size, out_caps,
+        bclass->prepare_output_buffer (trans, in_buf, outsize, oldcaps,
         out_buf);
-    if (ret != GST_FLOW_OK)
-      goto done;
 
-    /* decrease refcount again if vmethod returned refcounted in_buf. This
+    /* get a new ref to the srcpad caps, the prepare_output_buffer function can
+     * update the pad caps if it wants */
+    oldcaps = GST_PAD_CAPS (trans->srcpad);
+
+    /* FIXME 0.11:
+     * decrease refcount again if vmethod returned refcounted in_buf. This
      * is because we need to make sure that the buffer is writable for the
      * in_place transform. The docs of the vmethod say that you should return
      * a reffed inbuf, which is exactly what we don't want :), oh well.. */
     if (in_buf == *out_buf)
       gst_buffer_unref (in_buf);
+
+    /* never discard the buffer from the prepare_buffer method */
+    if (*out_buf != NULL)
+      discard = FALSE;
+  }
+
+  if (ret != GST_FLOW_OK)
+    goto alloc_failed;
+
+  if (*out_buf == NULL) {
+    GST_DEBUG_OBJECT (trans, "doing alloc with caps %" GST_PTR_FORMAT, oldcaps);
+
+    ret = gst_pad_alloc_buffer (trans->srcpad,
+        GST_BUFFER_OFFSET (in_buf), outsize, oldcaps, out_buf);
+    if (ret != GST_FLOW_OK)
+      goto alloc_failed;
   }
 
-  /* See if we want to prepare the buffer for in place output */
-  if (*out_buf == NULL && GST_BUFFER_SIZE (in_buf) == out_size
-      && bclass->transform_ip) {
-    if (gst_buffer_is_writable (in_buf)) {
-      if (trans->have_same_caps) {
-        /* Input buffer is already writable and caps are the same, return input as
-         * output buffer. We don't take an additional ref since that would make the
-         * output buffer not writable anymore. Caller should be prepared to deal
-         * with proper refcounting of input/output buffers. */
-        *out_buf = in_buf;
-        GST_LOG_OBJECT (trans, "reuse input buffer");
+  /* must always have a buffer by now */
+  if (*out_buf == NULL)
+    goto no_buffer;
+
+  /* check if we got different caps on this new output buffer */
+  newcaps = GST_BUFFER_CAPS (*out_buf);
+  newsize = GST_BUFFER_SIZE (*out_buf);
+  if (!gst_caps_is_equal (newcaps, oldcaps)) {
+    GstCaps *othercaps;
+    gboolean can_convert;
+
+    GST_DEBUG_OBJECT (trans, "received new caps %" GST_PTR_FORMAT, newcaps);
+
+    incaps = GST_PAD_CAPS (trans->sinkpad);
+
+    /* it's possible that the buffer we got is of the wrong size, get the
+     * expected size here, we will check the size if we are going to use the
+     * buffer later on. */
+    gst_base_transform_transform_size (trans,
+        GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
+
+    /* check if we can convert the current incaps to the new target caps */
+    can_convert =
+        gst_base_transform_can_transform (trans, trans->sinkpad, incaps,
+        newcaps);
+
+    if (can_convert) {
+      GST_DEBUG_OBJECT (trans, "reconfigure transform for current buffer");
+      /* caps not empty, try to renegotiate to the new format */
+      if (!gst_base_transform_configure_caps (trans, incaps, newcaps)) {
+        /* not sure we need to fail hard here, we can simply continue our
+         * conversion with what we negotiated before */
+        goto failed_configure;
+      }
+      /* new format configure, and use the new output buffer */
+      gst_pad_set_caps (trans->srcpad, newcaps);
+      discard = FALSE;
+      /* if we got a buffer of the wrong size, discard it now and make sure we
+       * allocate a propertly sized buffer later. */
+      if (newsize != expsize) {
+        if (in_buf != *out_buf)
+          gst_buffer_unref (*out_buf);
+        *out_buf = NULL;
+      }
+      outsize = expsize;
+    } else {
+      GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
+
+      /* we cannot convert the current buffer but we might be able to suggest a
+       * new format upstream, try to find what the best format is. */
+      othercaps =
+          gst_base_transform_find_transform (trans, trans->srcpad, newcaps);
+
+      if (!othercaps) {
+        GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
+        /* we received caps that we cannot transform. Upstream is behaving badly
+         * because it should have checked if we could handle these caps. We can
+         * simply ignore these caps and produce a buffer with our original caps. */
       } else {
-        /* Writable buffer, but need to change caps => subbuffer */
-        *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf));
-        gst_caps_replace (&GST_BUFFER_CAPS (*out_buf), out_caps);
-        GST_LOG_OBJECT (trans, "created sub-buffer of input buffer");
+        guint size_suggest;
+
+        GST_DEBUG_OBJECT (trans, "getting size of suggestion");
+
+        /* not a subset, we have a new upstream suggestion, remember it and
+         * allocate a default buffer. First we try to convert the size */
+        if (gst_base_transform_transform_size (trans,
+                GST_PAD_SRC, newcaps, expsize, othercaps, &size_suggest)) {
+
+          /* ok, remember the suggestions now */
+          GST_DEBUG_OBJECT (trans,
+              "storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
+              size_suggest, othercaps);
+
+          GST_OBJECT_LOCK (trans->sinkpad);
+          if (priv->sink_suggest)
+            gst_caps_unref (priv->sink_suggest);
+          priv->sink_suggest = gst_caps_ref (othercaps);
+          priv->size_suggest = size_suggest;
+          trans->priv->suggest_pending = TRUE;
+          GST_OBJECT_UNLOCK (trans->sinkpad);
+        }
+        gst_caps_unref (othercaps);
       }
-      /* we are done now */
-      goto done;
-    } else {
-      /* Make a writable buffer below and copy the data */
-      copy_inbuf = TRUE;
-      GST_LOG_OBJECT (trans, "need to copy input buffer to new output buffer");
+      if (in_buf != *out_buf)
+        gst_buffer_unref (*out_buf);
+      *out_buf = NULL;
     }
   }
 
   if (*out_buf == NULL) {
-    /* Sub-class didn't already provide a buffer for us. Make one */
-    ret = gst_pad_alloc_buffer (trans->srcpad,
-        GST_BUFFER_OFFSET (in_buf), out_size, out_caps, out_buf);
-    if (ret != GST_FLOW_OK || *out_buf == NULL)
-      goto done;
-
-    /* allocated buffer could be of different caps than what we requested */
-    if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {
-      /* FIXME, it is possible we can reconfigure the transform with new caps at this
-       * point but for now we just create a buffer ourselves */
+    if (!discard) {
+      GST_DEBUG_OBJECT (trans, "make default output buffer of size %d",
+          outsize);
+      /* no valid buffer yet, make one */
+      *out_buf = gst_buffer_new_and_alloc (outsize);
+      gst_buffer_copy_metadata (*out_buf, in_buf,
+          GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
+    } else {
+      GST_DEBUG_OBJECT (trans, "reuse input buffer");
+      *out_buf = in_buf;
+    }
+  } else {
+    if (trans->passthrough && in_buf != *out_buf) {
+      /* we are asked to perform a passthrough transform but the input and
+       * output buffers are different. We have to discard the output buffer and
+       * reuse the input buffer. */
+      GST_DEBUG_OBJECT (trans, "passthrough but different buffers");
+      discard = TRUE;
+    }
+    if (discard) {
+      GST_DEBUG_OBJECT (trans, "discard buffer, reuse input buffer");
       gst_buffer_unref (*out_buf);
-      *out_buf = gst_buffer_new_and_alloc (out_size);
-      gst_buffer_set_caps (*out_buf, out_caps);
+      *out_buf = in_buf;
+    } else {
+      GST_DEBUG_OBJECT (trans, "using allocated buffer");
+      gst_buffer_copy_metadata (*out_buf, in_buf,
+          GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
     }
   }
-
-  /* If the output buffer metadata is modifiable, copy timestamps and
-   * buffer flags */
-  if (*out_buf != in_buf && gst_buffer_is_metadata_writable (*out_buf)) {
-
-    if (copy_inbuf && gst_buffer_is_writable (*out_buf))
-      memcpy (GST_BUFFER_DATA (*out_buf), GST_BUFFER_DATA (in_buf), out_size);
-
-    gst_buffer_copy_metadata (*out_buf, in_buf,
-        GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
+  gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (trans->srcpad));
 
-    /* Unset the GAP flag if the element is _not_ GAP aware. Otherwise
-     * it might create an output buffer that does not contain neutral data
-     * but still has the GAP flag on it! */
-    if (!trans->priv->gap_aware)
-      GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
-  }
-
-done:
-  if (out_caps)
-    gst_caps_unref (out_caps);
-
-  trans->delay_configure = FALSE;
+  /* clear the GAP flag when the subclass does not understand it */
+  if (!trans->priv->gap_aware)
+    GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
 
   return ret;
+
+  /* ERRORS */
+alloc_failed:
+  {
+    GST_WARNING_OBJECT (trans, "pad-alloc failed: %s", gst_flow_get_name (ret));
+    return ret;
+  }
+no_buffer:
+  {
+    GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
+        ("Sub-class failed to provide an output buffer"), (NULL));
+    return GST_FLOW_ERROR;
+  }
+unknown_size:
+  {
+    GST_ERROR_OBJECT (trans, "unknown output size");
+    return GST_FLOW_ERROR;
+  }
+failed_configure:
+  {
+    GST_WARNING_OBJECT (trans, "failed to configure caps");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
 }
 
 /* Given @caps calcultate the size of one unit.
@@ -1038,9 +1447,15 @@
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   if (bclass->get_unit_size) {
     res = bclass->get_unit_size (trans, caps, size);
-//    GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
-//        ") has unit size %d, result %s", caps, *size, res ? "TRUE" : "FALSE");
-
+    if(res)
+        {
+        GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
+                ") has unit size %d, result TRUE", caps, *size);
+        }else{ 
+  
+        GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
+                ") has unit size %d, result FALSE", caps, *size);
+        }
     if (res) {
       /* and cache the values */
       if (trans->cache_caps1 == NULL) {
@@ -1070,167 +1485,185 @@
     GstCaps * caps, GstBuffer ** buf)
 {
   GstBaseTransform *trans;
+  GstBaseTransformPrivate *priv;
   GstFlowReturn res;
-  guint new_size;
-  gboolean issinkcaps = TRUE;
+  gboolean proxy, suggest, same_caps;
+  GstCaps *sink_suggest;
+  guint size_suggest;
 
   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  priv = trans->priv;
 
-  /* we cannot run this when we are transforming data and as such doing 
-   * another negotiation in the transform method. */
-  g_mutex_lock (trans->transform_lock);
+  GST_DEBUG_OBJECT (pad, "alloc with caps %" GST_PTR_FORMAT ", size %u", caps,
+      size);
+
+  /* if the code below does not come up with a better buffer, we will return _OK
+   * and an empty buffer. This will trigger the core to allocate a buffer with
+   * given input size and caps. */
+  *buf = NULL;
+  res = GST_FLOW_OK;
+
+  /* we remember our previous alloc request to quickly see if we can proxy or
+   * not. We skip this check if we have a pending suggestion. */
+  GST_OBJECT_LOCK (pad);
+  same_caps = !priv->suggest_pending && caps &&
+      gst_caps_is_equal (priv->sink_alloc, caps);
+  GST_OBJECT_UNLOCK (pad);
+
+  if (same_caps) {
+    /* we have seen this before, see below if we need to proxy */
+    GST_DEBUG_OBJECT (trans, "have old caps");
+    sink_suggest = caps;
+    size_suggest = size;
+    suggest = FALSE;
+  } else {
+    GstCaps *temp;
+    const GstCaps *templ;
+    gboolean empty;
+
+    GST_DEBUG_OBJECT (trans, "new format %" GST_PTR_FORMAT, caps);
 
-  *buf = NULL;
+    /* if we have a suggestion, pretend we got these as input */
+    GST_OBJECT_LOCK (pad);
+    if ((priv->sink_suggest && !gst_caps_is_equal (caps, priv->sink_suggest))) {
+      sink_suggest = gst_caps_ref (priv->sink_suggest);
+      size_suggest = priv->size_suggest;
+      GST_DEBUG_OBJECT (trans, "have suggestion %" GST_PTR_FORMAT,
+          sink_suggest);
+      /* suggest is TRUE when we have a custom suggestion pending that we need
+       * to unref later. */
+      suggest = TRUE;
+    } else {
+      GST_DEBUG_OBJECT (trans, "using caps %" GST_PTR_FORMAT, caps);
+      sink_suggest = caps;
+      size_suggest = size;
+      suggest = FALSE;
+    }
+    priv->suggest_pending = FALSE;
+    GST_OBJECT_UNLOCK (pad);
+
+    /* check if we actually handle this format on the sinkpad */
+    if (sink_suggest) {
+      templ = gst_pad_get_pad_template_caps (pad);
+      temp = gst_caps_intersect (sink_suggest, templ);
+
+      empty = gst_caps_is_empty (temp);
+      gst_caps_unref (temp);
+
+      if (empty)
+        goto not_supported;
+    }
 
-  GST_DEBUG_OBJECT (trans, "allocating a buffer of size %d ...", size);
-  if (offset == GST_BUFFER_OFFSET_NONE)
-    GST_DEBUG_OBJECT (trans, "... and offset NONE");
-  else
-    GST_DEBUG_OBJECT (trans, "... and offset %" G_GUINT64_FORMAT, offset);
+    /* find the best format for the other side here we decide if we will proxy
+     * the caps or not. */
+    if (sink_suggest == NULL) {
+      /* always proxy when the caps are NULL. When this is a new format, see if
+       * we can proxy it downstream */
+      GST_DEBUG_OBJECT (trans, "null caps, marking for proxy");
+      priv->proxy_alloc = TRUE;
+    } else {
+      GstCaps *othercaps;
+
+      /* we have a new format, see what we need to proxy to */
+      othercaps = gst_base_transform_find_transform (trans, pad, sink_suggest);
+      if (!othercaps || gst_caps_is_empty (othercaps)) {
+        /* no transform possible, we certainly can't proxy */
+        GST_DEBUG_OBJECT (trans, "can't find transform, disable proxy");
+        priv->proxy_alloc = FALSE;
+      } else {
+        /* we transformed into something */
+        if (gst_caps_is_equal (caps, othercaps)) {
+          GST_DEBUG_OBJECT (trans,
+              "best caps same as input, marking for proxy");
+          priv->proxy_alloc = TRUE;
+        } else {
+          GST_DEBUG_OBJECT (trans,
+              "best caps different from input, disable proxy");
+          priv->proxy_alloc = FALSE;
+        }
+      }
+      if (othercaps)
+        gst_caps_unref (othercaps);
+    }
+  }
+  /* remember the new caps */
+  GST_OBJECT_LOCK (pad);
+  gst_caps_replace (&priv->sink_alloc, sink_suggest);
+  GST_OBJECT_UNLOCK (pad);
 
-  /* if have_same_caps was previously set to TRUE we need to double check if it
-   * hasn't changed */
-  if (trans->have_same_caps) {
-    GstCaps *sinkcaps;
+  proxy = priv->proxy_alloc;
+  GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d", proxy);
+
+  /* we only want to proxy if we have no suggestion pending, FIXME */
+  if (proxy && !suggest) {
+    GstCaps *newcaps;
+
+    GST_DEBUG_OBJECT (trans, "proxy buffer-alloc with caps %" GST_PTR_FORMAT
+        ", size %u", caps, size);
+
+    /* we always proxy the input caps, never the suggestion. The reason is that
+     * We don't yet handle the caps of renegotiation in here. FIXME */
+    res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
+    if (res != GST_FLOW_OK)
+      goto alloc_failed;
+
+    /* check if the caps changed */
+    newcaps = GST_BUFFER_CAPS (*buf);
+
+    GST_DEBUG_OBJECT (trans, "got caps %" GST_PTR_FORMAT, newcaps);
 
-    GST_OBJECT_LOCK (trans->sinkpad);
-    sinkcaps = GST_PAD_CAPS (trans->sinkpad);
-    issinkcaps = sinkcaps && (gst_caps_is_equal (sinkcaps, caps));
-    GST_OBJECT_UNLOCK (trans->sinkpad);
+    if (!gst_caps_is_equal (newcaps, caps)) {
+      GST_DEBUG_OBJECT (trans, "caps are new");
+      /* we have new caps, see if we can proxy downstream */
+      if (gst_pad_peer_accept_caps (pad, newcaps)) {
+        /* peer accepts the caps, return a buffer in this format */
+        GST_DEBUG_OBJECT (trans, "peer accepted new caps");
+        /* remember the format */
+        GST_OBJECT_LOCK (pad);
+        gst_caps_replace (&priv->sink_alloc, newcaps);
+        GST_OBJECT_UNLOCK (pad);
+      } else {
+        GST_DEBUG_OBJECT (trans, "peer did not accept new caps");
+        /* peer does not accept the caps, free the buffer we received and
+         * create a buffer of the requested format by the default handler. */
+        gst_buffer_unref (*buf);
+        *buf = NULL;
+      }
+    } else {
+      GST_DEBUG_OBJECT (trans, "received required caps from peer");
+    }
   }
 
-  /* before any buffers are pushed, have_same_caps is TRUE; allocating can trigger
-   * a renegotiation and change that to FALSE */
-
-  /* bilboed: This seems wrong, from all debug logs, have_same_caps is
-   * initialized to FALSE */
-
-  /* checking against trans->have_same_caps is not enough !! It should also
-   *  check to see if the requested caps are equal to the sink caps */
-  if (trans->have_same_caps && issinkcaps) {
-    /* request a buffer with the same caps */
-    GST_DEBUG_OBJECT (trans, "requesting buffer with same caps, size %d", size);
-
-    res =
-        gst_pad_alloc_buffer_and_set_caps (trans->srcpad, offset, size, caps,
-        buf);
-  } else {
-    /* if we are configured, request a buffer with the src caps */
-    GstCaps *srccaps;
-    GstCaps *sinkcaps;
-    gboolean configured;
-
-    /* take lock, peek if the caps are ok */
-    GST_OBJECT_LOCK (trans->sinkpad);
-    sinkcaps = GST_PAD_CAPS (trans->sinkpad);
-    configured = (sinkcaps == NULL || gst_caps_is_equal (sinkcaps, caps));
-    GST_OBJECT_UNLOCK (trans->sinkpad);
-    if (!configured)
-      goto not_configured;
-
-    /* take lock on srcpad to grab the caps, caps can change when pushing a
-     * buffer. */
-    GST_OBJECT_LOCK (trans->srcpad);
-    if ((srccaps = GST_PAD_CAPS (trans->srcpad)))
-      gst_caps_ref (srccaps);
-    GST_OBJECT_UNLOCK (trans->srcpad);
-    if (!srccaps)
-      goto not_configured;
-
-    GST_DEBUG_OBJECT (trans, "calling transform_size");
-    if (!gst_base_transform_transform_size (trans,
-            GST_PAD_DIRECTION (pad), caps, size, srccaps, &new_size)) {
-      gst_caps_unref (srccaps);
-      goto unknown_size;
-    }
-
-    res =
-        gst_pad_alloc_buffer_and_set_caps (trans->srcpad, offset, new_size,
-        srccaps, buf);
-
-    gst_caps_unref (srccaps);
+  if (suggest) {
+    /* there was a custom suggestion, create a buffer of this format and return
+     * it. Note that this format  */
+    *buf = gst_buffer_new_and_alloc (size_suggest);
+    GST_DEBUG_OBJECT (trans,
+        "doing suggestion of size %u, caps %" GST_PTR_FORMAT, size_suggest,
+        sink_suggest);
+    GST_BUFFER_CAPS (*buf) = sink_suggest;
   }
 
-  if (res == GST_FLOW_OK && !trans->have_same_caps) {
-    /* note that we might have had same caps before, but calling the
-       alloc_buffer caused setcaps to switch us out of in_place -- in any case
-       the alloc_buffer served to transmit caps information but we can't use the
-       buffer. fall through and allocate a buffer corresponding to our sink
-       caps, if any */
-    GstCaps *sinkcaps;
-    GstCaps *srccaps;
-
-    GST_OBJECT_LOCK (trans->sinkpad);
-    if ((sinkcaps = GST_PAD_CAPS (trans->sinkpad)))
-      gst_caps_ref (sinkcaps);
-    GST_OBJECT_UNLOCK (trans->sinkpad);
-    if (!sinkcaps)
-      goto not_configured;
-
-    GST_OBJECT_LOCK (trans->srcpad);
-    if ((srccaps = GST_PAD_CAPS (trans->srcpad)))
-      gst_caps_ref (srccaps);
-    GST_OBJECT_UNLOCK (trans->srcpad);
-    if (!srccaps) {
-      gst_caps_unref (sinkcaps);
-      goto not_configured;
-    }
-
-    if (!gst_base_transform_transform_size (trans,
-            GST_PAD_DIRECTION (trans->srcpad), srccaps, GST_BUFFER_SIZE (*buf),
-            sinkcaps, &new_size)) {
-      gst_caps_unref (srccaps);
-      gst_caps_unref (sinkcaps);
-      goto unknown_size;
-    }
-    /* don't need the caps anymore now */
-    gst_caps_unref (srccaps);
-
-    gst_buffer_unref (*buf);
-
-    *buf = gst_buffer_new_and_alloc (new_size);
-    GST_BUFFER_OFFSET (*buf) = offset;
-    /* set caps, gives away the ref */
-    GST_BUFFER_CAPS (*buf) = sinkcaps;
-
-    res = GST_FLOW_OK;
-  }
-
-done:
-  g_mutex_unlock (trans->transform_lock);
   gst_object_unref (trans);
 
   return res;
 
-not_configured:
+  /* ERRORS */
+alloc_failed:
   {
-    /* let the default allocator handle it... */
-    GST_DEBUG_OBJECT (trans, "not configured");
-    gst_buffer_replace (buf, NULL);
-    if (trans->passthrough) {
-      /* ...by calling alloc_buffer without setting caps on the src pad, which
-       * will force negotiation in the chain function. */
-      res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
-    } else {
-      /* ...by letting the default handler create a buffer */
-      res = GST_FLOW_OK;
-    }
-    goto done;
+    GST_DEBUG_OBJECT (trans, "pad alloc failed: %s", gst_flow_get_name (res));
+    if (suggest)
+      gst_caps_unref (sink_suggest);
+    gst_object_unref (trans);
+    return res;
   }
-unknown_size:
+not_supported:
   {
-    /* let the default allocator handle it... */
-    GST_DEBUG_OBJECT (trans, "unknown size");
-    gst_buffer_replace (buf, NULL);
-    if (trans->passthrough) {
-      /* ...by calling alloc_buffer without setting caps on the src pad, which
-       * will force negotiation in the chain function. */
-      res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
-    } else {
-      /* ...by letting the default handler create a buffer */
-      res = GST_FLOW_OK;
-    }
-    goto done;
+    GST_DEBUG_OBJECT (trans, "pad alloc with unsupported caps");
+    if (suggest)
+      gst_caps_unref (sink_suggest);
+    gst_object_unref (trans);
+    return GST_FLOW_NOT_NEGOTIATED;
   }
 }
 
@@ -1252,6 +1685,8 @@
    * something different. */
   if (forward)
     ret = gst_pad_push_event (trans->srcpad, event);
+  else
+    gst_event_unref (event);
 
   gst_object_unref (trans);
 
@@ -1365,24 +1800,45 @@
   return ret;
 }
 
+/* perform a transform on @inbuf and put the result in @outbuf.
+ *
+ * This function is common to the push and pull-based operations.
+ *
+ * This function takes ownership of @inbuf */
 static GstFlowReturn
 gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
     GstBuffer ** outbuf)
 {
   GstBaseTransformClass *bclass;
   GstFlowReturn ret = GST_FLOW_OK;
-  guint out_size;
-  gboolean want_in_place;
+  gboolean want_in_place, reconfigure;
   GstClockTime qostime;
+  GstCaps *incaps;
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
+  if (G_LIKELY ((incaps = GST_BUFFER_CAPS (inbuf)))) {
+    GST_OBJECT_LOCK (trans);
+    reconfigure = trans->priv->reconfigure;
+    trans->priv->reconfigure = FALSE;
+    GST_OBJECT_UNLOCK (trans);
+
+    if (G_UNLIKELY (reconfigure)) {
+      GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
+      /* if we need to reconfigure we pretend a buffer with new caps arrived. This
+       * will reconfigure the transform with the new output format. We can only
+       * do this if the buffer actually has caps. */
+      if (!gst_base_transform_setcaps (trans->sinkpad, incaps))
+        goto not_negotiated;
+    }
+  }
+
   if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
-    GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset %"
+    GST_DEBUG_OBJECT (trans, "handling buffer %p of size %d and offset %"
         G_GUINT64_FORMAT, inbuf, GST_BUFFER_SIZE (inbuf),
         GST_BUFFER_OFFSET (inbuf));
   else
-    GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
+    GST_DEBUG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
         inbuf, GST_BUFFER_SIZE (inbuf));
 
   /* Don't allow buffer handling before negotiation, except in passthrough mode
@@ -1394,7 +1850,7 @@
 
   /* Set discont flag so we can mark the outgoing buffer */
   if (GST_BUFFER_IS_DISCONT (inbuf)) {
-    GST_LOG_OBJECT (trans, "got DISCONT buffer %p", inbuf);
+    GST_DEBUG_OBJECT (trans, "got DISCONT buffer %p", inbuf);
     trans->priv->discont = TRUE;
   }
 
@@ -1402,6 +1858,7 @@
   if (trans->segment.format != GST_FORMAT_TIME)
     goto no_qos;
 
+  /* QOS is done on the running time of the buffer, get it now */
   qostime = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
       GST_BUFFER_TIMESTAMP (inbuf));
 
@@ -1409,6 +1866,8 @@
     gboolean need_skip;
     GstClockTime earliest_time;
 
+    /* lock for getting the QoS parameters that are set (in a different thread)
+     * with the QOS events */
     GST_OBJECT_LOCK (trans);
     earliest_time = trans->priv->earliest_time;
     /* check for QoS, don't perform conversion for buffers
@@ -1428,76 +1887,48 @@
   }
 
 no_qos:
+
+  /* first try to allocate an output buffer based on the currently negotiated
+   * format. While we call pad-alloc we could renegotiate the srcpad format or
+   * have a new suggestion for upstream buffer-alloc. 
+   * In any case, outbuf will contain a buffer suitable for doing the configured
+   * transform after this function. */
+  ret = gst_base_transform_prepare_output_buffer (trans, inbuf, outbuf);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto no_buffer;
+
+  /* now perform the needed transform */
   if (trans->passthrough) {
     /* In passthrough mode, give transform_ip a look at the
      * buffer, without making it writable, or just push the
      * data through */
-    GST_LOG_OBJECT (trans, "element is in passthrough mode");
-
-    if (bclass->transform_ip)
-      ret = bclass->transform_ip (trans, inbuf);
-
-    *outbuf = inbuf;
-
-    goto done;
-  }
-
-  want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;
-  *outbuf = NULL;
-
-  if (want_in_place) {
-    /* If want_in_place is TRUE, we may need to prepare a new output buffer
-     * Sub-classes can implement a prepare_output_buffer function as they
-     * wish. */
-    GST_LOG_OBJECT (trans, "doing inplace transform");
-
-    ret = gst_base_transform_prepare_output_buffer (trans, inbuf,
-        GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad), outbuf);
-    if (G_UNLIKELY (ret != GST_FLOW_OK))
-      goto no_buffer;
-
-    ret = bclass->transform_ip (trans, *outbuf);
-
-  } else {
-    GST_LOG_OBJECT (trans, "doing non-inplace transform");
-
-    /* not transforming inplace, figure out the output size */
-    if (trans->always_in_place) {
-      out_size = GST_BUFFER_SIZE (inbuf);
+    if (bclass->transform_ip) {
+      GST_DEBUG_OBJECT (trans, "doing passthrough transform");
+      ret = bclass->transform_ip (trans, *outbuf);
     } else {
-      if (!gst_base_transform_transform_size (trans,
-              GST_PAD_DIRECTION (trans->sinkpad), GST_PAD_CAPS (trans->sinkpad),
-              GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad),
-              &out_size)) {
-        /* we have an error */
-        goto no_size;
-      }
+      GST_DEBUG_OBJECT (trans, "element is in passthrough");
     }
+  } else {
+    want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;
 
-    /* no in place transform, get buffer, this might renegotiate. */
-    ret = gst_base_transform_prepare_output_buffer (trans, inbuf, out_size,
-        GST_PAD_CAPS (trans->srcpad), outbuf);
-    if (ret != GST_FLOW_OK)
-      goto no_buffer;
+    if (want_in_place) {
+      GST_DEBUG_OBJECT (trans, "doing inplace transform");
 
-    if (bclass->transform)
-      ret = bclass->transform (trans, inbuf, *outbuf);
-    else
-      ret = GST_FLOW_NOT_SUPPORTED;
-  }
+      if (inbuf != *outbuf) {
+        /* different buffers, copy the input to the output first, we then do an
+         * in-place transform on the output buffer. */
+        memcpy (GST_BUFFER_DATA (*outbuf), GST_BUFFER_DATA (inbuf),
+            GST_BUFFER_SIZE (inbuf));
+      }
+      ret = bclass->transform_ip (trans, *outbuf);
+    } else {
+      GST_DEBUG_OBJECT (trans, "doing non-inplace transform");
 
-  /* if we got renegotiated we can configure now */
-  if (trans->pending_configure) {
-    gboolean success;
-
-    success =
-        gst_base_transform_configure_caps (trans,
-        GST_PAD_CAPS (trans->sinkpad), GST_PAD_CAPS (trans->srcpad));
-
-    trans->pending_configure = FALSE;
-
-    if (!success)
-      goto configure_failed;
+      if (bclass->transform)
+        ret = bclass->transform (trans, inbuf, *outbuf);
+      else
+        ret = GST_FLOW_NOT_SUPPORTED;
+    }
   }
 
 skip:
@@ -1505,7 +1936,6 @@
   if (*outbuf != inbuf)
     gst_buffer_unref (inbuf);
 
-done:
   return ret;
 
   /* ERRORS */
@@ -1516,28 +1946,13 @@
         ("not negotiated"), ("not negotiated"));
     return GST_FLOW_NOT_NEGOTIATED;
   }
-no_size:
-  {
-    gst_buffer_unref (inbuf);
-    GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
-        ("subclass did not specify output size"),
-        ("subclass did not specify output size"));
-    return GST_FLOW_ERROR;
-  }
 no_buffer:
   {
     gst_buffer_unref (inbuf);
-    GST_DEBUG_OBJECT (trans, "could not get buffer from pool: %s",
+    GST_WARNING_OBJECT (trans, "could not get buffer from pool: %s",
         gst_flow_get_name (ret));
     return ret;
   }
-configure_failed:
-  {
-    if (*outbuf != inbuf)
-      gst_buffer_unref (inbuf);
-    GST_DEBUG_OBJECT (trans, "could not negotiate");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
 }
 
 static gboolean
@@ -1563,27 +1978,43 @@
     guint length, GstBuffer ** buffer)
 {
   GstBaseTransform *trans;
+  GstBaseTransformClass *klass;
   GstFlowReturn ret;
   GstBuffer *inbuf;
 
   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
 
   ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
-  if (ret == GST_FLOW_OK) {
-    g_mutex_lock (trans->transform_lock);
-    ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
-    g_mutex_unlock (trans->transform_lock);
-  }
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto pull_error;
 
+  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
+  if (klass->before_transform)
+    klass->before_transform (trans, inbuf);
+
+  GST_BASE_TRANSFORM_LOCK (trans);
+  ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
+  GST_BASE_TRANSFORM_UNLOCK (trans);
+
+done:
   gst_object_unref (trans);
 
   return ret;
+
+  /* ERRORS */
+pull_error:
+  {
+    GST_DEBUG_OBJECT (trans, "failed to pull a buffer: %s",
+        gst_flow_get_name (ret));
+    goto done;
+  }
 }
 
 static GstFlowReturn
 gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
 {
   GstBaseTransform *trans;
+  GstBaseTransformClass *klass;
   GstFlowReturn ret;
   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
   GstBuffer *outbuf = NULL;
@@ -1598,10 +2029,14 @@
       last_stop = GST_BUFFER_TIMESTAMP (buffer);
   }
 
+  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
+  if (klass->before_transform)
+    klass->before_transform (trans, buffer);
+
   /* protect transform method and concurrent buffer alloc */
-  g_mutex_lock (trans->transform_lock);
+  GST_BASE_TRANSFORM_LOCK (trans);
   ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
-  g_mutex_unlock (trans->transform_lock);
+  GST_BASE_TRANSFORM_UNLOCK (trans);
 
   /* outbuf can be NULL, this means a dropped buffer, if we have a buffer but
    * GST_BASE_TRANSFORM_FLOW_DROPPED we will not push either. */
@@ -1698,6 +2133,7 @@
     trans->priv->proportion = 1.0;
     trans->priv->earliest_time = -1;
     trans->priv->discont = FALSE;
+    gst_caps_replace (&trans->priv->sink_suggest, NULL);
 
     GST_OBJECT_UNLOCK (trans);
   } else {
@@ -1714,6 +2150,8 @@
     }
     gst_caps_replace (&trans->cache_caps1, NULL);
     gst_caps_replace (&trans->cache_caps2, NULL);
+    gst_caps_replace (&trans->priv->sink_alloc, NULL);
+    gst_caps_replace (&trans->priv->sink_suggest, NULL);
 
     if (trans->priv->pad_mode != GST_ACTIVATE_NONE && bclass->stop)
       result &= bclass->stop (trans);
@@ -1784,7 +2222,7 @@
 {
   GstBaseTransformClass *bclass;
 
-  g_return_if_fail (trans != NULL);
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
@@ -1819,7 +2257,7 @@
 {
   gboolean result;
 
-  g_return_val_if_fail (trans != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
 
   GST_OBJECT_LOCK (trans);
   result = trans->passthrough;
@@ -1838,7 +2276,7 @@
  * to the transform_ip function.
  * <itemizedlist>
  *   <listitem>Always TRUE if no transform function is implemented.</listitem>
- *   <listitem>Always FALSE if ONLY transform_ip function is implemented.</listitem>
+ *   <listitem>Always FALSE if ONLY transform function is implemented.</listitem>
  * </itemizedlist>
  *
  * MT safe.
@@ -1852,7 +2290,7 @@
 {
   GstBaseTransformClass *bclass;
 
-  g_return_if_fail (trans != NULL);
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
@@ -1892,7 +2330,7 @@
 {
   gboolean result;
 
-  g_return_val_if_fail (trans != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
 
   GST_OBJECT_LOCK (trans);
   result = trans->always_in_place;
@@ -1906,13 +2344,16 @@
  * @trans: a #GstBaseTransform
  * @proportion: the proportion
  * @diff: the diff against the clock
- * @timestamp: the timestamp of the buffer generating the QoS
+ * @timestamp: the timestamp of the buffer generating the QoS expressed in
+ * running_time.
  *
- * Set the QoS parameters in the transform.
+ * Set the QoS parameters in the transform. This function is called internally
+ * when a QOS event is received but subclasses can provide custom information
+ * when needed.
+ *
+ * MT safe.
  *
  * Since: 0.10.5
- *
- * MT safe.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1923,7 +2364,7 @@
     gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
 {
 
-  g_return_if_fail (trans != NULL);
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans,
       "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
@@ -1942,9 +2383,9 @@
  *
  * Enable or disable QoS handling in the transform.
  *
- * Since: 0.10.5
+ * MT safe.
  *
- * MT safe.
+ * Since: 0.10.5
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1953,7 +2394,7 @@
 void
 gst_base_transform_set_qos_enabled (GstBaseTransform * trans, gboolean enabled)
 {
-  g_return_if_fail (trans != NULL);
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "enabled: %d", enabled);
 
@@ -1970,9 +2411,9 @@
  *
  * Returns: TRUE if QoS is enabled.
  *
- * Since: 0.10.5
+ * MT safe.
  *
- * MT safe.
+ * Since: 0.10.5
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -1983,7 +2424,7 @@
 {
   gboolean result;
 
-  g_return_val_if_fail (trans != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
 
   GST_OBJECT_LOCK (trans);
   result = trans->priv->qos_enabled;
@@ -1997,15 +2438,16 @@
  * @trans: a #GstBaseTransform
  * @gap_aware: New state
  *
- * If @gap_aware is %FALSE (as it is by default) subclasses will never get
- * output buffers with the %GST_BUFFER_FLAG_GAP flag set.
+ * If @gap_aware is %FALSE (the default), output buffers will have the
+ * %GST_BUFFER_FLAG_GAP flag unset.
  *
- * If set to %TRUE elements must handle output buffers with this flag set
- * correctly, i.e. they can assume that the buffer contains neutral data
- * but must unset the flag if the output is no neutral data.
- * Since: 0.10.16
+ * If set to %TRUE, the element must handle output buffers with this flag set
+ * correctly, i.e. it can assume that the buffer contains neutral data but must
+ * unset the flag if the output is no neutral data.
  *
  * MT safe.
+ *
+ * Since: 0.10.16
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -2014,10 +2456,69 @@
 void
 gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware)
 {
-  g_return_if_fail (trans != NULL);
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
 
   GST_OBJECT_LOCK (trans);
   trans->priv->gap_aware = gap_aware;
   GST_DEBUG_OBJECT (trans, "set gap aware %d", trans->priv->gap_aware);
   GST_OBJECT_UNLOCK (trans);
 }
+
+/**
+ * gst_base_transform_suggest:
+ * @trans: a #GstBaseTransform
+ * @caps: caps to suggest
+ * @size: buffer size to suggest
+ *
+ * Instructs @trans to suggest new @caps upstream. A copy of @caps will be
+ * taken.
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_base_transform_suggest (GstBaseTransform * trans, GstCaps * caps,
+    guint size)
+{
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
+
+  GST_OBJECT_LOCK (trans->sinkpad);
+  if (trans->priv->sink_suggest)
+    gst_caps_unref (trans->priv->sink_suggest);
+  if (caps)
+    caps = gst_caps_copy (caps);
+  trans->priv->sink_suggest = caps;
+  trans->priv->size_suggest = size;
+  trans->priv->suggest_pending = TRUE;
+  GST_DEBUG_OBJECT (trans, "new suggest %" GST_PTR_FORMAT, caps);
+  GST_OBJECT_UNLOCK (trans->sinkpad);
+}
+
+/**
+ * gst_base_transform_reconfigure:
+ * @trans: a #GstBaseTransform
+ *
+ * Instructs @trans to renegotiate a new downstream transform on the next
+ * buffer. This function is typically called after properties on the transform
+ * were set that influence the output format.
+ *
+ * Since: 0.10.21
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_base_transform_reconfigure (GstBaseTransform * trans)
+{
+  g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
+
+  GST_OBJECT_LOCK (trans);
+  GST_DEBUG_OBJECT (trans, "marking reconfigure");
+  trans->priv->reconfigure = TRUE;
+  gst_caps_replace (&trans->priv->sink_alloc, NULL);
+  GST_OBJECT_UNLOCK (trans);
+}
--- a/gstreamer_core/libs/gst/base/gstbasetransform.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstbasetransform.h	Fri Apr 16 15:15:52 2010 +0300
@@ -37,13 +37,13 @@
 /**
  * GST_BASE_TRANSFORM_SINK_NAME:
  *
- * the name of the templates for the sink pad
+ * The name of the templates for the sink pad.
  */
 #define GST_BASE_TRANSFORM_SINK_NAME	"sink"
 /**
  * GST_BASE_TRANSFORM_SRC_NAME:
  *
- * the name of the templates for the source pad
+ * The name of the templates for the source pad.
  */
 #define GST_BASE_TRANSFORM_SRC_NAME	"src"
 
@@ -144,12 +144,12 @@
 
 /**
  * GstBaseTransformClass:
- * @transform_caps: Optional.  given the pad in this direction and the given
+ * @transform_caps: Optional.  Given the pad in this direction and the given
  *                  caps, what caps are allowed on the other pad in this
  *                  element ?
  * @fixate_caps:    Optional. Given the pad in this direction and the given
  *                  caps, fixate the caps on the other pad.
- * @transform_size: Optional. given the size of a buffer in the given direction
+ * @transform_size: Optional. Given the size of a buffer in the given direction
  *                  with the given caps, calculate the size in bytes of a buffer
  *                  on the other pad with the given other caps.
  *                  The default implementation uses get_unit_size and keeps
@@ -182,6 +182,10 @@
  *                         analysis can return a subbuffer or even just
  *                         increment the reference to the input buffer (if in
  *                         passthrough mode)
+ * @before_transform: Optional. Since 0.10.22
+ *                    This method is called right before the base class will
+ *                    start processing. Dynamic properties or other delayed
+ *                    configuration could be performed in this method.
  *
  * Subclasses can override any of the available virtual methods or not, as
  * needed. At minimum either @transform or @transform_ip need to be overridden.
@@ -231,8 +235,10 @@
   /* src event */
   gboolean      (*src_event)      (GstBaseTransform *trans, GstEvent *event);
 
+  void          (*before_transform)  (GstBaseTransform *trans, GstBuffer *buffer);
+
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE - 1];
+  gpointer       _gst_reserved[GST_PADDING_LARGE - 2];
 };
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -291,7 +297,18 @@
 
 void            gst_base_transform_set_gap_aware    (GstBaseTransform *trans,
                                                      gboolean gap_aware);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
 
+
+void		gst_base_transform_suggest          (GstBaseTransform *trans,
+	                                             GstCaps *caps, guint size);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void		gst_base_transform_reconfigure      (GstBaseTransform *trans);
 G_END_DECLS
 
 #endif /* __GST_BASE_TRANSFORM_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/libs/gst/base/gstbitreader.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,440 @@
+/* GStreamer
+ *
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstbitreader.h"
+
+#include <string.h>
+
+/**
+ * SECTION:gstbitreader
+ * @short_description: Reads any number of bits from a memory buffer
+ *
+ * #GstBitReader provides a bit reader that can read any number of bits
+ * from a memory buffer. It provides functions for reading any number of bits
+ * into 8, 16, 32 and 64 bit variables.
+ */
+
+/**
+ * gst_bit_reader_new:
+ * @data: Data from which the #GstBitReader should read
+ * @size: Size of @data in bytes
+ *
+ * Create a new #GstBitReader instance, which will read from @data.
+ *
+ * Returns: a new #GstBitReader instance
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBitReader *
+gst_bit_reader_new (const guint8 * data, guint size)
+{
+  GstBitReader *ret = g_slice_new0 (GstBitReader);
+
+  ret->data = data;
+  ret->size = size;
+
+  return ret;
+}
+
+/**
+ * gst_bit_reader_new_from_buffer:
+ * @buffer: Buffer from which the #GstBitReader should read
+ *
+ * Create a new #GstBitReader instance, which will read from the
+ * #GstBuffer @buffer.
+ *
+ * Returns: a new #GstBitReader instance
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstBitReader *
+gst_bit_reader_new_from_buffer (const GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+  return gst_bit_reader_new (GST_BUFFER_DATA (buffer),
+      GST_BUFFER_SIZE (buffer));
+}
+
+/**
+ * gst_bit_reader_free:
+ * @reader: a #GstBitReader instance
+ *
+ * Frees a #GstBitReader instance, which was previously allocated by
+ * gst_bit_reader_new() or gst_bit_reader_new_from_buffer().
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_bit_reader_free (GstBitReader * reader)
+{
+  g_return_if_fail (reader != NULL);
+
+  g_slice_free (GstBitReader, reader);
+}
+
+/**
+ * gst_bit_reader_init:
+ * @reader: a #GstBitReader instance
+ * @data: Data from which the #GstBitReader should read
+ * @size: Size of @data in bytes
+ *
+ * Initializes a #GstBitReader instance to read from @data. This function
+ * can be called on already initialized instances.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_bit_reader_init (GstBitReader * reader, const guint8 * data, guint size)
+{
+  g_return_if_fail (reader != NULL);
+
+  reader->data = data;
+  reader->size = size;
+  reader->byte = reader->bit = 0;
+}
+
+/**
+ * gst_bit_reader_init_from_buffer:
+ * @reader: a #GstBitReader instance
+ * @buffer: Buffer from which the #GstBitReader should read
+ *
+ * Initializes a #GstBitReader instance to read from @buffer. This function
+ * can be called on already initialized instances.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_bit_reader_init_from_buffer (GstBitReader * reader,
+    const GstBuffer * buffer)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+
+  gst_bit_reader_init (reader, GST_BUFFER_DATA (buffer),
+      GST_BUFFER_SIZE (buffer));
+}
+
+/**
+ * gst_bit_reader_set_pos:
+ * @reader: a #GstBitReader instance
+ * @pos: The new position in bits
+ *
+ * Sets the new position of a #GstBitReader instance to @pos in bits.
+ *
+ * Returns: %TRUE if the position could be set successfully, %FALSE
+ * otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_bit_reader_set_pos (GstBitReader * reader, guint pos)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+
+  if (pos > reader->size * 8)
+    return FALSE;
+
+  reader->byte = pos / 8;
+  reader->bit = pos % 8;
+
+  return TRUE;
+}
+
+/**
+ * gst_bit_reader_get_pos:
+ * @reader: a #GstBitReader instance
+ *
+ * Returns the current position of a #GstBitReader instance in bits.
+ *
+ * Returns: The current position of @reader in bits.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_bit_reader_get_pos (const GstBitReader * reader)
+{
+  g_return_val_if_fail (reader != NULL, 0);
+
+  return reader->byte * 8 + reader->bit;
+}
+
+/**
+ * gst_bit_reader_get_remaining:
+ * @reader: a #GstBitReader instance
+ *
+ * Returns the remaining number of bits of a #GstBitReader instance.
+ *
+ * Returns: The remaining number of bits of @reader instance.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_bit_reader_get_remaining (const GstBitReader * reader)
+{
+  g_return_val_if_fail (reader != NULL, 0);
+
+  return reader->size * 8 - (reader->byte * 8 + reader->bit);
+}
+
+/**
+ * gst_bit_reader_skip:
+ * @reader: a #GstBitReader instance
+ * @nbits: the number of bits to skip
+ *
+ * Skips @nbits bits of the #GstBitReader instance.
+ *
+ * Returns: %TRUE if @nbits bits could be skipped, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_bit_reader_skip (GstBitReader * reader, guint nbits)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+
+  if (gst_bit_reader_get_remaining (reader) < nbits)
+    return FALSE;
+
+  reader->bit += nbits;
+  reader->byte += reader->bit / 8;
+  reader->bit = reader->bit % 8;
+
+  return TRUE;
+}
+
+/**
+ * gst_bit_reader_skip_to_byte:
+ * @reader: a #GstBitReader instance
+ *
+ * Skips until the next byte.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_bit_reader_skip_to_byte (GstBitReader * reader)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+
+  if (reader->byte > reader->size)
+    return FALSE;
+
+  if (reader->bit) {
+    reader->bit = 0;
+    reader->byte++;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_bit_reader_get_bits_uint8:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint8 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_get_bits_uint16:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint16 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_get_bits_uint32:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint32 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_get_bits_uint64:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint64 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_peek_bits_uint8:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint8 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_peek_bits_uint16:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint16 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_peek_bits_uint32:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint32 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_bit_reader_peek_bits_uint64:
+ * @reader: a #GstBitReader instance
+ * @val: Pointer to a #guint64 to store the result
+ * @nbits: number of bits to read
+ *
+ * Read @nbits bits into @val but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+#define GST_BIT_READER_READ_BITS(bits) \
+__declspec(dllexport) gboolean \
+gst_bit_reader_get_bits_uint##bits (GstBitReader *reader, guint##bits *val, guint nbits) \
+{ \
+  guint##bits ret = 0; \
+  \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  g_return_val_if_fail (nbits <= bits, FALSE); \
+  \
+  if (reader->byte * 8 + reader->bit + nbits > reader->size * 8) \
+    return FALSE; \
+  \
+  while (nbits > 0) { \
+    guint toread = MIN (nbits, 8 - reader->bit); \
+    \
+    ret <<= toread; \
+    ret |= (reader->data[reader->byte] & (0xff >> reader->bit)) >> (8 - toread - reader->bit); \
+    \
+    reader->bit += toread; \
+    if (reader->bit >= 8) { \
+      reader->byte++; \
+      reader->bit = 0; \
+    } \
+    nbits -= toread; \
+  } \
+  \
+  *val = ret; \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_bit_reader_peek_bits_uint##bits (const GstBitReader *reader, guint##bits *val, guint nbits) \
+{ \
+  GstBitReader tmp; \
+  \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  tmp = *reader; \
+  return gst_bit_reader_get_bits_uint##bits (&tmp, val, nbits); \
+}
+
+GST_BIT_READER_READ_BITS (8);
+GST_BIT_READER_READ_BITS (16);
+GST_BIT_READER_READ_BITS (32);
+GST_BIT_READER_READ_BITS (64);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/libs/gst/base/gstbitreader.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,169 @@
+/* GStreamer
+ *
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ *
+ * 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_BIT_READER_H__
+#define __GST_BIT_READER_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstBitReader:
+ * @data: Data from which the bit reader will read
+ * @size: Size of @data in bytes
+ * @byte: Current byte position
+ * @bit: Bit position in the current byte
+ *
+ * A bit reader instance.
+ */
+typedef struct {
+  const guint8 *data;
+  guint size;
+
+  guint byte;  /* Byte position */
+  guint bit;   /* Bit position in the current byte */
+} GstBitReader;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstBitReader * gst_bit_reader_new (const guint8 *data, guint size);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstBitReader * gst_bit_reader_new_from_buffer (const GstBuffer *buffer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_bit_reader_free (GstBitReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void gst_bit_reader_init (GstBitReader *reader, const guint8 *data, guint size);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_bit_reader_init_from_buffer (GstBitReader *reader, const GstBuffer *buffer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_bit_reader_set_pos (GstBitReader *reader, guint pos);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+guint gst_bit_reader_get_pos (const GstBitReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint gst_bit_reader_get_remaining (const GstBitReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_bit_reader_skip (GstBitReader *reader, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_skip_to_byte (GstBitReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_get_bits_uint8 (GstBitReader *reader, guint8 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_get_bits_uint16 (GstBitReader *reader, guint16 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_get_bits_uint32 (GstBitReader *reader, guint32 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_get_bits_uint64 (GstBitReader *reader, guint64 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader, guint8 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits);
+
+/**
+ * GST_BIT_READER_INIT:
+ * @data: Data from which the #GstBitReader should read
+ * @size: Size of @data in bytes
+ *
+ * A #GstBitReader must be initialized with this macro, before it can be
+ * used. This macro can used be to initialize a variable, but it cannot
+ * be assigned to a variable. In that case you have to use
+ * gst_bit_reader_init().
+ *
+ * Since: 0.10.22
+ */
+#define GST_BIT_READER_INIT(data, size) {data, size, 0, 0}
+
+/**
+ * GST_BIT_READER_INIT_FROM_BUFFER:
+ * @buffer: Buffer from which the #GstBitReader should read
+ *
+ * A #GstBitReader must be initialized with this macro, before it can be
+ * used. This macro can used be to initialize a variable, but it cannot
+ * be assigned to a variable. In that case you have to use
+ * gst_bit_reader_init().
+ *
+ * Since: 0.10.22
+ */
+#define GST_BIT_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0, 0}
+
+G_END_DECLS
+
+#endif /* __GST_BIT_READER_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/libs/gst/base/gstbytereader.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,1711 @@
+/* GStreamer
+ *
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstbytereader.h"
+
+#include <string.h>
+
+/**
+ * SECTION:gstbytereader
+ * @short_description: Reads different integer, string and floating point
+ *     types from a memory buffer
+ *
+ * #GstByteReader provides a byte reader that can read different integer and
+ * floating point types from a memory buffer. It provides functions for reading
+ * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits
+ * and functions for reading little/big endian floating points numbers of
+ * 32 and 64 bits. It also provides functions to read NUL-terminated strings
+ * in various character encodings.
+ */
+
+/**
+ * gst_byte_reader_new:
+ * @data: Data from which the #GstByteReader should read
+ * @size: Size of @data in bytes
+ *
+ * Create a new #GstByteReader instance, which will read from @data.
+ *
+ * Returns: a new #GstByteReader instance
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstByteReader *
+gst_byte_reader_new (const guint8 * data, guint size)
+{
+  GstByteReader *ret = g_slice_new0 (GstByteReader);
+
+  ret->data = data;
+  ret->size = size;
+
+  return ret;
+}
+
+/**
+ * gst_byte_reader_new_from_buffer:
+ * @buffer: Buffer from which the #GstByteReader should read
+ *
+ * Create a new #GstByteReader instance, which will read from the
+ * #GstBuffer @buffer.
+ *
+ * Returns: a new #GstByteReader instance
+ *
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstByteReader *
+gst_byte_reader_new_from_buffer (const GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+  return gst_byte_reader_new (GST_BUFFER_DATA (buffer),
+      GST_BUFFER_SIZE (buffer));
+}
+
+/**
+ * gst_byte_reader_free:
+ * @reader: a #GstByteReader instance
+ *
+ * Frees a #GstByteReader instance, which was previously allocated by
+ * gst_byte_reader_new() or gst_byte_reader_new_from_buffer().
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_byte_reader_free (GstByteReader * reader)
+{
+  g_return_if_fail (reader != NULL);
+
+  g_slice_free (GstByteReader, reader);
+}
+
+/**
+ * gst_byte_reader_init:
+ * @reader: a #GstByteReader instance
+ * @data: Data from which the #GstByteReader should read
+ * @size: Size of @data in bytes
+ *
+ * Initializes a #GstByteReader instance to read from @data. This function
+ * can be called on already initialized instances.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size)
+{
+  g_return_if_fail (reader != NULL);
+
+  reader->data = data;
+  reader->size = size;
+  reader->byte = 0;
+}
+
+/**
+ * gst_byte_reader_init_from_buffer:
+ * @reader: a #GstByteReader instance
+ * @buffer: Buffer from which the #GstByteReader should read
+ *
+ * Initializes a #GstByteReader instance to read from @buffer. This function
+ * can be called on already initialized instances.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+void
+gst_byte_reader_init_from_buffer (GstByteReader * reader,
+    const GstBuffer * buffer)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+
+  gst_byte_reader_init (reader, GST_BUFFER_DATA (buffer),
+      GST_BUFFER_SIZE (buffer));
+}
+
+/**
+ * gst_byte_reader_set_pos:
+ * @reader: a #GstByteReader instance
+ * @pos: The new position in bytes
+ *
+ * Sets the new position of a #GstByteReader instance to @pos in bytes.
+ *
+ * Returns: %TRUE if the position could be set successfully, %FALSE
+ * otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_set_pos (GstByteReader * reader, guint pos)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+
+  if (pos > reader->size)
+    return FALSE;
+
+  reader->byte = pos;
+
+  return TRUE;
+}
+
+/**
+ * gst_byte_reader_get_pos:
+ * @reader: a #GstByteReader instance
+ *
+ * Returns the current position of a #GstByteReader instance in bytes.
+ *
+ * Returns: The current position of @reader in bytes.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_byte_reader_get_pos (const GstByteReader * reader)
+{
+  g_return_val_if_fail (reader != NULL, 0);
+
+  return reader->byte;
+}
+
+/**
+ * gst_byte_reader_get_remaining:
+ * @reader: a #GstByteReader instance
+ *
+ * Returns the remaining number of bytes of a #GstByteReader instance.
+ *
+ * Returns: The remaining number of bytes of @reader instance.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_byte_reader_get_remaining (const GstByteReader * reader)
+{
+  g_return_val_if_fail (reader != NULL, 0);
+
+  return reader->size - reader->byte;
+}
+
+/**
+ * gst_byte_reader_skip:
+ * @reader: a #GstByteReader instance
+ * @nbytes: the number of bytes to skip
+ *
+ * Skips @nbytes bytes of the #GstByteReader instance.
+ *
+ * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_skip (GstByteReader * reader, guint nbytes)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < nbytes)
+    return FALSE;
+
+  reader->byte += nbytes;
+
+  return TRUE;
+}
+
+/**
+ * gst_byte_reader_get_uint8:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint8 to store the result
+ *
+ * Read an unsigned 8 bit integer into @val and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int8:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint8 to store the result
+ *
+ * Read a signed 8 bit integer into @val and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint8:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint8 to store the result
+ *
+ * Read a signed 8 bit integer into @val but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int8:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint8 to store the result
+ *
+ * Read a signed 8 bit integer into @val but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint16_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint16 to store the result
+ *
+ * Read an unsigned 16 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int16_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint16 to store the result
+ *
+ * Read a signed 16 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint16_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint16 to store the result
+ *
+ * Read a signed 16 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int16_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint16 to store the result
+ *
+ * Read a signed 16 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint16_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint16 to store the result
+ *
+ * Read an unsigned 16 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int16_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint16 to store the result
+ *
+ * Read a signed 16 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint16_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint16 to store the result
+ *
+ * Read a signed 16 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int16_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint16 to store the result
+ *
+ * Read a signed 16 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint24_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read an unsigned 24 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int24_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 24 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint24_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read a signed 24 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int24_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 24 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint24_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read an unsigned 24 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int24_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 24 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint24_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read a signed 24 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int24_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 24 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+
+/**
+ * gst_byte_reader_get_uint32_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read an unsigned 32 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int32_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 32 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint32_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read a signed 32 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int32_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 32 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint32_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read an unsigned 32 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int32_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 32 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint32_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint32 to store the result
+ *
+ * Read a signed 32 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int32_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint32 to store the result
+ *
+ * Read a signed 32 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint64_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint64 to store the result
+ *
+ * Read an unsigned 64 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int64_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint64 to store the result
+ *
+ * Read a signed 64 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint64_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint64 to store the result
+ *
+ * Read a signed 64 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int64_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint64 to store the result
+ *
+ * Read a signed 64 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_uint64_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint64 to store the result
+ *
+ * Read an unsigned 64 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_int64_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint64 to store the result
+ *
+ * Read a signed 64 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_uint64_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #guint64 to store the result
+ *
+ * Read a signed 64 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_int64_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gint64 to store the result
+ *
+ * Read a signed 64 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+#define GST_BYTE_READER_READ_INTS(bits) \
+__declspec(dllexport) gboolean \
+gst_byte_reader_get_uint##bits##_le (GstByteReader *reader, guint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \
+  reader->byte += bits / 8; \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_byte_reader_get_uint##bits##_be (GstByteReader *reader, guint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \
+  reader->byte += bits / 8; \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_byte_reader_get_int##bits##_le (GstByteReader *reader, gint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \
+  reader->byte += bits / 8; \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_byte_reader_get_int##bits##_be (GstByteReader *reader, gint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \
+  reader->byte += bits / 8; \
+  return TRUE; \
+} \
+__declspec(dllexport) gboolean \
+gst_byte_reader_peek_uint##bits##_le (GstByteReader *reader, guint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_byte_reader_peek_uint##bits##_be (GstByteReader *reader, guint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_byte_reader_peek_int##bits##_le (GstByteReader *reader, gint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_LE (&reader->data[reader->byte]); \
+  return TRUE; \
+} \
+\
+__declspec(dllexport) gboolean \
+gst_byte_reader_peek_int##bits##_be (GstByteReader *reader, gint##bits *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_UINT##bits##_BE (&reader->data[reader->byte]); \
+  return TRUE; \
+}
+
+
+GST_BYTE_READER_READ_INTS (16);
+GST_BYTE_READER_READ_INTS (32);
+GST_BYTE_READER_READ_INTS (64);
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_get_uint8 (GstByteReader * reader, guint8 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (reader->byte >= reader->size)
+    return FALSE;
+
+  *val = GST_READ_UINT8 (&reader->data[reader->byte]);
+  reader->byte++;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_get_int8 (GstByteReader * reader, gint8 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (reader->byte >= reader->size)
+    return FALSE;
+
+  *val = GST_READ_UINT8 (&reader->data[reader->byte]);
+  reader->byte++;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_peek_uint8 (GstByteReader * reader, guint8 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (reader->byte >= reader->size)
+    return FALSE;
+
+  *val = GST_READ_UINT8 (&reader->data[reader->byte]);
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_peek_int8 (GstByteReader * reader, gint8 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (reader->byte >= reader->size)
+    return FALSE;
+
+  *val = GST_READ_UINT8 (&reader->data[reader->byte]);
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_get_uint24_le (GstByteReader * reader, guint32 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  *val = GST_READ_UINT24_LE (&reader->data[reader->byte]);
+  reader->byte += 3;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_get_uint24_be (GstByteReader * reader, guint32 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  *val = GST_READ_UINT24_BE (&reader->data[reader->byte]);
+  reader->byte += 3;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_get_int24_le (GstByteReader * reader, gint32 * val)
+{
+  guint32 ret;
+
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  ret = GST_READ_UINT24_LE (&reader->data[reader->byte]);
+  if (ret & 0x00800000)
+    ret |= 0xff000000;
+
+  reader->byte += 3;
+
+  *val = ret;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_get_int24_be (GstByteReader * reader, gint32 * val)
+{
+  guint32 ret;
+
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  ret = GST_READ_UINT24_BE (&reader->data[reader->byte]);
+  if (ret & 0x00800000)
+    ret |= 0xff000000;
+
+  reader->byte += 3;
+
+  *val = ret;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_peek_uint24_le (GstByteReader * reader, guint32 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  *val = GST_READ_UINT24_LE (&reader->data[reader->byte]);
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_peek_uint24_be (GstByteReader * reader, guint32 * val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  *val = GST_READ_UINT24_BE (&reader->data[reader->byte]);
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_peek_int24_le (GstByteReader * reader, gint32 * val)
+{
+  guint32 ret;
+
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  ret = GST_READ_UINT24_LE (&reader->data[reader->byte]);
+  if (ret & 0x00800000)
+    ret |= 0xff000000;
+
+  *val = ret;
+  return TRUE;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+gboolean
+gst_byte_reader_peek_int24_be (GstByteReader * reader, gint32 * val)
+{
+  guint32 ret;
+
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < 3)
+    return FALSE;
+
+  ret = GST_READ_UINT24_BE (&reader->data[reader->byte]);
+  if (ret & 0x00800000)
+    ret |= 0xff000000;
+
+  *val = ret;
+  return TRUE;
+}
+
+/**
+ * gst_byte_reader_get_float32_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gfloat to store the result
+ *
+ * Read a 32 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_float32_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gfloat to store the result
+ *
+ * Read a 32 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_float32_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gfloat to store the result
+ *
+ * Read a 32 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_float32_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gfloat to store the result
+ *
+ * Read a 32 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_float64_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gdouble to store the result
+ *
+ * Read a 64 bit little endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_float64_le:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gdouble to store the result
+ *
+ * Read a 64 bit little endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_get_float64_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gdouble to store the result
+ *
+ * Read a 64 bit big endian integer into @val
+ * and update the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+/**
+ * gst_byte_reader_peek_float64_be:
+ * @reader: a #GstByteReader instance
+ * @val: Pointer to a #gdouble to store the result
+ *
+ * Read a 64 bit big endian integer into @val
+ * but keep the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+
+#define GST_BYTE_READER_READ_FLOATS(bits, type, TYPE) \
+    __declspec(dllexport) gboolean \
+gst_byte_reader_get_float##bits##_le (GstByteReader *reader, g##type *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_##TYPE##_LE (&reader->data[reader->byte]); \
+  reader->byte += bits / 8; \
+  return TRUE; \
+} \
+__declspec(dllexport) gboolean \
+gst_byte_reader_get_float##bits##_be (GstByteReader *reader, g##type *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_##TYPE##_BE (&reader->data[reader->byte]); \
+  reader->byte += bits / 8; \
+  return TRUE; \
+} \
+__declspec(dllexport) gboolean \
+gst_byte_reader_peek_float##bits##_le (GstByteReader *reader, g##type *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_##TYPE##_LE (&reader->data[reader->byte]); \
+  return TRUE; \
+} \
+__declspec(dllexport) gboolean \
+gst_byte_reader_peek_float##bits##_be (GstByteReader *reader, g##type *val) \
+{ \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  \
+  if (gst_byte_reader_get_remaining (reader) < bits / 8) \
+    return FALSE; \
+  \
+  *val = GST_READ_##TYPE##_BE (&reader->data[reader->byte]); \
+  return TRUE; \
+}
+
+GST_BYTE_READER_READ_FLOATS (32, float, FLOAT);
+GST_BYTE_READER_READ_FLOATS (64, double, DOUBLE);
+
+/**
+ * gst_byte_reader_get_data:
+ * @reader: a #GstByteReader instance
+ * @size: Size in bytes
+ * @val: Pointer to a #guint8 to store the result
+ *
+ * Returns a constant pointer to the current data
+ * position if at least @size bytes are left and
+ * updates the current position.
+ *
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_get_data (GstByteReader * reader, guint size,
+    const guint8 ** val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < size)
+    return FALSE;
+
+  *val = reader->data + reader->byte;
+  reader->byte += size;
+  return TRUE;
+}
+
+/**
+ * gst_byte_reader_peek_data:
+ * @reader: a #GstByteReader instance
+ * @size: Size in bytes
+ * @val: Pointer to a #guint8 to store the result
+ *
+ * Returns a constant pointer to the current data
+ * position if at least @size bytes are left and
+ * keeps the current position.
+ *
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ * 
+ * Since: 0.10.22
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_peek_data (GstByteReader * reader, guint size,
+    const guint8 ** val)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (gst_byte_reader_get_remaining (reader) < size)
+    return FALSE;
+
+  *val = reader->data + reader->byte;
+  return TRUE;
+}
+
+/**
+ * gst_byte_reader_dup_data:
+ * @reader: a #GstByteReader instance
+ * @size: Size in bytes
+ * @val: Pointer to a #guint8 to store the result
+ *
+ * Returns a newly-allocated copy of the current data
+ * position if at least @size bytes are left and
+ * updates the current position.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
+{
+  const guint8 *cval = NULL;
+
+  if (!gst_byte_reader_get_data (reader, size, &cval))
+    return FALSE;
+
+  *val = g_memdup (cval, size);
+  return TRUE;
+}
+
+/**
+ * gst_byte_reader_masked_scan_uint32:
+ * @reader: a #GstByteReader
+ * @mask: mask to apply to data before matching against @pattern
+ * @pattern: pattern to match (after mask is applied)
+ * @offset: offset from which to start scanning, relative to the current
+ *     position
+ * @size: number of bytes to scan from offset
+ *
+ * Scan for pattern @pattern with applied mask @mask in the byte reader data,
+ * starting from offset @offset relative to the current position.
+ *
+ * The bytes in @pattern and @mask are interpreted left-to-right, regardless
+ * of endianness.  All four bytes of the pattern must be present in the
+ * byte reader data for it to match, even if the first or last bytes are masked
+ * out.
+ *
+ * It is an error to call this function without making sure that there is
+ * enough data (offset+size bytes) in the byte reader.
+ *
+ * Returns: offset of the first match, or -1 if no match was found.
+ *
+ * Example:
+ * <programlisting>
+ * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
+ *
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
+ * // -> returns 0
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
+ * // -> returns -1
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
+ * // -> returns 1
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
+ * // -> returns -1
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
+ * // -> returns 0
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
+ * // -> returns 2
+ * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
+ * // -> returns -1
+ * </programlisting>
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+guint
+gst_byte_reader_masked_scan_uint32 (GstByteReader * reader, guint32 mask,
+    guint32 pattern, guint offset, guint size)
+{
+  const guint8 *data;
+  guint32 state;
+  guint i;
+
+  g_return_val_if_fail (size > 0, -1);
+  g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
+      -1);
+
+  /* we can't find the pattern with less than 4 bytes */
+  if (G_UNLIKELY (size < 4))
+    return -1;
+
+  data = reader->data + reader->byte + offset;
+
+  /* set the state to something that does not match */
+  state = ~pattern;
+
+  /* now find data */
+  for (i = 0; i < size; i++) {
+    /* throw away one byte and move in the next byte */
+    state = ((state << 8) | data[i]);
+    if (G_UNLIKELY ((state & mask) == pattern)) {
+      /* we have a match but we need to have skipped at
+       * least 4 bytes to fill the state. */
+      if (G_LIKELY (i >= 3))
+        return offset + i - 3;
+    }
+  }
+
+  /* nothing found */
+  return -1;
+}
+
+#define GST_BYTE_READER_SCAN_STRING(bits) \
+static guint \
+gst_byte_reader_scan_string_utf##bits (GstByteReader * reader) \
+{ \
+  guint len, off, max_len; \
+  \
+  max_len = (reader->size - reader->byte) / sizeof (guint##bits); \
+  \
+  /* need at least a single NUL terminator */ \
+  if (max_len < 1) \
+    return 0; \
+  \
+  len = 0; \
+  off = reader->byte; \
+  /* endianness does not matter if we are looking for a NUL terminator */ \
+  while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \
+    ++len; \
+    off += sizeof (guint##bits); \
+    /* have we reached the end without finding a NUL terminator? */ \
+    if (len == max_len) \
+      return 0; \
+  } \
+  /* return size in bytes including the NUL terminator (hence the +1) */ \
+  return (len + 1) * sizeof (guint##bits); \
+}
+
+#define GST_READ_UINT8_LE GST_READ_UINT8
+GST_BYTE_READER_SCAN_STRING (8);
+#undef GST_READ_UINT8_LE
+GST_BYTE_READER_SCAN_STRING (16);
+GST_BYTE_READER_SCAN_STRING (32);
+
+#define GST_BYTE_READER_SKIP_STRING(bits) \
+__declspec(dllexport) gboolean \
+gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \
+{ \
+  guint size; /* size in bytes including the terminator */ \
+  \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  \
+  size = gst_byte_reader_scan_string_utf##bits (reader); \
+  reader->byte += size; \
+  return (size > 0); \
+}
+
+/**
+ * gst_byte_reader_skip_string:
+ * @reader: a #GstByteReader instance
+ *
+ * Skips a NUL-terminated string in the #GstByteReader instance, advancing
+ * the current position to the byte after the string. This will work for
+ * any NUL-terminated string with a character width of 8 bits, so ASCII,
+ * UTF-8, ISO-8859-N etc.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+/**
+ * gst_byte_reader_skip_string_utf8:
+ * @reader: a #GstByteReader instance
+ *
+ * Skips a NUL-terminated string in the #GstByteReader instance, advancing
+ * the current position to the byte after the string. This will work for
+ * any NUL-terminated string with a character width of 8 bits, so ASCII,
+ * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+GST_BYTE_READER_SKIP_STRING (8);
+
+/**
+ * gst_byte_reader_skip_string_utf16:
+ * @reader: a #GstByteReader instance
+ *
+ * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance,
+ * advancing the current position to the byte after the string.
+ *
+ * No input checking for valid UTF-16 is done.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+GST_BYTE_READER_SKIP_STRING (16);
+
+/**
+ * gst_byte_reader_skip_string_utf32:
+ * @reader: a #GstByteReader instance
+ *
+ * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance,
+ * advancing the current position to the byte after the string.
+ *
+ * No input checking for valid UTF-32 is done.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+GST_BYTE_READER_SKIP_STRING (32);
+
+/**
+ * gst_byte_reader_peek_string:
+ * @reader: a #GstByteReader instance
+ * @str: Pointer to a #gchar to store the result
+ *
+ * Returns a constant pointer to the current data position if there is
+ * a NUL-terminated string in the data (this could be just a NUL terminator).
+ * The current position will be maintained. This will work for any
+ * NUL-terminated string with a character width of 8 bits, so ASCII,
+ * UTF-8, ISO-8859-N etc.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+/**
+ * gst_byte_reader_peek_string_utf8:
+ * @reader: a #GstByteReader instance
+ * @str: Pointer to a #gchar to store the result
+ *
+ * Returns a constant pointer to the current data position if there is
+ * a NUL-terminated string in the data (this could be just a NUL terminator).
+ * The current position will be maintained. This will work for any
+ * NUL-terminated string with a character width of 8 bits, so ASCII,
+ * UTF-8, ISO-8859-N etc.
+ *
+ * No input checking for valid UTF-8 is done.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_peek_string_utf8 (GstByteReader * reader, const gchar ** str)
+{
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (str != NULL, FALSE);
+
+  if (gst_byte_reader_scan_string_utf8 (reader) > 0) {
+    *str = (const gchar *) (reader->data + reader->byte);
+  } else {
+    *str = NULL;
+  }
+  return (*str != NULL);
+}
+
+/**
+ * gst_byte_reader_get_string_utf8:
+ * @reader: a #GstByteReader instance
+ * @str: Pointer to a #gchar to store the result
+ *
+ * Returns a constant pointer to the current data position if there is
+ * a NUL-terminated string in the data (this could be just a NUL terminator),
+ * advancing the current position to the byte after the string. This will work
+ * for any NUL-terminated string with a character width of 8 bits, so ASCII,
+ * UTF-8, ISO-8859-N etc.
+ *
+ * No input checking for valid UTF-8 is done.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be found, %FALSE otherwise.
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
+{
+  guint size;                   /* size in bytes including the terminator */
+
+  g_return_val_if_fail (reader != NULL, FALSE);
+  g_return_val_if_fail (str != NULL, FALSE);
+
+  size = gst_byte_reader_scan_string_utf8 (reader);
+  if (size == 0) {
+    *str = NULL;
+    return FALSE;
+  }
+
+  *str = (const gchar *) (reader->data + reader->byte);
+  reader->byte += size;
+  return TRUE;
+}
+
+#define GST_BYTE_READER_DUP_STRING(bits,type) \
+__declspec(dllexport) gboolean \
+gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
+{ \
+  guint size; /* size in bytes including the terminator */ \
+  \
+  g_return_val_if_fail (reader != NULL, FALSE); \
+  g_return_val_if_fail (str != NULL, FALSE); \
+  \
+  size = gst_byte_reader_scan_string_utf##bits (reader); \
+  if (size == 0) { \
+    *str = NULL; \
+    return FALSE; \
+  } \
+  *str = g_memdup (reader->data + reader->byte, size); \
+  reader->byte += size; \
+  return TRUE; \
+}
+
+/**
+ * gst_byte_reader_dup_string_utf8:
+ * @reader: a #GstByteReader instance
+ * @str: address of a string pointer to store the result
+ *
+ * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance,
+ * advancing the current position to the byte after the string. This will work
+ * for any NUL-terminated string with a character width of 8 bits, so ASCII,
+ * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The
+ *     string put into @str must be freed with g_free() when no longer needed.
+ *
+ * Since: 0.10.24
+ */
+GST_BYTE_READER_DUP_STRING (8, gchar);
+
+/**
+ * gst_byte_reader_dup_string_utf16:
+ * @reader: a #GstByteReader instance
+ * @str: address of a #guint16 pointer to store the result
+ *
+ * Returns a newly-allocated copy of the current data position if there is
+ * a NUL-terminated UTF-16 string in the data (this could be an empty string
+ * as well), and advances the current position.
+ *
+ * No input checking for valid UTF-16 is done. This function is endianness
+ * agnostic - you should not assume the UTF-16 characters are in host
+ * endianness.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Note: there is no peek or get variant of this function to ensure correct
+ * byte alignment of the UTF-16 string.
+ *
+ * Returns: %TRUE if a string could be read, %FALSE otherwise. The
+ *     string put into @str must be freed with g_free() when no longer needed.
+ *
+ * Since: 0.10.24
+ */
+GST_BYTE_READER_DUP_STRING (16, guint16);
+
+/**
+ * gst_byte_reader_dup_string_utf32:
+ * @reader: a #GstByteReader instance
+ * @str: address of a #guint32 pointer to store the result
+ *
+ * Returns a newly-allocated copy of the current data position if there is
+ * a NUL-terminated UTF-32 string in the data (this could be an empty string
+ * as well), and advances the current position.
+ *
+ * No input checking for valid UTF-32 is done. This function is endianness
+ * agnostic - you should not assume the UTF-32 characters are in host
+ * endianness.
+ *
+ * This function will fail if no NUL-terminator was found in in the data.
+ *
+ * Note: there is no peek or get variant of this function to ensure correct
+ * byte alignment of the UTF-32 string.
+ *
+ * Returns: %TRUE if a string could be read, %FALSE otherwise. The
+ *     string put into @str must be freed with g_free() when no longer needed.
+ *
+ * Since: 0.10.24
+ */
+GST_BYTE_READER_DUP_STRING (32, guint32);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/libs/gst/base/gstbytereader.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,414 @@
+/* GStreamer
+ *
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
+ *
+ * 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_BYTE_READER_H__
+#define __GST_BYTE_READER_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstByteReader:
+ * @data: Data from which the bit reader will read
+ * @size: Size of @data in bytes
+ * @byte: Current byte position
+ *
+ * A byte reader instance.
+ */
+typedef struct {
+  const guint8 *data;
+  guint size;
+
+  guint byte;  /* Byte position */
+} GstByteReader;
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstByteReader * gst_byte_reader_new (const guint8 *data, guint size);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstByteReader * gst_byte_reader_new_from_buffer (const GstBuffer *buffer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_byte_reader_free (GstByteReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_byte_reader_init_from_buffer (GstByteReader *reader, const GstBuffer *buffer);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+guint gst_byte_reader_get_pos (const GstByteReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+guint gst_byte_reader_get_remaining (const GstByteReader *reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_byte_reader_skip (GstByteReader *reader, guint nbytes);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_byte_reader_get_uint8 (GstByteReader *reader, guint8 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int8 (GstByteReader *reader, gint8 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint16_le (GstByteReader *reader, guint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int16_le (GstByteReader *reader, gint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint16_be (GstByteReader *reader, guint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int16_be (GstByteReader *reader, gint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint24_le (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int24_le (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint24_be (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int24_be (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint32_le (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int32_le (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint32_be (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int32_be (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint64_le (GstByteReader *reader, guint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int64_le (GstByteReader *reader, gint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_uint64_be (GstByteReader *reader, guint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_int64_be (GstByteReader *reader, gint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_byte_reader_peek_uint8 (GstByteReader *reader, guint8 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int8 (GstByteReader *reader, gint8 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint16_le (GstByteReader *reader, guint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int16_le (GstByteReader *reader, gint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint16_be (GstByteReader *reader, guint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int16_be (GstByteReader *reader, gint16 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint24_le (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int24_le (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint24_be (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int24_be (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint32_le (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int32_le (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint32_be (GstByteReader *reader, guint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int32_be (GstByteReader *reader, gint32 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint64_le (GstByteReader *reader, guint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int64_le (GstByteReader *reader, gint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_uint64_be (GstByteReader *reader, guint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_int64_be (GstByteReader *reader, gint64 *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_byte_reader_get_float32_le (GstByteReader *reader, gfloat *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_float32_be (GstByteReader *reader, gfloat *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_float64_le (GstByteReader *reader, gdouble *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_float64_be (GstByteReader *reader, gdouble *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+gboolean gst_byte_reader_peek_float32_le (GstByteReader *reader, gfloat *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_float32_be (GstByteReader *reader, gfloat *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_float64_le (GstByteReader *reader, gdouble *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_float64_be (GstByteReader *reader, gdouble *val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_dup_data  (GstByteReader * reader, guint size, guint8       ** val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_get_data  (GstByteReader * reader, guint size, const guint8 ** val);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_data (GstByteReader * reader, guint size, const guint8 ** val);
+
+#define gst_byte_reader_dup_string(reader,str) \
+    gst_byte_reader_dup_string_utf8(reader,str)
+
+gboolean gst_byte_reader_dup_string_utf8  (GstByteReader * reader, gchar   ** str);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_dup_string_utf16 (GstByteReader * reader, guint16 ** str);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_dup_string_utf32 (GstByteReader * reader, guint32 ** str);
+
+#define gst_byte_reader_skip_string(reader) \
+    gst_byte_reader_skip_string_utf8(reader)
+
+gboolean gst_byte_reader_skip_string_utf8  (GstByteReader * reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_skip_string_utf16 (GstByteReader * reader);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_skip_string_utf32 (GstByteReader * reader);
+
+#define gst_byte_reader_get_string(reader,str) \
+    gst_byte_reader_get_string_utf8(reader,str)
+
+#define gst_byte_reader_peek_string(reader,str) \
+    gst_byte_reader_peek_string_utf8(reader,str)
+
+gboolean gst_byte_reader_get_string_utf8   (GstByteReader * reader, const gchar ** str);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+gboolean gst_byte_reader_peek_string_utf8  (GstByteReader * reader, const gchar ** str);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+guint    gst_byte_reader_masked_scan_uint32 (GstByteReader * reader,
+                                             guint32         mask,
+                                             guint32         pattern,
+                                             guint           offset,
+                                             guint           size);
+
+/**
+ * GST_BYTE_READER_INIT:
+ * @data: Data from which the #GstByteReader should read
+ * @size: Size of @data in bytes
+ *
+ * A #GstByteReader must be initialized with this macro, before it can be
+ * used. This macro can used be to initialize a variable, but it cannot
+ * be assigned to a variable. In that case you have to use
+ * gst_byte_reader_init().
+ *
+ * Since: 0.10.22
+ */
+#define GST_BYTE_READER_INIT(data, size) {data, size, 0}
+
+/**
+ * GST_BYTE_READER_INIT_FROM_BUFFER:
+ * @buffer: Buffer from which the #GstByteReader should read
+ *
+ * A #GstByteReader must be initialized with this macro, before it can be
+ * used. This macro can used be to initialize a variable, but it cannot
+ * be assigned to a variable. In that case you have to use
+ * gst_byte_reader_init().
+ *
+ * Since: 0.10.22
+ */
+#define GST_BYTE_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0}
+
+G_END_DECLS
+
+#endif /* __GST_BYTE_READER_H__ */
--- a/gstreamer_core/libs/gst/base/gstcollectpads.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstcollectpads.c	Fri Apr 16 15:15:52 2010 +0300
@@ -95,6 +95,7 @@
     GstCollectPadsClass * g_class);
 static void ref_data (GstCollectData * data);
 static void unref_data (GstCollectData * data);
+static void gst_collect_pads_check_pads_unlocked (GstCollectPads * pads);
 
 static void
 gst_collect_pads_base_init (gpointer g_class)
@@ -545,6 +546,36 @@
   return GST_FLOW_NOT_SUPPORTED;
 }
 
+static gboolean
+gst_collect_pads_is_flushing (GstCollectPads * pads)
+{
+  GSList *walk = NULL;
+  gboolean res = TRUE;
+
+  GST_COLLECT_PADS_PAD_LOCK (pads);
+
+  /* Ensure pads->data state */
+  gst_collect_pads_check_pads_unlocked (pads);
+
+  GST_DEBUG ("Getting flushing state (pads:%p, pads->data:%p)",
+      pads, pads->data);
+
+  for (walk = pads->data; walk; walk = g_slist_next (walk)) {
+    GstCollectData *cdata = walk->data;
+
+    GST_DEBUG_OBJECT (cdata->pad, "flushing:%d", cdata->abidata.ABI.flushing);
+
+    if (cdata->abidata.ABI.flushing) {
+      goto done;
+    }
+  }
+
+  res = FALSE;
+done:
+  GST_COLLECT_PADS_PAD_UNLOCK (pads);
+  return res;
+}
+
 /* FIXME, I think this function is used to work around bad behaviour
  * of elements that add pads to themselves without activating them.
  *
@@ -556,6 +587,8 @@
 {
   GSList *walk = NULL;
 
+  GST_DEBUG ("Setting flushing (%d)", flushing);
+
   /* Update the pads flushing flag */
   for (walk = pads->data; walk; walk = g_slist_next (walk)) {
     GstCollectData *cdata = walk->data;
@@ -571,6 +604,10 @@
       GST_OBJECT_UNLOCK (cdata->pad);
     }
   }
+  /* Setting the pads to flushing means that we changed the values which
+   * are 'protected' by the cookie. We therefore update it to force a 
+   * recalculation of the current pad status. */
+  pads->abidata.ABI.pad_cookie++;
 }
 
 /**
@@ -597,6 +634,8 @@
   g_return_if_fail (GST_IS_COLLECT_PADS (pads));
 
   GST_COLLECT_PADS_PAD_LOCK (pads);
+  /* Ensure pads->data state */
+  gst_collect_pads_check_pads_unlocked (pads);
   gst_collect_pads_set_flushing_unlocked (pads, flushing);
   GST_COLLECT_PADS_PAD_UNLOCK (pads);
 }
@@ -831,19 +870,20 @@
 
     /* ignore pad with EOS */
     if (G_UNLIKELY (pdata->abidata.ABI.eos)) {
-      GST_DEBUG ("pad %p is EOS", pdata);
+      GST_DEBUG ("pad %s:%s is EOS", GST_DEBUG_PAD_NAME (pdata->pad));
       continue;
     }
 
     /* an empty buffer without EOS is weird when we get here.. */
     if (G_UNLIKELY ((buffer = pdata->buffer) == NULL)) {
-      GST_WARNING ("pad %p has no buffer", pdata);
+      GST_WARNING ("pad %s:%s has no buffer", GST_DEBUG_PAD_NAME (pdata->pad));
       goto not_filled;
     }
 
     /* this is the size left of the buffer */
     size = GST_BUFFER_SIZE (buffer) - pdata->pos;
-    GST_DEBUG ("pad %p has %d bytes left", pdata, size);
+    GST_DEBUG ("pad %s:%s has %d bytes left",
+        GST_DEBUG_PAD_NAME (pdata->pad), size);
 
     /* need to return the min of all available data */
     if (size < result)
@@ -1024,6 +1064,8 @@
 
   data->pos += size;
 
+  GST_LOG_OBJECT (pads, "Flushing %d bytes, requested %u", flushsize, size);
+
   if (data->pos >= GST_BUFFER_SIZE (buffer))
     /* _clear will also reset data->pos to 0 */
     gst_collect_pads_clear (pads, data);
@@ -1041,10 +1083,10 @@
  * Must be called with LOCK.
  */
 static void
-gst_collect_pads_check_pads (GstCollectPads * pads)
+gst_collect_pads_check_pads_unlocked (GstCollectPads * pads)
 {
-  /* the master list and cookie are protected with the PAD_LOCK */
-  GST_COLLECT_PADS_PAD_LOCK (pads);
+  GST_DEBUG ("stored cookie : %d, used_cookie:%d",
+      pads->abidata.ABI.pad_cookie, pads->cookie);
   if (G_UNLIKELY (pads->abidata.ABI.pad_cookie != pads->cookie)) {
     GSList *collected;
 
@@ -1064,10 +1106,13 @@
       /* update the stats */
       pads->numpads++;
       data = collected->data;
-      if (data->buffer)
-        pads->queuedpads++;
-      if (data->abidata.ABI.eos)
-        pads->eospads++;
+
+      if (G_LIKELY (!data->abidata.ABI.flushing)) {
+        if (data->buffer)
+          pads->queuedpads++;
+        if (data->abidata.ABI.eos)
+          pads->eospads++;
+      }
 
       /* add to the list of pads to collect */
       ref_data (data);
@@ -1076,6 +1121,14 @@
     /* and update the cookie */
     pads->cookie = pads->abidata.ABI.pad_cookie;
   }
+}
+
+static inline void
+gst_collect_pads_check_pads (GstCollectPads * pads)
+{
+  /* the master list and cookie are protected with the PAD_LOCK */
+  GST_COLLECT_PADS_PAD_LOCK (pads);
+  gst_collect_pads_check_pads_unlocked (pads);
   GST_COLLECT_PADS_PAD_UNLOCK (pads);
 }
 
@@ -1185,10 +1238,16 @@
         pads->eospads--;
         data->abidata.ABI.eos = FALSE;
       }
+
+      if (!gst_collect_pads_is_flushing (pads)) {
+        /* forward event if all pads are no longer flushing */
+        GST_DEBUG ("No more pads are flushing, forwarding FLUSH_STOP");
+        GST_OBJECT_UNLOCK (pads);
+        goto forward;
+      }
+      gst_event_unref (event);
       GST_OBJECT_UNLOCK (pads);
-
-      /* forward event */
-      goto forward;
+      goto done;
     }
     case GST_EVENT_EOS:
     {
@@ -1249,6 +1308,8 @@
   }
 
 forward:
+  GST_DEBUG_OBJECT (pads, "forward unhandled event: %s",
+      GST_EVENT_TYPE_NAME (event));
   res = gst_pad_event_default (pad, event);
 
 done:
@@ -1275,7 +1336,6 @@
 {
   GstCollectData *data;
   GstCollectPads *pads;
-  guint64 size;
   GstFlowReturn ret;
   GstBuffer **buffer_p;
 
@@ -1290,7 +1350,6 @@
   GST_OBJECT_UNLOCK (pad);
 
   pads = data->collect;
-  size = GST_BUFFER_SIZE (buffer);
 
   GST_OBJECT_LOCK (pads);
   /* if not started, bail out */
@@ -1321,6 +1380,7 @@
 
   /* While we have data queued on this pad try to collect stuff */
   do {
+    GST_DEBUG ("Pad %s:%s checking", GST_DEBUG_PAD_NAME (pad));
     /* Check if our collected condition is matched and call the collected function
      * if it is */
     ret = gst_collect_pads_check_collected (pads);
@@ -1363,6 +1423,7 @@
   while (data->buffer != NULL);
 
 unlock_done:
+  GST_DEBUG ("Pad %s:%s done", GST_DEBUG_PAD_NAME (pad));
   GST_OBJECT_UNLOCK (pads);
   unref_data (data);
   gst_buffer_unref (buffer);
--- a/gstreamer_core/libs/gst/base/gstcollectpads.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstcollectpads.h	Fri Apr 16 15:15:52 2010 +0300
@@ -83,7 +83,7 @@
 
 /**
  * GstCollectPadsFunction:
- * @pads: the #GstCollectPads that trigered the callback
+ * @pads: the #GstCollectPads that triggered the callback
  * @user_data: user data passed to gst_collect_pads_set_function()
  *
  * A function that will be called when all pads have received data.
@@ -248,13 +248,13 @@
 IMPORT_C
 #endif
 
-GstBuffer *      gst_collect_pads_read_buffer      (GstCollectPads * pads, GstCollectData * data,
+GstBuffer *     gst_collect_pads_read_buffer    (GstCollectPads * pads, GstCollectData * data,
 						 guint size);
 #ifdef __SYMBIAN32__
 IMPORT_C
 #endif
 
-GstBuffer *      gst_collect_pads_take_buffer      (GstCollectPads * pads, GstCollectData * data,
+GstBuffer *     gst_collect_pads_take_buffer    (GstCollectPads * pads, GstCollectData * data,
 						 guint size);
 #ifdef __SYMBIAN32__
 IMPORT_C
--- a/gstreamer_core/libs/gst/base/gstdataqueue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstdataqueue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -92,8 +92,6 @@
                q->cur_level.time,                                       \
                q->queue->length)
 
-static void gst_data_queue_class_init (GstDataQueueClass * klass);
-static void gst_data_queue_init (GstDataQueue * queue);
 static void gst_data_queue_finalize (GObject * object);
 
 static void gst_data_queue_set_property (GObject * object,
@@ -103,40 +101,17 @@
 
 static GObjectClass *parent_class = NULL;
 static guint gst_data_queue_signals[LAST_SIGNAL] = { 0 };
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
+
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (data_queue_debug, "dataqueue", 0, \
+      "data queue object"); \
+  GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "data_queue_dataflow", 0, \
+      "dataflow inside the data queue object"); \
+}
 
 
-GType
-gst_data_queue_get_type (void)
-{
-  static GType queue_type = 0;
-
-  if (!queue_type) {
-    static const GTypeInfo queue_info = {
-      sizeof (GstDataQueueClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_data_queue_class_init,
-      NULL,
-      NULL,
-      sizeof (GstDataQueue),
-      0,
-      (GInstanceInitFunc) gst_data_queue_init,
-      NULL
-    };
-
-    queue_type = g_type_register_static (G_TYPE_OBJECT,
-        "GstDataQueue", &queue_info, 0);
-    GST_DEBUG_CATEGORY_INIT (data_queue_debug, "dataqueue", 0,
-        "data queue object");
-    GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "data_queue_dataflow", 0,
-        "dataflow inside the data queue object");
-  }
-
-  return queue_type;
-}
+G_DEFINE_TYPE_WITH_CODE (GstDataQueue, gst_data_queue, G_TYPE_OBJECT, _do_init);
 
 static void
 gst_data_queue_class_init (GstDataQueueClass * klass)
@@ -181,16 +156,16 @@
   g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_BYTES,
       g_param_spec_uint ("current-level-bytes", "Current level (kB)",
           "Current amount of data in the queue (bytes)",
-          0, G_MAXUINT, 0, G_PARAM_READABLE));
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_VISIBLE,
       g_param_spec_uint ("current-level-visible",
           "Current level (visible items)",
           "Current number of visible items in the queue", 0, G_MAXUINT, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_TIME,
       g_param_spec_uint64 ("current-level-time", "Current level (ns)",
           "Current amount of data in the queue (in ns)", 0, G_MAXUINT64, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   /* set several parent class virtual functions */
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_data_queue_finalize);
--- a/gstreamer_core/libs/gst/base/gstdataqueue.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstdataqueue.h	Fri Apr 16 15:15:52 2010 +0300
@@ -107,7 +107,7 @@
 {
   GObject object;
 
-  /*< private > */
+  /*< private >*/
   /* the queue of data we're keeping our grubby hands on */
   GQueue *queue;
 
--- a/gstreamer_core/libs/gst/base/gstpushsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstpushsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -60,9 +60,7 @@
 #include <gst/gstmarshal.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_push_src_debug);
-#ifndef __SYMBIAN32__
 #define GST_CAT_DEFAULT gst_push_src_debug
-#endif
 
 #define _do_init(type) \
     GST_DEBUG_CATEGORY_INIT (gst_push_src_debug, "pushsrc", 0, \
--- a/gstreamer_core/libs/gst/base/gsttypefindhelper.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gsttypefindhelper.c	Fri Apr 16 15:15:52 2010 +0300
@@ -54,6 +54,9 @@
 
 /* ********************** typefinding in pull mode ************************ */
 
+static void
+helper_find_suggest (gpointer data, guint probability, const GstCaps * caps);
+
 typedef struct
 {
   GSList *buffers;              /* buffer cache */
@@ -86,6 +89,9 @@
   GstBuffer *buffer;
   GstFlowReturn ret;
   GSList *insert_pos = NULL;
+  guint buf_size;
+  guint64 buf_offset;
+  GstCaps *caps;
 
   helper = (GstTypeFindHelper *) data;
 
@@ -111,16 +117,14 @@
       guint64 buf_offset = GST_BUFFER_OFFSET (buf);
       guint buf_size = GST_BUFFER_SIZE (buf);
 
+      /* buffers are kept sorted by end offset (highest first) in the list, so
+       * at this point we save the current position and stop searching if 
+       * we're after the searched end offset */
       if (buf_offset <= offset) {
         if ((offset + size) < (buf_offset + buf_size)) {
           return GST_BUFFER_DATA (buf) + (offset - buf_offset);
         }
-        /* buffers are kept sorted by offset (highest first) in the list, so
-         * at this point we know we don't need to check the remaining buffers
-         * (is that correct or just a guess that we're unlikely to find a
-         * match further down and it's most of the time not worth going through
-         * the entire list? How do we know the next buffer isn't offset-N with
-         * a big enough size to cover the requested offset+size?) */
+      } else if (offset + size >= buf_offset + buf_size) {
         insert_pos = walk;
         break;
       }
@@ -134,18 +138,33 @@
    * of the file is also not a problem here, we'll just get a truncated buffer
    * in that case (and we'll have to double-check the size we actually get
    * anyway, see below) */
-  ret = helper->func (helper->obj, offset, MAX (size, 512), &buffer);
+  ret = helper->func (helper->obj, offset, MAX (size, 4096), &buffer);
 
   if (ret != GST_FLOW_OK)
     goto error;
 
+  caps = GST_BUFFER_CAPS (buffer);
+
+  if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
+    GST_DEBUG ("buffer has caps %" GST_PTR_FORMAT ", suggest max probability",
+        caps);
+
+    gst_caps_replace (&helper->caps, caps);
+    helper->best_probability = GST_TYPE_FIND_MAXIMUM;
+
+    gst_buffer_unref (buffer);
+    return NULL;
+  }
+
   /* getrange might silently return shortened buffers at the end of a file,
    * we must, however, always return either the full requested data or NULL */
-  if (GST_BUFFER_OFFSET (buffer) != offset || GST_BUFFER_SIZE (buffer) < size) {
+  buf_offset = GST_BUFFER_OFFSET (buffer);
+  buf_size = GST_BUFFER_SIZE (buffer);
+
+  if ((buf_offset != -1 && buf_offset != offset) || buf_size < size) {
     GST_DEBUG ("droping short buffer: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT
         " instead of %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
-        GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer) +
-        GST_BUFFER_SIZE (buffer) - 1, offset, offset + size - 1);
+        buf_offset, buf_offset + buf_size - 1, offset, offset + size - 1);
     gst_buffer_unref (buffer);
     return NULL;
   }
@@ -157,8 +176,7 @@
     /* if insert_pos is not set, our offset is bigger than the largest offset
      * we have so far; since we keep the list sorted with highest offsets
      * first, we need to prepend the buffer to the list */
-    /* FIXME: why not last_offset = buffer_offset + buffer_size here? */
-    helper->last_offset = GST_BUFFER_OFFSET (buffer);
+    helper->last_offset = GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer);
     helper->buffers = g_slist_prepend (helper->buffers, buffer);
   }
   return GST_BUFFER_DATA (buffer);
@@ -470,3 +488,72 @@
 
   return result;
 }
+
+/**
+ * gst_type_find_helper_for_extension:
+ * @obj: object doing the typefinding, or NULL (used for logging)
+ * @extension: an extension
+ *
+ * Tries to find the best #GstCaps associated with @extension.
+ *
+ * All available typefinders will be checked against the extension in order
+ * of rank. The caps of the first typefinder that can handle @extension will be
+ * returned.
+ *
+ * Returns: The #GstCaps corresponding to @extension, or #NULL if no type could
+ * be found. The caller should free the caps returned with gst_caps_unref().
+ * 
+ * Since: 0.10.23
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstCaps *
+gst_type_find_helper_for_extension (GstObject * obj, const gchar * extension)
+{
+  GList *l, *type_list;
+  GstCaps *result = NULL;
+
+  g_return_val_if_fail (extension != NULL, NULL);
+
+  GST_LOG_OBJECT (obj, "finding caps for extension %s", extension);
+
+  type_list = gst_type_find_factory_get_list ();
+  type_list = g_list_sort (type_list, type_find_factory_rank_cmp);
+
+  for (l = type_list; l; l = g_list_next (l)) {
+    GstTypeFindFactory *factory;
+    gchar **ext;
+    gint i;
+
+    factory = GST_TYPE_FIND_FACTORY (l->data);
+
+    /* get the extension that this typefind factory can handle */
+    ext = gst_type_find_factory_get_extensions (factory);
+    if (ext == NULL)
+      continue;
+
+    /* we only want to check those factories without a function */
+    if (factory->function != NULL)
+      continue;
+
+    /* there are extension, see if one of them matches the requested
+     * extension */
+    for (i = 0; ext[i]; i++) {
+      if (strcmp (ext[i], extension) == 0) {
+        /* we found a matching extension, take the caps */
+        if ((result = gst_type_find_factory_get_caps (factory))) {
+          gst_caps_ref (result);
+          goto done;
+        }
+      }
+    }
+  }
+done:
+  gst_plugin_feature_list_free (type_list);
+
+  GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT, result);
+
+  return result;
+}
--- a/gstreamer_core/libs/gst/base/gsttypefindhelper.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gsttypefindhelper.h	Fri Apr 16 15:15:52 2010 +0300
@@ -37,6 +37,13 @@
 GstCaps * gst_type_find_helper_for_buffer (GstObject              *obj,
                                            GstBuffer              *buf,
                                            GstTypeFindProbability *prob);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+
+GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
+                                              const gchar * extension);
 
 /**
  * GstTypeFindHelperGetRangeFunction:
--- a/gstreamer_core/libs/gst/check/gstbufferstraw.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/check/gstbufferstraw.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,8 +29,9 @@
  */
 
 #include "gstbufferstraw.h"
+#ifdef __SYMBIAN32__
 #include <glib_global.h>
-
+#endif
 static GCond *cond = NULL;
 static GMutex *lock = NULL;
 static GstBuffer *buf = NULL;
--- a/gstreamer_core/libs/gst/check/gstcheck.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/check/gstcheck.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,8 +31,6 @@
 #include "gstcheck.h"
 #include <glib_global.h>
 
-//#include "libgstreamer_wsd_solution.h"
-
 GST_DEBUG_CATEGORY (check_debug);
 
 /* logging function for tests
@@ -43,6 +41,13 @@
 
 //gboolean _gst_check_threads_running = FALSE;
 //GList *thread_list = NULL;
+#ifdef __SYMBIAN32__
+EXPORT_C
+GstDebugCategory ** _check_debug()
+{
+    return &check_debug;
+}
+#endif
 #if EMULATOR
 GET_GLOBAL_VAR_FROM_TLS(thread_list,gstcheck,GList*)
 #define thread_list (*GET_GSTREAMER_WSD_VAR_NAME(thread_list,gstcheck,g)())
@@ -99,7 +104,6 @@
 EXPORT_C GCond *check_cond = NULL;
 #endif
 
-
 /* FIXME 0.11: shouldn't _gst_check_debug be static? Not used anywhere */
 EXPORT_C gboolean _gst_check_debug = FALSE;
 #if EMULATOR
@@ -139,7 +143,6 @@
   }
 }
 
-
 static void gst_check_log_critical_func
     (const gchar * log_domain, GLogLevelFlags log_level,
     const gchar * message, gpointer user_data)
@@ -273,6 +276,22 @@
 gst_check_setup_src_pad (GstElement * element,
     GstStaticPadTemplate * template, GstCaps * caps)
 {
+  GstPad *srcpad;
+
+  srcpad = gst_check_setup_src_pad_by_name (element, template, "sink");
+  if (caps)
+    fail_unless (gst_pad_set_caps (srcpad, caps), "could not set caps on pad");
+  return srcpad;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GstPad *
+gst_check_setup_src_pad_by_name (GstElement * element,
+    GstStaticPadTemplate * template, gchar * name)
+{
   GstPad *srcpad, *sinkpad;
 
   /* sending pad */
@@ -281,12 +300,12 @@
   fail_if (srcpad == NULL, "Could not create a srcpad");
   ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
 
-  sinkpad = gst_element_get_pad (element, "sink");
+  sinkpad = gst_element_get_static_pad (element, name);
+  if (sinkpad == NULL)
+    sinkpad = gst_element_get_request_pad (element, name);
   fail_if (sinkpad == NULL, "Could not get sink pad from %s",
       GST_ELEMENT_NAME (element));
   ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
-  if (caps)
-    fail_unless (gst_pad_set_caps (srcpad, caps), "could not set caps on pad");
   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
       "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
   gst_object_unref (sinkpad);   /* because we got it higher up */
@@ -300,29 +319,46 @@
 
 
 void
-gst_check_teardown_src_pad (GstElement * element)
+gst_check_teardown_pad_by_name (GstElement * element, gchar * name)
 {
-  GstPad *srcpad, *sinkpad;
+  GstPad *pad_peer, *pad_element;
 
   /* clean up floating src pad */
-  sinkpad = gst_element_get_pad (element, "sink");
-  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
-  srcpad = gst_pad_get_peer (sinkpad);
+  pad_element = gst_element_get_static_pad (element, name);
+  ASSERT_OBJECT_REFCOUNT (pad_element, "pad", 2);
+  pad_peer = gst_pad_get_peer (pad_element);
 
-  gst_pad_unlink (srcpad, sinkpad);
+  if (pad_peer) {
+    if (gst_pad_get_direction (pad_element) == GST_PAD_SINK)
+      gst_pad_unlink (pad_peer, pad_element);
+    else
+      gst_pad_unlink (pad_element, pad_peer);
 
-  /* caps could have been set, make sure they get unset */
-  gst_pad_set_caps (srcpad, NULL);
+    /* caps could have been set, make sure they get unset */
+    gst_pad_set_caps (pad_peer, NULL);
+  }
 
   /* pad refs held by both creator and this function (through _get) */
-  ASSERT_OBJECT_REFCOUNT (sinkpad, "element sinkpad", 2);
-  gst_object_unref (sinkpad);
+  ASSERT_OBJECT_REFCOUNT (pad_element, "element pad_element", 2);
+  gst_object_unref (pad_element);
   /* one more ref is held by element itself */
 
-  /* pad refs held by both creator and this function (through _get_peer) */
-  ASSERT_OBJECT_REFCOUNT (srcpad, "check srcpad", 2);
-  gst_object_unref (srcpad);
-  gst_object_unref (srcpad);
+  if (pad_peer) {
+    /* pad refs held by both creator and this function (through _get_peer) */
+    ASSERT_OBJECT_REFCOUNT (pad_peer, "check pad_peer", 2);
+    gst_object_unref (pad_peer);
+    gst_object_unref (pad_peer);
+  }
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+void
+gst_check_teardown_src_pad (GstElement * element)
+{
+  gst_check_teardown_pad_by_name (element, "sink");
 }
 
 /* FIXME: set_caps isn't that useful; might want to check if fixed,
@@ -335,6 +371,22 @@
 gst_check_setup_sink_pad (GstElement * element, GstStaticPadTemplate * template,
     GstCaps * caps)
 {
+  GstPad *sinkpad;
+
+  sinkpad = gst_check_setup_sink_pad_by_name (element, template, "src");
+  if (caps)
+    fail_unless (gst_pad_set_caps (sinkpad, caps), "Could not set pad caps");
+  return sinkpad;
+}
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GstPad *
+gst_check_setup_sink_pad_by_name (GstElement * element,
+    GstStaticPadTemplate * template, gchar * name)
+{
   GstPad *srcpad, *sinkpad;
 
   /* receiving pad */
@@ -342,11 +394,11 @@
   GST_DEBUG_OBJECT (element, "setting up receiving pad %p", sinkpad);
   fail_if (sinkpad == NULL, "Could not create a sinkpad");
 
-  srcpad = gst_element_get_pad (element, "src");
+  srcpad = gst_element_get_static_pad (element, name);
+  if (srcpad == NULL)
+    srcpad = gst_element_get_request_pad (element, name);
   fail_if (srcpad == NULL, "Could not get source pad from %s",
       GST_ELEMENT_NAME (element));
-  if (caps)
-    fail_unless (gst_pad_set_caps (sinkpad, caps), "Could not set pad caps");
   gst_pad_set_chain_function (sinkpad, gst_check_chain_func);
 
   GST_DEBUG_OBJECT (element, "Linking element src pad and receiving sink pad");
@@ -366,23 +418,7 @@
 void
 gst_check_teardown_sink_pad (GstElement * element)
 {
-  GstPad *srcpad, *sinkpad;
-
-  /* clean up floating sink pad */
-  srcpad = gst_element_get_pad (element, "src");
-  sinkpad = gst_pad_get_peer (srcpad);
-
-  gst_pad_unlink (srcpad, sinkpad);
-
-  /* pad refs held by both creator and this function (through _get_pad) */
-  ASSERT_OBJECT_REFCOUNT (srcpad, "element srcpad", 2);
-  gst_object_unref (srcpad);
-  /* one more ref is held by element itself */
-
-  /* pad refs held by both creator and this function (through _get_peer) */
-  ASSERT_OBJECT_REFCOUNT (sinkpad, "check sinkpad", 2);
-  gst_object_unref (sinkpad);
-  gst_object_unref (sinkpad);
+  gst_check_teardown_pad_by_name (element, "src");
 }
 
 /**
@@ -411,7 +447,6 @@
 
 /**
  * gst_check_caps_equal:
- *
  * @caps1: first caps to compare
  * @caps2: second caps to compare
  *
@@ -483,8 +518,8 @@
   src_caps = GST_BUFFER_CAPS (buffer);
   src_pad = gst_pad_new (NULL, GST_PAD_SRC);
   gst_pad_set_caps (src_pad, src_caps);
-  pad_peer = gst_element_get_pad (element, "sink");
-  fail_if (pad_peer == NULL, "");
+  pad_peer = gst_element_get_static_pad (element, "sink");
+  fail_if (pad_peer == NULL);
   fail_unless (gst_pad_link (src_pad, pad_peer) == GST_PAD_LINK_OK,
       "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
   gst_object_unref (pad_peer);
@@ -505,11 +540,11 @@
     g_free (temp);
     fail_unless (gst_caps_is_fixed (sink_caps), "we need fixed caps");
     /* get the sink pad */
-    sink_pad = gst_pad_new ('\0', GST_PAD_SINK);
-    fail_unless (GST_IS_PAD (sink_pad), "");
+    sink_pad = gst_pad_new (NULL, GST_PAD_SINK);
+    fail_unless (GST_IS_PAD (sink_pad));
     gst_pad_set_caps (sink_pad, sink_caps);
     /* get the peer pad */
-    pad_peer = gst_element_get_pad (element, "src");
+    pad_peer = gst_element_get_static_pad (element, "src");
     fail_unless (gst_pad_link (pad_peer, sink_pad) == GST_PAD_LINK_OK,
         "Could not link sink and %s source pads", GST_ELEMENT_NAME (element));
     gst_object_unref (pad_peer);
@@ -568,7 +603,7 @@
 
 /**
  * gst_check_element_push_buffer:
- * @element: name of the element that needs to be created
+ * @element_name: name of the element that needs to be created
  * @buffer_in: push this buffer to the element
  * @buffer_out: compare the result with this buffer
  *
@@ -594,9 +629,6 @@
   out = g_list_append (out, buffer_out);
 
   gst_check_element_push_buffer_list (element_name, in, out, GST_FLOW_OK);
-
-  g_list_free (in);
-  g_list_free (out);
 }
 #ifdef __SYMBIAN32__
 EXPORT_C
--- a/gstreamer_core/libs/gst/check/gstcheck.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/check/gstcheck.h	Fri Apr 16 15:15:52 2010 +0300
@@ -40,6 +40,12 @@
 GST_DEBUG_CATEGORY_EXTERN (check_debug);
 #define GST_CAT_DEFAULT check_debug
 
+#define __CHECK_VERSION_LATER_THAN(major,minor,micro) \
+    (CHECK_MAJOR_VERSION > major || \
+     (CHECK_MAJOR_VERSION == (major) && CHECK_MINOR_VERSION > (minor)) || \
+     (CHECK_MAJOR_VERSION == (major) && CHECK_MINOR_VERSION == (minor) && \
+      CHECK_MICRO_VERSION > (micro)))
+
 /* logging function for tests
  * a test uses g_message() to log a debug line
  * a gst unit test can be run with GST_TEST_DEBUG env var set to see the
@@ -149,6 +155,23 @@
 IMPORT_C
 #endif
 
+GstPad * gst_check_setup_src_pad_by_name (GstElement * element,
+          GstStaticPadTemplate * template, gchar *name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+GstPad * gst_check_setup_sink_pad_by_name (GstElement * element, 
+          GstStaticPadTemplate * template, gchar *name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
+void gst_check_teardown_pad_by_name (GstElement * element, gchar *name);
+#ifdef __SYMBIAN32__
+IMPORT_C
+#endif
+
 void gst_check_teardown_src_pad (GstElement * element);
 #ifdef __SYMBIAN32__
 IMPORT_C
@@ -207,11 +230,8 @@
  *
  * wrapper for checks END_TEST
  */
-
 /*
-#if CHECK_MAJOR_VERSION > 0 || \
-    (CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION > 9) || \
-    (CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION > 3)
+#if __CHECK_VERSION_LATER_THAN(0,9,3)
 #define GST_START_TEST(__testname) \
 static void __testname (int __i__)\
 {\
@@ -230,7 +250,6 @@
 //#define GST_END_TEST END_TEST
 //#endif
 
-//#define GST_END_TEST }
 
 /* additional fail macros */
 /**
@@ -367,9 +386,11 @@
 G_STMT_START {				\
   _gst_check_threads_running = TRUE;	\
 					\
-  mutex = g_mutex_new ();		\
-  start_cond = g_cond_new ();		\
-  sync_cond = g_cond_new ();		\
+  if (mutex == NULL) {			\
+    mutex = g_mutex_new ();		\
+    start_cond = g_cond_new ();		\
+    sync_cond = g_cond_new ();		\
+  }					\
 } G_STMT_END;
 
 #define MAIN_START_THREAD_FUNCTIONS(count, function, data)	\
@@ -410,6 +431,8 @@
   /* join all threads */					\
   GST_DEBUG ("MAIN: joining");					\
   g_list_foreach (thread_list, (GFunc) g_thread_join, NULL);	\
+  g_list_free (thread_list);					\
+  thread_list = NULL;						\
   GST_DEBUG ("MAIN: joined");					\
 } G_STMT_END;
 
@@ -511,24 +534,12 @@
 #define GST_CHECK_MAIN(name)					\
 int main (int argc, char **argv)				\
 {								\
-    int i, num_fun;                  \
-gst_check_init (NULL, NULL);                    \
-i = sizeof(args);                           \
- num_fun = i/sizeof(int);                   \
-  for(i=0;i<num_fun;i++)                    \
-      if (!strcmp(args[i], argv[1]))                    \
-      {                                     \
-          fn[i]();                                  \
-          break;                                        \
-          }                     \
-  if(i == num_fun)                      \
-      std_log(LOG_FILENAME_LINE, "%s is invalid args", argv[1]);                      \
-  return 0;                                         \
+  Suite *s;                                                     \
+  gst_check_init (&argc, &argv);				\
+  s = name ## _suite ();					\
+  return gst_check_run_suite (s, # name, __FILE__);		\
 }
-
 */
-
-
 #define GST_CHECK_MAIN(name)                    \
     int main (int argc, char **argv)        \
     {                                   \
@@ -563,9 +574,6 @@
       return 0;                 \
     }
 
-
-
-
 /* Hack to allow run-time selection of unit tests to run via the
  * GST_CHECKS environment variable (test function names, comma-separated) */
 #ifdef __SYMBIAN32__
@@ -574,11 +582,17 @@
 
 
 gboolean _gst_check_run_test_func (const gchar * func_name);
-
 /*
-#if CHECK_MAJOR_VERSION > 0 || \
-    (CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION > 9) || \
-    (CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION > 3)
+#if __CHECK_VERSION_LATER_THAN(0,9,6)
+static inline void
+__gst_tcase_add_test (TCase * tc, TFun tf, const char * fname, int signal,
+    int allowed_exit_value, int start, int end)
+{
+  if (_gst_check_run_test_func (fname)) {
+    _tcase_add_test (tc, tf, fname, signal, allowed_exit_value, start, end);
+  }
+}
+#elif __CHECK_VERSION_LATER_THAN(0,9,3)
 static inline void
 __gst_tcase_add_test (TCase * tc, TFun tf, const char * fname, int signal,
     int start, int end)
@@ -602,6 +616,8 @@
 
 //#define _tcase_add_test __gst_tcase_add_test
 
+//#undef __CHECK_VERSION_LATER_THAN
+
 G_END_DECLS
 
 #endif /* __GST_CHECK_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/libs/gst/check/gstconsistencychecker.c	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,157 @@
+/* GStreamer
+ *
+ * unit testing helper lib
+ *
+ * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.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.
+ */
+
+/**
+ * SECTION:gstcheckconsistencychecker
+ * @short_description: Data flow consistency checker for GStreamer unit tests.
+ *
+ * These macros and functions are for internal use of the unit tests found
+ * inside the 'check' directories of various GStreamer packages.
+ *
+ * Since: 0.10.24
+ */
+
+#include "gstconsistencychecker.h"
+
+struct _GstStreamConsistency
+{
+  gboolean flushing;
+  gboolean newsegment;
+  gboolean eos;
+  gulong probeid;
+  GstPad *pad;
+};
+
+static gboolean
+source_pad_data_cb (GstPad * pad, GstMiniObject * data,
+    GstStreamConsistency * consist)
+{
+  if (GST_IS_BUFFER (data)) {
+    GST_DEBUG_OBJECT (pad, "Buffer %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (GST_BUFFER (data))));
+    /* If an EOS went through, a buffer would be invalid */
+    fail_if (consist->eos, "Buffer received after EOS");
+    /* Buffers need to be preceded by a newsegment event */
+    fail_unless (consist->newsegment, "Buffer received without newsegment");
+  } else {
+    GstEvent *event = (GstEvent *) data;
+
+    GST_DEBUG_OBJECT (pad, "%s", GST_EVENT_TYPE_NAME (event));
+    switch (GST_EVENT_TYPE (event)) {
+      case GST_EVENT_FLUSH_START:
+        consist->flushing = TRUE;
+        break;
+      case GST_EVENT_FLUSH_STOP:
+        /* Receiving a flush-stop is only valid after receiving a flush-start */
+        fail_unless (consist->flushing,
+            "Received a FLUSH_STOP without a FLUSH_START");
+        fail_if (consist->eos, "Received a FLUSH_STOP after an EOS");
+        consist->flushing = FALSE;
+        break;
+      case GST_EVENT_NEWSEGMENT:
+        consist->newsegment = TRUE;
+        consist->eos = FALSE;
+        break;
+      case GST_EVENT_EOS:
+        /* FIXME : not 100% sure about whether two eos in a row is valid */
+        fail_if (consist->eos, "Received EOS just after another EOS");
+        consist->eos = TRUE;
+        consist->newsegment = FALSE;
+        break;
+      case GST_EVENT_TAG:
+        GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT, event->structure);
+      default:
+        if (GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_IS_DOWNSTREAM (event)) {
+          fail_if (consist->eos, "Event received after EOS");
+          fail_unless (consist->newsegment, "Event received before newsegment");
+        }
+        /* FIXME : Figure out what to do for other events */
+        break;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_consistency_checker_new:
+ * @pad: The #GstPad on which the dataflow will be checked.
+ *
+ * Sets up a data probe on the given pad which will raise assertions if the
+ * data flow is inconsistent.
+ *
+ * Currently only works for source pads.
+ *
+ * Returns: A #GstStreamConsistency structure used to track data flow.
+ *
+ * Since: 0.10.24
+ */
+
+GstStreamConsistency *
+gst_consistency_checker_new (GstPad * pad)
+{
+  GstStreamConsistency *consist;
+
+  g_return_val_if_fail (pad != NULL, NULL);
+
+  consist = g_new0 (GstStreamConsistency, 1);
+  consist->pad = g_object_ref (pad);
+  consist->probeid =
+      gst_pad_add_data_probe (pad, (GCallback) source_pad_data_cb, consist);
+
+  return consist;
+}
+
+/**
+ * gst_consistency_checker_reset:
+ * @consist: The #GstStreamConsistency to reset.
+ *
+ * Reset the stream checker's internal variables.
+ *
+ * Since: 0.10.24
+ */
+
+void
+gst_consistency_checker_reset (GstStreamConsistency * consist)
+{
+  consist->eos = FALSE;
+  consist->flushing = FALSE;
+  consist->newsegment = FALSE;
+}
+
+/**
+ * gst_consistency_checker_free:
+ * @consist: The #GstStreamConsistency to free.
+ *
+ * Frees the allocated data and probe associated with @consist.
+ *
+ * Since: 0.10.24
+ */
+
+void
+gst_consistency_checker_free (GstStreamConsistency * consist)
+{
+  /* Remove the data probe */
+  gst_pad_remove_data_probe (consist->pad, consist->probeid);
+  g_object_unref (consist->pad);
+  g_free (consist);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/libs/gst/check/gstconsistencychecker.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,48 @@
+/* GStreamer
+ *
+ * unit testing helper lib
+ *
+ * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.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_CONSISTENCY_CHECKER_H__
+#define __GST_CONSISTENCY_CHECKER_H__
+
+#include <gst/check/gstcheck.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstStreamConsistency:
+ *
+ * Opaque consistency checker handle.
+ *
+ * Since: 0.10.24
+ */
+typedef struct _GstStreamConsistency GstStreamConsistency;
+
+
+GstStreamConsistency * gst_consistency_checker_new   (GstPad * pad);
+
+void                   gst_consistency_checker_reset (GstStreamConsistency * consist);
+
+void                   gst_consistency_checker_free  (GstStreamConsistency * consist);
+
+G_END_DECLS
+
+#endif /* __GST_CONSISTENCY_CHECKER_H__ */
--- a/gstreamer_core/libs/gst/check/std_log_result.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/check/std_log_result.h	Fri Apr 16 15:15:52 2010 +0300
@@ -21,6 +21,7 @@
 */
 
 
+
 #ifndef _STD_LOG_FILE_H__
 #define _STD_LOG_FILE_H__
 
@@ -28,6 +29,7 @@
 #include <time.h>
 #include <string.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #ifdef __SYMBIAN32__
 #include "libgstreamer_wsd_solution.h" 
 
@@ -80,20 +82,21 @@
 #endif
 void std_log(const char *filename,const int lineno,const char* aformat,...)
 {
-	va_list va;
-	if(fp_std_log==NULL)
-	{
-		fp_std_log = fopen(LOG_FILE,"a");
-	}
-	
-	va_start(va,aformat);    
-    {
-		fprintf(fp_std_log,"%s - [%d] : ",filename,lineno);
-		vfprintf(fp_std_log,aformat,va);
-		fprintf(fp_std_log,"\n");
-		fflush(fp_std_log);
-	}
-	va_end(va);
+    /* commented for helium setup memory issue , error value -4*/
+//	va_list va;
+//	if(fp_std_log==NULL)
+//	{
+//		fp_std_log = fopen(LOG_FILE,"a");
+//	}
+//	
+//	va_start(va,aformat);    
+//    {
+//		fprintf(fp_std_log,"%s - [%d] : ",filename,lineno);
+//		vfprintf(fp_std_log,aformat,va);
+//		fprintf(fp_std_log,"\n");
+//		fflush(fp_std_log);
+//	}
+//	va_end(va);
 }
 
 #ifdef __SYMBIAN32__
@@ -112,17 +115,21 @@
 #endif
 void close_log_file()
 {
-   fclose(fp_std_log);
-   fp_std_log = NULL;
+   /* commented for helium setup memory issue , error value -4*/
+  // fclose(fp_std_log);  
+  // fp_std_log = NULL;
 }
 
 // This function is used to generate the xml file used bt ATS
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
+
 void testResultXml(char *filename)
 {
-	char time_buf[50];
+    
+    /* commented for helium setup memory issue , error value -4*/
+	/*char time_buf[50];     
 
 	char result[10];
 
@@ -197,6 +204,7 @@
 
 		fclose(fp_result);
 	}
+	*/
 }
 
 #endif
--- a/gstreamer_core/libs/gst/controller/gstcontroller.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstcontroller.c	Fri Apr 16 15:15:52 2010 +0300
@@ -81,7 +81,6 @@
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #include <gobject_global.h>
-
 #endif
 #define GST_CAT_DEFAULT controller_debug
 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
@@ -151,6 +150,8 @@
       prop->pspec = pspec;
       prop->name = pspec->name;
       prop->disabled = FALSE;
+      memset (&prop->last_value, 0, sizeof (GValue));
+      g_value_init (&prop->last_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
     }
   } else {
     GST_WARNING ("class '%s' has no property '%s'", G_OBJECT_TYPE_NAME (object),
@@ -171,6 +172,7 @@
 {
   if (prop->csource)
     g_object_unref (prop->csource);
+  g_value_unset (&prop->last_value);
   g_free (prop);
 }
 
@@ -203,6 +205,58 @@
   return NULL;
 }
 
+/*
+ * gst_controller_add_property:
+ * @self: the controller object or %NULL if none yet exists
+ * @object: object to bind the property
+ * @name: name of projecty in @object
+ * @ref_existing: pointer to flag that tracks if we need to ref an existng
+ *   controller still
+ *
+ * Creates a new #GstControlledProperty if there is none for property @name yet.
+ * In case this is the first controlled propery, it creates the controller as
+ * well.
+ *
+ * Returns: a newly created controller object or reffed existing one with the
+ * given property bound.
+ */
+static GstController *
+gst_controller_add_property (GstController * self, GObject * object,
+    gchar * name, gboolean * ref_existing)
+{
+  /* test if this property isn't yet controlled */
+  if (!self || !gst_controller_find_controlled_property (self, name)) {
+    GstControlledProperty *prop;
+
+    /* create GstControlledProperty and add to self->propeties List */
+    if ((prop = gst_controlled_property_new (object, name))) {
+      /* if we don't have a controller object yet, now is the time to create one */
+      if (!self) {
+        self = g_object_new (GST_TYPE_CONTROLLER, NULL);
+        self->object = g_object_ref (object);
+        /* store the controller */
+        g_object_set_qdata (object, priv_gst_controller_key, self);
+        *ref_existing = FALSE;
+      } else {
+        /* only want one single _ref(), even for multiple properties */
+        if (*ref_existing) {
+          g_object_ref (self);
+          *ref_existing = FALSE;
+          GST_INFO ("returning existing controller");
+        }
+      }
+      self->properties = g_list_prepend (self->properties, prop);
+    }
+  } else {
+    GST_WARNING ("trying to control property again");
+    if (*ref_existing) {
+      g_object_ref (self);
+      *ref_existing = FALSE;
+    }
+  }
+  return self;
+}
+
 /* methods */
 
 /**
@@ -222,7 +276,6 @@
 gst_controller_new_valist (GObject * object, va_list var_args)
 {
   GstController *self;
-  GstControlledProperty *prop;
   gboolean ref_existing = TRUE;
   gchar *name;
 
@@ -233,34 +286,7 @@
   self = g_object_get_qdata (object, priv_gst_controller_key);
   /* create GstControlledProperty for each property */
   while ((name = va_arg (var_args, gchar *))) {
-    /* test if this property isn't yet controlled */
-    if (!self || !(prop = gst_controller_find_controlled_property (self, name))) {
-      /* create GstControlledProperty and add to self->propeties List */
-      if ((prop = gst_controlled_property_new (object, name))) {
-        /* if we don't have a controller object yet, now is the time to create one */
-        if (!self) {
-          self = g_object_new (GST_TYPE_CONTROLLER, NULL);
-          self->object = g_object_ref (object);
-          /* store the controller */
-          g_object_set_qdata (object, priv_gst_controller_key, self);
-          ref_existing = FALSE;
-        } else {
-          /* only want one single _ref(), even for multiple properties */
-          if (ref_existing) {
-            g_object_ref (self);
-            ref_existing = FALSE;
-            GST_INFO ("returning existing controller");
-          }
-        }
-        self->properties = g_list_prepend (self->properties, prop);
-      }
-    } else {
-      GST_WARNING ("trying to control property again");
-      if (ref_existing) {
-        g_object_ref (self);
-        ref_existing = FALSE;
-      }
-    }
+    self = gst_controller_add_property (self, object, name, &ref_existing);
   }
   va_end (var_args);
 
@@ -286,7 +312,6 @@
 gst_controller_new_list (GObject * object, GList * list)
 {
   GstController *self;
-  GstControlledProperty *prop;
   gboolean ref_existing = TRUE;
   gchar *name;
   GList *node;
@@ -299,34 +324,7 @@
   /* create GstControlledProperty for each property */
   for (node = list; node; node = g_list_next (node)) {
     name = (gchar *) node->data;
-    /* test if this property isn't yet controlled */
-    if (!self || !(prop = gst_controller_find_controlled_property (self, name))) {
-      /* create GstControlledProperty and add to self->propeties List */
-      if ((prop = gst_controlled_property_new (object, name))) {
-        /* if we don't have a controller object yet, now is the time to create one */
-        if (!self) {
-          self = g_object_new (GST_TYPE_CONTROLLER, NULL);
-          self->object = g_object_ref (object);
-          /* store the controller */
-          g_object_set_qdata (object, priv_gst_controller_key, self);
-          ref_existing = FALSE;
-        } else {
-          /* only want one single _ref(), even for multiple properties */
-          if (ref_existing) {
-            g_object_ref (self);
-            ref_existing = FALSE;
-            GST_INFO ("returning existing controller");
-          }
-        }
-        self->properties = g_list_prepend (self->properties, prop);
-      }
-    } else {
-      GST_WARNING ("trying to control property again");
-      if (ref_existing) {
-        g_object_ref (self);
-        ref_existing = FALSE;
-      }
-    }
+    self = gst_controller_add_property (self, object, name, &ref_existing);
   }
 
   if (self)
@@ -604,6 +602,9 @@
   GstControlledProperty *prop;
   GstControlSource *ret = NULL;
 
+  g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
+  g_return_val_if_fail (property_name, NULL);
+
   g_mutex_lock (self->lock);
   if ((prop = gst_controller_find_controlled_property (self, property_name))) {
     ret = prop->csource;
@@ -625,7 +626,8 @@
  * Gets the value for the given controller-handled property at the requested
  * time.
  *
- * Returns: the GValue of the property at the given time, or %NULL if the property isn't handled by the controller
+ * Returns: the GValue of the property at the given time, or %NULL if the
+ * property isn't handled by the controller
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -692,7 +694,9 @@
   g_mutex_lock (self->lock);
 
   /* TODO: Implement more logic, depending on interpolation mode
-   * and control points */
+   * and control points
+   * FIXME: we need playback direction
+   */
   ret = self->priv->last_sync + self->priv->control_rate;
 
   g_mutex_unlock (self->lock);
@@ -708,6 +712,9 @@
  * Sets the properties of the element, according to the controller that (maybe)
  * handles them and for the given timestamp.
  *
+ * If this function fails, it is most likely the application developers fault.
+ * Most probably the control sources are not setup correctly.
+ *
  * Returns: %TRUE if the controller values could be applied to the object
  * properties, %FALSE otherwise
  */
@@ -720,7 +727,8 @@
 {
   GstControlledProperty *prop;
   GList *node;
-  gboolean ret = FALSE;
+  gboolean ret = TRUE, val_ret;
+  GValue value = { 0, };
 
   g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
@@ -728,25 +736,39 @@
   GST_LOG ("sync_values");
 
   g_mutex_lock (self->lock);
+  g_object_freeze_notify (self->object);
   /* go over the controlled properties of the controller */
   for (node = self->properties; node; node = g_list_next (node)) {
-    GValue value = { 0, };
     prop = node->data;
 
-    GST_DEBUG ("  property '%s' at ts=%" G_GUINT64_FORMAT, prop->name,
-        timestamp);
-
     if (!prop->csource || prop->disabled)
       continue;
 
+    GST_LOG ("property '%s' at ts=%" G_GUINT64_FORMAT, prop->name, timestamp);
+
+    /* we can make this faster
+     * http://bugzilla.gnome.org/show_bug.cgi?id=536939
+     */
     g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
-    ret = gst_control_source_get_value (prop->csource, timestamp, &value);
-    if (ret) {
-      g_object_set_property (self->object, prop->name, &value);
-      g_value_unset (&value);
+    val_ret = gst_control_source_get_value (prop->csource, timestamp, &value);
+    if (G_LIKELY (val_ret)) {
+      /* always set the value for first time, but then only if it changed
+       * this should limit g_object_notify invocations.
+       * FIXME: can we detect negative playback rates?
+       */
+      if ((timestamp < self->priv->last_sync) ||
+          gst_value_compare (&value, &prop->last_value) != GST_VALUE_EQUAL) {
+        g_object_set_property (self->object, prop->name, &value);
+        g_value_copy (&value, &prop->last_value);
+      }
+    } else {
+      GST_DEBUG ("no control value for param %s", prop->name);
     }
+    g_value_unset (&value);
+    ret &= val_ret;
   }
   self->priv->last_sync = timestamp;
+  g_object_thaw_notify (self->object);
 
   g_mutex_unlock (self->lock);
 
@@ -982,7 +1004,8 @@
       g_param_spec_uint64 ("control-rate",
           "control rate",
           "Controlled properties will be updated at least every control-rate nanoseconds",
-          1, G_MAXUINT, 100 * GST_MSECOND, G_PARAM_READWRITE));
+          1, G_MAXUINT, 100 * GST_MSECOND,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /* register signals */
   /* set defaults for overridable methods */
@@ -995,9 +1018,10 @@
 GType
 gst_controller_get_type (void)
 {
-  static GType type = 0;
+  static volatile gsize type = 0;
 
-  if (type == 0) {
+  if (g_once_init_enter (&type)) {
+    GType _type;
     static const GTypeInfo info = {
       sizeof (GstControllerClass),
       NULL,                     /* base_init */
@@ -1010,7 +1034,8 @@
       (GInstanceInitFunc) _gst_controller_init, /* instance_init */
       NULL                      /* value_table */
     };
-    type = g_type_register_static (G_TYPE_OBJECT, "GstController", &info, 0);
+    _type = g_type_register_static (G_TYPE_OBJECT, "GstController", &info, 0);
+    g_once_init_leave (&type, _type);
   }
   return type;
 }
--- a/gstreamer_core/libs/gst/controller/gstcontroller.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstcontroller.h	Fri Apr 16 15:15:52 2010 +0300
@@ -35,15 +35,6 @@
 
 G_BEGIN_DECLS
 
-/**
- * GST_PARAM_CONTROLLABLE:
- *
- * Use this flag on GstElement properties you wish to be (eventually) handled
- * by a GstController.
- * TODO: needs to go to gstelemnt.h (to avoid clashes on G_PARAM_USER_SHIFT)
- */
-#define	GST_PARAM_CONTROLLABLE	(1 << (G_PARAM_USER_SHIFT + 1))
-
 /* type macros */
 
 #define GST_TYPE_CONTROLLER	       (gst_controller_get_type ())
--- a/gstreamer_core/libs/gst/controller/gstcontrollerprivate.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstcontrollerprivate.h	Fri Apr 16 15:15:52 2010 +0300
@@ -41,10 +41,13 @@
   gchar *name;                  /* name of the property */
   GstControlSource *csource;    /* GstControlSource for this property */
   gboolean disabled;
+  GValue last_value;
 } GstControlledProperty;
 
 #define GST_CONTROLLED_PROPERTY(obj)    ((GstControlledProperty *)(obj))
 
+extern GQuark priv_gst_controller_key;
+
 G_END_DECLS
 
 #endif /* __GST_CONTROLLER_PRIVATE_H__ */
--- a/gstreamer_core/libs/gst/controller/gstcontrolsource.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstcontrolsource.c	Fri Apr 16 15:15:52 2010 +0300
@@ -96,7 +96,7 @@
 {
   g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
 
-  if (self->get_value) {
+  if (G_LIKELY (self->get_value)) {
     return self->get_value (self, timestamp, value);
   } else {
     GST_ERROR ("Not bound to a specific property yet!");
@@ -130,7 +130,7 @@
 {
   g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
 
-  if (self->get_value_array) {
+  if (G_LIKELY (self->get_value_array)) {
     return self->get_value_array (self, timestamp, value_array);
   } else {
     GST_ERROR ("Not bound to a specific property yet!");
--- a/gstreamer_core/libs/gst/controller/gsthelper.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gsthelper.c	Fri Apr 16 15:15:52 2010 +0300
@@ -41,8 +41,6 @@
 #define GST_CAT_DEFAULT controller_debug
 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
 
-extern GQuark priv_gst_controller_key;
-
 /**
  * gst_object_control_properties:
  * @object: the object of which some properties should be controlled
@@ -149,12 +147,10 @@
 gboolean
 gst_object_set_controller (GObject * object, GstController * controller)
 {
-  GstController *ctrl;
-
   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
   g_return_val_if_fail (controller, FALSE);
 
-  if (!(ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
+  if (!g_object_get_qdata (object, priv_gst_controller_key)) {
     g_object_set_qdata (object, priv_gst_controller_key, controller);
     return (TRUE);
   }
@@ -207,12 +203,14 @@
   GstController *ctrl = NULL;
 
   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
 
   if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
     return gst_controller_sync_values (ctrl, timestamp);
   }
-  return (FALSE);
+  /* this is no failure, its called by elements regardless if there is a
+   * controller assigned or not
+   */
+  return (TRUE);
 }
 
 /**
--- a/gstreamer_core/libs/gst/controller/gstinterpolation.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstinterpolation.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,7 +1,7 @@
 /* GStreamer
  *
  * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * gstinterpolation.c: Interpolation methods for dynamic properties
  *
@@ -41,70 +41,53 @@
 
 /* common helper */
 
+static gint
+gst_control_point_find (gconstpointer p1, gconstpointer p2)
+{
+  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
+  GstClockTime ct2 = *(GstClockTime *) p2;
+
+  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
+}
+
 /*
- * gst_interpolation_control_source_find_control_point_node:
+ * gst_interpolation_control_source_find_control_point_iter:
  * @self: the interpolation control source to search in
  * @timestamp: the search key
  *
  * Find last value before given timestamp in control point list.
  *
- * Returns: the found #GList node or %NULL
+ * Returns: the found #GSequenceIter or %NULL
  */
-static GList *gst_interpolation_control_source_find_control_point_node
+static GSequenceIter *gst_interpolation_control_source_find_control_point_iter
     (GstInterpolationControlSource * self, GstClockTime timestamp)
 {
-  GList *prev_node = g_list_last (self->priv->values);
-  GList *node;
+  GSequenceIter *iter;
   GstControlPoint *cp;
 
-  /* Check if we can start from the last requested value
-   * to save some time */
-  node = self->priv->values;
-  if (self->priv->last_requested_value) {
-    GstControlPoint *last_cp = self->priv->last_requested_value->data;
-
-    if (timestamp > last_cp->timestamp)
-      node = self->priv->last_requested_value;
-  }
+  if (!self->priv->values)
+    return NULL;
 
-  /* iterate over timed value list */
-  for (; node; node = g_list_next (node)) {
-    cp = node->data;
-    /* this timestamp is newer that the one we look for */
-    if (timestamp < cp->timestamp) {
-      /* get previous one again */
-      prev_node = g_list_previous (node);
-      break;
-    }
-  }
+  iter =
+      g_sequence_search (self->priv->values, &timestamp,
+      (GCompareDataFunc) gst_control_point_find, NULL);
+
+  /* g_sequence_search() returns the iter where timestamp
+   * would be inserted, i.e. the iter > timestamp, so
+   * we need to get the previous one */
+  iter = g_sequence_iter_prev (iter);
 
-  /* If we have something to return save it as a
-   * potential start position for the next search */
-  if (prev_node)
-    self->priv->last_requested_value = prev_node;
-
-  return prev_node;
-}
+  /* g_sequence_iter_prev () on the begin iter returns
+   * the begin iter. Check if the prev iter is still
+   * after our timestamp, in that case return NULL
+   */
+  cp = g_sequence_get (iter);
+  if (cp->timestamp > timestamp)
+    return NULL;
 
-/*
- * gst_interpolation_control_source_get_first_value:
- * @self: the interpolation control source to search in
- *
- * Find the first value and return it.
- *
- * Returns: the found #GValue or %NULL if there are none.
- */
-static inline GValue *
-gst_interpolation_control_source_get_first_value (GstInterpolationControlSource
-    * self)
-{
-  if (self->priv->values && self->priv->nvalues > 0) {
-    GstControlPoint *cp = self->priv->values->data;
-
-    return &cp->value;
-  } else {
-    return NULL;
-  }
+  /* If the iter is the end iter return NULL as no
+   * data is linked to the end iter */
+  return G_UNLIKELY (g_sequence_iter_is_end (iter)) ? NULL : iter;
 }
 
 /*  steps-like (no-)interpolation, default */
@@ -115,11 +98,11 @@
 _interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
 { \
   GValue *ret; \
-  GList *node; \
+  GSequenceIter *iter; \
   \
-  if ((node = \
-          gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
-    GstControlPoint *cp = node->data; \
+  if ((iter = \
+          gst_interpolation_control_source_find_control_point_iter (self, timestamp))) { \
+    GstControlPoint *cp = g_sequence_get (iter); \
     g##type ret_val = g_value_get_##type (&cp->value); \
     \
     if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
@@ -129,7 +112,7 @@
     else \
       ret = &cp->value; \
   } else { \
-    ret = gst_interpolation_control_source_get_first_value (self); \
+    ret = &self->priv->default_value; \
   } \
   return ret; \
 } \
@@ -161,7 +144,7 @@
   \
   g_mutex_lock (self->lock); \
   for(i = 0; i < value_array->nbsamples; i++) { \
-    ret = _interpolate_none_get_##type (self, timestamp); \
+    ret = _interpolate_none_get_##type (self, ts); \
     if (!ret) { \
       g_mutex_unlock (self->lock); \
       return FALSE; \
@@ -189,17 +172,17 @@
 _interpolate_none_get (GstInterpolationControlSource * self,
     GstClockTime timestamp)
 {
-  GList *node;
+  GSequenceIter *iter;
   GValue *ret;
 
-  if ((node =
-          gst_interpolation_control_source_find_control_point_node (self,
+  if ((iter =
+          gst_interpolation_control_source_find_control_point_iter (self,
               timestamp))) {
-    GstControlPoint *cp = node->data;
+    GstControlPoint *cp = g_sequence_get (iter);
 
     ret = &cp->value;
   } else {
-    ret = gst_interpolation_control_source_get_first_value (self);
+    ret = &self->priv->default_value;
   }
   return ret;
 }
@@ -234,7 +217,7 @@
 
   g_mutex_lock (self->lock);
   for (i = 0; i < value_array->nbsamples; i++) {
-    ret = _interpolate_none_get (self, timestamp);
+    ret = _interpolate_none_get (self, ts);
     if (!ret) {
       g_mutex_unlock (self->lock);
       return FALSE;
@@ -258,7 +241,7 @@
 
   g_mutex_lock (self->lock);
   for (i = 0; i < value_array->nbsamples; i++) {
-    ret = _interpolate_none_get (self, timestamp);
+    ret = _interpolate_none_get (self, ts);
     if (!ret) {
       g_mutex_unlock (self->lock);
       return FALSE;
@@ -282,7 +265,7 @@
 
   g_mutex_lock (self->lock);
   for (i = 0; i < value_array->nbsamples; i++) {
-    ret = _interpolate_none_get (self, timestamp);
+    ret = _interpolate_none_get (self, ts);
     if (!ret) {
       g_mutex_unlock (self->lock);
       return FALSE;
@@ -327,13 +310,13 @@
 static inline GValue * \
 _interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
 { \
-  GList *node; \
+  GSequenceIter *iter; \
   GstControlPoint *cp; \
   \
   /* check if there is a value at the registered timestamp */ \
-  if ((node = \
-          gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
-    cp = node->data; \
+  if ((iter = \
+          gst_interpolation_control_source_find_control_point_iter (self, timestamp))) { \
+    cp = g_sequence_get (iter); \
     if (timestamp == cp->timestamp) { \
       g##type ret = g_value_get_##type (&cp->value); \
       if (g_value_get_##type (&self->priv->minimum_value) > ret) \
@@ -377,7 +360,7 @@
   \
   g_mutex_lock (self->lock); \
   for(i = 0; i < value_array->nbsamples; i++) { \
-    ret = _interpolate_trigger_get_##type (self, timestamp); \
+    ret = _interpolate_trigger_get_##type (self, ts); \
     if (!ret) { \
       g_mutex_unlock (self->lock); \
       return FALSE; \
@@ -406,14 +389,14 @@
 _interpolate_trigger_get (GstInterpolationControlSource * self,
     GstClockTime timestamp)
 {
-  GList *node;
+  GSequenceIter *iter;
   GstControlPoint *cp;
 
   /* check if there is a value at the registered timestamp */
-  if ((node =
-          gst_interpolation_control_source_find_control_point_node (self,
+  if ((iter =
+          gst_interpolation_control_source_find_control_point_iter (self,
               timestamp))) {
-    cp = node->data;
+    cp = g_sequence_get (iter);
     if (timestamp == cp->timestamp) {
       return &cp->value;
     }
@@ -452,7 +435,7 @@
 
   g_mutex_lock (self->lock);
   for (i = 0; i < value_array->nbsamples; i++) {
-    ret = _interpolate_trigger_get (self, timestamp);
+    ret = _interpolate_trigger_get (self, ts);
     if (!ret) {
       g_mutex_unlock (self->lock);
       return FALSE;
@@ -476,7 +459,7 @@
 
   g_mutex_lock (self->lock);
   for (i = 0; i < value_array->nbsamples; i++) {
-    ret = _interpolate_trigger_get (self, timestamp);
+    ret = _interpolate_trigger_get (self, ts);
     if (!ret) {
       g_mutex_unlock (self->lock);
       return FALSE;
@@ -500,7 +483,7 @@
 
   g_mutex_lock (self->lock);
   for (i = 0; i < value_array->nbsamples; i++) {
-    ret = _interpolate_trigger_get (self, timestamp);
+    ret = _interpolate_trigger_get (self, ts);
     if (!ret) {
       g_mutex_unlock (self->lock);
       return FALSE;
@@ -541,51 +524,55 @@
 /*  linear interpolation */
 /*  smoothes inbetween values */
 
-#define DEFINE_LINEAR_GET(type,round,convert) \
+#define DEFINE_LINEAR_GET(vtype,round,convert) \
 static inline gboolean \
-_interpolate_linear_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, g##type *ret) \
+_interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
 { \
-  GList *node; \
+  GSequenceIter *iter; \
+  GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
   \
-  if ((node = gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
-    GstControlPoint *cp1, *cp2; \
+  iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
+  if (iter) { \
+    cp1 = g_sequence_get (iter); \
+    iter = g_sequence_iter_next (iter); \
+    iter = g_sequence_iter_is_end (iter) ? NULL : iter; \
+  } else { \
+    cp.timestamp = G_GUINT64_CONSTANT(0); \
+    g_value_init (&cp.value, self->priv->type); \
+    g_value_copy (&self->priv->default_value, &cp.value); \
+    cp1 = &cp; \
+    if (G_LIKELY (self->priv->values)) \
+      iter = g_sequence_get_begin_iter (self->priv->values); \
+  } \
+  if (iter) { \
+    gdouble slope; \
+    g##vtype value1,value2; \
     \
-    cp1 = node->data; \
-    if ((node = g_list_next (node))) { \
-      gdouble slope; \
-      g##type value1,value2; \
-      \
-      cp2 = node->data; \
-      \
-      value1 = g_value_get_##type (&cp1->value); \
-      value2 = g_value_get_##type (&cp2->value); \
-      slope = (gdouble) convert (value2 - value1) / gst_guint64_to_gdouble (cp2->timestamp - cp1->timestamp); \
-      \
-      if (round) \
-        *ret = (g##type) (convert (value1) + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope + 0.5); \
-      else \
-        *ret = (g##type) (convert (value1) + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope); \
-    } \
-    else { \
-      *ret = g_value_get_##type (&cp1->value); \
-    } \
-  } else { \
-    GValue *first = gst_interpolation_control_source_get_first_value (self); \
-    if (!first) \
-      return FALSE; \
-    *ret = g_value_get_##type (first); \
+    cp2 = g_sequence_get (iter); \
+    \
+    value1 = g_value_get_##vtype (&cp1->value); \
+    value2 = g_value_get_##vtype (&cp2->value); \
+    slope = ((gdouble) convert (value2) - (gdouble) convert (value1)) / gst_guint64_to_gdouble (cp2->timestamp - cp1->timestamp); \
+    \
+    if (round) \
+      *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope + 0.5); \
+    else \
+      *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope); \
   } \
-  *ret = CLAMP (*ret, g_value_get_##type (&self->priv->minimum_value), g_value_get_##type (&self->priv->maximum_value)); \
+  else { \
+    *ret = g_value_get_##vtype (&cp1->value); \
+  } \
+  *ret = CLAMP (*ret, g_value_get_##vtype (&self->priv->minimum_value), g_value_get_##vtype (&self->priv->maximum_value)); \
   return TRUE; \
 } \
 \
 static gboolean \
-interpolate_linear_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
+interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
 { \
-  g##type ret; \
+  g##vtype ret; \
   g_mutex_lock (self->lock); \
-  if (_interpolate_linear_get_##type (self, timestamp, &ret)) { \
-    g_value_set_##type (value, ret); \
+  if (_interpolate_linear_get_##vtype (self, timestamp, &ret)) { \
+    g_value_set_##vtype (value, ret); \
     g_mutex_unlock (self->lock); \
     return TRUE; \
   } \
@@ -594,16 +581,16 @@
 } \
 \
 static gboolean \
-interpolate_linear_get_##type##_value_array (GstInterpolationControlSource *self, \
+interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *self, \
     GstClockTime timestamp, GstValueArray * value_array) \
 { \
   gint i; \
   GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
+  g##vtype *values = (g##vtype *) value_array->values; \
   \
   g_mutex_lock (self->lock); \
   for(i = 0; i < value_array->nbsamples; i++) { \
-    if (! _interpolate_linear_get_##type (self, ts, values)) { \
+    if (! _interpolate_linear_get_##vtype (self, ts, values)) { \
       g_mutex_unlock (self->lock); \
       return FALSE; \
     } \
@@ -621,7 +608,7 @@
 
 DEFINE_LINEAR_GET (ulong, TRUE, EMPTY);
 DEFINE_LINEAR_GET (int64, TRUE, EMPTY);
-DEFINE_LINEAR_GET (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_LINEAR_GET (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_LINEAR_GET (float, FALSE, EMPTY);
 DEFINE_LINEAR_GET (double, FALSE, EMPTY);
 
@@ -667,9 +654,9 @@
  *    .    .    .    .    .
  */
 
-#define DEFINE_CUBIC_GET(type,round, convert) \
+#define DEFINE_CUBIC_GET(vtype,round, convert) \
 static void \
-_interpolate_cubic_update_cache_##type (GstInterpolationControlSource *self) \
+_interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
 { \
   gint i, n = self->priv->nvalues; \
   gdouble *o = g_new0 (gdouble, n); \
@@ -680,24 +667,24 @@
   gdouble *b = g_new0 (gdouble, n); \
   gdouble *z = g_new0 (gdouble, n); \
   \
-  GList *node; \
+  GSequenceIter *iter; \
   GstControlPoint *cp; \
   GstClockTime x_prev, x, x_next; \
-  g##type y_prev, y, y_next; \
+  g##vtype y_prev, y, y_next; \
   \
   /* Fill linear system of equations */ \
-  node = self->priv->values; \
-  cp = node->data; \
+  iter = g_sequence_get_begin_iter (self->priv->values); \
+  cp = g_sequence_get (iter); \
   x = cp->timestamp; \
-  y = g_value_get_##type (&cp->value); \
+  y = g_value_get_##vtype (&cp->value); \
   \
   p[0] = 1.0; \
   \
-  node = node->next; \
-  cp = node->data; \
+  iter = g_sequence_iter_next (iter); \
+  cp = g_sequence_get (iter); \
   x_next = cp->timestamp; \
-  y_next = g_value_get_##type (&cp->value); \
-  h[0] = gst_util_guint64_to_gdouble (x_next - x); \
+  y_next = g_value_get_##vtype (&cp->value); \
+  h[0] = gst_guint64_to_gdouble (x_next - x); \
   \
   for (i = 1; i < n-1; i++) { \
     /* Shuffle x and y values */ \
@@ -705,12 +692,12 @@
     y_prev = y; \
     x = x_next; \
     y = y_next; \
-    node = node->next; \
-    cp = node->data; \
+    iter = g_sequence_iter_next (iter); \
+    cp = g_sequence_get (iter); \
     x_next = cp->timestamp; \
-    y_next = g_value_get_##type (&cp->value); \
+    y_next = g_value_get_##vtype (&cp->value); \
     \
-    h[i] = gst_util_guint64_to_gdouble (x_next - x); \
+    h[i] = gst_guint64_to_gdouble (x_next - x); \
     o[i] = h[i-1]; \
     p[i] = 2.0 * (h[i-1] + h[i]); \
     q[i] = h[i]; \
@@ -732,12 +719,12 @@
   \
   /* Save cache next in the GstControlPoint */ \
   \
-  node = self->priv->values; \
+  iter = g_sequence_get_begin_iter (self->priv->values); \
   for (i = 0; i < n; i++) { \
-    cp = node->data; \
+    cp = g_sequence_get (iter); \
     cp->cache.cubic.h = h[i]; \
     cp->cache.cubic.z = z[i]; \
-    node = node->next; \
+    iter = g_sequence_iter_next (iter); \
   } \
   \
   /* Free our temporary arrays */ \
@@ -750,64 +737,67 @@
 } \
 \
 static inline gboolean \
-_interpolate_cubic_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, g##type *ret) \
+_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
 { \
-  GList *node; \
+  GSequenceIter *iter; \
+  GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
   \
   if (self->priv->nvalues <= 2) \
-    return _interpolate_linear_get_##type (self, timestamp, ret); \
+    return _interpolate_linear_get_##vtype (self, timestamp, ret); \
   \
   if (!self->priv->valid_cache) { \
-    _interpolate_cubic_update_cache_##type (self); \
+    _interpolate_cubic_update_cache_##vtype (self); \
     self->priv->valid_cache = TRUE; \
   } \
   \
-  if ((node = gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
-    GstControlPoint *cp1, *cp2; \
+  iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
+  if (iter) { \
+    cp1 = g_sequence_get (iter); \
+    iter = g_sequence_iter_next (iter); \
+    iter = g_sequence_iter_is_end (iter) ? NULL : iter; \
+  } else { \
+    cp.timestamp = G_GUINT64_CONSTANT(0); \
+    g_value_init (&cp.value, self->priv->type); \
+    g_value_copy (&self->priv->default_value, &cp.value); \
+    cp1 = &cp; \
+    iter = g_sequence_get_begin_iter (self->priv->values); \
+  } \
+  if (iter) { \
+    gdouble diff1, diff2; \
+    g##vtype value1,value2; \
+    gdouble out; \
+    \
+    cp2 = g_sequence_get (iter); \
     \
-    cp1 = node->data; \
-    if ((node = g_list_next (node))) { \
-      gdouble diff1, diff2; \
-      g##type value1,value2; \
-      gdouble out; \
-      \
-      cp2 = node->data; \
-      \
-      value1 = g_value_get_##type (&cp1->value); \
-      value2 = g_value_get_##type (&cp2->value); \
-      \
-      diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); \
-      diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); \
-      \
-      out = (cp2->cache.cubic.z * diff1 * diff1 * diff1 + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; \
-      out += (convert (value2) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \
-      out += (convert (value1) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \
-      \
-      if (round) \
-        *ret = (g##type) (out + 0.5); \
-      else \
-        *ret = (g##type) out; \
-    } \
-    else { \
-      *ret = g_value_get_##type (&cp1->value); \
-    } \
-  } else { \
-    GValue *first = gst_interpolation_control_source_get_first_value (self); \
-    if (!first) \
-      return FALSE; \
-    *ret = g_value_get_##type (first); \
+    value1 = g_value_get_##vtype (&cp1->value); \
+    value2 = g_value_get_##vtype (&cp2->value); \
+    \
+    diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); \
+    diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); \
+    \
+    out = (cp2->cache.cubic.z * diff1 * diff1 * diff1 + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; \
+    out += (convert (value2) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \
+    out += (convert (value1) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \
+    \
+    if (round) \
+      *ret = (g##vtype) (out + 0.5); \
+    else \
+      *ret = (g##vtype) out; \
   } \
-  *ret = CLAMP (*ret, g_value_get_##type (&self->priv->minimum_value), g_value_get_##type (&self->priv->maximum_value)); \
+  else { \
+    *ret = g_value_get_##vtype (&cp1->value); \
+  } \
+  *ret = CLAMP (*ret, g_value_get_##vtype (&self->priv->minimum_value), g_value_get_##vtype (&self->priv->maximum_value)); \
   return TRUE; \
 } \
 \
 static gboolean \
-interpolate_cubic_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
+interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
 { \
-  g##type ret; \
+  g##vtype ret; \
   g_mutex_lock (self->lock); \
-  if (_interpolate_cubic_get_##type (self, timestamp, &ret)) { \
-    g_value_set_##type (value, ret); \
+  if (_interpolate_cubic_get_##vtype (self, timestamp, &ret)) { \
+    g_value_set_##vtype (value, ret); \
     g_mutex_unlock (self->lock); \
     return TRUE; \
   } \
@@ -816,16 +806,16 @@
 } \
 \
 static gboolean \
-interpolate_cubic_get_##type##_value_array (GstInterpolationControlSource *self, \
+interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self, \
     GstClockTime timestamp, GstValueArray * value_array) \
 { \
   gint i; \
   GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
+  g##vtype *values = (g##vtype *) value_array->values; \
   \
   g_mutex_lock (self->lock); \
   for(i = 0; i < value_array->nbsamples; i++) { \
-    if (! _interpolate_cubic_get_##type (self, ts, values)) { \
+    if (! _interpolate_cubic_get_##vtype (self, ts, values)) { \
       g_mutex_unlock (self->lock); \
       return FALSE; \
     } \
@@ -843,7 +833,7 @@
 
 DEFINE_CUBIC_GET (ulong, TRUE, EMPTY);
 DEFINE_CUBIC_GET (int64, TRUE, EMPTY);
-DEFINE_CUBIC_GET (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_CUBIC_GET (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_CUBIC_GET (float, FALSE, EMPTY);
 DEFINE_CUBIC_GET (double, FALSE, EMPTY);
 
@@ -872,9 +862,8 @@
   (GstControlSourceGetValueArray) NULL
 };
 
-
 /*  register all interpolation methods */
-GstInterpolateMethod *interpolation_methods[] = {
+GstInterpolateMethod *priv_gst_interpolation_methods[] = {
   &interpolate_none,
   &interpolate_trigger,
   &interpolate_linear,
@@ -882,4 +871,5 @@
   &interpolate_cubic
 };
 
-guint num_interpolation_methods = G_N_ELEMENTS (interpolation_methods);
+guint priv_gst_num_interpolation_methods =
+G_N_ELEMENTS (priv_gst_interpolation_methods);
--- a/gstreamer_core/libs/gst/controller/gstinterpolationcontrolsource.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstinterpolationcontrolsource.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,6 +1,6 @@
 /* GStreamer
  *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * gstinterpolationcontrolsource.c: Control source that provides several
  *                                  interpolation methods
@@ -43,13 +43,12 @@
 #include "gstcontrolsource.h"
 #include "gstinterpolationcontrolsource.h"
 #include "gstinterpolationcontrolsourceprivate.h"
-
 #ifdef __SYMBIAN32__
 #include <glib_global.h>
 #include <gobject_global.h>
 #endif
-extern GstInterpolateMethod *interpolation_methods[];
-extern guint num_interpolation_methods;
+#define GST_CAT_DEFAULT controller_debug
+GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
 
 static void gst_interpolation_control_source_init (GstInterpolationControlSource
     * self);
@@ -75,7 +74,7 @@
   g_return_if_fail (cp);
 
   g_value_unset (&cp->value);
-  g_free (cp);
+  g_slice_free (GstControlPoint, cp);
 }
 
 static void
@@ -96,13 +95,11 @@
     g_value_unset (&self->priv->maximum_value);
 
   if (self->priv->values) {
-    g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
-    g_list_free (self->priv->values);
+    g_sequence_free (self->priv->values);
     self->priv->values = NULL;
   }
 
   self->priv->nvalues = 0;
-  self->priv->last_requested_value = NULL;
   self->priv->valid_cache = FALSE;
 }
 
@@ -135,17 +132,21 @@
  *
  * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
  */
+/* *INDENT-OFF* */
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
 
 gboolean
-    gst_interpolation_control_source_set_interpolation_mode
-    (GstInterpolationControlSource * self, GstInterpolateMode mode) {
+gst_interpolation_control_source_set_interpolation_mode (
+    GstInterpolationControlSource * self, GstInterpolateMode mode)
+/* *INDENT-ON* */
+{
   gboolean ret = TRUE;
   GstControlSource *csource = GST_CONTROL_SOURCE (self);
 
-  if (mode >= num_interpolation_methods || interpolation_methods[mode] == NULL) {
+  if (mode >= priv_gst_num_interpolation_methods
+      || priv_gst_interpolation_methods[mode] == NULL) {
     GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
     return FALSE;
   }
@@ -163,68 +164,68 @@
   g_mutex_lock (self->lock);
   switch (self->priv->base) {
     case G_TYPE_INT:
-      csource->get_value = interpolation_methods[mode]->get_int;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
       csource->get_value_array =
-          interpolation_methods[mode]->get_int_value_array;
+          priv_gst_interpolation_methods[mode]->get_int_value_array;
       break;
     case G_TYPE_UINT:{
-      csource->get_value = interpolation_methods[mode]->get_uint;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
       csource->get_value_array =
-          interpolation_methods[mode]->get_uint_value_array;
+          priv_gst_interpolation_methods[mode]->get_uint_value_array;
       break;
     }
     case G_TYPE_LONG:{
-      csource->get_value = interpolation_methods[mode]->get_long;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
       csource->get_value_array =
-          interpolation_methods[mode]->get_long_value_array;
+          priv_gst_interpolation_methods[mode]->get_long_value_array;
       break;
     }
     case G_TYPE_ULONG:{
-      csource->get_value = interpolation_methods[mode]->get_ulong;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
       csource->get_value_array =
-          interpolation_methods[mode]->get_ulong_value_array;
+          priv_gst_interpolation_methods[mode]->get_ulong_value_array;
       break;
     }
     case G_TYPE_INT64:{
-      csource->get_value = interpolation_methods[mode]->get_int64;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
       csource->get_value_array =
-          interpolation_methods[mode]->get_int64_value_array;
+          priv_gst_interpolation_methods[mode]->get_int64_value_array;
       break;
     }
     case G_TYPE_UINT64:{
-      csource->get_value = interpolation_methods[mode]->get_uint64;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
       csource->get_value_array =
-          interpolation_methods[mode]->get_uint64_value_array;
+          priv_gst_interpolation_methods[mode]->get_uint64_value_array;
       break;
     }
     case G_TYPE_FLOAT:{
-      csource->get_value = interpolation_methods[mode]->get_float;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
       csource->get_value_array =
-          interpolation_methods[mode]->get_float_value_array;
+          priv_gst_interpolation_methods[mode]->get_float_value_array;
       break;
     }
     case G_TYPE_DOUBLE:{
-      csource->get_value = interpolation_methods[mode]->get_double;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
       csource->get_value_array =
-          interpolation_methods[mode]->get_double_value_array;
+          priv_gst_interpolation_methods[mode]->get_double_value_array;
       break;
     }
     case G_TYPE_BOOLEAN:{
-      csource->get_value = interpolation_methods[mode]->get_boolean;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
       csource->get_value_array =
-          interpolation_methods[mode]->get_boolean_value_array;
+          priv_gst_interpolation_methods[mode]->get_boolean_value_array;
       break;
     }
     case G_TYPE_ENUM:{
-      csource->get_value = interpolation_methods[mode]->get_enum;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
       csource->get_value_array =
-          interpolation_methods[mode]->get_enum_value_array;
+          priv_gst_interpolation_methods[mode]->get_enum_value_array;
       break;
     }
     case G_TYPE_STRING:{
-      csource->get_value = interpolation_methods[mode]->get_string;
+      csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
       csource->get_value_array =
-          interpolation_methods[mode]->get_string_value_array;
+          priv_gst_interpolation_methods[mode]->get_string_value_array;
       break;
     }
     default:
@@ -429,34 +430,61 @@
   return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
 }
 
+static GstControlPoint *
+_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
+    GValue * value)
+{
+  GstControlPoint *cp;
+
+  /* create a new GstControlPoint */
+  cp = g_slice_new0 (GstControlPoint);
+  cp->timestamp = timestamp;
+  g_value_init (&cp->value, self->priv->type);
+  g_value_copy (value, &cp->value);
+
+  return cp;
+}
+
 static void
 gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
     self, GstClockTime timestamp, GValue * value)
 {
-  GstControlPoint *cp;
-  GList *node;
+  GSequenceIter *iter;
 
   /* check if a control point for the timestamp already exists */
-  if ((node = g_list_find_custom (self->priv->values, &timestamp,
-              gst_control_point_find))) {
-    cp = node->data;
-    g_value_reset (&cp->value);
-    g_value_copy (value, &cp->value);
+
+  /* iter contains the iter right *after* timestamp */
+  if (G_LIKELY (self->priv->values)) {
+    iter =
+        g_sequence_search (self->priv->values, &timestamp,
+        (GCompareDataFunc) gst_control_point_find, NULL);
+    if (iter) {
+      GSequenceIter *prev = g_sequence_iter_prev (iter);
+      GstControlPoint *cp = g_sequence_get (prev);
+
+      /* If the timestamp is the same just update the control point value */
+      if (cp->timestamp == timestamp) {
+        /* update control point */
+        g_value_reset (&cp->value);
+        g_value_copy (value, &cp->value);
+        goto done;
+      }
+    }
   } else {
-    /* create a new GstControlPoint */
-    cp = g_new0 (GstControlPoint, 1);
-    cp->timestamp = timestamp;
-    g_value_init (&cp->value, self->priv->type);
-    g_value_copy (value, &cp->value);
-    /* and sort it into the prop->values list */
     self->priv->values =
-        g_list_insert_sorted (self->priv->values, cp,
-        gst_control_point_compare);
-    self->priv->nvalues++;
+        g_sequence_new ((GDestroyNotify) gst_control_point_free);
   }
+
+  /* sort new cp into the prop->values list */
+  g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp,
+          value), (GCompareDataFunc) gst_control_point_compare, NULL);
+  self->priv->nvalues++;
+
+done:
   self->priv->valid_cache = FALSE;
 }
 
+
 /**
  * gst_interpolation_control_source_set:
  * @self: the #GstInterpolationControlSource object
@@ -549,7 +577,7 @@
 gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
     GstClockTime timestamp)
 {
-  GList *node;
+  GSequenceIter *iter;
   gboolean res = FALSE;
 
   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
@@ -557,23 +585,22 @@
 
   g_mutex_lock (self->lock);
   /* check if a control point for the timestamp exists */
-  if ((node = g_list_find_custom (self->priv->values, &timestamp,
-              gst_control_point_find))) {
-    GstControlPoint *cp = node->data;
+  if ((iter =
+          g_sequence_search (self->priv->values, &timestamp,
+              (GCompareDataFunc) gst_control_point_find, NULL))) {
+    GstControlPoint *cp;
 
-    if (cp->timestamp == 0) {
-      /* Restore the default node */
-      g_value_reset (&cp->value);
-      g_value_copy (&self->priv->default_value, &cp->value);
-    } else {
-      if (node == self->priv->last_requested_value)
-        self->priv->last_requested_value = NULL;
-      gst_control_point_free (node->data);      /* free GstControlPoint */
-      self->priv->values = g_list_delete_link (self->priv->values, node);
+    /* Iter contains the iter right after timestamp, i.e.
+     * we need to get the previous one and check the timestamp
+     */
+    iter = g_sequence_iter_prev (iter);
+    cp = g_sequence_get (iter);
+    if (cp->timestamp == timestamp) {
+      g_sequence_remove (iter);
       self->priv->nvalues--;
+      self->priv->valid_cache = FALSE;
+      res = TRUE;
     }
-    self->priv->valid_cache = FALSE;
-    res = TRUE;
   }
   g_mutex_unlock (self->lock);
 
@@ -599,16 +626,22 @@
 
   g_mutex_lock (self->lock);
   /* free GstControlPoint structures */
-  g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
-  g_list_free (self->priv->values);
-  self->priv->last_requested_value = NULL;
-  self->priv->values = NULL;
+  if (self->priv->values) {
+    g_sequence_free (self->priv->values);
+    self->priv->values = NULL;
+  }
   self->priv->nvalues = 0;
   self->priv->valid_cache = FALSE;
 
   g_mutex_unlock (self->lock);
 }
 
+static void
+_append_control_point (GstControlPoint * cp, GList ** l)
+{
+  *l = g_list_prepend (*l, cp);
+}
+
 /**
  * gst_interpolation_control_source_get_all:
  * @self: the #GstInterpolationControlSource to get the list from
@@ -630,11 +663,12 @@
   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
 
   g_mutex_lock (self->lock);
-  if (self->priv->values)
-    res = g_list_copy (self->priv->values);
+  if (G_LIKELY (self->priv->values))
+    g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
+        &res);
   g_mutex_unlock (self->lock);
 
-  return res;
+  return g_list_reverse (res);
 }
 
 /**
--- a/gstreamer_core/libs/gst/controller/gstinterpolationcontrolsourceprivate.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstinterpolationcontrolsourceprivate.h	Fri Apr 16 15:15:52 2010 +0300
@@ -90,11 +90,13 @@
   GValue maximum_value;         /* max value for the handled property */
   GstInterpolateMode interpolation_mode;
   
-  GList *values;                /* List of GstControlPoint */
+  GSequence *values;            /* List of GstControlPoint */
   gint nvalues;                 /* Number of control points */
-  GList *last_requested_value;  /* last search result, can be used for incremental searches */
   gboolean valid_cache;
 };
 
+extern GstInterpolateMethod *priv_gst_interpolation_methods[];
+extern guint priv_gst_num_interpolation_methods;
+
 #endif /* __GST_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__ */
 
--- a/gstreamer_core/libs/gst/controller/gstlfocontrolsource.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/gstlfocontrolsource.c	Fri Apr 16 15:15:52 2010 +0300
@@ -77,7 +77,7 @@
   gdouble off = convert (g_value_get_##type (&self->priv->offset)); \
   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, self->priv->period); \
   \
-  ret = sin (2.0 * M_PI * (self->priv->frequency / GST_SECOND) * gst_util_guint64_to_gdouble (pos)); \
+  ret = sin (2.0 * M_PI * (self->priv->frequency / GST_SECOND) * gst_guint64_to_gdouble (pos)); \
   ret *= amp; \
   ret += off; \
   \
@@ -123,7 +123,7 @@
 
 DEFINE_SINE (ulong, TRUE, EMPTY);
 DEFINE_SINE (int64, TRUE, EMPTY);
-DEFINE_SINE (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_SINE (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_SINE (float, FALSE, EMPTY);
 DEFINE_SINE (double, FALSE, EMPTY);
 
@@ -209,7 +209,7 @@
 
 DEFINE_SQUARE (ulong, TRUE, EMPTY);
 DEFINE_SQUARE (int64, TRUE, EMPTY);
-DEFINE_SQUARE (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_SQUARE (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_SQUARE (float, FALSE, EMPTY);
 DEFINE_SQUARE (double, FALSE, EMPTY);
 
@@ -245,7 +245,7 @@
   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
   gdouble ret; \
   \
-  ret = - ((gst_util_guint64_to_gdouble (pos) - gst_util_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_util_guint64_to_gdouble (period)));\
+  ret = - ((gst_guint64_to_gdouble (pos) - gst_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_guint64_to_gdouble (period)));\
   \
   ret += off; \
   \
@@ -292,7 +292,7 @@
 
 DEFINE_SAW (ulong, TRUE, EMPTY);
 DEFINE_SAW (int64, TRUE, EMPTY);
-DEFINE_SAW (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_SAW (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_SAW (float, FALSE, EMPTY);
 DEFINE_SAW (double, FALSE, EMPTY);
 
@@ -328,7 +328,7 @@
   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
   gdouble ret; \
   \
-  ret = ((gst_util_guint64_to_gdouble (pos) - gst_util_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_util_guint64_to_gdouble (period)));\
+  ret = ((gst_guint64_to_gdouble (pos) - gst_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_guint64_to_gdouble (period)));\
   \
   ret += off; \
   \
@@ -375,7 +375,7 @@
 
 DEFINE_RSAW (ulong, TRUE, EMPTY);
 DEFINE_RSAW (int64, TRUE, EMPTY);
-DEFINE_RSAW (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_RSAW (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_RSAW (float, FALSE, EMPTY);
 DEFINE_RSAW (double, FALSE, EMPTY);
 
@@ -411,12 +411,12 @@
   GstClockTime pos = _calculate_pos (timestamp, self->priv->timeshift, period); \
   gdouble ret; \
   \
-  if (gst_util_guint64_to_gdouble (pos) <= gst_util_guint64_to_gdouble (period) / 4.0) \
-    ret = gst_util_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_util_guint64_to_gdouble (period)); \
-  else if (gst_util_guint64_to_gdouble (pos) <= (3.0 * gst_util_guint64_to_gdouble (period)) / 4.0) \
-    ret = -(gst_util_guint64_to_gdouble (pos) - gst_util_guint64_to_gdouble (period) / 2.0) * ((4.0 * amp) / gst_util_guint64_to_gdouble (period)); \
+  if (gst_guint64_to_gdouble (pos) <= gst_guint64_to_gdouble (period) / 4.0) \
+    ret = gst_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_guint64_to_gdouble (period)); \
+  else if (gst_guint64_to_gdouble (pos) <= (3.0 * gst_guint64_to_gdouble (period)) / 4.0) \
+    ret = -(gst_guint64_to_gdouble (pos) - gst_guint64_to_gdouble (period) / 2.0) * ((4.0 * amp) / gst_guint64_to_gdouble (period)); \
   else \
-    ret = gst_util_guint64_to_gdouble (period) - gst_util_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_util_guint64_to_gdouble (period)); \
+    ret = gst_guint64_to_gdouble (period) - gst_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_guint64_to_gdouble (period)); \
   \
   ret += off; \
   \
@@ -463,7 +463,7 @@
 
 DEFINE_TRIANGLE (ulong, TRUE, EMPTY);
 DEFINE_TRIANGLE (int64, TRUE, EMPTY);
-DEFINE_TRIANGLE (uint64, TRUE, gst_util_guint64_to_gdouble);
+DEFINE_TRIANGLE (uint64, TRUE, gst_guint64_to_gdouble);
 DEFINE_TRIANGLE (float, FALSE, EMPTY);
 DEFINE_TRIANGLE (double, FALSE, EMPTY);
 
@@ -1038,7 +1038,8 @@
    **/
   g_object_class_install_property (gobject_class, PROP_WAVEFORM,
       g_param_spec_enum ("waveform", "Waveform", "Waveform",
-          GST_TYPE_LFO_WAVEFORM, GST_LFO_WAVEFORM_SINE, G_PARAM_READWRITE));
+          GST_TYPE_LFO_WAVEFORM, GST_LFO_WAVEFORM_SINE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:frequency
@@ -1051,7 +1052,7 @@
   g_object_class_install_property (gobject_class, PROP_FREQUENCY,
       g_param_spec_double ("frequency", "Frequency",
           "Frequency of the waveform", 0.0, G_MAXDOUBLE, 1.0,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:timeshift
@@ -1066,7 +1067,7 @@
   g_object_class_install_property (gobject_class, PROP_TIMESHIFT,
       g_param_spec_uint64 ("timeshift", "Timeshift",
           "Timeshift of the waveform to the right", 0, G_MAXUINT64, 0,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:amplitude
@@ -1078,7 +1079,7 @@
    **/
   g_object_class_install_property (gobject_class, PROP_AMPLITUDE,
       g_param_spec_boxed ("amplitude", "Amplitude", "Amplitude of the waveform",
-          G_TYPE_VALUE, G_PARAM_READWRITE));
+          G_TYPE_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:offset
@@ -1090,5 +1091,5 @@
    **/
   g_object_class_install_property (gobject_class, PROP_OFFSET,
       g_param_spec_boxed ("offset", "Offset", "Offset of the waveform",
-          G_TYPE_VALUE, G_PARAM_READWRITE));
+          G_TYPE_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
--- a/gstreamer_core/libs/gst/controller/lib.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/controller/lib.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,6 +24,7 @@
 #  include "config.h"
 #endif
 #include <gst/gst.h>
+#include <gst/controller/gstcontroller.h>
 
 /* library initialisation */
 
@@ -43,7 +44,6 @@
 #ifdef __SYMBIAN32__
 EXPORT_C
 #endif
- 
 gboolean
 gst_controller_init (int *argc, char ***argv)
 {
--- a/gstreamer_core/libs/gst/dataprotocol/dataprotocol.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/dataprotocol/dataprotocol.c	Fri Apr 16 15:15:52 2010 +0300
@@ -85,7 +85,7 @@
 
 /* helper macros */
 
-/* write first 6 bytes of header, as well as ABI padding */
+/* write first 6 bytes of header */
 #define GST_DP_INIT_HEADER(h, version, flags, type)		\
 G_STMT_START {							\
   gint maj = 0, min = 0;					\
@@ -98,9 +98,6 @@
   h[2] = (guint8) flags;					\
   h[3] = 0; /* padding byte */					\
   GST_WRITE_UINT16_BE (h + 4, type);				\
-								\
-  GST_WRITE_UINT64_BE (h + 42, (guint64) 0); /* ABI padding */	\
-  GST_WRITE_UINT64_BE (h + 50, (guint64) 0); /* ABI padding */	\
 } G_STMT_END
 
 #define GST_DP_SET_CRC(h, flags, payload, length);		\
@@ -131,7 +128,6 @@
 
 /*** HELPER FUNCTIONS ***/
 
-
 static gboolean
 gst_dp_header_from_buffer_any (const GstBuffer * buffer, GstDPHeaderFlag flags,
     guint * length, guint8 ** header, GstDPVersion version)
@@ -225,7 +221,8 @@
 #if defined(__WINSCW__) || defined(__WINS__)
   /* version, flags, type */
   GST_DP_INIT_HEADER (h, version, flags, GST_DP_PAYLOAD_CAPS);
-  
+
+  /* buffer properties */
   GST_WRITE_UINT32_BE (h + 6, payload_length);
   GST_WRITE_UINT64_BE (h + 10, (guint64) 0);
   GST_WRITE_UINT64_BE (h + 18, (guint64) 0);
@@ -600,7 +597,6 @@
       GST_DP_PAYLOAD_EVENT_NONE + GST_EVENT_TYPE (event));
 
   /* length */
-  
   GST_WRITE_UINT32_BE (h + 6, (guint32) pl_length);
   /* timestamp */
   GST_WRITE_UINT64_BE (h + 10, GST_EVENT_TIMESTAMP (event));
@@ -679,7 +675,7 @@
   /* timestamp */
   GST_WRITE_UINT64_BE (h + 10, GST_EVENT_TIMESTAMP (event));
 
-  GST_DP_SET_CRC (h, flags, *payload, pl_length);
+  GST_DP_SET_CRC (h, flags, string, pl_length);
 
   GST_LOG ("created header from event:");
   gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH);
@@ -697,7 +693,7 @@
     tmp = tmp + 10;
     GST_WRITE_UINT64_BE (tmp, GST_EVENT_TIMESTAMP (event));
 
-    GST_DP_SET_CRC ((guint8 *)h, flags, *payload, pl_length);
+    GST_DP_SET_CRC ((guint8 *)h, flags, string, pl_length);
 
     GST_LOG ("created header from event:");
     gst_dp_dump_byte_array ((guint8 *)h, GST_DP_HEADER_LENGTH);
--- a/gstreamer_core/libs/gst/net/gstnetclientclock.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/net/gstnetclientclock.c	Fri Apr 16 15:15:52 2010 +0300
@@ -143,11 +143,12 @@
   g_object_class_install_property (gobject_class, PROP_ADDRESS,
       g_param_spec_string ("address", "address",
           "The address of the machine providing a time server, "
-          "as a dotted quad (x.x.x.x)", DEFAULT_ADDRESS, G_PARAM_READWRITE));
+          "as a dotted quad (x.x.x.x)", DEFAULT_ADDRESS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PORT,
       g_param_spec_int ("port", "port",
           "The port on which the remote server is listening", 0, G_MAXUINT16,
-          DEFAULT_PORT, G_PARAM_READWRITE));
+          DEFAULT_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
--- a/gstreamer_core/libs/gst/net/gstnettimepacket.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/net/gstnettimepacket.c	Fri Apr 16 15:15:52 2010 +0300
@@ -138,7 +138,11 @@
   gint ret;
 
   while (TRUE) {
+#ifdef G_OS_WIN32
+    ret = recvfrom (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE,
+#else
     ret = recvfrom (fd, buffer, GST_NET_TIME_PACKET_SIZE,
+#endif
         0, (struct sockaddr *) addr, len);
     if (ret < 0) {
       if (errno != EAGAIN && errno != EINTR)
@@ -213,10 +217,13 @@
 
 #ifdef G_OS_WIN32
   ioctlsocket (fd, FIONBIO, &flags);    /* Set nonblocking mode */
+  ret =
+      sendto (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr,
+      len);
+#else
+  ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr, len);
 #endif
 
-  ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr, len);
-
 #ifdef __CYGWIN__
   fcntl (fd, F_SETFL, fdflags);
 #endif
--- a/gstreamer_core/libs/gst/net/gstnettimepacket.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/net/gstnettimepacket.h	Fri Apr 16 15:15:52 2010 +0300
@@ -32,6 +32,9 @@
 #ifdef G_OS_WIN32
 #include <winsock2.h>
 #include <ws2tcpip.h>
+#ifndef socklen_t
+#define socklen_t int
+#endif
 #else
 #include <netdb.h>
 #include <sys/socket.h>
--- a/gstreamer_core/libs/gst/net/gstnettimeprovider.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/net/gstnettimeprovider.c	Fri Apr 16 15:15:52 2010 +0300
@@ -147,19 +147,19 @@
   g_object_class_install_property (gobject_class, PROP_PORT,
       g_param_spec_int ("port", "port",
           "The port to receive the packets from, 0=allocate", 0, G_MAXUINT16,
-          DEFAULT_PORT, G_PARAM_READWRITE));
+          DEFAULT_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_ADDRESS,
       g_param_spec_string ("address", "address",
           "The address to bind on, as a dotted quad (x.x.x.x)",
-          DEFAULT_ADDRESS, G_PARAM_READWRITE));
+          DEFAULT_ADDRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_CLOCK,
       g_param_spec_object ("clock", "Clock",
           "The clock to export over the network", GST_TYPE_CLOCK,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_ACTIVE,
       g_param_spec_boolean ("active", "Active",
           "TRUE if the clock will respond to queries over the network", TRUE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -314,7 +314,7 @@
           (GstObject *) g_value_get_object (value));
       break;
     case PROP_ACTIVE:
-      gst_atomic_int_set (&self->active.active, g_value_get_boolean (value));
+      g_atomic_int_set (&self->active.active, g_value_get_boolean (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -384,7 +384,13 @@
     goto bind_error;
 
   len = sizeof (my_addr);
+#ifdef G_OS_WIN32
+  ret =
+      getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr,
+      (gint *) & len);
+#else
   ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr, &len);
+#endif
   if (ret < 0)
     goto getsockname_error;
 
--- a/gstreamer_core/plugins/elements/gstcapsfilter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstcapsfilter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,9 +21,8 @@
  */
 /**
  * SECTION:element-capsfilter
- * @short_description: pass data though unmodified, but enforces format limmits
  *
- * The element does not modify data as such, but can enforce limmitations on the
+ * The element does not modify data as such, but can enforce limitations on the
  * data format.
  */
 
@@ -36,10 +35,7 @@
 #endif
 #include "../../gst/gst-i18n-lib.h"
 #include "gstcapsfilter.h"
-
-#ifdef __SYMBIAN32__
-#include <gstelement.h>
-#endif
+#include <glib_global.h>
 enum
 {
   PROP_0,
@@ -74,6 +70,7 @@
 static void gst_capsfilter_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_capsfilter_dispose (GObject * object);
+
 static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps);
 static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
@@ -115,7 +112,8 @@
       g_param_spec_boxed ("caps", _("Filter caps"),
           _("Restrict the possible allowed capabilities (NULL means ANY). "
               "Setting this property takes a reference to the supplied GstCaps "
-              "object."), GST_TYPE_CAPS, G_PARAM_READWRITE));
+              "object."), GST_TYPE_CAPS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
   trans_class->transform_caps = gst_capsfilter_transform_caps;
@@ -127,9 +125,19 @@
 static void
 gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
 {
+  GstBaseTransform *trans = GST_BASE_TRANSFORM (filter);
+  gst_base_transform_set_gap_aware (trans, TRUE);
   filter->filter_caps = gst_caps_new_any ();
 }
 
+static gboolean
+copy_func (GQuark field_id, const GValue * value, GstStructure * dest)
+{
+  gst_structure_id_set_value (dest, field_id, value);
+
+  return TRUE;
+}
+
 static void
 gst_capsfilter_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -139,7 +147,7 @@
   switch (prop_id) {
     case PROP_FILTER_CAPS:{
       GstCaps *new_caps;
-      GstCaps *old_caps;
+      GstCaps *old_caps, *suggest, *nego;
       const GstCaps *new_caps_val = gst_value_get_caps (value);
 
       if (new_caps_val == NULL) {
@@ -149,15 +157,60 @@
         gst_caps_ref (new_caps);
       }
 
+      GST_OBJECT_LOCK (capsfilter);
       old_caps = capsfilter->filter_caps;
       capsfilter->filter_caps = new_caps;
+      GST_OBJECT_UNLOCK (capsfilter);
+
       gst_caps_unref (old_caps);
 
       GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
 
-      /* FIXME: Need to activate these caps on the pads
-       * http://bugzilla.gnome.org/show_bug.cgi?id=361718
-       */
+      /* filter the currently negotiated format against the new caps */
+      GST_OBJECT_LOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
+      nego = GST_PAD_CAPS (GST_BASE_TRANSFORM_SINK_PAD (object));
+      if (nego) {
+        GST_DEBUG_OBJECT (capsfilter, "we had negotiated caps %" GST_PTR_FORMAT,
+            nego);
+
+        if (G_UNLIKELY (gst_caps_is_any (new_caps))) {
+          GST_DEBUG_OBJECT (capsfilter, "not settings any suggestion");
+
+          suggest = NULL;
+        } else {
+          GstStructure *s1, *s2;
+
+          /* first check if the name is the same */
+          s1 = gst_caps_get_structure (nego, 0);
+          s2 = gst_caps_get_structure (new_caps, 0);
+
+          if (gst_structure_get_name_id (s1) == gst_structure_get_name_id (s2)) {
+            /* same name, copy all fields from the new caps into the previously
+             * negotiated caps */
+            suggest = gst_caps_copy (nego);
+            s1 = gst_caps_get_structure (suggest, 0);
+            gst_structure_foreach (s2, (GstStructureForeachFunc) copy_func, s1);
+            GST_DEBUG_OBJECT (capsfilter, "copied structure fields");
+          } else {
+            GST_DEBUG_OBJECT (capsfilter, "different structure names");
+            /* different names, we can only suggest the complete caps */
+            suggest = gst_caps_copy (new_caps);
+          }
+        }
+      } else {
+        GST_DEBUG_OBJECT (capsfilter, "no negotiated caps");
+        /* no previous caps, the getcaps function will be used to find suitable
+         * caps */
+        suggest = NULL;
+      }
+      GST_OBJECT_UNLOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
+
+      GST_DEBUG_OBJECT (capsfilter, "suggesting new caps %" GST_PTR_FORMAT,
+          suggest);
+      gst_base_transform_suggest (GST_BASE_TRANSFORM (object), suggest, 0);
+      if (suggest)
+        gst_caps_unref (suggest);
+
       break;
     }
     default:
@@ -174,7 +227,9 @@
 
   switch (prop_id) {
     case PROP_FILTER_CAPS:
+      GST_OBJECT_LOCK (capsfilter);
       gst_value_set_caps (value, capsfilter->filter_caps);
+      GST_OBJECT_UNLOCK (capsfilter);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -197,9 +252,18 @@
     GstPadDirection direction, GstCaps * caps)
 {
   GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
-  GstCaps *ret;
+  GstCaps *ret, *filter_caps;
+
+  GST_OBJECT_LOCK (capsfilter);
+  filter_caps = gst_caps_ref (capsfilter->filter_caps);
+  GST_OBJECT_UNLOCK (capsfilter);
 
-  ret = gst_caps_intersect (caps, capsfilter->filter_caps);
+  ret = gst_caps_intersect (caps, filter_caps);
+  GST_DEBUG_OBJECT (capsfilter, "input:     %" GST_PTR_FORMAT, caps);
+  GST_DEBUG_OBJECT (capsfilter, "filter:    %" GST_PTR_FORMAT, filter_caps);
+  GST_DEBUG_OBJECT (capsfilter, "intersect: %" GST_PTR_FORMAT, ret);
+
+  gst_caps_unref (filter_caps);
 
   return ret;
 }
@@ -237,10 +301,11 @@
 gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
     gint size, GstCaps * caps, GstBuffer ** buf)
 {
+  GstFlowReturn ret = GST_FLOW_OK;
+
   if (GST_BUFFER_CAPS (input) != NULL) {
     /* Output buffer already has caps */
-    GST_DEBUG_OBJECT (trans,
-        "Input buffer already has caps (implicitely fixed)");
+    GST_LOG_OBJECT (trans, "Input buffer already has caps (implicitely fixed)");
     /* FIXME : Move this behaviour to basetransform. The given caps are the ones
      * of the source pad, therefore our outgoing buffers should always have
      * those caps. */
@@ -278,11 +343,19 @@
       if (GST_PAD_CAPS (trans->srcpad) == NULL)
         gst_pad_set_caps (trans->srcpad, out_caps);
     } else {
-      GST_DEBUG_OBJECT (trans, "Have unfixed output caps %" GST_PTR_FORMAT,
-          out_caps);
+      gchar *caps_str = gst_caps_to_string (out_caps);
+
+      GST_DEBUG_OBJECT (trans, "Cannot choose caps. Have unfixed output caps %"
+          GST_PTR_FORMAT, out_caps);
       gst_caps_unref (out_caps);
+
+      ret = GST_FLOW_ERROR;
+      GST_ELEMENT_ERROR (trans, STREAM, FORMAT,
+          ("Filter caps do not completely specify the output format"),
+          ("Output caps are unfixed: %s", caps_str));
+      g_free (caps_str);
     }
   }
 
-  return GST_FLOW_OK;
+  return ret;
 }
--- a/gstreamer_core/plugins/elements/gstelements.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstelements.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,9 +25,6 @@
 #  include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 #include <gst/gst.h>
 
 #include "gstcapsfilter.h"
--- a/gstreamer_core/plugins/elements/gstfakesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfakesink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,7 +21,6 @@
  */
 /**
  * SECTION:element-fakesink
- * @short_description: black hole for data
  * @see_also: #GstFakeSrc
  *
  * Dummy sink that swallows everything.
@@ -30,18 +29,9 @@
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include "gstfakesink.h"
 #include <gst/gstmarshal.h>
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-
-#include <gstelement.h>
-#endif
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -123,6 +113,7 @@
     const GValue * value, GParamSpec * pspec);
 static void gst_fake_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
+static void gst_fake_sink_finalize (GObject * obj);
 
 static GstStateChangeReturn gst_fake_sink_change_state (GstElement * element,
     GstStateChange transition);
@@ -136,6 +127,34 @@
 static guint gst_fake_sink_signals[LAST_SIGNAL] = { 0 };
 
 static void
+marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
+    guint n_param_values, const GValue * param_values, gpointer invocation_hint,
+    gpointer marshal_data)
+{
+  typedef void (*marshalfunc_VOID__MINIOBJECT_OBJECT) (gpointer obj,
+      gpointer arg1, gpointer arg2, gpointer data2);
+  register marshalfunc_VOID__MINIOBJECT_OBJECT callback;
+  register GCClosure *cc = (GCClosure *) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback =
+      (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data :
+      cc->callback);
+
+  callback (data1, gst_value_get_mini_object (param_values + 1),
+      g_value_get_object (param_values + 2), data2);
+}
+
+static void
 gst_fake_sink_base_init (gpointer g_class)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
@@ -164,40 +183,41 @@
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fake_sink_set_property);
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fake_sink_get_property);
+  gobject_class->finalize = gst_fake_sink_finalize;
 
   g_object_class_install_property (gobject_class, PROP_STATE_ERROR,
-      g_param_spec_enum ("state_error", "State Error",
+      g_param_spec_enum ("state-error", "State Error",
           "Generate a state change error", GST_TYPE_FAKE_SINK_STATE_ERROR,
-          DEFAULT_STATE_ERROR, G_PARAM_READWRITE));
+          DEFAULT_STATE_ERROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE,
-      g_param_spec_string ("last_message", "Last Message",
+      g_param_spec_string ("last-message", "Last Message",
           "The message describing current status", DEFAULT_LAST_MESSAGE,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
       g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
           "Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SILENT,
       g_param_spec_boolean ("silent", "Silent",
           "Don't produce last_message events", DEFAULT_SILENT,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DUMP,
       g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout",
-          DEFAULT_DUMP, G_PARAM_READWRITE));
+          DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class,
       PROP_CAN_ACTIVATE_PUSH,
       g_param_spec_boolean ("can-activate-push", "Can activate push",
           "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class,
       PROP_CAN_ACTIVATE_PULL,
       g_param_spec_boolean ("can-activate-pull", "Can activate pull",
           "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
       g_param_spec_int ("num-buffers", "num-buffers",
           "Number of buffers to accept going EOS", -1, G_MAXINT,
-          DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE));
+          DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstFakeSink::handoff:
@@ -210,7 +230,7 @@
   gst_fake_sink_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
-      gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
+      marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2,
       GST_TYPE_BUFFER, GST_TYPE_PAD);
 
   /**
@@ -226,7 +246,7 @@
   gst_fake_sink_signals[SIGNAL_PREROLL_HANDOFF] =
       g_signal_new ("preroll-handoff", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSinkClass, preroll_handoff),
-      NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
+      NULL, NULL, marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2,
       GST_TYPE_BUFFER, GST_TYPE_PAD);
 
   gstelement_class->change_state =
@@ -247,6 +267,17 @@
   fakesink->state_error = DEFAULT_STATE_ERROR;
   fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
   fakesink->num_buffers = DEFAULT_NUM_BUFFERS;
+  g_static_rec_mutex_init (&fakesink->notify_lock);
+}
+
+static void
+gst_fake_sink_finalize (GObject * obj)
+{
+  GstFakeSink *sink = GST_FAKE_SINK (obj);
+
+  g_static_rec_mutex_free (&sink->notify_lock);
+
+  G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
 static void
@@ -326,6 +357,20 @@
   }
 }
 
+static void
+gst_fake_sink_notify_last_message (GstFakeSink * sink)
+{
+  /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent
+   * g_object_notify() on the same object might lead to crashes, see
+   * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups.
+   * So we really don't want to do a g_object_notify() here for out-of-band
+   * events with the streaming thread possibly also doing a g_object_notify()
+   * for an in-band buffer or event. */
+  g_static_rec_mutex_lock (&sink->notify_lock);
+  g_object_notify ((GObject *) sink, "last_message");
+  g_static_rec_mutex_unlock (&sink->notify_lock);
+}
+
 static gboolean
 gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event)
 {
@@ -349,10 +394,14 @@
     g_free (sstr);
     GST_OBJECT_UNLOCK (sink);
 
-    g_object_notify (G_OBJECT (sink), "last_message");
+    gst_fake_sink_notify_last_message (sink);
   }
 
-  return TRUE;
+  if (GST_BASE_SINK_CLASS (parent_class)->event) {
+    return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
+  } else {
+    return TRUE;
+  }
 }
 
 static GstFlowReturn
@@ -370,7 +419,7 @@
     sink->last_message = g_strdup_printf ("preroll   ******* ");
     GST_OBJECT_UNLOCK (sink);
 
-    g_object_notify (G_OBJECT (sink), "last_message");
+    gst_fake_sink_notify_last_message (sink);
   }
   if (sink->signal_handoffs) {
     g_signal_emit (sink,
@@ -423,10 +472,10 @@
         ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
         G_GINT64_FORMAT ", flags: %d) %p", GST_BUFFER_SIZE (buf), ts_str,
         dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
-        GST_MINI_OBJECT (buf)->flags, buf);
+        GST_MINI_OBJECT_CAST (buf)->flags, buf);
     GST_OBJECT_UNLOCK (sink);
 
-    g_object_notify (G_OBJECT (sink), "last_message");
+    gst_fake_sink_notify_last_message (sink);
   }
   if (sink->signal_handoffs)
     g_signal_emit (G_OBJECT (sink), gst_fake_sink_signals[SIGNAL_HANDOFF], 0,
--- a/gstreamer_core/plugins/elements/gstfakesink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfakesink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -82,6 +82,7 @@
   gchar			*last_message;
   gint                  num_buffers;
   gint                  num_buffers_left;
+  GStaticRecMutex       notify_lock;
 };
 
 struct _GstFakeSinkClass {
--- a/gstreamer_core/plugins/elements/gstfakesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfakesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,49 +21,38 @@
  */
 /**
  * SECTION:element-fakesrc
- * @short_description: Generate (meaningless) buffers
  * @see_also: #GstFakeSink
  *
- * <refsect2>
- * <para>
  * The fakesrc element is a multipurpose element that can generate
  * a wide range of buffers and can operate in various scheduling modes.
- * </para>
- * <para>
+ * 
  * It is mostly used as a testing element, one trivial example for testing
  * basic <application>GStreamer</application> core functionality is:
- * </para>
+ * 
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch -v fakesrc num-buffers=5 ! fakesink
- * </programlisting>
- * This pipeline will push 5 empty buffers to the fakesink element and then
+ * ]| This pipeline will push 5 empty buffers to the fakesink element and then
  * sends an EOS.
- * </para>
- * <para>
- * Last reviewed on 2005-12-02 (0.9.7)
- * </para>
  * </refsect2>
+ * 
+ * Last reviewed on 2008-06-20 (0.10.21)
+ */
+
+/* FIXME: this ignores basesrc::blocksize property, which could be used as an
+ * alias to ::sizemax (see gst_base_src_get_blocksize()).
  */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include <stdlib.h>
 #include <string.h>
 
 #include "gstfakesrc.h"
 #include <gst/gstmarshal.h>
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-#include <gstelement.h>
-#endif
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -98,6 +87,7 @@
 #define DEFAULT_PARENTSIZE      4096*10
 #define DEFAULT_CAN_ACTIVATE_PULL TRUE
 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
+#define DEFAULT_FORMAT          GST_FORMAT_BYTES
 
 enum
 {
@@ -119,7 +109,9 @@
   PROP_LAST_MESSAGE,
   PROP_CAN_ACTIVATE_PULL,
   PROP_CAN_ACTIVATE_PUSH,
-  PROP_IS_LIVE
+  PROP_IS_LIVE,
+  PROP_FORMAT,
+  PROP_LAST,
 };
 
 /* not implemented
@@ -235,6 +227,34 @@
 static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 };
 
 static void
+marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
+    guint n_param_values, const GValue * param_values, gpointer invocation_hint,
+    gpointer marshal_data)
+{
+  typedef void (*marshalfunc_VOID__MINIOBJECT_OBJECT) (gpointer obj,
+      gpointer arg1, gpointer arg2, gpointer data2);
+  register marshalfunc_VOID__MINIOBJECT_OBJECT callback;
+  register GCClosure *cc = (GCClosure *) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback =
+      (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data :
+      cc->callback);
+
+  callback (data1, gst_value_get_mini_object (param_values + 1),
+      g_value_get_object (param_values + 2), data2);
+}
+
+static void
 gst_fake_src_base_init (gpointer g_class)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
@@ -252,11 +272,9 @@
 gst_fake_src_class_init (GstFakeSrcClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbase_src_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbase_src_class = GST_BASE_SRC_CLASS (klass);
 
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_fake_src_finalize);
@@ -273,63 +291,77 @@
 */
   g_object_class_install_property (gobject_class, PROP_DATA,
       g_param_spec_enum ("data", "data", "Data allocation method",
-          GST_TYPE_FAKE_SRC_DATA, DEFAULT_DATA, G_PARAM_READWRITE));
+          GST_TYPE_FAKE_SRC_DATA, DEFAULT_DATA,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZETYPE,
       g_param_spec_enum ("sizetype", "sizetype",
           "How to determine buffer sizes", GST_TYPE_FAKE_SRC_SIZETYPE,
-          DEFAULT_SIZETYPE, G_PARAM_READWRITE));
+          DEFAULT_SIZETYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SIZEMIN,
       g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0,
-          G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE));
+          G_MAXINT, DEFAULT_SIZEMIN,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SIZEMAX,
       g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0,
-          G_MAXINT, DEFAULT_SIZEMAX, G_PARAM_READWRITE));
+          G_MAXINT, DEFAULT_SIZEMAX,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PARENTSIZE,
       g_param_spec_int ("parentsize", "parentsize",
           "Size of parent buffer for sub-buffered allocation", 0, G_MAXINT,
-          DEFAULT_PARENTSIZE, G_PARAM_READWRITE));
+          DEFAULT_PARENTSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_FILLTYPE,
       g_param_spec_enum ("filltype", "filltype",
           "How to fill the buffer, if at all", GST_TYPE_FAKE_SRC_FILLTYPE,
-          DEFAULT_FILLTYPE, G_PARAM_READWRITE));
+          DEFAULT_FILLTYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DATARATE,
       g_param_spec_int ("datarate", "Datarate",
           "Timestamps buffers with number of bytes per second (0 = none)", 0,
-          G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
+          G_MAXINT, DEFAULT_DATARATE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SYNC,
       g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate",
-          DEFAULT_SYNC, G_PARAM_READWRITE));
+          DEFAULT_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PATTERN,
       g_param_spec_string ("pattern", "pattern", "pattern", DEFAULT_PATTERN,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE,
       g_param_spec_string ("last-message", "last-message",
-          "The last status message", NULL, G_PARAM_READABLE));
+          "The last status message", NULL,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SILENT,
       g_param_spec_boolean ("silent", "Silent",
           "Don't produce last_message events", DEFAULT_SILENT,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
       g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
           "Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DUMP,
       g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout",
-          DEFAULT_DUMP, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-      PROP_CAN_ACTIVATE_PUSH,
+          DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
       g_param_spec_boolean ("can-activate-push", "Can activate push",
           "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-  g_object_class_install_property (gobject_class,
-      PROP_CAN_ACTIVATE_PULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
       g_param_spec_boolean ("can-activate-pull", "Can activate pull",
           "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_IS_LIVE,
       g_param_spec_boolean ("is-live", "Is this a live source",
           "True if the element cannot produce data in PAUSED", FALSE,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstFakeSrc:format
+   *
+   * Set the format of the newsegment events to produce.
+   *
+   * Since: 0.10.20
+   */
+  g_object_class_install_property (gobject_class, PROP_FORMAT,
+      g_param_spec_enum ("format", "Format",
+          "The format of the segment events", GST_TYPE_FORMAT,
+          DEFAULT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstFakeSrc::handoff:
@@ -342,7 +374,7 @@
   gst_fake_src_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
-      gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
+      marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
       GST_TYPE_PAD);
 
   gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
@@ -372,6 +404,7 @@
   fakesrc->last_message = NULL;
   fakesrc->datarate = DEFAULT_DATARATE;
   fakesrc->sync = DEFAULT_SYNC;
+  fakesrc->format = DEFAULT_FORMAT;
 }
 
 static void
@@ -418,8 +451,7 @@
     g_object_notify (G_OBJECT (src), "last_message");
   }
 
-
-  return TRUE;
+  return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
 }
 
 static void
@@ -506,6 +538,9 @@
     case PROP_IS_LIVE:
       gst_base_src_set_live (basesrc, g_value_get_boolean (value));
       break;
+    case PROP_FORMAT:
+      src->format = g_value_get_enum (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -578,6 +613,9 @@
     case PROP_IS_LIVE:
       g_value_set_boolean (value, gst_base_src_is_live (basesrc));
       break;
+    case PROP_FORMAT:
+      g_value_set_enum (value, src->format);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -840,6 +878,8 @@
   src->pattern_byte = 0x00;
   src->bytes_sent = 0;
 
+  gst_base_src_set_format (basesrc, src->format);
+
   return TRUE;
 }
 
--- a/gstreamer_core/plugins/elements/gstfakesrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfakesrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -147,6 +147,7 @@
   gboolean	 signal_handoffs;
   gboolean	 dump;
   gboolean	 can_activate_pull;
+  GstFormat      format;
 
   guint64        bytes_sent;
 
--- a/gstreamer_core/plugins/elements/gstfdsink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfdsink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,7 +22,6 @@
 
 /**
  * SECTION:element-fdsink
- * @short_description: write to a unix file descriptor
  * @see_also: #GstFdSrc
  *
  * Write data to a unix file descriptor.
@@ -38,12 +37,18 @@
 #  include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 #include "../../gst/gst-i18n-lib.h"
 
 #include <sys/types.h>
+
+#ifdef G_OS_WIN32
+#include <io.h>                 /* lseek, open, close, read */
+#undef lseek
+#define lseek _lseeki64
+#undef off_t
+#define off_t guint64
+#endif
+
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <fcntl.h>
@@ -58,12 +63,6 @@
 #include <string.h>
 
 #include "gstfdsink.h"
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-#include <gstpoll.h>
-#include <gstelement.h>
-#endif
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -121,6 +120,9 @@
 static gboolean gst_fd_sink_stop (GstBaseSink * basesink);
 static gboolean gst_fd_sink_unlock (GstBaseSink * basesink);
 static gboolean gst_fd_sink_unlock_stop (GstBaseSink * basesink);
+static gboolean gst_fd_sink_event (GstBaseSink * sink, GstEvent * event);
+
+static gboolean gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset);
 
 static void
 gst_fd_sink_base_init (gpointer g_class)
@@ -154,11 +156,11 @@
   gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop);
   gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock);
   gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop);
-  gstbasesink_class->event = NULL;
+  gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_fd_sink_event);
 
   g_object_class_install_property (gobject_class, ARG_FD,
       g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
-          0, G_MAXINT, 1, G_PARAM_READWRITE));
+          0, G_MAXINT, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -172,6 +174,7 @@
   fdsink->fd = 1;
   fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
   fdsink->bytes_written = 0;
+  fdsink->current_pos = 0;
 
   GST_BASE_SINK (fdsink)->sync = TRUE;
 }
@@ -201,8 +204,7 @@
       switch (format) {
         case GST_FORMAT_DEFAULT:
         case GST_FORMAT_BYTES:
-          gst_query_set_position (query, GST_FORMAT_BYTES,
-              fdsink->bytes_written);
+          gst_query_set_position (query, GST_FORMAT_BYTES, fdsink->current_pos);
           return TRUE;
         default:
           return FALSE;
@@ -212,6 +214,10 @@
       gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
       return TRUE;
 
+    case GST_QUERY_URI:
+      gst_query_set_uri (query, fdsink->uri);
+      return TRUE;
+
     default:
       return gst_pad_query_default (pad, query);
   }
@@ -271,6 +277,7 @@
   size -= written;
   data += written;
   fdsink->bytes_written += written;
+  fdsink->current_pos += written;
 
   GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %d left", written, size);
 
@@ -302,9 +309,9 @@
         GST_ELEMENT_ERROR (fdsink, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL));
         break;
       default:{
-        GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE,
-            (_("Error while writing to file descriptor \"%d\"."), fdsink->fd),
-            ("%s", g_strerror (errno)));
+        GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL),
+            ("Error while writing to file descriptor %d: %s",
+                fdsink->fd, g_strerror (errno)));
       }
     }
     return GST_FLOW_ERROR;
@@ -336,20 +343,19 @@
         goto not_seekable;
     }
   } else
-    GST_DEBUG_OBJECT (fdsink, "File descriptor \"%d\" is seekable", fd);
+    GST_DEBUG_OBJECT (fdsink, "File descriptor %d is seekable", fd);
 
   return TRUE;
 
 invalid:
   {
-    GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE,
-        (_("File descriptor \"%d\" is not valid."), fd),
-        ("%s", g_strerror (errno)));
+    GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL),
+        ("File descriptor %d is not valid: %s", fd, g_strerror (errno)));
     return FALSE;
   }
 not_seekable:
   {
-    GST_DEBUG_OBJECT (fdsink, "File descriptor \"%d\" is a pipe", fd);
+    GST_DEBUG_OBJECT (fdsink, "File descriptor %d is a pipe", fd);
     return TRUE;
   }
 }
@@ -371,6 +377,9 @@
   gst_poll_add_fd (fdsink->fdset, &fd);
   gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
 
+  fdsink->bytes_written = 0;
+  fdsink->current_pos = 0;
+
   return TRUE;
 
   /* ERRORS */
@@ -498,16 +507,92 @@
   }
 }
 
+static gboolean
+gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset)
+{
+  off_t result;
+
+  result = lseek (fdsink->fd, new_offset, SEEK_SET);
+
+  if (result == -1)
+    goto seek_failed;
+
+  fdsink->current_pos = new_offset;
+
+  GST_DEBUG_OBJECT (fdsink, "File desciptor %d to seek to position "
+      "%" G_GUINT64_FORMAT, fdsink->fd, fdsink->current_pos);
+
+  return TRUE;
+
+  /* ERRORS */
+seek_failed:
+  {
+    GST_DEBUG_OBJECT (fdsink, "File desciptor %d failed to seek to position "
+        "%" G_GUINT64_FORMAT, fdsink->fd, new_offset);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_fd_sink_event (GstBaseSink * sink, GstEvent * event)
+{
+  GstEventType type;
+  GstFdSink *fdsink;
+
+  fdsink = GST_FD_SINK (sink);
+
+  type = GST_EVENT_TYPE (event);
+
+  switch (type) {
+    case GST_EVENT_NEWSEGMENT:
+    {
+      gint64 start, stop, pos;
+      GstFormat format;
+      gst_event_parse_new_segment (event, NULL, NULL, &format, &start,
+          &stop, &pos);
+
+      if (format == GST_FORMAT_BYTES) {
+        /* only try to seek and fail when we are going to a different
+         * position */
+        if (fdsink->current_pos != start) {
+          /* FIXME, the seek should be performed on the pos field, start/stop are
+           * just boundaries for valid bytes offsets. We should also fill the file
+           * with zeroes if the new position extends the current EOF (sparse streams
+           * and segment accumulation). */
+          if (!gst_fd_sink_do_seek (fdsink, (guint64) start))
+            goto seek_failed;
+        }
+      } else {
+        GST_DEBUG_OBJECT (fdsink,
+            "Ignored NEWSEGMENT event of format %u (%s)", (guint) format,
+            gst_format_get_name (format));
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  return TRUE;
+
+seek_failed:
+  {
+    GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK, (NULL),
+        ("Error while seeking on file descriptor %d: %s",
+            fdsink->fd, g_strerror (errno)));
+    return FALSE;
+  }
+
+}
+
 /*** GSTURIHANDLER INTERFACE *************************************************/
-#ifdef __SYMBIAN32__
-GstURIType
-#else
-static guint
-#endif 
+
+static GstURIType
 gst_fd_sink_uri_get_type (void)
 {
   return GST_URI_SINK;
 }
+
 static gchar **
 gst_fd_sink_uri_get_protocols (void)
 {
@@ -515,6 +600,7 @@
 
   return protocols;
 }
+
 static const gchar *
 gst_fd_sink_uri_get_uri (GstURIHandler * handler)
 {
--- a/gstreamer_core/plugins/elements/gstfdsink.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfdsink.h	Fri Apr 16 15:15:52 2010 +0300
@@ -58,6 +58,7 @@
 
   int fd;
   guint64 bytes_written;
+  guint64 current_pos;
 };
 
 struct _GstFdSinkClass {
--- a/gstreamer_core/plugins/elements/gstfdsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfdsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,22 +22,54 @@
  */
 /**
  * SECTION:element-fdsrc
- * @short_description: read from a unix file descriptor
  * @see_also: #GstFdSink
  *
  * Read data from a unix file descriptor.
+ * 
+ * To generate data, enter some data on the console folowed by enter.
+ * The above mentioned pipeline should dump data packets to the console.
+ * 
+ * If the #GstFdSrc:timeout property is set to a value bigger than 0, fdsrc will
+ * generate an element message named
+ * <classname>&quot;GstFdSrcTimeout&quot;</classname>
+ * if no data was recieved in the given timeout.
+ * The message's structure contains one field:
+ * <itemizedlist>
+ * <listitem>
+ *   <para>
+ *   #guint64
+ *   <classname>&quot;timeout&quot;</classname>: the timeout in microseconds that
+ *   expired when waiting for data.
+ *   </para>
+ * </listitem>
+ * </itemizedlist>
+ * 
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * echo "Hello GStreamer" | gst-launch -v fdsrc ! fakesink dump=true
+ * ]| A simple pipeline to read from the standard input and dump the data
+ * with a fakesink as hex ascii block.
+ * </refsect2>
+ * 
+ * Last reviewed on 2008-06-20 (0.10.21)
  */
 
-
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 #include "gst/gst_private.h"
 
 #include <sys/types.h>
+
+#ifdef G_OS_WIN32
+#include <io.h>                 /* lseek, open, close, read */
+#undef lseek
+#define lseek _lseeki64
+#undef off_t
+#define off_t guint64
+#endif
+
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <fcntl.h>
@@ -52,14 +84,6 @@
 #include <errno.h>
 
 #include "gstfdsrc.h"
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-#include <gstpoll.h>
-#include <gstelement.h>
-#endif
-
-#define DEFAULT_BLOCKSIZE       4096
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -69,10 +93,17 @@
 GST_DEBUG_CATEGORY_STATIC (gst_fd_src_debug);
 #define GST_CAT_DEFAULT gst_fd_src_debug
 
+#define DEFAULT_FD              0
+#define DEFAULT_TIMEOUT         0
+
 enum
 {
   PROP_0,
+
   PROP_FD,
+  PROP_TIMEOUT,
+
+  PROP_LAST
 };
 
 static void gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
@@ -108,6 +139,7 @@
 static gboolean gst_fd_src_is_seekable (GstBaseSrc * bsrc);
 static gboolean gst_fd_src_get_size (GstBaseSrc * src, guint64 * size);
 static gboolean gst_fd_src_do_seek (GstBaseSrc * src, GstSegment * segment);
+static gboolean gst_fd_src_query (GstBaseSrc * src, GstQuery * query);
 
 static GstFlowReturn gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf);
 
@@ -129,11 +161,9 @@
 {
   GObjectClass *gobject_class;
   GstBaseSrcClass *gstbasesrc_class;
-  GstElementClass *gstelement_class;
   GstPushSrcClass *gstpush_src_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
   gstpush_src_class = GST_PUSH_SRC_CLASS (klass);
 
@@ -145,7 +175,19 @@
 
   g_object_class_install_property (gobject_class, PROP_FD,
       g_param_spec_int ("fd", "fd", "An open file descriptor to read from",
-          0, G_MAXINT, 0, G_PARAM_READWRITE));
+          0, G_MAXINT, DEFAULT_FD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstFdSrc:timeout
+   *
+   * Post a message after timeout microseconds
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT,
+      g_param_spec_uint64 ("timeout", "Timeout",
+          "Post a message after timeout microseconds (0 = disabled)", 0,
+          G_MAXUINT64, DEFAULT_TIMEOUT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop);
@@ -154,6 +196,7 @@
   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fd_src_is_seekable);
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_fd_src_get_size);
   gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_fd_src_do_seek);
+  gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_fd_src_query);
 
   gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_fd_src_create);
 }
@@ -161,9 +204,10 @@
 static void
 gst_fd_src_init (GstFdSrc * fdsrc, GstFdSrcClass * klass)
 {
-  fdsrc->fd = -1;
   fdsrc->new_fd = 0;
   fdsrc->seekable_fd = FALSE;
+  fdsrc->fd = DEFAULT_FD;
+  fdsrc->timeout = DEFAULT_TIMEOUT;
   fdsrc->uri = g_strdup_printf ("fd://0");
   fdsrc->curoffset = 0;
 }
@@ -185,7 +229,7 @@
   struct stat stat_results;
 
   /* we need to always update the fdset since it may not have existed when
-   * gst_fd_src_update_fd() was called earlier */
+   * gst_fd_src_update_fd () was called earlier */
   if (src->fdset != NULL) {
     GstPollFD fd = GST_POLL_FD_INIT;
 
@@ -312,6 +356,11 @@
       }
       GST_OBJECT_UNLOCK (object);
       break;
+    case PROP_TIMEOUT:
+      src->timeout = g_value_get_uint64 (value);
+      GST_DEBUG_OBJECT (src, "poll timeout set to %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (src->timeout));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -328,6 +377,9 @@
     case PROP_FD:
       g_value_set_int (value, src->fd);
       break;
+    case PROP_TIMEOUT:
+      g_value_set_uint64 (value, src->timeout);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -341,30 +393,59 @@
   GstBuffer *buf;
   gssize readbytes;
   guint blocksize;
+  GstClockTime timeout;
 
 #ifndef HAVE_WIN32
+  gboolean try_again;
   gint retval;
 #endif
 
   src = GST_FD_SRC (psrc);
 
+  if (src->timeout > 0) {
+    timeout = src->timeout * GST_USECOND;
+  } else {
+    timeout = GST_CLOCK_TIME_NONE;
+  }
+
 #ifndef HAVE_WIN32
   do {
-    retval = gst_poll_wait (src->fdset, GST_CLOCK_TIME_NONE);
-  } while (retval == -1 && (errno == EINTR || errno == EAGAIN));        /* retry if interrupted */
+    try_again = FALSE;
+
+    GST_LOG_OBJECT (src, "doing poll, timeout %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (src->timeout));
+
+    retval = gst_poll_wait (src->fdset, timeout);
+    GST_LOG_OBJECT (src, "poll returned %d", retval);
 
-  if (retval == -1) {
-    if (errno == EBUSY)
-      goto stopped;
-    else
-      goto select_error;
-  }
+    if (G_UNLIKELY (retval == -1)) {
+      if (errno == EINTR || errno == EAGAIN) {
+        /* retry if interrupted */
+        try_again = TRUE;
+      } else if (errno == EBUSY) {
+        goto stopped;
+      } else {
+        goto poll_error;
+      }
+    } else if (G_UNLIKELY (retval == 0)) {
+      try_again = TRUE;
+      /* timeout, post element message */
+      gst_element_post_message (GST_ELEMENT_CAST (src),
+          gst_message_new_element (GST_OBJECT_CAST (src),
+              gst_structure_new ("GstFdSrcTimeout",
+                  "timeout", G_TYPE_UINT64, src->timeout, NULL)));
+    }
+  } while (G_UNLIKELY (try_again));     /* retry if interrupted or timeout */
 #endif
 
   blocksize = GST_BASE_SRC (src)->blocksize;
 
   /* create the buffer */
-  buf = gst_buffer_new_and_alloc (blocksize);
+  buf = gst_buffer_try_new_and_alloc (blocksize);
+  if (G_UNLIKELY (buf == NULL)) {
+    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", blocksize);
+    return GST_FLOW_ERROR;
+  }
 
   do {
     readbytes = read (src->fd, GST_BUFFER_DATA (buf), blocksize);
@@ -391,16 +472,16 @@
 
   /* ERRORS */
 #ifndef HAVE_WIN32
-select_error:
+poll_error:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
-        ("select on file descriptor: %s.", g_strerror (errno)));
-    GST_DEBUG_OBJECT (psrc, "Error during select");
+        ("poll on file descriptor: %s.", g_strerror (errno)));
+    GST_DEBUG_OBJECT (psrc, "Error during poll");
     return GST_FLOW_ERROR;
   }
 stopped:
   {
-    GST_DEBUG_OBJECT (psrc, "Select stopped");
+    GST_DEBUG_OBJECT (psrc, "Poll stopped");
     return GST_FLOW_WRONG_STATE;
   }
 #endif
@@ -421,6 +502,28 @@
 }
 
 static gboolean
+gst_fd_src_query (GstBaseSrc * basesrc, GstQuery * query)
+{
+  gboolean ret = FALSE;
+  GstFdSrc *src = GST_FD_SRC (basesrc);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_URI:
+      gst_query_set_uri (query, src->uri);
+      ret = TRUE;
+      break;
+    default:
+      ret = FALSE;
+      break;
+  }
+
+  if (!ret)
+    ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
+
+  return ret;
+}
+
+static gboolean
 gst_fd_src_is_seekable (GstBaseSrc * bsrc)
 {
   GstFdSrc *src = GST_FD_SRC (bsrc);
@@ -482,16 +585,13 @@
 }
 
 /*** GSTURIHANDLER INTERFACE *************************************************/
-#ifdef __SYMBIAN32__
-GstURIType
-#else
-static guint
-#endif
 
+static GstURIType
 gst_fd_src_uri_get_type (void)
 {
   return GST_URI_SRC;
 }
+
 static gchar **
 gst_fd_src_uri_get_protocols (void)
 {
@@ -499,6 +599,7 @@
 
   return protocols;
 }
+
 static const gchar *
 gst_fd_src_uri_get_uri (GstURIHandler * handler)
 {
--- a/gstreamer_core/plugins/elements/gstfdsrc.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfdsrc.h	Fri Apr 16 15:15:52 2010 +0300
@@ -62,6 +62,9 @@
   gint fd;
   gboolean seekable_fd;
 
+  /* poll timeout */
+  guint64 timeout;
+
   gchar *uri;
 
   GstPoll *fdset;
--- a/gstreamer_core/plugins/elements/gstfilesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfilesink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,7 +22,6 @@
  */
 /**
  * SECTION:element-filesink
- * @short_description: write stream to a file
  * @see_also: #GstFileSrc
  *
  * Write incoming data to a file in the local file system.
@@ -31,11 +30,6 @@
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#include <gstpoll.h>
-#include <gstbasesink.h> //rj
-#endif
 
 #include "../../gst/gst-i18n-lib.h"
 
@@ -47,8 +41,20 @@
 #include <errno.h>
 #include "gstfilesink.h"
 #include <string.h>
+#include <sys/types.h>
+
+#ifdef G_OS_WIN32
+#include <io.h>                 /* lseek, open, close, read */
+#undef lseek
+#define lseek _lseeki64
+#undef off_t
+#define off_t guint64
+#ifdef _MSC_VER                 /* Check if we are using MSVC, fileno is deprecated in favour */
+#define fileno _fileno          /* of _fileno */
+#endif
+#endif
+
 #include <sys/stat.h>
-#include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -146,7 +152,8 @@
 
   gst_element_class_set_details_simple (gstelement_class,
       "File Sink",
-      "Sink/File", "Write stream to a file", "Thomas <thomas@apestaart.org>");
+      "Sink/File", "Write stream to a file",
+      "Thomas Vander Stichele <thomas at apestaart dot org>");
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&sinktemplate));
 }
@@ -164,17 +171,19 @@
 
   g_object_class_install_property (gobject_class, PROP_LOCATION,
       g_param_spec_string ("location", "File Location",
-          "Location of the file to write", NULL, G_PARAM_READWRITE));
+          "Location of the file to write", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BUFFER_MODE,
       g_param_spec_enum ("buffer-mode", "Buffering mode",
           "The buffering mode to use", GST_TYPE_BUFFER_MODE,
-          DEFAULT_BUFFER_MODE, G_PARAM_READWRITE));
+          DEFAULT_BUFFER_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
       g_param_spec_uint ("buffer-size", "Buffering size",
           "Size of buffer in number of bytes for line or full buffer-mode", 0,
-          G_MAXUINT, DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE));
+          G_MAXUINT, DEFAULT_BUFFER_SIZE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstbasesink_class->get_times = NULL;
   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_file_sink_start);
@@ -231,8 +240,10 @@
   g_free (sink->filename);
   g_free (sink->uri);
   if (location != NULL) {
+    /* we store the filename as we received it from the application. On Windows
+     * this should be in UTF8 */
     sink->filename = g_strdup (location);
-    sink->uri = gst_uri_construct ("file", location);
+    sink->uri = gst_uri_construct ("file", sink->filename);
   } else {
     sink->filename = NULL;
     sink->uri = NULL;
@@ -243,11 +254,12 @@
   /* ERRORS */
 was_open:
   {
-    g_warning ("Changing the `location' property on filesink when "
-        "a file is open not supported.");
+    g_warning ("Changing the `location' property on filesink when a file is "
+        "open is not supported.");
     return FALSE;
   }
 }
+
 static void
 gst_file_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -301,6 +313,9 @@
   if (sink->filename == NULL || sink->filename[0] == '\0')
     goto no_filename;
 
+  /* FIXME, can we use g_fopen here? some people say that the FILE object is
+   * local to the .so that performed the fopen call, which would not be us when
+   * we use g_fopen. */
   sink->file = fopen (sink->filename, "wb");
   if (sink->file == NULL)
     goto open_failed;
@@ -407,6 +422,10 @@
       gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
       return TRUE;
 
+    case GST_QUERY_URI:
+      gst_query_set_uri (query, self->uri);
+      return TRUE;
+
     default:
       return gst_pad_query_default (pad, query);
   }
@@ -414,7 +433,7 @@
 
 #ifdef HAVE_FSEEKO
 # define __GST_STDIO_SEEK_FUNCTION "fseeko"
-#elif defined (G_OS_UNIX)
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
 # define __GST_STDIO_SEEK_FUNCTION "lseek"
 #else
 # define __GST_STDIO_SEEK_FUNCTION "fseek"
@@ -432,7 +451,7 @@
 #ifdef HAVE_FSEEKO
   if (fseeko (filesink->file, (off_t) new_offset, SEEK_SET) != 0)
     goto seek_failed;
-#elif defined (G_OS_UNIX)
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
   if (lseek (fileno (filesink->file), (off_t) new_offset,
           SEEK_SET) == (off_t) - 1)
     goto seek_failed;
@@ -530,11 +549,11 @@
 static gboolean
 gst_file_sink_get_current_offset (GstFileSink * filesink, guint64 * p_pos)
 {
-  off_t ret;
+  off_t ret = -1;
 
 #ifdef HAVE_FTELLO
   ret = ftello (filesink->file);
-#elif defined (G_OS_UNIX)
+#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
   if (fflush (filesink->file)) {
     GST_DEBUG_OBJECT (filesink, "Flush failed: %s", g_strerror (errno));
     /* ignore and continue */
@@ -555,16 +574,18 @@
 {
   GstFileSink *filesink;
   guint size;
+  guint8 *data;
+
+  filesink = GST_FILE_SINK (sink);
 
   size = GST_BUFFER_SIZE (buffer);
-
-  filesink = GST_FILE_SINK (sink);
+  data = GST_BUFFER_DATA (buffer);
 
   GST_DEBUG_OBJECT (filesink, "writing %u bytes at %" G_GUINT64_FORMAT,
       size, filesink->current_pos);
 
-  if (size > 0 && GST_BUFFER_DATA (buffer) != NULL) {
-    if (fwrite (GST_BUFFER_DATA (buffer), size, 1, filesink->file) != 1)
+  if (size > 0 && data != NULL) {
+    if (fwrite (data, size, 1, filesink->file) != 1)
       goto handle_error;
 
     filesink->current_pos += size;
@@ -603,15 +624,13 @@
 }
 
 /*** GSTURIHANDLER INTERFACE *************************************************/
-#ifdef __SYMBIAN32__
-GstURIType
-#else
-static guint
-#endif 
+
+static GstURIType
 gst_file_sink_uri_get_type (void)
 {
   return GST_URI_SINK;
 }
+
 static gchar **
 gst_file_sink_uri_get_protocols (void)
 {
@@ -619,6 +638,7 @@
 
   return protocols;
 }
+
 static const gchar *
 gst_file_sink_uri_get_uri (GstURIHandler * handler)
 {
--- a/gstreamer_core/plugins/elements/gstfilesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstfilesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -21,7 +21,6 @@
  */
 /**
  * SECTION:element-filesrc
- * @short_description: read from arbitrary point in a file
  * @see_also: #GstFileSrc
  *
  * Read data from a file in the local file system.
@@ -30,23 +29,29 @@
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include <gst/gst.h>
 #include "gstfilesrc.h"
 
 #include <stdio.h>
 #include <sys/types.h>
+#ifdef G_OS_WIN32
+#include <io.h>                 /* lseek, open, close, read */
+/* On win32, stat* default to 32 bit; we need the 64-bit
+ * variants, so explicitly define it that way. */
+#define stat __stat64
+#define fstat _fstat64
+#undef lseek
+#define lseek _lseeki64
+#undef off_t
+#define off_t guint64
+/* Prevent stat.h from defining the stat* functions as
+ * _stat*, since we're explicitly overriding that */
+#undef _INC_STAT_INL
+#endif
 #include <sys/stat.h>
 #include <fcntl.h>
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-#endif
-
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
 #endif
@@ -55,15 +60,10 @@
 # include <sys/mman.h>
 #endif
 
-#ifdef HAVE_WIN32
-#  include <io.h>               /* lseek, open, close, read */
-#endif
-
 #include <errno.h>
 #include <string.h>
 
 #include "../../gst/gst-i18n-lib.h"
-#include <gstelement.h>
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -84,6 +84,38 @@
 #define O_BINARY (0)
 #endif
 
+/* Copy of glib's g_open due to win32 libc/cross-DLL brokenness: we can't
+ * use the 'file descriptor' opened in glib (and returned from this function)
+ * in this library, as they may have unrelated C runtimes. */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+int
+gst_open (const gchar * filename, int flags, int mode)
+{
+#ifdef G_OS_WIN32
+  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+  int retval;
+  int save_errno;
+
+  if (wfilename == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  retval = _wopen (wfilename, flags, mode);
+  save_errno = errno;
+
+  g_free (wfilename);
+
+  errno = save_errno;
+  return retval;
+#else
+  return open (filename, flags, mode);
+#endif
+}
+
 
 /**********************************************************************
  * GStreamer Default File Source
@@ -165,6 +197,7 @@
 static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size);
 static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset,
     guint length, GstBuffer ** buffer);
+static gboolean gst_file_src_query (GstBaseSrc * src, GstQuery * query);
 
 static void gst_file_src_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
@@ -204,11 +237,9 @@
 gst_file_src_class_init (GstFileSrcClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbasesrc_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
 
   gobject_class->set_property = gst_file_src_set_property;
@@ -217,18 +248,23 @@
   g_object_class_install_property (gobject_class, ARG_FD,
       g_param_spec_int ("fd", "File-descriptor",
           "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_LOCATION,
       g_param_spec_string ("location", "File Location",
-          "Location of the file to read", NULL, G_PARAM_READWRITE));
+          "Location of the file to read", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
   g_object_class_install_property (gobject_class, ARG_MMAPSIZE,
       g_param_spec_ulong ("mmapsize", "mmap() Block Size",
           "Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_PLAYING));
   g_object_class_install_property (gobject_class, ARG_TOUCH,
       g_param_spec_boolean ("touch", "Touch mapped region read data",
           "Touch mmapped data regions to force them to be read from disk",
-          DEFAULT_TOUCH, G_PARAM_READWRITE));
+          DEFAULT_TOUCH,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_PLAYING));
   /**
    * GstFileSrc:use-mmap
    *
@@ -250,12 +286,14 @@
   g_object_class_install_property (gobject_class, ARG_USEMMAP,
       g_param_spec_boolean ("use-mmap", "Use mmap to read data",
           "Whether to use mmap() instead of read()",
-          DEFAULT_USEMMAP, G_PARAM_READWRITE));
+          DEFAULT_USEMMAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
   g_object_class_install_property (gobject_class, ARG_SEQUENTIAL,
       g_param_spec_boolean ("sequential", "Optimise for sequential mmap access",
           "Whether to use madvise to hint to the kernel that access to "
           "mmap pages will be sequential",
-          DEFAULT_SEQUENTIAL, G_PARAM_READWRITE));
+          DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_PLAYING));
 
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_file_src_finalize);
 
@@ -264,6 +302,7 @@
   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create);
+  gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_file_src_query);
 
   if (sizeof (off_t) < 8) {
     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
@@ -325,6 +364,8 @@
     src->filename = NULL;
     src->uri = NULL;
   } else {
+    /* we store the filename as received by the application. On Windoes this
+     * should be UTF8 */
     src->filename = g_strdup (location);
     src->uri = gst_uri_construct ("file", src->filename);
   }
@@ -336,7 +377,8 @@
   /* ERROR */
 wrong_state:
   {
-    GST_DEBUG_OBJECT (src, "setting location in wrong state");
+    g_warning ("Changing the `location' property on filesink when a file is "
+        "open is not supported.");
     GST_OBJECT_UNLOCK (src);
     return FALSE;
   }
@@ -534,8 +576,8 @@
   GST_LOG ("unmapped region %08lx+%08lx at %p",
       (gulong) offset, (gulong) size, data);
 
-  GST_MINI_OBJECT_CLASS (mmap_buffer_parent_class)->
-      finalize (GST_MINI_OBJECT (mmap_buffer));
+  GST_MINI_OBJECT_CLASS (mmap_buffer_parent_class)->finalize (GST_MINI_OBJECT
+      (mmap_buffer));
 }
 
 static GstBuffer *
@@ -567,12 +609,11 @@
 #ifdef MADV_SEQUENTIAL
   if (src->sequential) {
     /* madvise to tell the kernel what to do with it */
-  #ifndef __SYMBIAN32__
     if (madvise (mmapregion, size, MADV_SEQUENTIAL) < 0) {
       GST_WARNING_OBJECT (src, "warning: madvise failed: %s",
           g_strerror (errno));
     }
-  #endif
+  }
 #endif
 
   /* fill in the rest of the fields */
@@ -792,9 +833,14 @@
     src->read_position = offset;
   }
 
-  buf = gst_buffer_new_and_alloc (length);
+  buf = gst_buffer_try_new_and_alloc (length);
+  if (G_UNLIKELY (buf == NULL && length > 0)) {
+    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length);
+    return GST_FLOW_ERROR;
+  }
 
-  GST_LOG_OBJECT (src, "Reading %d bytes", length);
+  GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
+      length, offset);
   ret = read (src->fd, GST_BUFFER_DATA (buf), length);
   if (G_UNLIKELY (ret < 0))
     goto could_not_read;
@@ -869,6 +915,28 @@
 }
 
 static gboolean
+gst_file_src_query (GstBaseSrc * basesrc, GstQuery * query)
+{
+  gboolean ret = FALSE;
+  GstFileSrc *src = GST_FILE_SRC (basesrc);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_URI:
+      gst_query_set_uri (query, src->uri);
+      ret = TRUE;
+      break;
+    default:
+      ret = FALSE;
+      break;
+  }
+
+  if (!ret)
+    ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
+
+  return ret;
+}
+
+static gboolean
 gst_file_src_is_seekable (GstBaseSrc * basesrc)
 {
   GstFileSrc *src = GST_FILE_SRC (basesrc);
@@ -917,7 +985,8 @@
   GST_INFO_OBJECT (src, "opening file %s", src->filename);
 
   /* open the file */
-  src->fd = open (src->filename, O_RDONLY | O_BINARY);
+  src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0);
+
   if (src->fd < 0)
     goto open_failed;
 
@@ -1039,15 +1108,17 @@
 }
 
 /*** GSTURIHANDLER INTERFACE *************************************************/
+
 #ifdef __SYMBIAN32__
 GstURIType
 #else
-static guint
+static GstURIType
 #endif 
 gst_file_src_uri_get_type (void)
 {
   return GST_URI_SRC;
 }
+
 static gchar **
 gst_file_src_uri_get_protocols (void)
 {
@@ -1055,6 +1126,7 @@
 
   return protocols;
 }
+
 static const gchar *
 gst_file_src_uri_get_uri (GstURIHandler * handler)
 {
@@ -1066,47 +1138,54 @@
 static gboolean
 gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
 {
-  gchar *protocol, *location;
-  gboolean ret;
+  gchar *location, *hostname = NULL;
+  gboolean ret = FALSE;
   GstFileSrc *src = GST_FILE_SRC (handler);
-
-  protocol = gst_uri_get_protocol (uri);
-  if (strcmp (protocol, "file") != 0) {
-    g_free (protocol);
-    return FALSE;
-  }
-  g_free (protocol);
+  GError *error = NULL;
 
-  /* allow file://localhost/foo/bar by stripping localhost but fail
-   * for every other hostname */
-  if (g_str_has_prefix (uri, "file://localhost/")) {
-    char *tmp;
-
-    /* 16 == strlen ("file://localhost") */
-    tmp = g_strconcat ("file://", uri + 16, NULL);
-    /* we use gst_uri_get_location() although we already have the
-     * "location" with uri + 16 because it provides unescaping */
-    location = gst_uri_get_location (tmp);
-    g_free (tmp);
-  } else if (strcmp (uri, "file://") == 0) {
+  if (strcmp (uri, "file://") == 0) {
     /* Special case for "file://" as this is used by some applications
      *  to test with gst_element_make_from_uri if there's an element
      *  that supports the URI protocol. */
     gst_file_src_set_location (src, NULL);
     return TRUE;
-  } else {
-    location = gst_uri_get_location (uri);
+  }
+
+  location = g_filename_from_uri (uri, &hostname, &error);
+
+  if (!location || error) {
+    if (error) {
+      GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
+          error->message);
+      g_error_free (error);
+    } else {
+      GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
+    }
+    goto beach;
   }
 
-  if (!location)
-    return FALSE;
-  if (!g_path_is_absolute (location)) {
-    g_free (location);
-    return FALSE;
+  if ((hostname) && (strcmp (hostname, "localhost"))) {
+    /* Only 'localhost' is permitted */
+    GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
+    goto beach;
   }
+#ifdef G_OS_WIN32
+  /* Unfortunately, g_filename_from_uri() doesn't handle some UNC paths
+   * correctly on windows, it leaves them with an extra backslash
+   * at the start if they're of the mozilla-style file://///host/path/file 
+   * form. Correct this.
+   */
+  if (location[0] == '\\' && location[1] == '\\' && location[2] == '\\')
+    g_memmove (location, location + 1, strlen (location + 1) + 1);
+#endif
 
   ret = gst_file_src_set_location (src, location);
-  g_free (location);
+
+beach:
+  if (location)
+    g_free (location);
+  if (hostname)
+    g_free (hostname);
 
   return ret;
 }
--- a/gstreamer_core/plugins/elements/gstidentity.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstidentity.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,9 +22,8 @@
  */
 /**
  * SECTION:element-identity
- * @short_description: pass data through without modification
  *
- * Dummy element that passes incomming data through unmodified. I has some
+ * Dummy element that passes incomming data through unmodified. It has some
  * useful diagnostic functions, such as offset and timestamp checking.
  */
 
@@ -32,19 +31,11 @@
 #  include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 #include <stdlib.h>
 
 #include "../../gst/gst-i18n-lib.h"
 #include "gstidentity.h"
 #include <gst/gstmarshal.h>
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-
-#endif
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -115,6 +106,9 @@
 static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
 static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans,
     GstBuffer * buf);
+static GstFlowReturn gst_identity_prepare_output_buffer (GstBaseTransform
+    * trans, GstBuffer * in_buf, gint out_size, GstCaps * out_caps,
+    GstBuffer ** out_buf);
 static gboolean gst_identity_start (GstBaseTransform * trans);
 static gboolean gst_identity_stop (GstBaseTransform * trans);
 
@@ -143,6 +137,7 @@
   identity = GST_IDENTITY (object);
 
   g_free (identity->last_message);
+  g_static_rec_mutex_free (&identity->notify_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -169,8 +164,8 @@
     data2 = closure->data;
   }
   callback =
-      (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->
-      callback);
+      (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data :
+      cc->callback);
 
   callback (data1, gst_value_get_mini_object (param_values + 1), data2);
 }
@@ -179,11 +174,9 @@
 gst_identity_class_init (GstIdentityClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
   GstBaseTransformClass *gstbasetrans_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
@@ -192,52 +185,57 @@
   g_object_class_install_property (gobject_class, PROP_SLEEP_TIME,
       g_param_spec_uint ("sleep-time", "Sleep time",
           "Microseconds to sleep between processing", 0, G_MAXUINT,
-          DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
+          DEFAULT_SLEEP_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_ERROR_AFTER,
-      g_param_spec_int ("error_after", "Error After", "Error after N buffers",
-          G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-      PROP_DROP_PROBABILITY, g_param_spec_float ("drop_probability",
-          "Drop Probability",
+      g_param_spec_int ("error-after", "Error After", "Error after N buffers",
+          G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DROP_PROBABILITY,
+      g_param_spec_float ("drop-probability", "Drop Probability",
           "The Probability a buffer is dropped", 0.0, 1.0,
-          DEFAULT_DROP_PROBABILITY, G_PARAM_READWRITE));
+          DEFAULT_DROP_PROBABILITY,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DATARATE,
       g_param_spec_int ("datarate", "Datarate",
           "(Re)timestamps buffers with number of bytes per second (0 = inactive)",
-          0, G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
+          0, G_MAXINT, DEFAULT_DATARATE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SILENT,
       g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SINGLE_SEGMENT,
       g_param_spec_boolean ("single-segment", "Single Segment",
           "Timestamp buffers and eat newsegments so as to appear as one segment",
-          DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE));
+          DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE,
       g_param_spec_string ("last-message", "last-message", "last-message", NULL,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DUMP,
       g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout",
-          DEFAULT_DUMP, G_PARAM_READWRITE));
+          DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SYNC,
       g_param_spec_boolean ("sync", "Synchronize",
-          "Synchronize to pipeline clock", DEFAULT_SYNC, G_PARAM_READWRITE));
+          "Synchronize to pipeline clock", DEFAULT_SYNC,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_CHECK_PERFECT,
       g_param_spec_boolean ("check-perfect", "Check For Perfect Stream",
           "Verify that the stream is time- and data-contiguous. "
           "This only logs in the debug log.  This will be deprecated in favor "
           "of the check-imperfect-timestamp/offset properties.",
-          DEFAULT_CHECK_PERFECT, G_PARAM_READWRITE));
+          DEFAULT_CHECK_PERFECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class,
       PROP_CHECK_IMPERFECT_TIMESTAMP,
       g_param_spec_boolean ("check-imperfect-timestamp",
           "Check for discontiguous timestamps",
           "Send element messages if timestamps and durations do not match up",
-          DEFAULT_CHECK_IMPERFECT_TIMESTAMP, G_PARAM_READWRITE));
+          DEFAULT_CHECK_IMPERFECT_TIMESTAMP,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_CHECK_IMPERFECT_OFFSET,
       g_param_spec_boolean ("check-imperfect-offset",
           "Check for discontiguous offset",
           "Send element messages if offset and offset_end do not match up",
-          DEFAULT_CHECK_IMPERFECT_OFFSET, G_PARAM_READWRITE));
+          DEFAULT_CHECK_IMPERFECT_OFFSET,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstIdentity:signal-handoffs
@@ -250,7 +248,7 @@
   g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
       g_param_spec_boolean ("signal-handoffs",
           "Signal handoffs", "Send a signal before pushing the buffer",
-          DEFAULT_SIGNAL_HANDOFFS, G_PARAM_READWRITE));
+          DEFAULT_SIGNAL_HANDOFFS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstIdentity::handoff:
@@ -270,6 +268,8 @@
   gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_identity_event);
   gstbasetrans_class->transform_ip =
       GST_DEBUG_FUNCPTR (gst_identity_transform_ip);
+  gstbasetrans_class->prepare_output_buffer =
+      GST_DEBUG_FUNCPTR (gst_identity_prepare_output_buffer);
   gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start);
   gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_identity_stop);
 }
@@ -277,8 +277,6 @@
 static void
 gst_identity_init (GstIdentity * identity, GstIdentityClass * g_class)
 {
-  gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE);
-
   identity->sleep_time = DEFAULT_SLEEP_TIME;
   identity->error_after = DEFAULT_ERROR_AFTER;
   identity->drop_probability = DEFAULT_DROP_PROBABILITY;
@@ -292,6 +290,21 @@
   identity->dump = DEFAULT_DUMP;
   identity->last_message = NULL;
   identity->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
+  g_static_rec_mutex_init (&identity->notify_lock);
+}
+
+static void
+gst_identity_notify_last_message (GstIdentity * identity)
+{
+  /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent
+   * g_object_notify() on the same object might lead to crashes, see
+   * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups.
+   * So we really don't want to do a g_object_notify() here for out-of-band
+   * events with the streaming thread possibly also doing a g_object_notify()
+   * for an in-band buffer or event. */
+  g_static_rec_mutex_lock (&identity->notify_lock);
+  g_object_notify ((GObject *) identity, "last_message");
+  g_static_rec_mutex_unlock (&identity->notify_lock);
 }
 
 static gboolean
@@ -321,7 +334,7 @@
     g_free (sstr);
     GST_OBJECT_UNLOCK (identity);
 
-    g_object_notify (G_OBJECT (identity), "last_message");
+    gst_identity_notify_last_message (identity);
   }
 
   if (identity->single_segment
@@ -336,12 +349,18 @@
       /* This is the first newsegment, send out a (0, -1) newsegment */
       news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0);
 
-      if (!(gst_pad_event_default (trans->sinkpad, news)))
-        return FALSE;
+      gst_pad_event_default (trans->sinkpad, news);
     }
   }
 
-  GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event);
+  /* Reset previous timestamp, duration and offsets on NEWSEGMENT
+   * to prevent false warnings when checking for perfect streams */
+  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
+    identity->prev_timestamp = identity->prev_duration = GST_CLOCK_TIME_NONE;
+    identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE;
+  }
+
+  ret = parent_class->event (trans, event);
 
   if (identity->single_segment
       && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
@@ -352,6 +371,28 @@
   return ret;
 }
 
+static GstFlowReturn
+gst_identity_prepare_output_buffer (GstBaseTransform * trans,
+    GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf)
+{
+  GstIdentity *identity = GST_IDENTITY (trans);
+
+  /* only bother if we may have to alter metadata */
+  if (identity->datarate > 0 || identity->single_segment) {
+    if (gst_buffer_is_metadata_writable (in_buf))
+      *out_buf = gst_buffer_ref (in_buf);
+    else {
+      /* make even less writable */
+      gst_buffer_ref (in_buf);
+      /* extra ref is dropped going through the official process */
+      *out_buf = gst_buffer_make_metadata_writable (in_buf);
+    }
+  } else
+    *out_buf = gst_buffer_ref (in_buf);
+
+  return GST_FLOW_OK;
+}
+
 static void
 gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf)
 {
@@ -382,7 +423,9 @@
       }
 
       offset = GST_BUFFER_OFFSET (buf);
-      if (identity->prev_offset_end != offset) {
+      if (identity->prev_offset_end != offset &&
+          identity->prev_offset_end != GST_BUFFER_OFFSET_NONE &&
+          offset != GST_BUFFER_OFFSET_NONE) {
         GST_WARNING_OBJECT (identity,
             "Buffer not data-contiguous with previous one: "
             "prev offset_end %" G_GINT64_FORMAT ", new offset %"
@@ -405,11 +448,9 @@
     /* check if we had a previous buffer to compare to */
     if (identity->prev_timestamp != GST_CLOCK_TIME_NONE &&
         identity->prev_duration != GST_CLOCK_TIME_NONE) {
-      guint64 offset;
       GstClockTime t_expected;
       GstClockTimeDiff dt;
 
-      offset = GST_BUFFER_OFFSET (buf);
       t_expected = identity->prev_timestamp + identity->prev_duration;
       dt = GST_CLOCK_DIFF (t_expected, timestamp);
       if (dt != 0) {
@@ -536,7 +577,7 @@
             GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf),
             GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf);
         GST_OBJECT_UNLOCK (identity);
-        g_object_notify (G_OBJECT (identity), "last-message");
+        gst_identity_notify_last_message (identity);
       }
       /* return DROPPED to basetransform. */
       return GST_BASE_TRANSFORM_FLOW_DROPPED;
@@ -560,7 +601,7 @@
         GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
         GST_BUFFER_FLAGS (buf), buf);
     GST_OBJECT_UNLOCK (identity);
-    g_object_notify (G_OBJECT (identity), "last-message");
+    gst_identity_notify_last_message (identity);
   }
 
   if (identity->datarate > 0) {
@@ -740,8 +781,8 @@
   identity->offset = 0;
   identity->prev_timestamp = GST_CLOCK_TIME_NONE;
   identity->prev_duration = GST_CLOCK_TIME_NONE;
-  identity->prev_offset_end = -1;
-  identity->prev_offset = -1;
+  identity->prev_offset_end = GST_BUFFER_OFFSET_NONE;
+  identity->prev_offset = GST_BUFFER_OFFSET_NONE;
 
   return TRUE;
 }
--- a/gstreamer_core/plugins/elements/gstidentity.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstidentity.h	Fri Apr 16 15:15:52 2010 +0300
@@ -73,6 +73,7 @@
   gchar 	*last_message;
   guint64        offset;
   gboolean       signal_handoffs;
+  GStaticRecMutex  notify_lock;
 };
 
 struct _GstIdentityClass {
--- a/gstreamer_core/plugins/elements/gstmultiqueue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstmultiqueue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -23,7 +23,6 @@
 
 /**
  * SECTION:element-multiqueue
- * @short_description: Asynchronous data queues
  * @see_also: #GstQueue
  *
  * <refsect2>
@@ -35,12 +34,12 @@
  *   <itemizedlist><title>Multiple streamhandling</title>
  *   <listitem><para>
  *     The element handles queueing data on more than one stream at once. To
- *     achieve such a feature it has request sink pads (sink_%d) and
- *     'sometimes' src pads (src_%d).
+ *     achieve such a feature it has request sink pads (sink%d) and
+ *     'sometimes' src pads (src%d).
  *   </para><para>
  *     When requesting a given sinkpad with gst_element_get_request_pad(),
  *     the associated srcpad for that stream will be created.
- *     Ex: requesting sink_1 will generate src_1.
+ *     Example: requesting sink1 will generate src1.
  *   </para></listitem>
  *   </itemizedlist>
  * </listitem>
@@ -112,11 +111,6 @@
 #include <gst/gst.h>
 #include "gstmultiqueue.h"
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-#endif
-
 /**
  * GstSingleQueue:
  * @sinkpad: associated sink #GstPad
@@ -175,6 +169,7 @@
 
 static void wake_up_next_non_linked (GstMultiQueue * mq);
 static void compute_high_id (GstMultiQueue * mq);
+static void single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq);
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink%d",
     GST_PAD_SINK,
@@ -277,11 +272,32 @@
       GST_DEBUG_FUNCPTR (gst_multi_queue_get_property);
 
   /* SIGNALS */
+
+  /**
+   * GstMultiQueue::underrun:
+   * @multiqueue: the multqueue instance
+   *
+   * This signal is emitted from the streaming thread when there is
+   * no data in any of the queues inside the multiqueue instance (underrun).
+   *
+   * This indicates either starvation or EOS from the upstream data sources.
+   */
   gst_multi_queue_signals[SIGNAL_UNDERRUN] =
       g_signal_new ("underrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstMultiQueueClass, underrun), NULL, NULL,
       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
+  /**
+   * GstMultiQueue::overrun:
+   * @multiqueue: the multiqueue instance
+   *
+   * Reports that one of the queues in the multiqueue is full (overrun).
+   * A queue is full if the total amount of data inside it (num-buffers, time,
+   * size) is higher than the boundary values which can be set through the
+   * GObject properties.
+   *
+   * This can be used as an indicator of pre-roll. 
+   */
   gst_multi_queue_signals[SIGNAL_OVERRUN] =
       g_signal_new ("overrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstMultiQueueClass, overrun), NULL, NULL,
@@ -292,28 +308,33 @@
   g_object_class_install_property (gobject_class, ARG_MAX_SIZE_BYTES,
       g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
           "Max. amount of data in the queue (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, G_PARAM_READWRITE));
+          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_MAX_SIZE_BUFFERS,
       g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
-          "Max. number of buffers in the queue (0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS, G_PARAM_READWRITE));
+          "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
+          DEFAULT_MAX_SIZE_BUFFERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_MAX_SIZE_TIME,
       g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
-          "Max. amount of data in the queue (in ns, 0=disable)",
-          0, G_MAXUINT64, DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE));
+          "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
+          DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, ARG_EXTRA_SIZE_BYTES,
       g_param_spec_uint ("extra-size-bytes", "Extra Size (kB)",
           "Amount of data the queues can grow if one of them is empty (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BYTES, G_PARAM_READWRITE));
+          0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BYTES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_EXTRA_SIZE_BUFFERS,
       g_param_spec_uint ("extra-size-buffers", "Extra Size (buffers)",
           "Amount of buffers the queues can grow if one of them is empty (0=disable)",
-          0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BUFFERS, G_PARAM_READWRITE));
+          0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BUFFERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_EXTRA_SIZE_TIME,
       g_param_spec_uint64 ("extra-size-time", "Extra Size (ns)",
           "Amount of time the queues can grow if one of them is empty (in ns, 0=disable)",
-          0, G_MAXUINT64, DEFAULT_EXTRA_SIZE_TIME, G_PARAM_READWRITE));
+          0, G_MAXUINT64, DEFAULT_EXTRA_SIZE_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_multi_queue_finalize);
 
@@ -605,20 +626,28 @@
   sink_time =
       gst_segment_to_running_time (&sq->sink_segment, GST_FORMAT_TIME,
       sq->sink_segment.last_stop);
+  if (sink_time == GST_CLOCK_TIME_NONE)
+    goto beach;
 
   src_time = gst_segment_to_running_time (&sq->src_segment, GST_FORMAT_TIME,
       sq->src_segment.last_stop);
+  if (src_time == GST_CLOCK_TIME_NONE)
+    goto beach;
 
   GST_DEBUG_OBJECT (mq,
       "queue %d, sink %" GST_TIME_FORMAT ", src %" GST_TIME_FORMAT, sq->id,
       GST_TIME_ARGS (sink_time), GST_TIME_ARGS (src_time));
 
-  /* This allows for streams with out of order timestamping - sometimes the 
+  /* This allows for streams with out of order timestamping - sometimes the
    * emerging timestamp is later than the arriving one(s) */
-  if (sink_time >= src_time)
-    sq->cur_time = sink_time - src_time;
-  else
-    sq->cur_time = 0;
+  if (sink_time < src_time)
+    goto beach;
+
+  sq->cur_time = sink_time - src_time;
+  return;
+
+beach:
+  sq->cur_time = 0;
 }
 
 /* take a NEWSEGMENT event and apply the values to segment, updating the time
@@ -767,7 +796,7 @@
 {
   if (item->object)
     gst_mini_object_unref (item->object);
-  g_free (item);
+  g_slice_free (GstMultiQueueItem, item);
 }
 
 /* takes ownership of passed mini object! */
@@ -776,7 +805,7 @@
 {
   GstMultiQueueItem *item;
 
-  item = g_new (GstMultiQueueItem, 1);
+  item = g_slice_new (GstMultiQueueItem);
   item->object = object;
   item->destroy = (GDestroyNotify) gst_multi_queue_item_destroy;
   item->posid = curid;
@@ -1062,6 +1091,7 @@
   switch (type) {
     case GST_EVENT_EOS:
       sq->is_eos = TRUE;
+      single_queue_overrun_cb (sq->queue, sq);
       break;
     case GST_EVENT_NEWSEGMENT:
       apply_segment (mq, sq, sref, &sq->sink_segment);
@@ -1267,7 +1297,7 @@
     if (gst_data_queue_is_empty (ssq->queue)) {
       GST_LOG_OBJECT (mq, "Queue %d is empty", ssq->id);
       if (IS_FILLED (visible, size.visible)) {
-        sq->max_size.visible++;
+        sq->max_size.visible = size.visible + 1;
         GST_DEBUG_OBJECT (mq,
             "Another queue is empty, bumping single queue %d max visible to %d",
             sq->id, sq->max_size.visible);
@@ -1284,7 +1314,8 @@
         ssize.bytes, sq->max_size.bytes, sq->cur_time, sq->max_size.time);
 
     /* if this queue is filled completely we must signal overrun */
-    if (IS_FILLED (bytes, ssize.bytes) || IS_FILLED (time, sq->cur_time)) {
+    if (sq->is_eos || IS_FILLED (bytes, ssize.bytes) ||
+        IS_FILLED (time, sq->cur_time)) {
       GST_LOG_OBJECT (mq, "Queue %d is filled", ssq->id);
       filled = TRUE;
     }
@@ -1321,7 +1352,7 @@
 
       gst_data_queue_get_level (sq->queue, &size);
       if (IS_FILLED (visible, size.visible)) {
-        sq->max_size.visible++;
+        sq->max_size.visible = size.visible + 1;
         GST_DEBUG_OBJECT (mq,
             "queue %d is filled, bumping its max visible to %d", sq->id,
             sq->max_size.visible);
@@ -1357,13 +1388,9 @@
   if (IS_FILLED (visible, visible))
     return TRUE;
 
-  if (sq->cur_time != 0) {
-    /* if we have valid time in the queue, check */
-    res = IS_FILLED (time, sq->cur_time);
-  } else {
-    /* no valid time, check bytes */
-    res = IS_FILLED (bytes, bytes);
-  }
+  /* check time or bytes */
+  res = IS_FILLED (time, sq->cur_time) || IS_FILLED (bytes, bytes);
+
   return res;
 }
 
@@ -1455,11 +1482,17 @@
   gst_pad_set_element_private (sq->sinkpad, (gpointer) sq);
   gst_pad_set_element_private (sq->srcpad, (gpointer) sq);
 
-  gst_pad_set_active (sq->srcpad, TRUE);
+  /* only activate the pads when we are not in the NULL state
+   * and add the pad under the state_lock to prevend state changes
+   * between activating and adding */
+  g_static_rec_mutex_lock (GST_STATE_GET_LOCK (mqueue));
+  if (GST_STATE_TARGET (mqueue) != GST_STATE_NULL) {
+    gst_pad_set_active (sq->srcpad, TRUE);
+    gst_pad_set_active (sq->sinkpad, TRUE);
+  }
   gst_element_add_pad (GST_ELEMENT (mqueue), sq->srcpad);
-
-  gst_pad_set_active (sq->sinkpad, TRUE);
   gst_element_add_pad (GST_ELEMENT (mqueue), sq->sinkpad);
+  g_static_rec_mutex_unlock (GST_STATE_GET_LOCK (mqueue));
 
   GST_DEBUG_OBJECT (mqueue, "GstSingleQueue [%d] created and pads added",
       sq->id);
--- a/gstreamer_core/plugins/elements/gstqueue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gstqueue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -24,7 +24,6 @@
 
 /**
  * SECTION:element-queue
- * @short_description: Simple asynchronous data queue.
  *
  * Data is queued until one of the limits specified by the
  * #GstQueue:max-size-buffers, #GstQueue:max-size-bytes and/or
@@ -55,9 +54,6 @@
  * empty). The #GstQueue::overrun signal is emitted when the queue is filled
  * up. Both signals are emitted from the context of the streaming thread.
  */
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include "gst/gst_private.h"
 
@@ -65,11 +61,6 @@
 #include "gstqueue.h"
 
 #include "../../gst/gst-i18n-lib.h"
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-
-#endif
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -205,6 +196,7 @@
 static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event);
 static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query);
 
+static gboolean gst_queue_acceptcaps (GstPad * pad, GstCaps * caps);
 static GstCaps *gst_queue_getcaps (GstPad * pad);
 static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
 static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer);
@@ -212,8 +204,6 @@
 
 static gboolean gst_queue_src_activate_push (GstPad * pad, gboolean active);
 static gboolean gst_queue_sink_activate_push (GstPad * pad, gboolean active);
-static GstStateChangeReturn gst_queue_change_state (GstElement * element,
-    GstStateChange transition);
 
 static gboolean gst_queue_is_empty (GstQueue * queue);
 static gboolean gst_queue_is_filled (GstQueue * queue);
@@ -258,7 +248,6 @@
 gst_queue_class_init (GstQueueClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_queue_set_property);
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_queue_get_property);
@@ -318,51 +307,52 @@
   g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_BYTES,
       g_param_spec_uint ("current-level-bytes", "Current level (kB)",
           "Current amount of data in the queue (bytes)",
-          0, G_MAXUINT, 0, G_PARAM_READABLE));
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_BUFFERS,
       g_param_spec_uint ("current-level-buffers", "Current level (buffers)",
           "Current number of buffers in the queue",
-          0, G_MAXUINT, 0, G_PARAM_READABLE));
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_TIME,
       g_param_spec_uint64 ("current-level-time", "Current level (ns)",
           "Current amount of data in the queue (in ns)",
-          0, G_MAXUINT64, 0, G_PARAM_READABLE));
+          0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, ARG_MAX_SIZE_BYTES,
       g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
           "Max. amount of data in the queue (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, G_PARAM_READWRITE));
+          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_MAX_SIZE_BUFFERS,
       g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
-          "Max. number of buffers in the queue (0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS, G_PARAM_READWRITE));
+          "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
+          DEFAULT_MAX_SIZE_BUFFERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_MAX_SIZE_TIME,
       g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
-          "Max. amount of data in the queue (in ns, 0=disable)",
-          0, G_MAXUINT64, DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE));
+          "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
+          DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, ARG_MIN_THRESHOLD_BYTES,
       g_param_spec_uint ("min-threshold-bytes", "Min. threshold (kB)",
           "Min. amount of data in the queue to allow reading (bytes, 0=disable)",
-          0, G_MAXUINT, 0, G_PARAM_READWRITE));
+          0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_MIN_THRESHOLD_BUFFERS,
       g_param_spec_uint ("min-threshold-buffers", "Min. threshold (buffers)",
           "Min. number of buffers in the queue to allow reading (0=disable)",
-          0, G_MAXUINT, 0, G_PARAM_READWRITE));
+          0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, ARG_MIN_THRESHOLD_TIME,
       g_param_spec_uint64 ("min-threshold-time", "Min. threshold (ns)",
           "Min. amount of data in the queue to allow reading (in ns, 0=disable)",
-          0, G_MAXUINT64, 0, G_PARAM_READWRITE));
+          0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, ARG_LEAKY,
       g_param_spec_enum ("leaky", "Leaky",
           "Where the queue leaks, if at all",
-          GST_TYPE_QUEUE_LEAKY, GST_QUEUE_NO_LEAK, G_PARAM_READWRITE));
+          GST_TYPE_QUEUE_LEAKY, GST_QUEUE_NO_LEAK,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /* set several parent class virtual functions */
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_queue_finalize);
-
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_queue_change_state);
 }
 
 static void
@@ -380,6 +370,8 @@
       GST_DEBUG_FUNCPTR (gst_queue_link_sink));
   gst_pad_set_getcaps_function (queue->sinkpad,
       GST_DEBUG_FUNCPTR (gst_queue_getcaps));
+  gst_pad_set_acceptcaps_function (queue->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_queue_acceptcaps));
   gst_pad_set_bufferalloc_function (queue->sinkpad,
       GST_DEBUG_FUNCPTR (gst_queue_bufferalloc));
   gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
@@ -390,6 +382,8 @@
       GST_DEBUG_FUNCPTR (gst_queue_src_activate_push));
   gst_pad_set_link_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue_link_src));
+  gst_pad_set_acceptcaps_function (queue->srcpad,
+      GST_DEBUG_FUNCPTR (gst_queue_acceptcaps));
   gst_pad_set_getcaps_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue_getcaps));
   gst_pad_set_event_function (queue->srcpad,
@@ -441,6 +435,21 @@
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gboolean
+gst_queue_acceptcaps (GstPad * pad, GstCaps * caps)
+{
+  gboolean result;
+  GstQueue *queue;
+  GstPad *otherpad;
+
+  queue = GST_QUEUE (GST_PAD_PARENT (pad));
+
+  otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
+  result = gst_pad_peer_accept_caps (otherpad, caps);
+
+  return result;
+}
+
 static GstCaps *
 gst_queue_getcaps (GstPad * pad)
 {
@@ -801,14 +810,14 @@
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
         "refusing event, we are flushing");
     GST_QUEUE_MUTEX_UNLOCK (queue);
-    gst_buffer_unref (event);
+    gst_event_unref (event);
     return FALSE;
   }
 out_eos:
   {
     GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
     GST_QUEUE_MUTEX_UNLOCK (queue);
-    gst_buffer_unref (event);
+    gst_event_unref (event);
     return FALSE;
   }
 }
@@ -816,13 +825,18 @@
 static gboolean
 gst_queue_is_empty (GstQueue * queue)
 {
-  return (queue->queue->length == 0 ||
-      (queue->min_threshold.buffers > 0 &&
+  if (queue->queue->length == 0)
+    return TRUE;
+
+  /* It is possible that a max size is reached before all min thresholds are.
+   * Therefore, only consider it empty if it is not filled. */
+  return ((queue->min_threshold.buffers > 0 &&
           queue->cur_level.buffers < queue->min_threshold.buffers) ||
       (queue->min_threshold.bytes > 0 &&
           queue->cur_level.bytes < queue->min_threshold.bytes) ||
       (queue->min_threshold.time > 0 &&
-          queue->cur_level.time < queue->min_threshold.time));
+          queue->cur_level.time < queue->min_threshold.time)) &&
+      !gst_queue_is_filled (queue);
 }
 
 static gboolean
@@ -836,6 +850,27 @@
               queue->cur_level.time >= queue->max_size.time)));
 }
 
+static void
+gst_queue_leak_downstream (GstQueue * queue)
+{
+  /* for as long as the queue is filled, dequeue an item and discard it */
+  while (gst_queue_is_filled (queue)) {
+    GstMiniObject *leak;
+
+    leak = gst_queue_locked_dequeue (queue);
+    /* there is nothing to dequeue and the queue is still filled.. This should
+     * not happen */
+    g_assert (leak != NULL);
+
+    GST_CAT_DEBUG_OBJECT (queue_dataflow, queue,
+        "queue is full, leaking item %p on downstream end", leak);
+    gst_mini_object_unref (leak);
+
+    /* last buffer needs to get a DISCONT flag */
+    queue->head_needs_discont = TRUE;
+  }
+}
+
 static GstFlowReturn
 gst_queue_chain (GstPad * pad, GstBuffer * buffer)
 {
@@ -883,25 +918,8 @@
         /* now we can clean up and exit right away */
         goto out_unref;
       case GST_QUEUE_LEAK_DOWNSTREAM:
-      {
-        /* for as long as the queue is filled, dequeue an item and discard 
-         * it. */
-        do {
-          GstMiniObject *leak;
-
-          leak = gst_queue_locked_dequeue (queue);
-          /* there is nothing to dequeue and the queue is still filled.. This
-           * should not happen. */
-          g_assert (leak != NULL);
-
-          GST_CAT_DEBUG_OBJECT (queue_dataflow, queue,
-              "queue is full, leaking item %p on downstream end", leak);
-          gst_buffer_unref (leak);
-        } while (gst_queue_is_filled (queue));
-        /* last buffer needs to get a DISCONT flag */
-        queue->head_needs_discont = TRUE;
+        gst_queue_leak_downstream (queue);
         break;
-      }
       default:
         g_warning ("Unknown leaky type, using default");
         /* fall-through */
@@ -1198,9 +1216,9 @@
           peer_pos -= queue->cur_level.time;
           break;
         default:
-          GST_WARNING_OBJECT (queue, "dropping query in %s format, don't "
+          GST_DEBUG_OBJECT (queue, "Can't adjust query in %s format, don't "
               "know how to adjust value", gst_format_get_name (format));
-          return FALSE;
+          return TRUE;
       }
       /* set updated position */
       gst_query_set_position (query, format, peer_pos);
@@ -1222,6 +1240,10 @@
       else
         max = -1;
 
+      /* adjust for min-threshold */
+      if (queue->min_threshold.time > 0 && min != -1)
+        min += queue->min_threshold.time;
+
       gst_query_set_latency (query, live, min, max);
       break;
     }
@@ -1298,47 +1320,19 @@
   return result;
 }
 
-static GstStateChangeReturn
-gst_queue_change_state (GstElement * element, GstStateChange transition)
+static void
+queue_capacity_change (GstQueue * queue)
 {
-  GstQueue *queue;
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-
-  queue = GST_QUEUE (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    default:
-      break;
+  if (queue->leaky == GST_QUEUE_LEAK_DOWNSTREAM) {
+    gst_queue_leak_downstream (queue);
   }
 
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return ret;
+  /* changing the capacity of the queue must wake up
+   * the _chain function, it might have more room now
+   * to store the buffer/event in the queue */
+  GST_QUEUE_SIGNAL_DEL (queue);
 }
 
-/* changing the capacity of the queue must wake up
- * the _chain function, it might have more room now
- * to store the buffer/event in the queue */
-#define QUEUE_CAPACITY_CHANGE(q)\
-  GST_QUEUE_SIGNAL_DEL (q);
-
 /* Changing the minimum required fill level must
  * wake up the _loop function as it might now
  * be able to preceed.
@@ -1359,15 +1353,15 @@
   switch (prop_id) {
     case ARG_MAX_SIZE_BYTES:
       queue->max_size.bytes = g_value_get_uint (value);
-      QUEUE_CAPACITY_CHANGE (queue);
+      queue_capacity_change (queue);
       break;
     case ARG_MAX_SIZE_BUFFERS:
       queue->max_size.buffers = g_value_get_uint (value);
-      QUEUE_CAPACITY_CHANGE (queue);
+      queue_capacity_change (queue);
       break;
     case ARG_MAX_SIZE_TIME:
       queue->max_size.time = g_value_get_uint64 (value);
-      QUEUE_CAPACITY_CHANGE (queue);
+      queue_capacity_change (queue);
       break;
     case ARG_MIN_THRESHOLD_BYTES:
       queue->min_threshold.bytes = g_value_get_uint (value);
--- a/gstreamer_core/plugins/elements/gsttee.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gsttee.c	Fri Apr 16 15:15:52 2010 +0300
@@ -23,7 +23,6 @@
 
 /**
  * SECTION:element-tee
- * @short_description: 1-to-N pipe fitting
  * @see_also: #GstIdentity
  *
  * Split data to multiple pads.
@@ -33,18 +32,10 @@
 #  include "config.h"
 #endif
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 #include "gsttee.h"
 
 #include <string.h>
 
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#include <gobject_global.h>
-
-#endif
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
@@ -71,6 +62,10 @@
   return type;
 }
 
+/* lock to protect request pads from being removed while downstream */
+#define GST_TEE_DYN_LOCK(tee) g_mutex_lock ((tee)->dyn_lock)
+#define GST_TEE_DYN_UNLOCK(tee) g_mutex_unlock ((tee)->dyn_lock)
+
 #define DEFAULT_PROP_NUM_SRC_PADS	0
 #define DEFAULT_PROP_HAS_SINK_LOOP	FALSE
 #define DEFAULT_PROP_HAS_CHAIN		TRUE
@@ -87,6 +82,7 @@
   PROP_SILENT,
   PROP_LAST_MESSAGE,
   PROP_PULL_MODE,
+  PROP_ALLOC_PAD,
 };
 
 static GstStaticPadTemplate tee_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
@@ -106,6 +102,7 @@
 {
   gboolean pushed;
   GstFlowReturn result;
+  gboolean removed;
 } PushData;
 
 static GstPad *gst_tee_request_new_pad (GstElement * element,
@@ -119,6 +116,7 @@
     GValue * value, GParamSpec * pspec);
 
 static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
+static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list);
 static GstFlowReturn gst_tee_buffer_alloc (GstPad * pad, guint64 offset,
     guint size, GstCaps * caps, GstBuffer ** buf);
 static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
@@ -155,6 +153,8 @@
 
   g_free (tee->last_message);
 
+  g_mutex_free (tee->dyn_lock);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -174,27 +174,33 @@
   g_object_class_install_property (gobject_class, PROP_NUM_SRC_PADS,
       g_param_spec_int ("num-src-pads", "Num Src Pads",
           "The number of source pads", 0, G_MAXINT, DEFAULT_PROP_NUM_SRC_PADS,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_HAS_SINK_LOOP,
       g_param_spec_boolean ("has-sink-loop", "Has Sink Loop",
           "If the element should spawn a thread (unimplemented and deprecated)",
-          DEFAULT_PROP_HAS_SINK_LOOP, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+          DEFAULT_PROP_HAS_SINK_LOOP,
+          G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_HAS_CHAIN,
       g_param_spec_boolean ("has-chain", "Has Chain",
-          "If the element can operate in push mode",
-          DEFAULT_PROP_HAS_CHAIN, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+          "If the element can operate in push mode", DEFAULT_PROP_HAS_CHAIN,
+          G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SILENT,
       g_param_spec_boolean ("silent", "Silent",
           "Don't produce last_message events", DEFAULT_PROP_SILENT,
-          G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+          G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE,
-      g_param_spec_string ("last_message", "Last Message",
+      g_param_spec_string ("last-message", "Last Message",
           "The message describing current status", DEFAULT_PROP_LAST_MESSAGE,
-          G_PARAM_READABLE));
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PULL_MODE,
       g_param_spec_enum ("pull-mode", "Pull mode",
           "Behavior of tee in pull mode", GST_TYPE_TEE_PULL_MODE,
-          DEFAULT_PULL_MODE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+          DEFAULT_PULL_MODE,
+          G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_ALLOC_PAD,
+      g_param_spec_object ("alloc-pad", "Allocation Src Pad",
+          "The pad used for gst_pad_alloc_buffer", GST_TYPE_PAD,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
@@ -204,6 +210,8 @@
 static void
 gst_tee_init (GstTee * tee, GstTeeClass * g_class)
 {
+  tee->dyn_lock = g_mutex_new ();
+
   tee->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
   tee->sink_mode = GST_ACTIVATE_NONE;
 
@@ -216,6 +224,8 @@
   gst_pad_set_activatepush_function (tee->sinkpad,
       GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
   gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
+  gst_pad_set_chain_list_function (tee->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_tee_chain_list));
   gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
 
   tee->last_message = NULL;
@@ -249,6 +259,7 @@
   data = g_new0 (PushData, 1);
   data->pushed = FALSE;
   data->result = GST_FLOW_NOT_LINKED;
+  data->removed = FALSE;
   g_object_set_qdata_full (G_OBJECT (srcpad), push_data, data, g_free);
 
   GST_OBJECT_UNLOCK (tee);
@@ -290,7 +301,8 @@
     if (tee->allocpad == srcpad)
       tee->allocpad = NULL;
     gst_object_unref (srcpad);
-    GST_OBJECT_LOCK (tee);
+    GST_OBJECT_UNLOCK (tee);
+    g_object_notify (G_OBJECT (tee), "alloc-pad");
     return NULL;
   }
 }
@@ -299,6 +311,7 @@
 gst_tee_release_pad (GstElement * element, GstPad * pad)
 {
   GstTee *tee;
+  PushData *data;
 
   tee = GST_TEE (element);
 
@@ -308,10 +321,18 @@
   if (tee->allocpad == pad)
     tee->allocpad = NULL;
   GST_OBJECT_UNLOCK (tee);
+  g_object_notify (G_OBJECT (tee), "alloc-pad");
+
+  /* wait for pending pad_alloc to finish */
+  GST_TEE_DYN_LOCK (tee);
+  /* mark the pad as removed so that future pad_alloc fails with NOT_LINKED. */
+  data = g_object_get_qdata (G_OBJECT (pad), push_data);
+  data->removed = TRUE;
 
   gst_pad_set_active (pad, FALSE);
 
   gst_element_remove_pad (GST_ELEMENT_CAST (tee), pad);
+  GST_TEE_DYN_UNLOCK (tee);
 }
 
 static void
@@ -337,6 +358,18 @@
     case PROP_PULL_MODE:
       tee->pull_mode = g_value_get_enum (value);
       break;
+    case PROP_ALLOC_PAD:
+    {
+      GstPad *pad = g_value_get_object (value);
+      GST_OBJECT_LOCK (pad);
+      if (GST_OBJECT_PARENT (pad) == GST_OBJECT_CAST (object))
+        tee->allocpad = pad;
+      else
+        GST_WARNING_OBJECT (object, "Tried to set alloc pad %s which"
+            " is not my pad", GST_OBJECT_NAME (pad));
+      GST_OBJECT_UNLOCK (pad);
+      break;
+    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -370,6 +403,9 @@
     case PROP_PULL_MODE:
       g_value_set_enum (value, tee->pull_mode);
       break;
+    case PROP_ALLOC_PAD:
+      g_value_set_object (value, tee->allocpad);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -380,7 +416,7 @@
 /* we have no previous source pad we can use to proxy the pad alloc. Loop over
  * the source pads, try to alloc a buffer on each one of them. Keep a reference
  * to the first pad that succeeds, we will be using it to alloc more buffers
- * later. */
+ * later.  must be called with the OBJECT_LOCK on tee. */
 static GstFlowReturn
 gst_tee_find_buffer_alloc (GstTee * tee, guint64 offset, guint size,
     GstCaps * caps, GstBuffer ** buf)
@@ -397,13 +433,20 @@
 
   while (pads) {
     GstPad *pad;
+    PushData *data;
 
     pad = GST_PAD_CAST (pads->data);
     gst_object_ref (pad);
     GST_DEBUG_OBJECT (tee, "try alloc on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
     GST_OBJECT_UNLOCK (tee);
 
-    res = gst_pad_alloc_buffer (pad, offset, size, caps, buf);
+    GST_TEE_DYN_LOCK (tee);
+    data = g_object_get_qdata (G_OBJECT (pad), push_data);
+    if (!data->removed)
+      res = gst_pad_alloc_buffer (pad, offset, size, caps, buf);
+    else
+      res = GST_FLOW_NOT_LINKED;
+    GST_TEE_DYN_UNLOCK (tee);
 
     GST_DEBUG_OBJECT (tee, "got return value %d", res);
 
@@ -416,6 +459,7 @@
        * need to unref the buffer */
       if (res == GST_FLOW_OK)
         gst_buffer_unref (*buf);
+      *buf = NULL;
       goto retry;
     }
     if (res == GST_FLOW_OK) {
@@ -423,6 +467,9 @@
           GST_DEBUG_PAD_NAME (pad));
       /* we have a buffer, keep the pad for later and exit the loop. */
       tee->allocpad = pad;
+      GST_OBJECT_UNLOCK (tee);
+      g_object_notify (G_OBJECT (tee), "alloc-pad");
+      GST_OBJECT_LOCK (tee);
       break;
     }
     /* no valid buffer, try another pad */
@@ -446,6 +493,8 @@
 
   GST_OBJECT_LOCK (tee);
   if ((allocpad = tee->allocpad)) {
+    PushData *data;
+
     /* if we had a previous pad we used for allocating a buffer, continue using
      * it. */
     GST_DEBUG_OBJECT (tee, "using pad %s:%s for alloc",
@@ -453,7 +502,14 @@
     gst_object_ref (allocpad);
     GST_OBJECT_UNLOCK (tee);
 
-    res = gst_pad_alloc_buffer (allocpad, offset, size, caps, buf);
+    GST_TEE_DYN_LOCK (tee);
+    data = g_object_get_qdata (G_OBJECT (allocpad), push_data);
+    if (!data->removed)
+      res = gst_pad_alloc_buffer (allocpad, offset, size, caps, buf);
+    else
+      res = GST_FLOW_NOT_LINKED;
+    GST_TEE_DYN_UNLOCK (tee);
+
     gst_object_unref (allocpad);
 
     GST_OBJECT_LOCK (tee);
@@ -471,17 +527,23 @@
 }
 
 static GstFlowReturn
-gst_tee_do_push (GstTee * tee, GstPad * pad, GstBuffer * buffer)
+gst_tee_do_push (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list)
 {
   GstFlowReturn res;
 
   if (G_UNLIKELY (!tee->silent)) {
     GST_OBJECT_LOCK (tee);
     g_free (tee->last_message);
-    tee->last_message =
-        g_strdup_printf ("chain        ******* (%s:%s)t (%d bytes, %"
-        G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
-        GST_BUFFER_SIZE (buffer), GST_BUFFER_TIMESTAMP (buffer), buffer);
+    if (is_list) {
+      tee->last_message =
+          g_strdup_printf ("chain-list   ******* (%s:%s)t %p",
+          GST_DEBUG_PAD_NAME (pad), data);
+    } else {
+      tee->last_message =
+          g_strdup_printf ("chain        ******* (%s:%s)t (%d bytes, %"
+          G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
+          GST_BUFFER_SIZE (data), GST_BUFFER_TIMESTAMP (data), data);
+    }
     GST_OBJECT_UNLOCK (tee);
     g_object_notify (G_OBJECT (tee), "last_message");
   }
@@ -490,8 +552,12 @@
   if (pad == tee->pull_pad) {
     /* don't push on the pad we're pulling from */
     res = GST_FLOW_OK;
+  } else if (is_list) {
+    res =
+        gst_pad_push_list (pad,
+        gst_buffer_list_ref (GST_BUFFER_LIST_CAST (data)));
   } else {
-    res = gst_pad_push (pad, gst_buffer_ref (buffer));
+    res = gst_pad_push (pad, gst_buffer_ref (GST_BUFFER_CAST (data)));
   }
   return res;
 }
@@ -511,13 +577,15 @@
 }
 
 static GstFlowReturn
-gst_tee_handle_buffer (GstTee * tee, GstBuffer * buffer)
+gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
 {
   GList *pads;
   guint32 cookie;
   GstFlowReturn ret, cret;
 
-  tee->offset += GST_BUFFER_SIZE (buffer);
+  if (!is_list) {
+    tee->offset += GST_BUFFER_SIZE (data);
+  }
 
   GST_OBJECT_LOCK (tee);
   /* mark all pads as 'not pushed on yet' */
@@ -530,50 +598,45 @@
 
   while (pads) {
     GstPad *pad;
-    PushData *data;
+    PushData *pdata;
 
     pad = GST_PAD_CAST (pads->data);
 
     /* get the private data, something is really wrong with the internal state
      * when it is not there */
-    data = g_object_get_qdata (G_OBJECT (pad), push_data);
+    pdata = g_object_get_qdata (G_OBJECT (pad), push_data);
+    g_assert (pdata != NULL);
 
-    g_assert (data != NULL);
-
-    if (!data->pushed) {
+    if (!pdata->pushed) {
       /* not yet pushed, release lock and start pushing */
       gst_object_ref (pad);
       GST_OBJECT_UNLOCK (tee);
 
-      GST_LOG_OBJECT (tee, "Starting to push buffer %p", buffer);
+      GST_LOG_OBJECT (tee, "Starting to push %s %p",
+          is_list ? "list" : "buffer", data);
 
-      ret = gst_tee_do_push (tee, pad, buffer);
+      ret = gst_tee_do_push (tee, pad, data, is_list);
 
-      GST_LOG_OBJECT (tee, "Pushing buffer %p yielded result %s", buffer,
+      GST_LOG_OBJECT (tee, "Pushing item %p yielded result %s", data,
           gst_flow_get_name (ret));
 
       GST_OBJECT_LOCK (tee);
       /* keep track of which pad we pushed and the result value. We need to do
        * this before we release the refcount on the pad, the PushData is
        * destroyed when the last ref of the pad goes away. */
-      data->pushed = TRUE;
-      data->result = ret;
+      pdata->pushed = TRUE;
+      pdata->result = ret;
       gst_object_unref (pad);
     } else {
       /* already pushed, use previous return value */
-      ret = data->result;
+      ret = pdata->result;
       GST_LOG_OBJECT (tee, "pad already pushed with %s",
           gst_flow_get_name (ret));
     }
-    /* stop pushing more buffers when we have a fatal error */
-    if (GST_FLOW_IS_FATAL (ret))
-      goto error;
 
-    /* keep all other return values, overwriting the previous one */
-    GST_LOG_OBJECT (tee, "Replacing ret val %d with %d", cret, ret);
-    if (cret == GST_FLOW_NOT_LINKED)
-      cret = ret;
-
+    /* before we go combining the return value, check if the pad list is still
+     * the same. It could be possible that the pad we just pushed was removed
+     * and the return value it not valid anymore */
     if (GST_ELEMENT_CAST (tee)->pads_cookie != cookie) {
       GST_LOG_OBJECT (tee, "pad list changed");
       /* the list of pads changed, restart iteration. Pads that we already
@@ -581,11 +644,21 @@
        * again. */
       goto restart;
     }
+
+    /* stop pushing more buffers when we have a fatal error */
+    if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
+      goto error;
+
+    /* keep all other return values, overwriting the previous one. */
+    if (ret != GST_FLOW_NOT_LINKED) {
+      GST_LOG_OBJECT (tee, "Replacing ret val %d with %d", cret, ret);
+      cret = ret;
+    }
     pads = g_list_next (pads);
   }
   GST_OBJECT_UNLOCK (tee);
 
-  gst_buffer_unref (buffer);
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
 
   /* no need to unset gvalue */
   return cret;
@@ -594,7 +667,7 @@
 error:
   {
     GST_DEBUG_OBJECT (tee, "received error %s", gst_flow_get_name (ret));
-    gst_buffer_unref (buffer);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     GST_OBJECT_UNLOCK (tee);
     return ret;
   }
@@ -610,7 +683,7 @@
 
   GST_DEBUG_OBJECT (tee, "received buffer %p", buffer);
 
-  res = gst_tee_handle_buffer (tee, buffer);
+  res = gst_tee_handle_data (tee, buffer, FALSE);
 
   GST_DEBUG_OBJECT (tee, "handled buffer %s", gst_flow_get_name (res));
 
@@ -619,6 +692,25 @@
   return res;
 }
 
+static GstFlowReturn
+gst_tee_chain_list (GstPad * pad, GstBufferList * list)
+{
+  GstFlowReturn res;
+  GstTee *tee;
+
+  tee = GST_TEE (gst_pad_get_parent (pad));
+
+  GST_DEBUG_OBJECT (tee, "received list %p", list);
+
+  res = gst_tee_handle_data (tee, list, TRUE);
+
+  GST_DEBUG_OBJECT (tee, "handled list %s", gst_flow_get_name (res));
+
+  gst_object_unref (tee);
+
+  return res;
+}
+
 static gboolean
 gst_tee_sink_activate_push (GstPad * pad, gboolean active)
 {
@@ -790,7 +882,7 @@
   ret = gst_pad_pull_range (tee->sinkpad, offset, length, buf);
 
   if (ret == GST_FLOW_OK)
-    ret = gst_tee_handle_buffer (tee, gst_buffer_ref (*buf));
+    ret = gst_tee_handle_data (tee, gst_buffer_ref (*buf), FALSE);
   else if (ret == GST_FLOW_UNEXPECTED)
     gst_tee_pull_eos (tee);
 
--- a/gstreamer_core/plugins/elements/gsttee.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gsttee.h	Fri Apr 16 15:15:52 2010 +0300
@@ -65,6 +65,9 @@
   GstElement      element;
 
   /*< private >*/
+  /* lock protecting dynamic pads */
+  GMutex         *dyn_lock;
+
   GstPad         *sinkpad;
   GstPad         *allocpad;
   gint            pad_counter;
--- a/gstreamer_core/plugins/elements/gsttypefindelement.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gsttypefindelement.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,6 +18,15 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:element-typefind
+ *
+ * Determines the media-type of a stream. It applies typefind functions in the
+ * order of their rank. One the type has been deteted it sets its src pad caps
+ * to the found media type.
+ *
+ * Plugins can register custom typefinders by using #GstTypeFindFactory.
+ */
 
 /* FIXME: need a better solution for non-seekable streams */
 
@@ -25,8 +34,8 @@
  * 1) get a list of all typefind functions sorted best to worst
  * 2) if all elements have been called with all requested data goto 8
  * 3) call all functions once with all available data
- * 4) if a function returns a value >= ARG_MAXIMUM goto 8
- * 5) all functions with a result > ARG_MINIMUM or functions that did not get
+ * 4) if a function returns a value >= PROP_MAXIMUM goto 8
+ * 5) all functions with a result > PROP_MINIMUM or functions that did not get
  *    all requested data (where peek returned NULL) stay in list
  * 6) seek to requested offset of best function that still has open data
  *    requests
@@ -50,9 +59,6 @@
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include "gsttypefindelement.h"
 #include "gst/gst_private.h"
@@ -92,10 +98,12 @@
 };
 enum
 {
-  ARG_0,
-  ARG_CAPS,
-  ARG_MINIMUM,
-  ARG_MAXIMUM
+  PROP_0,
+  PROP_CAPS,
+  PROP_MINIMUM,
+  PROP_MAXIMUM,
+  PROP_FORCE_CAPS,
+  PROP_LAST
 };
 enum
 {
@@ -154,7 +162,8 @@
 {
   g_assert (caps != NULL);
 
-  GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT, caps);
+  GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
+      caps, probability);
   if (typefind->caps)
     gst_caps_unref (typefind->caps);
   typefind->caps = gst_caps_copy (caps);
@@ -191,19 +200,24 @@
 
   typefind_class->have_type = gst_type_find_element_have_type;
 
-  g_object_class_install_property (gobject_class, ARG_CAPS,
+  g_object_class_install_property (gobject_class, PROP_CAPS,
       g_param_spec_boxed ("caps", _("caps"),
           _("detected capabilities in stream"), gst_caps_get_type (),
-          G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class, ARG_MINIMUM,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MINIMUM,
       g_param_spec_uint ("minimum", _("minimum"),
           "minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM,
-          GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_MAXIMUM,
+          GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MAXIMUM,
       g_param_spec_uint ("maximum", _("maximum"),
           "probability to stop typefinding (deprecated; non-functional)",
           GST_TYPE_FIND_MINIMUM, GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MAXIMUM,
-          G_PARAM_READWRITE));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_FORCE_CAPS,
+      g_param_spec_boxed ("force-caps", _("force caps"),
+          _("force caps without doing a typefind"), gst_caps_get_type (),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstTypeFindElement::have-type:
    * @typefind: the typefind instance
@@ -222,6 +236,7 @@
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
 }
+
 static void
 gst_type_find_element_init (GstTypeFindElement * typefind,
     GstTypeFindElementClass * g_class)
@@ -265,18 +280,24 @@
 
   typefind->store = NULL;
 }
+
 static void
 gst_type_find_element_dispose (GObject * object)
 {
   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
 
-  G_OBJECT_CLASS (parent_class)->dispose (object);
-
   if (typefind->store) {
     gst_buffer_unref (typefind->store);
     typefind->store = NULL;
   }
+  if (typefind->force_caps) {
+    gst_caps_unref (typefind->force_caps);
+    typefind->force_caps = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
+
 static void
 gst_type_find_element_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -286,17 +307,25 @@
   typefind = GST_TYPE_FIND_ELEMENT (object);
 
   switch (prop_id) {
-    case ARG_MINIMUM:
+    case PROP_MINIMUM:
       typefind->min_probability = g_value_get_uint (value);
       break;
-    case ARG_MAXIMUM:
+    case PROP_MAXIMUM:
       typefind->max_probability = g_value_get_uint (value);
       break;
+    case PROP_FORCE_CAPS:
+      GST_OBJECT_LOCK (typefind);
+      if (typefind->force_caps)
+        gst_caps_unref (typefind->force_caps);
+      typefind->force_caps = g_value_dup_boxed (value);
+      GST_OBJECT_UNLOCK (typefind);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
+
 static void
 gst_type_find_element_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
@@ -306,15 +335,20 @@
   typefind = GST_TYPE_FIND_ELEMENT (object);
 
   switch (prop_id) {
-    case ARG_CAPS:
+    case PROP_CAPS:
       g_value_set_boxed (value, typefind->caps);
       break;
-    case ARG_MINIMUM:
+    case PROP_MINIMUM:
       g_value_set_uint (value, typefind->min_probability);
       break;
-    case ARG_MAXIMUM:
+    case PROP_MAXIMUM:
       g_value_set_uint (value, typefind->max_probability);
       break;
+    case PROP_FORCE_CAPS:
+      GST_OBJECT_LOCK (typefind);
+      g_value_set_boxed (value, typefind->force_caps);
+      GST_OBJECT_UNLOCK (typefind);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -352,7 +386,7 @@
       /* FIXME: this code assumes that there's no discont in the queue */
       switch (format) {
         case GST_FORMAT_BYTES:
-          peer_pos -= typefind->store->size;
+          peer_pos -= GST_BUFFER_SIZE (typefind->store);
           break;
         default:
           /* FIXME */
@@ -396,7 +430,7 @@
     gst_mini_object_unref (GST_MINI_OBJECT (event));
     return FALSE;
   }
-  return gst_pad_event_default (pad, event);
+  return gst_pad_push_event (typefind->sink, event);
 }
 
 static void
@@ -498,9 +532,19 @@
           }
 
           stop_typefinding (typefind);
-          res = gst_pad_event_default (pad, event);
+          res = gst_pad_push_event (typefind->src, event);
           break;
         }
+        case GST_EVENT_FLUSH_STOP:
+          g_list_foreach (typefind->cached_events,
+              (GFunc) gst_mini_object_unref, NULL);
+          g_list_free (typefind->cached_events);
+          typefind->cached_events = NULL;
+          gst_buffer_replace (&typefind->store, NULL);
+          /* fall through */
+        case GST_EVENT_FLUSH_START:
+          res = gst_pad_push_event (typefind->src, event);
+          break;
         default:
           GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
               GST_EVENT_TYPE_NAME (event));
@@ -511,7 +555,7 @@
       }
       break;
     case MODE_NORMAL:
-      res = gst_pad_event_default (pad, event);
+      res = gst_pad_push_event (typefind->src, event);
       break;
     case MODE_ERROR:
       break;
@@ -570,6 +614,73 @@
   return TRUE;
 }
 
+static GstCaps *
+gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad,
+    GstTypeFindProbability * probability)
+{
+  GstQuery *query;
+  gchar *uri;
+  size_t len;
+  gint find;
+  GstCaps *caps;
+
+  query = gst_query_new_uri ();
+
+  /* try getting the caps with an uri query and from the extension */
+  if (!gst_pad_peer_query (pad, query))
+    goto peer_query_failed;
+
+  gst_query_parse_uri (query, &uri);
+  if (uri == NULL)
+    goto no_uri;
+
+  GST_DEBUG_OBJECT (typefind, "finding extension of %s", uri);
+
+  /* find the extension on the uri, this is everything after a '.' */
+  len = strlen (uri);
+  find = len - 1;
+
+  while (find >= 0) {
+    if (uri[find] == '.')
+      break;
+    find--;
+  }
+  if (find < 0)
+    goto no_extension;
+
+  GST_DEBUG_OBJECT (typefind, "found extension %s", &uri[find + 1]);
+
+  caps =
+      gst_type_find_helper_for_extension (GST_OBJECT_CAST (typefind),
+      &uri[find + 1]);
+  if (caps)
+    *probability = GST_TYPE_FIND_MAXIMUM;
+
+  gst_query_unref (query);
+
+  return caps;
+
+  /* ERRORS */
+peer_query_failed:
+  {
+    GST_WARNING_OBJECT (typefind, "failed to query peer uri");
+    gst_query_unref (query);
+    return NULL;
+  }
+no_uri:
+  {
+    GST_WARNING_OBJECT (typefind, "could not parse the peer uri");
+    gst_query_unref (query);
+    return NULL;
+  }
+no_extension:
+  {
+    GST_WARNING_OBJECT (typefind, "could not find uri extension in %s", uri);
+    gst_query_unref (query);
+    return NULL;
+  }
+}
+
 static GstFlowReturn
 gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
 {
@@ -705,13 +816,22 @@
 
   typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
 
+  /* if we have force caps, use those */
+  if (typefind->force_caps) {
+    found_caps = gst_caps_ref (typefind->force_caps);
+    probability = GST_TYPE_FIND_MAXIMUM;
+    goto done;
+  }
+
   /* 1. try to activate in pull mode. if not, switch to push and succeed.
      2. try to pull type find.
      3. deactivate pull mode.
      4. src pad might have been activated push by the state change. deactivate.
-     5. if we didn't find any caps, fail.
-     6. emit have-type; maybe the app connected the source pad to something.
-     7. if the sink pad is activated, we are in pull mode. succeed.
+     5. if we didn't find any caps, try getting the uri extension by doing an uri
+     query.
+     6. if we didn't find any caps, fail.
+     7. emit have-type; maybe the app connected the source pad to something.
+     8. if the sink pad is activated, we are in pull mode. succeed.
      otherwise activate both pads in push mode and succeed.
    */
 
@@ -732,19 +852,23 @@
 
       if (!gst_pad_query_duration (peer, &format, &size)) {
         GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
+        gst_object_unref (peer);
         return FALSE;
       }
 
-      if (size > 0) {
-        found_caps = gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
-            (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
-            (guint64) size, &probability);
-      } else {
+      /* the size if 0, we cannot continue */
+      if (size == 0) {
         /* keep message in sync with message in sink event handler */
         GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
             (_("Stream contains no data.")), ("Can't typefind empty stream"));
+        gst_object_unref (peer);
+        return FALSE;
       }
 
+      found_caps = gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
+          (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
+          (guint64) size, &probability);
+
       gst_object_unref (peer);
     }
   }
@@ -757,18 +881,24 @@
 
   /* 5 */
   if (!found_caps || probability < typefind->min_probability) {
+    found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability);
+  }
+
+  /* 6 */
+  if (!found_caps || probability < typefind->min_probability) {
     GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
     gst_caps_replace (&found_caps, NULL);
     return FALSE;
   }
 
-  /* 6 */
+done:
+  /* 7 */
   g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
       0, probability, found_caps);
   gst_caps_unref (found_caps);
   typefind->mode = MODE_NORMAL;
 
-  /* 7 */
+  /* 8 */
   if (gst_pad_is_active (pad))
     return TRUE;
   else {
@@ -796,6 +926,7 @@
     case GST_STATE_CHANGE_PAUSED_TO_READY:
     case GST_STATE_CHANGE_READY_TO_NULL:
       gst_caps_replace (&typefind->caps, NULL);
+
       g_list_foreach (typefind->cached_events,
           (GFunc) gst_mini_object_unref, NULL);
       g_list_free (typefind->cached_events);
--- a/gstreamer_core/plugins/elements/gsttypefindelement.h	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/elements/gsttypefindelement.h	Fri Apr 16 15:15:52 2010 +0300
@@ -59,6 +59,7 @@
   GstBuffer *		store;
 
   GList *               cached_events;
+  GstCaps *             force_caps;
 };
 
 struct _GstTypeFindElementClass {
--- a/gstreamer_core/plugins/indexers/gstfileindex.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/indexers/gstfileindex.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,9 +18,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 #include <gst/gst.h>
 
 #include <unistd.h>
@@ -195,7 +192,8 @@
 
   g_object_class_install_property (gobject_class, ARG_LOCATION,
       g_param_spec_string ("location", "File Location",
-          "Location of the index file", NULL, G_PARAM_READWRITE));
+          "Location of the index file", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -218,7 +216,7 @@
       munmap (index_id->array->data, ARRAY_TOTAL_SIZE (index_id));
     g_array_free (index_id->array, !is_mmapped);
   }
-  g_free (index_id);
+  g_slice_free (GstFileIndexId, index_id);
 }
 
 static gboolean
@@ -405,7 +403,7 @@
           continue;
         }
 
-        id_index = g_new0 (GstFileIndexId, 1);
+        id_index = g_slice_new0 (GstFileIndexId);
         id_index->id_desc = (char *) xmlGetProp (writer, (xmlChar *) "id");
 
         for (wpart = writer->children; wpart; wpart = wpart->next) {
@@ -670,7 +668,7 @@
   id_index = g_hash_table_lookup (fileindex->id_index, &entry->id);
 
   if (!id_index) {
-    id_index = g_new0 (GstFileIndexId, 1);
+    id_index = g_slice_new0 (GstFileIndexId);
 
     id_index->id = entry->id;
     id_index->id_desc = g_strdup (entry->data.id.description);
@@ -974,7 +972,7 @@
 
   /* entry memory management needs improvement FIXME */
   if (!fileindex->ret_entry)
-    fileindex->ret_entry = g_new0 (GstIndexEntry, 1);
+    fileindex->ret_entry = g_slice_new0 (GstIndexEntry);
   entry = fileindex->ret_entry;
   if (entry->data.assoc.assocs) {
     g_free (entry->data.assoc.assocs);
--- a/gstreamer_core/plugins/indexers/gstindexers.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/indexers/gstindexers.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,9 +16,6 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include <gst/gst_private.h>
 #include <gst/gstversion.h>
--- a/gstreamer_core/plugins/indexers/gstmemindex.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/plugins/indexers/gstmemindex.c	Fri Apr 16 15:15:52 2010 +0300
@@ -16,9 +16,6 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#ifdef __SYMBIAN32__
-#include <gst_global.h>
-#endif
 
 #include <gst/gst.h>
 
@@ -185,7 +182,7 @@
     g_tree_destroy (index->tree);
   }
 
-  g_free (index);
+  g_slice_free (GstMemIndexFormatIndex, index);
 }
 
 static void
@@ -200,7 +197,7 @@
     id_index->format_index = NULL;
   }
 
-  g_free (id_index);
+  g_slice_free (GstMemIndexId, id_index);
 }
 
 static void
@@ -234,7 +231,7 @@
   id_index = g_hash_table_lookup (memindex->id_index, &entry->id);
 
   if (!id_index) {
-    id_index = g_new0 (GstMemIndexId, 1);
+    id_index = g_slice_new0 (GstMemIndexId);
 
     id_index->id = entry->id;
     id_index->format_index = g_hash_table_new (g_int_hash, g_int_equal);
@@ -269,7 +266,7 @@
   index = g_hash_table_lookup (id_index->format_index, format);
 
   if (!index) {
-    index = g_new0 (GstMemIndexFormatIndex, 1);
+    index = g_slice_new0 (GstMemIndexFormatIndex);
 
     index->format = *format;
     index->offset = assoc;
--- a/gstreamer_core/tools/grammar.y	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,932 +0,0 @@
-%{
-
-
-#include <glib-object.h>
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "../gst_private.h"
-#include "../gst-i18n-lib.h"
-
-#include "../gstconfig.h"
-#include "../gstparse.h"
-#include "../gstinfo.h"
-#include "../gsterror.h"
-#include "../gsturi.h"
-#include "../gstutils.h"
-#include "../gstvalue.h"
-#include "../gstchildproxy.h"
-#include "types.h"
-
-#include <glib_global.h>
-#include <glib_object.h>
-
-
-
-
-/* All error messages in this file are user-visible and need to be translated.
- * Don't start the message with a capital, and don't end them with a period,
- * as they will be presented inside a sentence/error.
- */
-  
-#define YYERROR_VERBOSE 1
-#define YYLEX_PARAM scanner
-
-typedef void* yyscan_t;
-
-int _gst_parse_yylex (void * yylval_param , yyscan_t yyscanner);
-int _gst_parse_yylex_init (yyscan_t scanner);
-int _gst_parse_yylex_destroy (yyscan_t scanner);
-struct yy_buffer_state * _gst_parse_yy_scan_string (char* , yyscan_t);
-void _gst_parse_yypush_buffer_state (void * new_buffer ,yyscan_t yyscanner );
-void _gst_parse_yypop_buffer_state (yyscan_t yyscanner );
-
-
-#ifdef __GST_PARSE_TRACE
-static guint __strings;
-static guint __links;
-static guint __chains;
-gchar *
-__gst_parse_strdup (gchar *org)
-{
-  gchar *ret; 
-  __strings++;
-  ret = g_strdup (org);
-  /* g_print ("ALLOCATED STR   (%3u): %p %s\n", __strings, ret, ret); */
-  return ret;
-}
-void
-__gst_parse_strfree (gchar *str)
-{
-  if (str) {
-    /* g_print ("FREEING STR     (%3u): %p %s\n", __strings - 1, str, str); */
-    g_free (str);
-    g_return_if_fail (__strings > 0);
-    __strings--;
-  }
-}
-link_t *__gst_parse_link_new ()
-{
-  link_t *ret;
-  __links++;
-  ret = g_new0 (link_t, 1);
-  /* g_print ("ALLOCATED LINK  (%3u): %p\n", __links, ret); */
-  return ret;
-}
-void
-__gst_parse_link_free (link_t *data)
-{
-  if (data) {
-    /* g_print ("FREEING LINK    (%3u): %p\n", __links - 1, data); */
-    g_free (data);
-    g_return_if_fail (__links > 0);
-    __links--;
-  }
-}
-chain_t *
-__gst_parse_chain_new ()
-{
-  chain_t *ret;
-  __chains++;
-  ret = g_new0 (chain_t, 1);
-  /* g_print ("ALLOCATED CHAIN (%3u): %p\n", __chains, ret); */
-  return ret;
-}
-void
-__gst_parse_chain_free (chain_t *data)
-{
-  /* g_print ("FREEING CHAIN   (%3u): %p\n", __chains - 1, data); */
-  g_free (data);
-  g_return_if_fail (__chains > 0);
-  __chains--;
-}
-
-#endif /* __GST_PARSE_TRACE */
-
-typedef struct {
-  gchar *src_pad;
-  gchar *sink_pad;
-  GstElement *sink;
-  GstCaps *caps;
-  gulong signal_id;
-  /* FIXME: need to connect to "disposed" signal to clean up,
-   * but there is no such signal */
-} DelayedLink;
-
-typedef struct {
-  GstElement *parent;
-  gchar *name;
-  gchar *value_str;
-  gulong signal_id;
-} DelayedSet;
-
-/*** define SET_ERROR and ERROR macros/functions */
-
-#ifdef G_HAVE_ISO_VARARGS
-
-#  define SET_ERROR(error, type, ...) \
-G_STMT_START { \
-  GST_CAT_ERROR (GST_CAT_PIPELINE, __VA_ARGS__); \
-  if ((error) && !*(error)) { \
-    g_set_error ((error), GST_PARSE_ERROR, (type), __VA_ARGS__); \
-  } \
-} G_STMT_END
-
-#  define ERROR(type, ...) \
-  SET_ERROR (((graph_t *) graph)->error, (type), __VA_ARGS__ )
-
-#elif defined(G_HAVE_GNUC_VARARGS)
-
-#  define SET_ERROR(error, type, args...) \
-G_STMT_START { \
-  GST_CAT_ERROR (GST_CAT_PIPELINE, args ); \
-  if ((error) && !*(error)) { \
-    g_set_error ((error), GST_PARSE_ERROR, (type), args ); \
-  } \
-} G_STMT_END
-
-#  define ERROR(type, args...) \
-  SET_ERROR (((graph_t *) graph)->error,(type) , args )
-
-#else
-
-static inline void
-SET_ERROR (GError **error, gint type, const char *format, ...)
-{
-  if (error) {
-    if (*error) {
-      g_warning ("error while parsing");
-    } else {
-      va_list varargs;
-      char *string;
-
-      va_start (varargs, format);
-      string = g_strdup_vprintf (format, varargs);
-      va_end (varargs);
-      
-      g_set_error (error, GST_PARSE_ERROR, type, string);
-
-      g_free (string);
-    }
-  }
-}
-
-#endif /* G_HAVE_ISO_VARARGS */
-
-/*** define YYPRINTF macro/function if we're debugging */
-
-/* bison 1.35 calls this macro with side effects, we need to make sure the
-   side effects work - crappy bison */
-
-#ifndef GST_DISABLE_GST_DEBUG
-#  define YYDEBUG 1
-
-#  ifdef G_HAVE_ISO_VARARGS
-
-/* #  define YYFPRINTF(a, ...) GST_CAT_DEBUG (GST_CAT_PIPELINE, __VA_ARGS__) */
-#    define YYFPRINTF(a, ...) \
-G_STMT_START { \
-     gchar *temp = g_strdup_printf (__VA_ARGS__); \
-     GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
-     g_free (temp); \
-} G_STMT_END
-
-#  elif defined(G_HAVE_GNUC_VARARGS)
-
-#    define YYFPRINTF(a, args...) \
-G_STMT_START { \
-     gchar *temp = g_strdup_printf ( args ); \
-     GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
-     g_free (temp); \
-} G_STMT_END
-
-#  else
-
-static inline void
-YYPRINTF(const char *format, ...)
-{
-  va_list varargs;
-  gchar *temp;
-  
-  va_start (varargs, format);
-  temp = g_strdup_vprintf (format, varargs);
-  GST_CAT_LOG (GST_CAT_PIPELINE, "%s", temp);
-  g_free (temp);
-  va_end (varargs);
-}
-
-#  endif /* G_HAVE_ISO_VARARGS */
-
-#endif /* GST_DISABLE_GST_DEBUG */
-
-#define GST_BIN_MAKE(res, type, chainval, assign, free_string) \
-G_STMT_START { \
-  chain_t *chain = chainval; \
-  GSList *walk; \
-  GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \
-  if (!chain) { \
-    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY_BIN, \
-        _("specified empty bin \"%s\", not allowed"), type); \
-    g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
-    g_slist_free (assign); \
-    gst_object_unref (bin); \
-    if (free_string) \
-      gst_parse_strfree (type); /* Need to clean up the string */ \
-    YYERROR; \
-  } else if (!bin) { \
-    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \
-        _("no bin \"%s\", skipping"), type); \
-    g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
-    g_slist_free (assign); \
-    res = chain; \
-  } else { \
-    for (walk = chain->elements; walk; walk = walk->next ) \
-      gst_bin_add (bin, GST_ELEMENT (walk->data)); \
-    g_slist_free (chain->elements); \
-    chain->elements = g_slist_prepend (NULL, bin); \
-    res = chain; \
-    /* set the properties now */ \
-    for (walk = assign; walk; walk = walk->next) \
-      gst_parse_element_set ((gchar *) walk->data, GST_ELEMENT (bin), graph); \
-    g_slist_free (assign); \
-  } \
-} G_STMT_END
-
-#define MAKE_LINK(link, _src, _src_name, _src_pads, _sink, _sink_name, _sink_pads) \
-G_STMT_START { \
-  link = gst_parse_link_new (); \
-  link->src = _src; \
-  link->sink = _sink; \
-  link->src_name = _src_name; \
-  link->sink_name = _sink_name; \
-  link->src_pads = _src_pads; \
-  link->sink_pads = _sink_pads; \
-  link->caps = NULL; \
-} G_STMT_END
-
-#define MAKE_REF(link, _src, _pads) \
-G_STMT_START { \
-  gchar *padname = _src; \
-  GSList *pads = _pads; \
-  if (padname) { \
-    while (*padname != '.') padname++; \
-    *padname = '\0'; \
-    padname++; \
-    if (*padname != '\0') \
-      pads = g_slist_prepend (pads, gst_parse_strdup (padname)); \
-  } \
-  MAKE_LINK (link, NULL, _src, pads, NULL, NULL, NULL); \
-} G_STMT_END
-
-static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object,
-                                gpointer data)
-{
-  DelayedSet *set = (DelayedSet *) data;
-  GParamSpec *pspec;
-  GValue v = { 0, }; 
-  GstObject *target = NULL;
-  GType value_type;
-
-  if (gst_child_proxy_lookup (GST_OBJECT (set->parent), set->name, &target, &pspec)) { 
-    value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-
-    GST_CAT_LOG (GST_CAT_PIPELINE, "parsing delayed property %s as a %s from %s", pspec->name,
-      g_type_name (value_type), set->value_str);
-    g_value_init (&v, value_type);
-    if (gst_value_deserialize (&v, set->value_str)) {
-      g_object_set_property (G_OBJECT (target), pspec->name, &v);
-    }
-    g_signal_handler_disconnect (child_proxy, set->signal_id);
-    g_free(set->name);
-    g_free(set->value_str);
-    g_free(set);
-  }
-
-  if (G_IS_VALUE (&v))
-    g_value_unset (&v);
-  if (target)
-    gst_object_unref (target);
-  return;
-}
-
-
-static void
-gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
-{
-  GParamSpec *pspec;
-  gchar *pos = value;
-  GValue v = { 0, }; 
-  GstObject *target = NULL;
-  GType value_type;
-
-  /* parse the string, so the property name is null-terminated an pos points
-     to the beginning of the value */
-  while (!g_ascii_isspace (*pos) && (*pos != '=')) pos++; 
-  if (*pos == '=') { 
-    *pos = '\0'; 
-  } else { 
-    *pos = '\0'; 
-    pos++;
-    while (g_ascii_isspace (*pos)) pos++; 
-  } 
-  pos++; 
-  while (g_ascii_isspace (*pos)) pos++; 
-  if (*pos == '"') {
-    pos++;
-    pos[strlen (pos) - 1] = '\0';
-  }
-  gst_parse_unescape (pos);
-
-  if (gst_child_proxy_lookup (GST_OBJECT (element), value, &target, &pspec)) { 
-    value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); 
-    GST_CAT_LOG (GST_CAT_PIPELINE, "parsing property %s as a %s", pspec->name,
-      g_type_name (value_type));
-    g_value_init (&v, value_type);
-    if (!gst_value_deserialize (&v, pos))
-      goto error;
-    g_object_set_property (G_OBJECT (target), pspec->name, &v);
-  } else { 
-    /* do a delayed set */
-    if (GST_IS_CHILD_PROXY (element)) {
-      DelayedSet *data = g_new (DelayedSet, 1);
-      
-      data->parent = element;
-      data->name = g_strdup(value);
-      data->value_str = g_strdup(pos);
-      data->signal_id = g_signal_connect(GST_OBJECT (element),"child-added", G_CALLBACK (gst_parse_new_child), data);
-    }
-    else {
-      SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
-          _("no property \"%s\" in element \"%s\""), value, \
-          GST_ELEMENT_NAME (element));
-    }
-      }
-
-out:
-  gst_parse_strfree (value);
-  if (G_IS_VALUE (&v))
-    g_value_unset (&v);
-  if (target)
-    gst_object_unref (target);
-  return;
-  
-error:
-  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
-         _("could not set property \"%s\" in element \"%s\" to \"%s\""), 
-	 value, GST_ELEMENT_NAME (element), pos); 
-  goto out;
-}
-static inline void
-gst_parse_free_link (link_t *link)
-{
-  gst_parse_strfree (link->src_name);
-  gst_parse_strfree (link->sink_name);
-  g_slist_foreach (link->src_pads, (GFunc) gst_parse_strfree, NULL);
-  g_slist_foreach (link->sink_pads, (GFunc) gst_parse_strfree, NULL);
-  g_slist_free (link->src_pads);
-  g_slist_free (link->sink_pads);
-  if (link->caps) gst_caps_unref (link->caps);
-  gst_parse_link_free (link);  
-}
-
-static void
-gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
-{
-  DelayedLink *link = (DelayedLink *) data;
-  
-  GST_CAT_INFO (GST_CAT_PIPELINE, "trying delayed linking %s:%s to %s:%s", 
-                GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
-                GST_STR_NULL (GST_ELEMENT_NAME (link->sink)), GST_STR_NULL (link->sink_pad));
-
-  if (gst_element_link_pads_filtered (src, link->src_pad, link->sink,
-      link->sink_pad, link->caps)) {
-    /* do this here, we don't want to get any problems later on when
-     * unlocking states */
-    GST_CAT_DEBUG (GST_CAT_PIPELINE, "delayed linking %s:%s to %s:%s worked", 
-               	   GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
-               	   GST_STR_NULL (GST_ELEMENT_NAME (link->sink)), GST_STR_NULL (link->sink_pad));
-    g_signal_handler_disconnect (src, link->signal_id);
-    g_free (link->src_pad);
-    g_free (link->sink_pad);
-    if (link->caps) gst_caps_unref (link->caps);
-    g_free (link);
-  }
-}
-/* both padnames and the caps may be NULL */
-static gboolean
-gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad, 
-                                GstElement *sink, const gchar *sink_pad,
-                                GstCaps *caps)
-{
-  GList *templs = gst_element_class_get_pad_template_list (
-      GST_ELEMENT_GET_CLASS (src));
-	 
-  for (; templs; templs = templs->next) {
-    GstPadTemplate *templ = (GstPadTemplate *) templs->data;
-    if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) &&
-        (GST_PAD_TEMPLATE_PRESENCE(templ) == GST_PAD_SOMETIMES))
-    {
-      DelayedLink *data = g_new (DelayedLink, 1); 
-      
-      /* TODO: maybe we should check if src_pad matches this template's names */
-
-      GST_CAT_DEBUG (GST_CAT_PIPELINE, "trying delayed link %s:%s to %s:%s", 
-                     GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (src_pad),
-                     GST_STR_NULL (GST_ELEMENT_NAME (sink)), GST_STR_NULL (sink_pad));
-
-      data->src_pad = g_strdup (src_pad);
-      data->sink = sink;
-      data->sink_pad = g_strdup (sink_pad);
-      if (caps) {
-      	data->caps = gst_caps_copy (caps);
-      } else {
-      	data->caps = NULL;
-      }
-      data->signal_id = g_signal_connect (G_OBJECT (src), "pad-added", 
-          G_CALLBACK (gst_parse_found_pad), data);
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-/*
- * performs a link and frees the struct. src and sink elements must be given
- * return values   0 - link performed
- *                 1 - link delayed
- *                <0 - error
- */
-static gint
-gst_parse_perform_link (link_t *link, graph_t *graph)
-{
-  GstElement *src = link->src;
-  GstElement *sink = link->sink;
-  GSList *srcs = link->src_pads;
-  GSList *sinks = link->sink_pads;
-  g_assert (GST_IS_ELEMENT (src));
-  g_assert (GST_IS_ELEMENT (sink));
-  
-  GST_CAT_INFO (GST_CAT_PIPELINE,
-      "linking %s:%s to %s:%s (%u/%u) with caps \"%" GST_PTR_FORMAT "\"", 
-      GST_ELEMENT_NAME (src), link->src_name ? link->src_name : "(any)",
-      GST_ELEMENT_NAME (sink), link->sink_name ? link->sink_name : "(any)",
-      g_slist_length (srcs), g_slist_length (sinks), link->caps);
-
-  if (!srcs || !sinks) {
-    if (gst_element_link_pads_filtered (src,
-        srcs ? (const gchar *) srcs->data : NULL, sink,
-        sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
-      goto success;
-    } else {
-      if (gst_parse_perform_delayed_link (src,
-          srcs ? (const gchar *) srcs->data : NULL,
-          sink, sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
-	goto success;
-      } else {
-        goto error;
-      }
-    }
-  }
-  if (g_slist_length (link->src_pads) != g_slist_length (link->src_pads)) {
-    goto error;
-  }
-  while (srcs && sinks) {
-    const gchar *src_pad = (const gchar *) srcs->data;
-    const gchar *sink_pad = (const gchar *) sinks->data;
-    srcs = g_slist_next (srcs);
-    sinks = g_slist_next (sinks);
-    if (gst_element_link_pads_filtered (src, src_pad, sink, sink_pad,
-        link->caps)) {
-      continue;
-    } else {
-      if (gst_parse_perform_delayed_link (src, src_pad,
-                                          sink, sink_pad,
-					  link->caps)) {
-	continue;
-      } else {
-        goto error;
-      }
-    }
-  }
-  
-success:
-  gst_parse_free_link (link);
-  return 0;
-  
-error:
-  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
-      _("could not link %s to %s"), GST_ELEMENT_NAME (src),
-      GST_ELEMENT_NAME (sink));
-  gst_parse_free_link (link);
-  return -1;
-}
-
-
-static int yyerror (void *scanner, graph_t *graph, const char *s);
-%}
-
-%union {
-    gchar *s;
-    chain_t *c;
-    link_t *l;
-    GstElement *e;
-    GSList *p;
-    graph_t *g;
-}
-
-%token <s> PARSE_URL
-%token <s> IDENTIFIER
-%left <s> REF PADREF BINREF
-%token <s> ASSIGNMENT
-%token <s> LINK
-
-%type <g> graph
-%type <c> chain bin
-%type <l> reference
-%type <l> linkpart link
-%type <p> linklist
-%type <e> element 
-%type <p> padlist pads assignments
-
-%left '(' ')'
-%left ','
-%right '.'
-%left '!' '='
-
-%parse-param { void *scanner }
-%parse-param { graph_t *graph }
-%pure-parser
-
-%start graph
-%%
-
-element:	IDENTIFIER     		      { $$ = gst_element_factory_make ($1, NULL); 
-						if ($$ == NULL) {
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1);
-						  gst_parse_strfree ($1);
-						  YYERROR;
-						}
-						gst_parse_strfree ($1);
-                                              }
-	|	element ASSIGNMENT	      { gst_parse_element_set ($2, $1, graph);
-						$$ = $1;
-	                                      }
-	;
-assignments:	/* NOP */		      { $$ = NULL; }
-	|	assignments ASSIGNMENT	      { $$ = g_slist_prepend ($1, $2); }
-	;		
-bin:	        '(' assignments chain ')' { GST_BIN_MAKE ($$, "bin", $3, $2, FALSE); }
-        |       BINREF assignments chain ')'  { GST_BIN_MAKE ($$, $1, $3, $2, TRUE); 
-						gst_parse_strfree ($1);
-					      }
-        |       BINREF assignments ')'	      { GST_BIN_MAKE ($$, $1, NULL, $2, TRUE); 
-						gst_parse_strfree ($1);
-					      }
-        |       BINREF assignments error ')'  { GST_BIN_MAKE ($$, $1, NULL, $2, TRUE); 
-						gst_parse_strfree ($1);
-					      }
-	;
-	
-pads:		PADREF 			      { $$ = g_slist_prepend (NULL, $1); }
-	|	PADREF padlist		      { $$ = $2;
-						$$ = g_slist_prepend ($$, $1);
-					      }				     
-	;
-padlist:	',' IDENTIFIER		      { $$ = g_slist_prepend (NULL, $2); }
-	|	',' IDENTIFIER padlist	      { $$ = g_slist_prepend ($3, $2); }
-	;
-	
-reference:	REF 			      { MAKE_REF ($$, $1, NULL); }
-	|	REF padlist		      { MAKE_REF ($$, $1, $2); }
-	;
-
-linkpart:	reference		      { $$ = $1; }
-	|	pads			      { MAKE_REF ($$, NULL, $1); }
-	|	/* NOP */		      { MAKE_REF ($$, NULL, NULL); }
-	;
-	
-link:		linkpart LINK linkpart	      { $$ = $1;
-						if ($2) {
-						  $$->caps = gst_caps_from_string ($2);
-						  if ($$->caps == NULL)
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $2);
-						  gst_parse_strfree ($2);
-						}
-						$$->sink_name = $3->src_name;
-						$$->sink_pads = $3->src_pads;
-						gst_parse_link_free ($3);
-					      }
-	;
-	
-linklist:	link			      { $$ = g_slist_prepend (NULL, $1); }
-	|	link linklist		      { $$ = g_slist_prepend ($2, $1); }
-	|	linklist error		      { $$ = $1; }
-	;	
-
-chain:   	element			      { $$ = gst_parse_chain_new ();
-						$$->first = $$->last = $1;
-						$$->front = $$->back = NULL;
-						$$->elements = g_slist_prepend (NULL, $1);
-					      }
-	|	bin			      { $$ = $1; }
-	|	chain chain		      { if ($1->back && $2->front) {
-						  if (!$1->back->sink_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-						    gst_parse_free_link ($1->back);
-						  } else {
-						    ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $1->back);
-						  }
-						  if (!$2->front->src_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
-						    gst_parse_free_link ($2->front);
-						  } else {
-						    ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
-						  }
-						  $1->back = NULL;
-						} else if ($1->back) {
-						  if (!$1->back->sink_name) {
-						    $1->back->sink = $2->first;
-						  }
-						} else if ($2->front) {
-						  if (!$2->front->src_name) {
-						    $2->front->src = $1->last;
-						  }
-						  $1->back = $2->front;
-						}
-						
-						if ($1->back) {
-						  ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $1->back);
-						}
-						$1->last = $2->last;
-						$1->back = $2->back;
-						$1->elements = g_slist_concat ($1->elements, $2->elements);
-						if ($2)
-						  gst_parse_chain_free ($2);
-						$$ = $1;
-					      }
-	|	chain linklist		      { GSList *walk;
-						if ($1->back) {
-						  $2 = g_slist_prepend ($2, $1->back);
-						  $1->back = NULL;
-						} else {
-						  if (!((link_t *) $2->data)->src_name) {
-						    ((link_t *) $2->data)->src = $1->last;
-						  }						  
-						}
-						for (walk = $2; walk; walk = walk->next) {
-						  link_t *link = (link_t *) walk->data;
-						  if (!link->sink_name && walk->next) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
-						    gst_parse_free_link (link);
-						  } else if (!link->src_name && !link->src) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-						    gst_parse_free_link (link);
-						  } else {
-						    if (walk->next) {
-						      ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, link);
-						    } else {
-						      $1->back = link;
-						    }
-						  }
-						}
-						g_slist_free ($2);
-						$$ = $1;
-					      }
-	|	chain error		      { $$ = $1; }
-	|	link chain		      { if ($2->front) {
-						  if (!$2->front->src_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-						    gst_parse_free_link ($2->front);
-						  } else {
-						    ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
-						  }
-						}
-						if (!$1->sink_name) {
-						  $1->sink = $2->first;
-						}
-						$2->front = $1;
-						$$ = $2;
-					      }
-	|	PARSE_URL chain		      { $$ = $2;
-						if ($$->front) {
-						  GstElement *element = 
-							  gst_element_make_from_uri (GST_URI_SRC, $1, NULL);
-						  if (!element) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
-							    _("no source element for URI \"%s\""), $1);
-						  } else {
-						    $$->front->src = element;
-						    ((graph_t *) graph)->links = g_slist_prepend (
-							    ((graph_t *) graph)->links, $$->front);
-						    $$->front = NULL;
-						    $$->elements = g_slist_prepend ($$->elements, element);
-						  }
-						} else {
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, 
-							  _("no element to link URI \"%s\" to"), $1);
-						}
-						g_free ($1);
-					      }
-	|	link PARSE_URL		      { GstElement *element =
-							  gst_element_make_from_uri (GST_URI_SINK, $2, NULL);
-						if (!element) {
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, 
-							  _("no sink element for URI \"%s\""), $2);
-						  gst_parse_link_free ($1);
-						  g_free ($2);
-						  YYERROR;
-						} else if ($1->sink_name || $1->sink_pads) {
-                                                  gst_object_unref (element);
-						  SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, 
-							  _("could not link sink element for URI \"%s\""), $2);
-						  gst_parse_link_free ($1);
-						  g_free ($2);
-						  YYERROR;
-						} else {
-						  $$ = gst_parse_chain_new ();
-						  $$->first = $$->last = element;
-						  $$->front = $1;
-						  $$->front->sink = element;
-						  $$->elements = g_slist_prepend (NULL, element);
-						}
-						g_free ($2);
-					      }
-	;
-graph:		/* NOP */		      { SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
-						$$ = (graph_t *) graph;
-					      }
-	|	chain			      { $$ = (graph_t *) graph;
-						if ($1->front) {
-						  if (!$1->front->src_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-						    gst_parse_free_link ($1->front);
-						  } else {
-						    $$->links = g_slist_prepend ($$->links, $1->front);
-						  }
-						  $1->front = NULL;
-						}
-						if ($1->back) {
-						  if (!$1->back->sink_name) {
-						    SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
-						    gst_parse_free_link ($1->back);
-						  } else {
-						    $$->links = g_slist_prepend ($$->links, $1->back);
-						  }
-						  $1->back = NULL;
-						}
-						$$->chain = $1;
-					      }
-	;
-
-%%
-
-
-static int
-yyerror (void *scanner, graph_t *graph, const char *s)
-{
-  /* FIXME: This should go into the GError somehow, but how? */
-  GST_WARNING ("Error during parsing: %s", s);
-  return -1;
-}
-
-
-GstElement *
-_gst_parse_launch (const gchar *str, GError **error)
-{
-  graph_t g;
-  gchar *dstr;
-  GSList *walk;
-  GstBin *bin = NULL;
-  GstElement *ret;
-  yyscan_t scanner;
-
-  g_return_val_if_fail (str != NULL, NULL);
-
-  g.chain = NULL;
-  g.links = NULL;
-  g.error = error;
-  
-#ifdef __GST_PARSE_TRACE
-  GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
-  __strings = __chains = __links = 0;
-#endif /* __GST_PARSE_TRACE */
-
-  dstr = g_strdup (str);
-  _gst_parse_yylex_init (&scanner);
-  _gst_parse_yy_scan_string (dstr, scanner);
-
-#ifndef YYDEBUG
-  yydebug = 1;
-#endif
-
-  if (yyparse (scanner, &g) != 0) {
-    SET_ERROR (error, GST_PARSE_ERROR_SYNTAX,
-        "Unrecoverable syntax error while parsing pipeline %s", str);
-    
-    _gst_parse_yylex_destroy (scanner);
-    g_free (dstr);
-  
-    goto error1;
-  }
-  _gst_parse_yylex_destroy (scanner);
-  g_free (dstr);
-  
-  GST_CAT_DEBUG (GST_CAT_PIPELINE, "got %u elements and %u links",
-      g.chain ? g_slist_length (g.chain->elements) : 0,
-      g_slist_length (g.links));
-  
-  if (!g.chain) {
-    ret = NULL;
-  } else if (!(((chain_t *) g.chain)->elements->next)) {
-    /* only one toplevel element */  
-    ret = (GstElement *) ((chain_t *) g.chain)->elements->data;
-    g_slist_free (((chain_t *) g.chain)->elements);
-    if (GST_IS_BIN (ret))
-      bin = GST_BIN (ret);
-    gst_parse_chain_free (g.chain);
-  } else {  
-    /* put all elements in our bin */
-    bin = GST_BIN (gst_element_factory_make ("pipeline", NULL));
-    g_assert (bin);
-    
-    for (walk = g.chain->elements; walk; walk = walk->next) {
-      if (walk->data != NULL)
-        gst_bin_add (bin, GST_ELEMENT (walk->data));
-    }
-    
-    g_slist_free (g.chain->elements);
-    ret = GST_ELEMENT (bin);
-    gst_parse_chain_free (g.chain);
-  }
-  
-  /* remove links */
-  for (walk = g.links; walk; walk = walk->next) {
-    link_t *l = (link_t *) walk->data;
-    if (!l->src) {
-      if (l->src_name) {
-        if (bin) {
-          l->src = gst_bin_get_by_name_recurse_up (bin, l->src_name);
-          if (l->src)
-            gst_object_unref (l->src);
-        } else {
-          l->src = strcmp (GST_ELEMENT_NAME (ret), l->src_name) == 0 ? ret : NULL;
-        }
-      }
-      if (!l->src) {
-        SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            "No element named \"%s\" - omitting link", l->src_name);
-        gst_parse_free_link (l);
-        continue;
-      }
-    }
-    if (!l->sink) {
-      if (l->sink_name) {
-        if (bin) {
-          l->sink = gst_bin_get_by_name_recurse_up (bin, l->sink_name);
-          if (l->sink)
-            gst_object_unref (l->sink);
-        } else {
-          l->sink = strcmp (GST_ELEMENT_NAME (ret), l->sink_name) == 0 ? ret : NULL;
-        }
-      }
-      if (!l->sink) {
-        SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-            "No element named \"%s\" - omitting link", l->sink_name);
-        gst_parse_free_link (l);
-        continue;
-      }
-    }
-    gst_parse_perform_link (l, &g);
-  }
-  g_slist_free (g.links);
-
-out:
-#ifdef __GST_PARSE_TRACE
-  GST_CAT_DEBUG (GST_CAT_PIPELINE,
-      "TRACE: %u strings, %u chains and %u links left", __strings, __chains,
-      __links);
-  if (__strings || __chains || __links) {
-    g_warning ("TRACE: %u strings, %u chains and %u links left", __strings,
-        __chains, __links);
-  }
-#endif /* __GST_PARSE_TRACE */
-
-  return ret;
-  
-error1:
-  if (g.chain) {
-    g_slist_foreach (g.chain->elements, (GFunc)gst_object_unref, NULL);
-    g_slist_free (g.chain->elements);
-    gst_parse_chain_free (g.chain);
-  }
-
-  g_slist_foreach (g.links, (GFunc)gst_parse_free_link, NULL);
-  g_slist_free (g.links);
-  
-  if (error)
-    g_assert (*error);
-  ret = NULL;
-  
-  goto out;
-}
--- a/gstreamer_core/tools/gst-inspect.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1399 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *               2000 Wim Taymans <wtay@chello.be>
- *               2004 Thomas Vander Stichele <thomas@apestaart.org>
- *
- * gst-inspect.c: tool to inspect the GStreamer registry
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <gst/controller/gstcontroller.h>
-
-#include "tools.h"
-
-#include <string.h>
-#include <locale.h>
-#include <glib/gprintf.h>
-
-static char *_name = NULL;
-
-static int print_element_info (GstElementFactory * factory,
-    gboolean print_names);
-
-static void
-n_print (const char *format, ...)
-{
-  va_list args;
-  gint retval;
-
-  if (_name)
-    g_print (_name);
-
-  va_start (args, format);
-  retval = g_vprintf (format, args);
-  va_end (args);
-}
-
-static gboolean
-print_field (GQuark field, const GValue * value, gpointer pfx)
-{
-  gchar *str = gst_value_serialize (value);
-
-  n_print ("%s  %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
-  g_free (str);
-  return TRUE;
-}
-
-static void
-print_caps (const GstCaps * caps, const gchar * pfx)
-{
-  guint i;
-
-  g_return_if_fail (caps != NULL);
-
-  if (gst_caps_is_any (caps)) {
-    n_print ("%sANY\n", pfx);
-    return;
-  }
-  if (gst_caps_is_empty (caps)) {
-    n_print ("%sEMPTY\n", pfx);
-    return;
-  }
-
-  for (i = 0; i < gst_caps_get_size (caps); i++) {
-    GstStructure *structure = gst_caps_get_structure (caps, i);
-
-    n_print ("%s%s\n", pfx, gst_structure_get_name (structure));
-    gst_structure_foreach (structure, print_field, (gpointer) pfx);
-  }
-}
-
-#if 0
-static void
-print_formats (const GstFormat * formats)
-{
-  while (formats && *formats) {
-    const GstFormatDefinition *definition;
-
-    definition = gst_format_get_details (*formats);
-    if (definition)
-      n_print ("\t\t(%d):\t%s (%s)\n", *formats,
-          definition->nick, definition->description);
-    else
-      n_print ("\t\t(%d):\tUnknown format\n", *formats);
-
-    formats++;
-  }
-}
-#endif
-
-static void
-print_query_types (const GstQueryType * types)
-{
-  while (types && *types) {
-    const GstQueryTypeDefinition *definition;
-
-    definition = gst_query_type_get_details (*types);
-    if (definition)
-      n_print ("\t\t(%d):\t%s (%s)\n", *types,
-          definition->nick, definition->description);
-    else
-      n_print ("\t\t(%d):\tUnknown query format\n", *types);
-
-    types++;
-  }
-}
-
-#ifndef GST_DISABLE_ENUMTYPES
-#if 0
-static void
-print_event_masks (const GstEventMask * masks)
-{
-  GType event_type;
-  GEnumClass *klass;
-  GType event_flags;
-  GFlagsClass *flags_class = NULL;
-
-  event_type = gst_event_type_get_type ();
-  klass = (GEnumClass *) g_type_class_ref (event_type);
-
-  while (masks && masks->type) {
-    GEnumValue *value;
-    gint flags = 0, index = 0;
-
-    switch (masks->type) {
-      case GST_EVENT_SEEK:
-        flags = masks->flags;
-        event_flags = gst_seek_type_get_type ();
-        flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
-        break;
-      default:
-        break;
-    }
-
-    value = g_enum_get_value (klass, masks->type);
-    g_print ("\t\t%s ", value->value_nick);
-
-    while (flags) {
-      GFlagsValue *value;
-
-      if (flags & 1) {
-        value = g_flags_get_first_value (flags_class, 1 << index);
-
-        if (value)
-          g_print ("| %s ", value->value_nick);
-        else
-          g_print ("| ? ");
-      }
-      flags >>= 1;
-      index++;
-    }
-    g_print ("\n");
-
-    masks++;
-  }
-}
-#endif
-#else
-static void
-print_event_masks (const GstEventMask * masks)
-{
-}
-#endif
-
-static char *
-get_rank_name (gint rank)
-{
-  switch (rank) {
-    case GST_RANK_NONE:
-      return "none";
-    case GST_RANK_MARGINAL:
-      return "marginal";
-    case GST_RANK_SECONDARY:
-      return "secondary";
-    case GST_RANK_PRIMARY:
-      return "primary";
-    default:
-      return "unknown";
-  }
-}
-
-static void
-print_factory_details_info (GstElementFactory * factory)
-{
-  n_print ("Factory Details:\n");
-  n_print ("  Long name:\t%s\n", factory->details.longname);
-  n_print ("  Class:\t%s\n", factory->details.klass);
-  n_print ("  Description:\t%s\n", factory->details.description);
-  n_print ("  Author(s):\t%s\n", factory->details.author);
-  n_print ("  Rank:\t\t%s (%d)\n",
-      get_rank_name (GST_PLUGIN_FEATURE (factory)->rank),
-      GST_PLUGIN_FEATURE (factory)->rank);
-  n_print ("\n");
-}
-
-static void
-print_hierarchy (GType type, gint level, gint * maxlevel)
-{
-  GType parent;
-  gint i;
-
-  parent = g_type_parent (type);
-
-  *maxlevel = *maxlevel + 1;
-  level++;
-
-  if (parent)
-    print_hierarchy (parent, level, maxlevel);
-
-  if (_name)
-    g_print (_name);
-
-  for (i = 1; i < *maxlevel - level; i++)
-    g_print ("      ");
-  if (*maxlevel - level)
-    g_print (" +----");
-
-  g_print ("%s\n", g_type_name (type));
-
-  if (level == 1)
-    n_print ("\n");
-}
-
-static void
-print_interfaces (GType type)
-{
-  guint n_ifaces;
-  GType *iface, *ifaces = g_type_interfaces (type, &n_ifaces);
-
-  if (ifaces) {
-    if (n_ifaces) {
-      if (_name)
-        g_print (_name);
-      g_print (_("Implemented Interfaces:\n"));
-      iface = ifaces;
-      while (*iface) {
-        if (_name)
-          g_print (_name);
-        g_print ("  %s\n", g_type_name (*iface));
-        iface++;
-      }
-      if (_name)
-        g_print (_name);
-      g_print ("\n");
-    }
-    g_free (ifaces);
-  }
-}
-
-static void
-print_element_properties_info (GstElement * element)
-{
-  GParamSpec **property_specs;
-  guint num_properties, i;
-  gboolean readable;
-  gboolean first_flag;
-
-  property_specs = g_object_class_list_properties
-      (G_OBJECT_GET_CLASS (element), &num_properties);
-  n_print ("\n");
-  n_print ("Element Properties:\n");
-
-  for (i = 0; i < num_properties; i++) {
-    GValue value = { 0, };
-    GParamSpec *param = property_specs[i];
-
-    readable = FALSE;
-
-    g_value_init (&value, param->value_type);
-
-    n_print ("  %-20s: %s\n", g_param_spec_get_name (param),
-        g_param_spec_get_blurb (param));
-
-    first_flag = TRUE;
-    n_print ("%-23.23s flags: ", "");
-    if (param->flags & G_PARAM_READABLE) {
-      g_object_get_property (G_OBJECT (element), param->name, &value);
-      readable = TRUE;
-      if (!first_flag)
-        g_print (", ");
-      else
-        first_flag = FALSE;
-      g_print (_("readable"));
-    }
-    if (param->flags & G_PARAM_WRITABLE) {
-      if (!first_flag)
-        g_print (", ");
-      else
-        first_flag = FALSE;
-      g_print (_("writable"));
-    }
-    if (param->flags & GST_PARAM_CONTROLLABLE) {
-      if (!first_flag)
-        g_print (", ");
-      else
-        first_flag = FALSE;
-      g_print (_("controllable"));
-    }
-    n_print ("\n");
-
-    switch (G_VALUE_TYPE (&value)) {
-      case G_TYPE_STRING:
-      {
-        GParamSpecString *pstring = G_PARAM_SPEC_STRING (param);
-
-        n_print ("%-23.23s String. ", "");
-
-        if (pstring->default_value == NULL)
-          g_print ("Default: null ");
-        else
-          g_print ("Default: \"%s\" ", pstring->default_value);
-
-        if (readable) {
-          const char *string_val = g_value_get_string (&value);
-
-          if (string_val == NULL)
-            g_print ("Current: null");
-          else
-            g_print ("Current: \"%s\"", string_val);
-        }
-        break;
-      }
-      case G_TYPE_BOOLEAN:
-      {
-        GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (param);
-
-        n_print ("%-23.23s Boolean. ", "");
-        g_print ("Default: %s ", (pboolean->default_value ? "true" : "false"));
-        if (readable)
-          g_print ("Current: %s",
-              (g_value_get_boolean (&value) ? "true" : "false"));
-        break;
-      }
-      case G_TYPE_ULONG:
-      {
-        GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
-
-        n_print ("%-23.23s Unsigned Long. ", "");
-        g_print ("Range: %lu - %lu Default: %lu ",
-            pulong->minimum, pulong->maximum, pulong->default_value);
-        if (readable)
-          g_print ("Current: %lu", g_value_get_ulong (&value));
-        break;
-      }
-      case G_TYPE_LONG:
-      {
-        GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
-
-        n_print ("%-23.23s Long. ", "");
-        g_print ("Range: %ld - %ld Default: %ld ",
-            plong->minimum, plong->maximum, plong->default_value);
-        if (readable)
-          g_print ("Current: %ld", g_value_get_long (&value));
-        break;
-      }
-      case G_TYPE_UINT:
-      {
-        GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
-
-        n_print ("%-23.23s Unsigned Integer. ", "");
-        g_print ("Range: %u - %u Default: %u ",
-            puint->minimum, puint->maximum, puint->default_value);
-        if (readable)
-          g_print ("Current: %u", g_value_get_uint (&value));
-        break;
-      }
-      case G_TYPE_INT:
-      {
-        GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
-
-        n_print ("%-23.23s Integer. ", "");
-        g_print ("Range: %d - %d Default: %d ",
-            pint->minimum, pint->maximum, pint->default_value);
-        if (readable)
-          g_print ("Current: %d", g_value_get_int (&value));
-        break;
-      }
-      case G_TYPE_UINT64:
-      {
-        GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
-
-        n_print ("%-23.23s Unsigned Integer64. ", "");
-        g_print ("Range: %" G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT
-            " Default: %" G_GUINT64_FORMAT " ",
-            puint64->minimum, puint64->maximum, puint64->default_value);
-        if (readable)
-          g_print ("Current: %" G_GUINT64_FORMAT, g_value_get_uint64 (&value));
-        break;
-      }
-      case G_TYPE_INT64:
-      {
-        GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
-
-        n_print ("%-23.23s Integer64. ", "");
-        g_print ("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT
-            " Default: %" G_GINT64_FORMAT " ",
-            pint64->minimum, pint64->maximum, pint64->default_value);
-        if (readable)
-          g_print ("Current: %" G_GINT64_FORMAT, g_value_get_int64 (&value));
-        break;
-      }
-      case G_TYPE_FLOAT:
-      {
-        GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
-
-        n_print ("%-23.23s Float. ", "");
-        g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
-            pfloat->minimum, pfloat->maximum, pfloat->default_value);
-        if (readable)
-          g_print ("Current: %15.7g", g_value_get_float (&value));
-        break;
-      }
-      case G_TYPE_DOUBLE:
-      {
-        GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
-
-        n_print ("%-23.23s Double. ", "");
-        g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
-            pdouble->minimum, pdouble->maximum, pdouble->default_value);
-        if (readable)
-          g_print ("Current: %15.7g", g_value_get_double (&value));
-        break;
-      }
-      default:
-        if (param->value_type == GST_TYPE_CAPS) {
-          const GstCaps *caps = gst_value_get_caps (&value);
-
-          if (!caps)
-            n_print ("%-23.23s Caps (NULL)", "");
-          else {
-            print_caps (caps, "                           ");
-          }
-        } else if (G_IS_PARAM_SPEC_ENUM (param)) {
-          GParamSpecEnum *penum = G_PARAM_SPEC_ENUM (param);
-          GEnumValue *values;
-          guint j = 0;
-          gint enum_value;
-          const gchar *def_val_nick = "", *cur_val_nick = "";
-
-          values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
-          enum_value = g_value_get_enum (&value);
-
-          while (values[j].value_name) {
-            if (values[j].value == enum_value)
-              cur_val_nick = values[j].value_nick;
-            if (values[j].value == penum->default_value)
-              def_val_nick = values[j].value_nick;
-            j++;
-          }
-
-          n_print
-              ("%-23.23s Enum \"%s\" Default: %d, \"%s\" Current: %d, \"%s\"",
-              "", g_type_name (G_VALUE_TYPE (&value)), penum->default_value,
-              def_val_nick, enum_value, cur_val_nick);
-
-          j = 0;
-          while (values[j].value_name) {
-            g_print ("\n");
-            if (_name)
-              g_print (_name);
-            g_print ("%-23.23s    (%d): %-16s - %s", "",
-                values[j].value, values[j].value_nick, values[j].value_name);
-            j++;
-          }
-          /* g_type_class_unref (ec); */
-        } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
-          GParamSpecFlags *pflags = G_PARAM_SPEC_FLAGS (param);
-          GFlagsValue *values;
-          guint j = 0;
-          gint flags_value;
-          GString *cur_flags = NULL, *def_flags = NULL;
-
-          values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
-          flags_value = g_value_get_flags (&value);
-
-          while (values[j].value_name) {
-            if (values[j].value & flags_value) {
-              if (cur_flags) {
-                g_string_append_printf (cur_flags, " | %s",
-                    values[j].value_nick);
-              } else {
-                cur_flags = g_string_new (values[j].value_nick);
-              }
-            }
-            if (values[j].value & pflags->default_value) {
-              if (def_flags) {
-                g_string_append_printf (def_flags, " | %s",
-                    values[j].value_nick);
-              } else {
-                def_flags = g_string_new (values[j].value_nick);
-              }
-            }
-            j++;
-          }
-
-          n_print
-              ("%-23.23s Flags \"%s\" Default: 0x%08x, \"%s\" Current: 0x%08x, \"%s\"",
-              "", g_type_name (G_VALUE_TYPE (&value)), pflags->default_value,
-              (def_flags ? def_flags->str : "(none)"), flags_value,
-              (cur_flags ? cur_flags->str : "(none)"));
-
-          j = 0;
-          while (values[j].value_name) {
-            g_print ("\n");
-            if (_name)
-              g_print (_name);
-            g_print ("%-23.23s    (0x%08x): %-16s - %s", "",
-                values[j].value, values[j].value_nick, values[j].value_name);
-            j++;
-          }
-
-          if (cur_flags)
-            g_string_free (cur_flags, TRUE);
-          if (def_flags)
-            g_string_free (def_flags, TRUE);
-        } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
-          n_print ("%-23.23s Object of type \"%s\"", "",
-              g_type_name (param->value_type));
-        } else if (G_IS_PARAM_SPEC_BOXED (param)) {
-          n_print ("%-23.23s Boxed pointer of type \"%s\"", "",
-              g_type_name (param->value_type));
-        } else if (G_IS_PARAM_SPEC_POINTER (param)) {
-          if (param->value_type != G_TYPE_POINTER) {
-            n_print ("%-23.23s Pointer of type \"%s\".", "",
-                g_type_name (param->value_type));
-          } else {
-            n_print ("%-23.23s Pointer.", "");
-          }
-        } else if (param->value_type == G_TYPE_VALUE_ARRAY) {
-          n_print ("%-23.23s Array of GValues", "");
-        } else if (GST_IS_PARAM_SPEC_FRACTION (param)) {
-          GstParamSpecFraction *pfraction = GST_PARAM_SPEC_FRACTION (param);
-
-          n_print ("%-23.23s Fraction. ", "");
-
-          g_print ("Range: %d/%d - %d/%d Default: %d/%d ",
-              pfraction->min_num, pfraction->min_den,
-              pfraction->max_num, pfraction->max_den,
-              pfraction->def_num, pfraction->def_den);
-          if (readable)
-            g_print ("Current: %d/%d",
-                gst_value_get_fraction_numerator (&value),
-                gst_value_get_fraction_denominator (&value));
-
-        } else {
-          n_print ("%-23.23s Unknown type %ld \"%s\"", "", param->value_type,
-              g_type_name (param->value_type));
-        }
-        break;
-    }
-    if (!readable)
-      g_print (" Write only\n");
-    else
-      g_print ("\n");
-
-    g_value_reset (&value);
-  }
-  if (num_properties == 0)
-    n_print ("  none\n");
-
-  g_free (property_specs);
-}
-
-static void
-print_pad_templates_info (GstElement * element, GstElementFactory * factory)
-{
-  GstElementClass *gstelement_class;
-  const GList *pads;
-  GstStaticPadTemplate *padtemplate;
-
-  n_print ("Pad Templates:\n");
-  if (!factory->numpadtemplates) {
-    n_print ("  none\n");
-    return;
-  }
-
-  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
-
-  pads = factory->staticpadtemplates;
-  while (pads) {
-    padtemplate = (GstStaticPadTemplate *) (pads->data);
-    pads = g_list_next (pads);
-
-    if (padtemplate->direction == GST_PAD_SRC)
-      n_print ("  SRC template: '%s'\n", padtemplate->name_template);
-    else if (padtemplate->direction == GST_PAD_SINK)
-      n_print ("  SINK template: '%s'\n", padtemplate->name_template);
-    else
-      n_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
-
-    if (padtemplate->presence == GST_PAD_ALWAYS)
-      n_print ("    Availability: Always\n");
-    else if (padtemplate->presence == GST_PAD_SOMETIMES)
-      n_print ("    Availability: Sometimes\n");
-    else if (padtemplate->presence == GST_PAD_REQUEST) {
-      n_print ("    Availability: On request\n");
-      n_print ("      Has request_new_pad() function: %s\n",
-          GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
-    } else
-      n_print ("    Availability: UNKNOWN!!!\n");
-
-    if (padtemplate->static_caps.string) {
-      n_print ("    Capabilities:\n");
-      print_caps (gst_static_caps_get (&padtemplate->static_caps), "      ");
-    }
-
-    n_print ("\n");
-  }
-}
-
-static void
-print_element_flag_info (GstElement * element)
-{
-  gboolean have_flags = FALSE;
-
-  n_print ("\n");
-  n_print ("Element Flags:\n");
-
-  if (!have_flags)
-    n_print ("  no flags set\n");
-
-  if (GST_IS_BIN (element)) {
-    n_print ("\n");
-    n_print ("Bin Flags:\n");
-    if (!have_flags)
-      n_print ("  no flags set\n");
-  }
-}
-
-static void
-print_implementation_info (GstElement * element)
-{
-  GstObjectClass *gstobject_class;
-  GstElementClass *gstelement_class;
-
-  gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
-  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
-
-  n_print ("\n");
-  n_print ("Element Implementation:\n");
-
-  n_print ("  Has change_state() function: %s\n",
-      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
-#ifndef GST_DISABLE_LOADSAVE
-  n_print ("  Has custom save_thyself() function: %s\n",
-      GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
-  n_print ("  Has custom restore_thyself() function: %s\n",
-      GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
-#endif
-}
-
-static void
-print_clocking_info (GstElement * element)
-{
-  if (!gst_element_requires_clock (element) &&
-      !(gst_element_provides_clock (element) &&
-          gst_element_get_clock (element))) {
-    n_print ("\n");
-    n_print ("Element has no clocking capabilities.");
-    return;
-  }
-
-  n_print ("\n");
-  n_print ("Clocking Interaction:\n");
-  if (gst_element_requires_clock (element)) {
-    n_print ("  element requires a clock\n");
-  }
-
-  if (gst_element_provides_clock (element)) {
-    GstClock *clock;
-
-    clock = gst_element_get_clock (element);
-    if (clock)
-      n_print ("  element provides a clock: %s\n", GST_OBJECT_NAME (clock));
-    else
-      n_print ("  element is supposed to provide a clock but returned NULL\n");
-  }
-}
-
-#ifndef GST_DISABLE_INDEX
-static void
-print_index_info (GstElement * element)
-{
-  if (gst_element_is_indexable (element)) {
-    n_print ("\n");
-    n_print ("Indexing capabilities:\n");
-    n_print ("  element can do indexing\n");
-  } else {
-    n_print ("\n");
-    n_print ("Element has no indexing capabilities.\n");
-  }
-}
-#else
-static void
-print_index_info (GstElement * element)
-{
-}
-#endif
-
-static void
-print_pad_info (GstElement * element)
-{
-  const GList *pads;
-  GstPad *pad;
-
-  n_print ("\n");
-  n_print ("Pads:\n");
-
-  if (!element->numpads) {
-    n_print ("  none\n");
-    return;
-  }
-
-  pads = element->pads;
-  while (pads) {
-    gchar *name;
-
-    pad = GST_PAD (pads->data);
-    pads = g_list_next (pads);
-
-    n_print ("");
-
-    name = gst_pad_get_name (pad);
-    if (gst_pad_get_direction (pad) == GST_PAD_SRC)
-      g_print ("  SRC: '%s'", name);
-    else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
-      g_print ("  SINK: '%s'", name);
-    else
-      g_print ("  UNKNOWN!!!: '%s'", name);
-
-    g_free (name);
-
-    g_print ("\n");
-
-    n_print ("    Implementation:\n");
-    if (pad->chainfunc)
-      n_print ("      Has chainfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
-    if (pad->getrangefunc)
-      n_print ("      Has getrangefunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
-    if (pad->eventfunc != gst_pad_event_default)
-      n_print ("      Has custom eventfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
-    if (pad->queryfunc != gst_pad_query_default)
-      n_print ("      Has custom queryfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
-    if (pad->querytypefunc != gst_pad_get_query_types_default) {
-      n_print ("        Provides query types:\n");
-      print_query_types (gst_pad_get_query_types (pad));
-    }
-
-    if (pad->intlinkfunc != gst_pad_get_internal_links_default)
-      n_print ("      Has custom intconnfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->intlinkfunc));
-
-    if (pad->bufferallocfunc)
-      n_print ("      Has bufferallocfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
-
-    if (pad->padtemplate)
-      n_print ("    Pad Template: '%s'\n", pad->padtemplate->name_template);
-
-    if (pad->caps) {
-      n_print ("    Capabilities:\n");
-      print_caps (pad->caps, "      ");
-    }
-  }
-}
-
-#if 0
-static gint
-compare_signal_names (GSignalQuery * a, GSignalQuery * b)
-{
-  return strcmp (a->signal_name, b->signal_name);
-}
-#endif
-
-static void
-print_signal_info (GstElement * element)
-{
-  /* Signals/Actions Block */
-  guint *signals;
-  guint nsignals;
-  gint i = 0, j, k;
-  GSignalQuery *query = NULL;
-  GType type;
-  GSList *found_signals, *l;
-
-  for (k = 0; k < 2; k++) {
-    found_signals = NULL;
-    for (type = G_OBJECT_TYPE (element); type; type = g_type_parent (type)) {
-      if (type == GST_TYPE_ELEMENT || type == GST_TYPE_OBJECT)
-        break;
-
-      if (type == GST_TYPE_BIN && G_OBJECT_TYPE (element) != GST_TYPE_BIN)
-        continue;
-
-      signals = g_signal_list_ids (type, &nsignals);
-      for (i = 0; i < nsignals; i++) {
-        query = g_new0 (GSignalQuery, 1);
-        g_signal_query (signals[i], query);
-
-        if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
-            (k == 1 && (query->signal_flags & G_SIGNAL_ACTION)))
-          found_signals = g_slist_append (found_signals, query);
-        else
-          g_free (query);
-      }
-      g_free (signals);
-      signals = NULL;
-    }
-
-    if (found_signals) {
-      n_print ("\n");
-      if (k == 0)
-        n_print ("Element Signals:\n");
-      else
-        n_print ("Element Actions:\n");
-    } else {
-      continue;
-    }
-
-    for (l = found_signals; l; l = l->next) {
-      gchar *indent;
-      int indent_len;
-
-      query = (GSignalQuery *) l->data;
-      indent_len = strlen (query->signal_name) +
-          strlen (g_type_name (query->return_type)) + 24;
-
-      indent = g_new0 (gchar, indent_len + 1);
-      memset (indent, ' ', indent_len);
-
-      n_print ("  \"%s\" :  %s user_function (%s* object",
-          query->signal_name,
-          g_type_name (query->return_type), g_type_name (type));
-
-      for (j = 0; j < query->n_params; j++) {
-        if (_name)
-          g_print (_name);
-        if (G_TYPE_IS_FUNDAMENTAL (query->param_types[j])) {
-          g_print (",\n%s%s arg%d", indent,
-              g_type_name (query->param_types[j]), j);
-        } else if (G_TYPE_IS_ENUM (query->param_types[j])) {
-          g_print (",\n%s%s arg%d", indent,
-              g_type_name (query->param_types[j]), j);
-        } else {
-          g_print (",\n%s%s* arg%d", indent,
-              g_type_name (query->param_types[j]), j);
-        }
-      }
-
-      if (k == 0) {
-        if (_name)
-          g_print (_name);
-        g_print (",\n%sgpointer user_data);\n", indent);
-      } else
-        g_print (");\n");
-
-      g_free (indent);
-    }
-
-    if (found_signals) {
-      g_slist_foreach (found_signals, (GFunc) g_free, NULL);
-      g_slist_free (found_signals);
-    }
-  }
-}
-
-static void
-print_children_info (GstElement * element)
-{
-  GList *children;
-
-  if (!GST_IS_BIN (element))
-    return;
-
-  children = (GList *) GST_BIN (element)->children;
-  if (children) {
-    n_print ("\n");
-    g_print ("Children:\n");
-  }
-
-  while (children) {
-    n_print ("  %s\n", GST_ELEMENT_NAME (GST_ELEMENT (children->data)));
-    children = g_list_next (children);
-  }
-}
-
-static void
-print_element_list (gboolean print_all)
-{
-  int plugincount = 0, featurecount = 0;
-  GList *plugins, *orig_plugins;
-
-  orig_plugins = plugins = gst_default_registry_get_plugin_list ();
-  while (plugins) {
-    GList *features, *orig_features;
-    GstPlugin *plugin;
-
-    plugin = (GstPlugin *) (plugins->data);
-    plugins = g_list_next (plugins);
-    plugincount++;
-
-    orig_features = features =
-        gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
-        plugin->desc.name);
-    while (features) {
-      GstPluginFeature *feature;
-
-      feature = GST_PLUGIN_FEATURE (features->data);
-      featurecount++;
-
-      if (GST_IS_ELEMENT_FACTORY (feature)) {
-        GstElementFactory *factory;
-
-        factory = GST_ELEMENT_FACTORY (feature);
-        if (print_all)
-          print_element_info (factory, TRUE);
-        else
-          g_print ("%s:  %s: %s\n", plugin->desc.name,
-              GST_PLUGIN_FEATURE_NAME (factory),
-              gst_element_factory_get_longname (factory));
-      }
-#ifndef GST_DISABLE_INDEX
-      else if (GST_IS_INDEX_FACTORY (feature)) {
-        GstIndexFactory *factory;
-
-        factory = GST_INDEX_FACTORY (feature);
-        if (!print_all)
-          g_print ("%s:  %s: %s\n", plugin->desc.name,
-              GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
-      }
-#endif
-      else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
-        GstTypeFindFactory *factory;
-
-        factory = GST_TYPE_FIND_FACTORY (feature);
-        if (!print_all)
-          g_print ("%s: %s: ", plugin->desc.name,
-              gst_plugin_feature_get_name (feature));
-        if (factory->extensions) {
-          guint i = 0;
-
-          while (factory->extensions[i]) {
-            if (!print_all)
-              g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
-            i++;
-          }
-          if (!print_all)
-            g_print ("\n");
-        } else {
-          if (!print_all)
-            g_print ("no extensions\n");
-        }
-      } else {
-        if (!print_all)
-          n_print ("%s:  %s (%s)\n", plugin->desc.name,
-              GST_PLUGIN_FEATURE_NAME (feature),
-              g_type_name (G_OBJECT_TYPE (feature)));
-      }
-
-      features = g_list_next (features);
-    }
-
-    gst_plugin_feature_list_free (orig_features);
-  }
-
-  gst_plugin_list_free (orig_plugins);
-
-  g_print ("\n");
-  g_print (_("Total count: "));
-  g_print (ngettext ("%d plugin", "%d plugins", plugincount), plugincount);
-  g_print (", ");
-  g_print (ngettext ("%d feature", "%d features", featurecount), featurecount);
-  g_print ("\n");
-}
-
-static void
-print_plugin_info (GstPlugin * plugin)
-{
-  n_print ("Plugin Details:\n");
-  n_print ("  Name:\t\t\t%s\n", plugin->desc.name);
-  n_print ("  Description:\t\t%s\n", plugin->desc.description);
-  n_print ("  Filename:\t\t%s\n",
-      plugin->filename ? plugin->filename : "(null)");
-  n_print ("  Version:\t\t%s\n", plugin->desc.version);
-  n_print ("  License:\t\t%s\n", plugin->desc.license);
-  n_print ("  Source module:\t%s\n", plugin->desc.source);
-  n_print ("  Binary package:\t%s\n", plugin->desc.package);
-  n_print ("  Origin URL:\t\t%s\n", plugin->desc.origin);
-  n_print ("\n");
-}
-
-static void
-print_plugin_features (GstPlugin * plugin)
-{
-  GList *features;
-  gint num_features = 0;
-  gint num_elements = 0;
-  gint num_types = 0;
-  gint num_indexes = 0;
-  gint num_other = 0;
-
-  features =
-      gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
-      plugin->desc.name);
-
-  while (features) {
-    GstPluginFeature *feature;
-
-    feature = GST_PLUGIN_FEATURE (features->data);
-
-    if (GST_IS_ELEMENT_FACTORY (feature)) {
-      GstElementFactory *factory;
-
-      factory = GST_ELEMENT_FACTORY (feature);
-      n_print ("  %s: %s\n", GST_PLUGIN_FEATURE_NAME (factory),
-          gst_element_factory_get_longname (factory));
-      num_elements++;
-    }
-#ifndef GST_DISABLE_INDEX
-    else if (GST_IS_INDEX_FACTORY (feature)) {
-      GstIndexFactory *factory;
-
-      factory = GST_INDEX_FACTORY (feature);
-      n_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
-      num_indexes++;
-    }
-#endif
-    else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
-      GstTypeFindFactory *factory;
-
-      factory = GST_TYPE_FIND_FACTORY (feature);
-      if (factory->extensions) {
-        guint i = 0;
-
-        g_print ("%s: %s: ", plugin->desc.name,
-            gst_plugin_feature_get_name (feature));
-        while (factory->extensions[i]) {
-          g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
-          i++;
-        }
-        g_print ("\n");
-      } else
-        g_print ("%s: %s: no extensions\n", plugin->desc.name,
-            gst_plugin_feature_get_name (feature));
-
-      num_types++;
-    } else {
-      n_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
-          g_type_name (G_OBJECT_TYPE (feature)));
-      num_other++;
-    }
-    num_features++;
-    features = g_list_next (features);
-  }
-  n_print ("\n");
-  n_print ("  %d features:\n", num_features);
-  if (num_elements > 0)
-    n_print ("  +-- %d elements\n", num_elements);
-  if (num_types > 0)
-    n_print ("  +-- %d types\n", num_types);
-  if (num_indexes > 0)
-    n_print ("  +-- %d indexes\n", num_indexes);
-  if (num_other > 0)
-    n_print ("  +-- %d other objects\n", num_other);
-
-  n_print ("\n");
-}
-
-static int
-print_element_features (const gchar * element_name)
-{
-  GstPluginFeature *feature;
-
-  /* FIXME implement other pretty print function for these */
-#ifndef GST_DISABLE_INDEX
-  feature = gst_default_registry_find_feature (element_name,
-      GST_TYPE_INDEX_FACTORY);
-  if (feature) {
-    n_print ("%s: an index\n", element_name);
-    return 0;
-  }
-#endif
-  feature = gst_default_registry_find_feature (element_name,
-      GST_TYPE_TYPE_FIND_FACTORY);
-  if (feature) {
-    n_print ("%s: a typefind function\n", element_name);
-    return 0;
-  }
-
-  return -1;
-}
-
-static int
-print_element_info (GstElementFactory * factory, gboolean print_names)
-{
-  GstElement *element;
-  gint maxlevel = 0;
-
-  factory =
-      GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
-          (factory)));
-
-  if (!factory) {
-    g_print ("element plugin couldn't be loaded\n");
-    return -1;
-  }
-
-  element = gst_element_factory_create (factory, NULL);
-  if (!element) {
-    g_print ("couldn't construct element for some reason\n");
-    return -1;
-  }
-
-  if (print_names)
-    _name = g_strdup_printf ("%s: ", GST_PLUGIN_FEATURE (factory)->name);
-  else
-    _name = NULL;
-
-  print_factory_details_info (factory);
-  if (GST_PLUGIN_FEATURE (factory)->plugin_name) {
-    GstPlugin *plugin;
-
-    plugin = gst_registry_find_plugin (gst_registry_get_default (),
-        GST_PLUGIN_FEATURE (factory)->plugin_name);
-    if (plugin) {
-      print_plugin_info (plugin);
-    }
-  }
-
-  print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
-  print_interfaces (G_OBJECT_TYPE (element));
-
-  print_pad_templates_info (element, factory);
-  print_element_flag_info (element);
-  print_implementation_info (element);
-  print_clocking_info (element);
-  print_index_info (element);
-  print_pad_info (element);
-  print_element_properties_info (element);
-  print_signal_info (element);
-  print_children_info (element);
-
-  gst_object_unref (element);
-  gst_object_unref (factory);
-  g_free (_name);
-
-  return 0;
-}
-
-
-static void
-print_plugin_automatic_install_info_codecs (GstElementFactory * factory)
-{
-  GstPadDirection direction;
-  const gchar *type_name;
-  const gchar *klass;
-  const GList *static_templates, *l;
-  GstCaps *caps = NULL;
-  guint i, num;
-
-  klass = gst_element_factory_get_klass (factory);
-  g_return_if_fail (klass != NULL);
-
-  if (strstr (klass, "Demuxer") ||
-      strstr (klass, "Decoder") ||
-      strstr (klass, "Depay") || strstr (klass, "Parser")) {
-    type_name = "decoder";
-    direction = GST_PAD_SINK;
-  } else if (strstr (klass, "Muxer") ||
-      strstr (klass, "Encoder") || strstr (klass, "Pay")) {
-    type_name = "encoder";
-    direction = GST_PAD_SRC;
-  } else {
-    return;
-  }
-
-  /* decoder/demuxer sink pads should always be static and there should only
-   * be one, the same applies to encoders/muxers and source pads */
-  static_templates = gst_element_factory_get_static_pad_templates (factory);
-  for (l = static_templates; l != NULL; l = l->next) {
-    GstStaticPadTemplate *tmpl = NULL;
-
-    tmpl = (GstStaticPadTemplate *) l->data;
-    if (tmpl->direction == direction) {
-      caps = gst_static_pad_template_get_caps (tmpl);
-      break;
-    }
-  }
-
-  if (caps == NULL) {
-    g_printerr ("Couldn't find static pad template for %s '%s'\n",
-        type_name, GST_PLUGIN_FEATURE_NAME (factory));
-    return;
-  }
-
-  caps = gst_caps_make_writable (caps);
-  num = gst_caps_get_size (caps);
-  for (i = 0; i < num; ++i) {
-    GstStructure *s;
-    gchar *s_str;
-
-    s = gst_caps_get_structure (caps, i);
-    /* remove fields that are almost always just MIN-MAX of some sort
-     * in order to make the caps look less messy */
-    gst_structure_remove_field (s, "pixel-aspect-ratio");
-    gst_structure_remove_field (s, "framerate");
-    gst_structure_remove_field (s, "channels");
-    gst_structure_remove_field (s, "width");
-    gst_structure_remove_field (s, "height");
-    gst_structure_remove_field (s, "rate");
-    gst_structure_remove_field (s, "depth");
-    gst_structure_remove_field (s, "clock-rate");
-    s_str = gst_structure_to_string (s);
-    g_print ("%s-%s\n", type_name, s_str);
-    g_free (s_str);
-  }
-  gst_caps_unref (caps);
-}
-
-static void
-print_plugin_automatic_install_info_protocols (GstElementFactory * factory)
-{
-  gchar **protocols, **p;
-
-  protocols = gst_element_factory_get_uri_protocols (factory);
-  if (protocols != NULL && *protocols != NULL) {
-    switch (gst_element_factory_get_uri_type (factory)) {
-      case GST_URI_SINK:
-        for (p = protocols; *p != NULL; ++p)
-          g_print ("urisink-%s\n", *p);
-        break;
-      case GST_URI_SRC:
-        for (p = protocols; *p != NULL; ++p)
-          g_print ("urisource-%s\n", *p);
-        break;
-      default:
-        break;
-    }
-    g_strfreev (protocols);
-  }
-}
-
-static void
-print_plugin_automatic_install_info (GstPlugin * plugin)
-{
-  const gchar *plugin_name;
-  GList *features, *l;
-
-  plugin_name = gst_plugin_get_name (plugin);
-
-  /* not interested in typefind factories, only element factories */
-  features = gst_registry_get_feature_list (gst_registry_get_default (),
-      GST_TYPE_ELEMENT_FACTORY);
-
-  for (l = features; l != NULL; l = l->next) {
-    GstPluginFeature *feature;
-
-    feature = GST_PLUGIN_FEATURE (l->data);
-
-    /* only interested in the ones that are in the plugin we just loaded */
-    if (g_str_equal (plugin_name, feature->plugin_name)) {
-      GstElementFactory *factory;
-
-      g_print ("element-%s\n", gst_plugin_feature_get_name (feature));
-
-      factory = GST_ELEMENT_FACTORY (feature);
-      print_plugin_automatic_install_info_protocols (factory);
-      print_plugin_automatic_install_info_codecs (factory);
-    }
-  }
-
-  g_list_foreach (features, (GFunc) gst_object_unref, NULL);
-  g_list_free (features);
-}
-
-int
-main (int argc, char *argv[])
-{
-  gboolean print_all = FALSE;
-  gboolean print_aii = FALSE;
-  GOptionEntry options[] = {
-    {"print-all", 'a', 0, G_OPTION_ARG_NONE, &print_all,
-        N_("Print all elements"), NULL},
-    {"print-plugin-auto-install-info", '\0', 0, G_OPTION_ARG_NONE, &print_aii,
-        N_("Print a machine-parsable list of features the specified plugin "
-              "provides.\n                                       "
-              "Useful in connection with external automatic plugin "
-              "installation mechanisms"), NULL},
-    GST_TOOLS_GOPTION_VERSION,
-    {NULL}
-  };
-  GOptionContext *ctx;
-  GError *err = NULL;
-
-#ifdef ENABLE_NLS
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-  textdomain (GETTEXT_PACKAGE);
-#endif
-
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-
-  ctx = g_option_context_new ("[ELEMENT-NAME | PLUGIN-NAME]");
-  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
-  g_option_context_add_group (ctx, gst_init_get_option_group ());
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    g_print ("Error initializing: %s\n", err->message);
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  gst_tools_print_version ("gst-inspect");
-
-  if (print_all && argc > 2) {
-    g_print ("-a requires no extra arguments\n");
-    return 1;
-  }
-
-  /* if no arguments, print out list of elements */
-  if (argc == 1 || print_all) {
-    print_element_list (print_all);
-    /* else we try to get a factory */
-  } else {
-    GstElementFactory *factory;
-    GstPlugin *plugin;
-    const char *arg = argv[argc - 1];
-    int retval;
-
-    factory = gst_element_factory_find (arg);
-    /* if there's a factory, print out the info */
-    if (factory) {
-      retval = print_element_info (factory, print_all);
-      gst_object_unref (factory);
-    } else {
-      retval = print_element_features (arg);
-    }
-
-    /* otherwise check if it's a plugin */
-    if (retval) {
-      plugin = gst_default_registry_find_plugin (arg);
-
-      /* if there is such a plugin, print out info */
-      if (plugin) {
-        if (print_aii) {
-          print_plugin_automatic_install_info (plugin);
-        } else {
-          print_plugin_info (plugin);
-          print_plugin_features (plugin);
-        }
-      } else {
-        GError *error = NULL;
-
-        if (g_file_test (arg, G_FILE_TEST_EXISTS)) {
-          plugin = gst_plugin_load_file (arg, &error);
-
-          if (plugin) {
-            if (print_aii) {
-              print_plugin_automatic_install_info (plugin);
-            } else {
-              print_plugin_info (plugin);
-              print_plugin_features (plugin);
-            }
-          } else {
-            g_print (_("Could not load plugin file: %s\n"), error->message);
-            g_error_free (error);
-            return -1;
-          }
-        } else {
-          g_print (_("No such element or plugin '%s'\n"), arg);
-          return -1;
-        }
-      }
-    }
-  }
-
-  return 0;
-}
--- a/gstreamer_core/tools/gst-launch.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,806 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *               2000 Wim Taymans <wtay@chello.be>
- *               2004 Thomas Vander Stichele <thomas@apestaart.org>
- *
- * gst-launch.c: tool to launch GStreamer pipelines from the command line
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-/* FIXME: hack alert */
-#ifdef WIN32
-#define DISABLE_FAULT_HANDLER
-#endif
-
-#include <string.h>
-#include <signal.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifndef DISABLE_FAULT_HANDLER
-#include <sys/wait.h>
-#endif
-#include <locale.h>             /* for LC_ALL */
-#include "tools.h"
-
-/* FIXME: This is just a temporary hack.  We should have a better
- * check for siginfo handling. */
-#ifdef SA_SIGINFO
-#define USE_SIGINFO
-#endif
-
-extern volatile gboolean glib_on_error_halt;
-
-#ifndef DISABLE_FAULT_HANDLER
-static void fault_restore (void);
-static void fault_spin (void);
-static void sigint_restore (void);
-static gboolean caught_intr = FALSE;
-#endif
-
-static GstElement *pipeline;
-static gboolean caught_error = FALSE;
-static gboolean tags = FALSE;
-static gboolean messages = FALSE;
-static gboolean is_live = FALSE;
-
-
-#ifndef GST_DISABLE_LOADSAVE
-static GstElement *
-xmllaunch_parse_cmdline (const gchar ** argv)
-{
-  GstElement *pipeline = NULL, *e;
-  GstXML *xml;
-  gboolean err;
-  const gchar *arg;
-  gchar *element, *property, *value;
-  GList *l;
-  gint i = 0;
-
-  if (!(arg = argv[0])) {
-    g_print (_
-        ("Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"));
-    exit (1);
-  }
-
-  xml = gst_xml_new ();
-  /* FIXME guchar from gstxml.c */
-  err = gst_xml_parse_file (xml, (guchar *) arg, NULL);
-
-  if (err != TRUE) {
-    fprintf (stderr, _("ERROR: parse of xml file '%s' failed.\n"), arg);
-    exit (1);
-  }
-
-  l = gst_xml_get_topelements (xml);
-  if (!l) {
-    fprintf (stderr, _("ERROR: no toplevel pipeline element in file '%s'.\n"),
-        arg);
-    exit (1);
-  }
-
-  if (l->next)
-    fprintf (stderr,
-        _("WARNING: only one toplevel element is supported at this time."));
-
-  pipeline = GST_ELEMENT (l->data);
-
-  while ((arg = argv[++i])) {
-    element = g_strdup (arg);
-    property = strchr (element, '.');
-    value = strchr (element, '=');
-
-    if (!(element < property && property < value)) {
-      fprintf (stderr,
-          _("ERROR: could not parse command line argument %d: %s.\n"), i,
-          element);
-      g_free (element);
-      exit (1);
-    }
-
-    *property++ = '\0';
-    *value++ = '\0';
-
-    e = gst_bin_get_by_name (GST_BIN (pipeline), element);
-    if (!e) {
-      fprintf (stderr, _("WARNING: element named '%s' not found.\n"), element);
-    } else {
-      gst_util_set_object_arg (G_OBJECT (e), property, value);
-    }
-    g_free (element);
-  }
-
-  if (!l)
-    return NULL;
-
-  gst_object_ref (pipeline);
-  gst_object_unref (xml);
-  return pipeline;
-}
-#endif
-
-#ifndef DISABLE_FAULT_HANDLER
-#ifndef USE_SIGINFO
-static void
-fault_handler_sighandler (int signum)
-{
-  fault_restore ();
-
-  /* printf is used instead of g_print(), since it's less likely to
-   * deadlock */
-  switch (signum) {
-    case SIGSEGV:
-      printf ("Caught SIGSEGV\n");
-      break;
-    case SIGQUIT:
-      printf ("Caught SIGQUIT\n");
-      break;
-    default:
-      printf ("signo:  %d\n", signum);
-      break;
-  }
-
-  fault_spin ();
-}
-
-#else /* USE_SIGINFO */
-
-static void
-fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
-{
-  fault_restore ();
-
-  /* printf is used instead of g_print(), since it's less likely to
-   * deadlock */
-  switch (si->si_signo) {
-    case SIGSEGV:
-      printf ("Caught SIGSEGV accessing address %p\n", si->si_addr);
-      break;
-    case SIGQUIT:
-      printf ("Caught SIGQUIT\n");
-      break;
-    default:
-      printf ("signo:  %d\n", si->si_signo);
-      printf ("errno:  %d\n", si->si_errno);
-      printf ("code:   %d\n", si->si_code);
-      break;
-  }
-
-  fault_spin ();
-}
-#endif /* USE_SIGINFO */
-
-static void
-fault_spin (void)
-{
-  int spinning = TRUE;
-
-  glib_on_error_halt = FALSE;
-  g_on_error_stack_trace ("gst-launch");
-
-  wait (NULL);
-
-  /* FIXME how do we know if we were run by libtool? */
-  printf ("Spinning.  Please run 'gdb gst-launch %d' to continue debugging, "
-      "Ctrl-C to quit, or Ctrl-\\ to dump core.\n", (gint) getpid ());
-  while (spinning)
-    g_usleep (1000000);
-}
-
-static void
-fault_restore (void)
-{
-  struct sigaction action;
-
-  memset (&action, 0, sizeof (action));
-  action.sa_handler = SIG_DFL;
-
-  sigaction (SIGSEGV, &action, NULL);
-  sigaction (SIGQUIT, &action, NULL);
-}
-
-static void
-fault_setup (void)
-{
-  struct sigaction action;
-
-  memset (&action, 0, sizeof (action));
-#ifdef USE_SIGINFO
-  action.sa_sigaction = fault_handler_sigaction;
-  action.sa_flags = SA_SIGINFO;
-#else
-  action.sa_handler = fault_handler_sighandler;
-#endif
-
-  sigaction (SIGSEGV, &action, NULL);
-  sigaction (SIGQUIT, &action, NULL);
-}
-#endif /* DISABLE_FAULT_HANDLER */
-
-static void
-print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
-{
-  gint i, count;
-
-  count = gst_tag_list_get_tag_size (list, tag);
-
-  for (i = 0; i < count; i++) {
-    gchar *str;
-
-    if (gst_tag_get_type (tag) == G_TYPE_STRING) {
-      if (!gst_tag_list_get_string_index (list, tag, i, &str))
-        g_assert_not_reached ();
-    } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) {
-      GstBuffer *img;
-
-      img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
-      if (img) {
-        gchar *caps_str;
-
-        caps_str = GST_BUFFER_CAPS (img) ?
-            gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
-        str = g_strdup_printf ("buffer of %u bytes, type: %s",
-            GST_BUFFER_SIZE (img), caps_str);
-        g_free (caps_str);
-      } else {
-        str = g_strdup ("NULL buffer");
-      }
-    } else {
-      str =
-          g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
-    }
-
-    if (i == 0) {
-      g_print ("%16s: %s\n", gst_tag_get_nick (tag), str);
-    } else {
-      g_print ("%16s: %s\n", "", str);
-    }
-
-    g_free (str);
-  }
-}
-
-#ifndef DISABLE_FAULT_HANDLER
-/* we only use sighandler here because the registers are not important */
-static void
-sigint_handler_sighandler (int signum)
-{
-  g_print ("Caught interrupt -- ");
-
-  sigint_restore ();
-
-  /* we set a flag that is checked by the mainloop, we cannot do much in the
-   * interrupt handler (no mutex or other blocking stuff) */
-  caught_intr = TRUE;
-}
-
-/* is called every 50 milliseconds (20 times a second), the interrupt handler
- * will set a flag for us. We react to this by posting a message. */
-static gboolean
-check_intr (GstElement * pipeline)
-{
-  if (!caught_intr) {
-    return TRUE;
-  } else {
-    caught_intr = FALSE;
-    g_print ("handling interrupt.\n");
-
-    /* post an application specific message */
-    gst_element_post_message (GST_ELEMENT (pipeline),
-        gst_message_new_application (GST_OBJECT (pipeline),
-            gst_structure_new ("GstLaunchInterrupt",
-                "message", G_TYPE_STRING, "Pipeline interrupted", NULL)));
-
-    /* remove timeout handler */
-    return FALSE;
-  }
-}
-
-static void
-sigint_setup (void)
-{
-  struct sigaction action;
-
-  memset (&action, 0, sizeof (action));
-  action.sa_handler = sigint_handler_sighandler;
-
-  sigaction (SIGINT, &action, NULL);
-}
-
-static void
-sigint_restore (void)
-{
-  struct sigaction action;
-
-  memset (&action, 0, sizeof (action));
-  action.sa_handler = SIG_DFL;
-
-  sigaction (SIGINT, &action, NULL);
-}
-
-static void
-play_handler (int signum)
-{
-  switch (signum) {
-    case SIGUSR1:
-      g_print ("Caught SIGUSR1 - Play request.\n");
-      gst_element_set_state (pipeline, GST_STATE_PLAYING);
-      break;
-    case SIGUSR2:
-      g_print ("Caught SIGUSR2 - Stop request.\n");
-      gst_element_set_state (pipeline, GST_STATE_NULL);
-      break;
-  }
-}
-
-static void
-play_signal_setup (void)
-{
-  struct sigaction action;
-
-  memset (&action, 0, sizeof (action));
-  action.sa_handler = play_handler;
-  sigaction (SIGUSR1, &action, NULL);
-  sigaction (SIGUSR2, &action, NULL);
-}
-#endif /* DISABLE_FAULT_HANDLER */
-
-/* returns TRUE if there was an error or we caught a keyboard interrupt. */
-static gboolean
-event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
-{
-  GstBus *bus;
-  GstMessage *message = NULL;
-  gboolean res = FALSE;
-  gboolean buffering = FALSE;
-
-  bus = gst_element_get_bus (GST_ELEMENT (pipeline));
-
-#ifndef DISABLE_FAULT_HANDLER
-  g_timeout_add (50, (GSourceFunc) check_intr, pipeline);
-#endif
-
-  while (TRUE) {
-    message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);
-
-    /* if the poll timed out, only when !blocking */
-    if (message == NULL)
-      goto exit;
-
-    /* check if we need to dump messages to the console */
-    if (messages) {
-      const GstStructure *s;
-
-      s = gst_message_get_structure (message);
-
-      g_print (_("Got Message from element \"%s\" (%s): "),
-          GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))),
-          gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
-      if (s) {
-        gchar *sstr;
-
-        sstr = gst_structure_to_string (s);
-        g_print ("%s\n", sstr);
-        g_free (sstr);
-      } else {
-        g_print ("no message details\n");
-      }
-    }
-
-    switch (GST_MESSAGE_TYPE (message)) {
-      case GST_MESSAGE_NEW_CLOCK:
-      {
-        GstClock *clock;
-
-        gst_message_parse_new_clock (message, &clock);
-
-        g_print ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
-        break;
-      }
-      case GST_MESSAGE_EOS:
-        g_print (_
-            ("Got EOS from element \"%s\".\n"),
-            GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
-        goto exit;
-      case GST_MESSAGE_TAG:
-        if (tags) {
-          GstTagList *tags;
-
-          gst_message_parse_tag (message, &tags);
-          g_print (_("FOUND TAG      : found by element \"%s\".\n"),
-              GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
-          gst_tag_list_foreach (tags, print_tag, NULL);
-          gst_tag_list_free (tags);
-        }
-        break;
-      case GST_MESSAGE_INFO:{
-        GError *gerror;
-        gchar *debug;
-        gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
-
-        gst_message_parse_info (message, &gerror, &debug);
-        if (debug) {
-          g_print (_("INFO:\n%s\n"), debug);
-        }
-        g_error_free (gerror);
-        g_free (debug);
-        g_free (name);
-        break;
-      }
-      case GST_MESSAGE_WARNING:{
-        GError *gerror;
-        gchar *debug;
-        gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
-
-        /* dump graph on warning */
-        GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
-            GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning");
-
-        gst_message_parse_warning (message, &gerror, &debug);
-        g_print (_("WARNING: from element %s: %s\n"), name, gerror->message);
-        if (debug) {
-          g_print (_("Additional debug info:\n%s\n"), debug);
-        }
-        g_error_free (gerror);
-        g_free (debug);
-        g_free (name);
-        break;
-      }
-      case GST_MESSAGE_ERROR:{
-        GError *gerror;
-        gchar *debug;
-
-        /* dump graph on error */
-        GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
-            GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
-
-        gst_message_parse_error (message, &gerror, &debug);
-        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
-        g_error_free (gerror);
-        g_free (debug);
-        /* we have an error */
-        res = TRUE;
-        goto exit;
-      }
-      case GST_MESSAGE_STATE_CHANGED:{
-        GstState old, new, pending;
-
-        gst_message_parse_state_changed (message, &old, &new, &pending);
-
-        /* we only care about pipeline state change messages */
-        if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline))
-          break;
-
-        /* dump graph for pipeline state changes */
-        {
-          gchar *dump_name = g_strdup_printf ("gst-launch.%s_%s",
-              gst_element_state_get_name (old),
-              gst_element_state_get_name (new));
-          GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
-              GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
-          g_free (dump_name);
-        }
-
-        /* ignore when we are buffering since then we mess with the states
-         * ourselves. */
-        if (buffering) {
-          fprintf (stderr,
-              _("Prerolled, waiting for buffering to finish...\n"));
-          break;
-        }
-
-        /* if we reached the final target state, exit */
-        if (target_state == GST_STATE_PAUSED && new == target_state)
-          goto exit;
-
-        /* else not an interesting message */
-        break;
-      }
-      case GST_MESSAGE_BUFFERING:{
-        gint percent;
-
-        gst_message_parse_buffering (message, &percent);
-        fprintf (stderr, _("buffering... %d  \r"), percent);
-
-        /* no state management needed for live pipelines */
-        if (is_live)
-          break;
-
-        if (percent == 100) {
-          /* a 100% message means buffering is done */
-          buffering = FALSE;
-          /* if the desired state is playing, go back */
-          if (target_state == GST_STATE_PLAYING) {
-            fprintf (stderr,
-                _("Done buffering, setting pipeline to PLAYING ...\n"));
-            gst_element_set_state (pipeline, GST_STATE_PLAYING);
-          } else
-            goto exit;
-        } else {
-          /* buffering busy */
-          if (buffering == FALSE && target_state == GST_STATE_PLAYING) {
-            /* we were not buffering but PLAYING, PAUSE  the pipeline. */
-            fprintf (stderr, _("Buffering, setting pipeline to PAUSED ...\n"));
-            gst_element_set_state (pipeline, GST_STATE_PAUSED);
-          }
-          buffering = TRUE;
-        }
-        break;
-      }
-      case GST_MESSAGE_APPLICATION:{
-        const GstStructure *s;
-
-        s = gst_message_get_structure (message);
-
-        if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
-          /* this application message is posted when we caught an interrupt and
-           * we need to stop the pipeline. */
-          fprintf (stderr, _("Interrupt: Stopping pipeline ...\n"));
-          /* return TRUE when we caught an interrupt */
-          res = TRUE;
-          goto exit;
-        }
-      }
-      default:
-        /* just be quiet by default */
-        break;
-    }
-    if (message)
-      gst_message_unref (message);
-  }
-  g_assert_not_reached ();
-
-exit:
-  {
-    if (message)
-      gst_message_unref (message);
-    gst_object_unref (bus);
-    return res;
-  }
-}
-
-int
-main (int argc, char *argv[])
-{
-  /* options */
-  gboolean verbose = FALSE;
-  gboolean no_fault = FALSE;
-  gboolean trace = FALSE;
-  gchar *savefile = NULL;
-  gchar *exclude_args = NULL;
-  GOptionEntry options[] = {
-    {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
-        N_("Output tags (also known as metadata)"), NULL},
-    {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
-        N_("Output status information and property notifications"), NULL},
-    {"messages", 'm', 0, G_OPTION_ARG_NONE, &messages,
-        N_("Output messages"), NULL},
-    {"exclude", 'X', 0, G_OPTION_ARG_NONE, &exclude_args,
-        N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")},
-#ifndef GST_DISABLE_LOADSAVE
-    {"output", 'o', 0, G_OPTION_ARG_STRING, &savefile,
-        N_("Save xml representation of pipeline to FILE and exit"), N_("FILE")},
-#endif
-    {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault,
-        N_("Do not install a fault handler"), NULL},
-    {"trace", 'T', 0, G_OPTION_ARG_NONE, &trace,
-        N_("Print alloc trace (if enabled at compile time)"), NULL},
-    GST_TOOLS_GOPTION_VERSION,
-    {NULL}
-  };
-  GOptionContext *ctx;
-  GError *err = NULL;
-  gchar **argvn;
-  GError *error = NULL;
-  gint res = 0;
-
-  free (malloc (8));            /* -lefence */
-
-#ifdef ENABLE_NLS
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-  textdomain (GETTEXT_PACKAGE);
-#endif
-
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-
-  gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE);
-
-  ctx = g_option_context_new ("PIPELINE-DESCRIPTION");
-  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
-  g_option_context_add_group (ctx, gst_init_get_option_group ());
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    if (err)
-      g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
-    else
-      g_print ("Error initializing: Unknown error!\n");
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  gst_tools_print_version ("gst-launch");
-
-#ifndef DISABLE_FAULT_HANDLER
-  if (!no_fault)
-    fault_setup ();
-
-  sigint_setup ();
-  play_signal_setup ();
-#endif
-
-  if (trace) {
-    if (!gst_alloc_trace_available ()) {
-      g_warning ("Trace not available (recompile with trace enabled).");
-    }
-    gst_alloc_trace_print_live ();
-  }
-
-  /* make a null-terminated version of argv */
-  argvn = g_new0 (char *, argc);
-  memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
-#ifndef GST_DISABLE_LOADSAVE
-  if (strstr (argv[0], "gst-xmllaunch")) {
-    pipeline = xmllaunch_parse_cmdline ((const gchar **) argvn);
-  } else
-#endif
-  {
-    pipeline =
-        (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
-  }
-  g_free (argvn);
-
-  if (!pipeline) {
-    if (error) {
-      fprintf (stderr, _("ERROR: pipeline could not be constructed: %s.\n"),
-          GST_STR_NULL (error->message));
-      g_error_free (error);
-    } else {
-      fprintf (stderr, _("ERROR: pipeline could not be constructed.\n"));
-    }
-    return 1;
-  } else if (error) {
-    fprintf (stderr, _("WARNING: erroneous pipeline: %s\n"),
-        GST_STR_NULL (error->message));
-    g_error_free (error);
-    return 1;
-  }
-
-  if (verbose) {
-    gchar **exclude_list =
-        exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
-    g_signal_connect (pipeline, "deep_notify",
-        G_CALLBACK (gst_object_default_deep_notify), exclude_list);
-  }
-#ifndef GST_DISABLE_LOADSAVE
-  if (savefile) {
-    gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
-  }
-#endif
-
-  if (!savefile) {
-    GstState state, pending;
-    GstStateChangeReturn ret;
-
-    /* If the top-level object is not a pipeline, place it in a pipeline. */
-    if (!GST_IS_PIPELINE (pipeline)) {
-      GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);
-
-      if (real_pipeline == NULL) {
-        fprintf (stderr, _("ERROR: the 'pipeline' element wasn't found.\n"));
-        return 1;
-      }
-      gst_bin_add (GST_BIN (real_pipeline), pipeline);
-      pipeline = real_pipeline;
-    }
-    fprintf (stderr, _("Setting pipeline to PAUSED ...\n"));
-    ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
-
-    switch (ret) {
-      case GST_STATE_CHANGE_FAILURE:
-        fprintf (stderr, _("ERROR: Pipeline doesn't want to pause.\n"));
-        res = -1;
-        event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING);
-        goto end;
-      case GST_STATE_CHANGE_NO_PREROLL:
-        fprintf (stderr, _("Pipeline is live and does not need PREROLL ...\n"));
-        is_live = TRUE;
-        break;
-      case GST_STATE_CHANGE_ASYNC:
-        fprintf (stderr, _("Pipeline is PREROLLING ...\n"));
-        caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED);
-        if (caught_error) {
-          fprintf (stderr, _("ERROR: pipeline doesn't want to preroll.\n"));
-          goto end;
-        }
-        state = GST_STATE_PAUSED;
-        /* fallthrough */
-      case GST_STATE_CHANGE_SUCCESS:
-        fprintf (stderr, _("Pipeline is PREROLLED ...\n"));
-        break;
-    }
-
-    caught_error = event_loop (pipeline, FALSE, GST_STATE_PLAYING);
-
-    if (caught_error) {
-      fprintf (stderr, _("ERROR: pipeline doesn't want to preroll.\n"));
-    } else {
-      GstClockTime tfthen, tfnow;
-      GstClockTimeDiff diff;
-
-      fprintf (stderr, _("Setting pipeline to PLAYING ...\n"));
-      if (gst_element_set_state (pipeline,
-              GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
-        GstMessage *err_msg;
-        GstBus *bus;
-
-        fprintf (stderr, _("ERROR: pipeline doesn't want to play.\n"));
-        bus = gst_element_get_bus (pipeline);
-        if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) {
-          GError *gerror;
-          gchar *debug;
-
-          gst_message_parse_error (err_msg, &gerror, &debug);
-          gst_object_default_error (GST_MESSAGE_SRC (err_msg), gerror, debug);
-          gst_message_unref (err_msg);
-          g_error_free (gerror);
-          g_free (debug);
-        }
-        gst_object_unref (bus);
-        res = -1;
-        goto end;
-      }
-
-      tfthen = gst_util_get_timestamp ();
-      caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
-      tfnow = gst_util_get_timestamp ();
-
-      diff = GST_CLOCK_DIFF (tfthen, tfnow);
-
-      g_print (_("Execution ended after %" G_GUINT64_FORMAT " ns.\n"), diff);
-    }
-
-    /* iterate mainloop to process pending stuff */
-    while (g_main_context_iteration (NULL, FALSE));
-
-    fprintf (stderr, _("Setting pipeline to PAUSED ...\n"));
-    gst_element_set_state (pipeline, GST_STATE_PAUSED);
-    if (!caught_error)
-      gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
-    fprintf (stderr, _("Setting pipeline to READY ...\n"));
-    gst_element_set_state (pipeline, GST_STATE_READY);
-    gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
-
-  end:
-    fprintf (stderr, _("Setting pipeline to NULL ...\n"));
-    gst_element_set_state (pipeline, GST_STATE_NULL);
-    gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
-  }
-
-  fprintf (stderr, _("FREEING pipeline ...\n"));
-  gst_object_unref (pipeline);
-
-  gst_deinit ();
-  if (trace)
-    gst_alloc_trace_print_live ();
-
-  return res;
-}
--- a/gstreamer_core/tools/gst-run.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,383 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Thomas Vander Stichele <thomas@apestaart.org>
- *
- * gst-run.c: tool to launch GStreamer tools with correct major/minor
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <glib.h>
-
-/* global statics for option parsing */
-static gboolean _print = FALSE;
-static gchar *_arg_mm = NULL;
-static gboolean _arg_list_mm = FALSE;
-
-/* popt options table for the wrapper */
-static GOptionEntry wrapper_options[] = {
-  {"print", 'p', 0, G_OPTION_ARG_NONE, &_print,
-      "print wrapped command line options", NULL},
-  {"gst-mm", 0, 0, G_OPTION_ARG_STRING, &_arg_mm,
-      "Force major/minor version", "VERSION"},
-  {"gst-list-mm", 0, 0, G_OPTION_ARG_NONE, &_arg_list_mm,
-      "List found major/minor versions", NULL},
-  {NULL}
-};
-
-/* print out the major/minor, which is the hash key */
-static void
-hash_print_key (gchar * key, gchar * value)
-{
-  g_print ("%s\n", (gchar *) key);
-}
-
-/* return value like strcmp, but compares major/minor numerically */
-static gint
-compare_major_minor (const gchar * first, const gchar * second)
-{
-  gchar **firsts, **seconds;
-  gint fmaj, fmin, smaj, smin;
-  gint ret = 0;
-
-  firsts = g_strsplit (first, ".", 0);
-  seconds = g_strsplit (second, ".", 0);
-
-  if (firsts[0] == NULL || firsts[1] == NULL) {
-    ret = -1;
-    goto beach;
-  }
-  if (seconds[0] == NULL || seconds[1] == NULL) {
-    ret = 1;
-    goto beach;
-  }
-
-  fmaj = atoi (firsts[0]);
-  fmin = atoi (firsts[1]);
-  smaj = atoi (seconds[0]);
-  smin = atoi (seconds[1]);
-
-  if (fmaj < smaj) {
-    ret = -1;
-    goto beach;
-  }
-  if (fmaj > smaj) {
-    ret = 1;
-    goto beach;
-  }
-
-  /* fmaj == smaj */
-  if (fmin < smin) {
-    ret = -1;
-    goto beach;
-  }
-  if (fmin > smin) {
-    ret = 1;
-    goto beach;
-  }
-  ret = 0;
-
-beach:
-  g_strfreev (firsts);
-  g_strfreev (seconds);
-  return ret;
-}
-
-static void
-find_highest_version (gchar * key, gchar * value, gchar ** highest)
-{
-  if (*highest == NULL) {
-    /* first value, so just set it */
-    *highest = key;
-  }
-  if (compare_major_minor (key, *highest) > 0)
-    *highest = key;
-}
-
-/* Libtool creates shell scripts named "base" that calls actual binaries as
- * .libs/lt-base.  If we detect this is a libtool script, unmangle so we
- * find the right binaries */
-static void
-unmangle_libtool (gchar ** dir, gchar ** base)
-{
-  gchar *new_dir, *new_base;
-
-  if (!*dir)
-    return;
-  if (!*base)
-    return;
-
-  /* we assume libtool when base starts with lt- and dir ends with .libs */
-  if (!g_str_has_prefix (*base, "lt-"))
-    return;
-  if (!g_str_has_suffix (*dir, ".libs"))
-    return;
-
-  new_base = g_strdup (&((*base)[3]));
-  new_dir = g_path_get_dirname (*dir);
-  g_free (*base);
-  g_free (*dir);
-  *base = new_base;
-  *dir = new_dir;
-}
-
-/* Returns a directory path that contains the binary given as an argument.
- * If the binary given contains a path, it gets looked for in that path.
- * If it doesn't contain a path, it gets looked for in the standard path.
- *
- * The returned string is newly allocated.
- */
-static gchar *
-get_dir_of_binary (const gchar * binary)
-{
-  gchar *base, *dir;
-  gchar *full;
-
-  base = g_path_get_basename (binary);
-  dir = g_path_get_dirname (binary);
-
-  /* if putting these two together yields the same as binary,
-   * then we have the right breakup.  If not, it's because no path was
-   * specified which caused get_basename to return "." */
-  full = g_build_filename (dir, base, NULL);
-
-  if (strcmp (full, binary) != 0) {
-    if (strcmp (dir, ".") != 0) {
-      g_warning ("This should not happen, g_path_get_dirname () has changed.");
-      g_free (base);
-      g_free (dir);
-      g_free (full);
-      return NULL;
-    }
-
-    /* we know no path was specified, so search standard path for binary */
-    g_free (full);
-    full = g_find_program_in_path (base);
-    if (!full) {
-      g_warning ("This should not happen, %s not in standard path.", base);
-      g_free (base);
-      g_free (dir);
-      return NULL;
-    }
-  }
-
-  g_free (base);
-  g_free (dir);
-  dir = g_path_get_dirname (full);
-  g_free (full);
-
-  return dir;
-}
-
-/* Search the given directory for candidate binaries matching the base binary.
- * Return a GHashTable of major/minor -> directory pairs
- */
-static GHashTable *
-get_candidates (const gchar * dir, const gchar * base)
-{
-  GDir *gdir;
-  GError *error = NULL;
-  const gchar *entry;
-  gchar *path;
-  gchar *suffix, *copy;
-
-  gchar *pattern;
-  GPatternSpec *spec, *specexe;
-
-  gchar **dirs;
-  gchar **cur;
-
-  GHashTable *candidates = NULL;
-
-  candidates = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-  /* compile our pattern specs */
-  pattern = g_strdup_printf ("%s-*.*", base);
-  spec = g_pattern_spec_new (pattern);
-  g_free (pattern);
-  pattern = g_strdup_printf ("%s-*.*.exe", base);
-  specexe = g_pattern_spec_new (pattern);
-  g_free (pattern);
-
-  /* get all dirs from the path and prepend with given dir */
-  if (dir)
-    path = g_strdup_printf ("%s%c%s",
-        dir, G_SEARCHPATH_SEPARATOR, g_getenv ("PATH"));
-  else
-    path = (gchar *) g_getenv ("PATH");
-  dirs = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 0);
-  if (dir)
-    g_free (path);
-
-  /* check all of these in reverse order by winding to bottom and going up  */
-  cur = &dirs[0];
-  while (*cur)
-    ++cur;
-
-  while (cur != &dirs[0]) {
-    --cur;
-    if (!g_file_test (*cur, G_FILE_TEST_EXISTS) ||
-        !g_file_test (*cur, G_FILE_TEST_IS_DIR)) {
-      continue;
-    }
-
-    gdir = g_dir_open (*cur, 0, &error);
-    if (!gdir) {
-      g_warning ("Could not open dir %s: %s", *cur, error->message);
-      g_error_free (error);
-      return NULL;
-    }
-    while ((entry = g_dir_read_name (gdir))) {
-      if (g_pattern_match_string (spec, entry)
-          || g_pattern_match_string (specexe, entry)) {
-        gchar *full;
-
-        /* is it executable ? */
-        full = g_build_filename (*cur, entry, NULL);
-        if (!g_file_test (full, G_FILE_TEST_IS_EXECUTABLE)) {
-          g_free (full);
-          continue;
-        }
-        g_free (full);
-
-        /* strip base and dash from it */
-        suffix = g_strdup (&(entry[strlen (base) + 1]));
-        copy = g_strdup (suffix);
-
-        /* strip possible .exe from copy */
-        if (g_strrstr (copy, ".exe"))
-          g_strrstr (copy, ".exe")[0] = '\0';
-
-        /* stricter pattern check: check if it only contains digits or dots */
-        g_strcanon (copy, "0123456789.", 'X');
-        if (strstr (copy, "X")) {
-          g_free (suffix);
-          g_free (copy);
-          continue;
-        }
-        g_free (copy);
-        g_hash_table_insert (candidates, suffix, g_strdup (*cur));
-      }
-    }
-  }
-
-  g_strfreev (dirs);
-  g_pattern_spec_free (spec);
-  return candidates;
-}
-
-int
-main (int argc, char **argv)
-{
-  GHashTable *candidates;
-  gchar *dir;
-  gchar *base;
-  gchar *highest = NULL;
-  gchar *binary;                /* actual binary we're going to run */
-  gchar *path = NULL;           /* and its path */
-  gchar *desc;
-  GOptionContext *ctx;
-  GError *err = NULL;
-
-  /* detect stuff */
-  dir = get_dir_of_binary (argv[0]);
-  base = g_path_get_basename (argv[0]);
-
-  /* parse command line options */
-  desc = g_strdup_printf ("wrapper to call versioned %s", base);
-  ctx = g_option_context_new (desc);
-  g_free (desc);
-  g_option_context_set_ignore_unknown_options (ctx, TRUE);
-  g_option_context_add_main_entries (ctx, wrapper_options, GETTEXT_PACKAGE);
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    g_print ("Error initializing: %s\n", err->message);
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  /* unmangle libtool if necessary */
-  unmangle_libtool (&dir, &base);
-
-  /* get all candidate binaries */
-  candidates = get_candidates (dir, base);
-  g_free (dir);
-
-  if (_arg_mm) {
-    /* if a version was forced, look it up in the hash table */
-    dir = g_hash_table_lookup (candidates, _arg_mm);
-    if (!dir) {
-      g_print ("ERROR: Major/minor %s of tool %s not found.\n", _arg_mm, base);
-      return 1;
-    }
-    binary = g_strdup_printf ("%s-%s", base, _arg_mm);
-  } else {
-    highest = NULL;
-
-    /* otherwise, just look up the highest version */
-    if (candidates) {
-      g_hash_table_foreach (candidates, (GHFunc) find_highest_version,
-          &highest);
-    }
-
-    if (highest == NULL) {
-      g_print ("ERROR: No version of tool %s found.\n", base);
-      return 1;
-    }
-    dir = g_hash_table_lookup (candidates, highest);
-    binary = g_strdup_printf ("%s-%s", base, highest);
-  }
-
-  g_free (base);
-
-  path = g_build_filename (dir, binary, NULL);
-  g_free (binary);
-
-  /* print out list of major/minors we found if asked for */
-  /* FIXME: do them in order by creating a GList of keys and sort them */
-  if (_arg_list_mm) {
-    g_hash_table_foreach (candidates, (GHFunc) hash_print_key, NULL);
-    g_hash_table_destroy (candidates);
-    return 0;
-  }
-
-  /* print out command line if asked for */
-  argv[0] = path;
-  if (_print) {
-    int i;
-
-    for (i = 0; i < argc; ++i) {
-      g_print ("%s", argv[i]);
-      if (i < argc - 1)
-        g_print (" ");
-    }
-    g_print ("\n");
-  }
-
-  /* execute */
-  if (execv (path, argv) == -1) {
-    g_warning ("Error executing %s: %s (%d)", path, g_strerror (errno), errno);
-  }
-  g_free (path);
-
-  return 0;
-}
--- a/gstreamer_core/tools/gst-typefind.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Thomas Vander Stichele <thomas@apestaart.org>
- *               2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *               2005 Andy Wingo <wingo@pobox.com>
- *
- * gst-typefind.c: Use GStreamer to find the type of a file
- *
- * 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.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <string.h>
-#include <locale.h>
-
-#include "tools.h"
-
-static void
-have_type_handler (GstElement * typefind, guint probability,
-    const GstCaps * caps, GstCaps ** p_caps)
-{
-  if (p_caps) {
-    *p_caps = gst_caps_copy (caps);
-  }
-}
-
-static void
-typefind_file (const gchar * filename)
-{
-  GstStateChangeReturn sret;
-  GstElement *pipeline;
-  GstElement *source;
-  GstElement *typefind;
-  GstElement *fakesink;
-  GstState state;
-  GstCaps *caps = NULL;
-  GDir *dir;
-
-  if ((dir = g_dir_open (filename, 0, NULL))) {
-    const gchar *entry;
-
-    while ((entry = g_dir_read_name (dir))) {
-      gchar *path;
-
-      path = g_strconcat (filename, G_DIR_SEPARATOR_S, entry, NULL);
-      typefind_file (path);
-      g_free (path);
-    }
-
-    g_dir_close (dir);
-    return;
-  }
-
-  pipeline = gst_pipeline_new ("pipeline");
-
-  source = gst_element_factory_make ("filesrc", "source");
-  g_assert (GST_IS_ELEMENT (source));
-  typefind = gst_element_factory_make ("typefind", "typefind");
-  g_assert (GST_IS_ELEMENT (typefind));
-  fakesink = gst_element_factory_make ("fakesink", "fakesink");
-  g_assert (GST_IS_ELEMENT (typefind));
-
-  gst_bin_add_many (GST_BIN (pipeline), source, typefind, fakesink, NULL);
-  gst_element_link_many (source, typefind, fakesink, NULL);
-
-  g_signal_connect (G_OBJECT (typefind), "have-type",
-      G_CALLBACK (have_type_handler), &caps);
-
-  g_object_set (source, "location", filename, NULL);
-
-  GST_DEBUG ("Starting typefinding for %s", filename);
-
-  /* typefind will only commit to PAUSED if it actually finds a type;
-   * otherwise the state change fails */
-  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
-
-  /* wait until state change either completes or fails */
-  sret = gst_element_get_state (GST_ELEMENT (pipeline), &state, NULL, -1);
-
-  switch (sret) {
-    case GST_STATE_CHANGE_FAILURE:{
-      GstMessage *msg;
-      GstBus *bus;
-      GError *err = NULL;
-
-      bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
-      msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
-      gst_object_unref (bus);
-
-      if (msg) {
-        gst_message_parse_error (msg, &err, NULL);
-        g_printerr ("%s - FAILED: %s\n", filename, err->message);
-        g_error_free (err);
-        gst_message_unref (msg);
-      } else {
-        g_printerr ("%s - FAILED: unknown error\n", filename);
-      }
-      break;
-    }
-    case GST_STATE_CHANGE_SUCCESS:{
-      if (caps) {
-        gchar *caps_str;
-
-        caps_str = gst_caps_to_string (caps);
-        g_print ("%s - %s\n", filename, caps_str);
-        g_free (caps_str);
-        gst_caps_unref (caps);
-      } else {
-        g_print ("%s - %s\n", filename, "No type found");
-      }
-      break;
-    }
-    default:
-      g_assert_not_reached ();
-  }
-
-  gst_element_set_state (pipeline, GST_STATE_NULL);
-  gst_object_unref (pipeline);
-}
-
-int
-main (int argc, char *argv[])
-{
-  gchar **filenames = NULL;
-  guint num, i;
-  GError *err = NULL;
-  GOptionContext *ctx;
-  GOptionEntry options[] = {
-    GST_TOOLS_GOPTION_VERSION,
-    {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL},
-    {NULL}
-  };
-
-#ifdef ENABLE_NLS
-  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-  textdomain (GETTEXT_PACKAGE);
-#endif
-
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-
-  ctx = g_option_context_new ("FILES");
-  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
-  g_option_context_add_group (ctx, gst_init_get_option_group ());
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  gst_tools_print_version ("gst-typefind");
-
-  if (filenames == NULL || *filenames == NULL) {
-    g_print ("Please give a filename to typefind\n\n");
-    return 1;
-  }
-
-  num = g_strv_length (filenames);
-
-  for (i = 0; i < num; ++i) {
-    typefind_file (filenames[i]);
-  }
-
-  g_strfreev (filenames);
-
-  return 0;
-}
--- a/gstreamer_core/tools/gst-xmlinspect.c	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,856 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <string.h>
-#include <locale.h>
-#include <glib/gprintf.h>
-
-#include "tools.h"
-
-#define PUT_START_TAG(pfx,tag)                                  \
-G_STMT_START{                                                   \
-  g_print ("%*.*s<%s>\n", pfx, pfx, "", tag);                   \
-}G_STMT_END
-
-#define PUT_END_TAG(pfx,tag)                                    \
-G_STMT_START{                                                   \
-  g_print ("%*.*s</%s>\n", pfx, pfx, "", tag);                  \
-}G_STMT_END
-
-#define PUT_ESCAPED(pfx,tag,value)                              \
-G_STMT_START{                                                   \
-  const gchar *toconv = value;                                  \
-  if (value) {                                                  \
-    gchar *v = g_markup_escape_text (toconv, strlen (toconv));  \
-    g_print ("%*.*s<%s>%s</%s>\n", pfx, pfx, "", tag, v, tag);  \
-    g_free (v);                                                 \
-  }                                                             \
-}G_STMT_END
-
-#ifdef G_HAVE_ISO_VARARGS
-
-#define PUT_STRING(pfx, ...)                                    \
-G_STMT_START{                                                   \
-  gchar *ps_val = g_strdup_printf(__VA_ARGS__);                 \
-  g_print ("%*.*s%s\n", pfx, pfx, "", ps_val);                  \
-  g_free(ps_val);                                               \
-}G_STMT_END
-
-#elif defined(G_HAVE_GNUC_VARARGS)
-
-#define PUT_STRING(pfx, str, a...)                              \
-G_STMT_START{                                                   \
-  g_print ("%*.*s"str"\n", pfx, pfx, "" , ##a);                 \
-}G_STMT_END
-
-#else
-
-static inline void
-PUT_STRING (int pfx, const char *format, ...)
-{
-  va_list varargs;
-
-  g_print ("%*.*s", pfx, pfx, "");
-  va_start (varargs, format);
-  g_vprintf (format, varargs);
-  va_end (varargs);
-  g_print ("\n");
-}
-
-#endif
-
-static void
-print_caps (const GstCaps * caps, gint pfx)
-{
-  char *s;
-
-  if (!caps)
-    return;
-
-  s = gst_caps_to_string (caps);
-  PUT_ESCAPED (pfx, "caps", s);
-  g_free (s);
-}
-
-#if 0
-static void
-print_formats (const GstFormat * formats, gint pfx)
-{
-  while (formats && *formats) {
-    const GstFormatDefinition *definition;
-
-    definition = gst_format_get_details (*formats);
-    if (definition)
-      PUT_STRING (pfx, "<format id=\"%d\" nick=\"%s\">%s</format>",
-          *formats, definition->nick, definition->description);
-    else
-      PUT_STRING (pfx, "<format id=\"%d\">unknown</format>", *formats);
-
-    formats++;
-  }
-}
-#endif
-
-static void
-print_query_types (const GstQueryType * types, gint pfx)
-{
-  while (types && *types) {
-    const GstQueryTypeDefinition *definition;
-
-    definition = gst_query_type_get_details (*types);
-    if (definition)
-      PUT_STRING (pfx, "<query-type id=\"%d\" nick=\"%s\">%s</query-type>",
-          *types, definition->nick, definition->description);
-    else
-      PUT_STRING (pfx, "<query-type id=\"%d\">unknown</query-type>", *types);
-
-    types++;
-  }
-}
-
-#if 0
-static void
-print_event_masks (const GstEventMask * masks, gint pfx)
-{
-#ifndef GST_DISABLE_ENUMTYPES
-  GType event_type;
-  GEnumClass *klass;
-  GType event_flags;
-  GFlagsClass *flags_class = NULL;
-
-  event_type = gst_event_type_get_type ();
-  klass = (GEnumClass *) g_type_class_ref (event_type);
-
-  while (masks && masks->type) {
-    GEnumValue *value;
-    gint flags = 0, index = 0;
-
-    switch (masks->type) {
-      case GST_EVENT_SEEK:
-        flags = masks->flags;
-        event_flags = gst_seek_type_get_type ();
-        flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
-        break;
-      default:
-        break;
-    }
-
-    value = g_enum_get_value (klass, masks->type);
-    PUT_STRING (pfx, "<event type=\"%s\">", value->value_nick);
-
-    while (flags) {
-      GFlagsValue *value;
-
-      if (flags & 1) {
-        value = g_flags_get_first_value (flags_class, 1 << index);
-
-        if (value)
-          PUT_ESCAPED (pfx + 1, "flag", value->value_nick);
-        else
-          PUT_ESCAPED (pfx + 1, "flag", "?");
-      }
-      flags >>= 1;
-      index++;
-    }
-    PUT_END_TAG (pfx, "event");
-
-    masks++;
-  }
-#endif
-}
-#endif
-
-static void
-output_hierarchy (GType type, gint level, gint * maxlevel)
-{
-  GType parent;
-
-  parent = g_type_parent (type);
-
-  *maxlevel = *maxlevel + 1;
-  level++;
-
-  PUT_STRING (level, "<object name=\"%s\">", g_type_name (type));
-
-  if (parent)
-    output_hierarchy (parent, level, maxlevel);
-
-  PUT_END_TAG (level, "object");
-}
-
-static void
-print_element_properties (GstElement * element, gint pfx)
-{
-  GParamSpec **property_specs;
-  guint num_properties;
-  gint i;
-  gboolean readable;
-
-  property_specs = g_object_class_list_properties
-      (G_OBJECT_GET_CLASS (element), &num_properties);
-
-  PUT_START_TAG (pfx, "element-properties");
-
-  for (i = 0; i < num_properties; i++) {
-    GValue value = { 0, };
-    GParamSpec *param = property_specs[i];
-
-    readable = FALSE;
-
-    g_value_init (&value, param->value_type);
-    if (param->flags & G_PARAM_READABLE) {
-      g_object_get_property (G_OBJECT (element), param->name, &value);
-      readable = TRUE;
-    }
-    PUT_START_TAG (pfx + 1, "element-property");
-    PUT_ESCAPED (pfx + 2, "name", g_param_spec_get_name (param));
-    PUT_ESCAPED (pfx + 2, "type", g_type_name (param->value_type));
-    PUT_ESCAPED (pfx + 2, "nick", g_param_spec_get_nick (param));
-    PUT_ESCAPED (pfx + 2, "blurb", g_param_spec_get_blurb (param));
-    if (readable) {
-      PUT_ESCAPED (pfx + 2, "flags", "RW");
-    } else {
-      PUT_ESCAPED (pfx + 2, "flags", "W");
-    }
-
-    switch (G_VALUE_TYPE (&value)) {
-      case G_TYPE_STRING:
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      case G_TYPE_BOOLEAN:
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      case G_TYPE_ULONG:
-      {
-        GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%lu\" max=\"%lu\"/>",
-            pulong->minimum, pulong->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_LONG:
-      {
-        GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%ld\" max=\"%ld\"/>",
-            plong->minimum, plong->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_UINT:
-      {
-        GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%u\" max=\"%u\"/>",
-            puint->minimum, puint->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_INT:
-      {
-        GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%d\" max=\"%d\"/>",
-            pint->minimum, pint->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_UINT64:
-      {
-        GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
-
-        PUT_STRING (pfx + 2,
-            "<range min=\"%" G_GUINT64_FORMAT "\" max=\"%" G_GUINT64_FORMAT
-            "\"/>", puint64->minimum, puint64->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_INT64:
-      {
-        GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
-
-        PUT_STRING (pfx + 2,
-            "<range min=\"%" G_GINT64_FORMAT "\" max=\"%" G_GINT64_FORMAT
-            "\"/>", pint64->minimum, pint64->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_FLOAT:
-      {
-        GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%f\" max=\"%f\"/>",
-            pfloat->minimum, pfloat->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_DOUBLE:
-      {
-        GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%g\" max=\"%g\"/>",
-            pdouble->minimum, pdouble->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      default:
-        if (param->value_type == GST_TYPE_CAPS) {
-          GstCaps *caps = g_value_peek_pointer (&value);
-
-          if (!caps)
-            PUT_ESCAPED (pfx + 2, "default", "NULL");
-          else {
-            print_caps (caps, 2);
-          }
-        } else if (G_IS_PARAM_SPEC_ENUM (param)) {
-          GEnumValue *values;
-          guint j = 0;
-          gint enum_value;
-
-          values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
-          enum_value = g_value_get_enum (&value);
-
-          while (values[j].value_name) {
-            if (values[j].value == enum_value)
-              break;
-            j++;
-          }
-          PUT_STRING (pfx + 2, "<default>%d</default>", values[j].value);
-
-          PUT_START_TAG (pfx + 2, "enum-values");
-          j = 0;
-          while (values[j].value_name) {
-            PUT_STRING (pfx + 3, "<value value=\"%d\" nick=\"%s\"/>",
-                values[j].value, values[j].value_nick);
-            j++;
-          }
-          PUT_END_TAG (pfx + 2, "enum-values");
-        } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
-          GFlagsValue *values;
-          guint j = 0;
-          gint flags_value;
-
-          values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
-          flags_value = g_value_get_flags (&value);
-
-          PUT_STRING (pfx + 2, "<default>%d</default>", flags_value);
-
-          PUT_START_TAG (pfx + 2, "flags");
-          j = 0;
-          while (values[j].value_name) {
-            PUT_STRING (pfx + 3, "<flag value=\"%d\" nick=\"%s\"/>",
-                values[j].value, values[j].value_nick);
-            j++;
-          }
-          PUT_END_TAG (pfx + 2, "flags");
-        } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
-          PUT_ESCAPED (pfx + 2, "object-type", g_type_name (param->value_type));
-        }
-        break;
-    }
-
-    PUT_END_TAG (pfx + 1, "element-property");
-  }
-  PUT_END_TAG (pfx, "element-properties");
-  g_free (property_specs);
-}
-
-static void
-print_element_signals (GstElement * element, gint pfx)
-{
-  guint *signals;
-  guint nsignals;
-  gint i, k;
-  GSignalQuery *query;
-
-  signals = g_signal_list_ids (G_OBJECT_TYPE (element), &nsignals);
-  for (k = 0; k < 2; k++) {
-    gint counted = 0;
-
-    if (k == 0)
-      PUT_START_TAG (pfx, "element-signals");
-    else
-      PUT_START_TAG (pfx, "element-actions");
-
-    for (i = 0; i < nsignals; i++) {
-      gint n_params;
-      GType return_type;
-      const GType *param_types;
-      gint j;
-
-      query = g_new0 (GSignalQuery, 1);
-      g_signal_query (signals[i], query);
-
-      if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
-          (k == 1 && (query->signal_flags & G_SIGNAL_ACTION))) {
-        n_params = query->n_params;
-        return_type = query->return_type;
-        param_types = query->param_types;
-
-        PUT_START_TAG (pfx + 1, "signal");
-        PUT_ESCAPED (pfx + 2, "name", query->signal_name);
-        PUT_ESCAPED (pfx + 2, "return-type", g_type_name (return_type));
-        PUT_ESCAPED (pfx + 2, "object-type",
-            g_type_name (G_OBJECT_TYPE (element)));
-
-        PUT_START_TAG (pfx + 2, "params");
-        for (j = 0; j < n_params; j++) {
-          PUT_ESCAPED (pfx + 3, "type", g_type_name (param_types[j]));
-        }
-
-        PUT_END_TAG (pfx + 2, "params");
-
-        PUT_END_TAG (pfx + 1, "signal");
-
-        counted++;
-      }
-
-      g_free (query);
-    }
-    if (k == 0)
-      PUT_END_TAG (pfx, "element-signals");
-    else
-      PUT_END_TAG (pfx, "element-actions");
-  }
-}
-
-static gint
-print_element_info (GstElementFactory * factory)
-{
-  GstElement *element;
-  GstObjectClass *gstobject_class;
-  GstElementClass *gstelement_class;
-  GList *pads;
-  GstPad *pad;
-  GstStaticPadTemplate *padtemplate;
-  gint maxlevel = 0;
-
-  element = gst_element_factory_create (factory, "element");
-  if (!element) {
-    g_print ("couldn't construct element for some reason\n");
-    return -1;
-  }
-  PUT_START_TAG (0, "element");
-  PUT_ESCAPED (1, "name", GST_PLUGIN_FEATURE_NAME (factory));
-
-  gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
-  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
-
-  PUT_START_TAG (1, "details");
-  PUT_ESCAPED (2, "long-name", factory->details.longname);
-  PUT_ESCAPED (2, "class", factory->details.klass);
-  PUT_ESCAPED (2, "description", factory->details.description);
-  PUT_ESCAPED (2, "authors", factory->details.author);
-  PUT_END_TAG (1, "details");
-
-  output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
-
-  PUT_START_TAG (1, "pad-templates");
-  if (factory->numpadtemplates) {
-    pads = factory->staticpadtemplates;
-    while (pads) {
-      padtemplate = (GstStaticPadTemplate *) (pads->data);
-      pads = g_list_next (pads);
-
-      PUT_START_TAG (2, "pad-template");
-      PUT_ESCAPED (3, "name", padtemplate->name_template);
-
-      if (padtemplate->direction == GST_PAD_SRC)
-        PUT_ESCAPED (3, "direction", "src");
-      else if (padtemplate->direction == GST_PAD_SINK)
-        PUT_ESCAPED (3, "direction", "sink");
-      else
-        PUT_ESCAPED (3, "direction", "unknown");
-
-      if (padtemplate->presence == GST_PAD_ALWAYS)
-        PUT_ESCAPED (3, "presence", "always");
-      else if (padtemplate->presence == GST_PAD_SOMETIMES)
-        PUT_ESCAPED (3, "presence", "sometimes");
-      else if (padtemplate->presence == GST_PAD_REQUEST) {
-        PUT_ESCAPED (3, "presence", "request");
-        PUT_ESCAPED (3, "request-function",
-            GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
-      } else
-        PUT_ESCAPED (3, "presence", "unknown");
-
-      if (padtemplate->static_caps.string) {
-        print_caps (gst_static_caps_get (&padtemplate->static_caps), 3);
-      }
-      PUT_END_TAG (2, "pad-template");
-    }
-  }
-  PUT_END_TAG (1, "pad-templates");
-
-  PUT_START_TAG (1, "element-flags");
-  PUT_END_TAG (1, "element-flags");
-
-  if (GST_IS_BIN (element)) {
-    PUT_START_TAG (1, "bin-flags");
-
-    PUT_END_TAG (1, "bin-flags");
-  }
-
-
-  PUT_START_TAG (1, "element-implementation");
-
-  PUT_STRING (2, "<state-change function=\"%s\"/>",
-      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
-
-#ifndef GST_DISABLE_LOADSAVE
-  PUT_STRING (2, "<save function=\"%s\"/>",
-      GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
-  PUT_STRING (2, "<load function=\"%s\"/>",
-      GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
-#endif
-  PUT_END_TAG (1, "element-implementation");
-
-  PUT_START_TAG (1, "clocking-interaction");
-  if (gst_element_requires_clock (element)) {
-    PUT_STRING (2, "<requires-clock/>");
-  }
-  if (gst_element_provides_clock (element)) {
-    GstClock *clock;
-
-    clock = gst_element_get_clock (element);
-    if (clock)
-      PUT_STRING (2, "<provides-clock name=\"%s\"/>", GST_OBJECT_NAME (clock));
-  }
-  PUT_END_TAG (1, "clocking-interaction");
-
-#ifndef GST_DISABLE_INDEX
-  if (gst_element_is_indexable (element)) {
-    PUT_STRING (1, "<indexing-capabilities/>");
-  }
-#endif
-
-  PUT_START_TAG (1, "pads");
-  if (element->numpads) {
-    const GList *pads;
-
-    pads = element->pads;
-    while (pads) {
-      pad = GST_PAD (pads->data);
-      pads = g_list_next (pads);
-
-      PUT_START_TAG (2, "pad");
-      PUT_ESCAPED (3, "name", gst_pad_get_name (pad));
-
-      if (gst_pad_get_direction (pad) == GST_PAD_SRC)
-        PUT_ESCAPED (3, "direction", "src");
-      else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
-        PUT_ESCAPED (3, "direction", "sink");
-      else
-        PUT_ESCAPED (3, "direction", "unknown");
-
-      if (pad->padtemplate)
-        PUT_ESCAPED (3, "template", pad->padtemplate->name_template);
-
-      PUT_START_TAG (3, "implementation");
-      if (pad->chainfunc)
-        PUT_STRING (4, "<chain-based function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
-      if (pad->getrangefunc)
-        PUT_STRING (4, "<get-range-based function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
-      if (pad->eventfunc != gst_pad_event_default)
-        PUT_STRING (4, "<event-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
-      if (pad->queryfunc != gst_pad_query_default)
-        PUT_STRING (4, "<query-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
-      if (pad->querytypefunc != gst_pad_get_query_types_default) {
-        PUT_STRING (4, "<query-type-func function=\"%s\">",
-            GST_DEBUG_FUNCPTR_NAME (pad->querytypefunc));
-        print_query_types (gst_pad_get_query_types (pad), 5);
-        PUT_END_TAG (4, "query-type-func");
-      }
-
-      if (pad->intlinkfunc != gst_pad_get_internal_links_default)
-        PUT_STRING (4, "<intlink-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->intlinkfunc));
-
-      if (pad->bufferallocfunc)
-        PUT_STRING (4, "<bufferalloc-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
-      PUT_END_TAG (3, "implementation");
-
-      if (pad->caps) {
-        print_caps (pad->caps, 3);
-      }
-      PUT_END_TAG (2, "pad");
-    }
-  }
-  PUT_END_TAG (1, "pads");
-
-  print_element_properties (element, 1);
-  print_element_signals (element, 1);
-
-  /* for compound elements */
-  /* FIXME: gst_bin_get_list does not exist anymore
-     if (GST_IS_BIN (element)) {
-     GList *children;
-     GstElement *child;
-     PUT_START_TAG (1, "children");
-     children = (GList *) gst_bin_get_list (GST_BIN (element));
-     while (children) {
-     child = GST_ELEMENT (children->data);
-     children = g_list_next (children);
-
-     PUT_ESCAPED (2, "child", GST_ELEMENT_NAME (child));
-     }
-     PUT_END_TAG (1, "children");
-     }
-   */
-  PUT_END_TAG (0, "element");
-
-  return 0;
-}
-
-static void
-print_element_list (void)
-{
-  GList *plugins;
-
-  plugins = gst_default_registry_get_plugin_list ();
-  while (plugins) {
-    GList *features;
-    GstPlugin *plugin;
-
-    plugin = (GstPlugin *) (plugins->data);
-    plugins = g_list_next (plugins);
-
-    features =
-        gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
-        plugin->desc.name);
-    while (features) {
-      GstPluginFeature *feature;
-
-      feature = GST_PLUGIN_FEATURE (features->data);
-
-      if (GST_IS_ELEMENT_FACTORY (feature)) {
-        GstElementFactory *factory;
-
-        factory = GST_ELEMENT_FACTORY (feature);
-        g_print ("%s:  %s: %s\n", plugin->desc.name,
-            GST_PLUGIN_FEATURE_NAME (factory),
-            gst_element_factory_get_longname (factory));
-      }
-#ifndef GST_DISABLE_INDEX
-      else if (GST_IS_INDEX_FACTORY (feature)) {
-        GstIndexFactory *factory;
-
-        factory = GST_INDEX_FACTORY (feature);
-        g_print ("%s:  %s: %s\n", plugin->desc.name,
-            GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
-      }
-#endif
-      else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
-        GstTypeFindFactory *factory;
-
-        factory = GST_TYPE_FIND_FACTORY (feature);
-        if (factory->extensions) {
-          guint i = 0;
-
-          g_print ("%s type: ", plugin->desc.name);
-          while (factory->extensions[i]) {
-            g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
-            i++;
-          }
-        } else
-          g_print ("%s type: N/A\n", plugin->desc.name);
-      } else {
-        g_print ("%s:  %s (%s)\n", plugin->desc.name,
-            GST_PLUGIN_FEATURE_NAME (feature),
-            g_type_name (G_OBJECT_TYPE (feature)));
-      }
-
-      features = g_list_next (features);
-    }
-  }
-}
-
-static void
-print_plugin_info (GstPlugin * plugin)
-{
-  GList *features;
-  gint num_features = 0;
-  gint num_elements = 0;
-  gint num_autoplug = 0;
-  gint num_types = 0;
-  gint num_indexes = 0;
-  gint num_other = 0;
-
-  g_print ("Plugin Details:\n");
-  g_print ("  Name:\t\t%s\n", plugin->desc.name);
-  g_print ("  Description:\t%s\n", plugin->desc.description);
-  g_print ("  Filename:\t%s\n", plugin->filename);
-  g_print ("  Version:\t%s\n", plugin->desc.version);
-  g_print ("  License:\t%s\n", plugin->desc.license);
-  g_print ("  Package:\t%s\n", plugin->desc.package);
-  g_print ("  Origin URL:\t%s\n", plugin->desc.origin);
-  g_print ("\n");
-
-  features =
-      gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
-      plugin->desc.name);
-
-  while (features) {
-    GstPluginFeature *feature;
-
-    feature = GST_PLUGIN_FEATURE (features->data);
-
-    if (GST_IS_ELEMENT_FACTORY (feature)) {
-      GstElementFactory *factory;
-
-      factory = GST_ELEMENT_FACTORY (feature);
-      g_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
-          gst_element_factory_get_longname (factory));
-      num_elements++;
-    }
-#ifndef GST_DISABLE_INDEX
-    else if (GST_IS_INDEX_FACTORY (feature)) {
-      GstIndexFactory *factory;
-
-      factory = GST_INDEX_FACTORY (feature);
-      g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
-      num_indexes++;
-    }
-#endif
-    else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
-      GstTypeFindFactory *factory;
-
-      factory = GST_TYPE_FIND_FACTORY (feature);
-      if (factory->extensions) {
-        guint i = 0;
-
-        g_print ("%s type: ", plugin->desc.name);
-        while (factory->extensions[i]) {
-          g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
-          i++;
-        }
-      } else
-        g_print ("%s type: N/A\n", plugin->desc.name);
-      num_types++;
-    } else {
-      g_print ("  %s (%s)\n", GST_OBJECT_NAME (feature),
-          g_type_name (G_OBJECT_TYPE (feature)));
-      num_other++;
-    }
-    num_features++;
-    features = g_list_next (features);
-  }
-  g_print ("\n  %d features:\n", num_features);
-  if (num_elements > 0)
-    g_print ("  +-- %d elements\n", num_elements);
-  if (num_autoplug > 0)
-    g_print ("  +-- %d autopluggers\n", num_autoplug);
-  if (num_types > 0)
-    g_print ("  +-- %d types\n", num_types);
-  if (num_indexes > 0)
-    g_print ("  +-- %d indexes\n", num_indexes);
-  if (num_other > 0)
-    g_print ("  +-- %d other objects\n", num_other);
-
-  g_print ("\n");
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  GstElementFactory *factory;
-  GstPlugin *plugin;
-  gchar *so;
-  GOptionEntry options[] = {
-    {"gst-inspect-plugin", 'p', 0, G_OPTION_ARG_STRING,
-        "Show plugin details", NULL},
-    {"gst-inspect-scheduler", 's', 0, G_OPTION_ARG_STRING,
-        "Show scheduler details", NULL},
-    GST_TOOLS_GOPTION_VERSION,
-    {NULL}
-  };
-  GOptionContext *ctx;
-  GError *err = NULL;
-
-  setlocale (LC_ALL, "");
-
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-
-  ctx = g_option_context_new ("[ELEMENT-NAME | PLUGIN-NAME]");
-  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
-  g_option_context_add_group (ctx, gst_init_get_option_group ());
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    g_print ("Error initializing: %s\n", err->message);
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  gst_tools_print_version ("gst-xmlinspect");
-
-  PUT_STRING (0, "<?xml version=\"1.0\"?>");
-
-  /* if no arguments, print out list of elements */
-  if (argc == 1) {
-    print_element_list ();
-
-    /* else we try to get a factory */
-  } else {
-    /* first check for help */
-    if (strstr (argv[1], "-help")) {
-      g_print ("Usage: %s\t\t\tList all registered elements\n", argv[0]);
-      g_print ("       %s element-name\tShow element details\n", argv[0]);
-      g_print ("       %s plugin-name[.so]\tShow information about plugin\n",
-          argv[0]);
-      return 0;
-    }
-
-    /* only search for a factory if there's not a '.so' */
-    if (!strstr (argv[1], ".so")) {
-      factory = gst_element_factory_find (argv[1]);
-
-      /* if there's a factory, print out the info */
-      if (factory)
-        return print_element_info (factory);
-      else {
-        GstPluginFeature *feature;
-
-        /* FIXME implement other pretty print function for these */
-#ifndef GST_DISABLE_INDEX
-        feature = gst_default_registry_find_feature (argv[1],
-            GST_TYPE_INDEX_FACTORY);
-        if (feature) {
-          g_print ("%s: an index\n", argv[1]);
-          return 0;
-        }
-#endif
-        feature = gst_default_registry_find_feature (argv[1],
-            GST_TYPE_TYPE_FIND_FACTORY);
-        if (feature) {
-          g_print ("%s: a type find function\n", argv[1]);
-          return 0;
-        }
-      }
-    } else {
-      /* strip the .so */
-      so = strstr (argv[1], ".so");
-      so[0] = '\0';
-    }
-
-    /* otherwise assume it's a plugin */
-    plugin = gst_default_registry_find_plugin (argv[1]);
-
-    /* if there is such a plugin, print out info */
-
-    if (plugin) {
-      print_plugin_info (plugin);
-    } else {
-      g_print ("no such element or plugin '%s'\n", argv[1]);
-      return -1;
-    }
-  }
-
-  return 0;
-}
--- a/gstreamer_core/tools/tools.h	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Benjamin Otte <otte@gnome.org>
- *
- * tools.h: header for common stuff of all GStreamer tools
- *
- * 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_TOOLS_H__
-#define __GST_TOOLS_H__
-
-#include <stdlib.h>
-
-#include <gst/gst.h>
-#include "gst/gst-i18n-app.h"
-
-/*
- * This is a kind of hacky way to make all the tools use the same version code.
- * If anyone knows a less hacky way to get this done, feel free to implement it.
- * 
- * It also includes all the files that all the tools require.
- */
-
-static gboolean __gst_tools_version = FALSE;
-
-#define GST_TOOLS_GOPTION_VERSION \
-    { "version", 0, 0, G_OPTION_ARG_NONE, &__gst_tools_version, \
-      N_("Print version information and exit"), NULL }
-
-static void
-gst_tools_print_version (const gchar * tool)
-{
-  gchar *s;
-
-  s = g_strdup_printf ("%s-%u.%u", tool, GST_VERSION_MAJOR, GST_VERSION_MINOR);
-  g_set_prgname (s);
-  g_free (s);
-
-  if (__gst_tools_version) {
-    gchar *version_str;
-
-    version_str = gst_version_string ();
-    g_print ("%s version %u.%u.%u\n", g_get_prgname (),
-        GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO);
-    g_print ("%s\n", version_str);
-    g_print ("%s\n", GST_PACKAGE_ORIGIN);
-    g_free (version_str);
-    exit (0);
-  }
-}
-
-#endif /* __GST_TOOLS_H__ */
--- a/gstreamer_core/tsrc/check/elements/createelementcore/src/createelementcore.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/createelementcore/src/createelementcore.c	Fri Apr 16 15:15:52 2010 +0300
@@ -108,11 +108,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
    
 void test_createelement_core()
@@ -193,16 +202,21 @@
    create_xml(0);
  }
 
-void (*fn[]) (void) = {
-        test_createelement_core
-};
+//void (*fn[]) (void) = {
+//        test_createelement_core
+//};
+//
+//char *args[] = {
+//        "test_createelement_core"
+//};
+//
+//GST_CHECK_MAIN (createelementcore);
 
-char *args[] = {
-        "test_createelement_core"
-};
-
-GST_CHECK_MAIN (createelementcore);
+int main()
+    {
+    gst_check_init(NULL,NULL);
+    test_createelement_core();
+    return 0;
+    }
 
 
-
-
--- a/gstreamer_core/tsrc/check/elements/fakesink/src/fakesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/fakesink/src/fakesink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -32,11 +32,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 typedef struct
--- a/gstreamer_core/tsrc/check/elements/fakesrc/src/fakesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/fakesrc/src/fakesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,11 +31,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gstreamer_core/tsrc/check/elements/fdsrc/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/fdsrc/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -20,8 +20,8 @@
 *
 */
 
-PRJ_EXPORTS
-//warning.wav       /epoc32/winscw/c/data/gstreamer/warning.wav
+PRJ_TESTEXPORTS
+warning.wav       /epoc32/winscw/c/data/gstreamer/warning.wav
 
 PRJ_TESTMMPFILES
 
--- a/gstreamer_core/tsrc/check/elements/fdsrc/src/fdsrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/fdsrc/src/fdsrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -50,11 +50,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gstreamer_core/tsrc/check/elements/filesink/src/filesink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/filesink/src/filesink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,7 +35,7 @@
 #endif
 
 #include <libgstreamer_wsd_macros.h>
-
+#include <stdlib.h>
 
 
 #define LOG_FILE "c:\\logs\\filesink_log1.txt"
@@ -47,11 +47,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+ 
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -449,4 +458,4 @@
  test_coverage();	                    
  test_uri_interface();              
 }
-#endif
\ No newline at end of file
+#endif
--- a/gstreamer_core/tsrc/check/elements/filesrc/src/filesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/filesrc/src/filesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -49,11 +49,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
@@ -485,11 +494,11 @@
   
 
   location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
-  fail_unless_equals_string (location, "file://%2Ffoo%2Fbar");
+  fail_unless_equals_string (location, "file://%5Cfoo%5Cbar");
   
 
   g_object_get (G_OBJECT (src), "location", &location, NULL);
-  fail_unless_equals_string (location, "/foo/bar");
+  fail_unless_equals_string (location, "\\foo\\bar");
   
 
   g_free (location);
@@ -500,11 +509,11 @@
   
 
   location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
-  fail_unless_equals_string (location, "file://%2Ffoo%2Fbaz");
+  fail_unless_equals_string (location, "file://%5Cfoo%5Cbaz");
   
 
   g_object_get (G_OBJECT (src), "location", &location, NULL);
-  fail_unless_equals_string (location, "/foo/baz");
+  fail_unless_equals_string (location, "\\foo\\baz");
   
 
   g_free (location);
--- a/gstreamer_core/tsrc/check/elements/gstqueue/src/gstqueue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/gstqueue/src/gstqueue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
@@ -315,12 +324,13 @@
   /* pushing gives away my reference ... */
   gst_pad_push (mysrcpad, gst_buffer_ref (buffer3));
 
-  g_mutex_lock (check_mutex);
+  //g_mutex_lock (check_mutex);
   /* start the src-task briefly leak buffer3 */
   gst_pad_set_active (mysinkpad, TRUE);
-  g_cond_wait (check_cond, check_mutex);
-  g_mutex_unlock (check_mutex);
-
+  //g_cond_wait (check_cond, check_mutex);
+  //g_mutex_unlock (check_mutex);
+  /// wait for second thread to read buffer.
+  sleep(2);
   gst_pad_set_active (mysinkpad, FALSE);
 
   GST_DEBUG ("stopping");
@@ -406,12 +416,12 @@
   /* pushing gives away my reference ... */
   gst_pad_push (mysrcpad, buffer3);
 
-  g_mutex_lock (check_mutex);
+  //g_mutex_lock (check_mutex);
   /* start the src-task briefly and leak buffer1 */
   gst_pad_set_active (mysinkpad, TRUE);
-  g_cond_wait (check_cond, check_mutex);
-  g_mutex_unlock (check_mutex);
-
+  //g_cond_wait (check_cond, check_mutex);
+  //g_mutex_unlock (check_mutex);
+  sleep(2);
   gst_pad_set_active (mysinkpad, FALSE);
 
   GST_DEBUG ("stopping");
--- a/gstreamer_core/tsrc/check/elements/identity/src/identity.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/identity/src/identity.c	Fri Apr 16 15:15:52 2010 +0300
@@ -40,11 +40,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gstreamer_core/tsrc/check/elements/multiqueue/src/multiqueue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/multiqueue/src/multiqueue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static GStaticMutex _check_lock = G_STATIC_MUTEX_INIT;
--- a/gstreamer_core/tsrc/check/elements/tee/src/tee.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/elements/tee/src/tee.c	Fri Apr 16 15:15:52 2010 +0300
@@ -36,11 +36,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static void
--- a/gstreamer_core/tsrc/check/generic/gststates/src/gststates.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/generic/gststates/src/gststates.c	Fri Apr 16 15:15:52 2010 +0300
@@ -45,11 +45,20 @@
 int fd_new;
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/generic/sinks/src/sinks.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/generic/sinks/src/sinks.c	Fri Apr 16 15:15:52 2010 +0300
@@ -105,11 +105,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gst/src/gst.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gst/src/gst.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstbin/src/gstbin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstbin/src/gstbin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -34,11 +34,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
@@ -401,7 +410,7 @@
    * base_src is blocked in the push and has an extra refcount.
    * base_sink_chain has taken a refcount on the sink, and is blocked on
    * preroll */
-  ASSERT_OBJECT_REFCOUNT (src, "src", 2);
+  ASSERT_OBJECT_REFCOUNT (src, "src", 4);
   /* refcount can be 4 if the bin is still processing the async_done message of
    * the sink. */
   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
@@ -453,7 +462,7 @@
   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
 
   /* each object is referenced by two messages */
-  ASSERT_OBJECT_REFCOUNT (src, "src", 3);
+  ASSERT_OBJECT_REFCOUNT (src, "src", 4);
   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
 
@@ -1028,6 +1037,85 @@
   create_xml(0); 
 }
 
+static void
+test_link_structure_change_state_changed_sync_cb (GstBus * bus,
+    GstMessage * message, gpointer data)
+{
+  GstPipeline *pipeline = GST_PIPELINE (data);
+  GstElement *src, *identity, *sink;
+  GstState old, snew, pending;
+
+  sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
+  fail_unless (sink != NULL, "Could not get sink");
+
+  gst_message_parse_state_changed (message, &old, &snew, &pending);
+  if (message->src != GST_OBJECT (sink) || snew != GST_STATE_READY) {
+    gst_object_unref (sink);
+    return;
+  }
+
+  src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
+  fail_unless (src != NULL, "Could not get src");
+
+  identity = gst_bin_get_by_name (GST_BIN (pipeline), "identity");
+  fail_unless (identity != NULL, "Could not get identity");
+
+  /* link src to identity, the pipeline should detect the new link and
+   * resync the state change */
+  fail_unless (gst_element_link (src, identity) == TRUE);
+
+  gst_object_unref (src);
+  gst_object_unref (identity);
+  gst_object_unref (sink);
+}
+
+void test_link_structure_change()
+{
+  GstElement *src, *identity, *sink, *pipeline;
+  GstBus *bus;
+  GstState state;
+  xmlfile = "test_link_structure_change";
+  std_log(LOG_FILENAME_LINE, "Test Started test_link_structure_change"); 
+  pipeline = gst_pipeline_new (NULL);
+  fail_unless (pipeline != NULL, "Could not create pipeline");
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  fail_unless (bus != NULL, "Could not get bus");
+
+  /* use the sync signal handler to link elements while the pipeline is still
+   * doing the state change */
+  gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, pipeline);
+  g_object_connect (bus, "signal::sync-message::state-changed",
+      G_CALLBACK (test_link_structure_change_state_changed_sync_cb), pipeline,
+      NULL);
+
+  src = gst_element_factory_make ("fakesrc", "src");
+  fail_if (src == NULL, "Could not create fakesrc");
+
+  identity = gst_element_factory_make ("identity", "identity");
+  fail_if (identity == NULL, "Could not create identity");
+
+  sink = gst_element_factory_make ("fakesink", "sink");
+  fail_if (sink == NULL, "Could not create fakesink1");
+
+  gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
+
+  gst_element_set_state (pipeline, GST_STATE_READY);
+  gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
+
+  /* the state change will be done on src only if the pipeline correctly resyncs
+   * after that filesrc has been linked to identity */
+  gst_element_get_state (src, &state, NULL, 0);
+  fail_unless_equals_int (state, GST_STATE_READY);
+
+  gst_object_unref (bus);
+  gst_object_unref (pipeline);
+  
+  std_log(LOG_FILENAME_LINE, "Test test_link_structure_change Successful");
+  create_xml(0); 
+}
+
+
 void (*fn[]) (void) = {
 test_message_state_changed,
 test_interface,
@@ -1039,7 +1127,8 @@
 test_iterate_sorted,
 test_children_state_change_order_flagged_sink,
 test_children_state_change_order_semi_sink,
-test_children_state_change_order_two_sink
+test_children_state_change_order_two_sink,
+test_link_structure_change
 };
 
 char *args[] = {
@@ -1053,7 +1142,8 @@
 "test_iterate_sorted",
 "test_children_state_change_order_flagged_sink",
 "test_children_state_change_order_semi_sink",
-"test_children_state_change_order_two_sink"
+"test_children_state_change_order_two_sink",
+"test_link_structure_change"
 };
 
 GST_CHECK_MAIN (gst_bin);
--- a/gstreamer_core/tsrc/check/gst/gstbuffer/src/gstbuffer.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstbuffer/src/gstbuffer.c	Fri Apr 16 15:15:52 2010 +0300
@@ -107,11 +107,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gstreamer_core/tsrc/check/gst/gstbus/src/gstbus.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstbus/src/gstbus.c	Fri Apr 16 15:15:52 2010 +0300
@@ -96,11 +96,20 @@
 #define LOG_FILENAME_LINE __FILE__, __LINE__
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstcaps/src/gstcaps.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstcaps/src/gstcaps.c	Fri Apr 16 15:15:52 2010 +0300
@@ -75,11 +75,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstelement/src/gstelement.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstelement/src/gstelement.c	Fri Apr 16 15:15:52 2010 +0300
@@ -30,11 +30,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstevent/src/gstevent.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstevent/src/gstevent.c	Fri Apr 16 15:15:52 2010 +0300
@@ -26,14 +26,24 @@
 #include <gst/gst_global.h>
 #include "std_log_result.h" 
 #define LOG_FILENAME_LINE __FILE__, __LINE__
+#include <stdlib.h> 
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -455,43 +465,43 @@
   g_object_set (G_OBJECT (fakesink), "silent", TRUE, "sync", TRUE, NULL);
 
   /* add pad-probes to faksrc.src and fakesink.sink */
-  fail_if ((srcpad = gst_element_get_pad (fakesrc, "src")) == NULL);
+  fail_if ((srcpad = gst_element_get_static_pad (fakesrc, "src")) == NULL);
   gst_pad_add_event_probe (srcpad, (GCallback) event_probe,
       GINT_TO_POINTER (TRUE));
 
-  fail_if ((sinkpad = gst_element_get_pad (fakesink, "sink")) == NULL);
+  fail_if ((sinkpad = gst_element_get_static_pad (fakesink, "sink")) == NULL);
   gst_pad_add_event_probe (sinkpad, (GCallback) event_probe,
       GINT_TO_POINTER (FALSE));
 
   /* Upstream events */
   test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
   fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+          &sent_event_time) < G_USEC_PER_SEC,
       "GST_EVENT_CUSTOM_UP took too long to reach source: %"
       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad);
   fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+          &sent_event_time) < G_USEC_PER_SEC,
       "GST_EVENT_CUSTOM_BOTH took too long to reach source: %"
       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad);
   fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+          &sent_event_time) < G_USEC_PER_SEC ,
       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
 
   /* Out of band downstream events */
   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad);
   fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+          &sent_event_time) < G_USEC_PER_SEC ,
       "GST_EVENT_CUSTOM_DS_OOB took too long to reach source: %"
       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad);
   fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+          &sent_event_time) < G_USEC_PER_SEC,
       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
       G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
 
--- a/gstreamer_core/tsrc/check/gst/gstghostpad/src/gstghostpad.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstghostpad/src/gstghostpad.c	Fri Apr 16 15:15:52 2010 +0300
@@ -49,11 +49,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -396,9 +405,9 @@
   ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
 
   ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2);   /* gsink */
-  ASSERT_OBJECT_REFCOUNT (isink, "isink", 2);   /* gsink */
+  ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);   /* gsink */
   ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* gsrc */
-  ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 2);     /* gsrc */
+  ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1);     /* gsrc */
 
   gst_object_unref (gsink);
   ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);
@@ -590,6 +599,8 @@
   GstPad *sinkpad, *ghostpad;
   GstPadTemplate *padtempl, *ghosttempl;
   GstCaps *padcaps, *ghostcaps, *newcaps;
+  GstCaps *copypadcaps;
+  
 	xmlfile = "gstghostpad_test_ghost_pads_new_from_template";
   std_log(LOG_FILENAME_LINE, "Test Started test_ghost_pads_new_from_template");  
   padcaps = gst_caps_from_string ("some/caps");
@@ -597,8 +608,9 @@
   ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
   fail_unless (ghostcaps != NULL);
 
+  copypadcaps = gst_caps_copy (padcaps);
   padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
-      GST_PAD_ALWAYS, padcaps);
+      GST_PAD_ALWAYS, copypadcaps);
   fail_unless (padtempl != NULL);
   ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
       GST_PAD_ALWAYS, ghostcaps);
@@ -618,6 +630,12 @@
   fail_unless (gst_caps_is_equal (newcaps, padcaps));
   gst_caps_unref (newcaps);
   gst_caps_unref (padcaps);
+  
+  gst_object_unref (sinkpad);
+  gst_object_unref (ghostpad);
+
+  gst_object_unref (padtempl);
+  gst_object_unref (ghosttempl);
   std_log(LOG_FILENAME_LINE, "Test Successful");
 	create_xml(0);
 }
@@ -629,6 +647,8 @@
   GstPad *sinkpad, *ghostpad;
   GstPadTemplate *padtempl, *ghosttempl;
   GstCaps *padcaps, *ghostcaps, *newcaps;
+  GstCaps *copypadcaps, *copyghostcaps;
+  
 	xmlfile = "gstghostpad_test_ghost_pads_new_no_target_from_template";
   std_log(LOG_FILENAME_LINE, "Test Started test_ghost_pads_new_no_target_from_template");  
   padcaps = gst_caps_from_string ("some/caps");
@@ -636,11 +656,14 @@
   ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
   fail_unless (ghostcaps != NULL);
 
+  copypadcaps = gst_caps_copy (padcaps);
+   copyghostcaps = gst_caps_copy (ghostcaps);
+   
   padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
-      GST_PAD_ALWAYS, padcaps);
+      GST_PAD_ALWAYS, copypadcaps);
   fail_unless (padtempl != NULL);
   ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
-      GST_PAD_ALWAYS, ghostcaps);
+      GST_PAD_ALWAYS, copyghostcaps);
 
   sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
   fail_unless (sinkpad != NULL);
@@ -664,6 +687,16 @@
   fail_unless (newcaps != NULL);
   fail_unless (gst_caps_is_equal (newcaps, padcaps));
   gst_caps_unref (newcaps);
+  
+  gst_object_unref (sinkpad);
+  gst_object_unref (ghostpad);
+
+  gst_object_unref (padtempl);
+  gst_object_unref (ghosttempl);
+
+  gst_caps_unref (padcaps);
+  gst_caps_unref (ghostcaps);
+  
   std_log(LOG_FILENAME_LINE, "Test Successful");
 	create_xml(0);
 }
--- a/gstreamer_core/tsrc/check/gst/gstindex/src/gstindex.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstindex/src/gstindex.c	Fri Apr 16 15:15:52 2010 +0300
@@ -26,11 +26,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/check/gstcheck.h>
--- a/gstreamer_core/tsrc/check/gst/gstinterface/src/gstinterface.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstinterface/src/gstinterface.c	Fri Apr 16 15:15:52 2010 +0300
@@ -27,11 +27,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstiterator/src/gstiterator.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstiterator/src/gstiterator.c	Fri Apr 16 15:15:52 2010 +0300
@@ -38,11 +38,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static GList *
--- a/gstreamer_core/tsrc/check/gst/gstmessage/src/gstmessage.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstmessage/src/gstmessage.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static GQuark domain;
--- a/gstreamer_core/tsrc/check/gst/gstminiobject/src/gstminiobject.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstminiobject/src/gstminiobject.c	Fri Apr 16 15:15:52 2010 +0300
@@ -32,11 +32,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #if EMULATOR
--- a/gstreamer_core/tsrc/check/gst/gstobject/src/gstobject.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstobject/src/gstobject.c	Fri Apr 16 15:15:52 2010 +0300
@@ -32,11 +32,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstpad/src/gstpad.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstpad/src/gstpad.c	Fri Apr 16 15:15:52 2010 +0300
@@ -33,11 +33,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include "libgstreamer_wsd_solution.h" 
--- a/gstreamer_core/tsrc/check/gst/gstparamspecs/src/gstparamspecs.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstparamspecs/src/gstparamspecs.c	Fri Apr 16 15:15:52 2010 +0300
@@ -26,11 +26,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstpipeline/src/gstpipeline.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstpipeline/src/gstpipeline.c	Fri Apr 16 15:15:52 2010 +0300
@@ -28,11 +28,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstplugin/src/gstplugin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstplugin/src/gstplugin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -45,11 +45,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstpoll/src/gstpoll.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstpoll/src/gstpoll.c	Fri Apr 16 15:15:52 2010 +0300
@@ -113,11 +113,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 /*
  //------------------Dropped due to Scket Pair-----------------------
--- a/gstreamer_core/tsrc/check/gst/gstquery/src/gstquery.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstquery/src/gstquery.c	Fri Apr 16 15:15:52 2010 +0300
@@ -49,11 +49,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstregistry/src/gstregistry.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstregistry/src/gstregistry.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,11 +31,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/gst/gstsegment/src/gstsegment.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstsegment/src/gstsegment.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,24 +1,15 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
+ /*
+ *  Copyright © 2008 Nokia Corporation.
+ *  This material, including documentation and any related 
+ *  computer programs, is protected by copyright controlled by 
+ *  Nokia Corporation. All rights are reserved. Copying, 
+ *  including reproducing, storing, adapting or translating, any 
+ *  or all of this material requires the prior written consent of 
+ *  Nokia Corporation. This material also contains confidential 
+ *  information which may not be disclosed to others without the 
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
  
 /* GStreamer
  * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
@@ -70,11 +61,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void segment_seek_nosize()
@@ -1595,7 +1595,7 @@
   /* accumulated 100 of previous segment to make 200 */
   fail_unless (segment.accum == 200);
   
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.last_stop == 200);
   
   fail_unless (segment.duration == -1);
   
@@ -1651,7 +1651,7 @@
   
   fail_unless (segment.accum == 400);
   
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.last_stop == 200);
   
   fail_unless (segment.duration == -1);
   
@@ -1944,7 +1944,7 @@
   
   fail_unless (segment.accum == 0);
   
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.last_stop == 200);
   
   fail_unless (segment.duration == -1);
   
@@ -1982,7 +1982,7 @@
   
   fail_unless (segment.accum == 50);
   
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.last_stop == 150);
   
   fail_unless (segment.duration == -1);
   
@@ -2016,7 +2016,7 @@
   
   fail_unless (segment.accum == 50);
   
-  fail_unless (segment.last_stop == 100);
+  fail_unless (segment.last_stop == 150);
   
   fail_unless (segment.duration == -1);
   
@@ -2067,7 +2067,7 @@
   
   fail_unless (segment.accum == 0);
   
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.last_stop == 200);
   
   fail_unless (segment.duration == -1);
   
@@ -2105,7 +2105,7 @@
   
   fail_unless (segment.accum == 0);
   
-  fail_unless (segment.last_stop == 150);
+  fail_unless (segment.last_stop == 200);
   
   fail_unless (segment.duration == -1);
   
--- a/gstreamer_core/tsrc/check/gst/gststructure/src/gststructure.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gststructure/src/gststructure.c	Fri Apr 16 15:15:52 2010 +0300
@@ -87,11 +87,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -444,43 +453,229 @@
   gchar *str;
 	xmlfile = "gststructure_test_structure_nested";
 	std_log(LOG_FILENAME_LINE, "Test Started test_structure_nested");
-  sc1 =
-      gst_structure_new ("Camera", "XResolution", G_TYPE_INT, 72, "YResolution",
-      G_TYPE_INT, 73, NULL);
-  fail_unless (sc1 != NULL);
+	  sc1 = gst_structure_new ("Camera",
+	      "XResolution", G_TYPE_INT, 72, "YResolution", G_TYPE_INT, 73, NULL);
+	  fail_unless (sc1 != NULL);
+
+	  sc2 = gst_structure_new ("Image-Data",
+	      "Orientation", G_TYPE_STRING, "top-left",
+	      "Comment", G_TYPE_STRING, "super photo", NULL);
+	  fail_unless (sc2 != NULL);
 
-  sc2 =
-      gst_structure_new ("Image-Data", "Orientation", G_TYPE_STRING, "top-left",
-      NULL);
-  fail_unless (sc2 != NULL);
+	  sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1,
+	      "Image Data", GST_TYPE_STRUCTURE, sc2, NULL);
+	  fail_unless (sp != NULL);
 
-  sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1,
-      "Image Data", GST_TYPE_STRUCTURE, sc2, NULL);
-  fail_unless (sp != NULL);
+	  fail_unless (gst_structure_n_fields (sp) == 2);
+
+	  fail_unless (gst_structure_has_field_typed (sp, "Camera",
+	          GST_TYPE_STRUCTURE));
 
-  fail_unless (gst_structure_has_field_typed (sp, "Camera",
-          GST_TYPE_STRUCTURE));
+	  str = gst_structure_to_string (sp);
+	  fail_unless (str != NULL);
 
-  str = gst_structure_to_string (sp);
-  fail_unless (str != NULL);
+	  GST_DEBUG ("serialized to '%s'", str);
 
-  fail_unless (g_str_equal (str,
-          "Exif"
-          ", Camera=(GstStructure)Camera, XResolution=(int)72, YResolution=(int)73;"
-          ", Image Data=(GstStructure)Image-Data, Orientation=(string)top-left;;"));
+	  fail_unless (g_str_equal (str,
+	          "Exif"
+	          ", Camera=(GstStructure)\"Camera\\,\\ XResolution\\=\\(int\\)72\\,\\ YResolution\\=\\(int\\)73\\;\""
+	          ", Image Data=(GstStructure)\"Image-Data\\,\\ Orientation\\=\\(string\\)top-left\\,\\ Comment\\=\\(string\\)\\\"super\\\\\\ photo\\\"\\;\";"));
 
-  g_free (str);
-  str = NULL;
+	  g_free (str);
+	  str = NULL;
 
-  gst_structure_free (sc1);
-  gst_structure_free (sc2);
-  gst_structure_free (sp);
+	  gst_structure_free (sc1);
+	  gst_structure_free (sc2);
+	  gst_structure_free (sp);
+	  
 	std_log(LOG_FILENAME_LINE, "Test Successful");
 	create_xml(0);
 }
 
+void test_string_properties()
+{
+  GstCaps *caps1, *caps2;
+  GstStructure *st1, *st2;
+  gchar *str, *res1, *res2;
+
+  xmlfile = "test_string_properties";
+    std_log(LOG_FILENAME_LINE, "Test Started test_string_properties");
+  /* test escaping/unescaping */
+  st1 = gst_structure_new ("RandomStructure", "prop1", G_TYPE_STRING, "foo",
+      "prop2", G_TYPE_STRING, "", "prop3", G_TYPE_STRING, NULL,
+      "prop4", G_TYPE_STRING, "NULL", NULL);
+  str = gst_structure_to_string (st1);
+  st2 = gst_structure_from_string (str, NULL);
+  g_free (str);
+
+  fail_unless (st2 != NULL);
+
+  /* need to put stuctures into caps to compare */
+  caps1 = gst_caps_new_empty ();
+  gst_caps_append_structure (caps1, st1);
+  caps2 = gst_caps_new_empty ();
+  gst_caps_append_structure (caps2, st2);
+  res1 = gst_caps_to_string (caps1);
+  res2 = gst_caps_to_string (caps2);
+  fail_unless (gst_caps_is_equal (caps1, caps2),
+      "Structures did not match:\n\tStructure 1: %s\n\tStructure 2: %s\n",
+      res1, res2);
+  gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
+  g_free (res1);
+  g_free (res2);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
+}
+
+void test_structure_nested_from_and_to_string()
+{
+  GstStructure *s;
+  gchar *str1, *str2, *end = NULL;
+
+  xmlfile = "test_structure_nested_from_and_to_string";
+    std_log(LOG_FILENAME_LINE, "Test Started test_structure_nested_from_and_to_string");
+    
+    str1 = "main"
+          ", main-sub1=(GstStructure)\"type-b\\,\\ machine-type\\=\\(int\\)0\\;\""
+          ", main-sub2=(GstStructure)\"type-a\\,\\ plugin-filename\\=\\(string\\)\\\"/home/user/lib/lib\\\\\\ with\\\\\\ spaces.dll\\\"\\,\\ machine-type\\=\\(int\\)1\\;\""
+          ";";
+//      ", main-sub3=(GstStructure)\"type-b\\,\\ plugin-filename\\=\\(string\\)\\home\\user\\lib\\lib_no_spaces.so\\,\\ machine-type\\=\\(int\\)1\\;\""
+//      ";";
+
+  s = gst_structure_from_string (str1, &end);
+  fail_unless (s != NULL);
+
+  GST_DEBUG ("not parsed part : %s", end);
+  fail_unless (*end == '\0');
+
+  fail_unless (gst_structure_n_fields (s) == 2);
+
+  fail_unless (gst_structure_has_field_typed (s, "main-sub1",
+          GST_TYPE_STRUCTURE));
+
+  str2 = gst_structure_to_string (s);
+  fail_unless (str2 != NULL);
+
+  fail_unless (g_str_equal (str1, str2));
+
+  g_free (str2);
+
+  gst_structure_free (s);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
+}
+
+
+void test_vararg_getters()
+{
+  GstStructure *s;
+  GstBuffer *buf, *buf2;
+  gboolean ret;
+  GstCaps *caps, *caps2;
+  gdouble d;
+  gint64 i64;
+  gchar *c;
+  gint i, num, denom;
+
+  xmlfile = "test_vararg_getters";
+    std_log(LOG_FILENAME_LINE, "Test Started test_vararg_getters");
+  
+  buf = gst_buffer_new_and_alloc (3);
+  GST_BUFFER_DATA (buf)[0] = 0xf0;
+  GST_BUFFER_DATA (buf)[1] = 0x66;
+  GST_BUFFER_DATA (buf)[2] = 0x0d;
+
+  caps = gst_caps_new_simple ("video/x-foo", NULL);
+
+  s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string",
+      G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps",
+      GST_TYPE_CAPS, caps, "int64", G_TYPE_INT64, G_GINT64_CONSTANT (-99),
+      "double", G_TYPE_DOUBLE, G_MAXDOUBLE, "frag", GST_TYPE_FRACTION, 39, 14,
+      NULL);
+
+  /* first the plain one */
+  ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, &d, "string",
+      G_TYPE_STRING, &c, "caps", GST_TYPE_CAPS, &caps2, "buf",
+      GST_TYPE_BUFFER, &buf2, "frag", GST_TYPE_FRACTION, &num, &denom, "int",
+      G_TYPE_INT, &i, "int64", G_TYPE_INT64, &i64, NULL);
+
+  fail_unless (ret);
+  fail_unless_equals_string (c, "Hello World!");
+  fail_unless_equals_int (i, 12345678);
+  fail_unless_equals_float (d, G_MAXDOUBLE);
+  fail_unless_equals_int (num, 39);
+  fail_unless_equals_int (denom, 14);
+  fail_unless (i64 == -99);
+  fail_unless (caps == caps2);
+  fail_unless (buf == buf2);
+
+  /* expected failures */
+  ASSERT_CRITICAL (gst_structure_get (s, NULL, G_TYPE_INT, &i, NULL));
+  fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "double",
+          G_TYPE_FLOAT, &d, NULL));
+  fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "dooble",
+          G_TYPE_DOUBLE, &d, NULL));
+
+  g_free (c);
+  c = NULL;
+  gst_caps_unref (caps2);
+  caps2 = NULL;
+  gst_buffer_unref (buf2);
+  buf2 = NULL;
+
+  /* and now the _id variant */
+  ret = gst_structure_id_get (s, g_quark_from_static_string ("double"),
+      G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING,
+      &c, g_quark_from_static_string ("caps"), GST_TYPE_CAPS, &caps2,
+      g_quark_from_static_string ("buf"), GST_TYPE_BUFFER, &buf2,
+      g_quark_from_static_string ("int"), G_TYPE_INT, &i,
+      g_quark_from_static_string ("int64"), G_TYPE_INT64, &i64, NULL);
+
+  fail_unless (ret);
+  fail_unless_equals_string (c, "Hello World!");
+  fail_unless_equals_int (i, 12345678);
+  fail_unless_equals_float (d, G_MAXDOUBLE);
+  fail_unless (i64 == -99);
+  fail_unless (caps == caps2);
+  fail_unless (buf == buf2);
+
+  /* expected failures */
+  ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL));
+  fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
+          G_TYPE_INT, &i, g_quark_from_static_string ("double"), G_TYPE_FLOAT,
+          &d, NULL));
+  fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
+          G_TYPE_INT, &i, g_quark_from_static_string ("dooble"), G_TYPE_DOUBLE,
+          &d, NULL));
+
+  g_free (c);
+  gst_caps_unref (caps2);
+  gst_buffer_unref (buf2);
+
+  /* finally make sure NULL as return location is handled gracefully */
+  ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string",
+      G_TYPE_STRING, NULL, "caps", GST_TYPE_CAPS, NULL, "buf",
+      GST_TYPE_BUFFER, NULL, "int", G_TYPE_INT, &i, "frag", GST_TYPE_FRACTION,
+      NULL, NULL, "int64", G_TYPE_INT64, &i64, NULL);
+
+  ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL,
+          &denom, NULL));
+  ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num,
+          NULL, NULL));
+
+  /* clean up */
+  gst_caps_unref (caps);
+  gst_buffer_unref (buf);
+  gst_structure_free (s);
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+    create_xml(0);
+}
 #if 1
-void (*fn[9]) (void) = {
+void (*fn[]) (void) = {
 	  		test_from_string_int,
 	  		test_from_string,
 				test_to_string,
@@ -489,7 +684,10 @@
 				test_structure_new,
 				test_fixate,
 				test_fixate_frac_list,
-				test_structure_nested
+				test_structure_nested,
+				test_string_properties,
+				test_structure_nested_from_and_to_string,
+				test_vararg_getters
 };
 
 char *args[] = {
@@ -501,7 +699,10 @@
 				"test_structure_new",
 				"test_fixate",
 				"test_fixate_frac_list",
-				"test_structure_nested"
+				"test_structure_nested",
+				"test_string_properties",
+				"test_structure_nested_from_and_to_string",
+				"test_vararg_getters"
 				
 };
 
@@ -511,25 +712,25 @@
 #endif
 
 
-#if 0
-int main()
-{
-    
-    
-	gst_check_init (NULL, NULL);
-	test_from_string_int();
-	test_from_string();
-	test_to_string();
-	test_to_from_string();
-	test_complete_structure();
-	test_structure_new();
-	test_fixate();
-	test_fixate_frac_list();
-	test_structure_nested();
-
-
-}
-#endif
+//#if 0
+//int main()
+//{
+//    
+//    
+//	gst_check_init (NULL, NULL);
+//	test_from_string_int();
+//	test_from_string();
+//	test_to_string();
+//	test_to_from_string();
+//	test_complete_structure();
+//	test_structure_new();
+//	test_fixate();
+//	test_fixate_frac_list();
+//	test_structure_nested();
+//
+//
+//}
+//#endif
 
 
 
--- a/gstreamer_core/tsrc/check/gst/gstsystemclock/src/gstsystemclock.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstsystemclock/src/gstsystemclock.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,24 +1,15 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
+ /*
+ *  Copyright © 2008 Nokia Corporation.
+ *  This material, including documentation and any related 
+ *  computer programs, is protected by copyright controlled by 
+ *  Nokia Corporation. All rights are reserved. Copying, 
+ *  including reproducing, storing, adapting or translating, any 
+ *  or all of this material requires the prior written consent of 
+ *  Nokia Corporation. This material also contains confidential 
+ *  information which may not be disclosed to others without the 
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
 
 /* GStreamer
  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
@@ -53,11 +44,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -94,7 +94,7 @@
 }
 
 
-#define TIME_UNIT (GST_SECOND / 5)
+#define TIME_UNIT (GST_SECOND)
 static void
 gst_clock_debug (GstClock * clock)
 {
@@ -122,6 +122,7 @@
   return FALSE;
 }
 
+GMutex *store_lock;
 static gboolean
 store_callback (GstClock * clock, GstClockTime time,
     GstClockID id, gpointer user_data)
@@ -129,7 +130,9 @@
   GList **list = user_data;
 
   GST_DEBUG ("unlocked async id %p", id);
+  g_mutex_lock (store_lock);
   *list = g_list_append (*list, id);
+  g_mutex_unlock (store_lock);
   return FALSE;
 }
 
@@ -151,9 +154,12 @@
   GstClockID id, id2;
   GstClockTime base;
   GstClockReturn result;
+  GstClockTime        time_my;
+  int value;
   
 	xmlfile = "test_single_shot";
   std_log(LOG_FILENAME_LINE, "Test Started test_single_shot");
+  GST_DEBUG ("test_single_shot started ");
 
   clock = gst_system_clock_obtain ();
   fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
@@ -184,15 +190,16 @@
       
   gst_clock_id_unref (id);
 
-  id = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
+    id = gst_clock_new_single_shot_id (clock, base + (2 * TIME_UNIT));
   GST_DEBUG ("waiting one second async id %p", id);
   result = gst_clock_id_wait_async (id, ok_callback, NULL);
-  gst_clock_id_unref (id);
   fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
   
   g_usleep (TIME_UNIT / (2 * 1000));
+    gst_clock_id_unschedule (id);
+    gst_clock_id_unref (id);
 
-  id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
+    id = gst_clock_new_single_shot_id (clock, base + (5 * TIME_UNIT));
   GST_DEBUG ("waiting one second async, with cancel on id %p", id);
   result = gst_clock_id_wait_async (id, error_callback, NULL);
   fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
@@ -204,13 +211,12 @@
   GST_DEBUG ("canceled id %p", id);
 
   GST_DEBUG ("waiting multiple one second async, with cancel");
-  id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
-  id2 = gst_clock_new_single_shot_id (clock, base + 6 * TIME_UNIT);
+    id = gst_clock_new_single_shot_id (clock, base + (5 * TIME_UNIT));
+    id2 = gst_clock_new_single_shot_id (clock, base + (6 * TIME_UNIT));
   GST_DEBUG ("waiting id %p", id);
   result = gst_clock_id_wait_async (id, ok_callback, NULL);
   fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
   
-  gst_clock_id_unref (id);
   GST_DEBUG ("waiting id %p", id2);
   result = gst_clock_id_wait_async (id2, error_callback, NULL);
   fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
@@ -220,8 +226,13 @@
   gst_clock_id_unschedule (id2);
   GST_DEBUG ("canceled id %p", id2);
   gst_clock_id_unref (id2);
-  g_usleep (TIME_UNIT / (2 * 1000));
+    g_usleep (TIME_UNIT / 1000 * 5);
+    fail_unless (((GstClockEntry *) id)->status == GST_CLOCK_OK,
+        "Waiting did not finish");
+    gst_clock_id_unref (id);
   
+    gst_object_unref (clock);
+  GST_DEBUG ("test_single_shot finished ");
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0);
 }
@@ -317,6 +328,7 @@
   std_log(LOG_FILENAME_LINE, "Test Started test_async_order");
   
   
+  store_lock = g_mutex_new ();
   clock = gst_system_clock_obtain ();
   fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
   
@@ -335,21 +347,26 @@
   
   g_usleep (TIME_UNIT / 1000);
   // at this point at least one of the timers should have timed out 
+    g_mutex_lock (store_lock);
   fail_unless (cb_list != NULL, "expected notification");
   
   fail_unless (cb_list->data == id2,
       "Expected notification for id2 to come first");
-      
+    g_mutex_unlock (store_lock);
   g_usleep (TIME_UNIT / 1000);
+    g_mutex_lock (store_lock);
   // now both should have timed out 
   next = g_list_next (cb_list);
   fail_unless (next != NULL, "expected second notification");
   
   fail_unless (next->data == id1, "Missing notification for id1");
+    g_mutex_unlock (store_lock);
   
   gst_clock_id_unref (id1);
   gst_clock_id_unref (id2);
   g_list_free (cb_list);
+    gst_object_unref (clock);
+    g_mutex_free (store_lock);
   
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0);
@@ -455,7 +472,7 @@
   xmlfile = "test_mixed";
   std_log(LOG_FILENAME_LINE, "Test Started test_mixed");
 
-
+  GST_DEBUG ("test_mixed started ");
   info.clock = gst_system_clock_obtain ();
   fail_unless (info.clock != NULL,
       "Could not create instance of GstSystemClock");
@@ -495,6 +512,7 @@
   gst_object_unref (info.clock);
   
   std_log(LOG_FILENAME_LINE, "Test Successful");
+  GST_DEBUG ("test_mixed finished ");
   create_xml(0);
   
 }
@@ -542,8 +560,89 @@
   
 } 
 
-
-
+struct test_async_sync_interaction_data
+{
+  GMutex *lock;
+  GstClockID sync_id;
+  GstClockID sync_id2;
+  GstClockID async_id;
+  GstClockID async_id2;
+  GstClockID async_id3;
+};
+static gboolean
+test_async_sync_interaction_cb (GstClock * clock, GstClockTime time,
+    GstClockID id, gpointer user_data)
+{
+  struct test_async_sync_interaction_data *td =
+      (struct test_async_sync_interaction_data *) (user_data);
+  g_mutex_lock (td->lock);
+  if (id == td->async_id)
+    goto out;
+  if (id != td->async_id2 && id != td->async_id3)
+    goto out;
+  if (id == td->async_id3) {
+    gst_clock_id_unschedule (td->sync_id);
+    gst_clock_id_unschedule (td->async_id2);
+  }
+out:
+  g_mutex_unlock (td->lock);
+  return FALSE;
+}
+void test_async_sync_interaction()
+{
+  GstClock *clock;
+  GstClockReturn result;
+  GstClockTime base;
+  GstClockTimeDiff jitter;
+  struct test_async_sync_interaction_data td;
+  int i;
+  xmlfile = "test_async_sync_interaction";
+std_log(LOG_FILENAME_LINE, "Test Started test_async_sync_interaction");
+    clock = gst_system_clock_obtain ();
+     fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
+     td.lock = g_mutex_new ();
+     for (i = 0; i < 50; i++) {
+       gst_clock_debug (clock);
+       base = gst_clock_get_time (clock);
+       g_mutex_lock (td.lock);
+       td.async_id = gst_clock_new_single_shot_id (clock, base + 40 * GST_MSECOND);
+       td.async_id2 =
+           gst_clock_new_single_shot_id (clock, base + 30 * GST_MSECOND);
+       td.async_id3 =
+           gst_clock_new_single_shot_id (clock, base + 20 * GST_MSECOND);
+       td.sync_id2 = gst_clock_new_single_shot_id (clock, base + 10 * GST_MSECOND);
+       td.sync_id = gst_clock_new_single_shot_id (clock, base + 50 * GST_MSECOND);
+       g_mutex_unlock (td.lock);
+       result = gst_clock_id_wait_async (td.async_id,
+           test_async_sync_interaction_cb, &td);
+       fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
+       result = gst_clock_id_wait (td.sync_id2, &jitter);
+       fail_unless (result == GST_CLOCK_OK || result == GST_CLOCK_EARLY,
+           "Waiting did not return OK or EARLY");
+       result = gst_clock_id_wait_async (td.async_id2,
+           test_async_sync_interaction_cb, &td);
+       fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
+       gst_clock_id_unschedule (td.async_id);
+       result = gst_clock_id_wait_async (td.async_id3,
+           test_async_sync_interaction_cb, &td);
+       fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
+       result = gst_clock_id_wait (td.sync_id, &jitter);
+       fail_unless (result == GST_CLOCK_UNSCHEDULED || result == GST_CLOCK_EARLY,
+           "Waiting did not return UNSCHEDULED");
+       gst_clock_id_unschedule (td.async_id3);
+       g_mutex_lock (td.lock);
+       gst_clock_id_unref (td.sync_id);
+       gst_clock_id_unref (td.sync_id2);
+       gst_clock_id_unref (td.async_id);
+       gst_clock_id_unref (td.async_id2);
+       gst_clock_id_unref (td.async_id3);
+       g_mutex_unlock (td.lock);
+     }
+     g_mutex_free (td.lock);
+     gst_object_unref (clock);
+     std_log(LOG_FILENAME_LINE, "Test Successful");
+     create_xml(0);
+   }
 /*void main(int argc,char** argv)
 {
         gst_init(&argc,&argv);
@@ -560,7 +659,7 @@
 }*/
 
 
-void (*fn[8]) (void) = {
+void (*fn[]) (void) = {
         test_range,
         test_diff,
         test_signedness,
@@ -568,7 +667,8 @@
         test_periodic_shot,
         test_periodic_multi,
         test_async_order,
-        test_mixed
+        test_mixed,
+        test_async_sync_interaction
 };
 
 char *args[] = {
@@ -580,6 +680,7 @@
         "test_periodic_multi",
         "test_async_order",
         "test_mixed",
+        "test_async_sync_interaction"
 };
 
 GST_CHECK_MAIN (gst_systemclock);
--- a/gstreamer_core/tsrc/check/gst/gsttag/src/gsttag.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gsttag/src/gsttag.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,11 +29,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 //gboolean _gst_check_debug = FALSE;
--- a/gstreamer_core/tsrc/check/gst/gsttagsetter/src/gsttagsetter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gsttagsetter/src/gsttagsetter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,11 +29,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /* some minimal GstTagSetter object */
--- a/gstreamer_core/tsrc/check/gst/gsttask/src/gsttask.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gsttask/src/gsttask.c	Fri Apr 16 15:15:52 2010 +0300
@@ -112,12 +112,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 static GMutex *task_lock ;
 static GCond  *task_cond ;
 
--- a/gstreamer_core/tsrc/check/gst/gsturi/src/gsturi.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gsturi/src/gsturi.c	Fri Apr 16 15:15:52 2010 +0300
@@ -31,11 +31,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_protocol_case()
@@ -46,14 +55,14 @@
   xmlfile = "gsturi_test_protocol_case";
   std_log(LOG_FILENAME_LINE, "Test Started gsturi_test_protocol_case");
 
-  element = gst_element_make_from_uri (GST_URI_SRC, "file://c:\\data\\gstreamer\\warning.wav", NULL);
+  element = gst_element_make_from_uri (GST_URI_SRC, "file:///foo/bar", NULL);
 
   /* no element? probably no registry, bail out */
   if (element == NULL)
     return;
 
   gst_object_unref (element);
-  element = gst_element_make_from_uri (GST_URI_SRC, "FILE://c:\\data\\gstreamer\\warning.wav", NULL);
+  element = gst_element_make_from_uri (GST_URI_SRC, "FILE:///foo/bar", NULL);
   fail_unless (element != NULL,
       "Got source for 'file://' URI but not for 'FILE://' URI");
   gst_object_unref (element);
--- a/gstreamer_core/tsrc/check/gst/gstutils/src/gstutils.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstutils/src/gstutils.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,11 +35,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #define SPECIAL_POINTER(x) ((void*)(19283847+(x)))
@@ -132,16 +141,16 @@
   gst_object_unref (bus);
 
   g_assert (n_buffer_probes == 10);     /* one for every buffer */
-  g_assert (n_event_probes == 2);       /* new segment and eos */
-  g_assert (n_data_probes == 12);       /* duh */
+  g_assert (n_event_probes == 3);       /* new segment, latency and eos */
+  g_assert (n_data_probes == 13);       /* duh */
 
   gst_element_set_state (pipeline, GST_STATE_NULL);
   gst_object_unref (pipeline);
 
   /* make sure nothing was sent in addition to the above when shutting down */
   g_assert (n_buffer_probes == 10);     /* one for every buffer */
-  g_assert (n_event_probes == 2);       /* new segment and eos */
-  g_assert (n_data_probes == 12);       /* duh */
+  g_assert (n_event_probes == 3);       /* new segment, latency and eos */
+  g_assert (n_data_probes == 13);       /* duh */
   
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0);
--- a/gstreamer_core/tsrc/check/gst/gstvalue/src/gstvalue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/gst/gstvalue/src/gstvalue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -1,24 +1,15 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
+ /*
+ *  Copyright © 2008 Nokia Corporation.
+ *  This material, including documentation and any related 
+ *  computer programs, is protected by copyright controlled by 
+ *  Nokia Corporation. All rights are reserved. Copying, 
+ *  including reproducing, storing, adapting or translating, any 
+ *  or all of this material requires the prior written consent of 
+ *  Nokia Corporation. This material also contains confidential 
+ *  information which may not be disclosed to others without the 
+ *  prior written consent of Nokia Corporation.
+ * ============================================================================
+ */
 
 /* GStreamer
  * Copyright (C) <2004> David Schleef <david at schleef dot org>
@@ -55,11 +46,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/libs/adapter/src/adapter.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/adapter/src/adapter.c	Fri Apr 16 15:15:52 2010 +0300
@@ -35,11 +35,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /* does some implementation dependent checking that should 
--- a/gstreamer_core/tsrc/check/libs/basesrc/src/basesrc.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/basesrc/src/basesrc.c	Fri Apr 16 15:15:52 2010 +0300
@@ -39,11 +39,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static gboolean
--- a/gstreamer_core/tsrc/check/libs/collectpads/src/collectpads.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/collectpads/src/collectpads.c	Fri Apr 16 15:15:52 2010 +0300
@@ -110,11 +110,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #define fail_unless_collected(expected)           \
--- a/gstreamer_core/tsrc/check/libs/controller/src/controller.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/controller/src/controller.c	Fri Apr 16 15:15:52 2010 +0300
@@ -112,11 +112,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/libs/gdp/src/gdp.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/gdp/src/gdp.c	Fri Apr 16 15:15:52 2010 +0300
@@ -114,11 +114,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/check/libs/gstnetclientclock/src/gstnetclientclock.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/gstnetclientclock/src/gstnetclientclock.c	Fri Apr 16 15:15:52 2010 +0300
@@ -103,11 +103,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_instantiation()
@@ -209,12 +218,12 @@
 
 
 
-void
-gst_net_client_clock_suite (void)
-{
-test_instantiation();
-test_functioning();
-}
+//void
+//gst_net_client_clock_suite (void)
+//{
+//test_instantiation();
+//test_functioning();
+//}
 
 void (*fn[]) (void) = {
 test_instantiation,
--- a/gstreamer_core/tsrc/check/libs/gstnettimeprovider/src/gstnettimeprovider.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/gstnettimeprovider/src/gstnettimeprovider.c	Fri Apr 16 15:15:52 2010 +0300
@@ -105,11 +105,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_refcounts()
--- a/gstreamer_core/tsrc/check/libs/libsabi/src/libsabi.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/libsabi/src/libsabi.c	Fri Apr 16 15:15:52 2010 +0300
@@ -98,11 +98,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 void test_ABI()
--- a/gstreamer_core/tsrc/check/libs/typefindhelper/src/typefindhelper.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/libs/typefindhelper/src/typefindhelper.c	Fri Apr 16 15:15:52 2010 +0300
@@ -155,11 +155,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /* make sure the entire data in the buffer is available for peeking */
--- a/gstreamer_core/tsrc/check/pipelines/cleanup/src/cleanup.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/pipelines/cleanup/src/cleanup.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,11 +29,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /*
@@ -155,7 +164,7 @@
 
   run_pipeline (pipeline, s,
       GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
-      GST_MESSAGE_ASYNC_DONE, GST_MESSAGE_EOS);
+      GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE, GST_MESSAGE_EOS);
   while (GST_OBJECT_REFCOUNT_VALUE (src) > 1)
     THREAD_SWITCH ();
   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
--- a/gstreamer_core/tsrc/check/pipelines/core-simple-launch-lines/src/core-simple-launch-lines.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/pipelines/core-simple-launch-lines/src/core-simple-launch-lines.c	Fri Apr 16 15:15:52 2010 +0300
@@ -30,11 +30,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -103,10 +112,13 @@
   bus = gst_element_get_bus (pipeline);
   fail_if (bus == NULL);
 
+  GST_DEBUG ("running pipeline %s", descr);
+  
   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
   ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
 
   if (ret != GST_STATE_CHANGE_SUCCESS) {
+    GST_WARNING ("have failed state change %d", ret);
     g_critical ("Couldn't set pipeline to PLAYING");
     goto done;
   }
@@ -141,7 +153,7 @@
   gst_object_unref (bus);
 }
 
-void test_2_elements()
+/*void test_2_elements()
 {
   gchar *s;
   GstElement *fakesrc, *fakesink, *pipeline;
@@ -222,10 +234,46 @@
             std_log(LOG_FILENAME_LINE, "Test Successful");
 					  create_xml(0);  
 
+}*/
+void test_2_elements()
+{
+  gchar *s;
+  GstElement *fakesrc, *fakesink, *pipeline;
+
+  xmlfile = "test_2_elements";
+  std_log(LOG_FILENAME_LINE, "Test Started test_2_elements");
+s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true";
+run_pipeline (setup_pipeline (s), s,
+    GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
+    GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE, GST_MESSAGE_UNKNOWN);
+
+s = "fakesrc can-activate-push=true ! fakesink can-activate-pull=false";
+run_pipeline (setup_pipeline (s), s,
+    GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
+    GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE, GST_MESSAGE_UNKNOWN);
+
+s = "fakesrc can-activate-push=false num-buffers=10 ! fakesink can-activate-pull=true";
+run_pipeline (setup_pipeline (s), s,
+    GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
+    GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE, GST_MESSAGE_EOS);
+
+s = "fakesrc can-activate-push=true num-buffers=10 ! fakesink can-activate-pull=false";
+run_pipeline (setup_pipeline (s), s,
+    GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
+    GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE, GST_MESSAGE_EOS);
+
+s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=false";
+ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
+        GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
+        GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE,
+        GST_MESSAGE_UNKNOWN));
+
+std_log(LOG_FILENAME_LINE, "Test Successful");
+                      create_xml(0);  
+
 }
 
 
-
 static void
 check_state_change_return (GstElement * pipeline, GstState state,
     GstStateChangeReturn immediate, GstStateChangeReturn final)
@@ -293,22 +341,18 @@
       
   //pipeline = gst_parse_launch (s, NULL);
   fail_unless (GST_IS_PIPELINE (pipeline));
-
-
-
-  check_state_change_return (pipeline, GST_STATE_READY,
-      GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
-  check_state_change_return (pipeline, GST_STATE_PAUSED,
-      GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
-  check_state_change_return (pipeline, GST_STATE_PLAYING,
-      GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
-  check_state_change_return (pipeline, GST_STATE_PAUSED,
-      GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
-  check_state_change_return (pipeline, GST_STATE_READY,
-      GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
-  check_state_change_return (pipeline, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS,
-      GST_STATE_CHANGE_SUCCESS);
-  gst_object_unref (pipeline);
+    check_state_change_return (pipeline, GST_STATE_READY,
+        GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
+    check_state_change_return (pipeline, GST_STATE_PAUSED,
+        GST_STATE_CHANGE_ASYNC, GST_STATE_CHANGE_SUCCESS);
+    check_state_change_return (pipeline, GST_STATE_PLAYING,
+        GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
+    /* can't check PAUSED, it's not deterministic */
+    check_state_change_return (pipeline, GST_STATE_READY,
+        GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS);
+    check_state_change_return (pipeline, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS,
+        GST_STATE_CHANGE_SUCCESS);
+    gst_object_unref (pipeline);
 
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0);
--- a/gstreamer_core/tsrc/check/pipelines/parse-disabled/src/parse-disabled.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/pipelines/parse-disabled/src/parse-disabled.c	Fri Apr 16 15:15:52 2010 +0300
@@ -30,11 +30,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/check/gstcheck.h>
--- a/gstreamer_core/tsrc/check/pipelines/parse-launch/src/parse-launch.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/pipelines/parse-launch/src/parse-launch.c	Fri Apr 16 15:15:52 2010 +0300
@@ -37,11 +37,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #define GST_TYPE_PARSE_TEST_ELEMENT (gst_parse_test_element_get_type())
@@ -568,6 +577,112 @@
   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 }
 
+void test_missing_elements()
+{
+  GstParseContext *ctx;
+  GstElement *element;
+  GError *err = NULL;
+  gchar **arr;
+
+  xmlfile = "test_missing_elements";
+    std_log(LOG_FILENAME_LINE, "Test Started test_missing_elements");
+  /* avoid misleading 'no such element' error debug messages when using cvs */
+  if (!g_getenv ("GST_DEBUG"))
+    gst_debug_set_default_threshold (GST_LEVEL_NONE);
+
+  /* one missing element */
+  ctx = gst_parse_context_new ();
+  element = gst_parse_launch_full ("fakesrc ! coffeesink", ctx,
+      GST_PARSE_FLAG_FATAL_ERRORS, &err);
+  fail_unless (err != NULL, "expected error");
+  fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
+  fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
+  arr = gst_parse_context_get_missing_elements (ctx);
+  fail_unless (arr != NULL, "expected missing elements");
+  fail_unless_equals_string (arr[0], "coffeesink");
+  fail_unless (arr[1] == NULL);
+  g_strfreev (arr);
+  gst_parse_context_free (ctx);
+  g_error_free (err);
+  err = NULL;
+
+  /* multiple missing elements */
+  ctx = gst_parse_context_new ();
+  element = gst_parse_launch_full ("fakesrc ! bogusenc ! identity ! goomux ! "
+      "fakesink", ctx, GST_PARSE_FLAG_FATAL_ERRORS, &err);
+  fail_unless (err != NULL, "expected error");
+  fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
+  fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
+  arr = gst_parse_context_get_missing_elements (ctx);
+  fail_unless (arr != NULL, "expected missing elements");
+  fail_unless_equals_string (arr[0], "bogusenc");
+  fail_unless_equals_string (arr[1], "goomux");
+  fail_unless (arr[2] == NULL);
+  g_strfreev (arr);
+  gst_parse_context_free (ctx);
+  g_error_free (err);
+  err = NULL;
+
+  /* multiple missing elements, different link pattern */
+  ctx = gst_parse_context_new ();
+  element = gst_parse_launch_full ("fakesrc ! bogusenc ! mux.sink "
+      "blahsrc ! goomux name=mux ! fakesink   fakesrc ! goosink", ctx,
+      GST_PARSE_FLAG_FATAL_ERRORS, &err);
+  fail_unless (err != NULL, "expected error");
+  fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
+  fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
+  arr = gst_parse_context_get_missing_elements (ctx);
+  fail_unless (arr != NULL, "expected missing elements");
+  fail_unless_equals_string (arr[0], "bogusenc");
+  fail_unless_equals_string (arr[1], "blahsrc");
+  fail_unless_equals_string (arr[2], "goomux");
+  fail_unless_equals_string (arr[3], "goosink");
+  fail_unless (arr[4] == NULL);
+  g_strfreev (arr);
+  gst_parse_context_free (ctx);
+  g_error_free (err);
+  err = NULL;
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+   create_xml(0);
+}
+
+
+void test_flags()
+{
+  GstElement *element;
+  GError *err = NULL;
+
+  xmlfile = "test_flags";
+    std_log(LOG_FILENAME_LINE, "Test Started test_flags");
+    
+  /* avoid misleading 'no such element' error debug messages when using cvs */
+  if (!g_getenv ("GST_DEBUG"))
+    gst_debug_set_default_threshold (GST_LEVEL_NONE);
+
+  /* default behaviour is to return any already constructed bins/elements */
+  element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, 0, &err);
+  fail_unless (err != NULL, "expected error");
+  fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
+  fail_unless (element != NULL, "expected partial pipeline/element");
+  g_error_free (err);
+  err = NULL;
+  gst_object_unref (element);
+
+  /* test GST_PARSE_FLAG_FATAL_ERRORS */
+  element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL,
+      GST_PARSE_FLAG_FATAL_ERRORS, &err);
+  fail_unless (err != NULL, "expected error");
+  fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
+  fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
+  g_error_free (err);
+  err = NULL;
+  
+  std_log(LOG_FILENAME_LINE, "Test Successful");
+   create_xml(0);
+}
+
+
 # if 0
 void
 parse_suite (void)
@@ -580,12 +695,14 @@
 }
 #endif
 
-void (*fn[5]) (void) = {
+void (*fn[]) (void) = {
 test_launch_lines,
 test_launch_lines2,
 expected_to_fail_pipes,
 leaking_fail_pipes,
-delayed_link
+delayed_link,
+test_missing_elements,
+test_flags
 };
 
 char *args[] = {
@@ -593,7 +710,9 @@
 "test_launch_lines2",
 "expected_to_fail_pipes",
 "leaking_fail_pipes",
-"delayed_link"
+"delayed_link",
+"test_missing_elements",
+"test_flags"
 };
 
 GST_CHECK_MAIN (parse-launch);
--- a/gstreamer_core/tsrc/check/pipelines/stress/src/stress.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/check/pipelines/stress/src/stress.c	Fri Apr 16 15:15:52 2010 +0300
@@ -25,11 +25,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/check/gstcheck.h>
--- a/gstreamer_core/tsrc/examples/adapter/src/adapter_test.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/adapter/src/adapter_test.c	Fri Apr 16 15:15:52 2010 +0300
@@ -39,11 +39,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static void
--- a/gstreamer_core/tsrc/examples/controller/src/audio-example.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/controller/src/audio-example.c	Fri Apr 16 15:15:52 2010 +0300
@@ -20,12 +20,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 gint
 main (gint argc, gchar ** argv)
 {
--- a/gstreamer_core/tsrc/examples/helloworld/src/helloworld.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/helloworld/src/helloworld.c	Fri Apr 16 15:15:52 2010 +0300
@@ -11,11 +11,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static void
@@ -76,44 +85,44 @@
   g_assert (bin);
 
   /* create a disk reader */
-  filesrc = gst_element_factory_make ("filesrc", "disk_source");
+  filesrc = gst_element_factory_make (/*"filesrc"*/"audiotestsrc", "disk_source");
   g_assert (filesrc);
   g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
 
   /* now it's time to get the decoder */
-  decoder = gst_element_factory_make ("mad", "decode");
-  if (!decoder) {
-    std_log(LOG_FILENAME_LINE, "could not find plugin mad");
-    g_print ("could not find plugin \"mad\"");
-    return -1;
-  }
+  //decoder = gst_element_factory_make ("mad", "decode");
+//  if (!decoder) {
+//    std_log(LOG_FILENAME_LINE, "could not find plugin mad");
+//    g_print ("could not find plugin \"mad\"");
+//    return -1;
+//  }
 
   /* also, we need to add some converters to make sure the audio stream
    * from the decoder is converted into a format the audio sink can
    * understand (if necessary) */
-  conv = gst_element_factory_make ("audioconvert", "audioconvert");
-  if (!conv) {
-    std_log(LOG_FILENAME_LINE, "could not create \"audioconvert\" element!");
-    g_print ("could not create \"audioconvert\" element!");
-    return -1;
-  }
-  resample = gst_element_factory_make ("audioresample", "audioresample");
-  if (!conv) {
-    std_log(LOG_FILENAME_LINE, "could not create \"audioresample\" element!");
-    g_print ("could not create \"audioresample\" element!");
-    return -1;
-  }
+//  conv = gst_element_factory_make ("audioconvert", "audioconvert");
+//  if (!conv) {
+//    std_log(LOG_FILENAME_LINE, "could not create \"audioconvert\" element!");
+//    g_print ("could not create \"audioconvert\" element!");
+//    return -1;
+//  }
+//  resample = gst_element_factory_make ("audioresample", "audioresample");
+//  if (!conv) {
+//    std_log(LOG_FILENAME_LINE, "could not create \"audioresample\" element!");
+//    g_print ("could not create \"audioresample\" element!");
+//    return -1;
+//  }
 
   /* and an audio sink */
   audiosink = gst_element_factory_make ("devsoundsink", "play_audio");
   g_assert (audiosink);
 
   /* add objects to the main pipeline */
-  gst_bin_add_many (GST_BIN (bin), filesrc, decoder, conv,
-      resample, audiosink, NULL);
+  gst_bin_add_many (GST_BIN (bin), filesrc/*, decoder, conv,
+      resample*/, audiosink, NULL);
 
   /* link the elements */
-  gst_element_link_many (filesrc, decoder, conv, resample, audiosink, NULL);
+  gst_element_link_many (filesrc, /*decoder, conv, resample,*/ audiosink, NULL);
 
   /* start playing */
   std_log(LOG_FILENAME_LINE, "START PLAYING");
Binary file gstreamer_core/tsrc/examples/launch/data/Crnival.mp3 has changed
--- a/gstreamer_core/tsrc/examples/launch/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/launch/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -23,7 +23,8 @@
 PRJ_PLATFORMS
 DEFAULT
 
-PRJ_EXPORTS
+PRJ_TESTEXPORTS
+../data/Crnival.mp3	/epoc32/winscw/c/data/gstreamer/Crnival.mp3
 										
 PRJ_TESTMMPFILES							
 launch.mmp
--- a/gstreamer_core/tsrc/examples/launch/src/launch.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/launch/src/launch.c	Fri Apr 16 15:15:52 2010 +0300
@@ -11,16 +11,28 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
-GstElement *pipeline, *source, *wavparse,*sink,*conv,*resample,*decoder;
+
+GstElement *pipeline, *source, *wavparse,*sink,*conv,*resample,*decoder,*audioconvert,*audioresample ;
 GstBus *bus;
 GMainLoop *loop;
 
+
+//audioconvert ! audioresample 
 static gboolean
 bus_call (GstBus     *bus,
           GstMessage *msg,
@@ -57,10 +69,10 @@
  {
    
    gst_element_set_state (pipeline, GST_STATE_PAUSED);
-   
-   if (!gst_element_link (wavparse, sink))
-      g_error ("link(wavparse, sink) failed!\n");
-    
+
+   if (!gst_element_link (wavparse, audioconvert))
+      g_error ("link(wavparse, audioconvert) failed!\n");
+
    gst_element_set_state (pipeline, GST_STATE_PLAYING);
  }
 
@@ -86,16 +98,25 @@
     source = gst_element_factory_make ("filesrc", "file-source");
     decoder = gst_element_factory_make ("wavparse", "wavparse-decoder");
     sink = gst_element_factory_make ("devsoundsink", "sink");
-        if (!pipeline || !source || !decoder) {
+    audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+    audioresample = gst_element_factory_make ("audioresample", "audioresample");    
+        if (!pipeline || !source || !decoder || !audioconvert || !audioresample) {
         g_print ("One element could not be created\n");
         return -1;
         }
     /* set filename property on the file source. Also add a message  handler. */
-    g_object_set (G_OBJECT (source), "location", argv[1], NULL);
+    g_object_set (G_OBJECT (source), "location", "c:\\data\\khuda1.wav", NULL);
             /* put all elements in a bin */
-    gst_bin_add_many (GST_BIN (pipeline),source, decoder,sink, NULL);
+    gst_bin_add_many (GST_BIN (pipeline),source, decoder,audioconvert,audioresample,sink, NULL);
             /* link together - note that we cannot link the parser and  decoder yet, because the parser uses dynamic pads. For that, we set a pad-added signal handler. */
     gst_element_link (source, decoder);
+   
+    if (!gst_element_link (audioconvert,audioresample))
+       g_error ("link(audioconvert,audioresample, sink) failed!\n");   
+    if (!gst_element_link (audioresample, sink))
+       g_error ("link(audioconvert,audioresample, sink) failed!\n"); 
+    
+    
     gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)), bus_call, loop);
     g_signal_connect (decoder, "pad-added", G_CALLBACK (new_pad_cb),pipeline);
             /* Now set to playing and iterate. */
--- a/gstreamer_core/tsrc/examples/launch/src/mp3parselaunch.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/launch/src/mp3parselaunch.c	Fri Apr 16 15:15:52 2010 +0300
@@ -11,11 +11,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 static void
--- a/gstreamer_core/tsrc/examples/manual/bin/src/bin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/bin/src/bin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -9,11 +9,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/gst.h>
@@ -40,7 +49,7 @@
   gst_bin_add_many (GST_BIN (bin), source, sink, NULL);
   gst_bin_add (GST_BIN (pipeline), bin);
   gst_element_link (source, sink);
-  getchar();
+  //getchar();
 /*** block b  from ../../../docs/manual/basics-bins.xml ***/
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0); 
--- a/gstreamer_core/tsrc/examples/manual/createelements/src/elementcreate.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/createelements/src/elementcreate.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,12 +13,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 int main (int   argc,
       char *argv[])
 {
@@ -33,7 +43,7 @@
   if (!element) {
    // g_print ("Failed to create element of type 'fakesrc'\n");
     std_log(LOG_FILENAME_LINE, "Failed to create element of type 'fakesrc'");
-    getchar();
+    //getchar();
     return -1;
   }
 
--- a/gstreamer_core/tsrc/examples/manual/elementfactory/src/elementfactory.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/elementfactory/src/elementfactory.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,12 +13,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 int
 main (int   argc,
       char *argv[])
--- a/gstreamer_core/tsrc/examples/manual/getelements/src/elementget.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/getelements/src/elementget.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,11 +13,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 #include <gst/gst.h>
 
--- a/gstreamer_core/tsrc/examples/manual/init/src/init.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/init/src/init.c	Fri Apr 16 15:15:52 2010 +0300
@@ -9,11 +9,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
@@ -41,7 +50,7 @@
   else
     nano_str = "";
 
-  getchar();
+  //getchar();
   std_log(LOG_FILENAME_LINE, "Test Successful");
   create_xml(0); 
 
--- a/gstreamer_core/tsrc/examples/manual/linkelements/src/elementlink.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/linkelements/src/elementlink.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,12 +13,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 int
 main (int   argc,
       char *argv[])
--- a/gstreamer_core/tsrc/examples/manual/makeelements/src/elementmake.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/makeelements/src/elementmake.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,12 +13,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 int
 main (int   argc,
       char *argv[])
--- a/gstreamer_core/tsrc/examples/manual/manual_decodebin/src/manual_decodebin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_decodebin/src/manual_decodebin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -9,11 +9,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/gst.h>
@@ -130,7 +139,7 @@
   audio = gst_bin_new ("audiobin");
   conv = gst_element_factory_make ("audioconvert", "aconv");
   audiopad = gst_element_get_pad (conv, "sink");
-  sink = gst_element_factory_make ("alsasink", "sink");
+  sink = gst_element_factory_make ("devsoundsink", "sink");
   gst_bin_add_many (GST_BIN (audio), conv, sink, NULL);
   gst_element_link (conv, sink);
   gst_element_add_pad (audio,
--- a/gstreamer_core/tsrc/examples/manual/manual_dynamic/src/manual_dynamic.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_dynamic/src/manual_dynamic.c	Fri Apr 16 15:15:52 2010 +0300
@@ -22,12 +22,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 static gboolean
 cb_feature_filter (GstPluginFeature *feature,
 		   gpointer          data)
--- a/gstreamer_core/tsrc/examples/manual/manual_ghostpad/src/manual_ghostpad.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_ghostpad/src/manual_ghostpad.c	Fri Apr 16 15:15:52 2010 +0300
@@ -11,11 +11,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 int
--- a/gstreamer_core/tsrc/examples/manual/manual_helloworld/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_helloworld/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -20,10 +20,8 @@
 *
 */
 
-PRJ_EXPORTS
-//warning.wav       /epoc32/winscw/c/data/gstreamer/warning.wav
-
-//khuda.wav       /epoc32/winscw/c/data/gstreamer/khuda.wav
+PRJ_TESTEXPORTS
+khuda.wav       /epoc32/winscw/c/data/gstreamer/khuda.wav
 
 PRJ_TESTMMPFILES
 
--- a/gstreamer_core/tsrc/examples/manual/manual_helloworld/src/manual_helloworld.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_helloworld/src/manual_helloworld.c	Fri Apr 16 15:15:52 2010 +0300
@@ -34,11 +34,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /*
--- a/gstreamer_core/tsrc/examples/manual/manual_playbin/src/manual_playbin.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_playbin/src/manual_playbin.c	Fri Apr 16 15:15:52 2010 +0300
@@ -9,11 +9,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 #include <gst/gst.h>
--- a/gstreamer_core/tsrc/examples/manual/manual_typefind/src/manual_typefind.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/manual_typefind/src/manual_typefind.c	Fri Apr 16 15:15:52 2010 +0300
@@ -13,11 +13,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /*** block b  from ../../../docs/manual/advanced-autoplugging.xml ***/
--- a/gstreamer_core/tsrc/examples/manual/pad/src/pad.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/pad/src/pad.c	Fri Apr 16 15:15:52 2010 +0300
@@ -9,11 +9,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 
--- a/gstreamer_core/tsrc/examples/manual/query/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/query/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -20,9 +20,8 @@
 *
 */
 
-PRJ_EXPORTS
-
-//khuda1.wav	/epoc32/winscw/c/data/gstreamer/khuda1.wav
+PRJ_TESTEXPORTS
+khuda1.wav	/epoc32/winscw/c/data/gstreamer/khuda1.wav
 
 PRJ_TESTMMPFILES
 
--- a/gstreamer_core/tsrc/examples/manual/query/src/query.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/manual/query/src/query.c	Fri Apr 16 15:15:52 2010 +0300
@@ -15,11 +15,20 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
 
 /*** block b  from ../../../docs/manual/advanced-position.xml ***/
--- a/gstreamer_core/tsrc/examples/metadata/src/read-metadata.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/metadata/src/read-metadata.c	Fri Apr 16 15:15:52 2010 +0300
@@ -48,12 +48,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 static gboolean
 message_loop (GstElement * element, GstTagList ** tags)
 {
--- a/gstreamer_core/tsrc/examples/queue/src/queue.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/queue/src/queue.c	Fri Apr 16 15:15:52 2010 +0300
@@ -18,12 +18,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 static void
 event_loop (GstElement * pipe)
 {
--- a/gstreamer_core/tsrc/examples/typefind/src/typefind.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/examples/typefind/src/typefind.c	Fri Apr 16 15:15:52 2010 +0300
@@ -29,12 +29,22 @@
 
 void create_xml(int result)
 {
+
     if(result)
+    {
         assert_failed = 1;
-    
+    } 
+
     testResultXml(xmlfile);
     close_log_file();
+
+    if(result)
+    {
+        exit (-1);
+    }    
+
 }
+
 static void
 type_found (GstElement * typefind, guint probability, const GstCaps * caps,
     gpointer user_data)
--- a/gstreamer_core/tsrc/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/tsrc/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -22,7 +22,10 @@
 
 #include "../check/group/bld.inf"
 #include "../examples/group/bld.inf"
-
+//#include "../gstreamertestcases/group/bld.inf"
+//#include "../gstreamertestcases_suite1/group/bld.inf"
+//#include "../gstreamertestcases_suite2/group/bld.inf"
+//#include "../gstreamertestcases_suite3/group/bld.inf"
 
 //  End of File
 										
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/group/custom/precase_custom.xml	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,11936 @@
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_async_state_change_empty" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstmessage.exe"/>
+	<param dst = "C:\sys\bin\gstmessage.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstmessage_test_parsing" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstmessage.exe"/>
+	<param parameters = "test_parsing"/>
+	<param result-file = "C:\LOGS\gstmessage_test_parsing.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstmessage_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstminiobject.exe"/>
+	<param dst = "C:\sys\bin\gstminiobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstminiobject_test_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstminiobject.exe"/>
+	<param parameters = "test_copy"/>
+	<param result-file = "C:\LOGS\gstminiobject_test_copy.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstminiobject_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_is_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstminiobject.exe"/>
+	<param dst = "C:\sys\bin\gstminiobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstminiobject_test_is_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstminiobject.exe"/>
+	<param parameters = "test_is_writable"/>
+	<param result-file = "C:\LOGS\gstminiobject_test_is_writable.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstminiobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_make_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstminiobject.exe"/>
+	<param dst = "C:\sys\bin\gstminiobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstminiobject_test_make_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstminiobject.exe"/>
+	<param parameters = "test_make_writable"/>
+	<param result-file = "C:\LOGS\gstminiobject_test_make_writable.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstminiobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ref_threaded" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstminiobject.exe"/>
+	<param dst = "C:\sys\bin\gstminiobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstminiobject_test_ref_threaded" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstminiobject.exe"/>
+	<param parameters = "test_ref_threaded"/>
+	<param result-file = "C:\LOGS\gstminiobject_test_ref_threaded.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstminiobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_unref_threaded" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstminiobject.exe"/>
+	<param dst = "C:\sys\bin\gstminiobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstminiobject_test_unref_threaded" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstminiobject.exe"/>
+	<param parameters = "test_unref_threaded"/>
+	<param result-file = "C:\LOGS\gstminiobject_test_unref_threaded.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstminiobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_collection" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstminiobject.exe"/>
+	<param dst = "C:\sys\bin\gstminiobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstminiobject_test_value_collection" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstminiobject.exe"/>
+	<param parameters = "test_value_collection"/>
+	<param result-file = "C:\LOGS\gstminiobject_test_value_collection.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstminiobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_hammer_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_hammer_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_hammer_bus"/>
+	<param result-file = "C:\LOGS\gstbus_test_hammer_bus.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_watch" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_watch" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_watch"/>
+	<param result-file = "C:\LOGS\gstbus_test_watch.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_watch_with_poll" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_watch_with_poll" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_watch_with_poll"/>
+	<param result-file = "C:\LOGS\gstbus_test_watch_with_poll.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_timed_pop" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_timed_pop" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_timed_pop"/>
+	<param result-file = "C:\LOGS\gstbus_test_timed_pop.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_timed_pop_thread" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_timed_pop_thread" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_timed_pop_thread"/>
+	<param result-file = "C:\LOGS\gstbus_test_timed_pop_thread.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_timed_pop_filtered" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_timed_pop_filtered" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_timed_pop_filtered"/>
+	<param result-file = "C:\LOGS\gstbus_test_timed_pop_filtered.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_timed_pop_filtered_with_timeout" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbus.exe"/>
+	<param dst = "C:\sys\bin\gstbus.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbus_test_timed_pop_filtered_with_timeout" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbus.exe"/>
+	<param parameters = "test_timed_pop_filtered_with_timeout"/>
+	<param result-file = "C:\LOGS\gstbus_test_timed_pop_filtered_with_timeout.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstbus_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_caps"/>
+	<param result-file = "C:\LOGS\test_caps.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_subbuffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_subbuffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_subbuffer"/>
+	<param result-file = "C:\LOGS\test_subbuffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_subbuffer_make_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_subbuffer_make_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_subbuffer_make_writable"/>
+	<param result-file = "C:\LOGS\test_subbuffer_make_writable.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_make_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_make_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_make_writable"/>
+	<param result-file = "C:\LOGS\test_make_writable.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_is_span_fast" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_is_span_fast" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_is_span_fast"/>
+	<param result-file = "C:\LOGS\test_is_span_fast.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_span" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_span" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_span"/>
+	<param result-file = "C:\LOGS\test_span.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_metadata_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_metadata_writable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_metadata_writable"/>
+	<param result-file = "C:\LOGS\test_metadata_writable.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_copy"/>
+	<param result-file = "C:\LOGS\test_copy.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_try_new_and_alloc" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbuffer_test_try_new_and_alloc" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbuffer.exe"/>
+	<param parameters = "test_try_new_and_alloc"/>
+	<param result-file = "C:\LOGS\test_try_new_and_alloc.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbuffer_logs.txt"/>
+   </params>
+</step>
+<step id="66.67.1.3.2" name="Install khuda.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="khuda.wav"/>
+     <param dst="C:\data\khuda.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_link"/>
+	<param result-file = "C:\LOGS\test_link.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_refcount" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_refcount" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_refcount"/>
+	<param result-file = "C:\LOGS\test_refcount.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_get_allowed_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_get_allowed_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_get_allowed_caps"/>
+	<param result-file = "C:\LOGS\test_get_allowed_caps.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_link_unlink_threaded" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_link_unlink_threaded" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_link_unlink_threaded"/>
+	<param result-file = "C:\LOGS\test_link_unlink_threaded.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_name_is_valid" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_name_is_valid" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_name_is_valid"/>
+	<param result-file = "C:\LOGS\test_name_is_valid.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_push_unlinked" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_push_unlinked" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_push_unlinked"/>
+	<param result-file = "C:\LOGS\test_push_unlinked.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_push_linked" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_push_linked" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_push_linked"/>
+	<param result-file = "C:\LOGS\test_push_linked.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_flowreturn" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_flowreturn" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_flowreturn"/>
+	<param result-file = "C:\LOGS\test_flowreturn.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_push_negotiation" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_push_negotiation" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_push_negotiation"/>
+	<param result-file = "C:\LOGS\test_push_negotiation.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_src_unref_unlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_src_unref_unlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_src_unref_unlink"/>
+	<param result-file = "C:\LOGS\test_src_unref_unlink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_sink_unref_unlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_sink_unref_unlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_sink_unref_unlink"/>
+	<param result-file = "C:\LOGS\test_sink_unref_unlink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_get_caps_must_be_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpad.exe"/>
+	<param dst = "C:\sys\bin\gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpad_test_get_caps_must_be_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpad.exe"/>
+	<param parameters = "test_get_caps_must_be_copy"/>
+	<param result-file = "C:\LOGS\test_get_caps_must_be_copy.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_init" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst.exe"/>
+	<param dst = "C:\sys\bin\gst.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gst_test_init" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst.exe"/>
+	<param parameters = "test_init"/>
+	<param result-file = "C:\LOGS\gst_test_init.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gst_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deinit" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst.exe"/>
+	<param dst = "C:\sys\bin\gst.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gst_test_deinit" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst.exe"/>
+	<param parameters = "test_deinit"/>
+	<param result-file = "C:\LOGS\gst_test_deinit.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gst_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deinit_sysclock" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst.exe"/>
+	<param dst = "C:\sys\bin\gst.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gst_test_deinit_sysclock" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst.exe"/>
+	<param parameters = "test_deinit_sysclock"/>
+	<param result-file = "C:\LOGS\gst_test_deinit_sysclock.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gst_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_new_pipeline" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst.exe"/>
+	<param dst = "C:\sys\bin\gst.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gst_test_new_pipeline" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst.exe"/>
+	<param parameters = "test_new_pipeline"/>
+	<param result-file = "C:\LOGS\gst_test_new_pipeline.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gst_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_new_fakesrc" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst.exe"/>
+	<param dst = "C:\sys\bin\gst.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gst_test_new_fakesrc" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst.exe"/>
+	<param parameters = "test_new_fakesrc"/>
+	<param result-file = "C:\LOGS\gst_test_new_fakesrc.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gst_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_version" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst.exe"/>
+	<param dst = "C:\sys\bin\gst.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gst_test_version" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst.exe"/>
+	<param parameters = "test_version"/>
+	<param result-file = "C:\LOGS\gst_test_version.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gst_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_create_events" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstevent.exe"/>
+	<param dst = "C:\sys\bin\gstevent.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstevent_create_events" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstevent.exe"/>
+	<param parameters = "create_events"/>
+	<param result-file = "C:\LOGS\gstevent_create_events.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstevent_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_send_custom_events" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstevent.exe"/>
+	<param dst = "C:\sys\bin\gstevent.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstevent_send_custom_events" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstevent.exe"/>
+	<param parameters = "send_custom_events"/>
+	<param result-file = "C:\LOGS\gstevent_send_custom_events.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstevent_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_add_remove_pad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstelement.exe"/>
+	<param dst = "C:\sys\bin\gstelement.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstelement_test_add_remove_pad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstelement.exe"/>
+	<param parameters = "test_add_remove_pad"/>
+	<param result-file = "C:\LOGS\gstelement_test_add_remove_pad.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstelement_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_add_pad_unref_element" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstelement.exe"/>
+	<param dst = "C:\sys\bin\gstelement.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstelement_test_add_pad_unref_element" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstelement.exe"/>
+	<param parameters = "test_add_pad_unref_element"/>
+	<param result-file = "C:\LOGS\gstelement_test_add_pad_unref_element.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstelement_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_error_no_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstelement.exe"/>
+	<param dst = "C:\sys\bin\gstelement.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstelement_test_error_no_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstelement.exe"/>
+	<param parameters = "test_error_no_bus"/>
+	<param result-file = "C:\LOGS\gstelement_test_error_no_bus.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstelement_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstelement.exe"/>
+	<param dst = "C:\sys\bin\gstelement.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstelement_test_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstelement.exe"/>
+	<param parameters = "test_link"/>
+	<param result-file = "C:\LOGS\gstelement_test_link.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstelement_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_link_no_pads" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstelement.exe"/>
+	<param dst = "C:\sys\bin\gstelement.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstelement_test_link_no_pads" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstelement.exe"/>
+	<param parameters = "test_link_no_pads"/>
+	<param result-file = "C:\LOGS\gstelement_test_link_no_pads.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstelement_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_class" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstelement.exe"/>
+	<param dst = "C:\sys\bin\gstelement.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstelement_test_class" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstelement.exe"/>
+	<param parameters = "test_class"/>
+	<param result-file = "C:\LOGS\gstelement_test_class.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstelement_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_remove1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_remove1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_remove1"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_remove1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_remove2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_remove2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_remove2"/>
+	<param result-file = "C:\LOGS\gstghostpad_testremove2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads_notarget" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads_notarget" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads_notarget"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads_notarget.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_link"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_link.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads_bin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads_bin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads_bin"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads_bin.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads_block" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads_block" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads_block"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads_block.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads_probes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads_probes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads_probes"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads_probes.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads_new_from_template" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads_new_from_template" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads_new_from_template"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads_new_from_template.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_ghost_pads_new_no_target_from_template" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstghostpad.exe"/>
+	<param dst = "C:\sys\bin\gstghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstghostpad_test_ghost_pads_new_no_target_from_template" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstghostpad.exe"/>
+	<param parameters = "test_ghost_pads_new_no_target_from_template"/>
+	<param result-file = "C:\LOGS\gstghostpad_test_ghost_pads_new_no_target_from_template.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstghostpad_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_message_state_changed_children" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_message_state_changed_children" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_message_state_changed_children"/>
+	<param result-file = "C:\LOGS\test_message_state_changed_children.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_watch_for_state_change" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_watch_for_state_change" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_watch_for_state_change"/>
+	<param result-file = "C:\LOGS\test_watch_for_state_change.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_add_linked" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_add_linked" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_add_linked"/>
+	<param result-file = "C:\LOGS\test_add_linked.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_add_self" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_add_self" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_add_self"/>
+	<param result-file = "C:\LOGS\test_add_self.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_iterate_sorted" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_iterate_sorted" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_iterate_sorted"/>
+	<param result-file = "C:\LOGS\test_iterate_sorted.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_children_state_change_order_flagged_sink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_children_state_change_order_flagged_sink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_children_state_change_order_flagged_sink"/>
+	<param result-file = "C:\LOGS\test_children_state_change_order_flagged_sink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_children_state_change_order_semi_sink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_children_state_change_order_semi_sink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_children_state_change_order_semi_sink"/>
+	<param result-file = "C:\LOGS\test_children_state_change_order_semi_sink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_children_state_change_order_two_sink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_children_state_change_order_two_sink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_children_state_change_order_two_sink"/>
+	<param result-file = "C:\LOGS\test_children_state_change_order_two_sink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_message_state_changed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_message_state_changed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_message_state_changed"/>
+	<param result-file = "C:\LOGS\test_message_state_changed.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_interface"/>
+	<param result-file = "C:\LOGS\test_interface.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_message_state_changed_child" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbin.exe"/>
+	<param dst = "C:\sys\bin\gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstbin_test_message_state_changed_child" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbin.exe"/>
+	<param parameters = "test_message_state_changed_child"/>
+	<param result-file = "C:\LOGS\test_message_state_changed_child.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstbin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fake_object_new" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fake_object_new" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fake_object_new"/>
+	<param result-file = "C:\LOGS\gstobject_test_fake_object_new.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fake_object_name" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fake_object_name" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fake_object_name"/>
+	<param result-file = "C:\LOGS\gstobject_test_fake_object_name.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fake_object_name_threaded_right" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fake_object_name_threaded_right" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fake_object_name_threaded_right"/>
+	<param result-file = "C:\LOGS\gstobject_test_fake_object_name_threaded_right.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fake_object_name_threaded_unique" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fake_object_name_threaded_unique" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fake_object_name_threaded_unique"/>
+	<param result-file = "C:\LOGS\gstobject_test_fake_object_name_threaded_unique.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fake_object_parentage" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fake_object_parentage" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fake_object_parentage"/>
+	<param result-file = "C:\LOGS\gstobject_test_fake_object_parentage.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fake_object_parentage_dispose" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fake_object_parentage_dispose" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fake_object_parentage_dispose"/>
+	<param result-file = "C:\LOGS\gstobject_test_fake_object_parentage_dispose.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fail_abstract_new" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstobject.exe"/>
+	<param dst = "C:\sys\bin\gstobject.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstobject_test_fail_abstract_new" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstobject.exe"/>
+	<param parameters = "test_fail_abstract_new"/>
+	<param result-file = "C:\LOGS\gstobject_test_fail_abstract_new.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstobject_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_from_string"/>
+	<param result-file = "C:\LOGS\gstcaps_test_from_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_double_append" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_double_append" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_double_append"/>
+	<param result-file = "C:\LOGS\gstcaps_test_double_append.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_mutability" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_mutability" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_mutability"/>
+	<param result-file = "C:\LOGS\gstcaps_test_mutability.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_buffer"/>
+	<param result-file = "C:\LOGS\gstcaps_test_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_static_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_static_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_static_caps"/>
+	<param result-file = "C:\LOGS\gstcaps_test_static_caps.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_merge_fundamental" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_merge_fundamental" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_merge_fundamental"/>
+	<param result-file = "C:\LOGS\gstcaps_test_merge_fundamental.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_gstcaps_test" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcaps.exe"/>
+	<param dst = "C:\sys\bin\gstcaps.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstcaps_test_merge_subset" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcaps.exe"/>
+	<param parameters = "test_merge_subset"/>
+	<param result-file = "C:\LOGS\gstcaps_test_merge_subset.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstcaps_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_manual_iteration" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstiterator.exe"/>
+	<param dst = "C:\sys\bin\gstiterator.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstiterator_test_manual_iteration" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstiterator.exe"/>
+	<param parameters = "test_manual_iteration"/>
+	<param result-file = "C:\LOGS\gstiterator_test_manual_iteration.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstiterator_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_resync" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstiterator.exe"/>
+	<param dst = "C:\sys\bin\gstiterator.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstiterator_test_resync" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstiterator.exe"/>
+	<param parameters = "test_resync"/>
+	<param result-file = "C:\LOGS\gstiterator_test_resync.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstiterator_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fold" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstiterator.exe"/>
+	<param dst = "C:\sys\bin\gstiterator.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstiterator_test_fold" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstiterator.exe"/>
+	<param parameters = "test_fold"/>
+	<param result-file = "C:\LOGS\gstiterator_test_fold.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstiterator_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_async_state_change_empty" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpipeline.exe"/>
+	<param dst = "C:\sys\bin\gstpipeline.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpipeline_test_async_state_change_empty" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpipeline.exe"/>
+	<param parameters = "test_async_state_change_empty"/>
+	<param result-file = "C:\LOGS\gstpipeline_test_async_state_change_empty.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpipeline_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_async_state_change_fake_ready" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpipeline.exe"/>
+	<param dst = "C:\sys\bin\gstpipeline.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpipeline_test_async_state_change_fake_ready" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpipeline.exe"/>
+	<param parameters = "test_async_state_change_fake_ready"/>
+	<param result-file = "C:\LOGS\gstpipeline_test_async_state_change_fake_ready.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpipeline_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_async_state_change_fake" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpipeline.exe"/>
+	<param dst = "C:\sys\bin\gstpipeline.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpipeline_test_async_state_change_fake" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpipeline.exe"/>
+	<param parameters = "test_async_state_change_fake"/>
+	<param result-file = "C:\LOGS\gstpipeline_test_async_state_change_fake.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpipeline_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_get_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpipeline.exe"/>
+	<param dst = "C:\sys\bin\gstpipeline.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpipeline_test_get_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpipeline.exe"/>
+	<param parameters = "test_get_bus"/>
+	<param result-file = "C:\LOGS\gstpipeline_test_get_bus.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpipeline_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpipeline.exe"/>
+	<param dst = "C:\sys\bin\gstpipeline.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpipeline_test_bus" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpipeline.exe"/>
+	<param parameters = "test_bus"/>
+	<param result-file = "C:\LOGS\gstpipeline_test_bus.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpipeline_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_base_time" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpipeline.exe"/>
+	<param dst = "C:\sys\bin\gstpipeline.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpipeline_test_base_time" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpipeline.exe"/>
+	<param parameters = "test_base_time"/>
+	<param result-file = "C:\LOGS\gstpipeline_test_base_time.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpipeline_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_register_static" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_register_static" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_register_static"/>
+	<param result-file = "C:\LOGS\gstplugin_test_register_static.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_registry" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_registry" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_registry"/>
+	<param result-file = "C:\LOGS\gstplugin_test_registry.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_registry_get_plugin_list" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_registry_get_plugin_list" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_registry_get_plugin_list"/>
+	<param result-file = "C:\LOGS\gstplugin_test_registry_get_plugin_list.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_find_plugin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_find_plugin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_find_plugin"/>
+	<param result-file = "C:\LOGS\gstplugin_test_find_plugin.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_find_feature" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_find_feature" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_find_feature"/>
+	<param result-file = "C:\LOGS\gstplugin_test_find_feature.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_find_element" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_find_element" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_find_element"/>
+	<param result-file = "C:\LOGS\gstplugin_test_find_element.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_version_checks" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_version_checks" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_version_checks"/>
+	<param result-file = "C:\LOGS\gstplugin_test_version_checks.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_load_coreelements" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_load_coreelements" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_load_coreelements"/>
+	<param result-file = "C:\LOGS\gstplugin_test_load_coreelements.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_typefind" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstplugin.exe"/>
+	<param dst = "C:\sys\bin\gstplugin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstplugin_test_typefind" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstplugin.exe"/>
+	<param parameters = "test_typefind"/>
+	<param result-file = "C:\LOGS\gstplugin_test_typefind.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstplugin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_poll_basic" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpoll.exe"/>
+	<param dst = "C:\sys\bin\gstpoll.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpoll_test_poll_basic" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpoll.exe"/>
+	<param parameters = "test_poll_basic"/>
+	<param result-file = "C:\LOGS\gstpoll_test_poll_basic.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpoll_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_poll_wait_stop" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpoll.exe"/>
+	<param dst = "C:\sys\bin\gstpoll.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpoll_test_poll_wait_stop" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpoll.exe"/>
+	<param parameters = "test_poll_wait_stop"/>
+	<param result-file = "C:\LOGS\gstpoll_test_poll_wait_stop.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpoll_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_poll_wait_flush" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpoll.exe"/>
+	<param dst = "C:\sys\bin\gstpoll.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpoll_test_poll_wait_flush" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpoll.exe"/>
+	<param parameters = "test_poll_wait_flush"/>
+	<param result-file = "C:\LOGS\gstpoll_test_poll_wait_flush.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpoll_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_poll_wait_restart" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpoll.exe"/>
+	<param dst = "C:\sys\bin\gstpoll.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpoll_test_poll_wait_restart" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpoll.exe"/>
+	<param parameters = "test_poll_wait_restart"/>
+	<param result-file = "C:\LOGS\gstpoll_test_poll_wait_restart.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpoll_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_poll_controllable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstpoll.exe"/>
+	<param dst = "C:\sys\bin\gstpoll.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstpoll_test_poll_controllable" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstpoll.exe"/>
+	<param parameters = "test_poll_controllable"/>
+	<param result-file = "C:\LOGS\gstpoll_test_poll_controllable.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpoll_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_index_entries" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstindex.exe"/>
+	<param dst = "C:\sys\bin\gstindex.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstindex_test_index_entries" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstindex.exe"/>
+	<param parameters = "test_index_entries"/>
+	<param result-file = "C:\LOGS\gstindex_test_index_entries.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstindex_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_seek_reverse" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_seek_reverse" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_seek_reverse"/>
+	<param result-file = "C:\LOGS\segment_seek_reverse.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_seek_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_seek_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_seek_rate"/>
+	<param result-file = "C:\LOGS\segment_seek_rate.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_open" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_open" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_open"/>
+	<param result-file = "C:\LOGS\segment_newsegment_open.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_closed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_closed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_closed"/>
+	<param result-file = "C:\LOGS\segment_newsegment_closed.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_streamtime" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_streamtime" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_streamtime"/>
+	<param result-file = "C:\LOGS\segment_newsegment_streamtime.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_streamtime_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_streamtime_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_streamtime_rate"/>
+	<param result-file = "C:\LOGS\segment_newsegment_streamtime_rate.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_streamtime_applied_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_streamtime_applied_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_streamtime_applied_rate"/>
+	<param result-file = "C:\LOGS\segment_newsegment_streamtime_applied_rate.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_streamtime_applied_rate_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_streamtime_applied_rate_rate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_streamtime_applied_rate_rate"/>
+	<param result-file = "C:\LOGS\segment_newsegment_streamtime_applied_rate_rate.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_runningtime" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_runningtime" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_runningtime"/>
+	<param result-file = "C:\LOGS\segment_newsegment_runningtime.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_accum" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_accum" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_accum"/>
+	<param result-file = "C:\LOGS\segment_newsegment_accum.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_newsegment_accum2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_newsegment_accum2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_newsegment_accum2"/>
+	<param result-file = "C:\LOGS\segment_newsegment_accum2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_seek_nosize" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_seek_nosize" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_seek_nosize"/>
+	<param result-file = "C:\LOGS\segment_seek_nosize.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_segment_seek_size" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsegment.exe"/>
+	<param dst = "C:\sys\bin\gstsegment.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsegment_segment_seek_size" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsegment.exe"/>
+	<param parameters = "segment_seek_size"/>
+	<param result-file = "C:\LOGS\segment_seek_size.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsegment_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_from_string_int" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_from_string_int" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_from_string_int"/>
+	<param result-file = "C:\LOGS\gststructure_test_from_string_int.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_from_string"/>
+	<param result-file = "C:\LOGS\gststructure_test_from_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_to_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_to_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_to_string"/>
+	<param result-file = "C:\LOGS\gststructure_test_to_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_to_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_to_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_to_from_string"/>
+	<param result-file = "C:\LOGS\gststructure_test_to_from_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_complete_structure" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_complete_structure" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_complete_structure"/>
+	<param result-file = "C:\LOGS\gststructure_test_complete_structure.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_structure_new" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_structure_new" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_structure_new"/>
+	<param result-file = "C:\LOGS\gststructure_test_structure_new.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fixate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_fixate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_fixate"/>
+	<param result-file = "C:\LOGS\gststructure_test_fixate.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fixate_frac_list" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_fixate_frac_list" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_fixate_frac_list"/>
+	<param result-file = "C:\LOGS\gststructure_test_fixate_frac_list.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_structure_nested" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststructure.exe"/>
+	<param dst = "C:\sys\bin\gststructure.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gststructure_test_structure_nested" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststructure.exe"/>
+	<param parameters = "test_structure_nested"/>
+	<param result-file = "C:\LOGS\gststructure_test_structure_nested.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststructure_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_range"/>
+	<param result-file = "C:\LOGS\test_range.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_diff" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_diff" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_diff"/>
+	<param result-file = "C:\LOGS\test_diff.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_signedness" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_signedness" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_signedness"/>
+	<param result-file = "C:\LOGS\test_signedness.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_single_shot" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_single_shot" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_single_shot"/>
+	<param result-file = "C:\LOGS\test_single_shot.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_periodic_shot" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_periodic_shot" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_periodic_shot"/>
+	<param result-file = "C:\LOGS\test_periodic_shot.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_periodic_multi" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_periodic_multi" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_periodic_multi"/>
+	<param result-file = "C:\LOGS\test_periodic_multi.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_async_order" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_async_order" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_async_order"/>
+	<param result-file = "C:\LOGS\test_async_order.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_mixed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsystemclock.exe"/>
+	<param dst = "C:\sys\bin\gstsystemclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsystemclock_test_mixed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsystemclock.exe"/>
+	<param parameters = "test_mixed"/>
+	<param result-file = "C:\LOGS\test_mixed.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\LOGS\gstsystemclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_buffer_probe_n_times" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_buffer_probe_n_times" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_buffer_probe_n_times"/>
+	<param result-file = "C:\LOGS\gstutils_test_buffer_probe_n_times.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_buffer_probe_once" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_buffer_probe_once" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_buffer_probe_once"/>
+	<param result-file = "C:\LOGS\gstutils_test_buffer_probe_once.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_math_scale" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_math_scale" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_math_scale"/>
+	<param result-file = "C:\LOGS\gstutils_test_math_scale.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_math_scale_uint64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_math_scale_uint64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_math_scale_uint64"/>
+	<param result-file = "C:\LOGS\gstutils_test_math_scale_uint64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_math_scale_random" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_math_scale_random" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_math_scale_random"/>
+	<param result-file = "C:\LOGS\gstutils_test_math_scale_random.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_guint64_to_gdouble" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_guint64_to_gdouble" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_guint64_to_gdouble"/>
+	<param result-file = "C:\LOGS\gstutils_test_guint64_to_gdouble.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_gdouble_to_guint64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_gdouble_to_guint64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_gdouble_to_guint64"/>
+	<param result-file = "C:\LOGS\gstutils_test_gdouble_to_guint64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_parse_bin_from_description" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_parse_bin_from_description" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_parse_bin_from_description"/>
+	<param result-file = "C:\LOGS\gstutils_test_parse_bin_from_description.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_element_found_tags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_element_found_tags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_element_found_tags"/>
+	<param result-file = "C:\LOGS\gstutils_test_element_found_tags.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_element_unlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_element_unlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_element_unlink"/>
+	<param result-file = "C:\LOGS\gstutils_test_element_unlink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_set_value_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstutils.exe"/>
+	<param dst = "C:\sys\bin\gstutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstutils_test_set_value_from_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstutils.exe"/>
+	<param parameters = "test_set_value_from_string"/>
+	<param result-file = "C:\LOGS\gstutils_test_set_value_from_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstutils_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_buffer"/>
+	<param result-file = "C:\LOGS\test_deserialize_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_serialize_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_serialize_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_serialize_buffer"/>
+	<param result-file = "C:\LOGS\test_serialize_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_gint" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_gint" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_gint"/>
+	<param result-file = "C:\LOGS\test_deserialize_gint.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_gint_failures" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_gint_failures" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_gint_failures"/>
+	<param result-file = "C:\LOGS\test_deserialize_gint_failures.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_guint" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_guint" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_guint"/>
+	<param result-file = "C:\LOGS\test_deserialize_guint.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_guint_failures" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_guint_failures" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_guint_failures"/>
+	<param result-file = "C:\LOGS\test_deserialize_guint_failures.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_gint64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_gint64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_gint64"/>
+	<param result-file = "C:\LOGS\test_deserialize_gint64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_gstfraction" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_gstfraction" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_gstfraction"/>
+	<param result-file = "C:\LOGS\test_deserialize_gstfraction.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_serialize_flags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_serialize_flags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_serialize_flags"/>
+	<param result-file = "C:\LOGS\test_serialize_flags.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_flags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_flags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_flags"/>
+	<param result-file = "C:\LOGS\test_deserialize_flags.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_serialize_deserialize_format_enum" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_serialize_deserialize_format_enum" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_serialize_deserialize_format_enum"/>
+	<param result-file = "C:\LOGS\test_serialize_deserialize_format_enum.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_string"/>
+	<param result-file = "C:\LOGS\test_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_deserialize_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_deserialize_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_deserialize_string"/>
+	<param result-file = "C:\LOGS\test_deserialize_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_intersect" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_value_intersect" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_value_intersect"/>
+	<param result-file = "C:\LOGS\test_value_intersect.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_date" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_date" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_date"/>
+	<param result-file = "C:\LOGS\test_date.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_fraction_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_fraction_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_fraction_range"/>
+	<param result-file = "C:\LOGS\test_fraction_range.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_subtract_fraction" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_value_subtract_fraction" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_value_subtract_fraction"/>
+	<param result-file = "C:\LOGS\test_value_subtract_fraction.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_compare" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_value_compare" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_value_compare"/>
+	<param result-file = "C:\LOGS\test_value_compare.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_subtract_int" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_value_subtract_int" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_value_subtract_int"/>
+	<param result-file = "C:\LOGS\test_value_subtract_int.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_subtract_double" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_value_subtract_double" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_value_subtract_double"/>
+	<param result-file = "C:\LOGS\test_value_subtract_double.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_value_subtract_fraction_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstvalue.exe"/>
+	<param dst = "C:\sys\bin\gstvalue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstvalue_test_value_subtract_fraction_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstvalue.exe"/>
+	<param parameters = "test_value_subtract_fraction_range"/>
+	<param result-file = "C:\LOGS\test_value_subtract_fraction_range.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstvalue_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_create" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttask.exe"/>
+	<param dst = "C:\sys\bin\gsttask.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttask_test_create" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttask.exe"/>
+	<param parameters = "test_create"/>
+	<param result-file = "C:\LOGS\gsttask_test_create.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttask_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_no_lock" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttask.exe"/>
+	<param dst = "C:\sys\bin\gsttask.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttask_test_no_lock" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttask.exe"/>
+	<param parameters = "test_no_lock"/>
+	<param result-file = "C:\LOGS\gsttask_test_no_lock.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttask_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_lock" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttask.exe"/>
+	<param dst = "C:\sys\bin\gsttask.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttask_test_lock" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttask.exe"/>
+	<param parameters = "test_lock"/>
+	<param result-file = "C:\LOGS\gsttask_test_lock.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttask_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_lock_start" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttask.exe"/>
+	<param dst = "C:\sys\bin\gsttask.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttask_test_lock_start" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttask.exe"/>
+	<param parameters = "test_lock_start"/>
+	<param result-file = "C:\LOGS\gsttask_test_lock_start.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttask_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_join" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttask.exe"/>
+	<param dst = "C:\sys\bin\gsttask.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttask_test_join" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttask.exe"/>
+	<param parameters = "test_join"/>
+	<param result-file = "C:\LOGS\gsttask_test_join.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttask_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_merge" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttag.exe"/>
+	<param dst = "C:\sys\bin\gsttag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttag_test_merge" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttag.exe"/>
+	<param parameters = "test_merge"/>
+	<param result-file = "C:\LOGS\gsttag_test_merge.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_date_tags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttag.exe"/>
+	<param dst = "C:\sys\bin\gsttag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttag_test_date_tags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttag.exe"/>
+	<param parameters = "test_date_tags"/>
+	<param result-file = "C:\LOGS\gsttag_test_date_tags.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_type" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttag.exe"/>
+	<param dst = "C:\sys\bin\gsttag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttag_test_type" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttag.exe"/>
+	<param parameters = "test_type"/>
+	<param result-file = "C:\LOGS\gsttag_test_type.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_set_non_utf8_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttag.exe"/>
+	<param dst = "C:\sys\bin\gsttag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttag_test_set_non_utf8_string" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttag.exe"/>
+	<param parameters = "test_set_non_utf8_string"/>
+	<param result-file = "C:\LOGS\gsttag_test_set_non_utf8_string.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+<step id="66.67.1.3.2" name="Install khuda.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="khuda.wav"/>
+     <param dst="C:\data\khuda.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_create_queries" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstquery.exe"/>
+	<param dst = "C:\sys\bin\gstquery.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstquery_create_queries" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstquery.exe"/>
+	<param parameters = "create_queries"/>
+	<param result-file = "C:\LOGS\gstquery_create_queries.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstquery_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_queries" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstquery.exe"/>
+	<param dst = "C:\sys\bin\gstquery.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstquery_test_queries" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstquery.exe"/>
+	<param parameters = "test_queries"/>
+	<param result-file = "C:\LOGS\gstquery_test_queries.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstquery_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_protocol_case" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsturi.exe"/>
+	<param dst = "C:\sys\bin\gsturi.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsturi_test_protocol_case" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsturi.exe"/>
+	<param parameters = "test_protocol_case"/>
+	<param result-file = "C:\LOGS\gsturi_test_protocol_case.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsturi_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_uri_get_location" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsturi.exe"/>
+	<param dst = "C:\sys\bin\gsturi.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsturi_test_uri_get_location" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsturi.exe"/>
+	<param parameters = "test_uri_get_location"/>
+	<param result-file = "C:\LOGS\gsturi_test_uri_get_location.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsturi_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_without_implements_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstinterface.exe"/>
+	<param dst = "C:\sys\bin\gstinterface.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstinterface_test_without_implements_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstinterface.exe"/>
+	<param parameters = "test_without_implements_interface"/>
+	<param result-file = "C:\LOGS\gstinterface_test_without_implements_interface.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstinterface_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_param_spec_fraction" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstparamspecs.exe"/>
+	<param dst = "C:\sys\bin\gstparamspecs.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstparamspecs_test_param_spec_fraction" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstparamspecs.exe"/>
+	<param parameters = "test_param_spec_fraction"/>
+	<param result-file = "C:\LOGS\gstparamspecs_test_param_spec_fraction.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstparamspecs_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_registry_update" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstregistry.exe"/>
+	<param dst = "C:\sys\bin\gstregistry.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstregistry_test_registry_update" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstregistry.exe"/>
+	<param parameters = "test_registry_update"/>
+	<param result-file = "C:\LOGS\gstregistry_test_registry_update.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstregistry_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_merge" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttagsetter.exe"/>
+	<param dst = "C:\sys\bin\gsttagsetter.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gsttagsetter_test_merge" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttagsetter.exe"/>
+	<param parameters = "test_merge"/>
+	<param result-file = "C:\LOGS\gsttagsetter_test_merge.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttagsetter_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install FAKESINK_test_clipping" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute FAKESINK_test_clipping" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param parameters = "test_clipping"/>
+	<param result-file = "C:\LOGS\fakesink_test_clipping.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesink_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install FAKESINK_test_preroll_sync" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute  FAKESINK_test_preroll_sync" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param parameters = "test_preroll_sync"/>
+	<param result-file = "C:\LOGS\fakesink_test_preroll_sync.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesink_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install  FAKESINK_test_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute FAKESINK_test_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param parameters = "test_eos"/>
+	<param result-file = "C:\LOGS\fakesink_test_eos.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesink_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install FAKESINK_test_eos2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute FAKESINK_test_eos2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesink.exe"/>
+	<param parameters = "test_eos2"/>
+	<param result-file = "C:\LOGS\fakesink_test_eos2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesink_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install FAKESRC_test_num_buffers" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FAKESRC_test_num_buffers" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param parameters = "test_num_buffers"/>
+	<param result-file = "C:\LOGS\fakesrc_test_num_buffers.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesrc_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install FAKESRC_test_sizetype_empty" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FAKESRC_test_sizetype_empty" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param parameters = "test_sizetype_empty"/>
+	<param result-file = "C:\LOGS\fakesrc_test_sizetype_empty.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesrc_log1.txt"/>
+  </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install FAKESRC_test_sizetype_random" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FAKESRC_test_sizetype_random" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param parameters = "test_sizetype_random"/>
+	<param result-file = "C:\LOGS\fakesrc_test_sizetype_random.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FAKESRC_test_no_preroll" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FAKESRC_test_no_preroll" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param parameters = "test_no_preroll"/>
+	<param result-file = "C:\LOGS\fakesrc_test_no_preroll.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesrc_log1.txt"/>
+  </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install FAKESRC_test_sizetype_fixed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfakesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FAKESRC_test_sizetype_fixed" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfakesrc.exe"/>
+	<param parameters = "test_sizetype_fixed"/>
+	<param result-file = "C:\LOGS\fakesrc_test_sizetype_fixed.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fakesrc_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install FILESINK_test_coverage" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESINK_test_coverage" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesink.exe"/>
+	<param parameters = "test_coverage"/>
+	<param result-file = "C:\LOGS\filesink_test_coverage.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESINK_test_uri_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESINK_test_uri_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesink.exe"/>
+	<param parameters = "test_uri_interface"/>
+	<param result-file = "C:\LOGS\filesink_test_uri_interface.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESINK_test_seeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesink.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESINK_test_seeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesink.exe"/>
+	<param parameters = "test_seeking"/>
+	<param result-file = "C:\LOGS\filesink_test_seeking.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install warning.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="warning.wav"/>
+     <param dst="C:\data\warning.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESRC_test_seeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESRC_test_seeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param parameters = "test_seeking"/>
+	<param result-file = "C:\LOGS\filesrc_test_seeking.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESRC_test_reverse" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESRC_test_reverse" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param parameters = "test_reverse"/>
+	<param result-file = "C:\LOGS\filesrc_test_reverse.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESRC_test_pull" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESRC_test_pull" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param parameters = "test_pull"/>
+	<param result-file = "C:\LOGS\filesrc_test_pull.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESRC_test_coverage" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESRC_test_coverage" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param parameters = "test_coverage"/>
+	<param result-file = "C:\LOGS\filesrc_test_coverage.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install FILESRC_test_uri_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfilesrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute FILESRC_test_uri_interface" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfilesrc.exe"/>
+	<param parameters = "test_uri_interface"/>
+	<param result-file = "C:\LOGS\filesrc_test_uri_interface.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesrc_log1.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install IDENTITY_test_one_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstidentity.exe"/>
+	<param dst = "C:\sys\bin\element_gstidentity.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute IDENTITY_test_one_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstidentity.exe"/>
+	<param parameters = "test_one_buffer"/>
+	<param result-file = "C:\LOGS\identity_test_one_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\identity_log1.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install MULTIQUEUE_test_simple_create_destroy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstmultiqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstmultiqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MULTIQUEUE_test_simple_create_destroy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstmultiqueue.exe"/>
+	<param parameters = "test_simple_create_destroy"/>
+	<param result-file = "C:\LOGS\multiqueue_test_simple_create_destroy.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multiqueue_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MULTIQUEUE_test_simple_pipeline" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstmultiqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstmultiqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MULTIQUEUE_test_simple_pipeline" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstmultiqueue.exe"/>
+	<param parameters = "test_simple_pipeline"/>
+	<param result-file = "C:\LOGS\multiqueue_test_simple_pipeline.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multiqueue_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MULTIQUEUE_test_simple_shutdown_while_running" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstmultiqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstmultiqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MULTIQUEUE_test_simple_shutdown_while_running" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstmultiqueue.exe"/>
+	<param parameters = "test_simple_shutdown_while_running"/>
+	<param result-file = "C:\LOGS\multiqueue_test_simple_shutdown_while_running.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multiqueue_log1.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install queue_test_non_leaky_underrun" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute queue_test_non_leaky_underrun" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstqueue.exe"/>
+	<param parameters = "test_non_leaky_underrun"/>
+	<param result-file = "C:\LOGS\queue_test_non_leaky_underrun.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\queue_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install queue_test_non_leaky_overrun" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute queue_test_non_leaky_overrun" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstqueue.exe"/>
+	<param parameters = "test_non_leaky_overrun"/>
+	<param result-file = "C:\LOGS\queue_test_non_leaky_overrun.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\queue_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install queue_test_leaky_upstream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute queue_test_leaky_upstream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstqueue.exe"/>
+	<param parameters = "test_leaky_upstream"/>
+	<param result-file = "C:\LOGS\queue_test_leaky_upstream.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\queue_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install queue_test_leaky_downstream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute queue_test_leaky_downstream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstqueue.exe"/>
+	<param parameters = "test_leaky_downstream"/>
+	<param result-file = "C:\LOGS\queue_test_leaky_downstream.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\queue_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install queue_test_time_level" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstqueue.exe"/>
+	<param dst = "C:\sys\bin\element_gstqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute queue_test_time_level" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstqueue.exe"/>
+	<param parameters = "test_time_level"/>
+	<param result-file = "C:\LOGS\queue_test_time_level.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\queue_log1.txt"/>
+   </params>
+</step>
+
+
+
+ 
+<step id = "66.67.1.1.1.1" name = "fdsrc_test_num_buffers" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfdsrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfdsrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute fdsrc_test_num_buffers" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfdsrc.exe"/>
+	<param parameters = "test_num_buffers"/>
+	<param result-file = "C:\LOGS\fdsrc_test_num_buffers.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fdsrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install fdsrc_test_nonseeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfdsrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfdsrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute fdsrc_test_nonseeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfdsrc.exe"/>
+	<param parameters = "test_nonseeking"/>
+	<param result-file = "C:\LOGS\fdsrc_test_nonseeking.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fdsrc_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install fdsrc_test_seeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gstfdsrc.exe"/>
+	<param dst = "C:\sys\bin\element_gstfdsrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute fdsrc_test_seeking" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gstfdsrc.exe"/>
+	<param parameters = "test_seeking"/>
+	<param result-file = "C:\LOGS\fdsrc_test_seeking.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\fdsrc_log1.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_COLLECTPADS_test_pad_add_remove" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcollectpads.exe"/>
+	<param dst = "C:\sys\bin\gstcollectpads.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_COLLECTPADS_test_pad_add_remove" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcollectpads.exe"/>
+	<param parameters = "test_pad_add_remove"/>
+	<param result-file = "C:\LOGS\test_pad_add_remove.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\collectpads_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_COLLECTPADS_test_collect" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcollectpads.exe"/>
+	<param dst = "C:\sys\bin\gstcollectpads.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_COLLECTPADS_test_collect" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcollectpads.exe"/>
+	<param parameters = "test_collect"/>
+	<param result-file = "C:\LOGS\test_collect.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\collectpads_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_COLLECTPADS_test_collect_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcollectpads.exe"/>
+	<param dst = "C:\sys\bin\gstcollectpads.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_COLLECTPADS_test_collect_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcollectpads.exe"/>
+	<param parameters = "test_collect_eos"/>
+	<param result-file = "C:\LOGS\test_collect_eos.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\collectpads_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_COLLECTPADS_test_collect_twice" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstcollectpads.exe"/>
+	<param dst = "C:\sys\bin\gstcollectpads.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_COLLECTPADS_test_collect_twice" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstcollectpads.exe"/>
+	<param parameters = "test_collect_twice"/>
+	<param result-file = "C:\LOGS\test_collect_twice.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\collectpads_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install ADAPTER_test_peek1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadapter.exe"/>
+	<param dst = "C:\sys\bin\gstadapter.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ADAPTER_test_peek1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadapter.exe"/>
+	<param parameters = "test_peek1"/>
+	<param result-file = "C:\LOGS\test_peek1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adapter_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install ADAPTER_test_take_order" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadapter.exe"/>
+	<param dst = "C:\sys\bin\gstadapter.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ADAPTER_test_take_order" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadapter.exe"/>
+	<param parameters = "test_take_order"/>
+	<param result-file = "C:\LOGS\test_take_order.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adapter_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install ADAPTER_test_take_buf_order" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadapter.exe"/>
+	<param dst = "C:\sys\bin\gstadapter.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ADAPTER_test_take_buf_order" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadapter.exe"/>
+	<param parameters = "test_take_buf_order"/>
+	<param result-file = "C:\LOGS\test_take_buf_order.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adapter_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install BASESRC_basesrc_eos_events_pull" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbasesrc.exe"/>
+	<param dst = "C:\sys\bin\gstbasesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute BASESRC_basesrc_eos_events_pull" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbasesrc.exe"/>
+	<param parameters = "basesrc_eos_events_pull"/>
+	<param result-file = "C:\LOGS\basesrc_eos_events_pull.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\basesrc_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install BASESRC_basesrc_eos_events_push" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbasesrc.exe"/>
+	<param dst = "C:\sys\bin\gstbasesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute BASESRC_basesrc_eos_events_push" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbasesrc.exe"/>
+	<param parameters = "basesrc_eos_events_push"/>
+	<param result-file = "C:\LOGS\basesrc_eos_events_push.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\basesrc_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install BASESRC_basesrc_eos_events_push_live_op" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbasesrc.exe"/>
+	<param dst = "C:\sys\bin\gstbasesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute BASESRC_basesrc_eos_events_push_live_op" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbasesrc.exe"/>
+	<param parameters = "basesrc_eos_events_push_live_op"/>
+	<param result-file = "C:\LOGS\basesrc_eos_events_push_live_op.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\basesrc_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install BASESRC_basesrc_eos_events_pull_live_op" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbasesrc.exe"/>
+	<param dst = "C:\sys\bin\gstbasesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute BASESRC_basesrc_eos_events_pull_live_op" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbasesrc.exe"/>
+	<param parameters = "basesrc_eos_events_pull_live_op"/>
+	<param result-file = "C:\LOGS\basesrc_eos_events_pull_live_op.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\basesrc_logs.txt"/>
+   </params>
+</step><step id = "66.67.1.1.1.1" name = "Install BASESRC_basesrc_eos_events_push_live_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbasesrc.exe"/>
+	<param dst = "C:\sys\bin\gstbasesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute BASESRC_basesrc_eos_events_push_live_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbasesrc.exe"/>
+	<param parameters = "basesrc_eos_events_push_live_eos"/>
+	<param result-file = "C:\LOGS\basesrc_eos_events_push_live_eos.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\basesrc_logs.txt"/>
+   </params>
+</step><step id = "66.67.1.1.1.1" name = "Install BASESRC_basesrc_eos_events_pull_live_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstbasesrc.exe"/>
+	<param dst = "C:\sys\bin\gstbasesrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute BASESRC_basesrc_eos_events_pull_live_eos" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstbasesrc.exe"/>
+	<param parameters = "basesrc_eos_events_pull_live_eos"/>
+	<param result-file = "C:\LOGS\basesrc_eos_events_pull_live_eos.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\basesrc_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install GDP_test_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgdp.exe"/>
+	<param dst = "C:\sys\bin\gstgdp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute GDP_test_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgdp.exe"/>
+	<param parameters = "test_conversion"/>
+	<param result-file = "C:\LOGS\test_conversion.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdp_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install GDP_test_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgdp.exe"/>
+	<param dst = "C:\sys\bin\gstgdp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute GDP_test_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgdp.exe"/>
+	<param parameters = "test_buffer"/>
+	<param result-file = "C:\LOGS\test_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdp_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install GDP_test_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgdp.exe"/>
+	<param dst = "C:\sys\bin\gstgdp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute GDP_test_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgdp.exe"/>
+	<param parameters = "test_caps"/>
+	<param result-file = "C:\LOGS\test_caps.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdp_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install GDP_test_event" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgdp.exe"/>
+	<param dst = "C:\sys\bin\gstgdp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute GDP_test_event" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgdp.exe"/>
+	<param parameters = "test_event"/>
+	<param result-file = "C:\LOGS\test_event.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdp_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install GDP_test_memory" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgdp.exe"/>
+	<param dst = "C:\sys\bin\gstgdp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute GDP_test_memory" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgdp.exe"/>
+	<param parameters = "test_memory"/>
+	<param result-file = "C:\LOGS\test_memory.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdp_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_LIBABI_test_ABI" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstlibsabi.exe"/>
+	<param dst = "C:\sys\bin\gstlibsabi.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_LIBABI_test_ABI" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstlibsabi.exe"/>
+	<param parameters = "test_ABI"/>
+	<param result-file = "C:\LOGS\test_ABI.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\libsabi_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_GSTNERCLIENTCLOCK_test_instantiation" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgstnetclientclock.exe"/>
+	<param dst = "C:\sys\bin\gstgstnetclientclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_GSTNERCLIENTCLOCK_test_instantiation" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgstnetclientclock.exe"/>
+	<param parameters = "test_instantiation"/>
+	<param result-file = "C:\LOGS\test_instantiation.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstnetclientclock_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install LIBS_GSTNERCLIENTCLOCK_test_functioning" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgstnetclientclock.exe"/>
+	<param dst = "C:\sys\bin\gstgstnetclientclock.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_GSTNERCLIENTCLOCK_test_functioning" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgstnetclientclock.exe"/>
+	<param parameters = "test_functioning"/>
+	<param result-file = "C:\LOGS\test_functioning.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstnetclientclock_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_GSTNETTIMEPROVIDER_test_refcounts" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgstnettimeprovider.exe"/>
+	<param dst = "C:\sys\bin\gstgstnettimeprovider.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_GSTNETTIMEPROVIDER_test_refcounts" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgstnettimeprovider.exe"/>
+	<param parameters = "test_refcounts"/>
+	<param result-file = "C:\LOGS\test_refcounts.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstnettimeprovider_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install LIBS_GSTNETTIMEPROVIDER_test_functioning" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstgstnettimeprovider.exe"/>
+	<param dst = "C:\sys\bin\gstgstnettimeprovider.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_GSTNETTIMEPROVIDER_test_functioning" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstgstnettimeprovider.exe"/>
+	<param parameters = "test_functioning"/>
+	<param result-file = "C:\LOGS\test_functioning.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstnettimeprovider_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_TYPEFINDHELPER_test_buffer_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gsttypefindhelper.exe"/>
+	<param dst = "C:\sys\bin\gsttypefindhelper.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_TYPEFINDHELPER_test_buffer_range" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gsttypefindhelper.exe"/>
+	<param parameters = "test_buffer_range"/>
+	<param result-file = "C:\LOGS\test_buffer_range.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\typefindhelper_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install test_stress_preroll " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "stress.exe"/>
+	<param dst = "C:\sys\bin\stress.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute test_stress_preroll" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\stress.exe"/>
+	<param parameters = "test_stress_preroll"/>
+	<param result-file = "C:\LOGS\test_stress_preroll.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\stress_logs.txt"/>
+  </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install test_stress " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "stress.exe"/>
+	<param dst = "C:\sys\bin\stress.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute test_stress" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\stress.exe"/>
+	<param parameters = "test_stress"/>
+	<param result-file = "C:\LOGS\test_stress.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\stress_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+	
+	
+	
+<!--<set id = "66.67.1.1" name = "PIPELINE_PARSE-LAUNCH" harness = "ATSINTERFACE" enabled = "true" passrate = "100">
+<target>
+	<device rank = "master" alias = "default"/>
+</target>
+<case id = "66.67.1.1.1" name = "PIPELINE_PARSE-LAUNCH" harness = "ATSINTERFACE" enabled = "true" passrate = "100">
+ 
+<step id = "66.67.1.1.1.1" name = "Install PIPELINE_PARSE-LAUNCH_test_launch_lines" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "parse-launch.exe"/>
+	<param dst = "C:\sys\bin\parse-launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PIPELINE_PARSE-LAUNCH_test_launch_lines" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\parse-launch.exe"/>
+	<param parameters = "test_launch_lines"/>
+	<param result-file = "C:\LOGS\test_launch_lines.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\parselunch_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install PIPELINE_PARSE-LAUNCH_test_launch_lines2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "parse-launch.exe"/>
+	<param dst = "C:\sys\bin\parse-launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PIPELINE_PARSE-LAUNCH_test_launch_lines2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\parse-launch.exe"/>
+	<param parameters = "test_launch_lines2"/>
+	<param result-file = "C:\LOGS\test_launch_lines2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\parselunch_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install PIPELINE_PARSE-LAUNCH_expected_to_fail_pipes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "parse-launch.exe"/>
+	<param dst = "C:\sys\bin\parse-launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PIPELINE_PARSE-LAUNCH_expected_to_fail_pipes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\parse-launch.exe"/>
+	<param parameters = "expected_to_fail_pipes"/>
+	<param result-file = "C:\LOGS\expected_to_fail_pipes.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\parselunch_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install PIPELINE_PARSE-LAUNCH_leaking_fail_pipes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "parse-launch.exe"/>
+	<param dst = "C:\sys\bin\parse-launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PIPELINE_PARSE-LAUNCH_leaking_fail_pipes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\parse-launch.exe"/>
+	<param parameters = "leaking_fail_pipes"/>
+	<param result-file = "C:\LOGS\leaking_fail_pipes.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\parselunch_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Install PIPELINE_PARSE-LAUNCH_delayed_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "parse-launch.exe"/>
+	<param dst = "C:\sys\bin\parse-launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PIPELINE_PARSE-LAUNCH_delayed_link" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\parse-launch.exe"/>
+	<param parameters = "delayed_link"/>
+	<param result-file = "C:\LOGS\delayed_link.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\parselunch_log1.txt"/>
+   </params>
+</step>
+</case>
+</set>-->
+	
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install EXAMPLE_ADAPTER " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "testgstadapter.exe"/>
+	<param dst = "C:\sys\bin\testgstadapter.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute EXAMPLE_ADAPTER" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\testgstadapter.exe"/>
+	<param result-file = "C:\LOGS\adapter_test.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adapter_test_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install EXAMPLE_LAUNCH " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "launch.exe"/>
+	<param dst = "C:\sys\bin\launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute EXAMPLE_LAUNCH" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\launch.exe"/>
+	<param parameters = "C:\data\gstreamer\warning.wav"/>
+	<param result-file = "C:\LOGS\launch_logs.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install EXAMPLE_HELLOWORLD" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "helloworld.exe"/>
+	<param dst = "C:\sys\bin\helloworld.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute EXAMPLE_HELLOWORLD" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\helloworld.exe"/>
+	<param result-file = "C:\LOGS\helloworld_logs.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_bin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstbin.exe"/>
+	<param dst = "C:\sys\bin\manual_gstbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_bin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstbin.exe"/>
+	<param result-file = "C:\LOGS\bin.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\bin_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstelementcreate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstelementcreate.exe"/>
+	<param dst = "C:\sys\bin\manual_gstelementcreate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstelementcreate" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstelementcreate.exe"/>
+	<param result-file = "C:\LOGS\test_elementcreate.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstdecodebin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstdecodebin.exe"/>
+	<param dst = "C:\sys\bin\manual_gstdecodebin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstdecodebin" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstdecodebin.exe"/>
+	<param parameters = "C:\data\gstreamer\Crnival.mp3"/>
+	<param result-file = "C:\LOGS\decodebin.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\decodebin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstelementget" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstelementget.exe"/>
+	<param dst = "C:\sys\bin\manual_gstelementget.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstelementget" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstelementget.exe"/>
+	<param result-file = "C:\LOGS\test_elementget.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstinit" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstinit.exe"/>
+	<param dst = "C:\sys\bin\manual_gstinit.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstinit" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstinit.exe"/>
+	<param result-file = "C:\LOGS\init.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\init_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstelementlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstelementlink.exe"/>
+	<param dst = "C:\sys\bin\manual_gstelementlink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstelementlink" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstelementlink.exe"/>
+	<param result-file = "C:\LOGS\test_elementlink.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstelementmake" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstelementmake.exe"/>
+	<param dst = "C:\sys\bin\manual_gstelementmake.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstelementmake" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstelementmake.exe"/>
+	<param result-file = "C:\LOGS\test_elementmake.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\filesink_log1.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_ghostpad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_ghostpad.exe"/>
+	<param dst = "C:\sys\bin\manual_ghostpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_ghostpad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_ghostpad.exe"/>
+	<param result-file = "C:\LOGS\ghostpad.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\ghostpad_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_typefind" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_typefind.exe"/>
+	<param dst = "C:\sys\bin\manual_typefind.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute  MANUAL_manual_typefind" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_typefind.exe"/>
+	<param parameters = "C:\data\gstreamer\Crnival.mp3"/>
+	<param result-file = "C:\LOGS\typefind.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\typefind_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install manual_gstpad.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstpad.exe"/>
+	<param dst = "C:\sys\bin\manual_gstpad.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute manual_gstpad.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstpad.exe"/>
+	<param result-file = "C:\LOGS\pad.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pad_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstplaybin.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstplaybin.exe"/>
+	<param dst = "C:\sys\bin\manual_gstplaybin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstplaybin.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstplaybin.exe"/>
+	<param parameters = "C:\data\gstreamer\Crnival.mp3"/>
+	<param result-file = "C:\LOGS\playbin.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstelementfactory.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstelementfactory.exe"/>
+	<param dst = "C:\sys\bin\manual_gstelementfactory.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstelementfactory.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstelementfactory.exe"/>
+	<param result-file = "C:\LOGS\elementfactory.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\elementfactory_logs.txt"/>
+   </params>
+</step>
+
+ 
+<step id = "66.67.1.1.1.1" name = "Install typefind" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "typefind.exe"/>
+	<param dst = "C:\sys\bin\typefind.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute typefind" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+        <param file = "C:\sys\bin\typefind.exe"/>
+        <param parameters = "C:\data\gstreamer\warning.wav"/>
+	<param result-file = "C:\LOGS\typefind_logs.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\typefind_logs.txt"/>
+   </params>
+</step>
+
+
+
+  
+<step id = "66.67.1.1.1.1" name = "Install metadata" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "metadata.exe"/>
+	<param dst = "C:\sys\bin\metadata.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute metadata" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\metadata.exe"/>
+	<param parameters = "C:\data\gstreamer\warning.wav"/>
+	<param result-file = "C:\LOGS\read-metadata_logs.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+
+
+
+  
+<step id = "66.67.1.1.1.1" name = "Install queue." harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "testqueue.exe"/>
+	<param dst = "C:\sys\bin\testqueue.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute queue" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\testqueue.exe"/>
+	<param parameters = "C:\data\gstreamer\Crnival.mp3"/>
+	<param result-file = "C:\LOGS\queue_logs.txt"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+
+
+
+
+<step id = "66.67.1.2.1.2" name = "Install controller" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "testaudioexample.exe"/>
+	<param dst = "C:\sys\bin\testaudioexample.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute controller" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\testaudioexample.exe"/>
+	<param result-file = "C:\LOGS\audio_example_logs.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audio_example_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_sink.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_sink.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_sink"/>
+	<param result-file = "C:\LOGS\sinks_test_sink.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_sink_completion.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_sink_completion.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_sink_completion"/>
+	<param result-file = "C:\LOGS\sinks_test_sink_completion.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+  </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_src_sink.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_src_sink.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_src_sink"/>
+	<param result-file = "C:\LOGS\sinks_test_src_sink.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_livesrc_remove.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_livesrc_remove.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_livesrc_remove"/>
+	<param result-file = "C:\LOGS\sinks_test_livesrc_remove.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_locked_sink.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_locked_sink.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_locked_sink"/>
+	<param result-file = "C:\LOGS\sinks_test_locked_sink.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_unlinked_live.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_unlinked_live.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_unlinked_live"/>
+	<param result-file = "C:\LOGS\sinks_test_unlinked_live.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_delayed_async.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_delayed_async.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_delayed_async"/>
+	<param result-file = "C:\LOGS\sinks_test_delayed_async.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_added_async.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_added_async.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_added_async"/>
+	<param result-file = "C:\LOGS\sinks_test_added_async.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_added_async2.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_added_async2.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_added_async2"/>
+	<param result-file = "C:\LOGS\sinks_test_added_async2.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_add_live.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_add_live.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_add_live"/>
+	<param result-file = "C:\LOGS\sinks_test_add_live.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install SINKS_test_bin_live.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsinks.exe"/>
+	<param dst = "C:\sys\bin\gstsinks.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute SINKS_test_bin_live.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsinks.exe"/>
+	<param parameters = "test_bin_live"/>
+	<param result-file = "C:\LOGS\sinks_test_bin_live.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\sinks_log.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install STATES_test_state_changes_up_and_down_seq.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststates.exe"/>
+	<param dst = "C:\sys\bin\gststates.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute states_test_state_changes_up_and_down_seq.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststates.exe"/>
+	<param parameters = "test_state_changes_up_and_down_seq"/>
+	<param result-file = "C:\LOGS\states_test_state_changes_up_and_down_seq.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\states_logs.txt"/>
+  </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install states_test_state_changes_up_seq.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststates.exe"/>
+	<param dst = "C:\sys\bin\gststates.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute states_test_state_changes_up_seq.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststates.exe"/>
+	<param parameters = "test_state_changes_up_seq"/>
+	<param result-file = "C:\LOGS\states_test_state_changes_up_seq.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\states_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install states_test_state_changes_down_seq.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststates.exe"/>
+	<param dst = "C:\sys\bin\states.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute states_test_state_changes_down_seq.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststates.exe"/>
+	<param parameters = "test_state_changes_down_seq"/>
+	<param result-file = "C:\LOGS\states_test_state_changes_down_seq.xml"/>
+	<param timeout ="1500" />
+  </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install EXAMPLE_MP3LAUNCH " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "mp3launch.exe"/>
+	<param dst = "C:\sys\bin\mp3launch.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute EXAMPLE_MP3LAUNCH" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\mp3launch.exe"/>
+	<param parameters = "C:\data\gstreamer\Crnival.mp3"/>
+	<param result-file = "C:\LOGS\mp3parselaunch_logs.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_manual_gstquery.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_gstquery.exe"/>
+	<param dst = "C:\sys\bin\manual_gstquery.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_manual_gstquery.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_gstquery.exe"/>
+	<param dst="c:\data\gstreamer\test\warning.wav"/>
+	<param result-file = "C:\LOGS\query.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\query_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.2.1.2" name = "Install MANUAL_DYNAMIC" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_dynamic.exe"/>
+	<param dst = "C:\sys\bin\manual_dynamic.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_DYNAMIC" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_dynamic.exe"/>
+	<param dst="c:\data\gstreamer\test\warning.wav"/>
+	<param result-file = "C:\LOGS\manual_dynamic.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\dynamic_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.2.1.2" name = "Install ELEMENT_TEE_test_num_buffers" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gsttee.exe"/>
+	<param dst = "C:\sys\bin\element_gsttee.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute ELEMENT_TEE_test_num_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gsttee.exe"/>
+	<param parameters = "test_num_buffers"/>
+	<param result-file = "C:\LOGS\tee_test_num_buffers.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\tee_log1.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Install ELEMENT_TEE_test_stress" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "element_gsttee.exe"/>
+	<param dst = "C:\sys\bin\element_gsttee.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute ELEMENT_TEE_test_stress" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\element_gsttee.exe"/>
+	<param parameters = "test_stress"/>
+	<param result-file = "C:\LOGS\tee_test_stress.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\tee_log1.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install LIBS_CLEANUP_test_pipeline_unref" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "cleanup.exe"/>
+	<param dst = "C:\sys\bin\cleanup.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_CLEANUP_test_pipeline_unref" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\cleanup.exe"/>
+	<param parameters = "test_pipeline_unref"/>
+	<param result-file = "C:\LOGS\test_pipeline_unref.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\cleanup_log1.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "Install parse-disabled_test_parse_launch_errors" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "parse-disabled.exe"/>
+	<param dst = "C:\sys\bin\parse-disabled.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute parse-disabled_test_parse_launch_errors" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\parse-disabled.exe"/>
+	<param parameters = "test_parse_launch_errors"/>
+	<param result-file = "C:\LOGS\parse-disabled_test_parse_launch_errors.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\parse-disabled_log1.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "Install simple-launch-lines_test_2_elements" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "simple-launch-lines.exe"/>
+	<param dst = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute simple-launch-lines_test_2_elements" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param parameters = "test_2_elements"/>
+	<param result-file = "C:\LOGS\test_2_elements.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\simple-launch-lines_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install simple-launch-lines_test_state_change_returns" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "simple-launch-lines.exe"/>
+	<param dst = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute simple-launch-lines_test_state_change_returns" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param parameters = "test_state_change_returns"/>
+	<param result-file = "C:\LOGS\test_state_change_returns.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\simple-launch-lines_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install simple-launch-lines_test_tee" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "simple-launch-lines.exe"/>
+	<param dst = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute simple-launch-lines_test_tee" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param parameters = "test_tee"/>
+	<param result-file = "C:\LOGS\simple-launch-lines_test_tee.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\simple-launch-lines_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "Install simple-launch-lines_test_stop_from_app" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "simple-launch-lines.exe"/>
+	<param dst = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute simple-launch-lines_test_stop_from_app" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\simple-launch-lines.exe"/>
+	<param parameters = "test_stop_from_app"/>
+	<param result-file = "C:\LOGS\simple-launch-lines_test_stop_from_app.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\simple-launch-lines_log1.txt"/>
+   </params>
+</step>
+<!--<step id = "66.67.1.2.1.2" name = "Install MANUAL_HELLOWORLD" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "manual_helloworld.exe"/>
+	<param dst = "C:\sys\bin\manual_helloworld.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id="66.67.1.3.2" name="Install warning.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="warning.wav"/>
+     <param dst="C:\data\gstreamer\warning.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+<step id = "66.67.1.2.1.2" name = "Execute MANUAL_HELLOWORLD" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\manual_helloworld.exe"/>
+	<param parameters = "c:\data\gstreamer\warning.wav"/>
+	<param result-file = "C:\LOGS\helloworld.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.2.1.2" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\helloworld_log1.txt"/>
+   </params>
+</step>-->
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_int_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_int_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_int_conversion"/>
+	<param result-file = "C:\LOGS\test_int_conversion.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioconvert_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "gstaudioconvert_test_int16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_int16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_int16"/>
+	<param result-file = "C:\LOGS\test_int16.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioconvert_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "gstaudioconvert_test_float32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_float32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_float32"/>
+	<param result-file = "C:\LOGS\test_float32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL gstaudioconvert_test_float_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_float_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_float_conversion"/>
+	<param result-file = "C:\LOGS\audioconvert_test_float_conversion.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioconvert_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL gstaudioconvert_test_multichannel_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_multichannel_conversion" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_multichannel_conversion"/>
+	<param result-file = "C:\LOGS\test_multichannel_conversion.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioconvert_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL gstaudioconvert_test_channel_remapping" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_channel_remapping" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_channel_remapping"/>
+	<param result-file = "C:\LOGS\test_channel_remapping.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioconvert_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL gstaudioconvert_test_caps_negotiation" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioconvert.exe"/>
+	<param dst = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudioconvert_test_caps_negotiation" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioconvert.exe"/>
+	<param parameters = "test_caps_negotiation"/>
+	<param result-file = "C:\LOGS\test_caps_negotiation.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioconvert_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_STATES_test_state_changes_up_and_down_seq" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "states.exe"/>
+	<param dst = "C:\sys\bin\states.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute STATES_test_state_changes_up_and_down_seq" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\states.exe"/>
+	<param parameters = "test_state_changes_up_and_down_seq"/>
+	<param result-file = "C:\LOGS\test_state_changes_up_and_down_seq.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststates_logs.txt"/>
+  </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_STATES_test_state_changes_up_seq" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "states.exe"/>
+	<param dst = "C:\sys\bin\states.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute STATES_test_state_changes_up_seq" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\states.exe"/>
+	<param parameters = "test_state_changes_up_seq"/>
+	<param result-file = "C:\LOGS\test_state_changes_up_seq.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststates_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_STATES_test_state_changes_down_seq" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "states.exe"/>
+	<param dst = "C:\sys\bin\states.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute STATES_test_state_changes_down_seq" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\states.exe"/>
+	<param parameters = "test_state_changes_down_seq"/>
+	<param result-file = "C:\LOGS\test_state_changes_down_seq.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gststates_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL CLOCK-SELECTION_test_add" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "clock-selection.exe"/>
+	<param dst = "C:\sys\bin\clock-selection.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute CLOCK-SELECTION_test_add" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\clock-selection.exe"/>
+	<param parameters = "test_add"/>
+	<param result-file = "C:\LOGS\test_add.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstclock-selection_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_next_fast_length" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_next_fast_length" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_next_fast_length"/>
+	<param result-file = "C:\LOGS\test_next_fast_length.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_s16_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_s16_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_s16_0hz"/>
+	<param result-file = "C:\LOGS\test_s16_0hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_s16_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_s16_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_s16_11025hz"/>
+	<param result-file = "C:\LOGS\test_s16_11025hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_s16_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_s16_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_s16_22050hz"/>
+	<param result-file = "C:\LOGS\test_s16_22050hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_s32_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_s32_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_s32_0hz"/>
+	<param result-file = "C:\LOGS\test_s32_0hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_s32_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_s32_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_s32_11025hz"/>
+	<param result-file = "C:\LOGS\test_s32_11025hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_s32_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_s32_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_s32_22050hz"/>
+	<param result-file = "C:\LOGS\test_s32_22050hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_f32_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_f32_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_f32_0hz"/>
+	<param result-file = "C:\LOGS\test_f32_0hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_f32_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_f32_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_f32_11025hz"/>
+	<param result-file = "C:\LOGS\test_f32_11025hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_f32_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_f32_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_f32_22050hz"/>
+	<param result-file = "C:\LOGS\test_f32_22050hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_f64_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_f64_0hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_f64_0hz"/>
+	<param result-file = "C:\LOGS\test_f64_0hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_f64_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_f64_11025hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_f64_11025hz"/>
+	<param result-file = "C:\LOGS\test_f64_11025hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_FFT_test_f64_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "fft.exe"/>
+	<param dst = "C:\sys\bin\fft.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_f64_22050hz" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\fft.exe"/>
+	<param parameters = "test_f64_22050hz"/>
+	<param result-file = "C:\LOGS\test_f64_22050hz.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstfft_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL NETBUFFER_test_netbuffer_copy" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstnetbuffer.exe"/>
+	<param dst = "C:\sys\bin\gstnetbuffer.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_FFT_test_next_fast_length" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstnetbuffer.exe"/>
+	<param parameters = "test_netbuffer_copy"/>
+	<param result-file = "C:\LOGS\test_netbuffer_copy.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\netbuffer_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL PBUTILS_test_pb_utils_init" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "pbutils.exe"/>
+	<param dst = "C:\sys\bin\pbutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PBUTILS_test_pb_utils_init" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\pbutils.exe"/>
+	<param parameters = "test_pb_utils_init"/>
+	<param result-file = "C:\LOGS\pbutils_test_pb_utils_init.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pbutils_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL PBUTILS_test_pb_utils_post_missing_messages" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "pbutils.exe"/>
+	<param dst = "C:\sys\bin\pbutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PBUTILS_test_pb_utils_post_missing_messages" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\pbutils.exe"/>
+	<param parameters = "test_pb_utils_post_missing_messages"/>
+	<param result-file = "C:\LOGS\pbutils_test_pb_utils_post_missing_messages.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pbutils_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL PBUTILS_test_pb_utils_taglist_add_codec_info" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "pbutils.exe"/>
+	<param dst = "C:\sys\bin\pbutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PBUTILS_test_pb_utils_taglist_add_codec_info" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\pbutils.exe"/>
+	<param parameters = "test_pb_utils_taglist_add_codec_info"/>
+	<param result-file = "C:\LOGS\pbutils_test_pb_utils_taglist_add_codec_info.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pbutils_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL PBUTILS_test_pb_utils_get_codec_description" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "pbutils.exe"/>
+	<param dst = "C:\sys\bin\pbutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PBUTILS_test_pb_utils_get_codec_description" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\pbutils.exe"/>
+	<param parameters = "test_pb_utils_get_codec_description"/>
+	<param result-file = "C:\LOGS\pbutils_test_pb_utils_get_codec_description.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pbutils_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL PBUTILS_test_pb_utils_install_plugins" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "pbutils.exe"/>
+	<param dst = "C:\sys\bin\pbutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PBUTILS_test_pb_utils_install_plugins" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\pbutils.exe"/>
+	<param parameters = "test_pb_utils_install_plugins"/>
+	<param result-file = "C:\LOGS\pbutils_test_pb_utils_install_plugins.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pbutils_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL PBUTILS_test_pb_utils_installer_details" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "pbutils.exe"/>
+	<param dst = "C:\sys\bin\pbutils.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute PBUTILS_test_pb_utils_installer_details" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\pbutils.exe"/>
+	<param parameters = "test_pb_utils_installer_details"/>
+	<param result-file = "C:\LOGS\pbutils_test_pb_utils_installer_details.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\pbutils_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL RTP_test_rtp_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_rtp.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_rtp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute RTP_test_rtp_buffer " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_rtp.exe"/>
+	<param parameters = "test_rtp_buffer"/>
+	<param result-file = "C:\LOGS\gst_rtp_test_rtp_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpad_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL RTP_test_rtp_buffer_set_extension_data" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_rtp.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_rtp.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute RTP_test_rtp_buffer_set_extension_data " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_rtp.exe"/>
+	<param parameters = "test_rtp_buffer_set_extension_data"/>
+	<param result-file = "C:\LOGS\gst_rtp_test_rtp_buffer_set_extension_data.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstpad_logs.txt"/>
+   </params>
+</step>
+>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL TAG_test_muscibrainz_tag_registration" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_tag.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute TAG_test_muscibrainz_tag_registration " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param parameters = "test_muscibrainz_tag_registration"/>
+	<param result-file = "C:\LOGS\test_muscibrainz_tag_registration.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL TAG_test_parse_extended_comment" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_tag.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute TAG_test_parse_extended_comment " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param parameters = "test_parse_extended_comment"/>
+	<param result-file = "C:\LOGS\test_parse_extended_comment.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+  </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL TAG_test_vorbis_tags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_tag.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute TAG_test_vorbis_tags " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param parameters = "test_vorbis_tags"/>
+	<param result-file = "C:\LOGS\test_vorbis_tags.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL TAG_test_id3_tags" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_tag.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute TAG_test_id3_tags " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param parameters = "test_id3_tags"/>
+	<param result-file = "C:\LOGS\test_id3_tags.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL TAG_test_id3v1_utf8_tag" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gst_plugin_tag.exe"/>
+	<param dst = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute TAG_test_id3v1_utf8_tag " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gst_plugin_tag.exe"/>
+	<param parameters = "test_id3v1_utf8_tag"/>
+	<param result-file = "C:\LOGS\test_id3v1_utf8_tag.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gsttag_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_AUDIO_test_channel_layout_value_intersect" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "taudio.exe"/>
+	<param dst = "C:\sys\bin\taudio.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_AUDIO_test_channel_layout_value_intersect" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\taudio.exe"/>
+	<param parameters = "test_channel_layout_value_intersect"/>
+	<param result-file = "C:\LOGS\test_channel_layout_value_intersect.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstaudio_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_AUDIO_test_buffer_clipping_samples" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "taudio.exe"/>
+	<param dst = "C:\sys\bin\taudio.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_AUDIO_test_buffer_clipping_samples" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\taudio.exe"/>
+	<param parameters = "test_buffer_clipping_samples"/>
+	<param result-file = "C:\LOGS\test_buffer_clipping_samples.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstaudio_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_AUDIO_test_buffer_clipping_time" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "taudio.exe"/>
+	<param dst = "C:\sys\bin\taudio.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_AUDIO_test_buffer_clipping_time" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\taudio.exe"/>
+	<param parameters = "test_buffer_clipping_time"/>
+	<param result-file = "C:\LOGS\test_buffer_clipping_time.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gstaudio_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL LIBS_AUDIO_test_multichannel_checks" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "taudio.exe"/>
+	<param dst = "C:\sys\bin\taudio.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute LIBS_AUDIO_test_multichannel_checks" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\taudio.exe"/>
+	<param parameters = "test_multichannel_checks"/>
+	<param result-file = "C:\LOGS\test_multichannel_checks.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL EXAMPLES_DYNAMIC_ADDSTREAM" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "addstream.exe"/>
+	<param dst = "C:\sys\bin\addstream.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute EXAMPLES_DYNAMIC_ADDSTREAM" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\addstream.exe"/>
+	<param result-file = "C:\LOGS\addstream.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_drop0" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_drop0" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_drop0"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_drop0.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_drop10" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_drop10" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_drop10"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_drop10.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_drop50" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_drop50" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_drop50"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_drop50.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_drop90" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_drop90" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_drop90"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_drop90.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_inject10" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_inject10" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_inject10"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_inject10.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_inject90" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_inject90" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_inject90"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_inject90.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_perfect_stream_drop45_inject25" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_perfect_stream_drop45_inject25" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_perfect_stream_drop45_inject25"/>
+	<param result-file = "C:\LOGS\audiorate_test_perfect_stream_drop45_inject25.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_AUDIORATE_test_large_discont" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiorate.exe"/>
+	<param dst = "C:\sys\bin\gstaudiorate.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_AUDIORATE_test_large_discont" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiorate.exe"/>
+	<param parameters = "test_large_discont"/>
+	<param result-file = "C:\LOGS\audiorate_test_large_discont.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiorate_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_ADDER_test_event" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadder.exe"/>
+	<param dst = "C:\sys\bin\gstadder.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_ADDER_test_event" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadder.exe"/>
+	<param parameters = "test_event"/>
+	<param result-file = "C:\LOGS\adder_test_event.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adder_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_ADDER_test_play_twice" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadder.exe"/>
+	<param dst = "C:\sys\bin\gstadder.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_ADDER_test_play_twice" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadder.exe"/>
+	<param parameters = "test_play_twice"/>
+	<param result-file = "C:\LOGS\adder_test_play_twice.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adder_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_ADDER_test_add_pad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadder.exe"/>
+	<param dst = "C:\sys\bin\gstadder.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_ADDER_test_add_pad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadder.exe"/>
+	<param parameters = "test_add_pad"/>
+	<param result-file = "C:\LOGS\adder_test_add_pad.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adder_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL ELEMENTS_ADDER_test_remove_pad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstadder.exe"/>
+	<param dst = "C:\sys\bin\gstadder.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute ELEMENTS_ADDER_test_remove_pad" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstadder.exe"/>
+	<param parameters = "test_remove_pad"/>
+	<param result-file = "C:\LOGS\adder_test_remove_pad.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\adder_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_no_clients" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_no_clients" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_no_clients"/>
+	<param result-file = "C:\LOGS\multifdsink_test_no_clients.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_add_client" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_add_client" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_add_client"/>
+	<param result-file = "C:\LOGS\multifdsink_test_add_client.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_streamheader" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_streamheader" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_streamheader"/>
+	<param result-file = "C:\LOGS\multifdsink_test_streamheader.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_change_streamheader" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_change_streamheader" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_change_streamheader"/>
+	<param result-file = "C:\LOGS\multifdsink_test_change_streamheader.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_burst_client_bytes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_burst_client_bytes" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_burst_client_bytes"/>
+	<param result-file = "C:\LOGS\multifdsink_test_burst_client_bytes.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_burst_client_bytes_keyframe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_burst_client_bytes_keyframe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_burst_client_bytes_keyframe"/>
+	<param result-file = "C:\LOGS\multifdsink_test_burst_client_bytes_keyframe.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_burst_client_bytes_with_keyframe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_burst_client_bytes_with_keyframe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_burst_client_bytes_with_keyframe"/>
+	<param result-file = "C:\LOGS\multifdsink_test_burst_client_bytes_with_keyframe.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL MULTIFDSINK_test_client_next_keyframe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "multifdsink.exe"/>
+	<param dst = "C:\sys\bin\multifdsink.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute MULTIFDSINK_test_client_next_keyframe" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\multifdsink.exe"/>
+	<param parameters = "test_client_next_keyframe"/>
+	<param result-file = "C:\LOGS\multifdsink_test_client_next_keyframe.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\multifdsink_logs.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_srt" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_srt" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_srt"/>
+	<param result-file = "C:\LOGS\subparse_test_srt.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_multiline" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_multiline" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_multiline"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_multiline.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_multiline_with_bogus_lines" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_multiline_with_bogus_lines" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_multiline_with_bogus_lines"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_multiline_with_bogus_lines.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_style1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_style1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_style1"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_style1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_style2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_style2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_style2"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_style2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_style3" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_style3" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_style3"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_style3.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_style4" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_style4" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_style4"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_style4.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_tmplayer_style4_with_bogus_lines" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_tmplayer_style4_with_bogus_lines" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_tmplayer_style4_with_bogus_lines"/>
+	<param result-file = "C:\LOGS\subparse_test_tmplayer_style4_with_bogus_lines.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_microdvd_with_fps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_microdvd_with_fps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_microdvd_with_fps"/>
+	<param result-file = "C:\LOGS\subparse_test_microdvd_with_fps.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_microdvd_with_italics" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_microdvd_with_italics" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_microdvd_with_italics"/>
+	<param result-file = "C:\LOGS\subparse_test_microdvd_with_italics.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_mpl2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_mpl2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_mpl2"/>
+	<param result-file = "C:\LOGS\subparse_test_mp12.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_subviewer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_subviewer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_subviewer"/>
+	<param result-file = "C:\LOGS\subparse_test_subviewer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_subviewer2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsubparse.exe"/>
+	<param dst = "C:\sys\bin\gstsubparse.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstsubparse_test_subviewer2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsubparse.exe"/>
+	<param parameters = "test_subviewer2"/>
+	<param result-file = "C:\LOGS\subparse_test_subviewer2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\subparse_log1.txt"/>
+   </params>
+</step>
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_unity_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_unity_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_unity_s8"/>
+	<param result-file = "C:\LOGS\volume_test_unity_s8.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_half_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_half_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_half_s8"/>
+	<param result-file = "C:\LOGS\volume_test_half_s8.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_double_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_double_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_double_s8"/>
+	<param result-file = "C:\LOGS\volume_test_double_s8.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_mute_s88" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_mute_s8" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_mute_s8"/>
+	<param result-file = "C:\LOGS\volume_test_mute_s8.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_unity_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_unity_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_unity_s16"/>
+	<param result-file = "C:\LOGS\volume_test_unity_s16.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_half_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_half_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_half_s16"/>
+	<param result-file = "C:\LOGS\volume_test_half_s16.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_double_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_double_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_double_s16"/>
+	<param result-file = "C:\LOGS\volume_test_double_s16.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_mute_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_mute_s16" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_mute_s16"/>
+	<param result-file = "C:\LOGS\volume_test_mute_s16.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_unity_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_unity_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_unity_s24"/>
+	<param result-file = "C:\LOGS\volume_test_unity_s24.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_half_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_half_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_half_s24"/>
+	<param result-file = "C:\LOGS\volume_test_half_s24.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_double_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_double_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_double_s24"/>
+	<param result-file = "C:\LOGS\volume_test_double_s24.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_mute_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_mute_s24" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_mute_s24"/>
+	<param result-file = "C:\LOGS\volume_test_mute_s24.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_unity_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_unity_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_unity_s32"/>
+	<param result-file = "C:\LOGS\volume_test_unity_s32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_half_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_half_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_half_s32"/>
+	<param result-file = "C:\LOGS\volume_test_half_s32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_double_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_double_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_double_s32"/>
+	<param result-file = "C:\LOGS\volume_test_double_s32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_mute_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_mute_s32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_mute_s32"/>
+	<param result-file = "C:\LOGS\volume_test_mute_s32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_unity_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_unity_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_unity_f32"/>
+	<param result-file = "C:\LOGS\volume_test_unity_f32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_half_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_half_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_half_f32"/>
+	<param result-file = "C:\LOGS\volume_test_half_f32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+   </step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_double_f328" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_double_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_double_f32"/>
+	<param result-file = "C:\LOGS\volume_test_double_f32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+  </params>
+</step>
+   <step id = "66.67.1.1.1.1" name = "INSTALL_test_mute_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_mute_f32" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_mute_f32"/>
+	<param result-file = "C:\LOGS\volume_test_mute_f32.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_unity_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_unity_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_unity_f64"/>
+	<param result-file = "C:\LOGS\volume_test_unity_f64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_half_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_half_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_half_f64"/>
+	<param result-file = "C:\LOGS\volume_test_half_f64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_double_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_double_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_double_f64"/>
+	<param result-file = "C:\LOGS\volume_test_double_f64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_mute_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_mute_f64" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_mute_f64"/>
+	<param result-file = "C:\LOGS\volume_test_mute_f64.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_wrong_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_wrong_caps" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_wrong_caps"/>
+	<param result-file = "C:\LOGS\volume_test_wrong_caps.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_passthrough" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_passthrough" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_passthrough"/>
+	<param result-file = "C:\LOGS\volume_test_passthrough.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_controller_usability" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "volume.exe"/>
+	<param dst = "C:\sys\bin\volume.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute volume_test_controller_usability" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\volume.exe"/>
+	<param parameters = "test_controller_usability"/>
+	<param result-file = "C:\LOGS\volume_test_controller_usability.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\volume_logs.txt"/>
+   </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install libgstdataprotocol.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdataprotocol.dll"/>
+     <param dst="c:\sys\bin\libgstdataprotocol.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_audio_per_byte" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gdpdepay.exe"/>
+	<param dst = "C:\sys\bin\gdpdepay.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gdpdepay_test_audio_per_byte" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gdpdepay.exe"/>
+	<param parameters = "test_audio_per_byte"/>
+	<param result-file = "C:\LOGS\gdpdepay_test_audio_per_byte.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdpdepay_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_audio_in_one_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gdpdepay.exe"/>
+	<param dst = "C:\sys\bin\gdpdepay.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gdpdepay_test_audio_in_one_buffer" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gdpdepay.exe"/>
+	<param parameters = "test_audio_in_one_buffer"/>
+	<param result-file = "C:\LOGS\gdpdepay_test_audio_in_one_buffer.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdpdepay_logs.txt"/>
+   </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_streamheader" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gdpdepay.exe"/>
+	<param dst = "C:\sys\bin\gdpdepay.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gdpdepay_test_streamheader" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gdpdepay.exe"/>
+	<param parameters = "test_streamheader"/>
+	<param result-file = "C:\LOGS\gdpdepay_test_streamheader.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\gdpdepay_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_perfect_stream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioresample.exe"/>
+	<param dst = "C:\sys\bin\gstaudioresample.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudiorate_test_perfect_stream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioresample.exe"/>
+	<param parameters = "test_perfect_stream"/>
+	<param result-file = "C:\LOGS\test_perfect_stream.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioresample_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "gstaudiorate_test_discont_stream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioresample.exe"/>
+	<param dst = "C:\sys\bin\gstaudioresample.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudiorate_test_discont_stream" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioresample.exe"/>
+	<param parameters = "test_discont_stream"/>
+	<param result-file = "C:\LOGS\test_discont_stream.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioresample_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "gstaudiorate_test_shutdown" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioresample.exe"/>
+	<param dst = "C:\sys\bin\gstaudioresample.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudiorate_test_shutdown" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioresample.exe"/>
+	<param parameters = "test_shutdown"/>
+	<param result-file = "C:\LOGS\test_shutdown.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioresample_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL gstaudiorate_test_reuse" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudioresample.exe"/>
+	<param dst = "C:\sys\bin\gstaudioresample.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudiorate_test_reuse" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudioresample.exe"/>
+	<param parameters = "test_reuse"/>
+	<param result-file = "C:\LOGS\test_reuse.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audioresample_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_all_waves" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstaudiotestsrc.exe"/>
+	<param dst = "C:\sys\bin\gstaudiotestsrc.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstaudiorate_test_all_waves" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstaudiotestsrc.exe"/>
+	<param parameters = "test_all_waves"/>
+	<param result-file = "C:\LOGS\test_all_waves.xml"/>
+	<param timeout ="900"/>
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\audiotestsrc_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_text_plain_streams" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstdecodebin.exe"/>
+	<param dst = "C:\sys\bin\gstdecodebin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstdecodebin_test_text_plain_streams" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstdecodebin.exe"/>
+	<param parameters = "test_text_plain_streams"/>
+	<param result-file = "C:\LOGS\test_text_plain_streams.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\decodebin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "gstdecodebin_test_reuse_without_decoders" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstdecodebin.exe"/>
+	<param dst = "C:\sys\bin\gstdecodebin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute gstdecodebin_test_reuse_without_decoders" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstdecodebin.exe"/>
+	<param parameters = "test_reuse_without_decoders"/>
+	<param result-file = "C:\LOGS\test_reuse_without_decoders.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\decodebin_logs.txt"/>
+   </params>
+</step>
+
+<!--<set id = "66.67.1.1" name = "playbin" harness = "ATSINTERFACE" enabled = "true" passrate = "100">
+<target>
+	<device rank = "master" alias = "default"/>
+</target>
+<case id = "66.67.1.1.1" name = "playbin.exe" harness = "ATSINTERFACE" enabled = "true" passrate = "100">
+<step id = "66.67.1.1.1.1" name = "INSTALL_test_missing_primary_decoder_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_missing_primary_decoder_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_missing_primary_decoder_decodebin1"/>
+	<param result-file = "C:\LOGS\test_missing_primary_decoder_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "playbin_test_perfect_stream_drop10" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_sink_usage_video_only_stream_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_sink_usage_video_only_stream_decodebin1"/>
+	<param result-file = "C:\LOGS\test_sink_usage_video_only_stream_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "playbin_test_sink_usage_video_only_stream_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_sink_usage_video_only_stream_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_sink_usage_video_only_stream_decodebin2"/>
+	<param result-file = "C:\LOGS\test_sink_usage_video_only_stream_decodebin2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_suburi_error_wrongproto_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_suburi_error_wrongproto_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_suburi_error_wrongproto_decodebin1"/>
+	<param result-file = "C:\LOGS\audioconvert_test_suburi_error_wrongproto_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_suburi_error_wrongproto_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_suburi_error_wrongproto_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_suburi_error_wrongproto_decodebin2"/>
+	<param result-file = "C:\LOGS\test_suburi_error_wrongproto_decodebin2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_suburi_error_invalidfile_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_suburi_error_invalidfile_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_suburi_error_invalidfile_decodebin1"/>
+	<param result-file = "C:\LOGS\test_suburi_error_invalidfile_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_suburi_error_invalidfile_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_suburi_error_invalidfile_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_suburi_error_invalidfile_decodebin2"/>
+	<param result-file = "C:\LOGS\test_suburi_error_invalidfile_decodebin2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_suburi_error_unknowntype_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_suburi_error_unknowntype_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_suburi_error_unknowntype_decodebin1"/>
+	<param result-file = "C:\LOGS\test_suburi_error_unknowntype_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_suburi_error_unknowntype_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_suburi_error_unknowntype_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_suburi_error_unknowntype_decodebin2"/>
+	<param result-file = "C:\LOGS\test_suburi_error_unknowntype_decodebin2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_missing_urisource_handler_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_missing_urisource_handler_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_missing_urisource_handler_decodebin1"/>
+	<param result-file = "C:\LOGS\test_missing_urisource_handler_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_missing_urisource_handler_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_missing_urisource_handler_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_missing_urisource_handler_decodebin2"/>
+	<param result-file = "C:\LOGS\test_missing_urisource_handler_decodebin2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_missing_suburisource_handler_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_missing_suburisource_handler_decodebin1" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_missing_suburisource_handler_decodebin1"/>
+	<param result-file = "C:\LOGS\test_missing_suburisource_handler_decodebin1.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL playbin_test_missing_suburisource_handler_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "playbin.exe"/>
+	<param dst = "C:\sys\bin\playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute playbin_test_missing_suburisource_handler_decodebin2" harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\playbin.exe"/>
+	<param parameters = "test_missing_suburisource_handler_decodebin2"/>
+	<param result-file = "C:\LOGS\test_missing_suburisource_handler_decodebin2.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\playbin_logs.txt"/>
+   </params>
+</step>
+
+</case>
+</set> -->
+
+
+
+
+<step id="66.67.1.3.2" name="Install warning.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="warning.wav"/>
+     <param dst="c:\data\gstreamer\test\warning.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "stress_playbin.exe"/>
+	<param dst = "C:\sys\bin\stress_playbin.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\stress_playbin.exe"/>
+	<param parameters = "c:\data\gstreamer\test"/>
+	<param result-file = "C:\LOGS\stress-playbin.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\stressplaybin_logs.txt"/>
+   </params>
+</step>
+
+
+
+
+<step id="66.67.1.3.2" name="Install warning.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="warning.wav"/>
+     <param dst="c:\data\gstreamer\test\warning.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gstsimple-launch-lines.exe"/>
+	<param dst = "C:\sys\bin\gstsimple-launch-lines.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gstsimple-launch-lines.exe"/>
+	<param parameters = "test_element_negotiation"/>
+	<param result-file = "C:\LOGS\simple-launch-lines_test_element_negotiation.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\simple-launch-lines_logs.txt"/>
+   </params>
+</step>
+
+
+<step id="66.67.1.3.2" name="Install warning.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="warning.wav"/>
+     <param dst="c:\data\gstreamer\test\warning.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id = "66.67.1.1.1.1" name = "INSTALL " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "false">
+ <command>install</command>
+  <params>
+	<param type = "binary"/>
+	<param src = "gststreamheader.exe"/>
+	<param dst = "C:\sys\bin\gststreamheader.exe"/>
+	<param component-path = "ATS3Drop"/>
+  </params>
+</step>
+<step id = "66.67.1.1.1.1" name = "Execute " harness = "ATSINTERFACE" enabled = "true" passrate = "100" significant = "true">
+ <command>execute</command>
+  <params>
+	<param file = "C:\sys\bin\gststreamheader.exe"/>
+	<param parameters = "test_multifdsink_gdp_tag"/>
+	<param result-file = "C:\LOGS\streamheader_test_multifdsink_gdp_tag.xml"/>
+	<param timeout ="900" />
+  </params>
+</step>
+<step id="66.67.1.1.1.1" name="Fetch Test module Logs" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+ <command>fetch-log</command>
+  <params>
+      <param type="text"/>
+	<param delete="true"/>
+	<param path="C:\Logs\streamheader_logs.txt"/>
+   </params>
+</step>
+
+<!-- dlls installation-->
+
+<step id="66.67.1.3.2" name="Install libgstadder.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstadder.dll"/>
+     <param dst="c:\sys\bin\libgstadder.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install libgstaudio.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstaudio.dll"/>
+     <param dst="c:\sys\bin\libgstaudio.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install libgstbase.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstbase.dll"/>
+     <param dst="c:\sys\bin\libgstbase.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install libgstcdda.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstcdda.dll"/>
+     <param dst="c:\sys\bin\libgstcdda.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstcontroller.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstcontroller.dll"/>
+     <param dst="c:\sys\bin\libgstcontroller.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstdataprotocol.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdataprotocol.dll"/>
+     <param dst="c:\sys\bin\libgstdataprotocol.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstdevsoundext.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdevsoundext.dll"/>
+     <param dst="c:\sys\bin\libgstdevsoundext.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstffmpegcolorspace.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstffmpegcolorspace.dll"/>
+     <param dst="c:\sys\bin\libgstffmpegcolorspace.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstfft.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstfft.dll"/>
+     <param dst="c:\sys\bin\libgstfft.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstgdp.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstgdp.dll"/>
+     <param dst="c:\sys\bin\libgstgdp.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstinterfaces.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstinterfaces.dll"/>
+     <param dst="c:\sys\bin\libgstinterfaces.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstnet.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstnet.dll"/>
+     <param dst="c:\sys\bin\libgstnet.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstnetbuffer.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstnetbuffer.dll"/>
+     <param dst="c:\sys\bin\libgstnetbuffer.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstpbutils.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstpbutils.dll"/>
+     <param dst="c:\sys\bin\libgstpbutils.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstreamer.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstreamer.dll"/>
+     <param dst="c:\sys\bin\libgstreamer.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstriff.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstriff.dll"/>
+     <param dst="c:\sys\bin\libgstriff.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstrtp.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstrtp.dll"/>
+     <param dst="c:\sys\bin\libgstrtp.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstsubparse.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstsubparse.dll"/>
+     <param dst="c:\sys\bin\libgstsubparse.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgsttag.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgsttag.dll"/>
+     <param dst="c:\sys\bin\libgsttag.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgsttag.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgsttag.dll"/>
+     <param dst="c:\sys\bin\libgsttag.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgsttag.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgsttag.dll"/>
+     <param dst="c:\sys\bin\libgsttag.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgsttcp.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgsttcp.dll"/>
+     <param dst="c:\sys\bin\libgsttcp.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<!--<step id="66.67.1.3.2" name="libgstvideo.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstvideo.dll"/>
+     <param dst="c:\sys\bin\libgstvideo.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstvideo.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstvideorate.dll"/>
+     <param dst="c:\sys\bin\libgstvideorate.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstvideoscale.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstvideoscale.dll"/>
+     <param dst="c:\sys\bin\libgstvideoscale.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstvideotestsrc.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstvideotestsrc.dll"/>
+     <param dst="c:\sys\bin\libgstvideotestsrc.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step> -->
+
+<step id="66.67.1.3.2" name="libgstvolume.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstvolume.dll"/>
+     <param dst="c:\sys\bin\libgstvolume.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstaudiorate.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstaudiorate.dll"/>
+     <param dst="c:\sys\bin\libgstaudiorate.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstaudioresample.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstaudioresample.dll"/>
+     <param dst="c:\sys\bin\libgstaudioresample.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstaudiotestsrc.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstaudiotestsrc.dll"/>
+     <param dst="c:\sys\bin\libgstaudiotestsrc.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstcoreelements.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstcoreelements.dll"/>
+     <param dst="c:\sys\bin\libgstcoreelements.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstcoreindexers.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstcoreindexers.dll"/>
+     <param dst="c:\sys\bin\libgstcoreindexers.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstdecodebin.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdecodebin.dll"/>
+     <param dst="c:\sys\bin\libgstdecodebin.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstdecodebin2.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdecodebin2.dll"/>
+     <param dst="c:\sys\bin\libgstdecodebin2.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstdevsoundsink.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdevsoundsink.dll"/>
+     <param dst="c:\sys\bin\libgstdevsoundsink.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstdevsoundsrc.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstdevsoundsrc.dll"/>
+     <param dst="c:\sys\bin\libgstdevsoundsrc.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstplaybin.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstplaybin.dll"/>
+     <param dst="c:\sys\bin\libgstplaybin.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgsttypefindfunctions.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgsttypefindfunctions.dll"/>
+     <param dst="c:\sys\bin\libgsttypefindfunctions.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstwavparse.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstwavparse.dll"/>
+     <param dst="c:\sys\bin\libgstwavparse.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstwavenc.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstwavenc.dll"/>
+     <param dst="c:\sys\bin\libgstwavenc.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstaudioconvert.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstaudioconvert.dll"/>
+     <param dst="c:\sys\bin\libgstaudioconvert.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstqueue2.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstqueue2.dll"/>
+     <param dst="c:\sys\bin\libgstqueue2.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="libgstautodetect.dll" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="libgstautodetect.dll"/>
+     <param dst="c:\sys\bin\libgstautodetect.dll"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<!--dlls installation complete-->
+
+<!--data files-->
+
+<step id="66.67.1.3.2" name="Install khuda.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="khuda.wav"/>
+     <param dst="C:\data\khuda.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install khuda1.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="khuda1.wav"/>
+     <param dst="C:\data\khuda1.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install crnival.mp3" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="crnival.mp3"/>
+     <param dst="C:\data\crnival.mp3"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
+
+<step id="66.67.1.3.2" name="Install warning.wav" harness="ATSINTERFACE" enabled="true" passrate="100" significant="false">
+<command>install</command>
+  <params>
+     <param type="data"/>
+     <param src="warning.wav"/>
+     <param dst="C:\data\warning.wav"/>
+     <param component-path="ATS3DROP"/>
+ </params>
+</step>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/Bwins/GstreamerTestCasesU.DEF	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	?LibEntryL@@YAPAVCScriptBase@@AAVCTestModuleIf@@@Z @ 1 NONAME ; class CScriptBase * LibEntryL(class CTestModuleIf &)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/EABI/GstreamerTestCasesU.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_Z9LibEntryLR13CTestModuleIf @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/conf/GstreamerTestCases.cfg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,969 @@
+[Test]
+title GSTRegistryGenerator
+create GstreamerTestCases foobar
+foobar Example GSTRegistryGenerator.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioconvert.exe	test_int_conversion
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe	test_int_conversion
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioconvert.exe test_int16
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe test_int16
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioconvert.exe test_float32
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe test_float32
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstaudioconvert.exe test_float_conversion
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe test_float_conversion
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstaudioconvert.exe test_multichannel_conversion
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe test_multichannel_conversion
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstaudioconvert.exe test_channel_remapping
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe test_channel_remapping
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstaudioconvert.exe test_caps_negotiation
+create GstreamerTestCases foobar
+foobar Example gstaudioconvert.exe test_caps_negotiation
+delete foobar
+[Endtest] 
+
+[Test]
+title clock-selection.exe test_add
+create GstreamerTestCases foobar
+foobar Example clock-selection.exe test_add
+delete foobar
+[Endtest] 
+
+[Test]
+title fft.exe test_next_fast_length
+create GstreamerTestCases foobar
+foobar Example fft.exe test_next_fast_length
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_s16_0hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_s16_0hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_s16_11025hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_s16_11025hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_s16_22050hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_s16_22050hz
+delete foobar
+[Endtest] 
+
+[Test]
+title fft.exe test_s32_0hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_s32_0hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_s32_11025hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_s32_11025hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_s32_22050hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_s32_22050hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_f32_0hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_f32_0hz
+delete foobar
+[Endtest] 
+
+[Test]
+title fft.exe test_f32_11025hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_f32_11025hz
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title fft.exe test_f32_22050hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_f32_22050hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_f64_0hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_f64_0hz
+delete foobar
+[Endtest] 
+
+
+[Test]
+title fft.exe test_f64_11025hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_f64_11025hz
+delete foobar
+[Endtest] 
+
+[Test]
+title fft.exe test_f64_22050hz
+create GstreamerTestCases foobar
+foobar Example fft.exe test_f64_22050hz
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstnetbuffer.exe test_netbuffer_copy
+create GstreamerTestCases foobar
+foobar Example gstnetbuffer.exe test_netbuffer_copy
+delete foobar
+[Endtest] 
+
+[Test]
+title pbutils.exe test_pb_utils_init
+create GstreamerTestCases foobar
+foobar Example pbutils.exe test_pb_utils_init
+delete foobar
+[Endtest] 
+
+[Test]
+title pbutils.exe test_pb_utils_post_missing_messages
+create GstreamerTestCases foobar
+foobar Example pbutils.exe test_pb_utils_post_missing_messages
+delete foobar
+[Endtest] 
+
+[Test]
+title pbutils.exe test_pb_utils_taglist_add_codec_info
+create GstreamerTestCases foobar
+foobar Example pbutils.exe test_pb_utils_taglist_add_codec_info
+delete foobar
+[Endtest] 
+
+
+[Test]
+title pbutils.exe test_pb_utils_get_codec_description
+create GstreamerTestCases foobar
+foobar Example pbutils.exe test_pb_utils_get_codec_description
+delete foobar
+[Endtest] 
+
+[Test]
+title pbutils.exe test_pb_utils_install_plugins
+create GstreamerTestCases foobar
+foobar Example pbutils.exe test_pb_utils_install_plugins
+delete foobar
+[Endtest] 
+
+[Test]
+title pbutils.exe test_pb_utils_installer_details
+create GstreamerTestCases foobar
+foobar Example pbutils.exe test_pb_utils_installer_details
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_rtp.exe test_rtp_buffer
+create GstreamerTestCases foobar
+foobar Example gst_plugin_rtp.exe test_rtp_buffer
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_rtp.exe test_rtp_buffer_set_extension_data
+create GstreamerTestCases foobar
+foobar Example gst_plugin_rtp.exe test_rtp_buffer_set_extension_data
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_tag.exe test_muscibrainz_tag_registration
+create GstreamerTestCases foobar
+foobar Example gst_plugin_tag.exe test_muscibrainz_tag_registration
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_tag.exe test_parse_extended_comment
+create GstreamerTestCases foobar
+foobar Example gst_plugin_tag.exe test_parse_extended_comment
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_tag.exe test_vorbis_tags
+create GstreamerTestCases foobar
+foobar Example gst_plugin_tag.exe test_vorbis_tags
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_tag.exe test_id3_tags
+create GstreamerTestCases foobar
+foobar Example gst_plugin_tag.exe test_id3_tags
+delete foobar
+[Endtest] 
+
+[Test]
+title gst_plugin_tag.exe test_id3v1_utf8_tag
+create GstreamerTestCases foobar
+foobar Example gst_plugin_tag.exe test_id3v1_utf8_tag
+delete foobar
+[Endtest] 
+
+[Test]
+title taudio.exe test_channel_layout_value_intersect
+create GstreamerTestCases foobar
+foobar Example taudio.exe test_channel_layout_value_intersect
+delete foobar
+[Endtest] 
+
+[Test]
+title taudio.exe test_buffer_clipping_samples
+create GstreamerTestCases foobar
+foobar Example taudio.exe test_buffer_clipping_samples
+delete foobar
+[Endtest] 
+
+[Test]
+title taudio.exe test_buffer_clipping_time
+create GstreamerTestCases foobar
+foobar Example taudio.exe test_buffer_clipping_time
+delete foobar
+[Endtest] 
+
+[Test]
+title taudio.exe test_multichannel_checks
+create GstreamerTestCases foobar
+foobar Example taudio.exe test_multichannel_checks
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_drop0
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_drop0
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_drop10
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_drop10
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_drop50
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_drop50
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_drop90
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_drop90
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_inject10
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_inject10
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_inject90
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_inject90
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_perfect_stream_drop45_inject25
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_perfect_stream_drop45_inject25
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiorate.exe test_large_discont
+create GstreamerTestCases foobar
+foobar Example gstaudiorate.exe test_large_discont
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstadder.exe test_event
+create GstreamerTestCases foobar
+foobar Example gstadder.exe test_event
+delete foobar
+[Endtest] 
+
+[Test]
+title gstadder.exe test_play_twice
+create GstreamerTestCases foobar
+foobar Example gstadder.exe test_play_twice
+delete foobar
+[Endtest] 
+
+[Test]
+title gstadder.exe test_add_pad
+create GstreamerTestCases foobar
+foobar Example gstadder.exe test_add_pad
+delete foobar
+[Endtest] 
+
+[Test]
+title gstadder.exe test_remove_pad
+create GstreamerTestCases foobar
+foobar Example gstadder.exe test_remove_pad
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_no_clients
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_no_clients
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_add_client
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_add_client
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_streamheader
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_streamheader
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_change_streamheader
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_change_streamheader
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_burst_client_bytes
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_burst_client_bytes
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_burst_client_bytes_keyframe
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_burst_client_bytes_keyframe
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_burst_client_bytes_with_keyframe
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_burst_client_bytes_with_keyframe
+delete foobar
+[Endtest] 
+
+[Test]
+title multifdsink.exe test_client_next_keyframe
+create GstreamerTestCases foobar
+foobar Example multifdsink.exe test_client_next_keyframe
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_srt
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_srt
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_tmplayer_multiline
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_multiline
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_tmplayer_multiline_with_bogus_lines
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_multiline_with_bogus_lines
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_tmplayer_style1
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_style1
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_tmplayer_style2
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_style2
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_tmplayer_style3
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_style3
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_tmplayer_style4
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_style4
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsubparse.exe test_tmplayer_style4_with_bogus_lines
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_tmplayer_style4_with_bogus_lines
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_microdvd_with_fps
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_microdvd_with_fps
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_microdvd_with_italics
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_microdvd_with_italics
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_mpl2
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_mpl2
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsubparse.exe test_subviewer
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_subviewer
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsubparse.exe test_subviewer2
+create GstreamerTestCases foobar
+foobar Example gstsubparse.exe test_subviewer2
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_unity_s8
+create GstreamerTestCases foobar
+foobar Example volume.exe test_unity_s8
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_half_s8
+create GstreamerTestCases foobar
+foobar Example volume.exe test_half_s8
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_double_s8
+create GstreamerTestCases foobar
+foobar Example volume.exe test_double_s8
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_mute_s8
+create GstreamerTestCases foobar
+foobar Example volume.exe test_mute_s8
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_unity_s16
+create GstreamerTestCases foobar
+foobar Example volume.exe test_unity_s16
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_half_s16
+create GstreamerTestCases foobar
+foobar Example volume.exe test_half_s16
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_double_s16
+create GstreamerTestCases foobar
+foobar Example volume.exe test_double_s16
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_mute_s16
+create GstreamerTestCases foobar
+foobar Example volume.exe test_mute_s16
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_unity_s24
+create GstreamerTestCases foobar
+foobar Example volume.exe test_unity_s24
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_half_s24
+create GstreamerTestCases foobar
+foobar Example volume.exe test_half_s24
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_double_s24
+create GstreamerTestCases foobar
+foobar Example volume.exe test_double_s24
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_mute_s24
+create GstreamerTestCases foobar
+foobar Example volume.exe test_mute_s24
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_unity_s32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_unity_s32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_half_s32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_half_s32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_double_s32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_double_s32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_mute_s32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_mute_s32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_unity_f32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_unity_f32
+delete foobar
+[Endtest] 
+
+
+[Test]
+title volume.exe test_half_f32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_half_f32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_double_f32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_double_f32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_mute_f32
+create GstreamerTestCases foobar
+foobar Example volume.exe test_mute_f32
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_unity_f64
+create GstreamerTestCases foobar
+foobar Example volume.exe test_unity_f64
+delete foobar
+[Endtest] 
+
+
+[Test]
+title volume.exe test_half_f64
+create GstreamerTestCases foobar
+foobar Example volume.exe test_half_f64
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_double_f64
+create GstreamerTestCases foobar
+foobar Example volume.exe test_double_f64
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_mute_f64
+create GstreamerTestCases foobar
+foobar Example volume.exe test_mute_f64
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_wrong_caps
+create GstreamerTestCases foobar
+foobar Example volume.exe test_wrong_caps
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_passthrough
+create GstreamerTestCases foobar
+foobar Example volume.exe test_passthrough
+delete foobar
+[Endtest] 
+
+[Test]
+title volume.exe test_controller_usability
+create GstreamerTestCases foobar
+foobar Example volume.exe test_controller_usability
+delete foobar
+[Endtest] 
+
+[Test]
+title gdpdepay.exe test_audio_per_byte
+create GstreamerTestCases foobar
+foobar Example gdpdepay.exe test_audio_per_byte
+delete foobar
+[Endtest] 
+
+[Test]
+title gdpdepay.exe test_audio_in_one_buffer
+create GstreamerTestCases foobar
+foobar Example gdpdepay.exe test_audio_in_one_buffer
+delete foobar
+[Endtest] 
+
+[Test]
+title gdpdepay.exe test_streamheader
+create GstreamerTestCases foobar
+foobar Example gdpdepay.exe test_streamheader
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioresample.exe test_perfect_stream
+create GstreamerTestCases foobar
+foobar Example gstaudioresample.exe test_perfect_stream
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioresample.exe test_discont_stream
+create GstreamerTestCases foobar
+foobar Example gstaudioresample.exe test_discont_stream
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioresample.exe test_shutdown
+create GstreamerTestCases foobar
+foobar Example gstaudioresample.exe test_shutdown
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudioresample.exe test_reuse
+create GstreamerTestCases foobar
+foobar Example gstaudioresample.exe test_reuse
+delete foobar
+[Endtest] 
+
+[Test]
+title gstaudiotestsrc.exe test_all_waves
+create GstreamerTestCases foobar
+foobar Example gstaudiotestsrc.exe test_all_waves
+delete foobar
+[Endtest] 
+
+[Test]
+title gstdecodebin.exe test_text_plain_streams
+create GstreamerTestCases foobar
+foobar Example gstdecodebin.exe test_text_plain_streams
+delete foobar
+[Endtest] 
+
+[Test]
+title gstdecodebin.exe test_reuse_without_decoders
+create GstreamerTestCases foobar
+foobar Example gstdecodebin.exe test_reuse_without_decoders
+delete foobar
+[Endtest] 
+
+[Test]
+title stress_playbin.exe 
+create GstreamerTestCases foobar
+foobar Example stress_playbin.exe c:\\data\\gstreamer\\gsttestfiles
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsimple-launch-lines.exe test_element_negotiation
+create GstreamerTestCases foobar
+foobar Example gstsimple-launch-lines.exe test_element_negotiation
+delete foobar
+[Endtest] 
+
+[Test]
+title gststreamheader.exe test_multifdsink_gdp_tag
+create GstreamerTestCases foobar
+foobar Example gststreamheader.exe test_multifdsink_gdp_tag
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstadapter.exe test_peek1
+create GstreamerTestCases foobar
+foobar Example gstadapter.exe test_peek1
+delete foobar
+[Endtest] 
+
+[Test]
+title gstadapter.exe test_take_order
+create GstreamerTestCases foobar
+foobar Example gstadapter.exe test_take_order
+delete foobar
+[Endtest] 
+
+[Test]
+title gstadapter.exe test_take_buf_order
+create GstreamerTestCases foobar
+foobar Example gstadapter.exe test_take_buf_order
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbasesrc.exe basesrc_eos_events_pull
+create GstreamerTestCases foobar
+foobar Example gstbasesrc.exe basesrc_eos_events_pull
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbasesrc.exe basesrc_eos_events_push
+create GstreamerTestCases foobar
+foobar Example gstbasesrc.exe basesrc_eos_events_push
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbasesrc.exe basesrc_eos_events_push_live_op
+create GstreamerTestCases foobar
+foobar Example gstbasesrc.exe basesrc_eos_events_push_live_op
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbasesrc.exe basesrc_eos_events_pull_live_op
+create GstreamerTestCases foobar
+foobar Example gstbasesrc.exe basesrc_eos_events_pull_live_op
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbasesrc.exe basesrc_eos_events_push_live_eos
+create GstreamerTestCases foobar
+foobar Example gstbasesrc.exe basesrc_eos_events_push_live_eos
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbasesrc.exe basesrc_eos_events_pull_live_eos
+create GstreamerTestCases foobar
+foobar Example gstbasesrc.exe basesrc_eos_events_pull_live_eos
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgdp.exe test_conversion
+create GstreamerTestCases foobar
+foobar Example gstgdp.exe test_conversion
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgdp.exe test_buffer
+create GstreamerTestCases foobar
+foobar Example gstgdp.exe test_buffer
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgdp.exe test_caps
+create GstreamerTestCases foobar
+foobar Example gstgdp.exe test_caps
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgdp.exe test_event
+create GstreamerTestCases foobar
+foobar Example gstgdp.exe test_event
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgdp.exe test_memory
+create GstreamerTestCases foobar
+foobar Example gstgdp.exe test_memory
+delete foobar
+[Endtest] 
+
+[Test]
+title gstlibsabi.exe test_ABI
+create GstreamerTestCases foobar
+foobar Example gstlibsabi.exe test_ABI
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgstnetclientclock.exe test_instantiation
+create GstreamerTestCases foobar
+foobar Example gstgstnetclientclock.exe test_instantiation
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgstnetclientclock.exe test_functioning
+create GstreamerTestCases foobar
+foobar Example gstgstnetclientclock.exe test_functioning
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgstnettimeprovider.exe test_refcounts
+create GstreamerTestCases foobar
+foobar Example gstgstnettimeprovider.exe test_refcounts
+delete foobar
+[Endtest] 
+
+[Test]
+title gstgstnettimeprovider.exe test_functioning
+create GstreamerTestCases foobar
+foobar Example gstgstnettimeprovider.exe test_functioning
+delete foobar
+[Endtest] 
+
+[Test]
+title gsttypefindhelper.exe test_buffer_range
+create GstreamerTestCases foobar
+foobar Example gsttypefindhelper.exe test_buffer_range
+delete foobar
+[Endtest] 
+
+[Test]
+title stress.exe test_stress_preroll
+create GstreamerTestCases foobar
+foobar Example stress.exe test_stress_preroll
+delete foobar
+[Endtest] 
+
+[Test]
+title stress.exe test_stress
+create GstreamerTestCases foobar
+foobar Example stress.exe test_stress
+delete foobar
+[Endtest] 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/group/GstreamerTestCases.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/*TYPE TESTCLASS*/
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+TARGET          GstreamerTestCases.dll
+TARGETTYPE      dll
+UID             0x1000008D 0x101FB3E3
+
+CAPABILITY      ALL -TCB
+/* Remove comments and replace 0x00000000 with correct vendor id */
+// VENDORID     0x00000000
+/* Remove comments and replace 0x00000000 with correct secure id */
+// SECUREID     0x00000000
+
+//TARGETPATH      ?target_path
+//DEFFILE         GstreamerTestCases.def
+
+USERINCLUDE     ../inc 
+
+OS_LAYER_SYSTEMINCLUDE
+
+SOURCEPATH      ../src
+
+SOURCE          GstreamerTestCases.cpp
+SOURCE          GstreamerTestCasesBlocks.cpp
+
+//RESOURCE        resource_file
+//RESOURCE        resource_file2
+
+LIBRARY         euser.lib
+LIBRARY         stiftestinterface.lib
+LIBRARY         stiftestengine.lib
+
+LANG            SC
+
+/*
+START WINS      
+?wins_specific_information
+END
+
+START MARM
+?marm_specific_information
+END
+*/
+// Other possible keywords:
+ 
+// DOCUMENT     ?file, that is not compiled, but added to MSVC project workspace (i.e. release notes)
+/*
+START BITMAP ?target
+TARGETPATH   ?emulated_path_on_target_machine
+HEADER
+SOURCE       ?color_depth ?source_bitmap
+END
+*/
+// DEFFILE ?filename
+// AIF ?filename
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/group/GstreamerTestCases_DoxyFile.txt	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,239 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+# 
+# Description:
+#
+#
+
+# Doxyfile 1.4.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = GstreamerTestCases
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = \GstreamerTestCases\
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = NO
+GENERATE_TESTLIST      = NO
+GENERATE_BUGLIST       = NO
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = \GstreamerTestCases\
+FILE_PATTERNS          = *.h \
+                         *.rh \
+                         *.hrh
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = NO
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = YES
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = YES
+TOC_EXPAND             = YES
+DISABLE_INDEX          = YES
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = YES
+RTF_OUTPUT             = Doc
+COMPACT_RTF            = YES
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = NONSHARABLE_CLASS
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+PRJ_PLATFORMS
+// specify the platforms your component needs to be built for here
+// defaults to WINS MARM so you can ignore this if you just build these
+	
+	DEFAULT
+
+PRJ_TESTEXPORTS
+// NOTE: If using ARS requirements all export operations should be done under this.
+// 'abld test export'
+
+../conf/GstreamerTestCases.cfg   /epoc32/winscw/c/TestFramework/GstreamerTestCases.cfg
+../init/GstreamerTestCases.ini   /epoc32/winscw/c/TestFramework/GstreamerTestCases.ini
+
+PRJ_EXPORTS
+// Specify the source file followed by its destination here
+// copy will be used to copy the source file to its destination
+// If there's no destination then the source file will be copied
+// to the same name in \epoc32\include
+// Example: 
+/*
+\agnmodel\inc\AGMCOMON.H
+*/
+
+PRJ_TESTMMPFILES
+
+	GstreamerTestCases.mmp
+
+PRJ_MMPFILES
+
+	// GstreamerTestCases_nrm.mmp
+
+// Specify the .mmp files required for building the important component
+// releasables.
+//
+// Specify "tidy" if the component you need to build doesn't need to be
+// released. Specify "ignore" if the MMP file exists but should be
+// ignored.
+// Example:
+/*
+\agnmodel\group\agnmodel.mmp
+#if defined(MARM)
+\agnmodel\group\agsvexe.mmp
+#endif
+*/
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/group/gstreamer_testcases.pkg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,212 @@
+; ============================================================================
+;  Name        : gstreamer_testcases.pkg
+;  Part of     : Gstreamer project
+;  Description : Package file for all gstreamer test binaries
+;
+;  Version     : %version: 2 %
+;
+;  Copyright © 2002-2006 Nokia.  All rights reserved.
+;  This material, including documentation and any related computer
+;  programs, is protected by copyright controlled by Nokia.  All
+;  rights are reserved.  Copying, including reproducing, storing,
+;  adapting or translating, any or all of this material requires the
+;  prior written consent of Nokia.  This material also contains
+;  confidential information which may not be disclosed to others
+;  without the prior written consent of Nokia.
+; ============================================================================
+
+;Languages
+&EN
+
+;Header
+#{"gstreamer_testcases.pkg"},(0x2001F45C),1,0,0, TYPE=SU
+
+;Supports S60 3.0
+[0x101F7961], 0, 0, 0, {"S60ProductID"}
+
+;Localised Vendor name
+%{"Nokia Testing EN"}
+
+;Unique Vendor name
+:"Vendor"
+
+
+;gstreamer dll
+
+"\epoc32\winscw\c\gstreamer\plugins_list\gst_dll_2001F41F.txt" - "c:\gstreamer\plugins_list\gst_dll_2001F41F.txt"
+"\epoc32\release\armv5\urel\libgstadder.dll"-"!:\sys\bin\libgstadder.dll"
+"\epoc32\release\armv5\urel\libgstaudio.dll"-"!:\sys\bin\libgstaudio.dll"
+"\epoc32\release\armv5\urel\libgstbase.dll"-"!:\sys\bin\libgstbase.dll"
+"\epoc32\release\armv5\urel\libgstcdda.dll"-"!:\sys\bin\libgstcdda.dll"
+"\epoc32\release\armv5\urel\libgstcontroller.dll"-"!:\sys\bin\libgstcontroller.dll"
+"\epoc32\release\armv5\urel\libgstdataprotocol.dll"-"!:\sys\bin\libgstdataprotocol.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundext.dll"-"!:\sys\bin\libgstdevsoundext.dll"
+"\epoc32\release\armv5\urel\libgstfft.dll"-"!:\sys\bin\libgstfft.dll"
+"\epoc32\release\armv5\urel\libgstgdp.dll"-"!:\sys\bin\libgstgdp.dll"
+"\epoc32\release\armv5\urel\libgstinterfaces.dll"-"!:\sys\bin\libgstinterfaces.dll"
+"\epoc32\release\armv5\urel\libgstnet.dll"-"!:\sys\bin\libgstnet.dll"
+"\epoc32\release\armv5\urel\libgstnetbuffer.dll"-"!:\sys\bin\libgstnetbuffer.dll"
+"\epoc32\release\armv5\urel\libgstpbutils.dll"-"!:\sys\bin\libgstpbutils.dll"
+"\epoc32\release\armv5\urel\libgstreamer.dll"-"!:\sys\bin\libgstreamer.dll"
+"\epoc32\release\armv5\urel\libgstriff.dll"-"!:\sys\bin\libgstriff.dll"
+"\epoc32\release\armv5\urel\libgstrtp.dll"-"!:\sys\bin\libgstrtp.dll"
+"\epoc32\release\armv5\urel\libgstsubparse.dll"-"!:\sys\bin\libgstsubparse.dll"
+"\epoc32\release\armv5\urel\libgsttag.dll"-"!:\sys\bin\libgsttag.dll"
+"\epoc32\release\armv5\urel\libgsttcp.dll"-"!:\sys\bin\libgsttcp.dll"
+"\epoc32\release\armv5\urel\libgstvolume.dll"-"!:\sys\bin\libgstvolume.dll"
+"\epoc32\release\armv5\urel\libgstaudiorate.dll"-"!:\sys\bin\libgstaudiorate.dll"
+"\epoc32\release\armv5\urel\libgstaudioresample.dll"-"!:\sys\bin\libgstaudioresample.dll"
+"\epoc32\release\armv5\urel\libgstaudiotestsrc.dll"-"!:\sys\bin\libgstaudiotestsrc.dll"
+"\epoc32\release\armv5\urel\libgstcoreelements.dll"-"!:\sys\bin\libgstcoreelements.dll"
+"\epoc32\release\armv5\urel\libgstcoreindexers.dll"-"!:\sys\bin\libgstcoreindexers.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin.dll"-"!:\sys\bin\libgstdecodebin.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin2.dll"-"!:\sys\bin\libgstdecodebin2.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsink.dll"-"!:\sys\bin\libgstdevsoundsink.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsrc.dll"-"!:\sys\bin\libgstdevsoundsrc.dll"
+"\epoc32\release\armv5\urel\libgstplaybin.dll"-"!:\sys\bin\libgstplaybin.dll"
+"\epoc32\release\armv5\urel\libgsttypefindfunctions.dll"-"!:\sys\bin\libgsttypefindfunctions.dll"
+"\epoc32\release\armv5\urel\libgstwavparse.dll"-"!:\sys\bin\libgstwavparse.dll"
+"\epoc32\release\armv5\urel\libgstwavenc.dll"-"!:\sys\bin\libgstwavenc.dll"
+"\epoc32\release\armv5\urel\libgstaudioconvert.dll"-"!:\sys\bin\libgstaudioconvert.dll"
+"\epoc32\release\armv5\urel\libgstqueue2.dll"-"!:\sys\bin\libgstqueue2.dll"
+"\epoc32\release\armv5\urel\libgstapp.dll"-"!:\sys\bin\libgstapp.dll"
+"\epoc32\release\armv5\urel\libgstautodetect.dll"-"!:\sys\bin\libgstautodetect.dll"
+"\epoc32\release\armv5\urel\liboil.dll"-"!:\sys\bin\liboil.dll"
+"\epoc32\release\armv5\urel\GstreamerTestCases.dll"-"!:\sys\bin\GstreamerTestCases.dll"
+;"\epoc32\release\armv5\urel\libgstvideo.dll"-"!:\sys\bin\libgstvideo.dll"
+;"\epoc32\release\armv5\urel\libgstvideorate.dll"-"!:\sys\bin\libgstvideorate.dll"
+;"\epoc32\release\armv5\urel\libgstvideoscale.dll"-"!:\sys\bin\libgstvideoscale.dll"
+;"\epoc32\release\armv5\urel\libgstvideotestsrc.dll"-"!:\sys\bin\libgstvideotestsrc.dll"
+;"\epoc32\release\armv5\urel\libgstffmpegcolorspace.dll"-"!:\sys\bin\libgstffmpegcolorspace.dll"
+
+
+;gstregistry exe
+
+"\epoc32\release\armv5\urel\GSTRegistryGenerator.exe"		  -"!:\sys\bin\GSTRegistryGenerator.exe",FR,RI
+
+;gstreamer-core test exe's
+
+"\epoc32\release\armv5\urel\cleanup.exe"-"!:\sys\bin\cleanup.exe"
+"\epoc32\release\armv5\urel\createelementcore.exe"-"!:\sys\bin\createelementcore.exe"
+"\epoc32\release\armv5\urel\element_gstfakesink.exe"-"!:\sys\bin\element_gstfakesink.exe"
+"\epoc32\release\armv5\urel\element_gstfakesrc.exe"-"!:\sys\bin\element_gstfakesrc.exe"
+"\epoc32\release\armv5\urel\element_gstfdsrc.exe"-"!:\sys\bin\element_gstfdsrc.exe"
+"\epoc32\release\armv5\urel\element_gstfilesink.exe"-"!:\sys\bin\element_gstfilesink.exe"
+"\epoc32\release\armv5\urel\element_gstfilesrc.exe"-"!:\sys\bin\element_gstfilesrc.exe"
+"\epoc32\release\armv5\urel\element_gstidentity.exe"-"!:\sys\bin\element_gstidentity.exe"
+"\epoc32\release\armv5\urel\element_gstmultiqueue.exe"-"!:\sys\bin\element_gstmultiqueue.exe"
+"\epoc32\release\armv5\urel\element_gstqueue.exe"-"!:\sys\bin\element_gstqueue.exe"
+"\epoc32\release\armv5\urel\element_gsttee.exe"-"!:\sys\bin\element_gsttee.exe"
+"\epoc32\release\armv5\urel\gst.exe"-"!:\sys\bin\gst.exe"
+"\epoc32\release\armv5\urel\gstadapter.exe"-"!:\sys\bin\gstadapter.exe"
+"\epoc32\release\armv5\urel\gstbasesrc.exe"-"!:\sys\bin\gstbasesrc.exe"
+"\epoc32\release\armv5\urel\gstbin.exe"-"!:\sys\bin\gstbin.exe"
+"\epoc32\release\armv5\urel\gstbuffer.exe"-"!:\sys\bin\gstbuffer.exe"
+"\epoc32\release\armv5\urel\gstbus.exe"-"!:\sys\bin\gstbus.exe"
+"\epoc32\release\armv5\urel\gstcaps.exe"-"!:\sys\bin\gstcaps.exe"
+"\epoc32\release\armv5\urel\gstcollectpads.exe"-"!:\sys\bin\gstcollectpads.exe"
+"\epoc32\release\armv5\urel\gstcontroller.exe"-"!:\sys\bin\gstcontroller.exe"
+"\epoc32\release\armv5\urel\gstelement.exe"-"!:\sys\bin\gstelement.exe"
+"\epoc32\release\armv5\urel\gstevent.exe"-"!:\sys\bin\gstevent.exe"
+"\epoc32\release\armv5\urel\gstgdp.exe"-"!:\sys\bin\gstgdp.exe"
+"\epoc32\release\armv5\urel\gstghostpad.exe"-"!:\sys\bin\gstghostpad.exe"
+"\epoc32\release\armv5\urel\gstgstnetclientclock.exe"-"!:\sys\bin\gstgstnetclientclock.exe"
+"\epoc32\release\armv5\urel\gstgstnettimeprovider.exe"-"!:\sys\bin\gstgstnettimeprovider.exe"
+"\epoc32\release\armv5\urel\gstindex.exe"-"!:\sys\bin\gstindex.exe"
+"\epoc32\release\armv5\urel\gstinterface.exe"-"!:\sys\bin\gstinterface.exe"
+"\epoc32\release\armv5\urel\gstiterator.exe"-"!:\sys\bin\gstiterator.exe"
+"\epoc32\release\armv5\urel\gstlibsabi.exe"-"!:\sys\bin\gstlibsabi.exe"
+"\epoc32\release\armv5\urel\gstmessage.exe"-"!:\sys\bin\gstmessage.exe"
+"\epoc32\release\armv5\urel\gstminiobject.exe"-"!:\sys\bin\gstminiobject.exe"
+"\epoc32\release\armv5\urel\gstobject.exe"-"!:\sys\bin\gstobject.exe"
+"\epoc32\release\armv5\urel\gstpad.exe"-"!:\sys\bin\gstpad.exe"
+"\epoc32\release\armv5\urel\gstparamspecs.exe"-"!:\sys\bin\gstparamspecs.exe"
+"\epoc32\release\armv5\urel\gstpipeline.exe"-"!:\sys\bin\gstpipeline.exe"
+"\epoc32\release\armv5\urel\gstplugin.exe"-"!:\sys\bin\gstplugin.exe"
+"\epoc32\release\armv5\urel\gstpoll.exe"-"!:\sys\bin\gstpoll.exe"
+"\epoc32\release\armv5\urel\gstquery.exe"-"!:\sys\bin\gstquery.exe"
+"\epoc32\release\armv5\urel\gstregistry.exe"-"!:\sys\bin\gstregistry.exe"
+"\epoc32\release\armv5\urel\gstsegment.exe"-"!:\sys\bin\gstsegment.exe"
+"\epoc32\release\armv5\urel\gstsinks.exe"-"!:\sys\bin\gstsinks.exe"
+"\epoc32\release\armv5\urel\gststates.exe"-"!:\sys\bin\gststates.exe"
+"\epoc32\release\armv5\urel\gststructure.exe"-"!:\sys\bin\gststructure.exe"
+"\epoc32\release\armv5\urel\gstsystemclock.exe"-"!:\sys\bin\gstsystemclock.exe"
+"\epoc32\release\armv5\urel\gsttag.exe"-"!:\sys\bin\gsttag.exe"
+"\epoc32\release\armv5\urel\gsttagsetter.exe"-"!:\sys\bin\gsttagsetter.exe"
+"\epoc32\release\armv5\urel\gsttask.exe"-"!:\sys\bin\gsttask.exe"
+"\epoc32\release\armv5\urel\gsttypefindhelper.exe"-"!:\sys\bin\gsttypefindhelper.exe"
+"\epoc32\release\armv5\urel\gsturi.exe"-"!:\sys\bin\gsturi.exe"
+"\epoc32\release\armv5\urel\gstutils.exe"-"!:\sys\bin\gstutils.exe"
+"\epoc32\release\armv5\urel\gstvalue.exe"-"!:\sys\bin\gstvalue.exe"
+"\epoc32\release\armv5\urel\helloworld.exe"-"!:\sys\bin\helloworld.exe"
+"\epoc32\release\armv5\urel\launch.exe"-"!:\sys\bin\launch.exe"
+"\epoc32\release\armv5\urel\manual_dynamic.exe"-"!:\sys\bin\manual_dynamic.exe"
+"\epoc32\release\armv5\urel\manual_ghostpad.exe"-"!:\sys\bin\manual_ghostpad.exe"
+"\epoc32\release\armv5\urel\manual_gstbin.exe"-"!:\sys\bin\manual_gstbin.exe"
+"\epoc32\release\armv5\urel\manual_gstdecodebin.exe"-"!:\sys\bin\manual_gstdecodebin.exe"
+"\epoc32\release\armv5\urel\manual_gstelementcreate.exe"-"!:\sys\bin\manual_gstelementcreate.exe"
+"\epoc32\release\armv5\urel\manual_gstelementfactory.exe"-"!:\sys\bin\manual_gstelementfactory.exe"
+"\epoc32\release\armv5\urel\manual_gstelementget.exe"-"!:\sys\bin\manual_gstelementget.exe"
+"\epoc32\release\armv5\urel\manual_gstelementlink.exe"-"!:\sys\bin\manual_gstelementlink.exe"
+"\epoc32\release\armv5\urel\manual_gstelementmake.exe"-"!:\sys\bin\manual_gstelementmake.exe"
+"\epoc32\release\armv5\urel\manual_gstinit.exe"-"!:\sys\bin\manual_gstinit.exe"
+"\epoc32\release\armv5\urel\manual_gstpad.exe"-"!:\sys\bin\manual_gstpad.exe"
+"\epoc32\release\armv5\urel\manual_gstplaybin.exe"-"!:\sys\bin\manual_gstplaybin.exe"
+"\epoc32\release\armv5\urel\manual_gstquery.exe"-"!:\sys\bin\manual_gstquery.exe"
+"\epoc32\release\armv5\urel\manual_helloworld.exe"-"!:\sys\bin\manual_helloworld.exe"
+"\epoc32\release\armv5\urel\manual_typefind.exe"-"!:\sys\bin\manual_typefind.exe"
+"\epoc32\release\armv5\urel\metadata.exe"-"!:\sys\bin\metadata.exe"
+"\epoc32\release\armv5\urel\mp3launch.exe"-"!:\sys\bin\mp3launch.exe"
+"\epoc32\release\armv5\urel\parse-disabled.exe"-"!:\sys\bin\parse-disabled.exe"
+"\epoc32\release\armv5\urel\parse-launch.exe"-"!:\sys\bin\parse-launch.exe"
+"\epoc32\release\armv5\urel\simple-launch-lines.exe"-"!:\sys\bin\simple-launch-lines.exe"
+"\epoc32\release\armv5\urel\stress.exe"-"!:\sys\bin\stress.exe"
+"\epoc32\release\armv5\urel\testaudioexample.exe"-"!:\sys\bin\testaudioexample.exe"
+"\epoc32\release\armv5\urel\testgstadapter.exe"-"!:\sys\bin\testgstadapter.exe"
+"\epoc32\release\armv5\urel\testqueue.exe"-"!:\sys\bin\testqueue.exe"
+"\epoc32\release\armv5\urel\typefind.exe"-"!:\sys\bin\typefind.exe"
+
+
+
+;gst_plugins_base test exe's
+
+"\epoc32\release\armv5\urel\gstadder.exe"-"!:\sys\bin\gstadder.exe"
+"\epoc32\release\armv5\urel\gstaudioconvert.exe"-"!:\sys\bin\gstaudioconvert.exe"
+"\epoc32\release\armv5\urel\gstaudiorate.exe"-"!:\sys\bin\gstaudiorate.exe"
+"\epoc32\release\armv5\urel\gstaudioresample.exe"-"!:\sys\bin\gstaudioresample.exe"
+"\epoc32\release\armv5\urel\gstaudiotestsrc.exe"-"!:\sys\bin\gstaudiotestsrc.exe"
+"\epoc32\release\armv5\urel\createelementbase.exe"-"!:\sys\bin\createelementbase.exe"
+"\epoc32\release\armv5\urel\gstdecodebin.exe"-"!:\sys\bin\gstdecodebin.exe"
+"\epoc32\release\armv5\urel\gdpdepay.exe"-"!:\sys\bin\gdpdepay.exe"
+"\epoc32\release\armv5\urel\multifdsink.exe"-"!:\sys\bin\multifdsink.exe"
+"\epoc32\release\armv5\urel\playbin.exe"-"!:\sys\bin\playbin.exe"
+"\epoc32\release\armv5\urel\gstsubparse.exe"-"!:\sys\bin\gstsubparse.exe"
+"\epoc32\release\armv5\urel\volume.exe"-"!:\sys\bin\volume.exe"
+"\epoc32\release\armv5\urel\clock-selection.exe"-"!:\sys\bin\clock-selection.exe"
+"\epoc32\release\armv5\urel\states.exe"-"!:\sys\bin\states.exe"
+"\epoc32\release\armv5\urel\fft.exe"-"!:\sys\bin\fft.exe"
+;"\epoc32\release\armv5\urel\gstnetbuffer.exe"-"!:\sys\bin\gstnetbuffer.exe"
+"\epoc32\release\armv5\urel\pbutils.exe"-"!:\sys\bin\pbutils.exe"
+"\epoc32\release\armv5\urel\gst_plugin_rtp.exe"-"!:\sys\bin\gst_plugin_rtp.exe"
+"\epoc32\release\armv5\urel\gst_plugin_tag.exe"-"!:\sys\bin\gst_plugin_tag.exe"
+"\epoc32\release\armv5\urel\taudio.exe"-"!:\sys\bin\taudio.exe"
+"\epoc32\release\armv5\urel\gstsimple-launch-lines.exe"-"!:\sys\bin\gstsimple-launch-lines.exe"
+"\epoc32\release\armv5\urel\gststreamheader.exe"-"!:\sys\bin\gststreamheader.exe"
+"\epoc32\release\armv5\urel\stress_playbin.exe"-"!:\sys\bin\stress_playbin.exe"
+
+;"\epoc32\release\armv5\urel\ffmpegcolorspace.exe"-"!:\sys\bin\ffmpegcolorspace.exe"
+;"\epoc32\release\armv5\urel\addstream.exe"-"!:\sys\bin\addstream.exe"
+;"\epoc32\release\armv5\urel\video.exe"-"!:\sys\bin\video.exe"
+;"\epoc32\release\armv5\urel\typefindfunctions.exe" -"!:\sys\bin\typefindfunctions.exe"
+;"\epoc32\release\armv5\urel\videorate.exe"-"!:\sys\bin\videorate.exe"
+
+
+
+;dependecy files
+
+
+;Testframework.ini and conf files
+
+"..\conf\GStreamerTestCases.cfg"-"c:\TestFramework\GStreamerTestCases.cfg"
+"..\init\GStreamerTestCases.ini"-"c:\TestFramework\GStreamerTestCases.ini"
+"..\init\TestFramework.ini"-"c:\TestFramework\TestFramework.ini"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/inc/GstreamerTestCases.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,190 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: STIF testclass declaration
+*
+*/
+
+
+#ifndef GSTREAMERTESTCASES_H
+#define GSTREAMERTESTCASES_H
+
+//  INCLUDES
+#include <StifLogger.h>
+#include <TestScripterInternal.h>
+#include <StifTestModule.h>
+#include <TestclassAssert.h>
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+#define TEST_CLASS_VERSION_MAJOR 0
+#define TEST_CLASS_VERSION_MINOR 0
+#define TEST_CLASS_VERSION_BUILD 0
+
+// Logging path
+_LIT( KGstreamerTestCasesLogPath, "\\logs\\testframework\\GstreamerTestCases\\" ); 
+// Log file
+_LIT( KGstreamerTestCasesLogFile, "GstreamerTestCases.htm" ); 
+_LIT( KGstreamerTestCasesLogFileWithTitle, "GstreamerTestCases_[%S].htm" );
+
+// FUNCTION PROTOTYPES
+//?type ?function_name(?arg_list);
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+class CGstreamerTestCases;
+
+// DATA TYPES
+//enum ?declaration
+//typedef ?declaration
+//extern ?data_type;
+
+// CLASS DECLARATION
+
+/**
+*  CGstreamerTestCases test class for STIF Test Framework TestScripter.
+*  ?other_description_lines
+*
+*  @lib ?library
+*  @since ?Series60_version
+*/
+NONSHARABLE_CLASS(CGstreamerTestCases) : public CScriptBase
+    {
+    public:  // Constructors and destructor
+
+        /**
+        * Two-phased constructor.
+        */
+        static CGstreamerTestCases* NewL( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * Destructor.
+        */
+        virtual ~CGstreamerTestCases();
+
+    public: // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    public: // Functions from base classes
+
+        /**
+        * From CScriptBase Runs a script line.
+        * @since ?Series60_version
+        * @param aItem Script line containing method name and parameters
+        * @return Symbian OS error code
+        */
+        virtual TInt RunMethodL( CStifItemParser& aItem );
+
+    protected:  // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    protected:  // Functions from base classes
+
+        /**
+        * From ?base_class ?member_description
+        */
+        //?type ?member_function();
+
+    private:
+
+        /**
+        * C++ default constructor.
+        */
+        CGstreamerTestCases( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * By default Symbian 2nd phase constructor is private.
+        */
+        void ConstructL();
+
+        // Prohibit copy constructor if not deriving from CBase.
+        // ?classname( const ?classname& );
+        // Prohibit assigment operator if not deriving from CBase.
+        // ?classname& operator=( const ?classname& );
+
+        /**
+        * Frees all resources allocated from test methods.
+        * @since ?Series60_version
+        */
+        void Delete();
+
+        /**
+        * Test methods are listed below. 
+        */
+
+        /**
+        * Example test method.
+        * @since ?Series60_version
+        * @param aItem Script line containing parameters.
+        * @return Symbian OS error code.
+        */
+        virtual TInt ExampleL( CStifItemParser& aItem );
+        
+        /**
+         * Method used to log version of test class
+         */
+        void SendTestClassVersion();
+
+        //ADD NEW METHOD DEC HERE
+        //[TestMethods] - Do not remove
+
+    public:     // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    protected:  // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    private:    // Data
+        
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+        // Reserved pointer for future extension
+        //TAny* iReserved;
+
+    public:     // Friend classes
+        //?friend_class_declaration;
+    protected:  // Friend classes
+        //?friend_class_declaration;
+    private:    // Friend classes
+        //?friend_class_declaration;
+
+    };
+
+#endif      // GSTREAMERTESTCASES_H
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/init/gstreamertestcases.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+[general]
+logFileName GStreamerTestCases.log
+logPath c:\logs\
+[general_end]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/init/testframework.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,184 @@
+#
+# This is STIFTestFramework initialization file
+# Comment lines start with '#'-character.
+# See STIF TestFramework users guide.doc for instructions
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set following test engine settings:
+#   - Set Test Reporting mode. TestReportMode's possible values are:
+#       + 'Summary': Summary of the tested test cases.
+#       + 'Environment': Hardware and software info.
+#       + 'TestCases': Test case report.
+#       + 'FullReport': Set of all above ones.
+#       + Example 'TestReportMode= Summary TestCases'
+#
+#   - CreateTestReport setting controls report creation mode
+#       + YES, Test report will created.
+#       + NO, No Test report.
+#
+#   - File path indicates the base path of the test report.
+#   - File name indicates the name of the test report.
+#
+#   - File format indicates the type of the test report.
+#       + TXT, Test report file will be txt type, for example 'TestReport.txt'.
+#       + HTML, Test report will be html type, for example 'TestReport.html'.
+#
+#   - File output indicates output source of the test report.
+#       + FILE, Test report logging to file.
+#       + RDEBUG, Test report logging to using rdebug.
+#
+#   - File Creation Mode indicates test report overwriting if file exist.
+#       + OVERWRITE, Overwrites if the Test report file exist.
+#       + APPEND, Continue logging after the old Test report information if
+#                 report exist.
+#   - Sets a device reset module's dll name(Reboot).
+#       + If Nokia specific reset module is not available or it is not correct one
+#         StifHWResetStub module may use as a template for user specific reset
+#         module.
+
+[Engine_Defaults]
+
+TestReportMode= FullReport      # Possible values are: 'Empty', 'Summary', 'Environment',
+                                                               'TestCases' or 'FullReport'
+
+CreateTestReport= YES           # Possible values: YES or NO
+
+TestReportFilePath= C:\LOGS\TestFramework\
+TestReportFileName= TestReport_GStreamerTestCases
+
+TestReportFormat= HTML          # Possible values: TXT or HTML
+TestReportOutput= FILE          # Possible values: FILE or RDEBUG
+TestReportFileCreationMode= OVERWRITE   # Possible values: OVERWRITE or APPEND
+
+DeviceResetDllName= StifResetForNokia.dll # e.g. 'StifHWResetStub.dll' for user specific reseting
+
+[End_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Module configurations start
+# Modules are added between module tags
+# tags. Module name is specified after ModuleName= tag, like
+# ModuleName= XXXXXXXXX
+# Modules might have initialisation file, specified as
+# IniFile= c:\testframework\YYYYYY
+# Modules might have several configuration files, like
+# TestCaseFile= c:\testframework\NormalCases.txt
+# TestCaseFile= c:\testframework\SmokeCases.txt
+# TestCaseFile= c:\testframework\ManualCases.txt
+
+# (TestCaseFile is synonym for old term ConfigFile)
+
+# Following case specifies demo module settings. Demo module
+# does not read any settings from file, so tags
+# IniFile and TestCaseFile are not used.
+# In the simplest case it is enough to specify only the
+# name of the test module when adding new test module
+
+#[New_Module]
+#ModuleName= demomodule
+#[End_Module]
+
+
+[New_Module]
+ModuleName= TestScripter
+TestCaseFile= c:\testframework\GstreamerTestCases.cfg
+IniFile= c:\testframework\GStreamerTestCases.ini
+[End_Module]
+
+# Load testmoduleXXX, optionally with initialization file and/or test case files
+#[New_Module]
+#ModuleName= testmodulexxx
+
+#TestModuleXXX used initialization file
+#IniFile= c:\testframework\init.txt
+
+#TestModuleXXX used configuration file(s)
+#TestCaseFile= c:\testframework\testcases1.cfg
+#TestCaseFile= c:\testframework\testcases2.cfg
+#TestCaseFile= c:\testframework\manualtestcases.cfg
+
+#[End_Module]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set STIFTestFramework logging overwrite parameters for Logger.
+#   Hardware and emulator environment logging path and styles can
+#   be configured from here to overwrite the Logger's implemented values.
+#
+#   Settings description:
+#   - Indicates option for creation log directory/directories. If log directory/directories
+#         is/are not created by user they will make by software.
+#       + YES, Create log directory/directories if not allready exist.
+#       + NO, Log directory/directories not created. Only created one is used.
+#
+#   - Overwrite emulator path setting.
+#       + Example: If 'EmulatorBasePath= C:\LOGS\TestFramework\' and in code is defined
+#                  Logger's path 'D:\\LOGS\\Module\\' with those definition the path
+#                  will be 'C:\LOGS\TestFramework\LOGS\Module\'
+#
+#   - Overwrite emulator's logging format.
+#       + TXT, Log file(s) will be txt type(s), for example 'Module.txt'.
+#       + HTML, Log file(s) will be html type(s), for example 'Module.html'.
+#
+#   - Overwrited emulator logging output source.
+#       + FILE, Logging to file(s).
+#       + RDEBUG, Logging to using rdebug(s).
+#
+#   - Overwrite hardware path setting (Same description as above in emulator path).
+#   - Overwrite hardware's logging format(Same description as above in emulator format).
+#   - Overwrite hardware's logging output source(Same description as above in emulator output).
+#
+#   - File Creation Mode indicates file overwriting if file exist.
+#       + OVERWRITE, Overwrites if file(s) exist.
+#       + APPEND, Continue logging after the old logging information if file(s) exist.
+#
+#   - Will thread id include to the log filename.
+#       + YES, Thread id to log file(s) name, Example filename 'Module_b9.txt'.
+#       + NO, No thread id to log file(s), Example filename 'Module.txt'.
+#
+#   - Will time stamps include the to log file.
+#       + YES, Time stamp added to each line in log file(s). Time stamp is
+#                 for example'12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No time stamp(s).
+#
+#   - Will line breaks include to the log file.
+#       + YES, Each logging event includes line break and next log event is in own line.
+#       + NO, No line break(s).
+#
+#   - Will event ranking include to the log file.
+#       + YES, Event ranking number added to each line in log file(s). Ranking number
+#                 depends on environment's tics, for example(includes time stamp also)
+#                 '012   12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No event ranking.
+#
+
+[Logger_Defaults]
+
+#NOTE: If you want to set Logger using next setting(s) remove comment(s)'#'
+
+#CreateLogDirectories= YES      # Possible values: YES or NO
+
+#EmulatorBasePath= C:\LOGS\TestFramework\
+#EmulatorFormat= HTML           # Possible values: TXT or HTML
+#EmulatorOutput= FILE           # Possible values: FILE or RDEBUG
+
+#HardwareBasePath= D:\LOGS\TestFramework\
+#HardwareFormat= HTML           # Possible values: TXT or HTML
+#HardwareOutput= FILE           # Possible values: FILE or RDEBUG
+
+#FileCreationMode= OVERWRITE        # Possible values: OVERWRITE or APPEND
+
+#ThreadIdToLogFile= YES             # Possible values: YES or NO
+#WithTimeStamp= YES             # Possible values: YES or NO
+#WithLineBreak= YES             # Possible values: YES or NO
+#WithEventRanking= YES          # Possible values: YES or NO
+
+[End_Logger_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+# End of file
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/src/GstreamerTestCases.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,204 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// INCLUDE FILES
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+#include <SettingServerClient.h>
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::CGstreamerTestCases
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases::CGstreamerTestCases( 
+    CTestModuleIf& aTestModuleIf ):
+        CScriptBase( aTestModuleIf )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::ConstructL()
+    {
+    //Read logger settings to check whether test case name is to be
+    //appended to log file name.
+    RSettingServer settingServer;
+    TInt ret = settingServer.Connect();
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        }
+    // Struct to StifLogger settigs.
+    TLoggerSettings loggerSettings; 
+    // Parse StifLogger defaults from STIF initialization file.
+    ret = settingServer.GetLoggerSettings(loggerSettings);
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        } 
+    // Close Setting server session
+    settingServer.Close();
+
+    TFileName logFileName;
+    
+    if(loggerSettings.iAddTestCaseTitle)
+        {
+        TName title;
+        TestModuleIf().GetTestCaseTitleL(title);
+        logFileName.Format(KGstreamerTestCasesLogFileWithTitle, &title);
+        }
+    else
+        {
+        logFileName.Copy(KGstreamerTestCasesLogFile);
+        }
+
+    iLog = CStifLogger::NewL( KGstreamerTestCasesLogPath, 
+                          logFileName,
+                          CStifLogger::ETxt,
+                          CStifLogger::EFile,
+                          EFalse );
+    
+    SendTestClassVersion();
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases* CGstreamerTestCases::NewL( 
+    CTestModuleIf& aTestModuleIf )
+    {
+    CGstreamerTestCases* self = new (ELeave) CGstreamerTestCases( aTestModuleIf );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+
+    }
+
+// Destructor
+CGstreamerTestCases::~CGstreamerTestCases()
+    { 
+
+    // Delete resources allocated from test methods
+    Delete();
+
+    // Delete logger
+    delete iLog; 
+
+    }
+
+//-----------------------------------------------------------------------------
+// CGstreamerTestCases::SendTestClassVersion
+// Method used to send version of test class
+//-----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::SendTestClassVersion()
+	{
+	TVersion moduleVersion;
+	moduleVersion.iMajor = TEST_CLASS_VERSION_MAJOR;
+	moduleVersion.iMinor = TEST_CLASS_VERSION_MINOR;
+	moduleVersion.iBuild = TEST_CLASS_VERSION_BUILD;
+	
+	TFileName moduleName;
+	moduleName = _L("GstreamerTestCases.dll");
+
+	TBool newVersionOfMethod = ETrue;
+	TestModuleIf().SendTestModuleVersion(moduleVersion, moduleName, newVersionOfMethod);
+	}
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// -----------------------------------------------------------------------------
+// LibEntryL is a polymorphic Dll entry point.
+// Returns: CScriptBase: New CScriptBase derived object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CScriptBase* LibEntryL( 
+    CTestModuleIf& aTestModuleIf ) // Backpointer to STIF Test Framework
+    {
+
+    return ( CScriptBase* ) CGstreamerTestCases::NewL( aTestModuleIf );
+
+    }
+
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases/src/GstreamerTestCasesBlocks.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,237 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// [INCLUDE FILES] - do not remove
+#include <e32svr.h>
+#include <StifParser.h>
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::Delete
+// Delete here all resources allocated and opened from test methods. 
+// Called from destructor. 
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::Delete() 
+    {
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::RunMethodL
+// Run specified method. Contains also table of test mothods and their names.
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::RunMethodL( 
+    CStifItemParser& aItem ) 
+    {
+
+    static TStifFunctionInfo const KFunctions[] =
+        {  
+        // Copy this line for every implemented function.
+        // First string is the function name used in TestScripter script file.
+        // Second is the actual implementation member function. 
+        ENTRY( "Example", CGstreamerTestCases::ExampleL ),
+        //ADD NEW ENTRY HERE
+        // [test cases entries] - Do not remove
+
+        };
+
+    const TInt count = sizeof( KFunctions ) / 
+                        sizeof( TStifFunctionInfo );
+
+    return RunInternalL( KFunctions, count, aItem );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ExampleL
+// Example test method function.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::ExampleL( CStifItemParser& aItem )
+{
+    TInt err = KErrNone;
+    RTimer timeoutTimer;
+    // Print to UI
+//    _LIT( KGstreamerTestCases, "GstreamerTestCases" );
+//    _LIT( KExample, "Test case: " );
+//    TestModuleIf().Printf( 0, KGstreamerTestCases, KExample );
+    // Print to log file
+
+    TPtrC string[2];
+    TFileName arg;
+    //_LIT( KParam, "Param[%i]: %S" );
+    
+    if( aItem.GetNextString ( string[0] ) != KErrNone)
+    {
+        iLog->Log( _L(">> Test cases Not Found") );
+        return -1;
+    }
+    iLog->Log( _L( "Test case Name is : " ) );
+    iLog->Log( string[0] );
+    
+    while ( aItem.GetNextString ( string[1] ) == KErrNone )
+    {
+        iLog->Log( string[1] );
+        arg.Append( string[1] );
+        arg.Append( TChar(' ') );
+    }
+    
+    
+    _LIT( KArg, "Arg: " );
+    iLog->Log( KArg );
+    iLog->Log( arg );
+    RProcess process;
+    err = process.Create( string[0],arg );
+    
+    if( !err )
+    {
+
+        if( timeoutTimer.CreateLocal() != KErrNone )
+        {
+            iLog->Log( _L(">> timeoutTimer.CreateLocal failed") );
+        }
+    
+        iLog->Log( _L(">> Test cases Started") );
+        TRequestStatus processStatus = KRequestPending;
+        TRequestStatus timerStatus = KRequestPending;
+        process.Logon( processStatus );
+        
+        process.Resume();
+        TTimeIntervalMicroSeconds32 timeout = 1 * 60 * 1000000;
+        timeoutTimer.After( timerStatus, timeout );
+        
+        while( processStatus == KRequestPending && timerStatus == KRequestPending )
+        {
+            User::WaitForAnyRequest();
+            
+        }
+        
+        err = process.ExitReason();
+        if( timerStatus != KRequestPending )
+        {
+            err = KErrTimedOut;
+        }
+        
+        process.LogonCancel( processStatus );
+        timeoutTimer.Cancel();
+        /// required to complete one of the pending request..
+        User::WaitForAnyRequest();
+        
+        process.Kill( KErrNone );
+        process.Close();
+        timeoutTimer.Close();
+        iLog->Log( _L(">> test cases completed") );
+    }
+    else
+    {
+        iLog->Log( _L(">> test cases exe not found") );
+    }
+
+
+    if( err != KErrNone )
+    {
+        iLog->Log( CStifLogger::ERed, _L( "Test cases FAILED!" ) );
+    }
+    else
+    {
+        iLog->Log( CStifLogger::EGreen, _L( "Test cases PASSED!" ) );
+    }
+    
+
+    return err;
+}
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+/*
+TInt CGstreamerTestCases::?member_function(
+   CItemParser& aItem )
+   {
+
+   ?code
+
+   }
+*/
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+// None
+
+//  [End of File] - Do not remove
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/Bwins/gstreamertestcases_suite1u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	?LibEntryL@@YAPAVCScriptBase@@AAVCTestModuleIf@@@Z @ 1 NONAME ; class CScriptBase * LibEntryL(class CTestModuleIf &)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/EABI/gstreamertestcases_suite1u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_Z9LibEntryLR13CTestModuleIf @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/conf/gstreamertestcases_suite1.cfg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,989 @@
+[Test]
+title testgstadapter.exe 
+create gstreamertestcases_suite1 foobar
+foobar Example testgstadapter.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title launch.exe C:\\data\\khuda.wav
+create gstreamertestcases_suite1 foobar
+foobar Example launch.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstbin.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstbin.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstelementcreate.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstelementcreate.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstdecodebin.exe C:\\data\\khuda.wav
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstdecodebin.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstelementget.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstelementget.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstinit.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstinit.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstelementlink.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstelementlink.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstelementmake.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstelementmake.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_ghostpad.exe 
+create gstreamertestcases_suite1 foobar
+foobar Example manual_ghostpad.exe 
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_typefind.exe C:\\data\\khuda.wav
+create gstreamertestcases_suite1 foobar
+foobar Example manual_typefind.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstpad.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstpad.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstplaybin.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstplaybin.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstelementfactory.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstelementfactory.exe
+delete foobar
+[Endtest] 
+
+[Test]
+title typefind.exe C:\\data\\khuda.wav
+create gstreamertestcases_suite1 foobar
+foobar Example typefind.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title metadata.exe C:\\data\\khuda.wav
+create gstreamertestcases_suite1 foobar
+foobar Example metadata.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title testaudioexample.exe
+create gstreamertestcases_suite1 foobar
+foobar Example testaudioexample.exe
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsinks.exe test_sink
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_sink
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_sink_completion
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_sink_completion
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_src_sink
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_src_sink
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_livesrc_remove
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_livesrc_remove
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsinks.exe test_locked_sink
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_locked_sink
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_unlinked_live
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_unlinked_live
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_delayed_async
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_delayed_async
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_added_async
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_added_async
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_added_async2
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_added_async2
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_add_live
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_add_live
+delete foobar
+[Endtest] 
+
+[Test]
+title gstsinks.exe test_bin_live
+create gstreamertestcases_suite1 foobar
+foobar Example gstsinks.exe test_bin_live
+delete foobar
+[Endtest] 
+
+[Test]
+title gststates.exe test_state_changes_up_and_down_seq
+create gstreamertestcases_suite1 foobar
+foobar Example gststates.exe test_state_changes_up_and_down_seq
+delete foobar
+[Endtest] 
+
+[Test]
+title gststates.exe test_state_changes_up_seq
+create gstreamertestcases_suite1 foobar
+foobar Example gststates.exe test_state_changes_up_seq
+delete foobar
+[Endtest] 
+
+[Test]
+title gststates.exe test_state_changes_down_seq
+create gstreamertestcases_suite1 foobar
+foobar Example gststates.exe test_state_changes_down_seq
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_gstquery.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_gstquery.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_dynamic.exe
+create gstreamertestcases_suite1 foobar
+foobar Example manual_dynamic.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title element_gsttee.exe test_num_buffers
+create gstreamertestcases_suite1 foobar
+foobar Example element_gsttee.exe test_num_buffers
+delete foobar
+[Endtest] 
+
+[Test]
+title element_gsttee.exe test_stress
+create gstreamertestcases_suite1 foobar
+foobar Example element_gsttee.exe test_stress
+delete foobar
+[Endtest] 
+
+[Test]
+title cleanup.exe test_pipeline_unref
+create gstreamertestcases_suite1 foobar
+foobar Example cleanup.exe test_pipeline_unref
+delete foobar
+[Endtest] 
+
+[Test]
+title parse-disabled.exe test_parse_launch_errors
+create gstreamertestcases_suite1 foobar
+foobar Example parse-disabled.exe test_parse_launch_errors
+delete foobar
+[Endtest] 
+
+[Test]
+title simple-launch-lines.exe test_2_elements
+create gstreamertestcases_suite1 foobar
+foobar Example simple-launch-lines.exe test_2_elements
+delete foobar
+[Endtest] 
+
+[Test]
+title simple-launch-lines.exe test_state_change_returns
+create gstreamertestcases_suite1 foobar
+foobar Example simple-launch-lines.exe test_state_change_returns
+delete foobar
+[Endtest] 
+
+[Test]
+title simple-launch-lines.exe test_stop_from_app
+create gstreamertestcases_suite1 foobar
+foobar Example simple-launch-lines.exe test_stop_from_app
+delete foobar
+[Endtest] 
+
+[Test]
+title manual_helloworld.exe C:\\data\\khuda.wav
+create gstreamertestcases_suite1 foobar
+foobar Example manual_helloworld.exe C:\\data\\khuda.wav
+delete foobar
+[Endtest] 
+
+[Test]
+title gstmessage.exe	test_parsing
+create gstreamertestcases_suite1 foobar
+foobar Example gstmessage.exe	test_parsing
+delete foobar
+[Endtest] 
+
+[Test]
+title gstminiobject.exe test_copy
+create gstreamertestcases_suite1 foobar
+foobar Example gstminiobject.exe test_copy
+delete foobar
+[Endtest] 
+
+[Test]
+title gstminiobject.exe test_is_writable
+create gstreamertestcases_suite1 foobar
+foobar Example gstminiobject.exe test_is_writable
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstminiobject.exe test_make_writable
+create gstreamertestcases_suite1 foobar
+foobar Example gstminiobject.exe test_make_writable
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstminiobject.exe test_ref_threaded
+create gstreamertestcases_suite1 foobar
+foobar Example gstminiobject.exe test_ref_threaded
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstminiobject.exe test_unref_threaded
+create gstreamertestcases_suite1 foobar
+foobar Example gstminiobject.exe test_unref_threaded
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstminiobject.exe test_value_collection
+create gstreamertestcases_suite1 foobar
+foobar Example gstminiobject.exe test_value_collection
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbus.exe test_hammer_bus
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_hammer_bus
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbus.exe test_watch
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_watch
+delete foobar
+[Endtest] 
+
+[Test]
+title gstbus.exe test_watch_with_poll
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_watch_with_poll
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbus.exe test_timed_pop
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_timed_pop
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbus.exe test_timed_pop_thread
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_timed_pop_thread
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbus.exe test_timed_pop_filtered
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_timed_pop_filtered
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbus.exe test_timed_pop_filtered_with_timeout
+create gstreamertestcases_suite1 foobar
+foobar Example gstbus.exe test_timed_pop_filtered_with_timeout
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbuffer.exe test_caps
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_caps
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbuffer.exe test_subbuffer
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_subbuffer
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbuffer.exe test_subbuffer_make_writable
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_subbuffer_make_writable
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbuffer.exe test_make_writable
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_make_writable
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbuffer.exe test_is_span_fast
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_is_span_fast
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbuffer.exe test_span
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_span
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbuffer.exe test_metadata_writable
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_metadata_writable
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbuffer.exe test_copy
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_copy
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbuffer.exe test_try_new_and_alloc
+create gstreamertestcases_suite1 foobar
+foobar Example gstbuffer.exe test_try_new_and_alloc
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpad.exe test_link
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_link
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpad.exe test_refcount
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_refcount
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_get_allowed_caps
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_get_allowed_caps
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_link_unlink_threaded
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_link_unlink_threaded
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_name_is_valid
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_name_is_valid
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_push_unlinked
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_push_unlinked
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_push_linked
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_push_linked
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_flowreturn
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_flowreturn
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_push_negotiation
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_push_negotiation
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_src_unref_unlink
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_src_unref_unlink
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpad.exe test_sink_unref_unlink
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_sink_unref_unlink
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstpad.exe test_get_caps_must_be_copy
+create gstreamertestcases_suite1 foobar
+foobar Example gstpad.exe test_get_caps_must_be_copy
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gst.exe test_init
+create gstreamertestcases_suite1 foobar
+foobar Example gst.exe test_init
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gst.exe test_deinit
+create gstreamertestcases_suite1 foobar
+foobar Example gst.exe test_deinit
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gst.exe test_deinit_sysclock
+create gstreamertestcases_suite1 foobar
+foobar Example gst.exe test_deinit_sysclock
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gst.exe test_new_pipeline
+create gstreamertestcases_suite1 foobar
+foobar Example gst.exe test_new_pipeline
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gst.exe test_new_fakesrc
+create gstreamertestcases_suite1 foobar
+foobar Example gst.exe test_new_fakesrc
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gst.exe test_version
+create gstreamertestcases_suite1 foobar
+foobar Example gst.exe test_version
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstevent.exe create_events
+create gstreamertestcases_suite1 foobar
+foobar Example gstevent.exe create_events
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstevent.exe send_custom_events
+create gstreamertestcases_suite1 foobar
+foobar Example gstevent.exe send_custom_events
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstelement.exe test_add_remove_pad
+create gstreamertestcases_suite1 foobar
+foobar Example gstelement.exe test_add_remove_pad
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstelement.exe test_add_pad_unref_element
+create gstreamertestcases_suite1 foobar
+foobar Example gstelement.exe test_add_pad_unref_element
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstelement.exe test_error_no_bus
+create gstreamertestcases_suite1 foobar
+foobar Example gstelement.exe test_error_no_bus
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstelement.exe test_link
+create gstreamertestcases_suite1 foobar
+foobar Example gstelement.exe test_link
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstelement.exe test_link_no_pads
+create gstreamertestcases_suite1 foobar
+foobar Example gstelement.exe test_link_no_pads
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstelement.exe test_class
+create gstreamertestcases_suite1 foobar
+foobar Example gstelement.exe test_class
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstghostpad.exe test_remove1
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_remove1
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstghostpad.exe test_remove2
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_remove2
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads_notarget
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads_notarget
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstghostpad.exe test_link
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_link
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads
+delete foobar
+[Endtest] 
+
+
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads_bin
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads_bin
+delete foobar
+[Endtest] 
+
+
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads_block
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads_block
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads_probes
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads_probes
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads_new_from_template
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads_new_from_template
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstghostpad.exe test_ghost_pads_new_no_target_from_template
+create gstreamertestcases_suite1 foobar
+foobar Example gstghostpad.exe test_ghost_pads_new_no_target_from_template
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstbin.exe test_message_state_changed_children
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_message_state_changed_children
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_watch_for_state_change
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_watch_for_state_change
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_add_linked
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_add_linked
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_add_self
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_add_self
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_iterate_sorted
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_iterate_sorted
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_children_state_change_order_flagged_sink
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_children_state_change_order_flagged_sink
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_children_state_change_order_semi_sink
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_children_state_change_order_semi_sink
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_children_state_change_order_two_sink
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_children_state_change_order_two_sink
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_message_state_changed
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_message_state_changed
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_interface
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_interface
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstbin.exe test_message_state_changed_child
+create gstreamertestcases_suite1 foobar
+foobar Example gstbin.exe test_message_state_changed_child
+delete foobar
+[Endtest] 
+
+[Test]
+title gstobject.exe test_fake_object_new
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fake_object_new
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstobject.exe test_fake_object_name
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fake_object_name
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstobject.exe test_fake_object_name_threaded_right
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fake_object_name_threaded_right
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstobject.exe test_fake_object_name_threaded_unique
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fake_object_name_threaded_unique
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstobject.exe test_fake_object_parentage
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fake_object_parentage
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstobject.exe test_fake_object_parentage_dispose
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fake_object_parentage_dispose
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstobject.exe test_fail_abstract_new
+create gstreamertestcases_suite1 foobar
+foobar Example gstobject.exe test_fail_abstract_new
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe test_from_string
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe test_from_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe test_double_append
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe test_double_append
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe test_mutability
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe test_mutability
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe test_buffer
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe test_buffer
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe test_static_caps
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe test_static_caps
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe test_merge_fundamental
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe test_merge_fundamental
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcaps.exe gstcaps_test
+create gstreamertestcases_suite1 foobar
+foobar Example gstcaps.exe gstcaps_test
+delete foobar
+[Endtest] 
Binary file gstreamer_core/tsrc/gstreamertestcases_suite1/data/khuda.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/group/GstreamerTestCases_DoxyFile.txt	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,239 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+# 
+# Description:
+#
+#
+
+# Doxyfile 1.4.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = GstreamerTestCases
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = \GstreamerTestCases\
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = NO
+GENERATE_TESTLIST      = NO
+GENERATE_BUGLIST       = NO
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = \GstreamerTestCases\
+FILE_PATTERNS          = *.h \
+                         *.rh \
+                         *.hrh
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = NO
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = YES
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = YES
+TOC_EXPAND             = YES
+DISABLE_INDEX          = YES
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = YES
+RTF_OUTPUT             = Doc
+COMPACT_RTF            = YES
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = NONSHARABLE_CLASS
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/group/GstreamerTestCases_suite1.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/*TYPE TESTCLASS*/
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+TARGET          gstreamertestcases_suite1.dll
+TARGETTYPE      dll
+UID             0x1000008D 0x101FB4E4
+
+CAPABILITY      ALL -TCB
+/* Remove comments and replace 0x00000000 with correct vendor id */
+// VENDORID     0x00000000
+/* Remove comments and replace 0x00000000 with correct secure id */
+// SECUREID     0x00000000
+
+//TARGETPATH      ?target_path
+//DEFFILE         GstreamerTestCases.def
+
+USERINCLUDE     ../inc 
+
+OS_LAYER_SYSTEMINCLUDE
+
+SOURCEPATH      ../src
+
+SOURCE          GstreamerTestCases.cpp
+SOURCE          GstreamerTestCasesBlocks.cpp
+
+//RESOURCE        resource_file
+//RESOURCE        resource_file2
+
+LIBRARY         euser.lib
+LIBRARY         stiftestinterface.lib
+LIBRARY         stiftestengine.lib
+
+LANG            SC
+
+/*
+START WINS      
+?wins_specific_information
+END
+
+START MARM
+?marm_specific_information
+END
+*/
+// Other possible keywords:
+ 
+// DOCUMENT     ?file, that is not compiled, but added to MSVC project workspace (i.e. release notes)
+/*
+START BITMAP ?target
+TARGETPATH   ?emulated_path_on_target_machine
+HEADER
+SOURCE       ?color_depth ?source_bitmap
+END
+*/
+// DEFFILE ?filename
+// AIF ?filename
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+PRJ_PLATFORMS
+// specify the platforms your component needs to be built for here
+// defaults to WINS MARM so you can ignore this if you just build these
+	
+	DEFAULT
+
+PRJ_TESTEXPORTS
+// NOTE: If using ARS requirements all export operations should be done under this.
+// 'abld test export'
+
+
+
+PRJ_EXPORTS
+// Specify the source file followed by its destination here
+// copy will be used to copy the source file to its destination
+// If there's no destination then the source file will be copied
+// to the same name in \epoc32\include
+// Example: 
+/*
+\agnmodel\inc\AGMCOMON.H
+*/
+
+PRJ_TESTMMPFILES
+GstreamerTestCases_suite1.mmp
+
+PRJ_MMPFILES
+//GstreamerTestCases_suite1.mmp
+
+	// GstreamerTestCases_nrm.mmp
+
+// Specify the .mmp files required for building the important component
+// releasables.
+//
+// Specify "tidy" if the component you need to build doesn't need to be
+// released. Specify "ignore" if the MMP file exists but should be
+// ignored.
+// Example:
+/*
+\agnmodel\group\agnmodel.mmp
+#if defined(MARM)
+\agnmodel\group\agsvexe.mmp
+#endif
+*/
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/group/gstreamer_testcases.pkg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,219 @@
+; ============================================================================
+;  Name        : gstreamer_testcases.pkg
+;  Part of     : Gstreamer project
+;  Description : Package file for all gstreamer test binaries
+;
+;  Version     : %version: 2 %
+;
+;  Copyright © 2002-2006 Nokia.  All rights reserved.
+;  This material, including documentation and any related computer
+;  programs, is protected by copyright controlled by Nokia.  All
+;  rights are reserved.  Copying, including reproducing, storing,
+;  adapting or translating, any or all of this material requires the
+;  prior written consent of Nokia.  This material also contains
+;  confidential information which may not be disclosed to others
+;  without the prior written consent of Nokia.
+; ============================================================================
+
+;Languages
+&EN
+
+;Header
+#{"gstreamer_testcases.pkg"},(0x2001F45C),1,0,0, TYPE=SU
+
+;Supports S60 3.0
+[0x101F7961], 0, 0, 0, {"S60ProductID"}
+
+;Localised Vendor name
+%{"Nokia Testing EN"}
+
+;Unique Vendor name
+:"Vendor"
+
+
+;gstreamer dll
+
+"\epoc32\winscw\c\gstreamer\plugins_list\gst_dll_2001F41F.txt" - "c:\gstreamer\plugins_list\gst_dll_2001F41F.txt"
+"\epoc32\release\armv5\urel\libgstadder.dll"-"!:\sys\bin\libgstadder.dll"
+"\epoc32\release\armv5\urel\libgstaudio.dll"-"!:\sys\bin\libgstaudio.dll"
+"\epoc32\release\armv5\urel\libgstbase.dll"-"!:\sys\bin\libgstbase.dll"
+"\epoc32\release\armv5\urel\libgstcdda.dll"-"!:\sys\bin\libgstcdda.dll"
+"\epoc32\release\armv5\urel\libgstcontroller.dll"-"!:\sys\bin\libgstcontroller.dll"
+"\epoc32\release\armv5\urel\libgstdataprotocol.dll"-"!:\sys\bin\libgstdataprotocol.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundext.dll"-"!:\sys\bin\libgstdevsoundext.dll"
+"\epoc32\release\armv5\urel\libgstfft.dll"-"!:\sys\bin\libgstfft.dll"
+"\epoc32\release\armv5\urel\libgstgdp.dll"-"!:\sys\bin\libgstgdp.dll"
+"\epoc32\release\armv5\urel\libgstinterfaces.dll"-"!:\sys\bin\libgstinterfaces.dll"
+"\epoc32\release\armv5\urel\libgstnet.dll"-"!:\sys\bin\libgstnet.dll"
+"\epoc32\release\armv5\urel\libgstnetbuffer.dll"-"!:\sys\bin\libgstnetbuffer.dll"
+"\epoc32\release\armv5\urel\libgstpbutils.dll"-"!:\sys\bin\libgstpbutils.dll"
+"\epoc32\release\armv5\urel\libgstreamer.dll"-"!:\sys\bin\libgstreamer.dll"
+"\epoc32\release\armv5\urel\libgstriff.dll"-"!:\sys\bin\libgstriff.dll"
+"\epoc32\release\armv5\urel\libgstrtp.dll"-"!:\sys\bin\libgstrtp.dll"
+"\epoc32\release\armv5\urel\libgstsubparse.dll"-"!:\sys\bin\libgstsubparse.dll"
+"\epoc32\release\armv5\urel\libgsttag.dll"-"!:\sys\bin\libgsttag.dll"
+"\epoc32\release\armv5\urel\libgsttcp.dll"-"!:\sys\bin\libgsttcp.dll"
+"\epoc32\release\armv5\urel\libgstvolume.dll"-"!:\sys\bin\libgstvolume.dll"
+"\epoc32\release\armv5\urel\libgstaudiorate.dll"-"!:\sys\bin\libgstaudiorate.dll"
+"\epoc32\release\armv5\urel\libgstaudioresample.dll"-"!:\sys\bin\libgstaudioresample.dll"
+"\epoc32\release\armv5\urel\libgstaudiotestsrc.dll"-"!:\sys\bin\libgstaudiotestsrc.dll"
+"\epoc32\release\armv5\urel\libgstcoreelements.dll"-"!:\sys\bin\libgstcoreelements.dll"
+"\epoc32\release\armv5\urel\libgstcoreindexers.dll"-"!:\sys\bin\libgstcoreindexers.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin.dll"-"!:\sys\bin\libgstdecodebin.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin2.dll"-"!:\sys\bin\libgstdecodebin2.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsink.dll"-"!:\sys\bin\libgstdevsoundsink.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsrc.dll"-"!:\sys\bin\libgstdevsoundsrc.dll"
+"\epoc32\release\armv5\urel\libgstplaybin.dll"-"!:\sys\bin\libgstplaybin.dll"
+"\epoc32\release\armv5\urel\libgsttypefindfunctions.dll"-"!:\sys\bin\libgsttypefindfunctions.dll"
+"\epoc32\release\armv5\urel\libgstwavparse.dll"-"!:\sys\bin\libgstwavparse.dll"
+"\epoc32\release\armv5\urel\libgstwavenc.dll"-"!:\sys\bin\libgstwavenc.dll"
+"\epoc32\release\armv5\urel\libgstaudioconvert.dll"-"!:\sys\bin\libgstaudioconvert.dll"
+"\epoc32\release\armv5\urel\libgstqueue2.dll"-"!:\sys\bin\libgstqueue2.dll"
+"\epoc32\release\armv5\urel\libgstapp.dll"-"!:\sys\bin\libgstapp.dll"
+"\epoc32\release\armv5\urel\libgstautodetect.dll"-"!:\sys\bin\libgstautodetect.dll"
+"\epoc32\release\armv5\urel\liboil.dll"-"!:\sys\bin\liboil.dll"
+"\epoc32\release\armv5\urel\gstreamertestcases_suite1.dll"-"!:\sys\bin\gstreamertestcases_suite1.dll"
+;"\epoc32\release\armv5\urel\libgstvideo.dll"-"!:\sys\bin\libgstvideo.dll"
+;"\epoc32\release\armv5\urel\libgstvideorate.dll"-"!:\sys\bin\libgstvideorate.dll"
+;"\epoc32\release\armv5\urel\libgstvideoscale.dll"-"!:\sys\bin\libgstvideoscale.dll"
+;"\epoc32\release\armv5\urel\libgstvideotestsrc.dll"-"!:\sys\bin\libgstvideotestsrc.dll"
+;"\epoc32\release\armv5\urel\libgstffmpegcolorspace.dll"-"!:\sys\bin\libgstffmpegcolorspace.dll"
+
+
+;gstregistry exe
+
+"\epoc32\release\armv5\urel\GSTRegistryGenerator.exe"		  -"!:\sys\bin\GSTRegistryGenerator.exe",FR,RI
+
+;gstreamer-core test exe's
+
+"\epoc32\release\armv5\urel\cleanup.exe"-"!:\sys\bin\cleanup.exe"
+"\epoc32\release\armv5\urel\createelementcore.exe"-"!:\sys\bin\createelementcore.exe"
+"\epoc32\release\armv5\urel\element_gstfakesink.exe"-"!:\sys\bin\element_gstfakesink.exe"
+"\epoc32\release\armv5\urel\element_gstfakesrc.exe"-"!:\sys\bin\element_gstfakesrc.exe"
+"\epoc32\release\armv5\urel\element_gstfdsrc.exe"-"!:\sys\bin\element_gstfdsrc.exe"
+"\epoc32\release\armv5\urel\element_gstfilesink.exe"-"!:\sys\bin\element_gstfilesink.exe"
+"\epoc32\release\armv5\urel\element_gstfilesrc.exe"-"!:\sys\bin\element_gstfilesrc.exe"
+"\epoc32\release\armv5\urel\element_gstidentity.exe"-"!:\sys\bin\element_gstidentity.exe"
+"\epoc32\release\armv5\urel\element_gstmultiqueue.exe"-"!:\sys\bin\element_gstmultiqueue.exe"
+"\epoc32\release\armv5\urel\element_gstqueue.exe"-"!:\sys\bin\element_gstqueue.exe"
+"\epoc32\release\armv5\urel\element_gsttee.exe"-"!:\sys\bin\element_gsttee.exe"
+"\epoc32\release\armv5\urel\gst.exe"-"!:\sys\bin\gst.exe"
+"\epoc32\release\armv5\urel\gstadapter.exe"-"!:\sys\bin\gstadapter.exe"
+"\epoc32\release\armv5\urel\gstbasesrc.exe"-"!:\sys\bin\gstbasesrc.exe"
+"\epoc32\release\armv5\urel\gstbin.exe"-"!:\sys\bin\gstbin.exe"
+"\epoc32\release\armv5\urel\gstbuffer.exe"-"!:\sys\bin\gstbuffer.exe"
+"\epoc32\release\armv5\urel\gstbus.exe"-"!:\sys\bin\gstbus.exe"
+"\epoc32\release\armv5\urel\gstcaps.exe"-"!:\sys\bin\gstcaps.exe"
+"\epoc32\release\armv5\urel\gstcollectpads.exe"-"!:\sys\bin\gstcollectpads.exe"
+"\epoc32\release\armv5\urel\gstcontroller.exe"-"!:\sys\bin\gstcontroller.exe"
+"\epoc32\release\armv5\urel\gstelement.exe"-"!:\sys\bin\gstelement.exe"
+"\epoc32\release\armv5\urel\gstevent.exe"-"!:\sys\bin\gstevent.exe"
+"\epoc32\release\armv5\urel\gstgdp.exe"-"!:\sys\bin\gstgdp.exe"
+"\epoc32\release\armv5\urel\gstghostpad.exe"-"!:\sys\bin\gstghostpad.exe"
+"\epoc32\release\armv5\urel\gstgstnetclientclock.exe"-"!:\sys\bin\gstgstnetclientclock.exe"
+"\epoc32\release\armv5\urel\gstgstnettimeprovider.exe"-"!:\sys\bin\gstgstnettimeprovider.exe"
+"\epoc32\release\armv5\urel\gstindex.exe"-"!:\sys\bin\gstindex.exe"
+"\epoc32\release\armv5\urel\gstinterface.exe"-"!:\sys\bin\gstinterface.exe"
+"\epoc32\release\armv5\urel\gstiterator.exe"-"!:\sys\bin\gstiterator.exe"
+"\epoc32\release\armv5\urel\gstlibsabi.exe"-"!:\sys\bin\gstlibsabi.exe"
+"\epoc32\release\armv5\urel\gstmessage.exe"-"!:\sys\bin\gstmessage.exe"
+"\epoc32\release\armv5\urel\gstminiobject.exe"-"!:\sys\bin\gstminiobject.exe"
+"\epoc32\release\armv5\urel\gstobject.exe"-"!:\sys\bin\gstobject.exe"
+"\epoc32\release\armv5\urel\gstpad.exe"-"!:\sys\bin\gstpad.exe"
+"\epoc32\release\armv5\urel\gstparamspecs.exe"-"!:\sys\bin\gstparamspecs.exe"
+"\epoc32\release\armv5\urel\gstpipeline.exe"-"!:\sys\bin\gstpipeline.exe"
+"\epoc32\release\armv5\urel\gstplugin.exe"-"!:\sys\bin\gstplugin.exe"
+"\epoc32\release\armv5\urel\gstpoll.exe"-"!:\sys\bin\gstpoll.exe"
+"\epoc32\release\armv5\urel\gstquery.exe"-"!:\sys\bin\gstquery.exe"
+"\epoc32\release\armv5\urel\gstregistry.exe"-"!:\sys\bin\gstregistry.exe"
+"\epoc32\release\armv5\urel\gstsegment.exe"-"!:\sys\bin\gstsegment.exe"
+"\epoc32\release\armv5\urel\gstsinks.exe"-"!:\sys\bin\gstsinks.exe"
+"\epoc32\release\armv5\urel\gststates.exe"-"!:\sys\bin\gststates.exe"
+"\epoc32\release\armv5\urel\gststructure.exe"-"!:\sys\bin\gststructure.exe"
+"\epoc32\release\armv5\urel\gstsystemclock.exe"-"!:\sys\bin\gstsystemclock.exe"
+"\epoc32\release\armv5\urel\gsttag.exe"-"!:\sys\bin\gsttag.exe"
+"\epoc32\release\armv5\urel\gsttagsetter.exe"-"!:\sys\bin\gsttagsetter.exe"
+"\epoc32\release\armv5\urel\gsttask.exe"-"!:\sys\bin\gsttask.exe"
+"\epoc32\release\armv5\urel\gsttypefindhelper.exe"-"!:\sys\bin\gsttypefindhelper.exe"
+"\epoc32\release\armv5\urel\gsturi.exe"-"!:\sys\bin\gsturi.exe"
+"\epoc32\release\armv5\urel\gstutils.exe"-"!:\sys\bin\gstutils.exe"
+"\epoc32\release\armv5\urel\gstvalue.exe"-"!:\sys\bin\gstvalue.exe"
+"\epoc32\release\armv5\urel\helloworld.exe"-"!:\sys\bin\helloworld.exe"
+"\epoc32\release\armv5\urel\launch.exe"-"!:\sys\bin\launch.exe"
+"\epoc32\release\armv5\urel\manual_dynamic.exe"-"!:\sys\bin\manual_dynamic.exe"
+"\epoc32\release\armv5\urel\manual_ghostpad.exe"-"!:\sys\bin\manual_ghostpad.exe"
+"\epoc32\release\armv5\urel\manual_gstbin.exe"-"!:\sys\bin\manual_gstbin.exe"
+"\epoc32\release\armv5\urel\manual_gstdecodebin.exe"-"!:\sys\bin\manual_gstdecodebin.exe"
+"\epoc32\release\armv5\urel\manual_gstelementcreate.exe"-"!:\sys\bin\manual_gstelementcreate.exe"
+"\epoc32\release\armv5\urel\manual_gstelementfactory.exe"-"!:\sys\bin\manual_gstelementfactory.exe"
+"\epoc32\release\armv5\urel\manual_gstelementget.exe"-"!:\sys\bin\manual_gstelementget.exe"
+"\epoc32\release\armv5\urel\manual_gstelementlink.exe"-"!:\sys\bin\manual_gstelementlink.exe"
+"\epoc32\release\armv5\urel\manual_gstelementmake.exe"-"!:\sys\bin\manual_gstelementmake.exe"
+"\epoc32\release\armv5\urel\manual_gstinit.exe"-"!:\sys\bin\manual_gstinit.exe"
+"\epoc32\release\armv5\urel\manual_gstpad.exe"-"!:\sys\bin\manual_gstpad.exe"
+"\epoc32\release\armv5\urel\manual_gstplaybin.exe"-"!:\sys\bin\manual_gstplaybin.exe"
+"\epoc32\release\armv5\urel\manual_gstquery.exe"-"!:\sys\bin\manual_gstquery.exe"
+"\epoc32\release\armv5\urel\manual_helloworld.exe"-"!:\sys\bin\manual_helloworld.exe"
+"\epoc32\release\armv5\urel\manual_typefind.exe"-"!:\sys\bin\manual_typefind.exe"
+"\epoc32\release\armv5\urel\metadata.exe"-"!:\sys\bin\metadata.exe"
+"\epoc32\release\armv5\urel\mp3launch.exe"-"!:\sys\bin\mp3launch.exe"
+"\epoc32\release\armv5\urel\parse-disabled.exe"-"!:\sys\bin\parse-disabled.exe"
+"\epoc32\release\armv5\urel\parse-launch.exe"-"!:\sys\bin\parse-launch.exe"
+"\epoc32\release\armv5\urel\simple-launch-lines.exe"-"!:\sys\bin\simple-launch-lines.exe"
+"\epoc32\release\armv5\urel\stress.exe"-"!:\sys\bin\stress.exe"
+"\epoc32\release\armv5\urel\testaudioexample.exe"-"!:\sys\bin\testaudioexample.exe"
+"\epoc32\release\armv5\urel\testgstadapter.exe"-"!:\sys\bin\testgstadapter.exe"
+"\epoc32\release\armv5\urel\testqueue.exe"-"!:\sys\bin\testqueue.exe"
+"\epoc32\release\armv5\urel\typefind.exe"-"!:\sys\bin\typefind.exe"
+
+
+
+;gst_plugins_base test exe's
+
+"\epoc32\release\armv5\urel\gstadder.exe"-"!:\sys\bin\gstadder.exe"
+"\epoc32\release\armv5\urel\gstaudioconvert.exe"-"!:\sys\bin\gstaudioconvert.exe"
+"\epoc32\release\armv5\urel\gstaudiorate.exe"-"!:\sys\bin\gstaudiorate.exe"
+"\epoc32\release\armv5\urel\gstaudioresample.exe"-"!:\sys\bin\gstaudioresample.exe"
+"\epoc32\release\armv5\urel\gstaudiotestsrc.exe"-"!:\sys\bin\gstaudiotestsrc.exe"
+"\epoc32\release\armv5\urel\createelementbase.exe"-"!:\sys\bin\createelementbase.exe"
+"\epoc32\release\armv5\urel\gstdecodebin.exe"-"!:\sys\bin\gstdecodebin.exe"
+"\epoc32\release\armv5\urel\gdpdepay.exe"-"!:\sys\bin\gdpdepay.exe"
+"\epoc32\release\armv5\urel\multifdsink.exe"-"!:\sys\bin\multifdsink.exe"
+"\epoc32\release\armv5\urel\playbin.exe"-"!:\sys\bin\playbin.exe"
+"\epoc32\release\armv5\urel\gstsubparse.exe"-"!:\sys\bin\gstsubparse.exe"
+"\epoc32\release\armv5\urel\volume.exe"-"!:\sys\bin\volume.exe"
+"\epoc32\release\armv5\urel\clock-selection.exe"-"!:\sys\bin\clock-selection.exe"
+"\epoc32\release\armv5\urel\states.exe"-"!:\sys\bin\states.exe"
+"\epoc32\release\armv5\urel\fft.exe"-"!:\sys\bin\fft.exe"
+;"\epoc32\release\armv5\urel\gstnetbuffer.exe"-"!:\sys\bin\gstnetbuffer.exe"
+"\epoc32\release\armv5\urel\pbutils.exe"-"!:\sys\bin\pbutils.exe"
+"\epoc32\release\armv5\urel\gst_plugin_rtp.exe"-"!:\sys\bin\gst_plugin_rtp.exe"
+"\epoc32\release\armv5\urel\gst_plugin_tag.exe"-"!:\sys\bin\gst_plugin_tag.exe"
+"\epoc32\release\armv5\urel\taudio.exe"-"!:\sys\bin\taudio.exe"
+"\epoc32\release\armv5\urel\gstsimple-launch-lines.exe"-"!:\sys\bin\gstsimple-launch-lines.exe"
+"\epoc32\release\armv5\urel\gststreamheader.exe"-"!:\sys\bin\gststreamheader.exe"
+"\epoc32\release\armv5\urel\stress_playbin.exe"-"!:\sys\bin\stress_playbin.exe"
+
+;"\epoc32\release\armv5\urel\ffmpegcolorspace.exe"-"!:\sys\bin\ffmpegcolorspace.exe"
+;"\epoc32\release\armv5\urel\addstream.exe"-"!:\sys\bin\addstream.exe"
+;"\epoc32\release\armv5\urel\video.exe"-"!:\sys\bin\video.exe"
+;"\epoc32\release\armv5\urel\typefindfunctions.exe" -"!:\sys\bin\typefindfunctions.exe"
+;"\epoc32\release\armv5\urel\videorate.exe"-"!:\sys\bin\videorate.exe"
+
+
+
+;dependecy files
+"\epoc32\winscw\c\data\gstreamer\khuda1.wav"-"c:\data\gstreamer\khuda1.wav"
+"\epoc32\winscw\c\data\gstreamer\khuda.wav"-"c:\data\gstreamer\khuda.wav"
+"\epoc32\winscw\c\data\gstreamer\warning.wav"-"c:\data\gstreamer\warning.wav"
+"\epoc32\winscw\c\data\gstreamer\Crnival.mp3"-"c:\data\gstreamer\Crnival.mp3"
+"\epoc32\winscw\c\data\gstreamer\khuda.wav"-"c:\data\gstreamer\gsttestfiles\khuda.wav"
+"\epoc32\winscw\c\data\gstreamer\khuda.wav"-"c:\data\khuda.wav"
+;"\epoc32\winscw\c\data\gstreamer\warning.wav"-"c:\data\warning.wav"
+;"\epoc32\winscw\c\data\gstreamer\Crnival.mp3"-"c:\data\Crnival.mp3"
+
+;Testframework.ini and conf files
+
+"..\conf\gstreamertestcases_suite1.cfg"-"c:\TestFramework\gstreamertestcases_suite1.cfg"
+"..\init\gstreamertestcases_suite1.ini"-"c:\TestFramework\gstreamertestcases_suite1.ini"
+"..\init\TestFramework.ini"-"c:\TestFramework\TestFramework.ini"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/inc/GstreamerTestCases.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,190 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: STIF testclass declaration
+*
+*/
+
+
+#ifndef GSTREAMERTESTCASES_H
+#define GSTREAMERTESTCASES_H
+
+//  INCLUDES
+#include <StifLogger.h>
+#include <TestScripterInternal.h>
+#include <StifTestModule.h>
+#include <TestclassAssert.h>
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+#define TEST_CLASS_VERSION_MAJOR 0
+#define TEST_CLASS_VERSION_MINOR 0
+#define TEST_CLASS_VERSION_BUILD 0
+
+// Logging path
+_LIT( KGstreamerTestCasesLogPath, "\\logs\\testframework\\GstreamerTestCases\\" ); 
+// Log file
+_LIT( KGstreamerTestCasesLogFile, "GstreamerTestCases.htm" ); 
+_LIT( KGstreamerTestCasesLogFileWithTitle, "GstreamerTestCases_[%S].htm" );
+
+// FUNCTION PROTOTYPES
+//?type ?function_name(?arg_list);
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+class CGstreamerTestCases;
+
+// DATA TYPES
+//enum ?declaration
+//typedef ?declaration
+//extern ?data_type;
+
+// CLASS DECLARATION
+
+/**
+*  CGstreamerTestCases test class for STIF Test Framework TestScripter.
+*  ?other_description_lines
+*
+*  @lib ?library
+*  @since ?Series60_version
+*/
+NONSHARABLE_CLASS(CGstreamerTestCases) : public CScriptBase
+    {
+    public:  // Constructors and destructor
+
+        /**
+        * Two-phased constructor.
+        */
+        static CGstreamerTestCases* NewL( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * Destructor.
+        */
+        virtual ~CGstreamerTestCases();
+
+    public: // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    public: // Functions from base classes
+
+        /**
+        * From CScriptBase Runs a script line.
+        * @since ?Series60_version
+        * @param aItem Script line containing method name and parameters
+        * @return Symbian OS error code
+        */
+        virtual TInt RunMethodL( CStifItemParser& aItem );
+
+    protected:  // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    protected:  // Functions from base classes
+
+        /**
+        * From ?base_class ?member_description
+        */
+        //?type ?member_function();
+
+    private:
+
+        /**
+        * C++ default constructor.
+        */
+        CGstreamerTestCases( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * By default Symbian 2nd phase constructor is private.
+        */
+        void ConstructL();
+
+        // Prohibit copy constructor if not deriving from CBase.
+        // ?classname( const ?classname& );
+        // Prohibit assigment operator if not deriving from CBase.
+        // ?classname& operator=( const ?classname& );
+
+        /**
+        * Frees all resources allocated from test methods.
+        * @since ?Series60_version
+        */
+        void Delete();
+
+        /**
+        * Test methods are listed below. 
+        */
+
+        /**
+        * Example test method.
+        * @since ?Series60_version
+        * @param aItem Script line containing parameters.
+        * @return Symbian OS error code.
+        */
+        virtual TInt ExampleL( CStifItemParser& aItem );
+        
+        /**
+         * Method used to log version of test class
+         */
+        void SendTestClassVersion();
+
+        //ADD NEW METHOD DEC HERE
+        //[TestMethods] - Do not remove
+
+    public:     // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    protected:  // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    private:    // Data
+        
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+        // Reserved pointer for future extension
+        //TAny* iReserved;
+
+    public:     // Friend classes
+        //?friend_class_declaration;
+    protected:  // Friend classes
+        //?friend_class_declaration;
+    private:    // Friend classes
+        //?friend_class_declaration;
+
+    };
+
+#endif      // GSTREAMERTESTCASES_H
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/init/gstreamertestcases_suite1.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+[general]
+logFileName gstreamertestcases_suite1.log
+logPath c:\logs\
+[general_end]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/init/testframework.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,184 @@
+#
+# This is STIFTestFramework initialization file
+# Comment lines start with '#'-character.
+# See STIF TestFramework users guide.doc for instructions
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set following test engine settings:
+#   - Set Test Reporting mode. TestReportMode's possible values are:
+#       + 'Summary': Summary of the tested test cases.
+#       + 'Environment': Hardware and software info.
+#       + 'TestCases': Test case report.
+#       + 'FullReport': Set of all above ones.
+#       + Example 'TestReportMode= Summary TestCases'
+#
+#   - CreateTestReport setting controls report creation mode
+#       + YES, Test report will created.
+#       + NO, No Test report.
+#
+#   - File path indicates the base path of the test report.
+#   - File name indicates the name of the test report.
+#
+#   - File format indicates the type of the test report.
+#       + TXT, Test report file will be txt type, for example 'TestReport.txt'.
+#       + HTML, Test report will be html type, for example 'TestReport.html'.
+#
+#   - File output indicates output source of the test report.
+#       + FILE, Test report logging to file.
+#       + RDEBUG, Test report logging to using rdebug.
+#
+#   - File Creation Mode indicates test report overwriting if file exist.
+#       + OVERWRITE, Overwrites if the Test report file exist.
+#       + APPEND, Continue logging after the old Test report information if
+#                 report exist.
+#   - Sets a device reset module's dll name(Reboot).
+#       + If Nokia specific reset module is not available or it is not correct one
+#         StifHWResetStub module may use as a template for user specific reset
+#         module.
+
+[Engine_Defaults]
+
+TestReportMode= FullReport      # Possible values are: 'Empty', 'Summary', 'Environment',
+                                                               'TestCases' or 'FullReport'
+
+CreateTestReport= YES           # Possible values: YES or NO
+
+TestReportFilePath= C:\LOGS\TestFramework\
+TestReportFileName= TestReport_gstreamertestcases_suite1
+
+TestReportFormat= HTML          # Possible values: TXT or HTML
+TestReportOutput= FILE          # Possible values: FILE or RDEBUG
+TestReportFileCreationMode= OVERWRITE   # Possible values: OVERWRITE or APPEND
+
+DeviceResetDllName= StifResetForNokia.dll # e.g. 'StifHWResetStub.dll' for user specific reseting
+
+[End_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Module configurations start
+# Modules are added between module tags
+# tags. Module name is specified after ModuleName= tag, like
+# ModuleName= XXXXXXXXX
+# Modules might have initialisation file, specified as
+# IniFile= c:\testframework\YYYYYY
+# Modules might have several configuration files, like
+# TestCaseFile= c:\testframework\NormalCases.txt
+# TestCaseFile= c:\testframework\SmokeCases.txt
+# TestCaseFile= c:\testframework\ManualCases.txt
+
+# (TestCaseFile is synonym for old term ConfigFile)
+
+# Following case specifies demo module settings. Demo module
+# does not read any settings from file, so tags
+# IniFile and TestCaseFile are not used.
+# In the simplest case it is enough to specify only the
+# name of the test module when adding new test module
+
+#[New_Module]
+#ModuleName= demomodule
+#[End_Module]
+
+
+[New_Module]
+ModuleName= TestScripter
+TestCaseFile= c:\testframework\gstreamertestcases_suite1.cfg
+IniFile= c:\testframework\gstreamertestcases_suite1.ini
+[End_Module]
+
+# Load testmoduleXXX, optionally with initialization file and/or test case files
+#[New_Module]
+#ModuleName= testmodulexxx
+
+#TestModuleXXX used initialization file
+#IniFile= c:\testframework\init.txt
+
+#TestModuleXXX used configuration file(s)
+#TestCaseFile= c:\testframework\testcases1.cfg
+#TestCaseFile= c:\testframework\testcases2.cfg
+#TestCaseFile= c:\testframework\manualtestcases.cfg
+
+#[End_Module]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set STIFTestFramework logging overwrite parameters for Logger.
+#   Hardware and emulator environment logging path and styles can
+#   be configured from here to overwrite the Logger's implemented values.
+#
+#   Settings description:
+#   - Indicates option for creation log directory/directories. If log directory/directories
+#         is/are not created by user they will make by software.
+#       + YES, Create log directory/directories if not allready exist.
+#       + NO, Log directory/directories not created. Only created one is used.
+#
+#   - Overwrite emulator path setting.
+#       + Example: If 'EmulatorBasePath= C:\LOGS\TestFramework\' and in code is defined
+#                  Logger's path 'D:\\LOGS\\Module\\' with those definition the path
+#                  will be 'C:\LOGS\TestFramework\LOGS\Module\'
+#
+#   - Overwrite emulator's logging format.
+#       + TXT, Log file(s) will be txt type(s), for example 'Module.txt'.
+#       + HTML, Log file(s) will be html type(s), for example 'Module.html'.
+#
+#   - Overwrited emulator logging output source.
+#       + FILE, Logging to file(s).
+#       + RDEBUG, Logging to using rdebug(s).
+#
+#   - Overwrite hardware path setting (Same description as above in emulator path).
+#   - Overwrite hardware's logging format(Same description as above in emulator format).
+#   - Overwrite hardware's logging output source(Same description as above in emulator output).
+#
+#   - File Creation Mode indicates file overwriting if file exist.
+#       + OVERWRITE, Overwrites if file(s) exist.
+#       + APPEND, Continue logging after the old logging information if file(s) exist.
+#
+#   - Will thread id include to the log filename.
+#       + YES, Thread id to log file(s) name, Example filename 'Module_b9.txt'.
+#       + NO, No thread id to log file(s), Example filename 'Module.txt'.
+#
+#   - Will time stamps include the to log file.
+#       + YES, Time stamp added to each line in log file(s). Time stamp is
+#                 for example'12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No time stamp(s).
+#
+#   - Will line breaks include to the log file.
+#       + YES, Each logging event includes line break and next log event is in own line.
+#       + NO, No line break(s).
+#
+#   - Will event ranking include to the log file.
+#       + YES, Event ranking number added to each line in log file(s). Ranking number
+#                 depends on environment's tics, for example(includes time stamp also)
+#                 '012   12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No event ranking.
+#
+
+[Logger_Defaults]
+
+#NOTE: If you want to set Logger using next setting(s) remove comment(s)'#'
+
+#CreateLogDirectories= YES      # Possible values: YES or NO
+
+#EmulatorBasePath= C:\LOGS\TestFramework\
+#EmulatorFormat= HTML           # Possible values: TXT or HTML
+#EmulatorOutput= FILE           # Possible values: FILE or RDEBUG
+
+#HardwareBasePath= D:\LOGS\TestFramework\
+#HardwareFormat= HTML           # Possible values: TXT or HTML
+#HardwareOutput= FILE           # Possible values: FILE or RDEBUG
+
+#FileCreationMode= OVERWRITE        # Possible values: OVERWRITE or APPEND
+
+#ThreadIdToLogFile= YES             # Possible values: YES or NO
+#WithTimeStamp= YES             # Possible values: YES or NO
+#WithLineBreak= YES             # Possible values: YES or NO
+#WithEventRanking= YES          # Possible values: YES or NO
+
+[End_Logger_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+# End of file
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/src/GstreamerTestCases.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,204 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// INCLUDE FILES
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+#include <SettingServerClient.h>
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::CGstreamerTestCases
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases::CGstreamerTestCases( 
+    CTestModuleIf& aTestModuleIf ):
+        CScriptBase( aTestModuleIf )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::ConstructL()
+    {
+    //Read logger settings to check whether test case name is to be
+    //appended to log file name.
+    RSettingServer settingServer;
+    TInt ret = settingServer.Connect();
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        }
+    // Struct to StifLogger settigs.
+    TLoggerSettings loggerSettings; 
+    // Parse StifLogger defaults from STIF initialization file.
+    ret = settingServer.GetLoggerSettings(loggerSettings);
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        } 
+    // Close Setting server session
+    settingServer.Close();
+
+    TFileName logFileName;
+    
+    if(loggerSettings.iAddTestCaseTitle)
+        {
+        TName title;
+        TestModuleIf().GetTestCaseTitleL(title);
+        logFileName.Format(KGstreamerTestCasesLogFileWithTitle, &title);
+        }
+    else
+        {
+        logFileName.Copy(KGstreamerTestCasesLogFile);
+        }
+
+    iLog = CStifLogger::NewL( KGstreamerTestCasesLogPath, 
+                          logFileName,
+                          CStifLogger::ETxt,
+                          CStifLogger::EFile,
+                          EFalse );
+    
+    SendTestClassVersion();
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases* CGstreamerTestCases::NewL( 
+    CTestModuleIf& aTestModuleIf )
+    {
+    CGstreamerTestCases* self = new (ELeave) CGstreamerTestCases( aTestModuleIf );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+
+    }
+
+// Destructor
+CGstreamerTestCases::~CGstreamerTestCases()
+    { 
+
+    // Delete resources allocated from test methods
+    Delete();
+
+    // Delete logger
+    delete iLog; 
+
+    }
+
+//-----------------------------------------------------------------------------
+// CGstreamerTestCases::SendTestClassVersion
+// Method used to send version of test class
+//-----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::SendTestClassVersion()
+	{
+	TVersion moduleVersion;
+	moduleVersion.iMajor = TEST_CLASS_VERSION_MAJOR;
+	moduleVersion.iMinor = TEST_CLASS_VERSION_MINOR;
+	moduleVersion.iBuild = TEST_CLASS_VERSION_BUILD;
+	
+	TFileName moduleName;
+	moduleName = _L("GstreamerTestCases.dll");
+
+	TBool newVersionOfMethod = ETrue;
+	TestModuleIf().SendTestModuleVersion(moduleVersion, moduleName, newVersionOfMethod);
+	}
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// -----------------------------------------------------------------------------
+// LibEntryL is a polymorphic Dll entry point.
+// Returns: CScriptBase: New CScriptBase derived object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CScriptBase* LibEntryL( 
+    CTestModuleIf& aTestModuleIf ) // Backpointer to STIF Test Framework
+    {
+
+    return ( CScriptBase* ) CGstreamerTestCases::NewL( aTestModuleIf );
+
+    }
+
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite1/src/GstreamerTestCasesBlocks.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,237 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// [INCLUDE FILES] - do not remove
+#include <e32svr.h>
+#include <StifParser.h>
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::Delete
+// Delete here all resources allocated and opened from test methods. 
+// Called from destructor. 
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::Delete() 
+    {
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::RunMethodL
+// Run specified method. Contains also table of test mothods and their names.
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::RunMethodL( 
+    CStifItemParser& aItem ) 
+    {
+
+    static TStifFunctionInfo const KFunctions[] =
+        {  
+        // Copy this line for every implemented function.
+        // First string is the function name used in TestScripter script file.
+        // Second is the actual implementation member function. 
+        ENTRY( "Example", CGstreamerTestCases::ExampleL ),
+        //ADD NEW ENTRY HERE
+        // [test cases entries] - Do not remove
+
+        };
+
+    const TInt count = sizeof( KFunctions ) / 
+                        sizeof( TStifFunctionInfo );
+
+    return RunInternalL( KFunctions, count, aItem );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ExampleL
+// Example test method function.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::ExampleL( CStifItemParser& aItem )
+{
+    TInt err = KErrNone;
+    RTimer timeoutTimer;
+    // Print to UI
+//    _LIT( KGstreamerTestCases, "GstreamerTestCases" );
+//    _LIT( KExample, "Test case: " );
+//    TestModuleIf().Printf( 0, KGstreamerTestCases, KExample );
+    // Print to log file
+
+    TPtrC string[2];
+    TFileName arg;
+    //_LIT( KParam, "Param[%i]: %S" );
+    
+    if( aItem.GetNextString ( string[0] ) != KErrNone)
+    {
+        iLog->Log( _L(">> Test cases Not Found") );
+        return -1;
+    }
+    iLog->Log( _L( "Test case Name is : " ) );
+    iLog->Log( string[0] );
+    
+    while ( aItem.GetNextString ( string[1] ) == KErrNone )
+    {
+        iLog->Log( string[1] );
+        arg.Append( string[1] );
+        arg.Append( TChar(' ') );
+    }
+    
+    
+    _LIT( KArg, "Arg: " );
+    iLog->Log( KArg );
+    iLog->Log( arg );
+    RProcess process;
+    err = process.Create( string[0],arg );
+    
+    if( !err )
+    {
+
+        if( timeoutTimer.CreateLocal() != KErrNone )
+        {
+            iLog->Log( _L(">> timeoutTimer.CreateLocal failed") );
+        }
+    
+        iLog->Log( _L(">> Test cases Started") );
+        TRequestStatus processStatus = KRequestPending;
+        TRequestStatus timerStatus = KRequestPending;
+        process.Logon( processStatus );
+        
+        process.Resume();
+        TTimeIntervalMicroSeconds32 timeout = 1 * 60 * 1000000;
+        timeoutTimer.After( timerStatus, timeout );
+        
+        while( processStatus == KRequestPending && timerStatus == KRequestPending )
+        {
+            User::WaitForAnyRequest();
+            
+        }
+        
+        err = process.ExitReason();
+        if( timerStatus != KRequestPending )
+        {
+            err = KErrTimedOut;
+        }
+        
+        process.LogonCancel( processStatus );
+        timeoutTimer.Cancel();
+        /// required to complete one of the pending request..
+        User::WaitForAnyRequest();
+        
+        process.Kill( KErrNone );
+        process.Close();
+        timeoutTimer.Close();
+        iLog->Log( _L(">> test cases completed") );
+    }
+    else
+    {
+        iLog->Log( _L(">> test cases exe not found") );
+    }
+
+
+    if( err != KErrNone )
+    {
+        iLog->Log( CStifLogger::ERed, _L( "Test cases FAILED!" ) );
+    }
+    else
+    {
+        iLog->Log( CStifLogger::EGreen, _L( "Test cases PASSED!" ) );
+    }
+    
+
+    return err;
+}
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+/*
+TInt CGstreamerTestCases::?member_function(
+   CItemParser& aItem )
+   {
+
+   ?code
+
+   }
+*/
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+// None
+
+//  [End of File] - Do not remove
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/Bwins/gstreamertestcases_suite2u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	?LibEntryL@@YAPAVCScriptBase@@AAVCTestModuleIf@@@Z @ 1 NONAME ; class CScriptBase * LibEntryL(class CTestModuleIf &)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/EABI/gstreamertestcases_suite2u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_Z9LibEntryLR13CTestModuleIf @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/conf/gstreamertestcases_suite2.cfg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,976 @@
+[Test]
+title gstiterator.exe test_manual_iteration
+create gstreamertestcases_suite2 foobar
+foobar Example gstiterator.exe test_manual_iteration
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstiterator.exe test_resync
+create gstreamertestcases_suite2 foobar
+foobar Example gstiterator.exe test_resync
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstiterator.exe test_fold
+create gstreamertestcases_suite2 foobar
+foobar Example gstiterator.exe test_fold
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpipeline.exe test_async_state_change_empty
+create gstreamertestcases_suite2 foobar
+foobar Example gstpipeline.exe test_async_state_change_empty
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpipeline.exe test_async_state_change_fake_ready
+create gstreamertestcases_suite2 foobar
+foobar Example gstpipeline.exe test_async_state_change_fake_ready
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpipeline.exe test_async_state_change_fake
+create gstreamertestcases_suite2 foobar
+foobar Example gstpipeline.exe test_async_state_change_fake
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpipeline.exe test_get_bus
+create gstreamertestcases_suite2 foobar
+foobar Example gstpipeline.exe test_get_bus
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpipeline.exe test_bus
+create gstreamertestcases_suite2 foobar
+foobar Example gstpipeline.exe test_bus
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpipeline.exe test_base_time
+create gstreamertestcases_suite2 foobar
+foobar Example gstpipeline.exe test_base_time
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_register_static
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_register_static
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_registry
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_registry
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_registry_get_plugin_list
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_registry_get_plugin_list
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_find_plugin
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_find_plugin
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_find_feature
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_find_feature
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_find_element
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_find_element
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_version_checks
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_version_checks
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_load_coreelements
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_load_coreelements
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstplugin.exe test_typefind
+create gstreamertestcases_suite2 foobar
+foobar Example gstplugin.exe test_typefind
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpoll.exe test_poll_basic
+create gstreamertestcases_suite2 foobar
+foobar Example gstpoll.exe test_poll_basic
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpoll.exe test_poll_wait_stop
+create gstreamertestcases_suite2 foobar
+foobar Example gstpoll.exe test_poll_wait_stop
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpoll.exe test_poll_wait_flush
+create gstreamertestcases_suite2 foobar
+foobar Example gstpoll.exe test_poll_wait_flush
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpoll.exe test_poll_wait_restart
+create gstreamertestcases_suite2 foobar
+foobar Example gstpoll.exe test_poll_wait_restart
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstpoll.exe test_poll_controllable
+create gstreamertestcases_suite2 foobar
+foobar Example gstpoll.exe test_poll_controllable
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstindex.exe test_index_entries
+create gstreamertestcases_suite2 foobar
+foobar Example gstindex.exe test_index_entries
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_seek_reverse
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_seek_reverse
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_seek_rate
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_seek_rate
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_open
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_open
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_closed
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_closed
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_streamtime
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_streamtime
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_streamtime_rate
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_streamtime_rate
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_streamtime_applied_rate
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_streamtime_applied_rate
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_streamtime_applied_rate_rate
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_streamtime_applied_rate_rate
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_runningtime
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_runningtime
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_accum
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_accum
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_newsegment_accum2
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_newsegment_accum2
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_seek_nosize
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_seek_nosize
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsegment.exe segment_seek_size
+create gstreamertestcases_suite2 foobar
+foobar Example gstsegment.exe segment_seek_size
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_from_string_int
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_from_string_int
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_from_string
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_from_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_to_string
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_to_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_to_from_string
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_to_from_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_complete_structure
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_complete_structure
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_structure_new
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_structure_new
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_fixate
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_fixate
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_fixate_frac_list
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_fixate_frac_list
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gststructure.exe test_structure_nested
+create gstreamertestcases_suite2 foobar
+foobar Example gststructure.exe test_structure_nested
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_range
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_range
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_diff
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_diff
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_signedness
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_signedness
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_single_shot
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_single_shot
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_periodic_shot
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_periodic_shot
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_periodic_multi
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_periodic_multi
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_async_order
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_async_order
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstsystemclock.exe test_mixed
+create gstreamertestcases_suite2 foobar
+foobar Example gstsystemclock.exe test_mixed
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_buffer_probe_n_times
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_buffer_probe_n_times
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_buffer_probe_once
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_buffer_probe_once
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_math_scale
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_math_scale
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_math_scale_uint64
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_math_scale_uint64
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_math_scale_random
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_math_scale_random
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_guint64_to_gdouble
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_guint64_to_gdouble
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_gdouble_to_guint64
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_gdouble_to_guint64
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_parse_bin_from_description
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_parse_bin_from_description
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_element_found_tags
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_element_found_tags
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_element_unlink
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_element_unlink
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstutils.exe test_set_value_from_string
+create gstreamertestcases_suite2 foobar
+foobar Example gstutils.exe test_set_value_from_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_buffer
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_buffer
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_serialize_buffer
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_serialize_buffer
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_gint
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_gint
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_gint_failures
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_gint_failures
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_guint
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_guint
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_guint_failures
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_guint_failures
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstvalue.exe test_deserialize_gint64
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_gint64
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_gstfraction
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_gstfraction
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_serialize_flags
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_serialize_flags
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_flags
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_flags
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_serialize_deserialize_format_enum
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_serialize_deserialize_format_enum
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_string
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_deserialize_string
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_deserialize_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_value_intersect
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_value_intersect
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_date
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_date
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_fraction_range
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_fraction_range
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_value_subtract_fraction
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_value_subtract_fraction
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_value_compare
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_value_compare
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstvalue.exe test_value_subtract_int
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_value_subtract_int
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_value_subtract_double
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_value_subtract_double
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstvalue.exe test_value_subtract_fraction_range
+create gstreamertestcases_suite2 foobar
+foobar Example gstvalue.exe test_value_subtract_fraction_range
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gsttask.exe test_create
+create gstreamertestcases_suite2 foobar
+foobar Example gsttask.exe test_create
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttask.exe test_no_lock
+create gstreamertestcases_suite2 foobar
+foobar Example gsttask.exe test_no_lock
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gsttask.exe test_lock
+create gstreamertestcases_suite2 foobar
+foobar Example gsttask.exe test_lock
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttask.exe test_lock_start
+create gstreamertestcases_suite2 foobar
+foobar Example gsttask.exe test_lock_start
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttask.exe test_join
+create gstreamertestcases_suite2 foobar
+foobar Example gsttask.exe test_join
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttag.exe test_merge
+create gstreamertestcases_suite2 foobar
+foobar Example gsttag.exe test_merge
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttag.exe test_date_tags
+create gstreamertestcases_suite2 foobar
+foobar Example gsttag.exe test_date_tags
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gsttag.exe test_type
+create gstreamertestcases_suite2 foobar
+foobar Example gsttag.exe test_type
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttag.exe test_set_non_utf8_string
+create gstreamertestcases_suite2 foobar
+foobar Example gsttag.exe test_set_non_utf8_string
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstquery.exe create_queries
+create gstreamertestcases_suite2 foobar
+foobar Example gstquery.exe create_queries
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstquery.exe test_queries
+create gstreamertestcases_suite2 foobar
+foobar Example gstquery.exe test_queries
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsturi.exe test_protocol_case
+create gstreamertestcases_suite2 foobar
+foobar Example gsturi.exe test_protocol_case
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gsturi.exe test_uri_get_location
+create gstreamertestcases_suite2 foobar
+foobar Example gsturi.exe test_uri_get_location
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstinterface.exe test_without_implements_interface
+create gstreamertestcases_suite2 foobar
+foobar Example gstinterface.exe test_without_implements_interface
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstparamspecs.exe test_param_spec_fraction
+create gstreamertestcases_suite2 foobar
+foobar Example gstparamspecs.exe test_param_spec_fraction
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstregistry.exe test_registry_update
+create gstreamertestcases_suite2 foobar
+foobar Example gstregistry.exe test_registry_update
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gsttagsetter.exe test_merge
+create gstreamertestcases_suite2 foobar
+foobar Example gsttagsetter.exe test_merge
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title element_gstfakesink.exe test_clipping
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesink.exe test_clipping
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesink.exe test_preroll_sync
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesink.exe test_preroll_sync
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesink.exe test_eos
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesink.exe test_eos
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesink.exe test_eos2
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesink.exe test_eos2
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesrc.exe test_num_buffers
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesrc.exe test_num_buffers
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title element_gstfakesrc.exe test_sizetype_empty
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesrc.exe test_sizetype_empty
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesrc.exe test_sizetype_random
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesrc.exe test_sizetype_random
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesrc.exe test_no_preroll
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesrc.exe test_no_preroll
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfakesrc.exe test_sizetype_fixed
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfakesrc.exe test_sizetype_fixed
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfilesink.exe test_coverage
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesink.exe test_coverage
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title element_gstfilesink.exe test_uri_interface
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesink.exe test_uri_interface
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfilesink.exe test_seeking
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesink.exe test_seeking
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfilesrc.exe test_seeking
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesrc.exe test_seeking
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfilesrc.exe test_reverse
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesrc.exe test_reverse
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfilesrc.exe test_pull
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesrc.exe test_pull
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title element_gstfilesrc.exe test_coverage
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesrc.exe test_coverage
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfilesrc.exe test_uri_interface
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstfilesrc.exe test_uri_interface
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstidentity.exe test_one_buffer
+create gstreamertestcases_suite2 foobar
+foobar Example element_gstidentity.exe test_one_buffer
+delete foobar
+[Endtest] 
Binary file gstreamer_core/tsrc/gstreamertestcases_suite2/data/khuda.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/group/GstreamerTestCases_DoxyFile.txt	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,239 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+# 
+# Description:
+#
+#
+
+# Doxyfile 1.4.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = GstreamerTestCases
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = \GstreamerTestCases\
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = NO
+GENERATE_TESTLIST      = NO
+GENERATE_BUGLIST       = NO
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = \GstreamerTestCases\
+FILE_PATTERNS          = *.h \
+                         *.rh \
+                         *.hrh
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = NO
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = YES
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = YES
+TOC_EXPAND             = YES
+DISABLE_INDEX          = YES
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = YES
+RTF_OUTPUT             = Doc
+COMPACT_RTF            = YES
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = NONSHARABLE_CLASS
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/group/GstreamerTestCases_suite2.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,80 @@
+/*TYPE TESTCLASS*/
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+TARGET          gstreamertestcases_suite2.dll
+TARGETTYPE      dll
+UID             0x1000008D 0x101FB5E5
+
+CAPABILITY      ALL -TCB
+/* Remove comments and replace 0x00000000 with correct vendor id */
+// VENDORID     0x00000000
+/* Remove comments and replace 0x00000000 with correct secure id */
+// SECUREID     0x00000000
+
+//TARGETPATH      ?target_path
+//DEFFILE         GstreamerTestCases.def
+
+USERINCLUDE     ../inc 
+
+OS_LAYER_SYSTEMINCLUDE
+
+SOURCEPATH      ../src
+
+SOURCE          GstreamerTestCases.cpp
+SOURCE          GstreamerTestCasesBlocks.cpp
+
+//RESOURCE        resource_file
+//RESOURCE        resource_file2
+
+LIBRARY         euser.lib
+LIBRARY         stiftestinterface.lib
+LIBRARY         stiftestengine.lib
+
+LANG            SC
+
+/*
+START WINS      
+?wins_specific_information
+END
+
+START MARM
+?marm_specific_information
+END
+*/
+// Other possible keywords:
+ 
+// DOCUMENT     ?file, that is not compiled, but added to MSVC project workspace (i.e. release notes)
+/*
+START BITMAP ?target
+TARGETPATH   ?emulated_path_on_target_machine
+HEADER
+SOURCE       ?color_depth ?source_bitmap
+END
+*/
+// DEFFILE ?filename
+// AIF ?filename
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+PRJ_PLATFORMS
+// specify the platforms your component needs to be built for here
+// defaults to WINS MARM so you can ignore this if you just build these
+	
+	DEFAULT
+
+PRJ_TESTEXPORTS
+// NOTE: If using ARS requirements all export operations should be done under this.
+// 'abld test export'
+
+
+
+PRJ_EXPORTS
+// Specify the source file followed by its destination here
+// copy will be used to copy the source file to its destination
+// If there's no destination then the source file will be copied
+// to the same name in \epoc32\include
+// Example: 
+/*
+\agnmodel\inc\AGMCOMON.H
+*/
+
+PRJ_TESTMMPFILES
+
+	GstreamerTestCases_suite2.mmp
+
+PRJ_MMPFILES
+//GstreamerTestCases_suite2.mmp
+
+	// GstreamerTestCases_nrm.mmp
+
+// Specify the .mmp files required for building the important component
+// releasables.
+//
+// Specify "tidy" if the component you need to build doesn't need to be
+// released. Specify "ignore" if the MMP file exists but should be
+// ignored.
+// Example:
+/*
+\agnmodel\group\agnmodel.mmp
+#if defined(MARM)
+\agnmodel\group\agsvexe.mmp
+#endif
+*/
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/group/gstreamer_testcases.pkg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,212 @@
+; ============================================================================
+;  Name        : gstreamer_testcases.pkg
+;  Part of     : Gstreamer project
+;  Description : Package file for all gstreamer test binaries
+;
+;  Version     : %version: 2 %
+;
+;  Copyright © 2002-2006 Nokia.  All rights reserved.
+;  This material, including documentation and any related computer
+;  programs, is protected by copyright controlled by Nokia.  All
+;  rights are reserved.  Copying, including reproducing, storing,
+;  adapting or translating, any or all of this material requires the
+;  prior written consent of Nokia.  This material also contains
+;  confidential information which may not be disclosed to others
+;  without the prior written consent of Nokia.
+; ============================================================================
+
+;Languages
+&EN
+
+;Header
+#{"gstreamer_testcases.pkg"},(0x2001F45C),1,0,0, TYPE=SU
+
+;Supports S60 3.0
+[0x101F7961], 0, 0, 0, {"S60ProductID"}
+
+;Localised Vendor name
+%{"Nokia Testing EN"}
+
+;Unique Vendor name
+:"Vendor"
+
+
+;gstreamer dll
+
+"\epoc32\winscw\c\gstreamer\plugins_list\gst_dll_2001F41F.txt" - "c:\gstreamer\plugins_list\gst_dll_2001F41F.txt"
+"\epoc32\release\armv5\urel\libgstadder.dll"-"!:\sys\bin\libgstadder.dll"
+"\epoc32\release\armv5\urel\libgstaudio.dll"-"!:\sys\bin\libgstaudio.dll"
+"\epoc32\release\armv5\urel\libgstbase.dll"-"!:\sys\bin\libgstbase.dll"
+"\epoc32\release\armv5\urel\libgstcdda.dll"-"!:\sys\bin\libgstcdda.dll"
+"\epoc32\release\armv5\urel\libgstcontroller.dll"-"!:\sys\bin\libgstcontroller.dll"
+"\epoc32\release\armv5\urel\libgstdataprotocol.dll"-"!:\sys\bin\libgstdataprotocol.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundext.dll"-"!:\sys\bin\libgstdevsoundext.dll"
+"\epoc32\release\armv5\urel\libgstfft.dll"-"!:\sys\bin\libgstfft.dll"
+"\epoc32\release\armv5\urel\libgstgdp.dll"-"!:\sys\bin\libgstgdp.dll"
+"\epoc32\release\armv5\urel\libgstinterfaces.dll"-"!:\sys\bin\libgstinterfaces.dll"
+"\epoc32\release\armv5\urel\libgstnet.dll"-"!:\sys\bin\libgstnet.dll"
+"\epoc32\release\armv5\urel\libgstnetbuffer.dll"-"!:\sys\bin\libgstnetbuffer.dll"
+"\epoc32\release\armv5\urel\libgstpbutils.dll"-"!:\sys\bin\libgstpbutils.dll"
+"\epoc32\release\armv5\urel\libgstreamer.dll"-"!:\sys\bin\libgstreamer.dll"
+"\epoc32\release\armv5\urel\libgstriff.dll"-"!:\sys\bin\libgstriff.dll"
+"\epoc32\release\armv5\urel\libgstrtp.dll"-"!:\sys\bin\libgstrtp.dll"
+"\epoc32\release\armv5\urel\libgstsubparse.dll"-"!:\sys\bin\libgstsubparse.dll"
+"\epoc32\release\armv5\urel\libgsttag.dll"-"!:\sys\bin\libgsttag.dll"
+"\epoc32\release\armv5\urel\libgsttcp.dll"-"!:\sys\bin\libgsttcp.dll"
+"\epoc32\release\armv5\urel\libgstvolume.dll"-"!:\sys\bin\libgstvolume.dll"
+"\epoc32\release\armv5\urel\libgstaudiorate.dll"-"!:\sys\bin\libgstaudiorate.dll"
+"\epoc32\release\armv5\urel\libgstaudioresample.dll"-"!:\sys\bin\libgstaudioresample.dll"
+"\epoc32\release\armv5\urel\libgstaudiotestsrc.dll"-"!:\sys\bin\libgstaudiotestsrc.dll"
+"\epoc32\release\armv5\urel\libgstcoreelements.dll"-"!:\sys\bin\libgstcoreelements.dll"
+"\epoc32\release\armv5\urel\libgstcoreindexers.dll"-"!:\sys\bin\libgstcoreindexers.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin.dll"-"!:\sys\bin\libgstdecodebin.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin2.dll"-"!:\sys\bin\libgstdecodebin2.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsink.dll"-"!:\sys\bin\libgstdevsoundsink.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsrc.dll"-"!:\sys\bin\libgstdevsoundsrc.dll"
+"\epoc32\release\armv5\urel\libgstplaybin.dll"-"!:\sys\bin\libgstplaybin.dll"
+"\epoc32\release\armv5\urel\libgsttypefindfunctions.dll"-"!:\sys\bin\libgsttypefindfunctions.dll"
+"\epoc32\release\armv5\urel\libgstwavparse.dll"-"!:\sys\bin\libgstwavparse.dll"
+"\epoc32\release\armv5\urel\libgstwavenc.dll"-"!:\sys\bin\libgstwavenc.dll"
+"\epoc32\release\armv5\urel\libgstaudioconvert.dll"-"!:\sys\bin\libgstaudioconvert.dll"
+"\epoc32\release\armv5\urel\libgstqueue2.dll"-"!:\sys\bin\libgstqueue2.dll"
+"\epoc32\release\armv5\urel\libgstapp.dll"-"!:\sys\bin\libgstapp.dll"
+"\epoc32\release\armv5\urel\libgstautodetect.dll"-"!:\sys\bin\libgstautodetect.dll"
+"\epoc32\release\armv5\urel\liboil.dll"-"!:\sys\bin\liboil.dll"
+"\epoc32\release\armv5\urel\gstreamertestcases_suite2.dll"-"!:\sys\bin\gstreamertestcases_suite2.dll"
+;"\epoc32\release\armv5\urel\libgstvideo.dll"-"!:\sys\bin\libgstvideo.dll"
+;"\epoc32\release\armv5\urel\libgstvideorate.dll"-"!:\sys\bin\libgstvideorate.dll"
+;"\epoc32\release\armv5\urel\libgstvideoscale.dll"-"!:\sys\bin\libgstvideoscale.dll"
+;"\epoc32\release\armv5\urel\libgstvideotestsrc.dll"-"!:\sys\bin\libgstvideotestsrc.dll"
+;"\epoc32\release\armv5\urel\libgstffmpegcolorspace.dll"-"!:\sys\bin\libgstffmpegcolorspace.dll"
+
+
+;gstregistry exe
+
+"\epoc32\release\armv5\urel\GSTRegistryGenerator.exe"		  -"!:\sys\bin\GSTRegistryGenerator.exe",FR,RI
+
+;gstreamer-core test exe's
+
+"\epoc32\release\armv5\urel\cleanup.exe"-"!:\sys\bin\cleanup.exe"
+"\epoc32\release\armv5\urel\createelementcore.exe"-"!:\sys\bin\createelementcore.exe"
+"\epoc32\release\armv5\urel\element_gstfakesink.exe"-"!:\sys\bin\element_gstfakesink.exe"
+"\epoc32\release\armv5\urel\element_gstfakesrc.exe"-"!:\sys\bin\element_gstfakesrc.exe"
+"\epoc32\release\armv5\urel\element_gstfdsrc.exe"-"!:\sys\bin\element_gstfdsrc.exe"
+"\epoc32\release\armv5\urel\element_gstfilesink.exe"-"!:\sys\bin\element_gstfilesink.exe"
+"\epoc32\release\armv5\urel\element_gstfilesrc.exe"-"!:\sys\bin\element_gstfilesrc.exe"
+"\epoc32\release\armv5\urel\element_gstidentity.exe"-"!:\sys\bin\element_gstidentity.exe"
+"\epoc32\release\armv5\urel\element_gstmultiqueue.exe"-"!:\sys\bin\element_gstmultiqueue.exe"
+"\epoc32\release\armv5\urel\element_gstqueue.exe"-"!:\sys\bin\element_gstqueue.exe"
+"\epoc32\release\armv5\urel\element_gsttee.exe"-"!:\sys\bin\element_gsttee.exe"
+"\epoc32\release\armv5\urel\gst.exe"-"!:\sys\bin\gst.exe"
+"\epoc32\release\armv5\urel\gstadapter.exe"-"!:\sys\bin\gstadapter.exe"
+"\epoc32\release\armv5\urel\gstbasesrc.exe"-"!:\sys\bin\gstbasesrc.exe"
+"\epoc32\release\armv5\urel\gstbin.exe"-"!:\sys\bin\gstbin.exe"
+"\epoc32\release\armv5\urel\gstbuffer.exe"-"!:\sys\bin\gstbuffer.exe"
+"\epoc32\release\armv5\urel\gstbus.exe"-"!:\sys\bin\gstbus.exe"
+"\epoc32\release\armv5\urel\gstcaps.exe"-"!:\sys\bin\gstcaps.exe"
+"\epoc32\release\armv5\urel\gstcollectpads.exe"-"!:\sys\bin\gstcollectpads.exe"
+"\epoc32\release\armv5\urel\gstcontroller.exe"-"!:\sys\bin\gstcontroller.exe"
+"\epoc32\release\armv5\urel\gstelement.exe"-"!:\sys\bin\gstelement.exe"
+"\epoc32\release\armv5\urel\gstevent.exe"-"!:\sys\bin\gstevent.exe"
+"\epoc32\release\armv5\urel\gstgdp.exe"-"!:\sys\bin\gstgdp.exe"
+"\epoc32\release\armv5\urel\gstghostpad.exe"-"!:\sys\bin\gstghostpad.exe"
+"\epoc32\release\armv5\urel\gstgstnetclientclock.exe"-"!:\sys\bin\gstgstnetclientclock.exe"
+"\epoc32\release\armv5\urel\gstgstnettimeprovider.exe"-"!:\sys\bin\gstgstnettimeprovider.exe"
+"\epoc32\release\armv5\urel\gstindex.exe"-"!:\sys\bin\gstindex.exe"
+"\epoc32\release\armv5\urel\gstinterface.exe"-"!:\sys\bin\gstinterface.exe"
+"\epoc32\release\armv5\urel\gstiterator.exe"-"!:\sys\bin\gstiterator.exe"
+"\epoc32\release\armv5\urel\gstlibsabi.exe"-"!:\sys\bin\gstlibsabi.exe"
+"\epoc32\release\armv5\urel\gstmessage.exe"-"!:\sys\bin\gstmessage.exe"
+"\epoc32\release\armv5\urel\gstminiobject.exe"-"!:\sys\bin\gstminiobject.exe"
+"\epoc32\release\armv5\urel\gstobject.exe"-"!:\sys\bin\gstobject.exe"
+"\epoc32\release\armv5\urel\gstpad.exe"-"!:\sys\bin\gstpad.exe"
+"\epoc32\release\armv5\urel\gstparamspecs.exe"-"!:\sys\bin\gstparamspecs.exe"
+"\epoc32\release\armv5\urel\gstpipeline.exe"-"!:\sys\bin\gstpipeline.exe"
+"\epoc32\release\armv5\urel\gstplugin.exe"-"!:\sys\bin\gstplugin.exe"
+"\epoc32\release\armv5\urel\gstpoll.exe"-"!:\sys\bin\gstpoll.exe"
+"\epoc32\release\armv5\urel\gstquery.exe"-"!:\sys\bin\gstquery.exe"
+"\epoc32\release\armv5\urel\gstregistry.exe"-"!:\sys\bin\gstregistry.exe"
+"\epoc32\release\armv5\urel\gstsegment.exe"-"!:\sys\bin\gstsegment.exe"
+"\epoc32\release\armv5\urel\gstsinks.exe"-"!:\sys\bin\gstsinks.exe"
+"\epoc32\release\armv5\urel\gststates.exe"-"!:\sys\bin\gststates.exe"
+"\epoc32\release\armv5\urel\gststructure.exe"-"!:\sys\bin\gststructure.exe"
+"\epoc32\release\armv5\urel\gstsystemclock.exe"-"!:\sys\bin\gstsystemclock.exe"
+"\epoc32\release\armv5\urel\gsttag.exe"-"!:\sys\bin\gsttag.exe"
+"\epoc32\release\armv5\urel\gsttagsetter.exe"-"!:\sys\bin\gsttagsetter.exe"
+"\epoc32\release\armv5\urel\gsttask.exe"-"!:\sys\bin\gsttask.exe"
+"\epoc32\release\armv5\urel\gsttypefindhelper.exe"-"!:\sys\bin\gsttypefindhelper.exe"
+"\epoc32\release\armv5\urel\gsturi.exe"-"!:\sys\bin\gsturi.exe"
+"\epoc32\release\armv5\urel\gstutils.exe"-"!:\sys\bin\gstutils.exe"
+"\epoc32\release\armv5\urel\gstvalue.exe"-"!:\sys\bin\gstvalue.exe"
+"\epoc32\release\armv5\urel\helloworld.exe"-"!:\sys\bin\helloworld.exe"
+"\epoc32\release\armv5\urel\launch.exe"-"!:\sys\bin\launch.exe"
+"\epoc32\release\armv5\urel\manual_dynamic.exe"-"!:\sys\bin\manual_dynamic.exe"
+"\epoc32\release\armv5\urel\manual_ghostpad.exe"-"!:\sys\bin\manual_ghostpad.exe"
+"\epoc32\release\armv5\urel\manual_gstbin.exe"-"!:\sys\bin\manual_gstbin.exe"
+"\epoc32\release\armv5\urel\manual_gstdecodebin.exe"-"!:\sys\bin\manual_gstdecodebin.exe"
+"\epoc32\release\armv5\urel\manual_gstelementcreate.exe"-"!:\sys\bin\manual_gstelementcreate.exe"
+"\epoc32\release\armv5\urel\manual_gstelementfactory.exe"-"!:\sys\bin\manual_gstelementfactory.exe"
+"\epoc32\release\armv5\urel\manual_gstelementget.exe"-"!:\sys\bin\manual_gstelementget.exe"
+"\epoc32\release\armv5\urel\manual_gstelementlink.exe"-"!:\sys\bin\manual_gstelementlink.exe"
+"\epoc32\release\armv5\urel\manual_gstelementmake.exe"-"!:\sys\bin\manual_gstelementmake.exe"
+"\epoc32\release\armv5\urel\manual_gstinit.exe"-"!:\sys\bin\manual_gstinit.exe"
+"\epoc32\release\armv5\urel\manual_gstpad.exe"-"!:\sys\bin\manual_gstpad.exe"
+"\epoc32\release\armv5\urel\manual_gstplaybin.exe"-"!:\sys\bin\manual_gstplaybin.exe"
+"\epoc32\release\armv5\urel\manual_gstquery.exe"-"!:\sys\bin\manual_gstquery.exe"
+"\epoc32\release\armv5\urel\manual_helloworld.exe"-"!:\sys\bin\manual_helloworld.exe"
+"\epoc32\release\armv5\urel\manual_typefind.exe"-"!:\sys\bin\manual_typefind.exe"
+"\epoc32\release\armv5\urel\metadata.exe"-"!:\sys\bin\metadata.exe"
+"\epoc32\release\armv5\urel\mp3launch.exe"-"!:\sys\bin\mp3launch.exe"
+"\epoc32\release\armv5\urel\parse-disabled.exe"-"!:\sys\bin\parse-disabled.exe"
+"\epoc32\release\armv5\urel\parse-launch.exe"-"!:\sys\bin\parse-launch.exe"
+"\epoc32\release\armv5\urel\simple-launch-lines.exe"-"!:\sys\bin\simple-launch-lines.exe"
+"\epoc32\release\armv5\urel\stress.exe"-"!:\sys\bin\stress.exe"
+"\epoc32\release\armv5\urel\testaudioexample.exe"-"!:\sys\bin\testaudioexample.exe"
+"\epoc32\release\armv5\urel\testgstadapter.exe"-"!:\sys\bin\testgstadapter.exe"
+"\epoc32\release\armv5\urel\testqueue.exe"-"!:\sys\bin\testqueue.exe"
+"\epoc32\release\armv5\urel\typefind.exe"-"!:\sys\bin\typefind.exe"
+
+
+
+;gst_plugins_base test exe's
+
+"\epoc32\release\armv5\urel\gstadder.exe"-"!:\sys\bin\gstadder.exe"
+"\epoc32\release\armv5\urel\gstaudioconvert.exe"-"!:\sys\bin\gstaudioconvert.exe"
+"\epoc32\release\armv5\urel\gstaudiorate.exe"-"!:\sys\bin\gstaudiorate.exe"
+"\epoc32\release\armv5\urel\gstaudioresample.exe"-"!:\sys\bin\gstaudioresample.exe"
+"\epoc32\release\armv5\urel\gstaudiotestsrc.exe"-"!:\sys\bin\gstaudiotestsrc.exe"
+"\epoc32\release\armv5\urel\createelementbase.exe"-"!:\sys\bin\createelementbase.exe"
+"\epoc32\release\armv5\urel\gstdecodebin.exe"-"!:\sys\bin\gstdecodebin.exe"
+"\epoc32\release\armv5\urel\gdpdepay.exe"-"!:\sys\bin\gdpdepay.exe"
+"\epoc32\release\armv5\urel\multifdsink.exe"-"!:\sys\bin\multifdsink.exe"
+"\epoc32\release\armv5\urel\playbin.exe"-"!:\sys\bin\playbin.exe"
+"\epoc32\release\armv5\urel\gstsubparse.exe"-"!:\sys\bin\gstsubparse.exe"
+"\epoc32\release\armv5\urel\volume.exe"-"!:\sys\bin\volume.exe"
+"\epoc32\release\armv5\urel\clock-selection.exe"-"!:\sys\bin\clock-selection.exe"
+"\epoc32\release\armv5\urel\states.exe"-"!:\sys\bin\states.exe"
+"\epoc32\release\armv5\urel\fft.exe"-"!:\sys\bin\fft.exe"
+;"\epoc32\release\armv5\urel\gstnetbuffer.exe"-"!:\sys\bin\gstnetbuffer.exe"
+"\epoc32\release\armv5\urel\pbutils.exe"-"!:\sys\bin\pbutils.exe"
+"\epoc32\release\armv5\urel\gst_plugin_rtp.exe"-"!:\sys\bin\gst_plugin_rtp.exe"
+"\epoc32\release\armv5\urel\gst_plugin_tag.exe"-"!:\sys\bin\gst_plugin_tag.exe"
+"\epoc32\release\armv5\urel\taudio.exe"-"!:\sys\bin\taudio.exe"
+"\epoc32\release\armv5\urel\gstsimple-launch-lines.exe"-"!:\sys\bin\gstsimple-launch-lines.exe"
+"\epoc32\release\armv5\urel\gststreamheader.exe"-"!:\sys\bin\gststreamheader.exe"
+"\epoc32\release\armv5\urel\stress_playbin.exe"-"!:\sys\bin\stress_playbin.exe"
+
+;"\epoc32\release\armv5\urel\ffmpegcolorspace.exe"-"!:\sys\bin\ffmpegcolorspace.exe"
+;"\epoc32\release\armv5\urel\addstream.exe"-"!:\sys\bin\addstream.exe"
+;"\epoc32\release\armv5\urel\video.exe"-"!:\sys\bin\video.exe"
+;"\epoc32\release\armv5\urel\typefindfunctions.exe" -"!:\sys\bin\typefindfunctions.exe"
+;"\epoc32\release\armv5\urel\videorate.exe"-"!:\sys\bin\videorate.exe"
+
+
+
+;dependecy files
+
+
+;Testframework.ini and conf files
+
+"..\conf\gstreamertestcases_suite2.cfg"-"c:\TestFramework\gstreamertestcases_suite2.cfg"
+"..\init\gstreamertestcases_suite2.ini"-"c:\TestFramework\gstreamertestcases_suite2.ini"
+"..\init\TestFramework.ini"-"c:\TestFramework\TestFramework.ini"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/inc/GstreamerTestCases.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,190 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: STIF testclass declaration
+*
+*/
+
+
+#ifndef GSTREAMERTESTCASES_H
+#define GSTREAMERTESTCASES_H
+
+//  INCLUDES
+#include <StifLogger.h>
+#include <TestScripterInternal.h>
+#include <StifTestModule.h>
+#include <TestclassAssert.h>
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+#define TEST_CLASS_VERSION_MAJOR 0
+#define TEST_CLASS_VERSION_MINOR 0
+#define TEST_CLASS_VERSION_BUILD 0
+
+// Logging path
+_LIT( KGstreamerTestCasesLogPath, "\\logs\\testframework\\GstreamerTestCases\\" ); 
+// Log file
+_LIT( KGstreamerTestCasesLogFile, "GstreamerTestCases.htm" ); 
+_LIT( KGstreamerTestCasesLogFileWithTitle, "GstreamerTestCases_[%S].htm" );
+
+// FUNCTION PROTOTYPES
+//?type ?function_name(?arg_list);
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+class CGstreamerTestCases;
+
+// DATA TYPES
+//enum ?declaration
+//typedef ?declaration
+//extern ?data_type;
+
+// CLASS DECLARATION
+
+/**
+*  CGstreamerTestCases test class for STIF Test Framework TestScripter.
+*  ?other_description_lines
+*
+*  @lib ?library
+*  @since ?Series60_version
+*/
+NONSHARABLE_CLASS(CGstreamerTestCases) : public CScriptBase
+    {
+    public:  // Constructors and destructor
+
+        /**
+        * Two-phased constructor.
+        */
+        static CGstreamerTestCases* NewL( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * Destructor.
+        */
+        virtual ~CGstreamerTestCases();
+
+    public: // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    public: // Functions from base classes
+
+        /**
+        * From CScriptBase Runs a script line.
+        * @since ?Series60_version
+        * @param aItem Script line containing method name and parameters
+        * @return Symbian OS error code
+        */
+        virtual TInt RunMethodL( CStifItemParser& aItem );
+
+    protected:  // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    protected:  // Functions from base classes
+
+        /**
+        * From ?base_class ?member_description
+        */
+        //?type ?member_function();
+
+    private:
+
+        /**
+        * C++ default constructor.
+        */
+        CGstreamerTestCases( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * By default Symbian 2nd phase constructor is private.
+        */
+        void ConstructL();
+
+        // Prohibit copy constructor if not deriving from CBase.
+        // ?classname( const ?classname& );
+        // Prohibit assigment operator if not deriving from CBase.
+        // ?classname& operator=( const ?classname& );
+
+        /**
+        * Frees all resources allocated from test methods.
+        * @since ?Series60_version
+        */
+        void Delete();
+
+        /**
+        * Test methods are listed below. 
+        */
+
+        /**
+        * Example test method.
+        * @since ?Series60_version
+        * @param aItem Script line containing parameters.
+        * @return Symbian OS error code.
+        */
+        virtual TInt ExampleL( CStifItemParser& aItem );
+        
+        /**
+         * Method used to log version of test class
+         */
+        void SendTestClassVersion();
+
+        //ADD NEW METHOD DEC HERE
+        //[TestMethods] - Do not remove
+
+    public:     // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    protected:  // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    private:    // Data
+        
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+        // Reserved pointer for future extension
+        //TAny* iReserved;
+
+    public:     // Friend classes
+        //?friend_class_declaration;
+    protected:  // Friend classes
+        //?friend_class_declaration;
+    private:    // Friend classes
+        //?friend_class_declaration;
+
+    };
+
+#endif      // GSTREAMERTESTCASES_H
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/init/gstreamertestcases_suite2.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+[general]
+logFileName gstreamertestcases_suite2.log
+logPath c:\logs\
+[general_end]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/init/testframework.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,184 @@
+#
+# This is STIFTestFramework initialization file
+# Comment lines start with '#'-character.
+# See STIF TestFramework users guide.doc for instructions
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set following test engine settings:
+#   - Set Test Reporting mode. TestReportMode's possible values are:
+#       + 'Summary': Summary of the tested test cases.
+#       + 'Environment': Hardware and software info.
+#       + 'TestCases': Test case report.
+#       + 'FullReport': Set of all above ones.
+#       + Example 'TestReportMode= Summary TestCases'
+#
+#   - CreateTestReport setting controls report creation mode
+#       + YES, Test report will created.
+#       + NO, No Test report.
+#
+#   - File path indicates the base path of the test report.
+#   - File name indicates the name of the test report.
+#
+#   - File format indicates the type of the test report.
+#       + TXT, Test report file will be txt type, for example 'TestReport.txt'.
+#       + HTML, Test report will be html type, for example 'TestReport.html'.
+#
+#   - File output indicates output source of the test report.
+#       + FILE, Test report logging to file.
+#       + RDEBUG, Test report logging to using rdebug.
+#
+#   - File Creation Mode indicates test report overwriting if file exist.
+#       + OVERWRITE, Overwrites if the Test report file exist.
+#       + APPEND, Continue logging after the old Test report information if
+#                 report exist.
+#   - Sets a device reset module's dll name(Reboot).
+#       + If Nokia specific reset module is not available or it is not correct one
+#         StifHWResetStub module may use as a template for user specific reset
+#         module.
+
+[Engine_Defaults]
+
+TestReportMode= FullReport      # Possible values are: 'Empty', 'Summary', 'Environment',
+                                                               'TestCases' or 'FullReport'
+
+CreateTestReport= YES           # Possible values: YES or NO
+
+TestReportFilePath= C:\LOGS\TestFramework\
+TestReportFileName= TestReport_gstreamertestcases_suite2
+
+TestReportFormat= HTML          # Possible values: TXT or HTML
+TestReportOutput= FILE          # Possible values: FILE or RDEBUG
+TestReportFileCreationMode= OVERWRITE   # Possible values: OVERWRITE or APPEND
+
+DeviceResetDllName= StifResetForNokia.dll # e.g. 'StifHWResetStub.dll' for user specific reseting
+
+[End_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Module configurations start
+# Modules are added between module tags
+# tags. Module name is specified after ModuleName= tag, like
+# ModuleName= XXXXXXXXX
+# Modules might have initialisation file, specified as
+# IniFile= c:\testframework\YYYYYY
+# Modules might have several configuration files, like
+# TestCaseFile= c:\testframework\NormalCases.txt
+# TestCaseFile= c:\testframework\SmokeCases.txt
+# TestCaseFile= c:\testframework\ManualCases.txt
+
+# (TestCaseFile is synonym for old term ConfigFile)
+
+# Following case specifies demo module settings. Demo module
+# does not read any settings from file, so tags
+# IniFile and TestCaseFile are not used.
+# In the simplest case it is enough to specify only the
+# name of the test module when adding new test module
+
+#[New_Module]
+#ModuleName= demomodule
+#[End_Module]
+
+
+[New_Module]
+ModuleName= TestScripter
+TestCaseFile= c:\testframework\gstreamertestcases_suite2.cfg
+IniFile= c:\testframework\GStreamerTestCases.ini
+[End_Module]
+
+# Load testmoduleXXX, optionally with initialization file and/or test case files
+#[New_Module]
+#ModuleName= testmodulexxx
+
+#TestModuleXXX used initialization file
+#IniFile= c:\testframework\init.txt
+
+#TestModuleXXX used configuration file(s)
+#TestCaseFile= c:\testframework\testcases1.cfg
+#TestCaseFile= c:\testframework\testcases2.cfg
+#TestCaseFile= c:\testframework\manualtestcases.cfg
+
+#[End_Module]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set STIFTestFramework logging overwrite parameters for Logger.
+#   Hardware and emulator environment logging path and styles can
+#   be configured from here to overwrite the Logger's implemented values.
+#
+#   Settings description:
+#   - Indicates option for creation log directory/directories. If log directory/directories
+#         is/are not created by user they will make by software.
+#       + YES, Create log directory/directories if not allready exist.
+#       + NO, Log directory/directories not created. Only created one is used.
+#
+#   - Overwrite emulator path setting.
+#       + Example: If 'EmulatorBasePath= C:\LOGS\TestFramework\' and in code is defined
+#                  Logger's path 'D:\\LOGS\\Module\\' with those definition the path
+#                  will be 'C:\LOGS\TestFramework\LOGS\Module\'
+#
+#   - Overwrite emulator's logging format.
+#       + TXT, Log file(s) will be txt type(s), for example 'Module.txt'.
+#       + HTML, Log file(s) will be html type(s), for example 'Module.html'.
+#
+#   - Overwrited emulator logging output source.
+#       + FILE, Logging to file(s).
+#       + RDEBUG, Logging to using rdebug(s).
+#
+#   - Overwrite hardware path setting (Same description as above in emulator path).
+#   - Overwrite hardware's logging format(Same description as above in emulator format).
+#   - Overwrite hardware's logging output source(Same description as above in emulator output).
+#
+#   - File Creation Mode indicates file overwriting if file exist.
+#       + OVERWRITE, Overwrites if file(s) exist.
+#       + APPEND, Continue logging after the old logging information if file(s) exist.
+#
+#   - Will thread id include to the log filename.
+#       + YES, Thread id to log file(s) name, Example filename 'Module_b9.txt'.
+#       + NO, No thread id to log file(s), Example filename 'Module.txt'.
+#
+#   - Will time stamps include the to log file.
+#       + YES, Time stamp added to each line in log file(s). Time stamp is
+#                 for example'12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No time stamp(s).
+#
+#   - Will line breaks include to the log file.
+#       + YES, Each logging event includes line break and next log event is in own line.
+#       + NO, No line break(s).
+#
+#   - Will event ranking include to the log file.
+#       + YES, Event ranking number added to each line in log file(s). Ranking number
+#                 depends on environment's tics, for example(includes time stamp also)
+#                 '012   12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No event ranking.
+#
+
+[Logger_Defaults]
+
+#NOTE: If you want to set Logger using next setting(s) remove comment(s)'#'
+
+#CreateLogDirectories= YES      # Possible values: YES or NO
+
+#EmulatorBasePath= C:\LOGS\TestFramework\
+#EmulatorFormat= HTML           # Possible values: TXT or HTML
+#EmulatorOutput= FILE           # Possible values: FILE or RDEBUG
+
+#HardwareBasePath= D:\LOGS\TestFramework\
+#HardwareFormat= HTML           # Possible values: TXT or HTML
+#HardwareOutput= FILE           # Possible values: FILE or RDEBUG
+
+#FileCreationMode= OVERWRITE        # Possible values: OVERWRITE or APPEND
+
+#ThreadIdToLogFile= YES             # Possible values: YES or NO
+#WithTimeStamp= YES             # Possible values: YES or NO
+#WithLineBreak= YES             # Possible values: YES or NO
+#WithEventRanking= YES          # Possible values: YES or NO
+
+[End_Logger_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+# End of file
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/src/GstreamerTestCases.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,204 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// INCLUDE FILES
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+#include <SettingServerClient.h>
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::CGstreamerTestCases
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases::CGstreamerTestCases( 
+    CTestModuleIf& aTestModuleIf ):
+        CScriptBase( aTestModuleIf )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::ConstructL()
+    {
+    //Read logger settings to check whether test case name is to be
+    //appended to log file name.
+    RSettingServer settingServer;
+    TInt ret = settingServer.Connect();
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        }
+    // Struct to StifLogger settigs.
+    TLoggerSettings loggerSettings; 
+    // Parse StifLogger defaults from STIF initialization file.
+    ret = settingServer.GetLoggerSettings(loggerSettings);
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        } 
+    // Close Setting server session
+    settingServer.Close();
+
+    TFileName logFileName;
+    
+    if(loggerSettings.iAddTestCaseTitle)
+        {
+        TName title;
+        TestModuleIf().GetTestCaseTitleL(title);
+        logFileName.Format(KGstreamerTestCasesLogFileWithTitle, &title);
+        }
+    else
+        {
+        logFileName.Copy(KGstreamerTestCasesLogFile);
+        }
+
+    iLog = CStifLogger::NewL( KGstreamerTestCasesLogPath, 
+                          logFileName,
+                          CStifLogger::ETxt,
+                          CStifLogger::EFile,
+                          EFalse );
+    
+    SendTestClassVersion();
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases* CGstreamerTestCases::NewL( 
+    CTestModuleIf& aTestModuleIf )
+    {
+    CGstreamerTestCases* self = new (ELeave) CGstreamerTestCases( aTestModuleIf );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+
+    }
+
+// Destructor
+CGstreamerTestCases::~CGstreamerTestCases()
+    { 
+
+    // Delete resources allocated from test methods
+    Delete();
+
+    // Delete logger
+    delete iLog; 
+
+    }
+
+//-----------------------------------------------------------------------------
+// CGstreamerTestCases::SendTestClassVersion
+// Method used to send version of test class
+//-----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::SendTestClassVersion()
+	{
+	TVersion moduleVersion;
+	moduleVersion.iMajor = TEST_CLASS_VERSION_MAJOR;
+	moduleVersion.iMinor = TEST_CLASS_VERSION_MINOR;
+	moduleVersion.iBuild = TEST_CLASS_VERSION_BUILD;
+	
+	TFileName moduleName;
+	moduleName = _L("GstreamerTestCases.dll");
+
+	TBool newVersionOfMethod = ETrue;
+	TestModuleIf().SendTestModuleVersion(moduleVersion, moduleName, newVersionOfMethod);
+	}
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// -----------------------------------------------------------------------------
+// LibEntryL is a polymorphic Dll entry point.
+// Returns: CScriptBase: New CScriptBase derived object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CScriptBase* LibEntryL( 
+    CTestModuleIf& aTestModuleIf ) // Backpointer to STIF Test Framework
+    {
+
+    return ( CScriptBase* ) CGstreamerTestCases::NewL( aTestModuleIf );
+
+    }
+
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite2/src/GstreamerTestCasesBlocks.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,237 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// [INCLUDE FILES] - do not remove
+#include <e32svr.h>
+#include <StifParser.h>
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::Delete
+// Delete here all resources allocated and opened from test methods. 
+// Called from destructor. 
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::Delete() 
+    {
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::RunMethodL
+// Run specified method. Contains also table of test mothods and their names.
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::RunMethodL( 
+    CStifItemParser& aItem ) 
+    {
+
+    static TStifFunctionInfo const KFunctions[] =
+        {  
+        // Copy this line for every implemented function.
+        // First string is the function name used in TestScripter script file.
+        // Second is the actual implementation member function. 
+        ENTRY( "Example", CGstreamerTestCases::ExampleL ),
+        //ADD NEW ENTRY HERE
+        // [test cases entries] - Do not remove
+
+        };
+
+    const TInt count = sizeof( KFunctions ) / 
+                        sizeof( TStifFunctionInfo );
+
+    return RunInternalL( KFunctions, count, aItem );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ExampleL
+// Example test method function.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::ExampleL( CStifItemParser& aItem )
+{
+    TInt err = KErrNone;
+    RTimer timeoutTimer;
+    // Print to UI
+//    _LIT( KGstreamerTestCases, "GstreamerTestCases" );
+//    _LIT( KExample, "Test case: " );
+//    TestModuleIf().Printf( 0, KGstreamerTestCases, KExample );
+    // Print to log file
+
+    TPtrC string[2];
+    TFileName arg;
+    //_LIT( KParam, "Param[%i]: %S" );
+    
+    if( aItem.GetNextString ( string[0] ) != KErrNone)
+    {
+        iLog->Log( _L(">> Test cases Not Found") );
+        return -1;
+    }
+    iLog->Log( _L( "Test case Name is : " ) );
+    iLog->Log( string[0] );
+    
+    while ( aItem.GetNextString ( string[1] ) == KErrNone )
+    {
+        iLog->Log( string[1] );
+        arg.Append( string[1] );
+        arg.Append( TChar(' ') );
+    }
+    
+    
+    _LIT( KArg, "Arg: " );
+    iLog->Log( KArg );
+    iLog->Log( arg );
+    RProcess process;
+    err = process.Create( string[0],arg );
+    
+    if( !err )
+    {
+
+        if( timeoutTimer.CreateLocal() != KErrNone )
+        {
+            iLog->Log( _L(">> timeoutTimer.CreateLocal failed") );
+        }
+    
+        iLog->Log( _L(">> Test cases Started") );
+        TRequestStatus processStatus = KRequestPending;
+        TRequestStatus timerStatus = KRequestPending;
+        process.Logon( processStatus );
+        
+        process.Resume();
+        TTimeIntervalMicroSeconds32 timeout = 1 * 60 * 1000000;
+        timeoutTimer.After( timerStatus, timeout );
+        
+        while( processStatus == KRequestPending && timerStatus == KRequestPending )
+        {
+            User::WaitForAnyRequest();
+            
+        }
+        
+        err = process.ExitReason();
+        if( timerStatus != KRequestPending )
+        {
+            err = KErrTimedOut;
+        }
+        
+        process.LogonCancel( processStatus );
+        timeoutTimer.Cancel();
+        /// required to complete one of the pending request..
+        User::WaitForAnyRequest();
+        
+        process.Kill( KErrNone );
+        process.Close();
+        timeoutTimer.Close();
+        iLog->Log( _L(">> test cases completed") );
+    }
+    else
+    {
+        iLog->Log( _L(">> test cases exe not found") );
+    }
+
+
+    if( err != KErrNone )
+    {
+        iLog->Log( CStifLogger::ERed, _L( "Test cases FAILED!" ) );
+    }
+    else
+    {
+        iLog->Log( CStifLogger::EGreen, _L( "Test cases PASSED!" ) );
+    }
+    
+
+    return err;
+}
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+/*
+TInt CGstreamerTestCases::?member_function(
+   CItemParser& aItem )
+   {
+
+   ?code
+
+   }
+*/
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+// None
+
+//  [End of File] - Do not remove
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/Bwins/gstreamertestcases_suite3u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	?LibEntryL@@YAPAVCScriptBase@@AAVCTestModuleIf@@@Z @ 1 NONAME ; class CScriptBase * LibEntryL(class CTestModuleIf &)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/EABI/gstreamertestcases_suite3u.def	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_Z9LibEntryLR13CTestModuleIf @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/conf/gstreamertestcases_suite3.cfg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,180 @@
+[Test]
+title element_gstmultiqueue.exe test_simple_create_destroy
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstmultiqueue.exe test_simple_create_destroy
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstmultiqueue.exe test_simple_pipeline
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstmultiqueue.exe test_simple_pipeline
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title element_gstmultiqueue.exe test_simple_shutdown_while_running
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstmultiqueue.exe test_simple_shutdown_while_running
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstqueue.exe test_non_leaky_underrun
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstqueue.exe test_non_leaky_underrun
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstqueue.exe test_non_leaky_overrun
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstqueue.exe test_non_leaky_overrun
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstqueue.exe test_leaky_upstream
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstqueue.exe test_leaky_upstream
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstqueue.exe test_leaky_downstream
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstqueue.exe test_leaky_downstream
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title element_gstqueue.exe test_time_level
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstqueue.exe test_time_level
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfdsrc.exe test_num_buffers
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstfdsrc.exe test_num_buffers
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfdsrc.exe test_nonseeking
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstfdsrc.exe test_nonseeking
+delete foobar
+[Endtest] 
+
+
+[Test]
+title element_gstfdsrc.exe test_seeking
+create gstreamertestcases_suite3 foobar
+foobar Example element_gstfdsrc.exe test_seeking
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcollectpads.exe test_pad_add_remove
+create gstreamertestcases_suite3 foobar
+foobar Example gstcollectpads.exe test_pad_add_remove
+delete foobar
+[Endtest] 
+
+
+
+[Test]
+title gstcollectpads.exe test_collect
+create gstreamertestcases_suite3 foobar
+foobar Example gstcollectpads.exe test_collect
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcollectpads.exe test_collect_eos
+create gstreamertestcases_suite3 foobar
+foobar Example gstcollectpads.exe test_collect_eos
+delete foobar
+[Endtest] 
+
+
+[Test]
+title gstcollectpads.exe test_collect_twice
+create gstreamertestcases_suite3 foobar
+foobar Example gstcollectpads.exe test_collect_twice
+delete foobar
+[Endtest]
+
+[Test]
+title gstaudioresample.exe test_live_switch
+create gstreamertestcases_suite3 foobar
+foobar Example gstaudioresample.exe test_live_switch
+delete foobar
+[Endtest]
+
+[Test]
+title gstaudioresample.exe test_pipelines
+create gstreamertestcases_suite3 foobar
+foobar Example gstaudioresample.exe test_pipelines
+delete foobar
+[Endtest]
+
+[Test]
+title gstaudioresample.exe test_preference_passthrough
+create gstreamertestcases_suite3 foobar
+foobar Example gstaudioresample.exe test_preference_passthrough
+delete foobar
+[Endtest]
+
+
+
+[Test]
+title parse-launch.exe test_launch_lines
+create gstreamertestcases_suite3 foobar
+foobar Example parse-launch.exe test_launch_lines
+delete foobar
+[Endtest] 
+
+
+[Test]
+title parse-launch.exe test_launch_lines2
+create gstreamertestcases_suite3 foobar
+foobar Example parse-launch.exe test_launch_lines2
+delete foobar
+[Endtest] 
+
+[Test]
+title parse-launch.exe expected_to_fail_pipes
+create gstreamertestcases_suite3 foobar
+foobar Example parse-launch.exe expected_to_fail_pipes
+delete foobar
+[Endtest] 
+
+[Test]
+title parse-launch.exe leaking_fail_pipes
+create gstreamertestcases_suite3 foobar
+foobar Example parse-launch.exe leaking_fail_pipes
+delete foobar
+[Endtest] 
+
+[Test]
+title parse-launch.exe delayed_link
+create gstreamertestcases_suite3 foobar
+foobar Example parse-launch.exe delayed_link
+delete foobar
+[Endtest] 
\ No newline at end of file
Binary file gstreamer_core/tsrc/gstreamertestcases_suite3/data/khuda.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/group/GstreamerTestCases_DoxyFile.txt	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,239 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+# 
+# Description:
+#
+#
+
+# Doxyfile 1.4.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = GstreamerTestCases
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = \GstreamerTestCases\
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = NO
+GENERATE_TESTLIST      = NO
+GENERATE_BUGLIST       = NO
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = \GstreamerTestCases\
+FILE_PATTERNS          = *.h \
+                         *.rh \
+                         *.hrh
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = NO
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = YES
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = YES
+TOC_EXPAND             = YES
+DISABLE_INDEX          = YES
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = YES
+RTF_OUTPUT             = Doc
+COMPACT_RTF            = YES
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = NONSHARABLE_CLASS
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/group/GstreamerTestCases_suite3.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,81 @@
+/*TYPE TESTCLASS*/
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+TARGET          gstreamertestcases_suite3.dll
+TARGETTYPE      dll
+UID             0x1000008D 0x101FB6E6
+
+CAPABILITY      ALL -TCB
+
+/* Remove comments and replace 0x00000000 with correct vendor id */
+// VENDORID     0x00000000
+/* Remove comments and replace 0x00000000 with correct secure id */
+// SECUREID     0x00000000
+
+//TARGETPATH      ?target_path
+//DEFFILE         GstreamerTestCases.def
+
+USERINCLUDE     ../inc 
+
+OS_LAYER_SYSTEMINCLUDE
+
+SOURCEPATH      ../src
+
+SOURCE          GstreamerTestCases.cpp
+SOURCE          GstreamerTestCasesBlocks.cpp
+
+//RESOURCE        resource_file
+//RESOURCE        resource_file2
+
+LIBRARY         euser.lib
+LIBRARY         stiftestinterface.lib
+LIBRARY         stiftestengine.lib
+
+LANG            SC
+
+/*
+START WINS      
+?wins_specific_information
+END
+
+START MARM
+?marm_specific_information
+END
+*/
+// Other possible keywords:
+ 
+// DOCUMENT     ?file, that is not compiled, but added to MSVC project workspace (i.e. release notes)
+/*
+START BITMAP ?target
+TARGETPATH   ?emulated_path_on_target_machine
+HEADER
+SOURCE       ?color_depth ?source_bitmap
+END
+*/
+// DEFFILE ?filename
+// AIF ?filename
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
+
+PRJ_PLATFORMS
+// specify the platforms your component needs to be built for here
+// defaults to WINS MARM so you can ignore this if you just build these
+	
+	DEFAULT
+
+PRJ_TESTEXPORTS
+// NOTE: If using ARS requirements all export operations should be done under this.
+// 'abld test export'
+
+
+
+PRJ_EXPORTS
+// Specify the source file followed by its destination here
+// copy will be used to copy the source file to its destination
+// If there's no destination then the source file will be copied
+// to the same name in \epoc32\include
+// Example: 
+/*
+\agnmodel\inc\AGMCOMON.H
+*/
+
+PRJ_TESTMMPFILES
+
+	GstreamerTestCases_suite3.mmp
+
+PRJ_MMPFILES
+//GstreamerTestCases_suite3.mmp
+
+	// GstreamerTestCases_nrm.mmp
+
+// Specify the .mmp files required for building the important component
+// releasables.
+//
+// Specify "tidy" if the component you need to build doesn't need to be
+// released. Specify "ignore" if the MMP file exists but should be
+// ignored.
+// Example:
+/*
+\agnmodel\group\agnmodel.mmp
+#if defined(MARM)
+\agnmodel\group\agsvexe.mmp
+#endif
+*/
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/group/gstreamer_testcases.pkg	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,212 @@
+; ============================================================================
+;  Name        : gstreamer_testcases.pkg
+;  Part of     : Gstreamer project
+;  Description : Package file for all gstreamer test binaries
+;
+;  Version     : %version: 2 %
+;
+;  Copyright © 2002-2006 Nokia.  All rights reserved.
+;  This material, including documentation and any related computer
+;  programs, is protected by copyright controlled by Nokia.  All
+;  rights are reserved.  Copying, including reproducing, storing,
+;  adapting or translating, any or all of this material requires the
+;  prior written consent of Nokia.  This material also contains
+;  confidential information which may not be disclosed to others
+;  without the prior written consent of Nokia.
+; ============================================================================
+
+;Languages
+&EN
+
+;Header
+#{"gstreamer_testcases.pkg"},(0x2001F45C),1,0,0, TYPE=SU
+
+;Supports S60 3.0
+[0x101F7961], 0, 0, 0, {"S60ProductID"}
+
+;Localised Vendor name
+%{"Nokia Testing EN"}
+
+;Unique Vendor name
+:"Vendor"
+
+
+;gstreamer dll
+
+"\epoc32\winscw\c\gstreamer\plugins_list\gst_dll_2001F41F.txt" - "c:\gstreamer\plugins_list\gst_dll_2001F41F.txt"
+"\epoc32\release\armv5\urel\libgstadder.dll"-"!:\sys\bin\libgstadder.dll"
+"\epoc32\release\armv5\urel\libgstaudio.dll"-"!:\sys\bin\libgstaudio.dll"
+"\epoc32\release\armv5\urel\libgstbase.dll"-"!:\sys\bin\libgstbase.dll"
+"\epoc32\release\armv5\urel\libgstcdda.dll"-"!:\sys\bin\libgstcdda.dll"
+"\epoc32\release\armv5\urel\libgstcontroller.dll"-"!:\sys\bin\libgstcontroller.dll"
+"\epoc32\release\armv5\urel\libgstdataprotocol.dll"-"!:\sys\bin\libgstdataprotocol.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundext.dll"-"!:\sys\bin\libgstdevsoundext.dll"
+"\epoc32\release\armv5\urel\libgstfft.dll"-"!:\sys\bin\libgstfft.dll"
+"\epoc32\release\armv5\urel\libgstgdp.dll"-"!:\sys\bin\libgstgdp.dll"
+"\epoc32\release\armv5\urel\libgstinterfaces.dll"-"!:\sys\bin\libgstinterfaces.dll"
+"\epoc32\release\armv5\urel\libgstnet.dll"-"!:\sys\bin\libgstnet.dll"
+"\epoc32\release\armv5\urel\libgstnetbuffer.dll"-"!:\sys\bin\libgstnetbuffer.dll"
+"\epoc32\release\armv5\urel\libgstpbutils.dll"-"!:\sys\bin\libgstpbutils.dll"
+"\epoc32\release\armv5\urel\libgstreamer.dll"-"!:\sys\bin\libgstreamer.dll"
+"\epoc32\release\armv5\urel\libgstriff.dll"-"!:\sys\bin\libgstriff.dll"
+"\epoc32\release\armv5\urel\libgstrtp.dll"-"!:\sys\bin\libgstrtp.dll"
+"\epoc32\release\armv5\urel\libgstsubparse.dll"-"!:\sys\bin\libgstsubparse.dll"
+"\epoc32\release\armv5\urel\libgsttag.dll"-"!:\sys\bin\libgsttag.dll"
+"\epoc32\release\armv5\urel\libgsttcp.dll"-"!:\sys\bin\libgsttcp.dll"
+"\epoc32\release\armv5\urel\libgstvolume.dll"-"!:\sys\bin\libgstvolume.dll"
+"\epoc32\release\armv5\urel\libgstaudiorate.dll"-"!:\sys\bin\libgstaudiorate.dll"
+"\epoc32\release\armv5\urel\libgstaudioresample.dll"-"!:\sys\bin\libgstaudioresample.dll"
+"\epoc32\release\armv5\urel\libgstaudiotestsrc.dll"-"!:\sys\bin\libgstaudiotestsrc.dll"
+"\epoc32\release\armv5\urel\libgstcoreelements.dll"-"!:\sys\bin\libgstcoreelements.dll"
+"\epoc32\release\armv5\urel\libgstcoreindexers.dll"-"!:\sys\bin\libgstcoreindexers.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin.dll"-"!:\sys\bin\libgstdecodebin.dll"
+"\epoc32\release\armv5\urel\libgstdecodebin2.dll"-"!:\sys\bin\libgstdecodebin2.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsink.dll"-"!:\sys\bin\libgstdevsoundsink.dll"
+"\epoc32\release\armv5\urel\libgstdevsoundsrc.dll"-"!:\sys\bin\libgstdevsoundsrc.dll"
+"\epoc32\release\armv5\urel\libgstplaybin.dll"-"!:\sys\bin\libgstplaybin.dll"
+"\epoc32\release\armv5\urel\libgsttypefindfunctions.dll"-"!:\sys\bin\libgsttypefindfunctions.dll"
+"\epoc32\release\armv5\urel\libgstwavparse.dll"-"!:\sys\bin\libgstwavparse.dll"
+"\epoc32\release\armv5\urel\libgstwavenc.dll"-"!:\sys\bin\libgstwavenc.dll"
+"\epoc32\release\armv5\urel\libgstaudioconvert.dll"-"!:\sys\bin\libgstaudioconvert.dll"
+"\epoc32\release\armv5\urel\libgstqueue2.dll"-"!:\sys\bin\libgstqueue2.dll"
+"\epoc32\release\armv5\urel\libgstapp.dll"-"!:\sys\bin\libgstapp.dll"
+"\epoc32\release\armv5\urel\libgstautodetect.dll"-"!:\sys\bin\libgstautodetect.dll"
+"\epoc32\release\armv5\urel\liboil.dll"-"!:\sys\bin\liboil.dll"
+"\epoc32\release\armv5\urel\gstreamertestcases_suite3.dll"-"!:\sys\bin\gstreamertestcases_suite3.dll"
+;"\epoc32\release\armv5\urel\libgstvideo.dll"-"!:\sys\bin\libgstvideo.dll"
+;"\epoc32\release\armv5\urel\libgstvideorate.dll"-"!:\sys\bin\libgstvideorate.dll"
+;"\epoc32\release\armv5\urel\libgstvideoscale.dll"-"!:\sys\bin\libgstvideoscale.dll"
+;"\epoc32\release\armv5\urel\libgstvideotestsrc.dll"-"!:\sys\bin\libgstvideotestsrc.dll"
+;"\epoc32\release\armv5\urel\libgstffmpegcolorspace.dll"-"!:\sys\bin\libgstffmpegcolorspace.dll"
+
+
+;gstregistry exe
+
+"\epoc32\release\armv5\urel\GSTRegistryGenerator.exe"		  -"!:\sys\bin\GSTRegistryGenerator.exe",FR,RI
+
+;gstreamer-core test exe's
+
+"\epoc32\release\armv5\urel\cleanup.exe"-"!:\sys\bin\cleanup.exe"
+"\epoc32\release\armv5\urel\createelementcore.exe"-"!:\sys\bin\createelementcore.exe"
+"\epoc32\release\armv5\urel\element_gstfakesink.exe"-"!:\sys\bin\element_gstfakesink.exe"
+"\epoc32\release\armv5\urel\element_gstfakesrc.exe"-"!:\sys\bin\element_gstfakesrc.exe"
+"\epoc32\release\armv5\urel\element_gstfdsrc.exe"-"!:\sys\bin\element_gstfdsrc.exe"
+"\epoc32\release\armv5\urel\element_gstfilesink.exe"-"!:\sys\bin\element_gstfilesink.exe"
+"\epoc32\release\armv5\urel\element_gstfilesrc.exe"-"!:\sys\bin\element_gstfilesrc.exe"
+"\epoc32\release\armv5\urel\element_gstidentity.exe"-"!:\sys\bin\element_gstidentity.exe"
+"\epoc32\release\armv5\urel\element_gstmultiqueue.exe"-"!:\sys\bin\element_gstmultiqueue.exe"
+"\epoc32\release\armv5\urel\element_gstqueue.exe"-"!:\sys\bin\element_gstqueue.exe"
+"\epoc32\release\armv5\urel\element_gsttee.exe"-"!:\sys\bin\element_gsttee.exe"
+"\epoc32\release\armv5\urel\gst.exe"-"!:\sys\bin\gst.exe"
+"\epoc32\release\armv5\urel\gstadapter.exe"-"!:\sys\bin\gstadapter.exe"
+"\epoc32\release\armv5\urel\gstbasesrc.exe"-"!:\sys\bin\gstbasesrc.exe"
+"\epoc32\release\armv5\urel\gstbin.exe"-"!:\sys\bin\gstbin.exe"
+"\epoc32\release\armv5\urel\gstbuffer.exe"-"!:\sys\bin\gstbuffer.exe"
+"\epoc32\release\armv5\urel\gstbus.exe"-"!:\sys\bin\gstbus.exe"
+"\epoc32\release\armv5\urel\gstcaps.exe"-"!:\sys\bin\gstcaps.exe"
+"\epoc32\release\armv5\urel\gstcollectpads.exe"-"!:\sys\bin\gstcollectpads.exe"
+"\epoc32\release\armv5\urel\gstcontroller.exe"-"!:\sys\bin\gstcontroller.exe"
+"\epoc32\release\armv5\urel\gstelement.exe"-"!:\sys\bin\gstelement.exe"
+"\epoc32\release\armv5\urel\gstevent.exe"-"!:\sys\bin\gstevent.exe"
+"\epoc32\release\armv5\urel\gstgdp.exe"-"!:\sys\bin\gstgdp.exe"
+"\epoc32\release\armv5\urel\gstghostpad.exe"-"!:\sys\bin\gstghostpad.exe"
+"\epoc32\release\armv5\urel\gstgstnetclientclock.exe"-"!:\sys\bin\gstgstnetclientclock.exe"
+"\epoc32\release\armv5\urel\gstgstnettimeprovider.exe"-"!:\sys\bin\gstgstnettimeprovider.exe"
+"\epoc32\release\armv5\urel\gstindex.exe"-"!:\sys\bin\gstindex.exe"
+"\epoc32\release\armv5\urel\gstinterface.exe"-"!:\sys\bin\gstinterface.exe"
+"\epoc32\release\armv5\urel\gstiterator.exe"-"!:\sys\bin\gstiterator.exe"
+"\epoc32\release\armv5\urel\gstlibsabi.exe"-"!:\sys\bin\gstlibsabi.exe"
+"\epoc32\release\armv5\urel\gstmessage.exe"-"!:\sys\bin\gstmessage.exe"
+"\epoc32\release\armv5\urel\gstminiobject.exe"-"!:\sys\bin\gstminiobject.exe"
+"\epoc32\release\armv5\urel\gstobject.exe"-"!:\sys\bin\gstobject.exe"
+"\epoc32\release\armv5\urel\gstpad.exe"-"!:\sys\bin\gstpad.exe"
+"\epoc32\release\armv5\urel\gstparamspecs.exe"-"!:\sys\bin\gstparamspecs.exe"
+"\epoc32\release\armv5\urel\gstpipeline.exe"-"!:\sys\bin\gstpipeline.exe"
+"\epoc32\release\armv5\urel\gstplugin.exe"-"!:\sys\bin\gstplugin.exe"
+"\epoc32\release\armv5\urel\gstpoll.exe"-"!:\sys\bin\gstpoll.exe"
+"\epoc32\release\armv5\urel\gstquery.exe"-"!:\sys\bin\gstquery.exe"
+"\epoc32\release\armv5\urel\gstregistry.exe"-"!:\sys\bin\gstregistry.exe"
+"\epoc32\release\armv5\urel\gstsegment.exe"-"!:\sys\bin\gstsegment.exe"
+"\epoc32\release\armv5\urel\gstsinks.exe"-"!:\sys\bin\gstsinks.exe"
+"\epoc32\release\armv5\urel\gststates.exe"-"!:\sys\bin\gststates.exe"
+"\epoc32\release\armv5\urel\gststructure.exe"-"!:\sys\bin\gststructure.exe"
+"\epoc32\release\armv5\urel\gstsystemclock.exe"-"!:\sys\bin\gstsystemclock.exe"
+"\epoc32\release\armv5\urel\gsttag.exe"-"!:\sys\bin\gsttag.exe"
+"\epoc32\release\armv5\urel\gsttagsetter.exe"-"!:\sys\bin\gsttagsetter.exe"
+"\epoc32\release\armv5\urel\gsttask.exe"-"!:\sys\bin\gsttask.exe"
+"\epoc32\release\armv5\urel\gsttypefindhelper.exe"-"!:\sys\bin\gsttypefindhelper.exe"
+"\epoc32\release\armv5\urel\gsturi.exe"-"!:\sys\bin\gsturi.exe"
+"\epoc32\release\armv5\urel\gstutils.exe"-"!:\sys\bin\gstutils.exe"
+"\epoc32\release\armv5\urel\gstvalue.exe"-"!:\sys\bin\gstvalue.exe"
+"\epoc32\release\armv5\urel\helloworld.exe"-"!:\sys\bin\helloworld.exe"
+"\epoc32\release\armv5\urel\launch.exe"-"!:\sys\bin\launch.exe"
+"\epoc32\release\armv5\urel\manual_dynamic.exe"-"!:\sys\bin\manual_dynamic.exe"
+"\epoc32\release\armv5\urel\manual_ghostpad.exe"-"!:\sys\bin\manual_ghostpad.exe"
+"\epoc32\release\armv5\urel\manual_gstbin.exe"-"!:\sys\bin\manual_gstbin.exe"
+"\epoc32\release\armv5\urel\manual_gstdecodebin.exe"-"!:\sys\bin\manual_gstdecodebin.exe"
+"\epoc32\release\armv5\urel\manual_gstelementcreate.exe"-"!:\sys\bin\manual_gstelementcreate.exe"
+"\epoc32\release\armv5\urel\manual_gstelementfactory.exe"-"!:\sys\bin\manual_gstelementfactory.exe"
+"\epoc32\release\armv5\urel\manual_gstelementget.exe"-"!:\sys\bin\manual_gstelementget.exe"
+"\epoc32\release\armv5\urel\manual_gstelementlink.exe"-"!:\sys\bin\manual_gstelementlink.exe"
+"\epoc32\release\armv5\urel\manual_gstelementmake.exe"-"!:\sys\bin\manual_gstelementmake.exe"
+"\epoc32\release\armv5\urel\manual_gstinit.exe"-"!:\sys\bin\manual_gstinit.exe"
+"\epoc32\release\armv5\urel\manual_gstpad.exe"-"!:\sys\bin\manual_gstpad.exe"
+"\epoc32\release\armv5\urel\manual_gstplaybin.exe"-"!:\sys\bin\manual_gstplaybin.exe"
+"\epoc32\release\armv5\urel\manual_gstquery.exe"-"!:\sys\bin\manual_gstquery.exe"
+"\epoc32\release\armv5\urel\manual_helloworld.exe"-"!:\sys\bin\manual_helloworld.exe"
+"\epoc32\release\armv5\urel\manual_typefind.exe"-"!:\sys\bin\manual_typefind.exe"
+"\epoc32\release\armv5\urel\metadata.exe"-"!:\sys\bin\metadata.exe"
+"\epoc32\release\armv5\urel\mp3launch.exe"-"!:\sys\bin\mp3launch.exe"
+"\epoc32\release\armv5\urel\parse-disabled.exe"-"!:\sys\bin\parse-disabled.exe"
+"\epoc32\release\armv5\urel\parse-launch.exe"-"!:\sys\bin\parse-launch.exe"
+"\epoc32\release\armv5\urel\simple-launch-lines.exe"-"!:\sys\bin\simple-launch-lines.exe"
+"\epoc32\release\armv5\urel\stress.exe"-"!:\sys\bin\stress.exe"
+"\epoc32\release\armv5\urel\testaudioexample.exe"-"!:\sys\bin\testaudioexample.exe"
+"\epoc32\release\armv5\urel\testgstadapter.exe"-"!:\sys\bin\testgstadapter.exe"
+"\epoc32\release\armv5\urel\testqueue.exe"-"!:\sys\bin\testqueue.exe"
+"\epoc32\release\armv5\urel\typefind.exe"-"!:\sys\bin\typefind.exe"
+
+
+
+;gst_plugins_base test exe's
+
+"\epoc32\release\armv5\urel\gstadder.exe"-"!:\sys\bin\gstadder.exe"
+"\epoc32\release\armv5\urel\gstaudioconvert.exe"-"!:\sys\bin\gstaudioconvert.exe"
+"\epoc32\release\armv5\urel\gstaudiorate.exe"-"!:\sys\bin\gstaudiorate.exe"
+"\epoc32\release\armv5\urel\gstaudioresample.exe"-"!:\sys\bin\gstaudioresample.exe"
+"\epoc32\release\armv5\urel\gstaudiotestsrc.exe"-"!:\sys\bin\gstaudiotestsrc.exe"
+"\epoc32\release\armv5\urel\createelementbase.exe"-"!:\sys\bin\createelementbase.exe"
+"\epoc32\release\armv5\urel\gstdecodebin.exe"-"!:\sys\bin\gstdecodebin.exe"
+"\epoc32\release\armv5\urel\gdpdepay.exe"-"!:\sys\bin\gdpdepay.exe"
+"\epoc32\release\armv5\urel\multifdsink.exe"-"!:\sys\bin\multifdsink.exe"
+"\epoc32\release\armv5\urel\playbin.exe"-"!:\sys\bin\playbin.exe"
+"\epoc32\release\armv5\urel\gstsubparse.exe"-"!:\sys\bin\gstsubparse.exe"
+"\epoc32\release\armv5\urel\volume.exe"-"!:\sys\bin\volume.exe"
+"\epoc32\release\armv5\urel\clock-selection.exe"-"!:\sys\bin\clock-selection.exe"
+"\epoc32\release\armv5\urel\states.exe"-"!:\sys\bin\states.exe"
+"\epoc32\release\armv5\urel\fft.exe"-"!:\sys\bin\fft.exe"
+;"\epoc32\release\armv5\urel\gstnetbuffer.exe"-"!:\sys\bin\gstnetbuffer.exe"
+"\epoc32\release\armv5\urel\pbutils.exe"-"!:\sys\bin\pbutils.exe"
+"\epoc32\release\armv5\urel\gst_plugin_rtp.exe"-"!:\sys\bin\gst_plugin_rtp.exe"
+"\epoc32\release\armv5\urel\gst_plugin_tag.exe"-"!:\sys\bin\gst_plugin_tag.exe"
+"\epoc32\release\armv5\urel\taudio.exe"-"!:\sys\bin\taudio.exe"
+"\epoc32\release\armv5\urel\gstsimple-launch-lines.exe"-"!:\sys\bin\gstsimple-launch-lines.exe"
+"\epoc32\release\armv5\urel\gststreamheader.exe"-"!:\sys\bin\gststreamheader.exe"
+"\epoc32\release\armv5\urel\stress_playbin.exe"-"!:\sys\bin\stress_playbin.exe"
+
+;"\epoc32\release\armv5\urel\ffmpegcolorspace.exe"-"!:\sys\bin\ffmpegcolorspace.exe"
+;"\epoc32\release\armv5\urel\addstream.exe"-"!:\sys\bin\addstream.exe"
+;"\epoc32\release\armv5\urel\video.exe"-"!:\sys\bin\video.exe"
+;"\epoc32\release\armv5\urel\typefindfunctions.exe" -"!:\sys\bin\typefindfunctions.exe"
+;"\epoc32\release\armv5\urel\videorate.exe"-"!:\sys\bin\videorate.exe"
+
+
+
+;dependecy files
+
+
+;Testframework.ini and conf files
+
+"..\conf\gstreamertestcases_suite3.cfg"-"c:\TestFramework\gstreamertestcases_suite3.cfg"
+"..\init\gstreamertestcases_suite3.ini"-"c:\TestFramework\gstreamertestcases_suite3.ini"
+"..\init\TestFramework.ini"-"c:\TestFramework\TestFramework.ini"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/inc/GstreamerTestCases.h	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,190 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: STIF testclass declaration
+*
+*/
+
+
+#ifndef GSTREAMERTESTCASES_H
+#define GSTREAMERTESTCASES_H
+
+//  INCLUDES
+#include <StifLogger.h>
+#include <TestScripterInternal.h>
+#include <StifTestModule.h>
+#include <TestclassAssert.h>
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+#define TEST_CLASS_VERSION_MAJOR 0
+#define TEST_CLASS_VERSION_MINOR 0
+#define TEST_CLASS_VERSION_BUILD 0
+
+// Logging path
+_LIT( KGstreamerTestCasesLogPath, "\\logs\\testframework\\GstreamerTestCases\\" ); 
+// Log file
+_LIT( KGstreamerTestCasesLogFile, "GstreamerTestCases.htm" ); 
+_LIT( KGstreamerTestCasesLogFileWithTitle, "GstreamerTestCases_[%S].htm" );
+
+// FUNCTION PROTOTYPES
+//?type ?function_name(?arg_list);
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+class CGstreamerTestCases;
+
+// DATA TYPES
+//enum ?declaration
+//typedef ?declaration
+//extern ?data_type;
+
+// CLASS DECLARATION
+
+/**
+*  CGstreamerTestCases test class for STIF Test Framework TestScripter.
+*  ?other_description_lines
+*
+*  @lib ?library
+*  @since ?Series60_version
+*/
+NONSHARABLE_CLASS(CGstreamerTestCases) : public CScriptBase
+    {
+    public:  // Constructors and destructor
+
+        /**
+        * Two-phased constructor.
+        */
+        static CGstreamerTestCases* NewL( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * Destructor.
+        */
+        virtual ~CGstreamerTestCases();
+
+    public: // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    public: // Functions from base classes
+
+        /**
+        * From CScriptBase Runs a script line.
+        * @since ?Series60_version
+        * @param aItem Script line containing method name and parameters
+        * @return Symbian OS error code
+        */
+        virtual TInt RunMethodL( CStifItemParser& aItem );
+
+    protected:  // New functions
+
+        /**
+        * ?member_description.
+        * @since ?Series60_version
+        * @param ?arg1 ?description
+        * @return ?description
+        */
+        //?type ?member_function( ?type ?arg1 );
+
+    protected:  // Functions from base classes
+
+        /**
+        * From ?base_class ?member_description
+        */
+        //?type ?member_function();
+
+    private:
+
+        /**
+        * C++ default constructor.
+        */
+        CGstreamerTestCases( CTestModuleIf& aTestModuleIf );
+
+        /**
+        * By default Symbian 2nd phase constructor is private.
+        */
+        void ConstructL();
+
+        // Prohibit copy constructor if not deriving from CBase.
+        // ?classname( const ?classname& );
+        // Prohibit assigment operator if not deriving from CBase.
+        // ?classname& operator=( const ?classname& );
+
+        /**
+        * Frees all resources allocated from test methods.
+        * @since ?Series60_version
+        */
+        void Delete();
+
+        /**
+        * Test methods are listed below. 
+        */
+
+        /**
+        * Example test method.
+        * @since ?Series60_version
+        * @param aItem Script line containing parameters.
+        * @return Symbian OS error code.
+        */
+        virtual TInt ExampleL( CStifItemParser& aItem );
+        
+        /**
+         * Method used to log version of test class
+         */
+        void SendTestClassVersion();
+
+        //ADD NEW METHOD DEC HERE
+        //[TestMethods] - Do not remove
+
+    public:     // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    protected:  // Data
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+    private:    // Data
+        
+        // ?one_line_short_description_of_data
+        //?data_declaration;
+
+        // Reserved pointer for future extension
+        //TAny* iReserved;
+
+    public:     // Friend classes
+        //?friend_class_declaration;
+    protected:  // Friend classes
+        //?friend_class_declaration;
+    private:    // Friend classes
+        //?friend_class_declaration;
+
+    };
+
+#endif      // GSTREAMERTESTCASES_H
+
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/init/gstreamertestcases_suite3.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,4 @@
+[general]
+logFileName gstreamertestcases_suite3.log
+logPath c:\logs\
+[general_end]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/init/testframework.ini	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,184 @@
+#
+# This is STIFTestFramework initialization file
+# Comment lines start with '#'-character.
+# See STIF TestFramework users guide.doc for instructions
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set following test engine settings:
+#   - Set Test Reporting mode. TestReportMode's possible values are:
+#       + 'Summary': Summary of the tested test cases.
+#       + 'Environment': Hardware and software info.
+#       + 'TestCases': Test case report.
+#       + 'FullReport': Set of all above ones.
+#       + Example 'TestReportMode= Summary TestCases'
+#
+#   - CreateTestReport setting controls report creation mode
+#       + YES, Test report will created.
+#       + NO, No Test report.
+#
+#   - File path indicates the base path of the test report.
+#   - File name indicates the name of the test report.
+#
+#   - File format indicates the type of the test report.
+#       + TXT, Test report file will be txt type, for example 'TestReport.txt'.
+#       + HTML, Test report will be html type, for example 'TestReport.html'.
+#
+#   - File output indicates output source of the test report.
+#       + FILE, Test report logging to file.
+#       + RDEBUG, Test report logging to using rdebug.
+#
+#   - File Creation Mode indicates test report overwriting if file exist.
+#       + OVERWRITE, Overwrites if the Test report file exist.
+#       + APPEND, Continue logging after the old Test report information if
+#                 report exist.
+#   - Sets a device reset module's dll name(Reboot).
+#       + If Nokia specific reset module is not available or it is not correct one
+#         StifHWResetStub module may use as a template for user specific reset
+#         module.
+
+[Engine_Defaults]
+
+TestReportMode= FullReport      # Possible values are: 'Empty', 'Summary', 'Environment',
+                                                               'TestCases' or 'FullReport'
+
+CreateTestReport= YES           # Possible values: YES or NO
+
+TestReportFilePath= C:\LOGS\TestFramework\
+TestReportFileName= TestReport_gstreamertestcases_suite3
+
+TestReportFormat= HTML          # Possible values: TXT or HTML
+TestReportOutput= FILE          # Possible values: FILE or RDEBUG
+TestReportFileCreationMode= OVERWRITE   # Possible values: OVERWRITE or APPEND
+
+DeviceResetDllName= StifResetForNokia.dll # e.g. 'StifHWResetStub.dll' for user specific reseting
+
+[End_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Module configurations start
+# Modules are added between module tags
+# tags. Module name is specified after ModuleName= tag, like
+# ModuleName= XXXXXXXXX
+# Modules might have initialisation file, specified as
+# IniFile= c:\testframework\YYYYYY
+# Modules might have several configuration files, like
+# TestCaseFile= c:\testframework\NormalCases.txt
+# TestCaseFile= c:\testframework\SmokeCases.txt
+# TestCaseFile= c:\testframework\ManualCases.txt
+
+# (TestCaseFile is synonym for old term ConfigFile)
+
+# Following case specifies demo module settings. Demo module
+# does not read any settings from file, so tags
+# IniFile and TestCaseFile are not used.
+# In the simplest case it is enough to specify only the
+# name of the test module when adding new test module
+
+#[New_Module]
+#ModuleName= demomodule
+#[End_Module]
+
+
+[New_Module]
+ModuleName= TestScripter
+TestCaseFile= c:\testframework\gstreamertestcases_suite3.cfg
+IniFile= c:\testframework\gstreamertestcases_suite3.ini
+[End_Module]
+
+# Load testmoduleXXX, optionally with initialization file and/or test case files
+#[New_Module]
+#ModuleName= testmodulexxx
+
+#TestModuleXXX used initialization file
+#IniFile= c:\testframework\init.txt
+
+#TestModuleXXX used configuration file(s)
+#TestCaseFile= c:\testframework\testcases1.cfg
+#TestCaseFile= c:\testframework\testcases2.cfg
+#TestCaseFile= c:\testframework\manualtestcases.cfg
+
+#[End_Module]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+# Set STIFTestFramework logging overwrite parameters for Logger.
+#   Hardware and emulator environment logging path and styles can
+#   be configured from here to overwrite the Logger's implemented values.
+#
+#   Settings description:
+#   - Indicates option for creation log directory/directories. If log directory/directories
+#         is/are not created by user they will make by software.
+#       + YES, Create log directory/directories if not allready exist.
+#       + NO, Log directory/directories not created. Only created one is used.
+#
+#   - Overwrite emulator path setting.
+#       + Example: If 'EmulatorBasePath= C:\LOGS\TestFramework\' and in code is defined
+#                  Logger's path 'D:\\LOGS\\Module\\' with those definition the path
+#                  will be 'C:\LOGS\TestFramework\LOGS\Module\'
+#
+#   - Overwrite emulator's logging format.
+#       + TXT, Log file(s) will be txt type(s), for example 'Module.txt'.
+#       + HTML, Log file(s) will be html type(s), for example 'Module.html'.
+#
+#   - Overwrited emulator logging output source.
+#       + FILE, Logging to file(s).
+#       + RDEBUG, Logging to using rdebug(s).
+#
+#   - Overwrite hardware path setting (Same description as above in emulator path).
+#   - Overwrite hardware's logging format(Same description as above in emulator format).
+#   - Overwrite hardware's logging output source(Same description as above in emulator output).
+#
+#   - File Creation Mode indicates file overwriting if file exist.
+#       + OVERWRITE, Overwrites if file(s) exist.
+#       + APPEND, Continue logging after the old logging information if file(s) exist.
+#
+#   - Will thread id include to the log filename.
+#       + YES, Thread id to log file(s) name, Example filename 'Module_b9.txt'.
+#       + NO, No thread id to log file(s), Example filename 'Module.txt'.
+#
+#   - Will time stamps include the to log file.
+#       + YES, Time stamp added to each line in log file(s). Time stamp is
+#                 for example'12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No time stamp(s).
+#
+#   - Will line breaks include to the log file.
+#       + YES, Each logging event includes line break and next log event is in own line.
+#       + NO, No line break(s).
+#
+#   - Will event ranking include to the log file.
+#       + YES, Event ranking number added to each line in log file(s). Ranking number
+#                 depends on environment's tics, for example(includes time stamp also)
+#                 '012   12.Nov.2003 115958    LOGGING INFO'
+#       + NO, No event ranking.
+#
+
+[Logger_Defaults]
+
+#NOTE: If you want to set Logger using next setting(s) remove comment(s)'#'
+
+#CreateLogDirectories= YES      # Possible values: YES or NO
+
+#EmulatorBasePath= C:\LOGS\TestFramework\
+#EmulatorFormat= HTML           # Possible values: TXT or HTML
+#EmulatorOutput= FILE           # Possible values: FILE or RDEBUG
+
+#HardwareBasePath= D:\LOGS\TestFramework\
+#HardwareFormat= HTML           # Possible values: TXT or HTML
+#HardwareOutput= FILE           # Possible values: FILE or RDEBUG
+
+#FileCreationMode= OVERWRITE        # Possible values: OVERWRITE or APPEND
+
+#ThreadIdToLogFile= YES             # Possible values: YES or NO
+#WithTimeStamp= YES             # Possible values: YES or NO
+#WithLineBreak= YES             # Possible values: YES or NO
+#WithEventRanking= YES          # Possible values: YES or NO
+
+[End_Logger_Defaults]
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+# End of file
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/src/GstreamerTestCases.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,204 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// INCLUDE FILES
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+#include <SettingServerClient.h>
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::CGstreamerTestCases
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases::CGstreamerTestCases( 
+    CTestModuleIf& aTestModuleIf ):
+        CScriptBase( aTestModuleIf )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::ConstructL()
+    {
+    //Read logger settings to check whether test case name is to be
+    //appended to log file name.
+    RSettingServer settingServer;
+    TInt ret = settingServer.Connect();
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        }
+    // Struct to StifLogger settigs.
+    TLoggerSettings loggerSettings; 
+    // Parse StifLogger defaults from STIF initialization file.
+    ret = settingServer.GetLoggerSettings(loggerSettings);
+    if(ret != KErrNone)
+        {
+        User::Leave(ret);
+        } 
+    // Close Setting server session
+    settingServer.Close();
+
+    TFileName logFileName;
+    
+    if(loggerSettings.iAddTestCaseTitle)
+        {
+        TName title;
+        TestModuleIf().GetTestCaseTitleL(title);
+        logFileName.Format(KGstreamerTestCasesLogFileWithTitle, &title);
+        }
+    else
+        {
+        logFileName.Copy(KGstreamerTestCasesLogFile);
+        }
+
+    iLog = CStifLogger::NewL( KGstreamerTestCasesLogPath, 
+                          logFileName,
+                          CStifLogger::ETxt,
+                          CStifLogger::EFile,
+                          EFalse );
+    
+    SendTestClassVersion();
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CGstreamerTestCases* CGstreamerTestCases::NewL( 
+    CTestModuleIf& aTestModuleIf )
+    {
+    CGstreamerTestCases* self = new (ELeave) CGstreamerTestCases( aTestModuleIf );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+
+    }
+
+// Destructor
+CGstreamerTestCases::~CGstreamerTestCases()
+    { 
+
+    // Delete resources allocated from test methods
+    Delete();
+
+    // Delete logger
+    delete iLog; 
+
+    }
+
+//-----------------------------------------------------------------------------
+// CGstreamerTestCases::SendTestClassVersion
+// Method used to send version of test class
+//-----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::SendTestClassVersion()
+	{
+	TVersion moduleVersion;
+	moduleVersion.iMajor = TEST_CLASS_VERSION_MAJOR;
+	moduleVersion.iMinor = TEST_CLASS_VERSION_MINOR;
+	moduleVersion.iBuild = TEST_CLASS_VERSION_BUILD;
+	
+	TFileName moduleName;
+	moduleName = _L("GstreamerTestCases.dll");
+
+	TBool newVersionOfMethod = ETrue;
+	TestModuleIf().SendTestModuleVersion(moduleVersion, moduleName, newVersionOfMethod);
+	}
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// -----------------------------------------------------------------------------
+// LibEntryL is a polymorphic Dll entry point.
+// Returns: CScriptBase: New CScriptBase derived object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CScriptBase* LibEntryL( 
+    CTestModuleIf& aTestModuleIf ) // Backpointer to STIF Test Framework
+    {
+
+    return ( CScriptBase* ) CGstreamerTestCases::NewL( aTestModuleIf );
+
+    }
+
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gstreamer_core/tsrc/gstreamertestcases_suite3/src/GstreamerTestCasesBlocks.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -0,0 +1,237 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description: This file contains testclass implementation.
+*
+*/
+
+// [INCLUDE FILES] - do not remove
+#include <e32svr.h>
+#include <StifParser.h>
+#include <StifTestInterface.h>
+#include "GstreamerTestCases.h"
+
+// EXTERNAL DATA STRUCTURES
+//extern  ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES  
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+//const ?type ?constant_var = ?constant;
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// ?function_name ?description.
+// ?description
+// Returns: ?value_1: ?description
+//          ?value_n: ?description_line1
+//                    ?description_line2
+// -----------------------------------------------------------------------------
+//
+/*
+?type ?function_name(
+    ?arg_type arg,  // ?description
+    ?arg_type arg)  // ?description
+    {
+
+    ?code  // ?comment
+
+    // ?comment
+    ?code
+    }
+*/
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::Delete
+// Delete here all resources allocated and opened from test methods. 
+// Called from destructor. 
+// -----------------------------------------------------------------------------
+//
+void CGstreamerTestCases::Delete() 
+    {
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::RunMethodL
+// Run specified method. Contains also table of test mothods and their names.
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::RunMethodL( 
+    CStifItemParser& aItem ) 
+    {
+
+    static TStifFunctionInfo const KFunctions[] =
+        {  
+        // Copy this line for every implemented function.
+        // First string is the function name used in TestScripter script file.
+        // Second is the actual implementation member function. 
+        ENTRY( "Example", CGstreamerTestCases::ExampleL ),
+        //ADD NEW ENTRY HERE
+        // [test cases entries] - Do not remove
+
+        };
+
+    const TInt count = sizeof( KFunctions ) / 
+                        sizeof( TStifFunctionInfo );
+
+    return RunInternalL( KFunctions, count, aItem );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::ExampleL
+// Example test method function.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CGstreamerTestCases::ExampleL( CStifItemParser& aItem )
+{
+    TInt err = KErrNone;
+    RTimer timeoutTimer;
+    // Print to UI
+//    _LIT( KGstreamerTestCases, "GstreamerTestCases" );
+//    _LIT( KExample, "Test case: " );
+//    TestModuleIf().Printf( 0, KGstreamerTestCases, KExample );
+    // Print to log file
+
+    TPtrC string[2];
+    TFileName arg;
+    //_LIT( KParam, "Param[%i]: %S" );
+    
+    if( aItem.GetNextString ( string[0] ) != KErrNone)
+    {
+        iLog->Log( _L(">> Test cases Not Found") );
+        return -1;
+    }
+    iLog->Log( _L( "Test case Name is : " ) );
+    iLog->Log( string[0] );
+    
+    while ( aItem.GetNextString ( string[1] ) == KErrNone )
+    {
+        iLog->Log( string[1] );
+        arg.Append( string[1] );
+        arg.Append( TChar(' ') );
+    }
+    
+    
+    _LIT( KArg, "Arg: " );
+    iLog->Log( KArg );
+    iLog->Log( arg );
+    RProcess process;
+    err = process.Create( string[0],arg );
+    
+    if( !err )
+    {
+
+        if( timeoutTimer.CreateLocal() != KErrNone )
+        {
+            iLog->Log( _L(">> timeoutTimer.CreateLocal failed") );
+        }
+    
+        iLog->Log( _L(">> Test cases Started") );
+        TRequestStatus processStatus = KRequestPending;
+        TRequestStatus timerStatus = KRequestPending;
+        process.Logon( processStatus );
+        
+        process.Resume();
+        TTimeIntervalMicroSeconds32 timeout = 1 * 60 * 1000000;
+        timeoutTimer.After( timerStatus, timeout );
+        
+        while( processStatus == KRequestPending && timerStatus == KRequestPending )
+        {
+            User::WaitForAnyRequest();
+            
+        }
+        
+        err = process.ExitReason();
+        if( timerStatus != KRequestPending )
+        {
+            err = KErrTimedOut;
+        }
+        
+        process.LogonCancel( processStatus );
+        timeoutTimer.Cancel();
+        /// required to complete one of the pending request..
+        User::WaitForAnyRequest();
+        
+        process.Kill( KErrNone );
+        process.Close();
+        timeoutTimer.Close();
+        iLog->Log( _L(">> test cases completed") );
+    }
+    else
+    {
+        iLog->Log( _L(">> test cases exe not found") );
+    }
+
+
+    if( err != KErrNone )
+    {
+        iLog->Log( CStifLogger::ERed, _L( "Test cases FAILED!" ) );
+    }
+    else
+    {
+        iLog->Log( CStifLogger::EGreen, _L( "Test cases PASSED!" ) );
+    }
+    
+
+    return err;
+}
+
+// -----------------------------------------------------------------------------
+// CGstreamerTestCases::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+/*
+TInt CGstreamerTestCases::?member_function(
+   CItemParser& aItem )
+   {
+
+   ?code
+
+   }
+*/
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+// None
+
+//  [End of File] - Do not remove
--- a/gstregistrygenerator/group/gstregistrygenerator.mmp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstregistrygenerator/group/gstregistrygenerator.mmp	Fri Apr 16 15:15:52 2010 +0300
@@ -7,11 +7,35 @@
 ============================================================================
 */
 
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser 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.
+*
+* Description:
+*
+*/
+
 #include <platform_paths.hrh>      
 
 TARGET		  GSTRegistryGenerator.exe
 TARGETTYPE	  STDEXE
-UID			 0 0x2002BC6E
+UID			 0 0xEE84F17B
+
+EPOCHEAPSIZE 0x100000 0x1000000
 
 CAPABILITY All -Tcb
 
@@ -36,7 +60,7 @@
 
 
 SOURCEPATH	  ../src
-SOURCE		  gstregistrygenerator.cpp
+SOURCE		  GSTRegistryGenerator.cpp
 
 STATICLIBRARY    libcrt0.lib
 
--- a/gstregistrygenerator/src/gstregistrygenerator.cpp	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstregistrygenerator/src/gstregistrygenerator.cpp	Fri Apr 16 15:15:52 2010 +0300
@@ -7,7 +7,12 @@
 int
 main (int argc, char *argv[])
 {
+  // To Update registry set GST_REGISTRY_UPDATE to yes.
+  // by default it will not update the registry..
+  // if the registry is not present it will create registry.
+  setenv("GST_REGISTRY_UPDATE", "yes", 0);
   //This will update registry
   gst_init (&argc, &argv);  
+  gst_deinit();
   return 0;
 }
--- a/rom/gstreamer.iby	Fri Mar 19 09:35:09 2010 +0200
+++ b/rom/gstreamer.iby	Fri Apr 16 15:15:52 2010 +0300
@@ -46,8 +46,8 @@
 file=ABI_DIR\BUILD_DIR\libgstreamer.dll             SHARED_LIB_DIR\libgstreamer.dll
 file=ABI_DIR\BUILD_DIR\libgstriff.dll               SHARED_LIB_DIR\libgstriff.dll
 file=ABI_DIR\BUILD_DIR\libgsttag.dll                SHARED_LIB_DIR\libgsttag.dll
-file=ABI_DIR\BUILD_DIR\libgstvideo.dll              SHARED_LIB_DIR\libgstvideo.dll
-file=ABI_DIR\BUILD_DIR\libgstvideorate.dll          SHARED_LIB_DIR\libgstvideorate.dll
+//file=ABI_DIR\BUILD_DIR\libgstvideo.dll              SHARED_LIB_DIR\libgstvideo.dll
+//file=ABI_DIR\BUILD_DIR\libgstvideorate.dll          SHARED_LIB_DIR\libgstvideorate.dll
 //file=ABI_DIR\BUILD_DIR\libgstvideoscale.dll       SHARED_LIB_DIR\libgstvideoscale.dll
 //file=ABI_DIR\BUILD_DIR\libgstvideotestsrc.dll     SHARED_LIB_DIR\libgstvideotestsrc.dll
 file=ABI_DIR\BUILD_DIR\libgstdevsoundext.dll        SHARED_LIB_DIR\libgstdevsoundext.dll
@@ -80,7 +80,7 @@
 //GStreamer_Stub
 data=ZSYSTEM\install\gstreamer_stub.sis             System\Install\gstreamer_stub.sis
 data=\epoc32\winscw\c\gstreamer\plugins_list\gst_dll_2001F41F.txt             gstreamer\plugins_list\gst_dll_2001F41F.txt
-data=\epoc32\winscw\c\gstreamer\.gstreamer-0.10\registry.i686.bin           gstreamer\.gstreamer-0.10\registry.i686.bin
+//data=\epoc32\winscw\c\gstreamer\.gstreamer-0.10\registry.i686.bin           gstreamer\.gstreamer-0.10\registry.i686.bin
 
 #endif // end of FF_GSTREAMER
 
--- a/sis/gstreamer.pkg	Fri Mar 19 09:35:09 2010 +0200
+++ b/sis/gstreamer.pkg	Fri Apr 16 15:15:52 2010 +0300
@@ -1,4 +1,4 @@
-; 
+;
 ; Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 ;
 ; This library is free software; you can redistribute it and/or
Binary file sis/gstreamer_framework.pkg has changed
--- a/tsrc/group/bld.inf	Fri Mar 19 09:35:09 2010 +0200
+++ b/tsrc/group/bld.inf	Fri Apr 16 15:15:52 2010 +0300
@@ -25,8 +25,9 @@
 PRJ_EXPORTS
 
 PRJ_TESTMMPFILES
+#include "../../gst_plugins_base/tsrc/group/bld.inf"
 #include "../../gstreamer_core/tsrc/group/bld.inf"
-#include "../../gst_plugins_base/tsrc/group/bld.inf"
+
 
 //  End of File
 										
--- a/tsrc/group/gstreamer_testcases.pkg	Fri Mar 19 09:35:09 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-; ============================================================================
-;  Name        : gstreamer_testcases.pkg
-;  Part of     : Gstreamer project
-;  Description : Package file for all gstreamer test binaries
-;
-;  Version     : %version: 5 %
-;
-; 
-; Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-;
-; This library is free software; you can redistribute it and/or
-; modify it under the terms of the GNU Lesser 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
-; Lesser General Public License for more details.
-;
-; You should have received a copy of the GNU Lesser 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.
-; ============================================================================
-
-;Languages
-&EN
-
-;Header
-#{"gstreamer_testcases.pkg"},(0x2001F45C),1,0,0, TYPE=SU
-
-;Supports S60 3.0
-[0x101F7961], 0, 0, 0, {"S60ProductID"}
-
-;Localised Vendor name
-%{"Nokia Testing EN"}
-
-;Unique Vendor name
-:"Vendor"
-
-;gstreamer-core test exe's
-
-"\epoc32\release\armv5\urel\cleanup.exe"-"!:\sys\bin\cleanup.exe"
-"\epoc32\release\armv5\urel\createelementcore.exe"-"!:\sys\bin\createelementcore.exe"
-"\epoc32\release\armv5\urel\element_gstfakesink.exe"-"!:\sys\bin\element_gstfakesink.exe"
-"\epoc32\release\armv5\urel\element_gstfakesrc.exe"-"!:\sys\bin\element_gstfakesrc.exe"
-"\epoc32\release\armv5\urel\element_gstfdsrc.exe"-"!:\sys\bin\element_gstfdsrc.exe"
-"\epoc32\release\armv5\urel\element_gstfilesink.exe"-"!:\sys\bin\element_gstfilesink.exe"
-"\epoc32\release\armv5\urel\element_gstfilesrc.exe"-"!:\sys\bin\element_gstfilesrc.exe"
-"\epoc32\release\armv5\urel\element_gstidentity.exe"-"!:\sys\bin\element_gstidentity.exe"
-"\epoc32\release\armv5\urel\element_gstmultiqueue.exe"-"!:\sys\bin\element_gstmultiqueue.exe"
-"\epoc32\release\armv5\urel\element_gstqueue.exe"-"!:\sys\bin\element_gstqueue.exe"
-"\epoc32\release\armv5\urel\element_gsttee.exe"-"!:\sys\bin\element_gsttee.exe"
-"\epoc32\release\armv5\urel\gst.exe"-"!:\sys\bin\gst.exe"
-"\epoc32\release\armv5\urel\gstadapter.exe"-"!:\sys\bin\gstadapter.exe"
-"\epoc32\release\armv5\urel\gstbasesrc.exe"-"!:\sys\bin\gstbasesrc.exe"
-"\epoc32\release\armv5\urel\gstbin.exe"-"!:\sys\bin\gstbin.exe"
-"\epoc32\release\armv5\urel\gstbuffer.exe"-"!:\sys\bin\gstbuffer.exe"
-"\epoc32\release\armv5\urel\gstbus.exe"-"!:\sys\bin\gstbus.exe"
-"\epoc32\release\armv5\urel\gstcaps.exe"-"!:\sys\bin\gstcaps.exe"
-"\epoc32\release\armv5\urel\gstcollectpads.exe"-"!:\sys\bin\gstcollectpads.exe"
-"\epoc32\release\armv5\urel\gstcontroller.exe"-"!:\sys\bin\gstcontroller.exe"
-"\epoc32\release\armv5\urel\gstelement.exe"-"!:\sys\bin\gstelement.exe"
-"\epoc32\release\armv5\urel\gstevent.exe"-"!:\sys\bin\gstevent.exe"
-"\epoc32\release\armv5\urel\gstgdp.exe"-"!:\sys\bin\gstgdp.exe"
-"\epoc32\release\armv5\urel\gstghostpad.exe"-"!:\sys\bin\gstghostpad.exe"
-"\epoc32\release\armv5\urel\gstgstnetclientclock.exe"-"!:\sys\bin\gstgstnetclientclock.exe"
-"\epoc32\release\armv5\urel\gstgstnettimeprovider.exe"-"!:\sys\bin\gstgstnettimeprovider.exe"
-"\epoc32\release\armv5\urel\gstindex.exe"-"!:\sys\bin\gstindex.exe"
-"\epoc32\release\armv5\urel\gstinterface.exe"-"!:\sys\bin\gstinterface.exe"
-"\epoc32\release\armv5\urel\gstiterator.exe"-"!:\sys\bin\gstiterator.exe"
-"\epoc32\release\armv5\urel\gstlibsabi.exe"-"!:\sys\bin\gstlibsabi.exe"
-"\epoc32\release\armv5\urel\gstmessage.exe"-"!:\sys\bin\gstmessage.exe"
-"\epoc32\release\armv5\urel\gstminiobject.exe"-"!:\sys\bin\gstminiobject.exe"
-"\epoc32\release\armv5\urel\gstobject.exe"-"!:\sys\bin\gstobject.exe"
-"\epoc32\release\armv5\urel\gstpad.exe"-"!:\sys\bin\gstpad.exe"
-"\epoc32\release\armv5\urel\gstparamspecs.exe"-"!:\sys\bin\gstparamspecs.exe"
-"\epoc32\release\armv5\urel\gstpipeline.exe"-"!:\sys\bin\gstpipeline.exe"
-"\epoc32\release\armv5\urel\gstplugin.exe"-"!:\sys\bin\gstplugin.exe"
-"\epoc32\release\armv5\urel\gstpoll.exe"-"!:\sys\bin\gstpoll.exe"
-"\epoc32\release\armv5\urel\gstquery.exe"-"!:\sys\bin\gstquery.exe"
-"\epoc32\release\armv5\urel\gstregistry.exe"-"!:\sys\bin\gstregistry.exe"
-"\epoc32\release\armv5\urel\gstsegment.exe"-"!:\sys\bin\gstsegment.exe"
-"\epoc32\release\armv5\urel\gstsinks.exe"-"!:\sys\bin\gstsinks.exe"
-"\epoc32\release\armv5\urel\gststates.exe"-"!:\sys\bin\gststates.exe"
-"\epoc32\release\armv5\urel\gststructure.exe"-"!:\sys\bin\gststructure.exe"
-"\epoc32\release\armv5\urel\gstsystemclock.exe"-"!:\sys\bin\gstsystemclock.exe"
-"\epoc32\release\armv5\urel\gsttag.exe"-"!:\sys\bin\gsttag.exe"
-"\epoc32\release\armv5\urel\gsttagsetter.exe"-"!:\sys\bin\gsttagsetter.exe"
-"\epoc32\release\armv5\urel\gsttask.exe"-"!:\sys\bin\gsttask.exe"
-"\epoc32\release\armv5\urel\gsttypefindhelper.exe"-"!:\sys\bin\gsttypefindhelper.exe"
-"\epoc32\release\armv5\urel\gsturi.exe"-"!:\sys\bin\gsturi.exe"
-"\epoc32\release\armv5\urel\gstutils.exe"-"!:\sys\bin\gstutils.exe"
-"\epoc32\release\armv5\urel\gstvalue.exe"-"!:\sys\bin\gstvalue.exe"
-"\epoc32\release\armv5\urel\helloworld.exe"-"!:\sys\bin\helloworld.exe"
-"\epoc32\release\armv5\urel\launch.exe"-"!:\sys\bin\launch.exe"
-"\epoc32\release\armv5\urel\manual_dynamic.exe"-"!:\sys\bin\manual_dynamic.exe"
-"\epoc32\release\armv5\urel\manual_ghostpad.exe"-"!:\sys\bin\manual_ghostpad.exe"
-"\epoc32\release\armv5\urel\manual_gstbin.exe"-"!:\sys\bin\manual_gstbin.exe"
-"\epoc32\release\armv5\urel\manual_gstdecodebin.exe"-"!:\sys\bin\manual_gstdecodebin.exe"
-"\epoc32\release\armv5\urel\manual_gstelementcreate.exe"-"!:\sys\bin\manual_gstelementcreate.exe"
-"\epoc32\release\armv5\urel\manual_gstelementfactory.exe"-"!:\sys\bin\manual_gstelementfactory.exe"
-"\epoc32\release\armv5\urel\manual_gstelementget.exe"-"!:\sys\bin\manual_gstelementget.exe"
-"\epoc32\release\armv5\urel\manual_gstelementlink.exe"-"!:\sys\bin\manual_gstelementlink.exe"
-"\epoc32\release\armv5\urel\manual_gstelementmake.exe"-"!:\sys\bin\manual_gstelementmake.exe"
-"\epoc32\release\armv5\urel\manual_gstinit.exe"-"!:\sys\bin\manual_gstinit.exe"
-"\epoc32\release\armv5\urel\manual_gstpad.exe"-"!:\sys\bin\manual_gstpad.exe"
-"\epoc32\release\armv5\urel\manual_gstplaybin.exe"-"!:\sys\bin\manual_gstplaybin.exe"
-"\epoc32\release\armv5\urel\manual_gstquery.exe"-"!:\sys\bin\manual_gstquery.exe"
-"\epoc32\release\armv5\urel\manual_helloworld.exe"-"!:\sys\bin\manual_helloworld.exe"
-"\epoc32\release\armv5\urel\manual_typefind.exe"-"!:\sys\bin\manual_typefind.exe"
-"\epoc32\release\armv5\urel\metadata.exe"-"!:\sys\bin\metadata.exe"
-"\epoc32\release\armv5\urel\mp3launch.exe"-"!:\sys\bin\mp3launch.exe"
-"\epoc32\release\armv5\urel\parse-disabled.exe"-"!:\sys\bin\parse-disabled.exe"
-"\epoc32\release\armv5\urel\parse-launch.exe"-"!:\sys\bin\parse-launch.exe"
-"\epoc32\release\armv5\urel\simple-launch-lines.exe"-"!:\sys\bin\simple-launch-lines.exe"
-"\epoc32\release\armv5\urel\stress.exe"-"!:\sys\bin\stress.exe"
-"\epoc32\release\armv5\urel\testaudioexample.exe"-"!:\sys\bin\testaudioexample.exe"
-"\epoc32\release\armv5\urel\testgstadapter.exe"-"!:\sys\bin\testgstadapter.exe"
-"\epoc32\release\armv5\urel\testqueue.exe"-"!:\sys\bin\testqueue.exe"
-"\epoc32\release\armv5\urel\typefind.exe"-"!:\sys\bin\typefind.exe"
-
-
-
-;gst_plugins_base test exe's
-
-"\epoc32\release\armv5\urel\gstadder.exe"-"!:\sys\bin\gstadder.exe"
-"\epoc32\release\armv5\urel\gstaudioconvert.exe"-"!:\sys\bin\gstaudioconvert.exe"
-"\epoc32\release\armv5\urel\gstaudiorate.exe"-"!:\sys\bin\gstaudiorate.exe"
-"\epoc32\release\armv5\urel\gstaudioresample.exe"-"!:\sys\bin\gstaudioresample.exe"
-"\epoc32\release\armv5\urel\gstaudiotestsrc.exe"-"!:\sys\bin\gstaudiotestsrc.exe"
-"\epoc32\release\armv5\urel\createelementbase.exe"-"!:\sys\bin\createelementbase.exe"
-"\epoc32\release\armv5\urel\gstdecodebin.exe"-"!:\sys\bin\gstdecodebin.exe"
-"\epoc32\release\armv5\urel\gdpdepay.exe"-"!:\sys\bin\gdpdepay.exe"
-"\epoc32\release\armv5\urel\multifdsink.exe"-"!:\sys\bin\multifdsink.exe"
-"\epoc32\release\armv5\urel\playbin.exe"-"!:\sys\bin\playbin.exe"
-"\epoc32\release\armv5\urel\gstsubparse.exe"-"!:\sys\bin\gstsubparse.exe"
-"\epoc32\release\armv5\urel\volume.exe"-"!:\sys\bin\volume.exe"
-"\epoc32\release\armv5\urel\clock-selection.exe"-"!:\sys\bin\clock-selection.exe"
-"\epoc32\release\armv5\urel\states.exe"-"!:\sys\bin\states.exe"
-"\epoc32\release\armv5\urel\fft.exe"-"!:\sys\bin\fft.exe"
-"\epoc32\release\armv5\urel\gstnetbuffer.exe"-"!:\sys\bin\gstnetbuffer.exe"
-"\epoc32\release\armv5\urel\pbutils.exe"-"!:\sys\bin\pbutils.exe"
-"\epoc32\release\armv5\urel\gst_plugin_rtp.exe"-"!:\sys\bin\gst_plugin_rtp.exe"
-"\epoc32\release\armv5\urel\gst_plugin_tag.exe"-"!:\sys\bin\gst_plugin_tag.exe"
-"\epoc32\release\armv5\urel\taudio.exe"-"!:\sys\bin\taudio.exe"
-"\epoc32\release\armv5\urel\gstsimple-launch-lines.exe"-"!:\sys\bin\gstsimple-launch-lines.exe"
-"\epoc32\release\armv5\urel\gststreamheader.exe"-"!:\sys\bin\gststreamheader.exe"
-"\epoc32\release\armv5\urel\stress_playbin.exe"-"!:\sys\bin\stress_playbin.exe"
-
-;"\epoc32\release\armv5\urel\ffmpegcolorspace.exe"-"!:\sys\bin\ffmpegcolorspace.exe"
-;"\epoc32\release\armv5\urel\addstream.exe"-"!:\sys\bin\addstream.exe"
-;"\epoc32\release\armv5\urel\video.exe"-"!:\sys\bin\video.exe"
-;"\epoc32\release\armv5\urel\typefindfunctions.exe" -"!:\sys\bin\typefindfunctions.exe"
-;"\epoc32\release\armv5\urel\videorate.exe"-"!:\sys\bin\videorate.exe"
-
-
-
-;dependecy files
-;"\epoc32\winscw\c\data\gstreamer\khuda.wav"-"c:\data\gstreamer\khuda.wav"
-;"\epoc32\winscw\c\data\gstreamer\warning.wav"-"c:\data\gstreamer\warning.wav"
-;"\epoc32\winscw\c\data\gstreamer\Crnival.mp3"-"c:\data\gstreamer\Crnival.mp3"