201009
authorhgs
Wed, 24 Mar 2010 18:04:17 -0500
changeset 16 8e837d1bf446
parent 15 4b0c6ed43234
child 17 512aaca1665c
201009
QtGSTPlayer/QtGSTPlayer.loc
QtGSTPlayer/QtGSTPlayer.pro
QtGSTPlayer/QtGSTPlayer.qrc
QtGSTPlayer/QtGSTPlayer.rss
QtGSTPlayer/QtGSTPlayer_0x2002c392.mmp
QtGSTPlayer/QtGSTPlayer_reg.rss
QtGSTPlayer/QtGSTPlayer_template.pkg
QtGSTPlayer/bld.inf
QtGSTPlayer/folder.png
QtGSTPlayer/folderview.cpp
QtGSTPlayer/folderview.h
QtGSTPlayer/main.cpp
QtGSTPlayer/moc_folderview.cpp
QtGSTPlayer/qrc_QtGSTPlayer.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/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/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/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/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/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
internal/gstplayer/data/gstplayer.rss
internal/gstplayer/inc/gstplayer.hrh
internal/gstplayer/inc/gstreamer.h
internal/gstplayer/src/GSTPlayerappui.cpp
internal/gstplayer/src/SymGstreamer.cpp
internal/miscfiles/copyplugins.bat
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.loc	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,13 @@
+// ============================================================================
+// * Generated by qmake (2.01a) (Qt 4.6.1) on: 2010-02-23T15:57:15
+// * This file is generated by qmake and should not be modified by the
+// * user.
+// ============================================================================
+
+#ifdef LANGUAGE_SC
+#define STRING_r_short_caption "QtGSTPlayer"
+#define STRING_r_caption "QtGSTPlayer"
+#else
+#define STRING_r_short_caption "QtGSTPlayer"
+#define STRING_r_caption "QtGSTPlayer"
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer.pro	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/QtGSTPlayer" >
+        <file>folder.png</file>
+        <file>settings.png</file>
+    </qresource>
+</RCC>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer.rss	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,21 @@
+// ============================================================================
+// * Generated by qmake (2.01a) (Qt 4.6.1) on: 2010-02-23T15:57:15
+// * This file is generated by qmake and should not be modified by the
+// * user.
+// ============================================================================
+
+#include <appinfo.rh>
+#include "QtGSTPlayer.loc"
+
+RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info
+	{
+	short_caption = STRING_r_short_caption;
+	caption_and_icon =
+	CAPTION_AND_ICON_INFO
+		{
+		caption = STRING_r_caption;
+		number_of_icons = 0;
+		icon_file = "";
+		};
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer_0x2002c392.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,142 @@
+// ==============================================================================
+// Generated by qmake (2.01a) (Qt 4.6.1) on: 2010-02-23T15:57:15
+// This file is generated by qmake and should not be modified by the
+// user.
+//  Name        : QtGSTPlayer.mmp
+// ==============================================================================
+
+TARGET		QtGSTPlayer.exe
+TARGETTYPE		EXE
+
+UID		0x2002c391 0x2002c392
+SECUREID		0x2002c392
+
+CAPABILITY All -Tcb
+EPOCSTACKSIZE		0x14000
+EPOCHEAPSIZE		0x020000 0x800000
+
+SOURCEPATH			. 
+LANG SC 
+START RESOURCE		QtGSTPlayer.rss
+HEADER
+TARGETPATH			/resource/apps
+END
+
+SOURCEPATH			.
+START RESOURCE		QtGSTPlayer_reg.rss
+TARGETPATH		/private/10003a3f/import/apps
+END
+
+
+// Qt Macros
+MACRO		UNICODE
+MACRO		QT_KEYPAD_NAVIGATION
+MACRO		QT_SOFTKEYS_ENABLED
+MACRO		QT_USE_MATH_H_FLOATS
+MACRO		HB_GESTURE_FW
+MACRO		HB_EFFECTS
+MACRO		QT_NO_DEBUG
+MACRO		QT_GUI_LIB
+MACRO		QT_CORE_LIB
+SYSTEMINCLUDE		/epoc32/include/mw/hb/hbcore
+SYSTEMINCLUDE		/epoc32/include/mw/hb/hbfeedback
+SYSTEMINCLUDE		/epoc32/include/mw/hb/hbinput
+SYSTEMINCLUDE		/epoc32/include/mw/hb/hbtools
+SYSTEMINCLUDE		/epoc32/include/mw/hb/hbwidgets
+
+
+SYSTEMINCLUDE		/epoc32/include/mw/QtCore
+SYSTEMINCLUDE		/epoc32/include/mw/QtGui
+SYSTEMINCLUDE		/epoc32/include/mw
+SYSTEMINCLUDE		../../../qt/mkspecs/common/symbian
+SYSTEMINCLUDE		../../../qt/mkspecs/common/symbian/tmp
+SYSTEMINCLUDE		/epoc32/include
+SYSTEMINCLUDE		/epoc32/include/stdapis
+SYSTEMINCLUDE		/epoc32/include/stdapis/sys
+SYSTEMINCLUDE		.
+SYSTEMINCLUDE		tmp
+
+SYSTEMINCLUDE		/epoc32/include/stdapis/stlportv5
+SYSTEMINCLUDE		/epoc32/include/mw
+SYSTEMINCLUDE		/epoc32/include/platform/mw
+SYSTEMINCLUDE		/epoc32/include/platform
+SYSTEMINCLUDE		/epoc32/include/platform/loc
+SYSTEMINCLUDE		/epoc32/include/platform/mw/loc
+SYSTEMINCLUDE		/epoc32/include/platform/loc/sc
+SYSTEMINCLUDE		/epoc32/include/platform/mw/loc/sc
+SYSTEMINCLUDE		/epoc32/include/mw/qtgui
+SYSTEMINCLUDE		/epoc32/include/mw/qtcore
+MW_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
+
+OS_LAYER_GLIB_SYSTEMINCLUDE
+
+USERINCLUDE		/sf/mw/gstreamer/include/gstreamer
+USERINCLUDE		/sf/mw/gstreamer/include/gstreamer/gst
+USERINCLUDE		/sf/mw/gstreamer/include/gstreamer/gst/base
+USERINCLUDE		/sf/mw/gstreamer/include/gstreamer/gst/controller
+USERINCLUDE		/sf/mw/gstreamer/include/gstreamer/gst/dataprotocol
+USERINCLUDE		/sf/mw/gstreamer/include/gstreamer/gst/net
+
+
+
+SOURCEPATH 	.
+SOURCE		main.cpp
+SOURCE		folderview.cpp
+SOURCE		views.cpp
+SOURCE		record_play.c
+SOURCE		moc_folderview.cpp
+SOURCE		qrc_QtGSTPlayer.cpp
+
+
+LIBRARY		HbCore.lib
+LIBRARY		HbWidgets.lib
+LIBRARY		HbTools.lib
+LIBRARY		QtGui.lib
+LIBRARY		QtCore.lib
+LIBRARY		libstdcppv5.lib
+LIBRARY		libc.lib
+LIBRARY		libm.lib
+LIBRARY		euser.lib
+LIBRARY		libdl.lib
+LIBRARY		cone.lib
+LIBRARY		eikcore.lib
+LIBRARY		mediaclientaudio.lib
+LIBRARY		eikcoctl.lib
+LIBRARY		eiksrv.lib
+LIBRARY		apparc.lib
+LIBRARY		avkon.lib
+LIBRARY		efsrv.lib
+LIBRARY		charconv.lib
+LIBRARY		ws32.lib
+LIBRARY		hal.lib
+LIBRARY		gdi.lib
+LIBRARY		apgrfx.lib
+LIBRARY         libglib.lib
+LIBRARY         libgmodule.lib
+
+LIBRARY         libgobject.lib
+LIBRARY         libgthread.lib
+
+
+LIBRARY         libgstreamer.lib
+LIBRARY			libgstbase.lib
+LIBRARY			libgstcontroller.lib 
+
+
+STATICLIBRARY	qtmain.lib
+
+
+
+OPTION CW -wchar_t on
+OPTION ARMCC --visibility_inlines_hidden
+
+VERSION 10.0
+
+PAGED
+
+OPTION_REPLACE ARMCC --export_all_vtbl -D__QT_NOEFFECTMACRO_DONOTUSE
+
+USERINCLUDE .
+
+STDCPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer_reg.rss	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,18 @@
+// ============================================================================
+// * Generated by qmake (2.01a) (Qt 4.6.1) on: 2010-02-23T15:57:15
+// * This file is generated by qmake and should not be modified by the
+// * user.
+// ============================================================================
+
+#include <QtGSTPlayer.rsg>
+#include <appinfo.rh>
+
+UID2 KUidAppRegistrationResourceFile
+UID3 0x2002c392
+
+RESOURCE APP_REGISTRATION_INFO
+	{
+	app_file="QtGSTPlayer";
+	localisable_resource_file="\\resource\\apps\\QtGSTPlayer";
+
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/QtGSTPlayer_template.pkg	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,32 @@
+; QtGSTPlayer_template.pkg generated by qmake at 2010-02-23T15:57:15
+; This file is generated by qmake and should not be modified by the user
+;
+
+; Language
+&EN
+
+; SIS header: name, uid, version
+#{"QtGSTPlayer"},(0x2002c392),1,0,0
+
+; Localised Vendor name
+%{"Vendor"}
+
+; Unique Vendor name
+:"Vendor"
+
+; Manual PKG pre-rules from PRO files
+; Default HW/platform dependencies
+[0x101F7961],0,0,0,{"S60ProductID"}
+[0x102032BE],0,0,0,{"S60ProductID"}
+[0x102752AE],0,0,0,{"S60ProductID"}
+[0x1028315F],0,0,0,{"S60ProductID"}
+ 
+; Default dependency to Qt libraries
+;(0x2001E61C), , , , {"Qt"}
+
+; Executable and default resource files
+"/epoc32/release/armv5/urel/QtGSTPlayer.exe"    - "!:\sys\bin\QtGSTPlayer.exe"
+"/epoc32/data/z/resource/apps/QtGSTPlayer.rsc"    - "!:\resource\apps\QtGSTPlayer.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/QtGSTPlayer_reg.rsc"    - "!:\private\10003a3f\import\apps\QtGSTPlayer_reg.rsc"
+
+; Manual PKG post-rules from PRO files
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,21 @@
+// ============================================================================
+// * Makefile for building: QtGSTPlayer
+// * Generated by qmake (2.01a) (Qt 4.6.1) on: 2010-02-23T15:57:15
+// * This file is generated by qmake and should not be modified by the
+// * user.
+// * Project:  QtGSTPlayer.pro
+// * Template: app
+// ============================================================================
+
+#define BLD_INF_QTGSTPLAYER_024F332B
+
+
+PRJ_PLATFORMS
+DEFAULT
+
+
+PRJ_MMPFILES
+QtGSTPlayer_0x2002c392.mmp
+
+prj_extensions
+
Binary file QtGSTPlayer/folder.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/folderview.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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/moc_folderview.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,110 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'folderview.h'
+**
+** Created: Tue Feb 23 15:59:43 2010
+**      by: The Qt Meta Object Compiler version 62 (Qt 4.6.1)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "folderview.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'folderview.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 62
+#error "This file was generated using the moc from 4.6.2. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_FolderView[] = {
+
+ // content:
+       4,       // revision
+       0,       // classname
+       0,    0, // classinfo
+      14,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+      12,   11,   11,   11, 0x0a,
+      40,   34,   11,   11, 0x0a,
+      66,   11,   11,   11, 0x0a,
+      79,   11,   11,   11, 0x0a,
+      92,   11,   11,   11, 0x0a,
+     105,   11,   11,   11, 0x0a,
+     119,   11,   11,   11, 0x0a,
+     133,   11,   11,   11, 0x0a,
+     147,   11,   11,   11, 0x0a,
+     160,   11,   11,   11, 0x0a,
+     168,   11,   11,   11, 0x0a,
+     177,   11,   11,   11, 0x0a,
+     184,   11,   11,   11, 0x0a,
+     203,  199,   11,   11, 0x0a,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_FolderView[] = {
+    "FolderView\0\0folderViewTriggered()\0"
+    "index\0item_pressed(QModelIndex)\0"
+    "record_AMR()\0record_WAV()\0record_RAW()\0"
+    "record_G711()\0record_G729()\0record_ILBC()\0"
+    "record_AAC()\0pause()\0resume()\0stop()\0"
+    "timertimeout()\0err\0showNote(int)\0"
+};
+
+const QMetaObject FolderView::staticMetaObject = {
+    { &HbView::staticMetaObject, qt_meta_stringdata_FolderView,
+      qt_meta_data_FolderView, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &FolderView::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *FolderView::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *FolderView::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_FolderView))
+        return static_cast<void*>(const_cast< FolderView*>(this));
+    return HbView::qt_metacast(_clname);
+}
+
+int FolderView::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = HbView::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: folderViewTriggered(); break;
+        case 1: item_pressed((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break;
+        case 2: record_AMR(); break;
+        case 3: record_WAV(); break;
+        case 4: record_RAW(); break;
+        case 5: record_G711(); break;
+        case 6: record_G729(); break;
+        case 7: record_ILBC(); break;
+        case 8: record_AAC(); break;
+        case 9: pause(); break;
+        case 10: resume(); break;
+        case 11: stop(); break;
+        case 12: timertimeout(); break;
+        case 13: showNote((*reinterpret_cast< const int(*)>(_a[1]))); break;
+        default: ;
+        }
+        _id -= 14;
+    }
+    return _id;
+}
+QT_END_MOC_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/qrc_QtGSTPlayer.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,1116 @@
+/****************************************************************************
+** Resource object code
+**
+** Created: Tue Feb 23 15:59:43 2010
+**      by: The Resource Compiler for Qt version 4.6.1
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+static const unsigned char qt_resource_data[] = {
+  // Q:/sf/mw/gstreamer/internal/QtGSTPlayer/folder.png
+  0x0,0x0,0x20,0xb2,
+  0x89,
+  0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,
+  0x0,0x2,0x31,0x0,0x0,0x0,0x9a,0x8,0x3,0x0,0x0,0x0,0x6f,0xf5,0xe9,0xc2,
+  0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,
+  0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0xa,0xc,0x4,0xb,0xb,
+  0xb,0x12,0x16,0x8,0x17,0x17,0x17,0x22,0x29,0xe,0x2d,0x33,0x1d,0x31,0x3c,0x15,
+  0x26,0x26,0x26,0x2c,0x2c,0x2c,0x32,0x32,0x32,0x3d,0x3d,0x3d,0x3c,0x48,0x1a,0x44,
+  0x53,0x1e,0x45,0x48,0x3e,0x4e,0x5e,0x22,0x4c,0x50,0x3f,0x59,0x6c,0x27,0x5f,0x6b,
+  0x3f,0x5e,0x71,0x29,0x62,0x76,0x2a,0x48,0x48,0x48,0x4e,0x53,0x40,0x59,0x59,0x59,
+  0x59,0x62,0x41,0x61,0x6d,0x42,0x66,0x6a,0x5c,0x6b,0x79,0x43,0x6b,0x71,0x5b,0x74,
+  0x7d,0x5b,0x63,0x63,0x63,0x67,0x68,0x64,0x68,0x69,0x64,0x6e,0x6e,0x6e,0x6e,0x71,
+  0x66,0x71,0x75,0x65,0x72,0x74,0x6d,0x75,0x7a,0x64,0x75,0x7a,0x6a,0x78,0x7f,0x65,
+  0x78,0x7d,0x6a,0x71,0x71,0x71,0x76,0x78,0x73,0x79,0x7c,0x72,0x7a,0x7a,0x7a,0x74,
+  0x8c,0x33,0x76,0x86,0x49,0x76,0x80,0x58,0x79,0x87,0x54,0x79,0x83,0x5d,0x7b,0x8a,
+  0x54,0x7d,0x8a,0x5c,0x7f,0x94,0x46,0x7f,0x91,0x50,0x7b,0x84,0x64,0x7b,0x82,0x69,
+  0x7e,0x89,0x61,0x7e,0x83,0x73,0x89,0xa6,0x3c,0x80,0x8d,0x5c,0x84,0x9a,0x48,0x83,
+  0x95,0x54,0x83,0x92,0x5b,0x86,0x99,0x53,0x8a,0x9e,0x54,0x8a,0x9c,0x5b,0x82,0x8c,
+  0x65,0x84,0x89,0x76,0x85,0x92,0x62,0x89,0x97,0x62,0x8b,0x9b,0x61,0x8d,0x96,0x73,
+  0x91,0x9c,0x73,0x8c,0xa4,0x4c,0x8e,0xa2,0x55,0x8d,0xa0,0x59,0x93,0xad,0x4b,0x90,
+  0xa5,0x57,0x92,0xa6,0x5b,0x93,0xab,0x52,0x95,0xab,0x58,0x98,0xae,0x5a,0x93,0xb1,
+  0x41,0x95,0xb1,0x4c,0x99,0xb5,0x4d,0x9b,0xbb,0x44,0x9b,0xb8,0x4a,0x97,0xb0,0x52,
+  0x99,0xb3,0x52,0x9d,0xb9,0x50,0x8f,0xa0,0x61,0x98,0xaa,0x67,0x9b,0xa5,0x7f,0x9c,
+  0xb2,0x63,0xa0,0xbe,0x4d,0xa0,0xbd,0x52,0xa5,0xbc,0x67,0xa7,0xba,0x72,0xa0,0xc1,
+  0x46,0xa3,0xc3,0x4c,0xa7,0xc8,0x4d,0xaa,0xcc,0x4c,0xa5,0xc4,0x51,0xa5,0xc0,0x59,
+  0xa8,0xc7,0x52,0xa8,0xc4,0x59,0xab,0xcd,0x51,0xac,0xca,0x5b,0xae,0xd2,0x4c,0xae,
+  0xd1,0x52,0xae,0xd1,0x59,0xb0,0xce,0x5e,0xb0,0xd3,0x4f,0xb1,0xd3,0x55,0xb4,0xd5,
+  0x5b,0xaa,0xc3,0x64,0xaf,0xc5,0x71,0xae,0xc2,0x79,0xad,0xd1,0x66,0xad,0xd1,0x6f,
+  0xb2,0xce,0x63,0xb2,0xcb,0x6a,0xb0,0xc7,0x70,0xb5,0xcd,0x75,0xb6,0xcb,0x7b,0xb8,
+  0xcf,0x7c,0xb4,0xd3,0x62,0xb4,0xd3,0x6a,0xb8,0xd6,0x66,0xb8,0xd5,0x6a,0xb9,0xd8,
+  0x63,0xbc,0xda,0x6b,0xb4,0xd2,0x74,0xb3,0xd4,0x7a,0xb9,0xd3,0x73,0xbc,0xd5,0x7b,
+  0xbd,0xd9,0x73,0xc0,0xdc,0x74,0xc2,0xdc,0x7a,0x87,0x87,0x87,0x93,0x93,0x93,0x99,
+  0x9c,0x93,0x9b,0x9b,0x9b,0x9f,0xa7,0x8a,0x9c,0xa0,0x92,0xa1,0xaa,0x88,0xa1,0xa6,
+  0x93,0xae,0xbd,0x83,0xb1,0xbe,0x8c,0xb5,0xbe,0x9d,0xa6,0xa6,0xa6,0xac,0xac,0xac,
+  0xad,0xb1,0xa5,0xb1,0xb2,0xaf,0xbb,0xbb,0xbb,0xb3,0xc4,0x84,0xb3,0xc2,0x8c,0xb6,
+  0xc8,0x86,0xb9,0xcd,0x83,0xb9,0xc7,0x94,0xba,0xc5,0x9e,0xbb,0xcb,0x92,0xbc,0xc9,
+  0x9a,0xb5,0xd4,0x80,0xbb,0xd4,0x82,0xbe,0xda,0x8d,0xba,0xd0,0x98,0xbb,0xc4,0xa3,
+  0xc0,0xd7,0x82,0xc2,0xd5,0x8e,0xc3,0xdb,0x84,0xc5,0xdc,0x89,0xc2,0xd3,0x94,0xc3,
+  0xd3,0x99,0xc4,0xdb,0x9c,0xcb,0xde,0x95,0xc9,0xdb,0x9a,0xc3,0xcd,0xa8,0xc6,0xca,
+  0xb9,0xc7,0xd1,0xac,0xca,0xd7,0xa5,0xc9,0xd4,0xac,0xcb,0xda,0xa2,0xce,0xdb,0xaa,
+  0xc9,0xd2,0xb4,0xd1,0xde,0xad,0xd3,0xde,0xb4,0xc7,0xe0,0x83,0xc8,0xe0,0x85,0xcb,
+  0xe1,0x8c,0xcd,0xe2,0x92,0xcf,0xe1,0x9b,0xd0,0xe5,0x96,0xd2,0xe6,0x9d,0xcc,0xe0,
+  0xaf,0xcc,0xe2,0xbb,0xd2,0xe4,0xa4,0xd4,0xe4,0xab,0xd6,0xe8,0xa5,0xd7,0xe8,0xac,
+  0xd9,0xe9,0xac,0xd2,0xe3,0xb3,0xd5,0xe4,0xbd,0xd7,0xe8,0xb5,0xd8,0xe5,0xb5,0xda,
+  0xe6,0xbd,0xdc,0xeb,0xb2,0xdd,0xea,0xbb,0xe0,0xee,0xbb,0xc2,0xc2,0xc2,0xca,0xcb,
+  0xc7,0xcd,0xcd,0xcd,0xcf,0xd0,0xcf,0xd1,0xd6,0xc4,0xd0,0xd1,0xcf,0xd6,0xdc,0xc4,
+  0xd8,0xdf,0xc3,0xd5,0xd5,0xd5,0xdc,0xdc,0xdc,0xd4,0xe0,0xcd,0xda,0xe2,0xc3,0xdc,
+  0xe2,0xcc,0xdc,0xea,0xc1,0xde,0xe2,0xd1,0xde,0xe6,0xdb,0xda,0xe8,0xd4,0xdf,0xeb,
+  0xde,0xe0,0xe6,0xce,0xe2,0xed,0xc2,0xe3,0xed,0xc9,0xe0,0xe1,0xdd,0xe5,0xeb,0xdc,
+  0xe8,0xed,0xdc,0xe4,0xf0,0xc6,0xe6,0xf1,0xca,0xe8,0xf2,0xcc,0xe7,0xf2,0xd3,0xe6,
+  0xf1,0xdf,0xeb,0xf3,0xd3,0xed,0xf3,0xda,0xf0,0xf6,0xdd,0xe3,0xe3,0xe3,0xe9,0xec,
+  0xe2,0xec,0xec,0xec,0xeb,0xf2,0xe3,0xee,0xf1,0xec,0xf1,0xf6,0xe3,0xf1,0xf4,0xeb,
+  0xf4,0xf9,0xe6,0xf5,0xf9,0xeb,0xf8,0xfa,0xef,0xf4,0xf4,0xf4,0xf5,0xf8,0xf2,0xf9,
+  0xfb,0xf4,0xfb,0xfb,0xfa,0xff,0xff,0xff,0x92,0x33,0xcc,0x38,0x0,0x0,0x1d,0x5d,
+  0x49,0x44,0x41,0x54,0x78,0x5e,0xed,0x9d,0x6b,0x80,0x5b,0xc5,0x75,0x80,0x65,0x59,
+  0x69,0xb4,0x52,0xeb,0xbe,0x50,0xd5,0xbc,0xd6,0xde,0x78,0xbd,0xb6,0x54,0x35,0x4,
+  0xda,0xda,0x6e,0x48,0x6c,0x76,0x81,0xa4,0xf1,0x1a,0xd6,0x24,0xe,0xb6,0x43,0x63,
+  0x43,0xbc,0x32,0x4,0x64,0xc7,0x98,0x26,0x7d,0x40,0x81,0xb8,0x10,0x6c,0x24,0xd4,
+  0xa6,0xf,0x6d,0xa4,0xb6,0x69,0xd2,0x92,0x26,0x25,0xb4,0x21,0x4d,0x29,0x21,0x24,
+  0x4,0xb7,0x26,0xa1,0x69,0x42,0xbc,0x5a,0xc7,0xb0,0x2a,0x4d,0x1f,0x1,0x5,0xdb,
+  0xd4,0x6b,0x59,0x96,0xc1,0x96,0x77,0xd4,0x99,0xab,0xc7,0xde,0xc7,0xcc,0x39,0x33,
+  0x7a,0x5c,0x69,0x15,0xcd,0xf,0xbc,0xec,0xce,0xbd,0x77,0xee,0x99,0xef,0x9e,0x39,
+  0x73,0xe6,0xcc,0x19,0x47,0xa9,0x57,0x7a,0x12,0x50,0x91,0x80,0x43,0xa5,0x72,0xaf,
+  0x6e,0x4f,0x2,0xa5,0x1e,0x31,0x3d,0x8,0xd4,0x24,0xd0,0x23,0x46,0x4d,0x5e,0xbd,
+  0xda,0x3d,0x62,0x7a,0xc,0xa8,0x49,0xa0,0x47,0x8c,0x9a,0xbc,0x7a,0xb5,0x7b,0xc4,
+  0xf4,0x18,0x50,0x93,0x40,0x8f,0x18,0x35,0x79,0xf5,0x6a,0xf7,0x88,0xe9,0x31,0xa0,
+  0x26,0x81,0xa6,0x11,0x33,0xfb,0xca,0xe9,0x99,0x97,0x59,0x39,0x7e,0xfc,0xb8,0xf6,
+  0xef,0xe9,0xd3,0x5,0xa2,0xd6,0x96,0x5e,0xed,0xf9,0x20,0x81,0xc6,0x89,0x21,0x2f,
+  0x7d,0xfb,0xa9,0x83,0x7,0xe,0x3c,0x71,0xef,0xdd,0x1f,0xdd,0xc5,0x4a,0x24,0x12,
+  0xd1,0xfe,0xbd,0xf3,0xee,0x7,0xbe,0x71,0xe0,0xc0,0xc1,0xa7,0xbe,0xfd,0xdf,0xf3,
+  0x41,0xe,0xbd,0x36,0xca,0x4a,0xa0,0x1,0x62,0x8,0x21,0xe7,0x9e,0xff,0xec,0xfe,
+  0x7d,0x77,0xec,0xda,0x49,0x29,0x11,0x95,0x9d,0xbb,0xee,0xd8,0xb7,0xef,0xb3,0xff,
+  0x71,0x9e,0xd6,0x96,0x6d,0x93,0x7d,0xf5,0x48,0x11,0x28,0x2d,0x6f,0x6,0xf4,0xf4,
+  0xe,0x14,0x56,0x45,0x1e,0xf5,0x12,0x33,0x3b,0x73,0xf4,0xe0,0xdd,0x10,0x29,0x16,
+  0x82,0xee,0xf9,0xea,0xf1,0xd3,0x9d,0x26,0x87,0xc3,0x6e,0x87,0xb0,0x78,0x5a,0x4d,
+  0x4c,0x71,0x40,0xfc,0x70,0x47,0xa2,0xd5,0x4f,0xaf,0xfb,0xfe,0x75,0x11,0x43,0x7e,
+  0x74,0xf0,0x89,0x8f,0x1,0x7a,0x45,0xf4,0xa7,0xbb,0xbf,0x78,0xf0,0x7f,0xeb,0x6e,
+  0x69,0x2b,0x2e,0xec,0x46,0x62,0x5a,0xfd,0x55,0xaa,0x13,0x43,0xce,0x1e,0xdc,0x7f,
+  0x87,0x92,0x76,0xd1,0x1,0xb4,0xf3,0x8e,0x7d,0xcf,0xce,0xb6,0xfa,0x9d,0xe4,0xd9,
+  0xea,0x3a,0x62,0xc8,0xc9,0x27,0x9e,0x93,0x7f,0xfd,0xba,0x6a,0xaa,0x12,0xf3,0xca,
+  0xb,0x5f,0xa8,0x97,0x96,0x2a,0x38,0xbb,0xfe,0xe1,0xc5,0x42,0x5d,0x6d,0x6d,0xfe,
+  0x45,0x5d,0x46,0xcc,0xec,0x89,0xaf,0xdf,0x12,0xf9,0x74,0xf3,0xc5,0x64,0xb8,0xa3,
+  0x1a,0x31,0x67,0xe,0xde,0x7b,0x53,0x1d,0xa3,0x91,0xf9,0x92,0xdd,0xf,0xfc,0xdb,
+  0xf9,0x16,0xbf,0x97,0xdc,0xed,0xbb,0x8a,0x18,0x72,0xec,0x89,0x3d,0x54,0xd2,0x1d,
+  0x44,0xc,0x39,0xf7,0xe8,0xde,0x46,0xf5,0x4b,0x95,0x9d,0x9d,0x1f,0xfb,0xd7,0x4e,
+  0x18,0x9c,0xba,0x88,0x18,0x72,0xe2,0xeb,0x7b,0x76,0x33,0xf1,0xca,0x13,0x93,0x93,
+  0x2e,0x79,0xdd,0x7,0x28,0xad,0x63,0xc8,0xe9,0xa7,0x3e,0xdc,0x4,0xf5,0x32,0x77,
+  0x8b,0x8f,0xfe,0xfb,0x69,0x39,0x45,0xd0,0xc2,0x5a,0x5d,0x43,0xcc,0xb9,0xe3,0x8f,
+  0x6b,0xb8,0x30,0x62,0xa,0x47,0x72,0x72,0x22,0xcb,0x48,0x17,0xfd,0xd,0x65,0x89,
+  0x99,0xfd,0xce,0xc7,0x9b,0xca,0xb,0xbb,0xd9,0x3d,0xdf,0x9d,0x95,0x7b,0xb5,0x96,
+  0xd5,0xea,0x12,0x62,0xc8,0xb,0x5f,0x67,0xe3,0x51,0xb9,0xfc,0x66,0x3c,0x34,0x2d,
+  0x27,0x30,0x69,0x60,0x32,0xea,0xc4,0x90,0x73,0xbf,0x7f,0x4b,0xd3,0x81,0xa1,0xbe,
+  0xe1,0x7b,0xcf,0xb7,0x77,0xde,0xd4,0x15,0xc4,0xcc,0x1e,0x7f,0xbc,0x3c,0x1e,0x95,
+  0xcb,0xca,0x40,0xa0,0xfd,0xc4,0x9c,0x7d,0xec,0xe6,0x16,0xf0,0xc2,0x6e,0xf9,0xe1,
+  0x7f,0x39,0x2b,0xf7,0x3d,0xb4,0xa6,0xd6,0xfc,0x27,0x86,0x9c,0x3d,0x76,0x9f,0xe,
+  0x17,0x2a,0xd2,0x8b,0x54,0x88,0xc9,0x4a,0x98,0x32,0x54,0x15,0xa9,0xea,0x98,0x1f,
+  0x7d,0xbe,0x19,0x13,0x24,0x3e,0x73,0xbb,0x1f,0x6c,0xa7,0x4f,0x6f,0xde,0x13,0x43,
+  0xe,0x3d,0x3e,0x37,0x1e,0x95,0x25,0xac,0x44,0x8c,0x8c,0xc5,0xa3,0x4c,0xc,0x79,
+  0xee,0x77,0x5b,0xa4,0x60,0xca,0xb7,0xbd,0xf3,0x7,0xed,0x1b,0x99,0xe6,0x37,0x31,
+  0x64,0xf6,0xe8,0x7d,0x56,0x63,0xa1,0xed,0xc4,0xcc,0x3e,0x7a,0x63,0x4b,0x81,0x89,
+  0x44,0x76,0x1e,0x2c,0xb6,0x66,0xcc,0xc1,0xef,0x3a,0x9f,0x89,0x21,0x67,0xf,0xed,
+  0x37,0x8e,0x47,0x9d,0xa1,0x63,0x5e,0x79,0x78,0xbc,0xc5,0xc0,0xd0,0xdb,0x3f,0xdc,
+  0x2e,0x1f,0xf0,0x3c,0x26,0x66,0xf6,0x19,0x8e,0x7e,0xe9,0x80,0x51,0xe9,0xd4,0xed,
+  0xcd,0xf2,0xd9,0x41,0xdc,0xed,0xfc,0x9b,0xff,0xc3,0xf5,0x41,0x2b,0x6a,0xcc,0x57,
+  0x62,0xc8,0xb9,0x43,0xfb,0x45,0x93,0x57,0xf9,0x51,0x89,0x6,0xa0,0xc0,0x6,0x41,
+  0xf9,0xaf,0xa6,0x6a,0xb0,0x3f,0xe6,0xd4,0x6f,0xb5,0x5e,0xc1,0x68,0x4f,0xf8,0xed,
+  0xf6,0x78,0xf3,0xe6,0x29,0x31,0xb3,0x87,0xfe,0x40,0xdc,0x2f,0xf2,0xc4,0xd4,0xbe,
+  0x41,0x16,0x24,0x64,0xf9,0x20,0x49,0x21,0x9f,0xe7,0x1,0x5,0x12,0xf3,0xd2,0xed,
+  0x36,0x1,0x13,0x89,0xb4,0x47,0xcb,0xcc,0x53,0x62,0x4e,0xec,0x5,0xfa,0xa5,0xe,
+  0x62,0x4c,0xb3,0xa1,0x32,0x3c,0xc5,0x4c,0x26,0xcb,0x33,0x30,0x21,0x62,0x5e,0xba,
+  0x8d,0x67,0x59,0xb5,0x6,0xa2,0xdd,0xf7,0xb4,0x63,0x60,0xea,0x11,0xa3,0xc1,0x21,
+  0x22,0x26,0xa3,0x5f,0x4f,0xaa,0x2a,0x21,0x80,0x98,0x53,0xbf,0xd7,0x1a,0x38,0x4,
+  0x77,0x6d,0xc7,0xc0,0xd4,0x23,0x46,0x48,0xc,0x29,0x50,0x8e,0xd4,0x88,0x29,0x7c,
+  0x4a,0xd,0x98,0xf0,0xd6,0x8d,0x63,0xeb,0x46,0x87,0xaf,0x60,0x65,0x78,0xdd,0xba,
+  0xb1,0x8d,0xdb,0xc3,0x6a,0x37,0x78,0xc0,0xfe,0x19,0xd3,0x8f,0x37,0x31,0x24,0x5f,
+  0x29,0x94,0x8d,0x6c,0xf5,0xe7,0xda,0xbf,0x39,0xd5,0x51,0xe9,0xfc,0x43,0xf2,0x8e,
+  0xde,0xf0,0x8e,0x4d,0x6b,0x57,0xaf,0x18,0x1a,0xa4,0x25,0x50,0x2e,0xec,0xc7,0xa1,
+  0x55,0xab,0x2f,0xdd,0xbc,0x43,0x1e,0x9b,0xdd,0xf,0xdb,0xbe,0x30,0xf9,0xe3,0x4e,
+  0xc,0xb2,0x16,0x99,0x53,0xb2,0x7c,0xff,0x59,0xb6,0xab,0xc7,0x37,0x5f,0x79,0x51,
+  0x15,0x94,0xa,0x2f,0xba,0x7f,0x6,0x2f,0x1a,0xdd,0x2c,0xed,0xd1,0x79,0xaa,0x15,
+  0x33,0x68,0xe8,0x9e,0x6d,0x25,0x86,0x44,0xfb,0xc4,0x25,0x5,0x35,0xbb,0x59,0x96,
+  0x6f,0x91,0xea,0x11,0xa8,0x28,0xcd,0x95,0x9e,0x97,0xd4,0x30,0xe3,0xeb,0x2e,0x59,
+  0x6a,0xe5,0xc4,0xf0,0x9b,0xa5,0xab,0x2f,0xdd,0x2a,0x37,0x3e,0xed,0xfc,0x1f,0x9b,
+  0x91,0x69,0x2f,0x31,0xb9,0x29,0x71,0xe1,0x59,0x10,0x35,0xe1,0x34,0x8b,0x18,0x92,
+  0x7,0x81,0xe1,0xaa,0x18,0x51,0xc6,0xa1,0x97,0xe4,0xb6,0xa,0x6c,0xbf,0x74,0x99,
+  0x5e,0xbd,0x4,0x43,0xb4,0x44,0xa3,0xd1,0x78,0x3c,0x4e,0xff,0x4b,0x7f,0xe,0x56,
+  0xc6,0xa8,0xa1,0x77,0x6c,0x95,0x52,0x59,0x1f,0x3f,0x65,0x2f,0x32,0x6d,0x25,0xa6,
+  0xfe,0x57,0x6d,0x16,0x31,0x25,0x92,0xd5,0xa,0xe3,0xa6,0xfc,0xd3,0x5c,0xc9,0x17,
+  0x8a,0x7c,0xf7,0x1e,0x7f,0xae,0x74,0xf6,0xf3,0x32,0x4a,0x81,0xf2,0x32,0xa7,0x4c,
+  0x42,0xd1,0x58,0x22,0x35,0x95,0xd1,0x29,0xb2,0x62,0x6e,0x3a,0x9d,0x4c,0xc4,0xa2,
+  0x1a,0x36,0x4b,0x87,0xa5,0xf4,0xcc,0x83,0xf6,0xc6,0xff,0xfe,0xb8,0x13,0x53,0x81,
+  0x96,0x3b,0xbb,0x16,0x1,0xcd,0x27,0xe6,0x29,0x89,0x31,0x29,0x3c,0x76,0xd1,0x40,
+  0x15,0x98,0x60,0x34,0x79,0x24,0xcb,0x1d,0xf5,0xa8,0xe2,0x3b,0x9c,0x88,0xb2,0x7a,
+  0xcb,0xc7,0x24,0xd4,0xcc,0xce,0xe7,0xeb,0xff,0xf2,0xea,0xb8,0xb2,0x47,0x8c,0xd8,
+  0x1f,0xa3,0x44,0xcc,0x49,0x89,0x80,0xbb,0xf1,0x8b,0xab,0xf6,0x4b,0x30,0x3a,0x91,
+  0x13,0x68,0xb0,0xf2,0x53,0x49,0x31,0x9b,0xa0,0x9a,0x66,0xf0,0x62,0x9,0x13,0xf8,
+  0x43,0xb6,0x2a,0x99,0x1e,0x31,0x5a,0x7,0xd1,0xb0,0x2a,0xd0,0x6e,0x32,0xc0,0xc3,
+  0xd3,0x31,0xb3,0x12,0x63,0xd2,0xc6,0x37,0x55,0xf4,0x4b,0x28,0x36,0x29,0xe3,0x47,
+  0xc9,0xa7,0x62,0xc1,0xc0,0x9b,0x36,0xe1,0x6a,0xe6,0x6f,0xed,0x8c,0x96,0xe9,0x11,
+  0xa3,0xae,0x98,0x79,0xc4,0x7c,0xf,0x57,0x31,0x63,0xcb,0x2a,0x23,0x52,0x2c,0x2d,
+  0x4b,0x67,0x7e,0x32,0x1a,0x58,0xf6,0x6e,0xd4,0x3e,0xba,0xf9,0x59,0xf5,0x97,0xa8,
+  0xfb,0x8a,0x1e,0x31,0xea,0xa2,0xe3,0x10,0x73,0x6,0xdd,0x35,0x10,0x7e,0xf7,0x9b,
+  0xcb,0x1a,0x26,0x9a,0x2,0x87,0x23,0x63,0x73,0x48,0x31,0x19,0x1a,0x7c,0x37,0xaa,
+  0x65,0x3e,0x22,0xa3,0xb2,0xd4,0x5f,0x94,0x7b,0x45,0x8f,0x18,0x75,0x41,0x72,0x88,
+  0xf9,0x16,0xa6,0x7,0xc2,0x6b,0xcb,0xc0,0x4,0x13,0x32,0x61,0xa2,0xba,0x36,0x91,
+  0x4c,0x7c,0xf0,0x52,0xc,0x99,0xed,0x5f,0x51,0x7f,0x8b,0x7a,0xaf,0xe8,0x11,0xa3,
+  0x49,0x8e,0x17,0xec,0x40,0xad,0x4f,0x4e,0x8,0x4,0xad,0x6c,0x25,0x66,0xd6,0x1c,
+  0x6a,0x6c,0x1,0xa8,0xa2,0x61,0x42,0x29,0xf5,0x68,0xcb,0x7c,0xf2,0x97,0xc6,0x30,
+  0x20,0x3f,0xa0,0x7e,0xdb,0x1e,0x31,0x73,0x42,0xad,0x2f,0xda,0xc1,0x2a,0x41,0x1a,
+  0xed,0xc0,0x55,0x8,0x56,0x62,0xbe,0x83,0xf5,0xe8,0xfa,0x25,0xe5,0x11,0x69,0xba,
+  0x1e,0x1b,0x95,0x4c,0x5e,0xb6,0x11,0x79,0x40,0xf8,0x93,0xf5,0xdc,0xd8,0xfc,0xca,
+  0x74,0x5a,0x3f,0x19,0xb,0xf9,0x7d,0xb4,0x4,0x42,0xd1,0x64,0x26,0xc7,0x9b,0xfc,
+  0xab,0xea,0x18,0x42,0xfd,0xea,0xe9,0x44,0xb4,0x7c,0x5b,0x9f,0x3f,0x10,0x8a,0xa7,
+  0xa6,0xb3,0x79,0x85,0x91,0xb9,0x5e,0xb4,0x8d,0xd7,0x35,0xcd,0x83,0x57,0xb9,0x2d,
+  0xf5,0xc7,0x34,0x40,0xcc,0xb9,0x7d,0x48,0x87,0x5e,0xf3,0x46,0xd,0x98,0x98,0xe2,
+  0x88,0x54,0x6d,0x12,0x99,0x7e,0x17,0xe6,0xcb,0xbb,0xf6,0x70,0xc3,0xc8,0x14,0x52,
+  0x21,0x9f,0x53,0x9f,0xd0,0xc7,0xe9,0xf1,0x45,0x93,0x96,0x9d,0x5f,0x4a,0xc4,0x90,
+  0x6c,0x2a,0xd6,0xdf,0x67,0xb8,0x2b,0x7b,0x82,0xcb,0xbb,0x24,0x96,0x3c,0xd2,0x70,
+  0x8b,0x11,0x96,0x66,0x8f,0x1f,0x9b,0x2b,0x4f,0x43,0xc3,0xc0,0xf0,0xc8,0xc8,0x23,
+  0xba,0xba,0xec,0xc7,0x93,0x48,0xeb,0x1a,0x23,0xe6,0xbb,0x2c,0x91,0x1d,0x50,0xc6,
+  0xdf,0xaa,0xcd,0x92,0xe2,0x75,0x2,0x43,0x5,0x73,0xe4,0x5a,0xc4,0x2f,0xb3,0xed,
+  0x8f,0x85,0xc6,0xef,0xb4,0x5f,0x54,0xee,0xd7,0x8b,0x7c,0xc2,0xcf,0x4b,0x3e,0xe5,
+  0xf2,0xc,0x4c,0x18,0xef,0xac,0x40,0xc,0x49,0x5,0xbc,0x2e,0x51,0x52,0x29,0x97,
+  0xa7,0x5f,0xd5,0xa6,0xa3,0x6e,0xaa,0x84,0xf0,0x65,0xfc,0xfe,0x49,0x13,0x41,0x33,
+  0x7b,0xf7,0xe8,0xa,0x14,0xe9,0x16,0xbe,0xf1,0x46,0x7d,0x55,0xf6,0xf3,0x93,0x48,
+  0x50,0x40,0x43,0xc4,0xcc,0x3e,0x81,0xa8,0x98,0xb5,0xda,0x98,0x14,0x93,0x9d,0x53,
+  0x73,0x3e,0x1d,0x92,0xfe,0x0,0xfc,0x8c,0xf0,0xfb,0x85,0xdb,0x40,0x27,0x85,0x89,
+  0xc0,0xfa,0x6b,0x4f,0x22,0x53,0x7e,0x8b,0x22,0xa8,0x5e,0xe6,0x74,0xc7,0x32,0x3a,
+  0x33,0x49,0x96,0x18,0x92,0x89,0x59,0x95,0x8b,0xb1,0x29,0x4e,0x57,0x7f,0x8a,0xeb,
+  0xf5,0x16,0x2a,0xf,0xa5,0xac,0x66,0x33,0xb8,0xc7,0x43,0x2c,0xd4,0x27,0x70,0x62,
+  0xcc,0xcb,0x4a,0xda,0x6a,0x93,0x94,0x1d,0x73,0xe2,0xe,0xb8,0x37,0xb7,0xbe,0x5e,
+  0xb3,0x61,0x1a,0x0,0x86,0x4a,0xf0,0x1f,0x11,0x25,0xb3,0xe9,0x8f,0x44,0x6a,0x54,
+  0x82,0x98,0x42,0x14,0x48,0x6e,0x47,0x7b,0xd9,0x1d,0x9c,0xbb,0xb9,0x1c,0x31,0x24,
+  0x8d,0xdc,0xb2,0xc2,0x8e,0xd3,0x17,0xcf,0x28,0x8c,0x4e,0x1d,0x45,0xc,0x77,0x11,
+  0x5b,0x8a,0x98,0x6f,0x22,0x2a,0xe6,0x2d,0x6c,0x4c,0x8a,0x4a,0x6e,0x5,0x17,0x7d,
+  0x5e,0xe4,0x5a,0x64,0xe4,0x1b,0xc9,0xa,0x2e,0xc5,0x89,0xc9,0x7,0x84,0xa,0xa6,
+  0xd2,0xb1,0x7d,0x8a,0xc4,0x14,0x43,0x7d,0x40,0x8a,0x43,0xc3,0x9f,0x9c,0xde,0xb8,
+  0x3c,0x32,0xdd,0x41,0xc,0x41,0x54,0xcc,0x7a,0xe6,0x89,0x9,0x4d,0xca,0x8b,0x85,
+  0xdf,0xf3,0xff,0xb9,0xd,0x46,0x66,0x58,0x24,0x78,0x94,0x98,0x8c,0x7f,0x1,0xd6,
+  0xbd,0xb1,0xb9,0x36,0x49,0xe8,0x98,0xc2,0x84,0x7,0xbb,0xa1,0xc1,0xc2,0x5e,0x24,
+  0xed,0x73,0xb0,0x8f,0x98,0xeb,0xee,0x8f,0x83,0x5d,0x26,0x8a,0x92,0x91,0xd1,0x31,
+  0xaf,0x22,0x1f,0xff,0xc5,0x4c,0xc5,0x24,0x1a,0x76,0x98,0x14,0xff,0x12,0xf6,0xe3,
+  0x6d,0xd,0x1d,0xe1,0xa3,0x86,0x11,0x93,0xf5,0xa1,0xdd,0xdb,0xa7,0x53,0x90,0x38,
+  0x31,0x19,0xb1,0x4d,0x24,0x78,0x92,0x33,0x20,0x52,0x90,0xa6,0x57,0xb2,0x8f,0x98,
+  0xab,0x7,0x3,0x49,0xe8,0x23,0x67,0x31,0xe0,0xbc,0x38,0x5f,0x19,0x62,0x1e,0x83,
+  0x89,0xd9,0xc2,0x66,0xd6,0xc1,0xc6,0x8c,0x18,0x4d,0x6e,0x5f,0x41,0x36,0x73,0x2f,
+  0x17,0xbc,0x21,0x42,0x4c,0xce,0x8f,0x2,0xe3,0x8,0x28,0x58,0xbe,0x24,0xb5,0x8,
+  0xbf,0xa1,0xa5,0x86,0x4f,0x4e,0x7,0x77,0x14,0x31,0xf5,0xfa,0x63,0xc8,0xbd,0x30,
+  0x31,0xbf,0xc6,0x54,0xc,0x18,0x82,0x2a,0xe9,0xa2,0x2a,0x22,0x9b,0x2d,0x87,0x5,
+  0x93,0x31,0x98,0x98,0xac,0x4,0x30,0x2e,0x7d,0xf3,0x11,0x1d,0x53,0x8c,0xa,0xe7,
+  0xd3,0x20,0x48,0xae,0x98,0x8c,0x16,0xee,0xa,0x62,0xce,0x0,0xbb,0x33,0x29,0x4b,
+  0x61,0x36,0x51,0x6a,0x70,0x9e,0x54,0x41,0xea,0xcf,0x10,0x65,0x16,0xe4,0xf,0x4b,
+  0x20,0x31,0xc5,0x7e,0x9,0x85,0xe0,0xd7,0x77,0x26,0x4c,0x4c,0x2e,0x28,0x71,0x3f,
+  0x6e,0x95,0x5,0x32,0x42,0xea,0xa,0x62,0x7e,0x0,0xaf,0x29,0xad,0xa7,0x2a,0xa6,
+  0x71,0xb3,0x57,0x63,0xa6,0xf0,0x41,0x10,0x99,0x6d,0x2b,0xf8,0x69,0xd6,0x21,0x62,
+  0x48,0x54,0xa6,0x83,0x27,0xf4,0x5a,0x10,0x24,0x26,0xd7,0x8f,0xcd,0xba,0xc4,0xcf,
+  0x73,0x2e,0xc1,0x87,0xee,0x6e,0x20,0x86,0x1c,0x84,0xbf,0xfc,0xb7,0x36,0x4d,0xc5,
+  0x94,0x4a,0x57,0xc3,0x9e,0xe5,0x91,0x10,0xd7,0x54,0x3,0x88,0x21,0x71,0x99,0x21,
+  0xc4,0x6d,0xb8,0x2d,0x44,0x8c,0xdb,0x2b,0x3,0xa0,0xb0,0x8e,0xf,0x45,0xa6,0x73,
+  0x88,0xe1,0xe7,0x78,0x10,0x64,0x7e,0x30,0xac,0x44,0x9e,0xfb,0x1a,0xdc,0x8d,0x2c,
+  0xee,0x2e,0x29,0x69,0xa9,0x60,0xd5,0xbe,0x4,0xcf,0x96,0xde,0xcf,0x4f,0xff,0x7,
+  0x10,0x93,0x82,0x1d,0x77,0x95,0xae,0x8d,0x1a,0xda,0x5,0x11,0xd3,0x10,0x2f,0xf4,
+  0xe2,0x25,0xd8,0x3a,0x4a,0xe7,0x10,0x83,0xf5,0x95,0xe1,0xef,0x6,0x62,0xce,0xc0,
+  0x7b,0x4e,0xd6,0xb3,0xc8,0x5e,0x4c,0xe,0xb2,0x4f,0xff,0xe1,0x35,0x20,0x9d,0x1b,
+  0x6,0xb9,0x68,0x8a,0x89,0xf1,0x49,0xb9,0x4d,0xdc,0x69,0xdb,0x88,0x71,0x62,0x73,
+  0xca,0x6e,0x20,0xe6,0x4,0x9c,0x5e,0x68,0x2d,0x35,0x63,0xc,0xb,0x7e,0xb2,0x74,
+  0xf0,0xea,0xfd,0xe8,0x3a,0x90,0x98,0x2d,0x2b,0xb8,0xf3,0xd,0x31,0x31,0x72,0x2a,
+  0x61,0x89,0x71,0x12,0xd3,0x4a,0x1d,0xe3,0x70,0xf0,0x7,0xd6,0x9a,0x30,0xba,0x81,
+  0x98,0xe3,0x60,0x27,0x86,0xd7,0x50,0x62,0xcc,0x6b,0xaa,0x75,0x43,0x73,0xfe,0xef,
+  0xe0,0x11,0x70,0x55,0x94,0xe7,0x8,0x6b,0x90,0x18,0x97,0xc1,0xee,0x2d,0x95,0x5a,
+  0x4b,0x8c,0x13,0xf6,0x43,0x74,0x1c,0x31,0x84,0x86,0xdd,0x15,0xa,0x74,0x67,0x1b,
+  0xe8,0xd2,0x37,0x8c,0x4a,0x87,0xc0,0x4e,0xdc,0x4e,0xa3,0xbb,0x42,0x9c,0xd0,0x9b,
+  0x3a,0xa1,0x41,0x36,0x76,0x8f,0x84,0xa6,0x38,0x37,0x6e,0x90,0x18,0xaf,0xc9,0x1c,
+  0x6d,0x2d,0x31,0xe,0x2f,0xb8,0xfe,0xd6,0x61,0xc4,0x90,0x2,0xdd,0x84,0xc2,0xd6,
+  0xb,0x58,0x8a,0x5f,0x20,0x48,0xcc,0x40,0xcc,0x1,0x78,0xa0,0xa0,0x6b,0x4a,0xf7,
+  0xa3,0x33,0x0,0x69,0x7e,0xbe,0xc,0xbb,0x7d,0xaf,0xe0,0x3a,0xb6,0x1b,0x24,0x26,
+  0x6e,0x6a,0x9d,0x12,0x31,0x4e,0x97,0xc7,0xe3,0xef,0xf,0x85,0xfa,0xfd,0x5e,0x8f,
+  0x5b,0x6e,0xe2,0xed,0x87,0xc4,0xd5,0x51,0xc4,0x90,0xbc,0xb6,0x97,0xb6,0x56,0x72,
+  0xc2,0x63,0x61,0xd,0xc4,0xc0,0x1e,0xdf,0xcd,0x34,0x32,0x6,0x5c,0x9e,0x90,0x86,
+  0x45,0xab,0xf8,0x2c,0x7c,0x30,0xc6,0x68,0x20,0xce,0x71,0x9c,0x36,0x46,0x8c,0xcb,
+  0xdc,0x81,0xf2,0xc4,0x38,0x3d,0x8b,0x63,0x73,0xce,0x7f,0x72,0x24,0xde,0xef,0x95,
+  0x80,0xc6,0x9,0x1d,0xde,0xd7,0x41,0xc4,0x50,0xfd,0x62,0x59,0x8d,0x14,0x5,0xfb,
+  0x18,0x88,0x81,0xfb,0x70,0xdd,0x40,0x20,0x64,0x9c,0x6a,0xa8,0x21,0x62,0xaa,0x7d,
+  0xa,0x9e,0x98,0x8d,0x71,0x9d,0xcb,0x8d,0x11,0x33,0x60,0x6e,0xb0,0x34,0x31,0x8b,
+  0x12,0xd3,0x26,0x7e,0x8b,0x99,0x14,0xbe,0xea,0xe9,0xd0,0x45,0x56,0x58,0x84,0xa5,
+  0x46,0xcc,0xd,0xef,0x79,0xcf,0x35,0xd5,0x2,0xa6,0x3d,0xd8,0x5a,0xab,0x56,0xfb,
+  0x61,0x14,0x59,0x89,0xd4,0xf2,0x51,0xc9,0x22,0xa3,0x27,0x86,0xc0,0xfe,0xbb,0x77,
+  0xd0,0x15,0x82,0xe6,0x99,0x31,0xa5,0xd2,0x7d,0xf0,0x18,0x18,0x8,0x71,0x26,0xf2,
+  0xd2,0xc4,0x38,0x5d,0x6e,0x8f,0xb7,0x7f,0xb1,0xdf,0xe3,0x71,0xd7,0x1c,0x7b,0x2e,
+  0xb,0xef,0x72,0xc4,0x38,0xbd,0x9,0xae,0x31,0x58,0x4c,0x19,0x63,0x89,0x79,0xd3,
+  0xb5,0x98,0xd8,0x8a,0x54,0x22,0x86,0x64,0xd3,0xc9,0x25,0xd5,0x72,0xd1,0xe,0x40,
+  0x74,0x17,0xd6,0xaa,0xd5,0x7e,0xa0,0x33,0x16,0x70,0x70,0x28,0xe7,0x91,0xc9,0x31,
+  0x9b,0x57,0x2b,0xc5,0xb2,0x41,0xc3,0xd7,0x32,0x7a,0x62,0xce,0xa1,0x1e,0x5f,0x99,
+  0xe5,0x12,0x69,0xc5,0x73,0x1b,0x3c,0x59,0xa,0x4,0x38,0x78,0x4a,0x12,0xe3,0xf2,
+  0x47,0x27,0x2b,0xe1,0x70,0xc5,0xa9,0x44,0xc8,0x57,0x86,0xc6,0x6a,0x55,0x48,0x11,
+  0xe3,0x14,0xbf,0x35,0xbe,0x54,0xa9,0x8f,0xad,0x30,0x49,0x46,0x89,0x18,0x7a,0x6d,
+  0xa6,0x9a,0x17,0x21,0x30,0x2,0x99,0x80,0x74,0x7e,0xc2,0x29,0x20,0x31,0x8c,0xf,
+  0xe3,0x5e,0x8b,0x32,0x43,0xdc,0xf5,0x54,0x3d,0x31,0x67,0x61,0x62,0x2e,0xa4,0xf1,
+  0xe0,0x8d,0x86,0x52,0xe9,0x85,0xf6,0x11,0xf8,0x71,0x81,0x0,0x67,0xb2,0x24,0x47,
+  0x8c,0x6f,0xd2,0xf8,0x79,0x64,0x53,0xa1,0x85,0xe,0x87,0xd3,0xda,0x7a,0x19,0x62,
+  0x5c,0xd0,0x4b,0x17,0x13,0xc8,0xd2,0x84,0x53,0xac,0x64,0x3a,0x86,0x18,0xc2,0xd2,
+  0xc7,0x98,0x66,0x47,0x5a,0x32,0x22,0x34,0xab,0xd9,0x49,0xb8,0xb,0x69,0x6c,0x4c,
+  0xb3,0x96,0x8,0x34,0x70,0xfe,0x4,0x23,0x86,0xe3,0xce,0x90,0x21,0xa6,0x6f,0x82,
+  0x93,0xce,0x38,0x17,0xea,0xf3,0x5a,0x47,0x39,0x9,0x62,0x16,0xa5,0xc1,0xaf,0x84,
+  0x1c,0x46,0x42,0x3a,0xbd,0xc2,0x81,0x5c,0x99,0x18,0x96,0xcf,0x49,0x2b,0x97,0x21,
+  0x3a,0x46,0xcb,0xfc,0x64,0x2c,0x90,0x8e,0xa1,0x7b,0xd9,0x32,0x96,0xdd,0x1b,0x84,
+  0x45,0x86,0x63,0x79,0xf0,0x66,0xe0,0x2e,0xa4,0xa1,0xe,0x4d,0xf3,0xdf,0x31,0x62,
+  0xfe,0x14,0x7e,0xdc,0x50,0x80,0x33,0xd1,0x90,0x20,0xa6,0x4f,0xd0,0xc8,0xc,0x7,
+  0x40,0x9c,0x18,0x37,0x6a,0xb9,0x4d,0xc2,0xc8,0x88,0xa7,0x4b,0xaa,0xc4,0x14,0xd3,
+  0xd5,0xf2,0x25,0x68,0x8a,0x42,0x47,0xa5,0x89,0x5a,0xcd,0xda,0xf,0x59,0x80,0x7b,
+  0xa6,0x4e,0xac,0x7f,0x96,0xc9,0x0,0xd,0xbb,0x7c,0x23,0x74,0x72,0xcd,0x73,0xaa,
+  0x49,0xdb,0x2d,0xe6,0x8a,0x7f,0x85,0x11,0xa3,0xb,0xc8,0xad,0x5e,0x8b,0x13,0xe3,
+  0x52,0xd1,0x83,0x28,0x31,0x2e,0xfc,0x6c,0x7b,0x6c,0xcd,0xdc,0x27,0x12,0x90,0x2a,
+  0x31,0x73,0xf7,0x69,0xf2,0x9e,0x48,0x66,0xb3,0x58,0x1b,0xc9,0x34,0xf,0x96,0xcf,
+  0xf7,0x18,0xdc,0x85,0x8b,0x3,0xb2,0x11,0xac,0x72,0x10,0x7d,0x1a,0x7e,0xdc,0xaa,
+  0x80,0x71,0x9d,0x59,0xbb,0x29,0x4a,0xc,0x68,0x75,0x58,0xda,0x85,0x11,0xe3,0x8c,
+  0x4a,0x4,0xd3,0x91,0x10,0xbc,0xa6,0x25,0x5a,0xbb,0xed,0x18,0x62,0x98,0x8e,0xe1,
+  0x13,0xc3,0xdb,0x69,0xa8,0xb7,0x7c,0xbf,0x7,0x77,0x61,0x7f,0x20,0xd0,0x3c,0x8f,
+  0x2f,0x6d,0xe1,0xe7,0x30,0x62,0x42,0xd6,0xd7,0x40,0x89,0x59,0x2c,0xd1,0xc5,0x73,
+  0xb7,0xc5,0x88,0xe9,0x97,0x7a,0xe1,0x3c,0xbc,0x6c,0x6e,0x76,0x34,0x57,0x1f,0xdf,
+  0x31,0xc4,0x30,0x6d,0xc2,0x1d,0x95,0x50,0x3b,0xe6,0x29,0x54,0xc7,0x34,0x73,0xaa,
+  0x54,0xfa,0x32,0xfc,0xb8,0x95,0x81,0xa0,0x3a,0x31,0x4e,0xb5,0x9d,0x54,0x18,0x31,
+  0x92,0x77,0x9b,0x0,0xdd,0xbf,0x7e,0x81,0xd4,0x3a,0x86,0x18,0x36,0x57,0xb2,0xfa,
+  0x5e,0xa8,0xe6,0x41,0x89,0x41,0x22,0xf0,0xe8,0xa8,0x24,0x37,0xdc,0x48,0xd6,0x7a,
+  0x4,0x26,0x66,0x35,0xef,0x71,0x98,0x8e,0xe1,0xa8,0x25,0xa8,0x35,0x8,0x31,0x7e,
+  0xc9,0x37,0xc9,0x81,0xde,0x5f,0x53,0x4c,0x4e,0xed,0x9e,0x1d,0x43,0x4c,0xf9,0x98,
+  0x13,0x23,0xd7,0x84,0xfd,0x8e,0x8b,0xba,0x7e,0x54,0x42,0x52,0xd,0xf5,0xf3,0x3e,
+  0x7a,0x49,0x99,0xf2,0xaa,0x7d,0x9,0xd3,0x31,0x1,0x6b,0x8b,0x11,0x62,0xac,0x5e,
+  0x5d,0xb8,0x7d,0x30,0x31,0x4e,0x59,0x23,0x9a,0xc4,0x20,0x25,0xb3,0x50,0x60,0x3d,
+  0x77,0xe,0x31,0xcc,0xf9,0x62,0xf4,0xe0,0xb1,0x85,0xc9,0x1c,0x7f,0x80,0xd7,0x13,
+  0x3,0x7,0x3b,0x44,0x16,0x7,0x14,0xbf,0x60,0x84,0xa6,0xbf,0xc6,0xec,0x18,0xfd,
+  0xce,0xa2,0xca,0xbd,0x10,0x62,0xc0,0xb5,0x62,0x4e,0x73,0x60,0x62,0x7c,0xd2,0xf1,
+  0x86,0x53,0x60,0xc4,0xa8,0x20,0xb2,0xaa,0x73,0x88,0x29,0x95,0xfd,0x75,0x34,0x11,
+  0xe,0xfb,0x46,0xe9,0x2a,0x1,0x5b,0x98,0x14,0x45,0x3c,0xe8,0x89,0x79,0x1,0xee,
+  0xc2,0x25,0x4d,0x26,0x6,0x99,0x5d,0xaf,0xe0,0x19,0xda,0x30,0x31,0x4e,0x91,0x91,
+  0x29,0x62,0x17,0x24,0xc6,0xc9,0x99,0xdd,0x8b,0x6e,0x34,0x0,0x4d,0x97,0x4,0x1c,
+  0xb7,0x9d,0x18,0xd1,0xe6,0xd9,0xb9,0x90,0x7,0xde,0xeb,0xea,0x89,0x41,0x66,0xd7,
+  0xaf,0x6f,0x32,0x31,0x7f,0x81,0xf9,0x63,0x38,0x31,0xc5,0x30,0x31,0x6e,0x55,0x7f,
+  0x11,0x48,0x8c,0x5b,0xc1,0x5f,0x99,0x82,0x88,0xf1,0xf0,0xbd,0x80,0x5d,0x40,0xc,
+  0xe2,0xc1,0x7b,0x63,0x93,0x89,0xf9,0x73,0x98,0x18,0x7a,0xe0,0x81,0x75,0x54,0x80,
+  0x89,0xf1,0x29,0x4d,0xad,0xe9,0x7,0x4,0x12,0xe3,0x91,0x1e,0x94,0xe8,0xf6,0x2b,
+  0x88,0x18,0x81,0x75,0xd5,0x5,0xc4,0x20,0xeb,0x4a,0x17,0x36,0x99,0x98,0xdb,0xb1,
+  0x75,0x25,0x65,0x3b,0x86,0xe3,0xf2,0x6b,0xc0,0xf2,0x95,0x9d,0x29,0x69,0x8f,0x0,
+  0x97,0xa,0xf8,0x16,0x74,0xf7,0x13,0x43,0xf7,0xb7,0x35,0x30,0x33,0xb2,0x5e,0xa,
+  0x47,0xfc,0x85,0xe9,0x92,0xbd,0x55,0x65,0xc0,0x3a,0x46,0x76,0x6e,0x53,0x6b,0xb,
+  0xa8,0x63,0x14,0xcc,0x98,0x52,0x9,0xdc,0xf1,0xcd,0x37,0xaf,0xda,0x4e,0x8c,0x35,
+  0x9f,0x83,0xe9,0x37,0x68,0xb4,0x3,0x12,0x1f,0x43,0x23,0xaa,0x9a,0x49,0xc,0xd9,
+  0xf,0xea,0x98,0xad,0x94,0x18,0xd5,0xd9,0xb5,0x64,0x1a,0xe,0x49,0x9f,0xaf,0x82,
+  0x19,0x53,0x2a,0x81,0x3b,0x78,0xf9,0x73,0xcc,0xb6,0x13,0x53,0x5f,0x6f,0x1a,0xa2,
+  0x36,0xe1,0xed,0x4a,0x34,0x6a,0xb3,0x99,0x3e,0x5f,0xe4,0x8,0xa7,0x4d,0x94,0x18,
+  0x45,0x9f,0xaf,0x53,0x59,0x4,0xa0,0x8e,0x91,0x5a,0x21,0xa8,0x3e,0x32,0x5,0x25,
+  0x3a,0xe2,0x8f,0x6f,0xdd,0x40,0xc,0x9c,0xa0,0x6a,0xf3,0x40,0x53,0xd7,0x95,0x9e,
+  0x83,0xa3,0x8a,0xaf,0xa4,0x5b,0x5d,0x14,0x89,0xe9,0x6b,0x2e,0x31,0x4a,0x77,0x9b,
+  0x82,0x22,0xab,0xbc,0xdc,0x5b,0x75,0x3,0x31,0x70,0xe4,0xed,0xd6,0xa5,0xbc,0x38,
+  0x4a,0x25,0xb9,0xea,0x2b,0x3f,0xa,0x6f,0xbc,0x7e,0xa7,0x3a,0x31,0xc2,0xb8,0x2,
+  0x61,0x1b,0x21,0x1d,0xe3,0x52,0x7a,0xb3,0x69,0xc8,0xf4,0xe5,0xa3,0xdc,0xd,0xc4,
+  0xc0,0xfb,0x95,0xe8,0xe,0xb7,0x26,0x6e,0x25,0xc0,0xf2,0x48,0x8c,0xd0,0x14,0xb0,
+  0x8a,0x3a,0xc6,0xb2,0x55,0x0,0xed,0x73,0x30,0xb7,0x3,0x7a,0xb5,0xbe,0x42,0x6,
+  0x5a,0xbf,0x76,0x77,0xad,0x8e,0x79,0x6,0xd9,0x45,0xdb,0x94,0xf4,0x54,0x15,0xe9,
+  0x9d,0x7f,0x10,0x7e,0xd8,0x4a,0x1a,0x55,0xac,0x48,0x8c,0xf2,0xe4,0x1a,0xf4,0xc7,
+  0x78,0x94,0x88,0xc9,0x42,0xb9,0x43,0xf8,0xea,0xaa,0x1b,0x74,0xcc,0x51,0xd8,0x43,
+  0x32,0x3a,0x60,0xda,0xb6,0xac,0x24,0x53,0x53,0xe5,0x97,0x6e,0x5,0x1f,0xb6,0x7d,
+  0x15,0x37,0xaa,0x18,0x9c,0x5d,0xab,0xae,0x11,0xc0,0x1e,0x3c,0xb5,0x31,0xe,0x5c,
+  0xbe,0xee,0x74,0x62,0xb4,0x7d,0xb3,0xa6,0xfe,0xc9,0x8b,0xe,0x76,0x33,0xcc,0x95,
+  0x66,0xe0,0x14,0x55,0x1b,0x87,0x80,0xdd,0x37,0xaa,0xf4,0xbc,0x8,0x9b,0x31,0x9b,
+  0x87,0x2,0xbc,0x31,0x10,0x24,0x46,0x3d,0x41,0x1f,0x34,0x2a,0xa9,0x11,0x93,0x7,
+  0x1d,0x32,0x1d,0x3e,0x2a,0x69,0x9b,0x93,0x4c,0x6d,0xd4,0x76,0xa4,0xf0,0xda,0x6d,
+  0x20,0xe6,0x55,0xd8,0xf4,0x1d,0x5f,0x19,0x55,0x70,0x9c,0x23,0x8,0x3d,0x4,0xeb,
+  0xb3,0xab,0xe8,0x22,0x1,0x27,0x9e,0x9,0x24,0x46,0xc9,0x81,0xa2,0x35,0xaf,0x47,
+  0x8c,0x26,0x86,0xfa,0x89,0x99,0x7d,0x12,0xee,0xc6,0x77,0x84,0x24,0x83,0xd2,0x24,
+  0x14,0xce,0xd,0xb0,0x19,0x73,0x5,0x9d,0x2a,0x71,0x1c,0x72,0x10,0x31,0x4e,0x75,
+  0xbb,0x1c,0xc9,0xb5,0x29,0xf1,0x1a,0xd5,0x2a,0x5,0x30,0x6b,0x63,0xd7,0xea,0x98,
+  0xd2,0xb7,0x60,0x1f,0xde,0x96,0xa0,0xfa,0x67,0x2c,0x90,0xfa,0x69,0x78,0x50,0xda,
+  0x41,0xd,0x5f,0x9e,0x42,0x83,0x88,0x71,0xa9,0xae,0x5c,0xc3,0x3a,0x46,0xcd,0xbb,
+  0x3,0x8e,0x4a,0xdd,0x6b,0xc7,0x94,0x8e,0x21,0xe7,0xb7,0x2d,0x97,0x4a,0x17,0x3e,
+  0x35,0x85,0xaf,0x21,0x7f,0x6,0xd6,0x66,0xdb,0xa8,0x19,0x13,0xe7,0x44,0xb2,0x43,
+  0xc4,0xb8,0xd5,0x15,0x60,0xf3,0xfc,0x31,0xf3,0x9a,0x18,0x5,0x5d,0x6a,0x3e,0xf5,
+  0xef,0x55,0x38,0x9f,0x6f,0x64,0x83,0xcc,0xc6,0xeb,0x82,0xcf,0xed,0x8d,0x66,0xe0,
+  0x83,0xcd,0x4e,0xc3,0x89,0x1d,0x22,0x6c,0x8d,0x60,0x82,0xb3,0x26,0x1,0x11,0xe3,
+  0x69,0x27,0x31,0xe0,0x5c,0xa9,0x7b,0xfd,0x31,0x25,0xf2,0x5,0xf8,0xd3,0xdf,0xb1,
+  0x52,0x70,0x5e,0x80,0x8e,0xd2,0x72,0xd0,0xab,0xd3,0x1b,0x4d,0x8b,0x8f,0x1b,0x22,
+  0x8f,0xde,0x4,0x3f,0xe8,0x12,0x6a,0xc6,0xf0,0xcc,0x12,0x90,0x18,0x74,0xfb,0xa2,
+  0xe5,0x5b,0x2,0xd7,0x95,0x94,0x16,0xd1,0x32,0x90,0x3f,0x86,0xef,0xda,0xe9,0x6,
+  0x7f,0x4c,0xa9,0x84,0x4,0x6e,0x86,0x47,0x71,0x8f,0x4c,0x4d,0x76,0x6e,0xbf,0x30,
+  0xa3,0xd5,0x2b,0x48,0x36,0xfb,0x30,0x9d,0x29,0x71,0x33,0x8f,0x40,0xc4,0x78,0x95,
+  0x97,0xae,0xe1,0x88,0x2a,0xa5,0x79,0xe1,0x34,0xe4,0xf3,0xed,0xde,0x75,0x25,0x1a,
+  0x15,0xc,0x9b,0xbe,0x91,0x1d,0x97,0xa1,0x5f,0x9e,0x6e,0x87,0xa0,0xd3,0x13,0x9a,
+  0xe6,0x8e,0x4e,0xdf,0x45,0x54,0xc,0x1b,0x94,0xa2,0xbc,0xd,0x79,0x76,0x12,0xa3,
+  0x14,0x6d,0x33,0xd,0xc5,0x86,0x77,0xef,0xda,0x35,0xd5,0xda,0xd8,0xa1,0x7f,0x1b,
+  0xb0,0xd9,0x52,0xc6,0xb8,0x11,0xc3,0xd9,0x9f,0xb4,0x7e,0xab,0xe7,0x3f,0x4,0x8f,
+  0x49,0x91,0xcb,0xd9,0x99,0x3c,0x3c,0x7b,0xc,0x22,0x46,0x3e,0xf4,0xbf,0x76,0x67,
+  0x70,0x54,0x52,0x5a,0x74,0x48,0x43,0x6b,0xd7,0xdd,0x1b,0x1f,0x43,0x25,0x79,0x14,
+  0x51,0x32,0xe1,0x3f,0x84,0xe7,0x41,0x64,0xb1,0x39,0xe2,0x75,0xa1,0xcf,0x92,0x9d,
+  0xe3,0x9f,0x10,0x60,0xb6,0xd2,0x7d,0x4,0xfc,0x55,0x4f,0x3b,0x89,0x51,0x8a,0xda,
+  0x9c,0x80,0x2,0x7d,0x3b,0x34,0x6,0x4f,0x69,0x8a,0x54,0xab,0x6c,0x3e,0xef,0xfa,
+  0xc,0x76,0x78,0xf1,0xad,0xdf,0x87,0x1e,0x44,0x92,0x9c,0x6f,0xcd,0xe5,0x4b,0x1a,
+  0xc6,0xa6,0x1f,0xfe,0xe,0x42,0xcc,0x6,0x6a,0xc6,0x4,0xb9,0xe7,0xd1,0xda,0x49,
+  0x8c,0x17,0xf7,0x11,0xcc,0x89,0x2,0x3c,0x26,0x85,0xbf,0x7c,0xd1,0x71,0x96,0xaf,
+  0xb6,0x51,0x29,0x47,0xb7,0x2d,0x81,0x19,0x7d,0xcd,0xc4,0x90,0x83,0xd0,0xc9,0xb8,
+  0xac,0xa7,0x3f,0xf5,0xa,0x80,0x8c,0x68,0x92,0xe9,0xd3,0x1d,0xee,0x8b,0x99,0xbd,
+  0x91,0x71,0x1a,0xe9,0xc0,0x5b,0xb8,0xa6,0xcf,0xb5,0x93,0x18,0xa5,0xbd,0x2c,0xe0,
+  0xd2,0x35,0xdf,0x19,0xdd,0x61,0xc4,0x18,0xf2,0x6d,0x2,0xa7,0xbe,0x9b,0x89,0x29,
+  0xcd,0xdc,0x85,0x28,0x80,0x9b,0x1e,0x5,0x88,0x89,0x8b,0xb6,0x93,0x3a,0x7d,0xb5,
+  0x2c,0x49,0x7f,0xf,0xbb,0x7b,0x23,0x91,0x4d,0x54,0xc5,0x8,0x42,0x71,0x20,0x62,
+  0x54,0x37,0x44,0x22,0xeb,0x4a,0x34,0xb,0x9a,0xbc,0xda,0x26,0xd0,0x36,0x5a,0x41,
+  0x9a,0xaa,0xce,0x22,0x46,0xdb,0x16,0x39,0x57,0xb2,0xdc,0x5d,0xfa,0x4c,0x20,0x16,
+  0x62,0xc8,0x17,0x11,0x62,0x22,0xbb,0x66,0x84,0xf3,0xa5,0x22,0x30,0x63,0x70,0xf5,
+  0x4f,0x6b,0x7b,0x34,0x9f,0x47,0xe6,0x49,0x91,0x8,0xcb,0xfd,0x27,0x58,0xf3,0xb4,
+  0x93,0x18,0x47,0xbf,0xf0,0xa0,0x76,0xab,0x63,0x67,0x3e,0xee,0x89,0xd4,0xbf,0x45,
+  0xd1,0x98,0x0,0x5a,0x94,0x4,0x8f,0x47,0x4c,0xe9,0x1c,0x62,0xfb,0x46,0x22,0x77,
+  0x9d,0x10,0x20,0x83,0xe4,0xde,0x71,0xc5,0xb2,0x84,0xbc,0x88,0x9c,0x76,0x1b,0x89,
+  0x6c,0x64,0xa9,0x22,0x5,0xcb,0x11,0x10,0x31,0xa,0x1d,0x5c,0x95,0x15,0xbc,0xef,
+  0xda,0x8d,0xbb,0x2b,0x2b,0x37,0x82,0x5f,0x3c,0xca,0x17,0x57,0x8b,0x74,0xc,0x75,
+  0x7e,0xaa,0x3b,0xbf,0x59,0xa,0x19,0x73,0x11,0x68,0x19,0x8b,0x8e,0x29,0x95,0x10,
+  0xbf,0x2f,0x55,0x41,0xfb,0x66,0xf8,0xfa,0x3a,0x8d,0x1c,0x71,0xe4,0xf4,0x25,0x66,
+  0xee,0xc4,0x54,0x58,0x78,0xd,0x3b,0x20,0x59,0xb0,0xe,0x6d,0x2b,0x31,0xe,0x3c,
+  0xa5,0x59,0x45,0xe,0x70,0x4,0x9e,0xbd,0xb9,0x1d,0xea,0x21,0x86,0x94,0x53,0x86,
+  0xe7,0xf2,0xf9,0x42,0xb1,0x58,0xcc,0xe7,0xcb,0xff,0xcb,0xdf,0x4c,0xc1,0x21,0xe6,
+  0x65,0x64,0x39,0x32,0x12,0xd9,0x7d,0xd7,0x49,0xde,0x67,0x53,0xb0,0xcc,0xac,0x2d,
+  0xba,0xfa,0x27,0x6e,0xc6,0x80,0x89,0xb0,0x58,0xaa,0x80,0xe8,0x68,0x4e,0x7b,0x89,
+  0xf1,0xa2,0xee,0xca,0x32,0x31,0x44,0x68,0xbe,0x31,0x1,0x88,0x2c,0xe8,0xce,0xd1,
+  0x31,0x65,0x1b,0x86,0xe6,0x3,0xa9,0xbc,0x2f,0xcb,0x1,0xcd,0x7e,0x83,0xe6,0x8f,
+  0xa9,0xaa,0x58,0x74,0xba,0x44,0x7,0xa6,0xa3,0x9c,0xbb,0x81,0x5e,0x2c,0xd,0x9e,
+  0xd7,0xbe,0x7,0x5,0x66,0x9c,0x66,0x1a,0x12,0xa7,0x68,0xb4,0x97,0x18,0x87,0x64,
+  0xfe,0x62,0x38,0x0,0xcf,0x67,0x6f,0x8e,0xaa,0x5f,0x51,0x1f,0x95,0x34,0x3e,0x8c,
+  0x83,0x90,0x6,0x11,0x57,0xc9,0x70,0x74,0x4c,0x9,0x39,0xca,0x4d,0xeb,0xf4,0xbd,
+  0xcf,0x58,0xe5,0x90,0x4b,0x2c,0x86,0xf3,0x21,0xff,0x14,0xe,0x4c,0x64,0x1d,0x9b,
+  0x28,0x9,0x13,0x16,0xda,0x4c,0x8c,0x20,0x2b,0x83,0x79,0x4c,0x9e,0x4,0x5f,0x5b,
+  0xb4,0x1b,0xb7,0x45,0x3a,0x86,0xe,0xea,0xaa,0x76,0xc,0x3b,0x96,0xc0,0x1c,0xe8,
+  0xcb,0x6,0x2a,0x34,0xab,0x59,0x4d,0x10,0x2f,0x62,0x3e,0x19,0x8a,0xcc,0x2d,0x4f,
+  0xbe,0x6a,0x61,0x86,0xa6,0xc2,0x8a,0x2f,0xa2,0xd9,0xb9,0xf9,0x65,0xe1,0x5,0xdb,
+  0x51,0xd,0x13,0xd9,0xce,0xc6,0x24,0x71,0xde,0x60,0x9b,0x89,0x59,0x10,0x92,0xf1,
+  0xe2,0x15,0xe1,0x33,0x48,0x45,0x4b,0xea,0x2d,0x22,0x66,0xad,0x3a,0x31,0x54,0x9f,
+  0x64,0x2d,0x2f,0x4a,0x15,0x8f,0x3c,0x31,0xa5,0x7,0xf0,0xae,0x8d,0x44,0xf6,0xbf,
+  0xc0,0x55,0xb7,0xe9,0xea,0x31,0x0,0x46,0x6e,0x16,0xfc,0xe4,0xdb,0x24,0x6e,0xaa,
+  0x99,0xbd,0x1,0xc1,0xf1,0xe8,0x88,0x7,0xaf,0xe9,0x73,0x25,0xfa,0x2,0x12,0xf9,
+  0x7c,0x4b,0x45,0xf8,0xd4,0x64,0xe1,0x2e,0x96,0xfa,0x89,0x99,0xd9,0xb,0x88,0x72,
+  0x5d,0x20,0x20,0x3d,0xc7,0xab,0xe8,0x8,0xae,0x3a,0xa1,0xe3,0x92,0x15,0x23,0xee,
+  0xec,0x9a,0xdd,0x65,0x6,0xf3,0xe3,0x6b,0x2d,0xde,0xf3,0x24,0xd7,0x0,0x26,0xb9,
+  0x89,0x7e,0x8b,0x9a,0x7e,0xcd,0x5,0xf0,0x1,0xd7,0x15,0x11,0xb0,0xf5,0x1,0xe8,
+  0x48,0x6d,0x9b,0x75,0xc,0x35,0x5b,0xf,0x63,0x6e,0x3c,0xee,0xc2,0x88,0xee,0x6b,
+  0x11,0xa6,0x88,0xa8,0x9f,0x98,0x93,0x50,0xe0,0x1b,0x25,0x46,0x35,0xe0,0x99,0xef,
+  0x7d,0xa1,0x9a,0x7,0xcb,0x0,0x3d,0x27,0x1b,0xf2,0x18,0xea,0x66,0x63,0x5d,0xbc,
+  0x7b,0xef,0x81,0xb3,0x3c,0x3d,0x43,0x8a,0xd3,0x8b,0x5d,0xba,0xad,0xeb,0xb,0x16,
+  0xfe,0xfc,0xfb,0x30,0x47,0xaf,0x86,0xcc,0xb6,0xe5,0x4c,0xc5,0xf0,0x8e,0xe2,0xaa,
+  0xb4,0xcd,0x76,0x62,0x1c,0x5e,0xf8,0x5c,0x2,0x1a,0x2b,0xc,0x8f,0x49,0xe2,0xc3,
+  0x4f,0xea,0x27,0xe6,0xc,0x44,0xc,0x8d,0x14,0xa9,0x87,0x18,0xeb,0x87,0xa1,0x44,
+  0x4c,0x89,0x3c,0x24,0x31,0x84,0x94,0xf5,0xcc,0xb1,0x73,0xbc,0xaf,0x90,0x64,0x42,
+  0x55,0xe7,0xcc,0x82,0xd7,0x5e,0xf0,0x3e,0xb9,0xbb,0x8d,0xd3,0x78,0x70,0xaa,0x62,
+  0x80,0x50,0x26,0xfb,0x89,0x71,0x78,0xc0,0x6d,0x50,0x64,0xa,0x39,0x35,0x59,0x6c,
+  0x9,0xd5,0x4f,0xc,0x18,0x5c,0xbb,0x6d,0x50,0x99,0x18,0x96,0x6a,0xb3,0x51,0x62,
+  0x4a,0x5,0xf8,0x70,0x61,0x1d,0x1,0x7b,0x1e,0x7f,0xfa,0x4,0x97,0x99,0x74,0x90,
+  0x8d,0x4d,0xaf,0xf9,0xe9,0x5f,0x96,0xe4,0x25,0x12,0x1e,0xd6,0xe,0x6,0x82,0x7a,
+  0xa8,0xd,0xc4,0x38,0xfa,0x78,0x1,0xc7,0x55,0x4f,0x44,0x12,0x1,0xc6,0x2d,0x7e,
+  0x9b,0xfa,0x89,0x39,0xb,0xe9,0x98,0xed,0xcb,0x95,0xf,0x1c,0xe1,0x27,0x7b,0x56,
+  0xb2,0x63,0xa8,0x3c,0xbe,0xbf,0x4d,0x4e,0x2f,0xb0,0x69,0xd3,0x9e,0xfd,0xdf,0x3c,
+  0x7a,0xf6,0xdc,0xac,0xe1,0xa0,0x33,0x42,0xce,0x9f,0x4a,0xff,0xdc,0xcf,0xbe,0xed,
+  0x83,0x52,0xc3,0x11,0x7b,0x56,0xf8,0x4a,0x66,0xc4,0xc0,0x87,0x97,0xb6,0x83,0x18,
+  0x87,0x2b,0x24,0x38,0x39,0x84,0x14,0xe2,0xc8,0xf1,0x4a,0x8e,0x25,0x62,0x27,0x60,
+  0xfd,0xc4,0xcc,0x82,0xc9,0x9a,0x46,0x7,0x4d,0x94,0xce,0xce,0x22,0xb6,0x18,0x5d,
+  0x23,0xb0,0x4e,0x8b,0xa8,0xe5,0xcb,0xcd,0xe8,0xcb,0xf3,0xc7,0x68,0xf7,0x2f,0x7e,
+  0xe,0xde,0x83,0x66,0xe6,0xe9,0x96,0xfd,0x5f,0x3b,0xf0,0xf4,0xa1,0x63,0xc7,0x59,
+  0x39,0xf6,0xe2,0xb,0x87,0x9e,0x3e,0x70,0xdb,0xd,0xd2,0xb0,0x68,0x37,0x1b,0x5b,
+  0xca,0x80,0x89,0x82,0xce,0x84,0xb6,0x10,0xe3,0x70,0x78,0x12,0x3c,0x1b,0xb0,0x90,
+  0x4,0xb7,0xce,0x32,0xeb,0xd7,0x5,0x44,0xab,0xd7,0x4f,0xc,0x1,0xf7,0xae,0x8e,
+  0x8f,0x7e,0x52,0x47,0xc8,0xec,0x7f,0x7d,0xfb,0xa1,0xc7,0x10,0xdf,0x35,0x3d,0x4b,
+  0xc9,0xa,0x7,0x75,0xc8,0x28,0xcc,0xae,0xd9,0x13,0xf3,0x9f,0x18,0x97,0xd6,0x32,
+  0xb5,0x8a,0x7b,0xca,0x65,0xd7,0x2d,0xea,0x97,0x6e,0xd4,0x3c,0x31,0x1,0xd8,0xd0,
+  0x6c,0x13,0x31,0x8e,0x85,0xbe,0x98,0x79,0x21,0xbb,0x98,0xf6,0x63,0xa,0xc6,0xe1,
+  0x80,0x72,0x66,0xd7,0x4f,0xc,0x72,0xc4,0x66,0xf8,0xba,0x47,0xce,0x97,0x99,0x39,
+  0xf5,0xe5,0xcf,0x3c,0x78,0xeb,0xf6,0xc8,0xd7,0xb8,0xa6,0xa6,0x6e,0xa2,0x43,0xa7,
+  0xd7,0x96,0x8d,0x1f,0x5c,0xc5,0x23,0x9c,0x5d,0x6b,0x37,0xcb,0xbf,0x4b,0xc2,0xe3,
+  0xa6,0x4e,0x86,0xe0,0x8a,0x4d,0xda,0x34,0x29,0x8,0xd8,0xc,0xac,0x4d,0xed,0x22,
+  0x86,0x6e,0xa7,0x71,0xfb,0x13,0x2c,0xad,0x36,0x2b,0x74,0xa9,0x2e,0x1d,0xe8,0xc3,
+  0x79,0x81,0x8f,0x48,0x6f,0x80,0x18,0x6c,0xb1,0x78,0xe7,0xcd,0xd7,0x5d,0x7f,0xfd,
+  0xf5,0xb7,0xde,0xb1,0x67,0xa7,0xa6,0xe6,0xf7,0x9d,0x41,0x86,0x25,0x9a,0xc8,0xc1,
+  0x42,0xc,0xfb,0x1d,0xef,0x32,0xe1,0xa8,0x44,0x2b,0x1f,0x79,0x97,0xbc,0x2d,0xd3,
+  0x28,0x39,0x63,0xcb,0x34,0xd,0xc3,0xdb,0x7,0xa9,0x6f,0x76,0xfb,0x88,0x61,0x63,
+  0x8c,0xb3,0xcf,0x37,0x10,0xc,0x6,0xfb,0x7d,0x5e,0x9,0x5a,0x34,0xff,0x1f,0x34,
+  0x1c,0x34,0x40,0xc,0x72,0xe6,0x88,0xb9,0x33,0x3e,0x3c,0x83,0x39,0x95,0x14,0xfe,
+  0xe,0x11,0x43,0x52,0x23,0x75,0xc,0x4c,0x75,0xb1,0xb3,0xfe,0xf5,0xf4,0x84,0x5d,
+  0x61,0x1c,0xd5,0xdc,0xfb,0xb4,0x97,0x18,0xf8,0xe4,0x2d,0xeb,0x5f,0x7,0xc0,0x35,
+  0x86,0x6,0x88,0x41,0x12,0xfd,0x98,0xbb,0x60,0xe7,0xcb,0x82,0x73,0x4c,0x14,0x40,
+  0xa9,0x55,0x85,0x88,0x29,0x91,0x89,0x11,0x5b,0xb4,0x4c,0xf8,0xed,0xbf,0xe0,0xf5,
+  0xf5,0xf,0x88,0x2,0xef,0x74,0xef,0x35,0xaf,0x88,0xf1,0xc0,0x31,0x7c,0xd,0x10,
+  0xf3,0xaa,0xe2,0x67,0xf9,0x1b,0x21,0xce,0x69,0xab,0xf5,0xe0,0x2,0xdb,0x31,0xf4,
+  0xaf,0x24,0xb1,0x6a,0x4c,0xb1,0x71,0x75,0x54,0x1f,0x7f,0xcb,0x22,0x2f,0x2d,0x7e,
+  0x89,0x5c,0x23,0xf6,0x11,0xa3,0x73,0x59,0xab,0xaa,0x96,0x4a,0x7d,0xec,0x5c,0x83,
+  0x6,0x88,0x29,0xed,0x52,0x13,0xf3,0x3b,0xd1,0xe1,0x5e,0x1e,0x1f,0x50,0xc7,0xd0,
+  0x39,0x76,0x62,0xc5,0x95,0x6a,0x73,0x64,0xb5,0x57,0x61,0xb5,0xb7,0xbf,0x81,0xf1,
+  0xe2,0xf5,0x7a,0x3c,0xdc,0x6d,0x90,0x86,0x77,0xb1,0x8d,0x18,0x37,0x3a,0x71,0xc6,
+  0x38,0x82,0x8d,0x18,0xe6,0xbf,0x18,0x0,0x6e,0x81,0x84,0xff,0x61,0xa6,0xaf,0xa9,
+  0x17,0xae,0xe2,0x2e,0xee,0x96,0x33,0x84,0xc3,0x7b,0x4d,0xac,0x24,0x21,0xc4,0x94,
+  0x8a,0x13,0xc1,0x35,0xad,0x9d,0x32,0xbd,0xf7,0x17,0x2b,0xc0,0x38,0x1d,0xb,0xdc,
+  0xd1,0x69,0x38,0xbc,0xc0,0x36,0x62,0x3c,0xd3,0x60,0xa,0x21,0xc,0x17,0x6a,0x25,
+  0x83,0x56,0x2f,0xeb,0x88,0x46,0x88,0x39,0x24,0x11,0x8f,0xa2,0xa3,0x66,0x33,0x77,
+  0xc0,0xaf,0x4,0xf6,0x66,0xb3,0x59,0xfe,0xac,0x88,0xaf,0x77,0x30,0x62,0xe8,0xc0,
+  0x14,0x5a,0xb9,0x45,0x5d,0x71,0xc8,0x5e,0x31,0xfe,0xf6,0x9f,0xa9,0x1,0xa3,0x85,
+  0x38,0x46,0xd3,0x10,0x33,0xf6,0x11,0x53,0x28,0x80,0x47,0xf9,0x61,0xc8,0xb8,0xf0,
+  0x3d,0xb8,0x8d,0x10,0x73,0x12,0xc9,0xa6,0x62,0x12,0xff,0xb6,0x40,0x90,0xe3,0x4a,
+  0xd4,0x87,0x82,0x37,0x6d,0x54,0x62,0x9f,0x42,0x2a,0xb4,0x62,0xb8,0x55,0x73,0xa6,
+  0x6b,0xde,0xa0,0x99,0x30,0x5e,0x6f,0x5f,0x6d,0xc3,0x8f,0xbb,0x1f,0x70,0xe2,0xd9,
+  0x48,0x4c,0x69,0xba,0x1,0x64,0x5c,0x12,0xc7,0x1e,0x37,0x42,0xc,0x96,0x7f,0xce,
+  0x44,0xc,0x3d,0x16,0x84,0x13,0x33,0x33,0x47,0x4c,0x53,0x75,0xc,0x35,0x7f,0x33,
+  0xd1,0xc0,0xf2,0x2d,0xad,0xb0,0x66,0xc6,0x7f,0xb5,0xa2,0x60,0xbc,0x86,0x4d,0x8,
+  0x4e,0xef,0xfd,0xdc,0x58,0x1e,0x3b,0x3d,0x78,0x74,0x9e,0x43,0x72,0x3,0xe0,0x19,
+  0xb3,0x80,0x9a,0x71,0x21,0x8e,0x48,0xed,0x8b,0x6e,0x84,0x18,0x7c,0x23,0xa2,0x91,
+  0x99,0x21,0xde,0xea,0x24,0x4b,0xca,0x5a,0xd9,0x34,0x2b,0x19,0x2,0xcf,0x9a,0x8d,
+  0x8e,0x4a,0xac,0x52,0x2e,0x1e,0x1c,0x1c,0x6e,0xfe,0x3c,0x7b,0xfd,0xeb,0xca,0xfa,
+  0xc5,0xeb,0xb1,0x38,0xc4,0xdc,0xa1,0x24,0xd7,0xe1,0x68,0xa7,0x8e,0xa1,0xdf,0x4a,
+  0x48,0xce,0x53,0x67,0x66,0xa7,0xf,0xcf,0xb2,0xd3,0x28,0x31,0xe4,0x1b,0xb2,0xe3,
+  0xbe,0x56,0x6f,0x55,0x40,0xaa,0x49,0x32,0x63,0x93,0x14,0x31,0xa5,0x7c,0x32,0x10,
+  0x58,0x3e,0xda,0x5c,0xb,0xf8,0x9a,0x37,0x54,0x15,0x8c,0x15,0x18,0xe6,0x2f,0xf5,
+  0x85,0x38,0x99,0x10,0xed,0x25,0xa6,0x54,0x8c,0x23,0x3b,0xb0,0xb8,0x7a,0xc6,0x87,
+  0x5,0x61,0x95,0x3b,0xa6,0x21,0x1d,0x53,0x3a,0x8b,0xed,0x76,0x36,0x10,0x75,0xb9,
+  0x60,0x1f,0xbb,0xc,0x22,0xa6,0x3a,0x72,0xc4,0x94,0xc8,0x74,0x2c,0x18,0x58,0x31,
+  0xbc,0xa3,0x59,0x63,0x53,0xb8,0x66,0xc0,0x78,0xbd,0x6e,0xe1,0x5e,0x6d,0x6f,0xcc,
+  0x1c,0xe8,0x63,0x33,0x31,0x74,0x64,0xf2,0xa9,0x8e,0x4c,0x2e,0xa9,0x68,0xf2,0x86,
+  0x89,0x29,0x1d,0x83,0xcf,0x8e,0x31,0xaa,0xa0,0xe1,0x0,0xc7,0x12,0x27,0xb4,0x48,
+  0x20,0x63,0xaa,0x26,0x49,0xc,0x5d,0x97,0x4c,0x85,0x98,0x9e,0x69,0x8a,0x3d,0x13,
+  0x5e,0x5f,0xd3,0x2f,0x9c,0x11,0x49,0xf7,0xdd,0x3a,0xcd,0x6e,0x9,0xbb,0x89,0xa1,
+  0x9a,0x20,0x8e,0xc4,0x4c,0x99,0xd4,0xcc,0x5c,0x46,0x2,0xac,0x33,0x1a,0xd3,0x31,
+  0x25,0xf2,0x55,0x7c,0xb7,0x60,0xd,0x9b,0xd,0x81,0xa0,0x15,0xe,0x51,0x56,0x70,
+  0x53,0xc3,0x4d,0xd5,0xa4,0x89,0x29,0x91,0x23,0x31,0xba,0xf2,0xb3,0xe2,0xf2,0xb1,
+  0x46,0xf5,0xcc,0xf8,0xdb,0x5f,0x57,0x1d,0x8f,0x0,0x5,0xa3,0x75,0x84,0xbf,0xdd,
+  0x3a,0x86,0xf9,0xbd,0x8f,0xc,0xc8,0x5b,0x33,0x6e,0x85,0xac,0xea,0xd,0x12,0x53,
+  0x2a,0x7e,0x42,0xde,0xb4,0xdc,0xc2,0x3b,0x42,0xb1,0xd5,0xc4,0xd0,0xcf,0x6d,0x2a,
+  0x4a,0xf5,0xcc,0xe0,0xd0,0xda,0x2d,0xe3,0xf5,0x52,0x13,0xde,0xb1,0xf9,0xe2,0x37,
+  0x2f,0xf6,0x55,0x2c,0x5e,0xdd,0x9c,0x9a,0x6b,0x10,0x58,0x43,0x1e,0xed,0xd7,0x31,
+  0x8c,0x99,0x69,0x2d,0xfe,0x14,0x2d,0x4e,0x77,0x88,0xbf,0xf1,0x94,0xaf,0x6d,0x1a,
+  0x25,0xa6,0x94,0xfd,0xf5,0xab,0x64,0xbd,0x1e,0x34,0x3f,0xb2,0x35,0xaf,0x64,0xeb,
+  0x89,0xa1,0xcc,0x4c,0xc6,0xd9,0x12,0xf3,0xe0,0xca,0xd1,0x4d,0x5b,0xd5,0xa1,0x9,
+  0x6f,0x1c,0x1b,0x5e,0xce,0x22,0x33,0x7,0xfc,0x1a,0x33,0x6e,0xe1,0x66,0xb8,0x4a,
+  0xe7,0x58,0x93,0x22,0xb4,0x85,0x18,0xda,0xe1,0xe9,0x10,0xbc,0x63,0x80,0x35,0xd8,
+  0xb,0x87,0xf,0x5a,0xb0,0x69,0x98,0x98,0x52,0x2a,0xb8,0xf2,0x6a,0x29,0x66,0xc2,
+  0x1b,0x86,0x2,0xd6,0x79,0x84,0x1d,0xc4,0x94,0x48,0x7e,0x32,0xaa,0x5,0xb2,0xc,
+  0x2e,0x1f,0x19,0xdd,0xa8,0x34,0xc1,0x7b,0xef,0xda,0x8b,0x96,0x69,0x81,0xbc,0xac,
+  0x2c,0xf1,0x7b,0xdd,0xe8,0x77,0xeb,0xb6,0x4e,0xb0,0xdb,0x45,0xc,0xd5,0x33,0x71,
+  0x3f,0x64,0x3,0xbb,0x68,0xbc,0x95,0x8c,0x19,0xa9,0xe3,0xa6,0x71,0x62,0xe8,0x12,
+  0xce,0xe0,0xc8,0x28,0xca,0xcc,0x96,0xd1,0x11,0x9a,0x58,0xd0,0x1a,0xa2,0x4e,0x89,
+  0xc9,0x96,0x7d,0x32,0x60,0xa9,0xdb,0x8e,0xa9,0xbc,0x2b,0xdd,0x8b,0x14,0x8f,0x6,
+  0xcb,0xd4,0xc,0xad,0x5c,0x33,0xb6,0x6d,0xc7,0x78,0x18,0x52,0x37,0xe1,0xf0,0xf8,
+  0xf6,0x6d,0x63,0x17,0xbf,0x69,0xa8,0x46,0xb,0xbd,0x32,0x14,0x9d,0x48,0x5b,0x77,
+  0xc1,0x99,0xd4,0xbe,0x93,0xe3,0x42,0x28,0x4c,0x8a,0x8b,0x96,0xd0,0x48,0xad,0x14,
+  0xd3,0xa2,0xdb,0x4d,0x71,0xb6,0x8,0x67,0xe3,0xfe,0x3e,0x97,0x15,0x1b,0xa7,0xcb,
+  0xd3,0x9f,0x0,0x53,0xc7,0xf1,0x1b,0x45,0x32,0xc0,0xcb,0xc8,0x1d,0x6b,0x4a,0x92,
+  0xd4,0x4c,0x18,0xba,0x64,0x8c,0xf6,0x1,0xef,0xeb,0xd,0x8f,0xef,0xd8,0x76,0xe5,
+  0x9a,0x55,0x65,0xc9,0x5b,0xd7,0x36,0x39,0x39,0x63,0x4,0xbf,0xd2,0x9b,0x93,0xf2,
+  0x96,0xef,0xdc,0x6b,0x93,0xdc,0x64,0x8c,0xb6,0xb4,0x5c,0x6,0x87,0x56,0xaf,0x19,
+  0xbe,0x6a,0xc3,0xa6,0xcd,0x5b,0xb6,0xd3,0x52,0xe5,0x3d,0x4c,0x7f,0xde,0xba,0x71,
+  0xe3,0xd8,0x86,0xab,0x86,0xd7,0xac,0x5e,0xaa,0x45,0x4b,0xcd,0x95,0x68,0x22,0x4d,
+  0x5,0x42,0x52,0xc8,0xc4,0xb5,0x5f,0x4e,0x6a,0x6a,0x8c,0x34,0x58,0x3b,0x97,0x8c,
+  0x6,0x99,0x7a,0x74,0x51,0x5,0x49,0xff,0xe3,0xa6,0x61,0x3d,0xa1,0x38,0xb8,0x12,
+  0xd6,0xe0,0x3,0x91,0xcb,0x49,0x59,0xe5,0xf,0xad,0x1e,0xde,0x40,0x3b,0xa0,0x2a,
+  0xfd,0x71,0x2a,0xfc,0x2d,0x9b,0xae,0xbe,0x6a,0x78,0xb5,0x66,0x4,0x94,0x8b,0x35,
+  0x4f,0x85,0x7d,0xc4,0xd0,0xb7,0xc8,0x4f,0x53,0xd1,0xe9,0x20,0x18,0x1c,0x1c,0x5a,
+  0xb1,0x6a,0x25,0x2d,0x23,0xe5,0xb2,0x9a,0xfe,0xb8,0x7c,0xd9,0xb2,0x41,0xbd,0x62,
+  0x29,0x57,0xf,0xc5,0x26,0xab,0x4b,0x0,0xb9,0x38,0x74,0x1c,0x27,0x16,0x5e,0xd2,
+  0xda,0xae,0x0,0xee,0x9e,0xcf,0x4c,0x51,0xe5,0x90,0x4c,0xd2,0xff,0xa4,0xf9,0x1b,
+  0x34,0x6c,0x6c,0x1a,0xc9,0x25,0xab,0xa,0x7f,0x45,0x4d,0xfa,0x54,0xf8,0xab,0x56,
+  0x18,0x94,0x3a,0x15,0xbc,0x35,0x25,0x8f,0xad,0xc4,0x50,0x15,0x41,0xf2,0xe9,0x78,
+  0x34,0xa4,0xc7,0xc6,0xa8,0x49,0xac,0xff,0x17,0x8c,0xc6,0x26,0x68,0xe,0xf1,0x39,
+  0x7d,0x4f,0x8a,0x51,0xb1,0x4f,0xb5,0x89,0xe7,0xc5,0xd9,0xd8,0x83,0xf6,0x3f,0x8a,
+  0x6e,0x73,0x37,0x7c,0xbc,0xdc,0x5e,0x8,0xc5,0x26,0xac,0x73,0x25,0xcc,0x80,0x99,
+  0xfb,0xbb,0x5e,0xdb,0xd7,0x33,0x2a,0xd5,0xa4,0x42,0xa,0xd3,0xa9,0x4,0xc5,0x6,
+  0x43,0x85,0xa9,0x96,0x68,0x3c,0x59,0x53,0x2e,0xba,0x1,0xee,0x70,0x40,0x60,0x0,
+  0x7b,0x64,0xf2,0x70,0xd8,0xdf,0x3f,0x1d,0xf9,0xc4,0xfc,0x64,0xa2,0x3c,0x1f,0x11,
+  0xd0,0x12,0x4f,0x66,0x9a,0x27,0xcd,0x86,0x88,0x61,0xe2,0x23,0x34,0x69,0x5a,0x3a,
+  0x19,0x8f,0x9,0x9b,0x4c,0x35,0x4b,0x22,0x75,0x38,0x23,0xca,0x10,0x5b,0x4c,0xfa,
+  0x78,0x1,0x92,0xb,0x9b,0xb6,0x72,0xd6,0x91,0x7d,0xdc,0xec,0x46,0x15,0x73,0x53,
+  0x13,0x74,0x1d,0xc7,0x52,0xa8,0x56,0x4f,0xb,0x45,0x5f,0x5f,0x23,0x1a,0x26,0x46,
+  0x7b,0x2c,0x5b,0x7a,0x20,0xc5,0xec,0x34,0x1b,0xdf,0x27,0xaa,0x85,0xe,0xf4,0xe9,
+  0xe9,0x2c,0x1d,0x85,0x90,0xe5,0xb,0x92,0xf2,0x5a,0x27,0x20,0x81,0xe6,0x7d,0x14,
+  0xf5,0x9,0x66,0xde,0x5d,0xc5,0x92,0xd7,0x4d,0xcf,0x89,0x3f,0x45,0x8d,0x2c,0x9a,
+  0xd8,0x4e,0x6a,0xe5,0x48,0xe9,0x5d,0x9b,0x43,0x8c,0xd2,0x23,0xad,0x95,0xf3,0x71,
+  0xf3,0xb4,0xc9,0xa3,0x7e,0x82,0x5f,0x83,0x6d,0xe8,0x5d,0x2e,0x29,0x81,0x8e,0x20,
+  0x86,0x2e,0x11,0x4f,0x18,0x99,0xe9,0x99,0xbd,0x92,0xfd,0x67,0x7f,0xb5,0xce,0x20,
+  0x86,0xd,0x6c,0xb9,0x81,0xb9,0xc8,0x4d,0xd9,0xb4,0xa8,0xf6,0xcb,0xab,0xf7,0xc4,
+  0x8e,0x21,0x86,0x32,0x43,0x7d,0xaa,0xe5,0xc9,0xb6,0x4b,0xfd,0xac,0xf3,0x5e,0x4f,
+  0xda,0x25,0x81,0xe,0x22,0x86,0xbe,0x72,0x7e,0x2a,0xc1,0x12,0x26,0xc0,0xbb,0x4f,
+  0xed,0x12,0x4d,0xef,0x39,0x5c,0x9,0x74,0x16,0x31,0x6c,0x74,0x2a,0x4e,0x72,0x4f,
+  0x88,0xec,0xf5,0x5f,0x87,0x48,0xa0,0xe3,0x88,0xe9,0x10,0xb9,0xf4,0x9a,0x21,0x92,
+  0x40,0x8f,0x98,0x1e,0x1b,0x6a,0x12,0xe8,0x11,0xa3,0x26,0xaf,0x5e,0xed,0x1e,0x31,
+  0x3d,0x6,0xd4,0x24,0xd0,0x23,0x46,0x4d,0x5e,0xbd,0xda,0xff,0xf,0x65,0xda,0xe8,
+  0xf,0x87,0x6,0xa8,0xe8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,
+  0x82,
+    // Q:/sf/mw/gstreamer/internal/QtGSTPlayer/settings.png
+  0x0,0x0,0x1f,0xe6,
+  0x89,
+  0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,
+  0x0,0x2,0x31,0x0,0x0,0x0,0x9a,0x8,0x3,0x0,0x0,0x0,0x6f,0xf5,0xe9,0xc2,
+  0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,
+  0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0xa,0xc,0x4,0xb,0xb,
+  0xb,0x12,0x16,0x8,0x17,0x17,0x17,0x22,0x29,0xe,0x2d,0x33,0x1d,0x31,0x3c,0x15,
+  0x26,0x26,0x26,0x2c,0x2c,0x2c,0x32,0x32,0x32,0x3d,0x3d,0x3d,0x3c,0x48,0x1a,0x44,
+  0x53,0x1e,0x45,0x48,0x3e,0x4e,0x5e,0x22,0x4c,0x50,0x3f,0x59,0x6c,0x27,0x5f,0x6b,
+  0x3f,0x5e,0x71,0x29,0x62,0x76,0x2a,0x48,0x48,0x48,0x4e,0x53,0x40,0x59,0x59,0x59,
+  0x59,0x62,0x41,0x61,0x6d,0x42,0x66,0x6a,0x5c,0x6b,0x79,0x43,0x6b,0x71,0x5b,0x74,
+  0x7d,0x5b,0x63,0x63,0x63,0x67,0x68,0x64,0x68,0x69,0x64,0x6e,0x6e,0x6e,0x6e,0x71,
+  0x66,0x71,0x75,0x65,0x72,0x74,0x6d,0x75,0x7a,0x64,0x75,0x7a,0x6a,0x78,0x7f,0x65,
+  0x78,0x7d,0x6a,0x71,0x71,0x71,0x76,0x78,0x73,0x79,0x7c,0x72,0x7a,0x7a,0x7a,0x74,
+  0x8c,0x33,0x76,0x86,0x49,0x76,0x80,0x58,0x79,0x87,0x54,0x79,0x83,0x5d,0x7b,0x8a,
+  0x54,0x7d,0x8a,0x5c,0x7f,0x94,0x46,0x7f,0x91,0x50,0x7b,0x84,0x64,0x7b,0x82,0x69,
+  0x7e,0x89,0x61,0x7e,0x83,0x73,0x89,0xa6,0x3c,0x80,0x8d,0x5c,0x84,0x9a,0x48,0x83,
+  0x95,0x54,0x83,0x92,0x5b,0x86,0x99,0x53,0x8a,0x9e,0x54,0x8a,0x9c,0x5b,0x82,0x8c,
+  0x65,0x84,0x89,0x76,0x85,0x92,0x62,0x89,0x97,0x62,0x8b,0x9b,0x61,0x8d,0x96,0x73,
+  0x91,0x9c,0x73,0x8c,0xa4,0x4c,0x8e,0xa2,0x55,0x8d,0xa0,0x59,0x93,0xad,0x4b,0x90,
+  0xa5,0x57,0x92,0xa6,0x5b,0x93,0xab,0x52,0x95,0xab,0x58,0x98,0xae,0x5a,0x93,0xb1,
+  0x41,0x95,0xb1,0x4c,0x99,0xb5,0x4d,0x9b,0xbb,0x44,0x9b,0xb8,0x4a,0x97,0xb0,0x52,
+  0x99,0xb3,0x52,0x9d,0xb9,0x50,0x8f,0xa0,0x61,0x98,0xaa,0x67,0x9b,0xa5,0x7f,0x9c,
+  0xb2,0x63,0xa0,0xbe,0x4d,0xa0,0xbd,0x52,0xa5,0xbc,0x67,0xa7,0xba,0x72,0xa0,0xc1,
+  0x46,0xa3,0xc3,0x4c,0xa7,0xc8,0x4d,0xaa,0xcc,0x4c,0xa5,0xc4,0x51,0xa5,0xc0,0x59,
+  0xa8,0xc7,0x52,0xa8,0xc4,0x59,0xab,0xcd,0x51,0xac,0xca,0x5b,0xae,0xd2,0x4c,0xae,
+  0xd1,0x52,0xae,0xd1,0x59,0xb0,0xce,0x5e,0xb0,0xd3,0x4f,0xb1,0xd3,0x55,0xb4,0xd5,
+  0x5b,0xaa,0xc3,0x64,0xaf,0xc5,0x71,0xae,0xc2,0x79,0xad,0xd1,0x66,0xad,0xd1,0x6f,
+  0xb2,0xce,0x63,0xb2,0xcb,0x6a,0xb0,0xc7,0x70,0xb5,0xcd,0x75,0xb6,0xcb,0x7b,0xb8,
+  0xcf,0x7c,0xb4,0xd3,0x62,0xb4,0xd3,0x6a,0xb8,0xd6,0x66,0xb8,0xd5,0x6a,0xb9,0xd8,
+  0x63,0xbc,0xda,0x6b,0xb4,0xd2,0x74,0xb3,0xd4,0x7a,0xb9,0xd3,0x73,0xbc,0xd5,0x7b,
+  0xbd,0xd9,0x73,0xc0,0xdc,0x74,0xc2,0xdc,0x7a,0x87,0x87,0x87,0x93,0x93,0x93,0x99,
+  0x9c,0x93,0x9b,0x9b,0x9b,0x9f,0xa7,0x8a,0x9c,0xa0,0x92,0xa1,0xaa,0x88,0xa1,0xa6,
+  0x93,0xae,0xbd,0x83,0xb1,0xbe,0x8c,0xb5,0xbe,0x9d,0xa6,0xa6,0xa6,0xac,0xac,0xac,
+  0xad,0xb1,0xa5,0xb1,0xb2,0xaf,0xbb,0xbb,0xbb,0xb3,0xc4,0x84,0xb3,0xc2,0x8c,0xb6,
+  0xc8,0x86,0xb9,0xcd,0x83,0xb9,0xc7,0x94,0xba,0xc5,0x9e,0xbb,0xcb,0x92,0xbc,0xc9,
+  0x9a,0xb5,0xd4,0x80,0xbb,0xd4,0x82,0xbe,0xda,0x8d,0xba,0xd0,0x98,0xbb,0xc4,0xa3,
+  0xc0,0xd7,0x82,0xc2,0xd5,0x8e,0xc3,0xdb,0x84,0xc5,0xdc,0x89,0xc2,0xd3,0x94,0xc3,
+  0xd3,0x99,0xc4,0xdb,0x9c,0xcb,0xde,0x95,0xc9,0xdb,0x9a,0xc3,0xcd,0xa8,0xc6,0xca,
+  0xb9,0xc7,0xd1,0xac,0xca,0xd7,0xa5,0xc9,0xd4,0xac,0xcb,0xda,0xa2,0xce,0xdb,0xaa,
+  0xc9,0xd2,0xb4,0xd1,0xde,0xad,0xd3,0xde,0xb4,0xc7,0xe0,0x83,0xc8,0xe0,0x85,0xcb,
+  0xe1,0x8c,0xcd,0xe2,0x92,0xcf,0xe1,0x9b,0xd0,0xe5,0x96,0xd2,0xe6,0x9d,0xcc,0xe0,
+  0xaf,0xcc,0xe2,0xbb,0xd2,0xe4,0xa4,0xd4,0xe4,0xab,0xd6,0xe8,0xa5,0xd7,0xe8,0xac,
+  0xd9,0xe9,0xac,0xd2,0xe3,0xb3,0xd5,0xe4,0xbd,0xd7,0xe8,0xb5,0xd8,0xe5,0xb5,0xda,
+  0xe6,0xbd,0xdc,0xeb,0xb2,0xdd,0xea,0xbb,0xe0,0xee,0xbb,0xc2,0xc2,0xc2,0xca,0xcb,
+  0xc7,0xcd,0xcd,0xcd,0xcf,0xd0,0xcf,0xd1,0xd6,0xc4,0xd0,0xd1,0xcf,0xd6,0xdc,0xc4,
+  0xd8,0xdf,0xc3,0xd5,0xd5,0xd5,0xdc,0xdc,0xdc,0xd4,0xe0,0xcd,0xda,0xe2,0xc3,0xdc,
+  0xe2,0xcc,0xdc,0xea,0xc1,0xde,0xe2,0xd1,0xde,0xe6,0xdb,0xda,0xe8,0xd4,0xdf,0xeb,
+  0xde,0xe0,0xe6,0xce,0xe2,0xed,0xc2,0xe3,0xed,0xc9,0xe0,0xe1,0xdd,0xe5,0xeb,0xdc,
+  0xe8,0xed,0xdc,0xe4,0xf0,0xc6,0xe6,0xf1,0xca,0xe8,0xf2,0xcc,0xe7,0xf2,0xd3,0xe6,
+  0xf1,0xdf,0xeb,0xf3,0xd3,0xed,0xf3,0xda,0xf0,0xf6,0xdd,0xe3,0xe3,0xe3,0xe9,0xec,
+  0xe2,0xec,0xec,0xec,0xeb,0xf2,0xe3,0xee,0xf1,0xec,0xf1,0xf6,0xe3,0xf1,0xf4,0xeb,
+  0xf4,0xf9,0xe6,0xf5,0xf9,0xeb,0xf8,0xfa,0xef,0xf4,0xf4,0xf4,0xf5,0xf8,0xf2,0xf9,
+  0xfb,0xf4,0xfb,0xfb,0xfa,0xff,0xff,0xff,0x92,0x33,0xcc,0x38,0x0,0x0,0x1c,0x91,
+  0x49,0x44,0x41,0x54,0x78,0x5e,0xed,0x9d,0x7d,0x80,0x1b,0xc5,0x75,0xc0,0x77,0xce,
+  0xb2,0xc1,0xb2,0x2c,0x9f,0x8b,0x6d,0x10,0xa4,0x1f,0x29,0x95,0xc0,0xf1,0xe9,0x1c,
+  0x48,0x29,0x89,0xdd,0x9a,0x18,0x8,0xa1,0x94,0x42,0x5a,0x42,0x93,0x86,0x36,0x69,
+  0xda,0x4a,0x39,0xf5,0x23,0xad,0x90,0xb0,0x9,0xd4,0x1,0x17,0xda,0x7c,0x14,0x63,
+  0x6c,0x41,0xc0,0xba,0xb,0xd8,0x29,0xb1,0x4d,0x1c,0xf0,0x19,0x9f,0x29,0x1,0xee,
+  0xb0,0x81,0xd4,0x76,0x5b,0x1c,0x52,0x55,0xb2,0xcf,0xe7,0x9c,0x7d,0x4,0x52,0x55,
+  0xf4,0xcb,0xad,0x74,0x4a,0x23,0xcb,0xd7,0x99,0xd5,0xb7,0x76,0xe6,0xbd,0x19,0xad,
+  0x4e,0xd2,0x9,0xcd,0x1f,0x58,0x9c,0x46,0xb3,0xbb,0x6f,0x7e,0xfb,0xe6,0xcd,0x9b,
+  0x37,0x6f,0x34,0xad,0x53,0x3a,0x12,0xe8,0x48,0xa0,0x23,0x81,0x8e,0x4,0x3a,0x12,
+  0xe8,0x48,0xa0,0x23,0x81,0x8e,0x4,0x3a,0x12,0xe8,0x48,0xa0,0x23,0x81,0x8e,0x4,
+  0x3a,0x12,0xe8,0x48,0xa0,0x23,0x81,0x8e,0x4,0x3a,0x12,0xe8,0x48,0xe0,0x5d,0x20,
+  0x81,0xae,0x73,0xe7,0x75,0x9f,0xc7,0xca,0xa2,0x45,0x8b,0xf4,0x7f,0xe7,0xcd,0xb3,
+  0x92,0x77,0xc1,0x73,0x77,0x1e,0x51,0x59,0x2,0xe4,0xfc,0x2b,0x56,0xac,0x5c,0xb5,
+  0x6a,0xf5,0x9d,0x77,0x7f,0x65,0x13,0x2b,0xa1,0x50,0x48,0xff,0xf7,0xde,0xbb,0x6f,
+  0xfb,0xf0,0xaa,0x55,0x2b,0x57,0x5c,0xf1,0xb3,0xca,0x4d,0x76,0x7e,0xd0,0x9e,0x12,
+  0x20,0x84,0xcc,0xbe,0xf8,0x53,0x6b,0xd6,0xae,0xdf,0xb4,0x99,0x52,0x22,0x2a,0x9b,
+  0x37,0xad,0x5f,0xbb,0xf6,0x53,0xbf,0x30,0x8b,0xd6,0x6e,0x3d,0x31,0x10,0xb,0x50,
+  0xa6,0xfd,0x76,0xa1,0xab,0xb7,0xa0,0xb0,0x4c,0xca,0xa3,0xab,0x7b,0xc9,0xca,0xbb,
+  0x21,0x52,0xc,0x4,0xdd,0xf5,0x91,0x45,0xf3,0x5a,0x4d,0xe,0xcb,0xd2,0x53,0xc2,
+  0x92,0x32,0x29,0x21,0xf4,0xe7,0x96,0x71,0xf1,0xc5,0xa7,0x7c,0xe8,0xcf,0x67,0x54,
+  0x5,0x72,0xc1,0xca,0xd5,0x5f,0x4,0xf4,0x8a,0xe8,0xab,0xbb,0x3f,0xb6,0xf2,0xa7,
+  0x5b,0xea,0x41,0xdb,0x91,0x98,0x56,0x7b,0x2b,0x35,0x8d,0xcc,0x59,0xb9,0x66,0xbd,
+  0x92,0x76,0x29,0x3,0x68,0xf3,0xfa,0xb5,0x97,0x76,0xb5,0xce,0x33,0xb5,0x1d,0x31,
+  0x64,0xc1,0xea,0x4b,0x5a,0xea,0x9d,0xd4,0xb4,0x73,0x2f,0xfa,0x78,0xad,0xb4,0x14,
+  0xc0,0xd9,0xf4,0x1b,0x17,0x5a,0x5b,0xe4,0xa9,0xda,0x8c,0x98,0xae,0x85,0x57,0x3f,
+  0x18,0xfa,0x4c,0x8b,0xc8,0x36,0x77,0x1b,0x73,0x57,0xde,0xf9,0x48,0xd,0xa3,0x51,
+  0xf5,0x4f,0x36,0xde,0xf6,0x4b,0xb3,0x5a,0xe2,0xb9,0xda,0x8a,0x18,0xb2,0x78,0xf5,
+  0x6,0x2a,0xe9,0x16,0x22,0x86,0xcc,0xbe,0x7e,0x9d,0x59,0xfd,0x52,0x60,0x67,0xf3,
+  0x17,0x7f,0xb9,0x15,0x6,0xa7,0x36,0x22,0x86,0x2c,0xbc,0x7a,0xc3,0x46,0x26,0x5e,
+  0x79,0x62,0xec,0xd2,0xc5,0x56,0xcb,0xfb,0x4d,0xe6,0xad,0x78,0xa8,0xe,0xea,0xa5,
+  0xd4,0xc4,0x57,0x7e,0x71,0x5e,0x2d,0xf7,0x51,0xd7,0xdf,0xb4,0xd,0x31,0xb3,0x17,
+  0x5d,0xab,0xe3,0xc2,0x88,0xb1,0x2e,0xb5,0xcb,0x9,0xc9,0x29,0x5d,0x24,0x1b,0xac,
+  0xb8,0x6c,0xd7,0x7,0xbe,0x50,0x57,0x5e,0x58,0x63,0x77,0x5d,0xde,0x25,0xf7,0x68,
+  0xd3,0x56,0xab,0x4d,0x88,0x21,0x17,0x5d,0xcd,0xc6,0xa3,0x5c,0xf9,0x5b,0x7f,0xc4,
+  0x25,0x27,0x30,0x69,0x60,0x9c,0xea,0xc4,0x90,0xd9,0x7f,0xf9,0x60,0xdd,0x81,0xa1,
+  0xbe,0xe1,0x3b,0x67,0x35,0x77,0xde,0xd4,0x16,0xc4,0x74,0x2d,0xba,0x36,0x37,0x1e,
+  0xe5,0xca,0xe1,0x58,0xac,0xf9,0xc4,0xcc,0xb9,0xee,0xe1,0x69,0xe0,0x85,0x35,0xf9,
+  0xd0,0xaf,0xcc,0x91,0x7b,0x1f,0xa6,0xa7,0xd6,0xcc,0x27,0x86,0xcc,0x59,0x7c,0x47,
+  0x19,0x2e,0x54,0xa4,0x47,0x54,0x88,0x71,0x48,0x98,0x32,0x54,0x15,0xa9,0xea,0x98,
+  0xb,0x3e,0x51,0x8f,0x9,0x12,0x9f,0xb9,0x8d,0xb7,0x36,0xd3,0xa7,0x37,0xe3,0x89,
+  0x21,0xcb,0xaf,0x2d,0x8d,0x47,0x39,0x9,0x2b,0x11,0x23,0x83,0x82,0x32,0x31,0xe4,
+  0x92,0xbf,0x9e,0x26,0x5,0x93,0x6b,0xf6,0xde,0xf7,0x36,0x6f,0x64,0x9a,0xd9,0xc4,
+  0x90,0xae,0x25,0x77,0x18,0x8d,0x85,0xa6,0x13,0xd3,0x75,0xfd,0xa3,0xd3,0xa,0x4c,
+  0x28,0xb4,0x79,0xa5,0x65,0x7a,0xc6,0x1c,0xbc,0xd5,0x99,0x4c,0xc,0x99,0xb3,0x7c,
+  0x4d,0xe5,0x78,0xd4,0x1a,0x3a,0xe6,0xdc,0x9b,0xfb,0xa7,0x19,0x18,0xda,0xfc,0xcd,
+  0xcd,0xf2,0x1,0xcf,0x60,0x62,0xba,0x2e,0xe3,0xe8,0x97,0x16,0x18,0x95,0xe6,0xdf,
+  0x57,0x2f,0x9f,0x1d,0xc4,0xdd,0xe6,0xdf,0xf9,0x29,0x5c,0x1f,0x4c,0x47,0x8d,0x99,
+  0x4a,0xc,0x99,0xbd,0x7c,0x8d,0x68,0xf2,0x2a,0x3f,0x2a,0xd1,0x0,0x14,0xd8,0x20,
+  0xc8,0x7d,0x8b,0x56,0x2b,0xef,0x99,0xf9,0x7f,0x33,0xfd,0xa,0x46,0xbf,0xc2,0x97,
+  0x9b,0xe3,0xcd,0x9b,0xa1,0xc4,0x74,0x2d,0xff,0xb,0x71,0xbf,0xc8,0x13,0x53,0xec,
+  0x69,0x16,0x24,0x64,0x78,0x21,0x89,0xd5,0x66,0x53,0xb6,0x30,0xcf,0xbf,0xaf,0x41,
+  0xc0,0x84,0x42,0xcd,0xd1,0x32,0x33,0x94,0x98,0x85,0xeb,0x80,0x7e,0xa9,0x81,0x18,
+  0xee,0x6c,0xc8,0xe2,0x74,0x3a,0x54,0xd,0xcc,0xf3,0xef,0xe7,0x59,0x56,0xd3,0x3,
+  0xd1,0xc6,0xbb,0x9a,0x31,0x30,0x75,0x88,0xd1,0x55,0x8b,0x88,0x18,0xa7,0xe2,0x7a,
+  0xd2,0xfc,0xbf,0x9a,0x1e,0x38,0x4,0xad,0x36,0x63,0x60,0xea,0x10,0x23,0x24,0x86,
+  0x58,0x29,0x47,0x6a,0xc4,0x58,0x3f,0xab,0x6,0x4c,0x78,0xdb,0xae,0xc1,0x7d,0x43,
+  0x23,0x2f,0xb0,0x32,0xb2,0x6f,0xdf,0xe0,0xae,0x81,0xb0,0x5a,0x3,0xb7,0x35,0x7e,
+  0xc6,0xf4,0xee,0x26,0x86,0xd8,0xf2,0x85,0xb2,0xe1,0x28,0x7c,0x2e,0xfe,0x6b,0x57,
+  0x1d,0x95,0x66,0xdd,0x22,0xef,0xe8,0xd,0x6f,0xd9,0xb9,0xff,0xe0,0xd1,0xd1,0x31,
+  0x5a,0x62,0xb9,0xc2,0x3e,0x8e,0x1e,0x3a,0xf8,0xf2,0x8e,0x2d,0xf2,0xd8,0x6c,0xbc,
+  0xb9,0xe1,0xb,0x93,0xef,0x76,0x62,0x90,0xb5,0x48,0xbb,0x92,0xe5,0xfb,0xab,0xb2,
+  0x5d,0xdd,0xbf,0xe3,0xd9,0x23,0x5,0x50,0xf2,0xbc,0x94,0xfd,0x33,0x76,0x64,0x68,
+  0x87,0xb4,0x47,0x67,0xc5,0x74,0xcc,0xa0,0xa1,0x36,0x9b,0x4a,0xc,0x9,0x4e,0x8a,
+  0x8b,0x7,0xba,0xed,0x7a,0x59,0xbe,0x16,0xaa,0x47,0xa0,0xa2,0x34,0x57,0xba,0x58,
+  0x52,0xc3,0xf4,0xef,0x7b,0xed,0x84,0x91,0x93,0x8a,0xbf,0x9c,0x38,0xf8,0xf2,0x36,
+  0xb9,0xf1,0x69,0xf3,0xcf,0x34,0x18,0x99,0xe6,0x12,0x63,0xef,0x11,0x17,0xd0,0x82,
+  0xa8,0x17,0x31,0xc4,0x6,0x2,0xa3,0xa4,0x62,0xce,0x97,0xdb,0x2a,0x30,0xf0,0xf2,
+  0xf1,0x72,0xf5,0x12,0x8d,0xd0,0x12,0xc,0x6,0xfd,0x7e,0x3f,0xfd,0x2f,0xfd,0x1c,
+  0xcd,0x8f,0x51,0xa3,0xaf,0x6c,0x93,0x52,0x59,0x5f,0x98,0xdf,0x58,0x64,0x9a,0x4a,
+  0x4c,0xed,0x8f,0x5a,0x2f,0x62,0x34,0xe2,0xd0,0xb,0xe3,0x26,0xf7,0xa9,0x54,0x6c,
+  0x56,0x8b,0xca,0x98,0x34,0xe7,0x13,0x32,0x4a,0x81,0xf2,0x52,0x52,0x26,0x91,0x60,
+  0xc0,0xe7,0xe9,0x71,0x96,0x29,0x32,0x8b,0xdd,0xe5,0xf6,0xfa,0x2,0x41,0x1d,0x9b,
+  0x13,0x23,0x52,0x7a,0xe6,0xd6,0xc6,0xc6,0xff,0xbe,0xdb,0x89,0xc9,0x43,0xab,0xbc,
+  0x3a,0x6d,0x84,0x7d,0x85,0xc4,0x98,0x14,0x1e,0x3c,0x32,0x5e,0x0,0x26,0x1a,0xf4,
+  0x2e,0x75,0x70,0x47,0x3d,0xaa,0xf8,0x96,0xf9,0x82,0xac,0xde,0xb1,0x41,0x9,0x35,
+  0xb3,0xf9,0xe2,0xda,0xdf,0xbc,0x1a,0x7e,0xd9,0x21,0x46,0xec,0x8f,0x51,0x12,0xe7,
+  0x2,0x89,0x80,0xbb,0xfe,0xd7,0xb,0xf6,0x4b,0x34,0xd8,0x67,0x7,0x35,0x18,0xb1,
+  0x38,0x7c,0x54,0xd3,0x8c,0xbd,0x2e,0x61,0x2,0x7f,0xad,0xa1,0x4a,0xa6,0x43,0x8c,
+  0xce,0x5,0xd,0xab,0x52,0xf3,0xbc,0x54,0xd3,0xd4,0x25,0x31,0x26,0xed,0x7a,0x33,
+  0xaf,0x5f,0x22,0x81,0x5e,0x19,0x3f,0x8a,0xcd,0x13,0x88,0xc6,0xde,0xdc,0x89,0xab,
+  0x99,0xdf,0x56,0x19,0x3d,0x95,0xde,0x3,0x4e,0xe5,0xe,0x31,0x66,0x25,0x98,0xfb,
+  0xfd,0xfb,0x71,0x15,0x33,0x78,0x3c,0x3f,0x22,0x5,0xdc,0xb2,0x74,0xda,0x7a,0x83,
+  0xb1,0xe3,0xcf,0xa1,0xf6,0xd1,0xc3,0x97,0xd6,0xe7,0x21,0xa4,0x5a,0xe9,0x10,0x23,
+  0x25,0x26,0xac,0xd2,0x5c,0x74,0xd7,0x40,0xf8,0xb9,0x1f,0xe4,0x34,0x4c,0xd0,0xa3,
+  0x60,0x50,0x13,0x8b,0x37,0x32,0xf6,0x1c,0xaa,0x65,0xbe,0x2a,0xa3,0xb2,0xb0,0x67,
+  0x90,0xfc,0xbe,0x43,0x8c,0xa4,0xa0,0xe0,0x6a,0x1f,0xc4,0xf4,0x40,0x78,0x7f,0xe,
+  0x98,0xa8,0x4f,0x26,0x4c,0xb4,0xec,0x62,0xc4,0xe9,0x1f,0x7b,0x19,0x43,0x66,0xe0,
+  0xa3,0x75,0x79,0xa,0xa9,0x46,0x3a,0xc4,0xe8,0x62,0xe2,0x5,0x3b,0x68,0x2c,0x57,
+  0x89,0x94,0x10,0xb5,0xae,0xea,0x50,0x63,0x3,0x40,0x79,0xd,0x13,0xf1,0x48,0xb6,
+  0x58,0x76,0x5d,0x9b,0xf7,0x5f,0x6,0x31,0x20,0xbf,0xa1,0xde,0xac,0xdc,0x93,0x19,
+  0x6b,0x75,0x88,0x29,0xcc,0x95,0x8c,0xb2,0xa1,0xd1,0xe,0x92,0xa,0xe1,0x3,0x58,
+  0x8f,0xee,0x3d,0x99,0x1b,0x91,0x5c,0xb5,0xd8,0xa8,0xa4,0xf7,0xa5,0x5d,0xc8,0x5,
+  0xc2,0x9f,0xab,0xa5,0xe1,0xea,0x47,0xa6,0xd3,0xfa,0xde,0x40,0x24,0x9e,0xa0,0x25,
+  0x16,0x9,0x7a,0x9d,0x76,0xde,0xe4,0x5f,0x95,0x18,0x42,0xfd,0xea,0x6e,0x5f,0x30,
+  0xd7,0x6c,0x22,0x1e,0x8b,0xf8,0x3d,0x2e,0x87,0x4d,0x61,0x64,0xae,0x15,0xed,0xca,
+  0xdf,0xd5,0xcd,0x83,0x97,0x6f,0x96,0xfa,0x63,0x4c,0x10,0x33,0x7b,0x2d,0xd2,0xa1,
+  0x4f,0xfd,0x50,0x7,0x26,0x20,0x9,0xa0,0xa1,0x27,0x5d,0xcf,0x63,0xbe,0xbc,0x27,
+  0x97,0x99,0x46,0xc6,0xea,0x89,0x24,0xb2,0xe5,0x9,0x7d,0xb2,0xa9,0x44,0xd0,0x6b,
+  0xd8,0xf9,0xa5,0x44,0xc,0x71,0x78,0x2,0x13,0x93,0x15,0xad,0xb2,0x2b,0x64,0x92,
+  0x27,0x3,0xde,0xa5,0xa6,0xef,0x18,0x61,0xa9,0x6b,0xd1,0xe2,0x52,0xb9,0x12,0x1a,
+  0x6,0x46,0x86,0x87,0x6f,0x28,0xab,0xcb,0x3e,0x2e,0x40,0xee,0xce,0x1c,0x31,0x97,
+  0xb3,0x44,0x76,0x40,0xe9,0xff,0x9e,0x3e,0x4b,0xf2,0xd7,0x8,0xc,0x15,0xcc,0xd2,
+  0x27,0x11,0xbf,0xcc,0xd6,0x3f,0x15,0x1a,0xbf,0xae,0xb8,0xa8,0xdc,0x5e,0x2e,0xf2,
+  0xbe,0x38,0x2f,0xf9,0x54,0x26,0x35,0xde,0x57,0xd9,0xb2,0x2,0x31,0xc4,0x13,0x4b,
+  0x66,0x44,0x49,0xa5,0x32,0xa9,0x9,0x55,0x9b,0x8e,0xc6,0xcf,0xfa,0x84,0xf,0x13,
+  0x8f,0xf7,0x56,0x11,0xd4,0xbd,0x6e,0x43,0x59,0x81,0x22,0xdd,0xc2,0x8f,0x3e,0x5a,
+  0x5e,0x95,0x7d,0xbe,0xa,0x9,0xa,0x30,0x45,0x4c,0xd7,0x6a,0x44,0xc5,0xec,0xd7,
+  0xc7,0xa4,0x80,0xec,0x9c,0x9a,0xf3,0xea,0x10,0xf7,0x37,0xe0,0x6b,0x84,0xbf,0x29,
+  0xdc,0x6,0xda,0x2b,0x4c,0x4,0x36,0x51,0xbc,0x12,0xe9,0x89,0x1b,0x14,0x41,0xe1,
+  0x67,0xd9,0x74,0xc0,0x59,0x66,0x26,0xc9,0x12,0x43,0x9c,0x1,0xa3,0x72,0xa9,0xbc,
+  0x95,0x6c,0x66,0xc2,0xa3,0xb4,0xd6,0xab,0x29,0x65,0x35,0xeb,0xc6,0x3d,0x1e,0x62,
+  0xa1,0xae,0xc6,0x89,0xa9,0x5e,0x56,0xd2,0x57,0x9b,0xa4,0xb4,0xc2,0xc2,0xf5,0x70,
+  0x6f,0x6e,0x7b,0x5b,0xb7,0x61,0x4c,0x0,0x43,0x7b,0xf6,0xd7,0x11,0x25,0xb3,0xf3,
+  0xcf,0x44,0x6a,0x54,0x82,0x18,0x6b,0x10,0x48,0x6e,0x47,0x7b,0x39,0x1d,0x2d,0x35,
+  0x2e,0x47,0xc,0x71,0x23,0x4d,0xe6,0xd9,0xc9,0x26,0xfc,0x4e,0x85,0xd1,0xa9,0xa5,
+  0x88,0xe1,0x2e,0x62,0x4b,0x11,0xf3,0x21,0x44,0xc5,0x7c,0x9f,0x8d,0x49,0x41,0xc9,
+  0xad,0xe0,0xa2,0xb1,0x99,0x3c,0x89,0x8c,0x7c,0xc3,0xe,0xc1,0x4f,0x71,0x62,0x6c,
+  0x31,0xa1,0x82,0xc9,0x77,0xec,0xa4,0x22,0x31,0x96,0xc8,0x24,0x90,0xe2,0xb0,0xe2,
+  0xab,0x6c,0xd2,0x2f,0x8f,0x4c,0x7b,0x10,0x43,0x10,0x15,0xb3,0x97,0x79,0x62,0x22,
+  0xbd,0xf2,0x62,0xe1,0xf7,0xfc,0xcf,0x6f,0x85,0x91,0x19,0x11,0x9,0x1e,0x25,0xc6,
+  0x19,0x3f,0x8b,0x75,0x6f,0xa0,0x74,0x4f,0x12,0x3a,0xc6,0xda,0x97,0xc2,0x1a,0xac,
+  0xb0,0xb0,0x4f,0x4b,0xfb,0x1c,0x1a,0x47,0xcc,0x13,0xb7,0xfb,0xc1,0x2e,0x13,0x45,
+  0xc9,0xc8,0xe8,0x98,0x73,0x90,0x97,0xff,0x75,0xa6,0x62,0x7c,0xa6,0x1d,0x26,0x96,
+  0xdf,0x87,0xfd,0x78,0xdb,0x22,0x4b,0xf9,0xa8,0x61,0xc4,0x38,0x12,0x68,0xf7,0x4e,
+  0x96,0x29,0x48,0x9c,0x18,0xa7,0xd8,0x26,0x12,0x5c,0x29,0x1b,0x13,0x29,0xc8,0xaa,
+  0x47,0x6a,0x1c,0x31,0xcf,0x8c,0xc5,0xbc,0xd0,0x4b,0xce,0x62,0xc0,0x79,0x71,0xbe,
+  0x32,0xc4,0x5c,0x7,0x13,0xb3,0x9d,0xcd,0xac,0xa3,0xe6,0x8c,0x18,0x5d,0x6e,0x1f,
+  0x45,0x36,0x73,0x1f,0x13,0x3c,0x21,0x42,0x8c,0x3d,0x8e,0x2,0x33,0x15,0x53,0xb0,
+  0x7c,0x89,0xe7,0x34,0xde,0xa0,0xa1,0x46,0x42,0x4e,0x7,0xb7,0x14,0x31,0xb5,0xfa,
+  0x63,0xc8,0x9d,0x30,0x31,0xff,0xc0,0x54,0xc,0x18,0x82,0x2a,0xe9,0xa2,0xb2,0x20,
+  0x9b,0x2d,0x47,0x4,0x93,0x31,0x98,0x18,0x87,0x4,0x30,0x99,0xf2,0xdb,0x47,0x74,
+  0x8c,0x25,0x28,0x9c,0x4f,0x83,0x20,0x65,0x2,0x32,0x5a,0xb8,0x2d,0x88,0x99,0xb,
+  0xec,0xce,0xa4,0x2c,0x85,0xd9,0x44,0xc9,0xe4,0x3c,0x29,0x8f,0xd4,0x1f,0x21,0xca,
+  0x2c,0xca,0x1f,0x96,0x40,0x62,0x2c,0x13,0x12,0xa,0x21,0x5e,0xde,0x99,0x30,0x31,
+  0xf6,0xa8,0x44,0x7b,0xdc,0x2a,0x67,0x65,0x84,0xd4,0x16,0xc4,0xbc,0x17,0x5e,0x53,
+  0xda,0x4b,0x55,0x8c,0x79,0xb3,0x57,0x67,0xc6,0xfa,0x75,0x10,0x99,0xad,0x47,0xf9,
+  0x69,0xd6,0x21,0x62,0x48,0x50,0xa6,0x83,0xfb,0xca,0xb5,0x20,0x48,0x8c,0x7d,0x2,
+  0x9b,0x75,0x89,0xaf,0x97,0x3d,0x89,0xf,0xdd,0xed,0x40,0xc,0x59,0x9,0xbf,0xf9,
+  0xdf,0xab,0x9b,0x8a,0xd1,0xb4,0x67,0x60,0xcf,0xf2,0x70,0x84,0x6b,0xaa,0x1,0xc4,
+  0x10,0xbf,0xcc,0x10,0x92,0xae,0x68,0x16,0x22,0x26,0x9d,0x94,0x1,0x50,0x58,0x27,
+  0x81,0x22,0xd3,0x3a,0xc4,0xf0,0x73,0x3c,0x60,0x99,0x1f,0xd8,0xab,0x37,0xfb,0x1a,
+  0xb8,0x1b,0x59,0xdc,0x9d,0x57,0xd2,0x52,0xc1,0xaa,0xdd,0x4,0xcf,0x96,0xbe,0xc9,
+  0x4f,0xff,0x7,0x10,0xe3,0x81,0x1d,0x77,0xf9,0xae,0xd,0x56,0xdc,0x17,0x44,0x8c,
+  0x29,0x5e,0xe8,0x8f,0x4f,0x62,0x33,0x8d,0xd6,0x21,0x6,0xeb,0x2b,0xf1,0xf7,0x73,
+  0xe1,0x3d,0x27,0x7b,0x59,0x64,0x2f,0x26,0x7,0xd9,0xab,0xbf,0xe7,0x29,0x90,0xce,
+  0xdd,0x63,0x5c,0x34,0xc5,0xc4,0x24,0xa4,0xdc,0x26,0x69,0x77,0xc3,0x88,0xc9,0x62,
+  0x73,0xca,0x76,0x20,0x66,0x21,0x9c,0x5e,0x68,0x3f,0x35,0x63,0x2a,0x16,0xfc,0x64,
+  0xe9,0xe0,0xd5,0xbb,0xe0,0x9,0x90,0x98,0xed,0x47,0xb9,0xf3,0xd,0x31,0x31,0x72,
+  0x2a,0xe1,0x64,0xe5,0x24,0x66,0x3a,0x75,0xcc,0xd4,0x14,0x7f,0x60,0x2d,0xa,0xa3,
+  0x1d,0x88,0x59,0x4,0x76,0x62,0xf8,0x0,0x25,0xa6,0x7a,0x4d,0xb5,0x66,0x68,0x66,
+  0xfd,0x16,0x3c,0x2,0x1e,0xa,0xf2,0x1c,0x61,0x26,0x89,0xc9,0x54,0xd8,0xbd,0x9a,
+  0x36,0xbd,0xc4,0x64,0x61,0x3f,0x44,0xcb,0x11,0x43,0x68,0xd8,0x9d,0xd5,0x4a,0x77,
+  0xb6,0xc9,0xbb,0xf4,0x97,0x83,0x9d,0x38,0x40,0x73,0xd9,0x44,0x38,0xa1,0x37,0x35,
+  0x42,0x83,0x6c,0xec,0x1e,0x8e,0xf4,0x70,0x1a,0x36,0x49,0x4c,0xb2,0xca,0x1c,0x9d,
+  0x5e,0x62,0xa6,0x92,0xe0,0xfa,0x5b,0x8b,0x11,0x43,0xac,0x74,0x13,0xa,0x5b,0x2f,
+  0x60,0x29,0x7e,0x65,0x83,0xc4,0x56,0xc1,0x3,0x5,0x5d,0x53,0xba,0x1d,0x9d,0x1,
+  0x48,0xf3,0x73,0x23,0xec,0xf6,0x7d,0x81,0xeb,0xd8,0x36,0x49,0x8c,0xbf,0xea,0xee,
+  0x94,0x88,0xc9,0x66,0x52,0xa9,0xf8,0x44,0x24,0x32,0x11,0x4f,0xa6,0xd2,0x72,0x13,
+  0xef,0x38,0x24,0xae,0x96,0x22,0x86,0xd8,0xf4,0xbd,0xb4,0xc5,0x62,0x97,0x3b,0x16,
+  0x16,0xf6,0xf8,0xee,0xa0,0x91,0x31,0xe0,0xf2,0x84,0x34,0x2c,0x7a,0xc5,0x4b,0xe1,
+  0x83,0x31,0x86,0x62,0x7e,0x8e,0xe3,0xd4,0x1c,0x31,0x99,0xea,0xe,0x94,0x27,0x26,
+  0x9b,0x3a,0x15,0x28,0x39,0xff,0xc9,0x52,0xff,0x44,0x52,0x2,0x9a,0x2c,0x74,0x78,
+  0x5f,0xb,0x11,0x43,0xf5,0x8b,0x61,0x35,0x52,0x2a,0xd8,0x7,0xee,0xc3,0x7d,0xe3,
+  0xb1,0x48,0xe5,0x54,0x43,0xd,0x91,0xaa,0xda,0xf3,0xe1,0x89,0xd9,0x20,0xd7,0xb9,
+  0x6c,0x8e,0x98,0xf1,0xea,0x1b,0x96,0x26,0xe6,0xb4,0xcf,0x55,0xc5,0xaf,0xc5,0xe9,
+  0xc1,0x57,0x3d,0xa7,0xca,0x22,0x2b,0xc,0xc2,0x52,0x23,0xe6,0xb1,0xa7,0x9f,0x7e,
+  0xaa,0x50,0xc0,0xb4,0x7,0xdb,0x8a,0xd5,0x8a,0x1f,0x86,0x90,0x95,0x48,0x3d,0x1f,
+  0x55,0x2d,0xc8,0x10,0xd8,0x7f,0xf7,0xa,0x5d,0x21,0xa8,0x9f,0x19,0xa3,0x69,0x77,
+  0xc0,0x63,0x60,0x2c,0xc2,0x99,0xc8,0x4b,0x13,0x93,0xcd,0xa4,0x53,0xc9,0x89,0x53,
+  0xf1,0x54,0x2a,0x5d,0x74,0xec,0x65,0xc,0xbc,0xcb,0x11,0x93,0x4d,0xfa,0xb8,0xc6,
+  0xa0,0xc5,0x53,0x19,0x4b,0xcc,0x9b,0xae,0x5,0xc4,0x56,0xa4,0x12,0x31,0xc4,0xe1,
+  0xf6,0x9e,0x2c,0x94,0x23,0x5b,0x0,0xd1,0xbd,0x51,0xac,0x56,0xfc,0x40,0x67,0x2c,
+  0xe0,0xe0,0x90,0xcb,0x23,0x63,0x67,0x36,0xaf,0x5e,0x2c,0x39,0x83,0x6,0xd7,0x32,
+  0xb3,0x51,0x8f,0xaf,0xcc,0x72,0x89,0xb4,0xe2,0xb9,0x1f,0x9e,0x2c,0xc5,0x62,0x1c,
+  0x3c,0x25,0x89,0xc9,0xc4,0x83,0xbd,0xf9,0x70,0x38,0x4b,0x8f,0x2f,0x92,0xc8,0x41,
+  0x63,0xb4,0x2a,0xa4,0x88,0xc9,0x8a,0x9f,0x1a,0x5f,0xaa,0x2c,0x8f,0xad,0xa8,0x92,
+  0x8c,0x12,0x31,0xf4,0xb7,0xce,0x42,0x5e,0x84,0xd8,0x30,0x64,0x2,0xd2,0xf9,0x9,
+  0xa7,0x80,0xc4,0x30,0x3e,0x2a,0xf7,0x5a,0xe4,0x18,0x42,0xd7,0x53,0xe7,0xc0,0xc4,
+  0xbc,0x41,0xe3,0xc1,0xe5,0xe7,0x5d,0x38,0x38,0x5f,0x85,0x2f,0x17,0x8b,0x71,0x26,
+  0x4b,0x72,0xc4,0x24,0x7a,0x2b,0x5f,0xf,0x87,0x27,0x72,0x66,0x6a,0x2a,0x6b,0xbc,
+  0x7b,0x19,0x62,0x32,0xd0,0x43,0x5b,0x7c,0xc8,0xd2,0x44,0x56,0xac,0x64,0x5a,0x86,
+  0x18,0xc2,0xd2,0xc7,0x54,0xcd,0x8e,0xf4,0x64,0x44,0x68,0xca,0xa1,0x5,0x70,0x17,
+  0xd2,0xd8,0x98,0x7a,0x2d,0x11,0xe8,0x38,0xfd,0x9,0x46,0xc,0xc7,0x9d,0x21,0x43,
+  0xcc,0x64,0x1f,0x27,0x9d,0xb1,0x3d,0x32,0x99,0x34,0x8e,0x72,0x12,0xc4,0x9c,0x76,
+  0x83,0x6f,0x9,0x59,0x86,0x84,0x74,0x26,0x85,0x3,0xb9,0x32,0x31,0x2c,0x9f,0x93,
+  0x5e,0x5e,0x42,0x74,0x8c,0x9e,0xf9,0xa9,0xb2,0x40,0x3a,0x86,0xee,0x65,0x73,0x1a,
+  0x76,0x6f,0x10,0x16,0x19,0x8e,0x29,0x88,0x6e,0xb8,0xb,0x69,0xa8,0x43,0xdd,0xfc,
+  0x77,0x8c,0x98,0x3f,0x86,0x2f,0x37,0x1a,0xe3,0x4c,0x34,0x24,0x88,0x99,0x14,0xdc,
+  0xa4,0x93,0x3,0x20,0x4e,0x4c,0x1a,0xb5,0xdc,0x7a,0x61,0x64,0xc4,0xd3,0x25,0x55,
+  0x62,0x2c,0xee,0x42,0xb9,0x9,0x9a,0xa2,0xd0,0x51,0xa9,0xaf,0x58,0xb3,0xf8,0xc1,
+  0x1,0x74,0x3e,0x53,0x27,0xc6,0xaf,0x65,0x32,0x40,0xc3,0x2e,0xdf,0x10,0x9d,0x5c,
+  0xf3,0x9c,0x6a,0xf8,0xf0,0x23,0xa8,0xf1,0x7b,0x18,0x31,0x65,0x1,0xb9,0x85,0x26,
+  0x70,0x62,0x32,0x2a,0x7a,0x10,0x25,0x26,0x83,0x9f,0x6d,0x8f,0xad,0x99,0x27,0x44,
+  0x2,0x52,0x25,0xa6,0xd4,0x4e,0x9d,0xf7,0x44,0x32,0x9b,0xc5,0x78,0x93,0x4c,0xf3,
+  0x60,0xde,0xb7,0xc5,0x70,0x17,0x9e,0x8a,0xc9,0x46,0xb0,0xca,0x41,0xf4,0x19,0xf8,
+  0x72,0x87,0x62,0x95,0xeb,0xcc,0x7a,0xa3,0x28,0x31,0xa0,0xd5,0x61,0xb8,0x2f,0x8c,
+  0x98,0x6c,0x10,0x35,0xfe,0xe8,0x4e,0xb5,0x8,0xbc,0xa6,0x25,0x5a,0xbb,0x6d,0x19,
+  0x62,0x98,0x8e,0xe1,0x13,0x83,0xa5,0xd9,0x78,0x3f,0xdc,0x85,0x13,0xb1,0x18,0xc6,
+  0x9c,0x1c,0x2a,0xf9,0x5a,0x9f,0xc4,0x88,0x89,0x18,0x9b,0x43,0x89,0x39,0x25,0xd1,
+  0xc5,0xa5,0x66,0x31,0x62,0x26,0xa4,0x1e,0xd8,0x6,0x2f,0x9b,0x57,0x3b,0x9a,0xb,
+  0x97,0x6f,0x19,0x62,0x98,0x36,0xe1,0x8e,0x4a,0xa8,0x1d,0xb3,0x2,0xd5,0x31,0x98,
+  0x25,0xa4,0x44,0xcc,0x8d,0xf0,0xe5,0xe,0xc7,0xa2,0xea,0xc4,0x64,0xd5,0x76,0x52,
+  0x61,0xc4,0x48,0xb6,0xd6,0x7,0xba,0x7f,0xe3,0x2,0xa9,0xb5,0xc,0x31,0x6c,0xae,
+  0x64,0xf4,0xbd,0x50,0xcd,0x83,0x12,0x83,0x44,0xe0,0xd1,0x51,0x49,0x89,0x8,0xac,
+  0xf2,0xd,0x30,0x31,0x7,0x79,0x97,0xc3,0x74,0xc,0x47,0x2d,0x41,0xb7,0x81,0x10,
+  0x13,0xc7,0x1e,0x21,0xff,0xbd,0x1d,0xf4,0xfe,0x56,0xc5,0xe4,0x14,0xdb,0x6c,0x19,
+  0x62,0x34,0xdd,0xc8,0xad,0xe4,0x9a,0xb0,0xbf,0xa1,0xa,0x2,0x49,0x35,0x34,0xc1,
+  0x7b,0xe9,0x25,0x65,0xca,0xab,0x76,0x13,0xa6,0x63,0x62,0xc6,0x3b,0x46,0x88,0x31,
+  0x7a,0x75,0xe1,0xfb,0x83,0x89,0xc9,0xca,0x1a,0xd1,0x24,0x0,0x29,0x99,0x33,0x2,
+  0xeb,0xb9,0x75,0x88,0x61,0xce,0x97,0x4a,0xf,0x1e,0x5b,0x98,0xb4,0xe3,0x3,0x3c,
+  0x1c,0xec,0x10,0x3a,0x15,0x53,0x7c,0x83,0x11,0x9a,0x7e,0x17,0xb3,0x63,0xca,0x77,
+  0x16,0xe5,0xdb,0x42,0x88,0x1,0xd7,0x8a,0x39,0xb7,0x3,0x13,0x93,0x90,0x8e,0x37,
+  0xec,0x1,0x23,0x46,0x5,0x91,0x55,0xad,0x43,0x8c,0x96,0xf3,0xd7,0xd1,0x44,0x38,
+  0xec,0x1d,0xa5,0xab,0x4,0x6c,0x61,0x52,0x26,0xe2,0xe1,0x22,0xb8,0xb,0x4f,0xd6,
+  0x99,0x18,0x64,0x76,0x7d,0x94,0x67,0x68,0xc3,0xc4,0x64,0x45,0x46,0xa6,0x88,0x5d,
+  0x90,0x98,0x2c,0x67,0x76,0x2f,0x6a,0x68,0x1c,0x9a,0x2e,0x9,0x38,0x6e,0x3a,0x31,
+  0xa2,0xcd,0xb3,0xa5,0x90,0x7,0x6c,0x4,0x41,0x66,0xd7,0x6f,0xd7,0x99,0x98,0x3f,
+  0xc0,0xfc,0x31,0x9c,0x98,0x62,0x98,0x98,0xb4,0xaa,0xbf,0x8,0x24,0x26,0xad,0xe0,
+  0xaf,0xf4,0x40,0xc4,0xa4,0xf8,0x5e,0xc0,0x36,0x20,0x6,0xf1,0xe0,0xfd,0xb0,0xce,
+  0xc4,0xfc,0x21,0x4c,0xc,0x3d,0xf0,0xc0,0x38,0x2a,0xc0,0xc4,0x24,0xf0,0x91,0xb7,
+  0xf2,0xad,0x1,0x89,0x49,0x49,0xf,0x4a,0x74,0xfb,0x15,0x44,0x8c,0xc0,0xba,0x6a,
+  0x3,0x62,0x90,0x75,0xa5,0x37,0xea,0x4c,0xcc,0x7d,0xd8,0xba,0x92,0xb2,0x1d,0xc3,
+  0x71,0xf9,0x99,0xb0,0x7c,0x65,0x67,0x4a,0xfa,0x25,0xc0,0xa5,0x2,0xbe,0x5,0xdd,
+  0xfe,0xc4,0xd0,0xfd,0x6d,0xd8,0xb8,0xa6,0xf4,0x3d,0x1c,0xf1,0x17,0xa6,0x4b,0xf6,
+  0x46,0x95,0x1,0xeb,0x18,0xd9,0xb9,0x4d,0xf1,0x36,0x41,0x1d,0xa3,0x60,0xc6,0x68,
+  0x1a,0xb8,0xe3,0x9b,0x6f,0x5e,0x35,0x9d,0x18,0x63,0x3e,0x87,0xaa,0xbf,0xa0,0x2a,
+  0x1b,0x89,0x8f,0xa1,0x11,0x55,0x4a,0x44,0x20,0x95,0xc9,0x1a,0x50,0xc7,0x6c,0xa3,
+  0xc4,0xa8,0xce,0xae,0x25,0xd3,0x70,0x48,0xfa,0x7c,0x15,0xcc,0x18,0x4d,0x3,0x77,
+  0xf0,0xf2,0xe7,0x98,0x4d,0x27,0xa6,0xe,0xbd,0x9,0x6f,0x57,0xa2,0x51,0x9b,0xa8,
+  0x4b,0x47,0xe1,0x26,0x90,0x23,0x9c,0x76,0x52,0x62,0x14,0x7d,0xbe,0x59,0x85,0xab,
+  0xe7,0xaa,0x82,0x3a,0x46,0x6a,0x85,0xa0,0x70,0x49,0xf,0x94,0xe8,0x88,0x3f,0xbe,
+  0xb5,0x3,0x31,0x70,0x82,0xaa,0x1d,0xe3,0x75,0x5d,0x57,0xba,0x4,0x8e,0x2a,0x7e,
+  0x96,0x6e,0x75,0x51,0x24,0x66,0xb2,0xbe,0xc4,0x28,0xb5,0xd6,0x3,0x45,0x56,0x25,
+  0xb9,0x4d,0xb5,0x3,0x31,0x70,0xe4,0xed,0xb6,0x13,0xbc,0x38,0x4a,0x25,0xb9,0x96,
+  0x57,0xbe,0x1e,0xde,0x78,0xfd,0x1d,0x75,0x62,0x84,0x71,0x5,0xc2,0x7b,0x84,0x74,
+  0x4c,0x46,0xe9,0xc9,0x5c,0x90,0xe9,0xcb,0x47,0xb9,0x1d,0x88,0x81,0xf7,0x2b,0xd1,
+  0x1d,0x6e,0x75,0xdc,0x4a,0x80,0xe5,0x91,0x18,0xa6,0x29,0x60,0x15,0x75,0x8c,0x61,
+  0xab,0x0,0xda,0xe7,0x60,0x6e,0x7,0xf4,0xd7,0xe5,0x15,0x9c,0xd0,0xfa,0x75,0xba,
+  0x6d,0x75,0xcc,0x65,0xc8,0x2e,0xda,0xba,0xa4,0xa7,0xca,0x4b,0x6f,0xd6,0xad,0xf0,
+  0xc5,0xe,0xd3,0xa8,0x62,0x45,0x62,0x94,0x27,0xd7,0xa0,0x1d,0x93,0x52,0x22,0xc6,
+  0x1,0xe5,0xe,0xe1,0xab,0xab,0x76,0xd0,0x31,0x4b,0x60,0xf,0xc9,0xd0,0x78,0xd5,
+  0xb6,0x65,0x25,0x99,0x56,0x55,0x3e,0xff,0x1,0xf0,0x62,0x3,0x87,0xb8,0x51,0xc5,
+  0xe0,0xec,0x5a,0x75,0x8d,0x0,0xb6,0x7c,0xd5,0xc6,0x38,0x70,0xf9,0xba,0xd5,0x89,
+  0xd1,0xf7,0xcd,0x56,0xf5,0x8f,0x4d,0xea,0x60,0xb7,0x6e,0x38,0x45,0xd5,0xae,0x51,
+  0x60,0xf7,0x8d,0x2a,0x3d,0x17,0xc2,0x66,0xcc,0x8e,0xd1,0x18,0x6f,0xc,0x4,0x89,
+  0x51,0x4f,0xd0,0x7,0x8d,0x4a,0x6a,0xc4,0xd8,0x40,0x87,0x4c,0x8b,0x8f,0x4a,0xfa,
+  0xe6,0xa4,0xaa,0x7b,0xd4,0x77,0xa4,0xa0,0x9d,0x7a,0xe,0x6c,0xfa,0xf6,0x1f,0xe,
+  0xe2,0x6d,0xa0,0x17,0xc9,0x57,0xb8,0x5,0xd6,0x67,0x7b,0xe8,0x22,0x1,0x27,0x9e,
+  0x9,0x24,0x46,0xc9,0x81,0x82,0xce,0xae,0x3b,0xc4,0x48,0x10,0xd3,0x75,0x15,0xdc,
+  0x8d,0xaf,0x44,0x24,0x83,0xd2,0x24,0xb0,0x79,0xc,0x36,0x63,0x5e,0xa0,0x53,0x25,
+  0x8e,0x43,0xe,0x22,0x26,0xab,0x6e,0x97,0xe3,0xf9,0x7c,0x25,0x9e,0x44,0xaf,0x62,
+  0x5,0xb3,0x36,0xb6,0xad,0x8e,0xd1,0x3e,0x8,0xfb,0xf0,0xb6,0x47,0xd5,0x5f,0x63,
+  0x81,0xc8,0xe7,0xc1,0x83,0xd2,0x16,0x6a,0xf8,0xf2,0x14,0x1a,0x44,0x4c,0x46,0x75,
+  0xe5,0x1a,0xb6,0x63,0xd4,0xbc,0x3b,0xe0,0xa8,0xd4,0xbe,0x76,0x8c,0xb6,0x18,0x39,
+  0xbf,0xed,0x98,0x54,0xba,0xf0,0x9e,0x1e,0x74,0x41,0x42,0xfb,0x34,0xac,0xcd,0xb6,
+  0x52,0x33,0xc6,0xcf,0x89,0x64,0x87,0x88,0x49,0xab,0x2b,0xc0,0xfa,0xf9,0x63,0x66,
+  0x34,0x31,0xb2,0x8a,0x94,0x53,0xef,0x1c,0x38,0x9f,0x6f,0x68,0xb7,0xcc,0xc6,0x6b,
+  0x6b,0x22,0x9d,0xc,0x3a,0xe1,0x9c,0x35,0xf3,0xe0,0xc4,0xe,0x21,0xb6,0x46,0xd0,
+  0xc7,0x59,0x93,0x80,0x88,0x49,0x35,0x93,0x18,0x70,0xae,0xd4,0xbe,0xfe,0x18,0x8d,
+  0x7c,0x1c,0x7e,0xf5,0xb7,0x1c,0x16,0x9c,0x17,0x50,0x46,0x5f,0x2e,0xe8,0x35,0x9b,
+  0xc,0xba,0xc5,0xb9,0x1,0xc8,0xf5,0x8f,0xc0,0x17,0x7a,0x8d,0x9a,0x31,0x3c,0xb3,
+  0x4,0x24,0x6,0xdd,0xbe,0x68,0x78,0x47,0xc0,0x75,0x25,0xa5,0x45,0x34,0x27,0xe4,
+  0x8f,0xe1,0xbb,0x76,0xda,0xc1,0x1f,0xa3,0x69,0x48,0xe0,0x66,0x78,0x8,0xf7,0xc8,
+  0x14,0x65,0x97,0x8e,0xb,0x33,0x5a,0x9d,0x8b,0x64,0xb3,0xf,0xd3,0x99,0x12,0x37,
+  0xf3,0x8,0x44,0x4c,0x52,0x79,0xe9,0x1a,0x5e,0x89,0x54,0x9a,0x17,0xba,0x20,0x9f,
+  0x6f,0xfb,0xae,0x2b,0xd1,0xa8,0x60,0xd8,0xf4,0xd,0x6d,0x79,0x9,0x7d,0xf3,0xca,
+  0x76,0x8,0x66,0x53,0x11,0x17,0x77,0x74,0xba,0x1c,0x51,0x31,0x6c,0x50,0xa,0xf2,
+  0x36,0xe4,0x35,0x92,0x18,0xa5,0x68,0x1b,0x17,0x14,0x1b,0xde,0xbe,0x6b,0xd7,0x54,
+  0x6b,0x63,0x87,0xfe,0xed,0xc6,0x66,0x4b,0xce,0xca,0x8d,0x18,0xd9,0x9,0xaf,0xf1,
+  0x5d,0x9d,0xf5,0x35,0x78,0x4c,0xa,0xbd,0xc8,0xce,0xe4,0xe1,0xd9,0x63,0x10,0x31,
+  0xf2,0xa1,0xff,0xc5,0x96,0xc1,0x51,0x49,0x69,0xd1,0xc1,0xd,0xad,0x5d,0xb7,0x6f,
+  0x7c,0xc,0x95,0xe4,0x12,0x44,0xc9,0x84,0xff,0x1c,0x9e,0x7,0x91,0x53,0xd5,0x11,
+  0xaf,0x67,0x12,0x86,0xec,0x1c,0xbf,0x86,0x0,0xb3,0x8d,0xee,0x23,0xe0,0xaf,0x7a,
+  0x36,0x92,0x18,0xa5,0xa8,0xcd,0x3e,0x28,0xd0,0xb7,0x45,0x63,0xf0,0x4c,0x4c,0x91,
+  0xca,0x7e,0x3a,0x17,0x3b,0xbc,0xf8,0x81,0xf7,0x41,0x17,0x22,0x5e,0xce,0xbb,0x96,
+  0x49,0x78,0x2b,0xc6,0xa6,0xf7,0x7c,0x9,0x21,0x66,0x37,0x35,0x63,0xa2,0xdc,0x5d,
+  0xe2,0x8d,0x24,0x26,0x89,0xfb,0x8,0x4a,0xa2,0x0,0x8f,0x49,0xe1,0x2f,0x5f,0xb4,
+  0x9c,0xe5,0xab,0x6f,0x54,0xb2,0xd3,0x6d,0x4b,0x2a,0x19,0x7d,0x35,0xb2,0x12,0x3a,
+  0x19,0x97,0xf5,0xf4,0x67,0xcf,0x5,0x90,0x11,0x4d,0x32,0x13,0x65,0x87,0xfb,0x62,
+  0x66,0x6f,0xa8,0x9f,0x46,0x3a,0xf0,0x16,0xae,0xe9,0x75,0x1b,0x49,0x8c,0xd2,0x5e,
+  0x16,0x70,0xe9,0x9a,0xef,0x8c,0x6e,0x31,0x62,0x2a,0xf2,0x6d,0xaa,0x9c,0xfa,0xde,
+  0x7d,0xf,0xa2,0x0,0x1e,0xb9,0x1e,0x20,0xc6,0x2f,0xda,0x4e,0x9a,0x4d,0x14,0xb3,
+  0x24,0xfd,0x26,0xec,0xee,0xd,0x85,0x76,0x52,0x15,0x23,0x8,0xc5,0x81,0x88,0x51,
+  0xdd,0x10,0x49,0x1f,0x3,0xde,0xe1,0xa6,0xb0,0x16,0x4e,0xa0,0x6d,0xb4,0x82,0x34,
+  0x55,0xad,0x45,0x8c,0xbe,0x2d,0xb2,0x54,0x1c,0xe8,0x2e,0xfd,0x22,0x5,0xe4,0x63,
+  0x8,0x31,0xa1,0x4d,0xdd,0xc2,0xf9,0x92,0x5,0x98,0x31,0x64,0x26,0x5c,0xfa,0x1e,
+  0xcd,0x8b,0x91,0x79,0x52,0x28,0xc4,0x72,0xff,0x9,0xd6,0x3c,0x1b,0x49,0xcc,0xd4,
+  0x4,0x96,0x3e,0xa5,0xf4,0xea,0x2c,0x9b,0x89,0x7b,0x22,0xcb,0xdf,0x7c,0x4b,0x65,
+  0x2,0x68,0x99,0x24,0x78,0xc5,0x9f,0xcf,0x46,0x6c,0xdf,0x50,0xe8,0x9e,0x85,0x2,
+  0x64,0x90,0xdc,0x3b,0x99,0x80,0x83,0x90,0xb,0x91,0xd3,0x6e,0x43,0xa1,0x5d,0x2c,
+  0x55,0xa4,0x60,0x39,0x2,0x22,0x46,0xa1,0x83,0xb,0xf,0xb,0xef,0xbb,0x4e,0xe3,
+  0xee,0xca,0x7c,0x43,0xf0,0x83,0x7,0xf9,0xe2,0x9a,0x26,0x1d,0x43,0x9d,0x9f,0xea,
+  0xce,0x6f,0x96,0x42,0xa6,0xba,0xc8,0x6b,0x19,0xc4,0xef,0x4b,0x55,0xd0,0xda,0x6e,
+  0xfe,0xc0,0xe4,0x46,0x8e,0x38,0xca,0x26,0x7c,0xdd,0xf7,0x62,0x2a,0x2c,0x7c,0x80,
+  0x1d,0x90,0x2c,0x58,0x87,0x6e,0x28,0x31,0x53,0x78,0x4a,0xb3,0xbc,0x1c,0xe0,0x8,
+  0xbc,0xc6,0xe6,0x76,0xa8,0x85,0x18,0x92,0x4b,0x19,0x6e,0xb7,0xd9,0xac,0x16,0x8b,
+  0xc5,0x66,0xcb,0xfd,0xaf,0xf4,0x66,0x8a,0xf3,0x90,0xe5,0xc8,0x50,0x68,0xe3,0x3d,
+  0xb,0x78,0xaf,0x8d,0xd5,0x30,0xb3,0x36,0xe8,0xea,0xff,0x7b,0x18,0x3,0x26,0xc4,
+  0x62,0xa9,0x62,0xa2,0xa3,0x39,0x1b,0x4b,0x4c,0x12,0x75,0x57,0xe6,0x88,0x21,0x42,
+  0xf3,0x8d,0x9,0x40,0x64,0x41,0xb7,0x8e,0x8e,0xc9,0xd9,0x30,0x34,0x1f,0x48,0xfe,
+  0x79,0x59,0xe,0x68,0xf6,0x17,0xc9,0xc7,0x97,0x98,0x2e,0xd1,0x81,0x69,0x9,0xa7,
+  0x35,0xd0,0x8b,0xa5,0xc3,0xf3,0xe3,0xa7,0x51,0x60,0xfa,0x69,0xa6,0x21,0x71,0x8a,
+  0xc6,0xc6,0x12,0x33,0x25,0x99,0xbf,0x18,0xe,0xc0,0x4b,0x34,0x36,0x47,0xd5,0x3f,
+  0xa9,0x8f,0x4a,0x3a,0x1f,0x95,0x83,0x90,0xe,0x91,0xb4,0x92,0x41,0x8e,0x72,0xd3,
+  0x3b,0x7d,0xdd,0x65,0x46,0x39,0xd8,0x7d,0xa7,0xe0,0x7c,0xc8,0xff,0x83,0x3,0x13,
+  0xda,0xc7,0x26,0x4a,0xc2,0x84,0x85,0xd,0x26,0x46,0x90,0x95,0xa1,0x7a,0x4c,0xee,
+  0x5,0x1f,0x5b,0xb4,0x1b,0x77,0x9a,0x74,0xc,0x1d,0xd4,0x55,0xed,0x18,0x76,0x2c,
+  0x41,0x75,0xa0,0x2f,0x1b,0xa8,0xe4,0x2d,0x99,0xb,0x31,0x9f,0xc,0x45,0xe6,0xc1,
+  0xab,0xce,0x31,0x30,0x43,0x53,0x61,0xf9,0x4f,0xd3,0xec,0xdc,0xfc,0x72,0xe6,0x9d,
+  0x1,0x54,0xc3,0x84,0x6,0xd8,0x98,0x24,0xce,0x1b,0xdc,0x60,0x62,0xce,0x46,0x64,
+  0xbc,0x78,0x16,0xf8,0xc,0x52,0xd1,0x92,0xfa,0x34,0x11,0xb3,0x5f,0x9d,0x18,0xaa,
+  0x4f,0x1c,0x86,0x7,0xa5,0x8a,0x47,0x9e,0x18,0xed,0x36,0xbc,0x6b,0x43,0xa1,0x35,
+  0x17,0x71,0xd5,0xad,0xbb,0x70,0xc,0x40,0x25,0x37,0x67,0xff,0xf7,0xbb,0x12,0x8d,
+  0xea,0x66,0x6f,0x4c,0x70,0x3c,0x3a,0xe2,0xc1,0xab,0xfb,0x5c,0x89,0x3e,0x80,0x44,
+  0x3e,0x5f,0xcd,0x2,0x9f,0x9a,0x2c,0xdc,0xc5,0x52,0x3b,0x31,0xdd,0xeb,0x0,0x51,
+  0xee,0x8b,0xc5,0xa4,0xe7,0x78,0x79,0x65,0xc9,0x55,0x27,0x74,0x5c,0x32,0x62,0x24,
+  0x74,0xc5,0x75,0x63,0x7e,0x7c,0xfd,0x8e,0x37,0x5c,0xc5,0x35,0x80,0x89,0xbd,0x6f,
+  0xc2,0xa0,0xa6,0x7f,0xf2,0xe,0x7c,0xc0,0x75,0x5e,0x4,0x6c,0x7d,0x0,0x3a,0x52,
+  0xbb,0xc1,0x3a,0x86,0x9a,0xad,0xcb,0xb0,0xd5,0x17,0xee,0xc2,0x48,0xd9,0xdb,0x22,
+  0x4c,0x11,0x51,0x3b,0x31,0xb,0xa0,0xc0,0x37,0x4a,0x8c,0x6a,0xc0,0x33,0xdf,0xfb,
+  0x42,0x35,0x8f,0xb4,0x21,0xa3,0x91,0xeb,0x50,0x37,0x1b,0xeb,0xe2,0x8d,0xeb,0x56,
+  0xcd,0xe1,0xe9,0x19,0x62,0x71,0x9d,0xca,0x94,0x6d,0x5d,0x3f,0x7b,0xe6,0xdf,0xbf,
+  0x85,0x39,0x7a,0x75,0x64,0xb6,0x1e,0x63,0x2a,0x86,0x77,0x14,0x57,0xbe,0xdf,0x1a,
+  0x4e,0xcc,0x54,0x12,0x3e,0x97,0x80,0xfa,0x8d,0xe1,0x31,0x49,0x7c,0xf8,0x49,0xed,
+  0xc4,0xcc,0x85,0x88,0xa1,0x91,0x22,0xb5,0x10,0x63,0x7c,0x31,0x94,0x88,0xd1,0xc8,
+  0x2d,0x12,0x43,0x48,0x4e,0xcf,0x2c,0x9e,0xcd,0x7b,0xb,0x89,0x33,0x52,0x70,0xce,
+  0x9c,0xfd,0xf1,0x3b,0xdf,0x92,0x6b,0xad,0x9f,0xc6,0x83,0x53,0x15,0x3,0x84,0x32,
+  0x35,0x9e,0x98,0xa9,0x14,0xb8,0xd,0x8a,0xf4,0x20,0xa7,0x26,0x8b,0x2d,0xa1,0xda,
+  0x89,0x1,0x83,0x6b,0xb7,0x8e,0x29,0x13,0xc3,0x52,0x6d,0x9a,0x25,0x46,0xb3,0xc2,
+  0x87,0xb,0x97,0x11,0xb0,0xe1,0xda,0x2b,0x17,0x72,0x99,0x71,0x47,0xd9,0xd8,0xf4,
+  0x93,0xff,0xfe,0x67,0x49,0x5e,0x42,0xe1,0x11,0xfd,0x60,0x20,0xa8,0x87,0x9a,0x40,
+  0xcc,0xd4,0x24,0x2f,0xe0,0xb8,0xe0,0xec,0xf5,0x22,0xc0,0xa4,0xc5,0x4f,0x53,0x3b,
+  0x31,0x73,0x20,0x1d,0x33,0x70,0x4c,0xf9,0xc0,0x11,0x7e,0xb2,0x67,0x25,0x3b,0x86,
+  0xca,0xe3,0x7d,0x5b,0xe5,0xf4,0x2,0x9b,0x36,0x6d,0x58,0xf3,0xa1,0x25,0x73,0x66,
+  0x77,0x55,0x1c,0x74,0x46,0xc8,0xac,0xf9,0xee,0xff,0xf8,0xcf,0xef,0x7e,0x5d,0x6a,
+  0x38,0x62,0xd7,0xa,0x3f,0xcb,0x8c,0x18,0xf8,0xf0,0xd2,0x66,0x10,0x33,0x95,0x89,
+  0x8,0x72,0x21,0x13,0xab,0x1f,0x39,0x5e,0x69,0xea,0xa4,0xd8,0xb,0x56,0x3b,0x31,
+  0x5d,0x60,0xb2,0xa6,0xa1,0xb1,0x2a,0x4a,0xbb,0xba,0x10,0x5b,0x8c,0xae,0x11,0x18,
+  0xa7,0x45,0xd4,0xf2,0x95,0xc8,0xe8,0x5b,0xd6,0xb2,0xe5,0x93,0xf0,0x1e,0xb4,0x6a,
+  0x9e,0x1e,0x5c,0x73,0xcd,0xaa,0x2b,0x97,0x2f,0x5e,0xc4,0xca,0xe2,0xb,0x2f,0x5a,
+  0x7e,0xe5,0xaa,0xfb,0x1f,0x93,0x86,0x45,0x6f,0x6c,0xf0,0x4,0x3,0x26,0x8,0x3a,
+  0x13,0x9a,0x42,0xcc,0xd4,0x54,0xca,0xc7,0xb3,0x1,0xad,0x5e,0x70,0xeb,0x2c,0xb3,
+  0x7e,0x33,0x40,0xb4,0x7a,0xed,0xc4,0x10,0x70,0xef,0x6a,0xff,0xd0,0xe7,0xca,0xfa,
+  0xb1,0xeb,0xe7,0xae,0xb8,0xe5,0x3a,0xc4,0x79,0x4b,0xcf,0x52,0x32,0xc2,0x41,0x1d,
+  0x32,0xa,0xb3,0x6b,0x76,0x45,0xdb,0xe7,0xfb,0xa5,0xb5,0x4c,0xb1,0xe2,0x86,0x5c,
+  0xd9,0xf4,0xa0,0xfa,0x4f,0x77,0xe9,0x9e,0x98,0x18,0x6c,0x68,0x36,0x89,0x98,0xa9,
+  0x33,0x89,0x40,0xf5,0x42,0xb6,0xc5,0x1d,0xc7,0x14,0xcc,0xd4,0x14,0x94,0x33,0xbb,
+  0x76,0x62,0x90,0x23,0x36,0xc3,0x4f,0xdc,0x30,0x2b,0xc7,0xcc,0xfc,0x1b,0x3f,0x7d,
+  0xeb,0x3,0x3,0xa1,0x6b,0xb8,0xa6,0x66,0x9,0x2b,0xe6,0xad,0x33,0x6c,0xfc,0xe0,
+  0x2a,0x1e,0x58,0x59,0xd9,0x9e,0x97,0xf0,0xb8,0xa9,0x93,0x21,0xf8,0xc5,0x4e,0x7d,
+  0x9a,0x14,0x5,0x6c,0x6,0x76,0xb7,0xcd,0x22,0x86,0x6e,0xa7,0x49,0xc7,0x7d,0x2c,
+  0xad,0x36,0x2b,0x74,0xa9,0xce,0x1d,0x9b,0xc4,0x79,0x81,0x8f,0x48,0x37,0x41,0xc,
+  0xb6,0x58,0xbc,0xf9,0xe1,0x27,0x1e,0x7f,0xfc,0xf1,0x7,0xd6,0x6f,0xd8,0xac,0xab,
+  0xf9,0xb5,0x73,0x91,0x61,0x89,0x26,0x72,0x30,0x10,0xc3,0xfe,0x86,0x79,0x16,0xaa,
+  0xbf,0x5f,0xfa,0xbc,0xbc,0x2d,0x63,0x96,0x9c,0xc1,0xe3,0xba,0x86,0xe1,0xed,0x83,
+  0x2c,0xbf,0xad,0xe6,0x11,0xc3,0xc6,0x98,0xec,0x64,0x62,0x3c,0x1a,0x8d,0x4e,0x24,
+  0x92,0x12,0xb4,0xe8,0xfe,0x3f,0x68,0x38,0x30,0x41,0xc,0x72,0xe6,0x48,0x75,0x67,
+  0x3c,0xd4,0xad,0xda,0xf5,0x35,0xd6,0x27,0x9e,0xe1,0x1a,0x6,0xa6,0x9a,0xd8,0xd9,
+  0xfb,0x36,0x3d,0x61,0x57,0x18,0x47,0x55,0xba,0xff,0xe6,0x12,0x3,0x9f,0xbc,0x65,
+  0xfc,0x76,0x1c,0x5c,0x63,0x30,0x41,0xc,0x92,0xe8,0xa7,0xba,0xb,0x36,0x9f,0x27,
+  0x71,0x8e,0x49,0x8d,0x90,0x54,0xfe,0x8c,0xf4,0xd,0x37,0x44,0xcb,0x84,0x5f,0xfd,
+  0xb7,0x64,0x62,0x62,0x5c,0x14,0x78,0x57,0x76,0x53,0x33,0x8a,0x98,0x14,0x1c,0xc3,
+  0x67,0x82,0x98,0x73,0x14,0x5f,0xcb,0xbf,0x8b,0x70,0x4e,0x5b,0xad,0xb,0x22,0xd5,
+  0x8d,0x10,0xdf,0xa1,0x41,0xc5,0x9b,0xab,0xa1,0x7a,0xff,0xf7,0x4f,0x27,0x69,0x89,
+  0x4b,0xe4,0x1a,0x69,0x1c,0x31,0x65,0x2e,0x6b,0x55,0xd5,0x92,0xaf,0x8f,0x9d,0x6b,
+  0x60,0x82,0x18,0x6d,0x93,0x9a,0x98,0xbf,0x83,0xe,0xf7,0x75,0xc3,0xc7,0xe2,0x3b,
+  0xfa,0xac,0xda,0x1c,0x59,0xed,0x51,0x58,0xed,0x81,0xb7,0x18,0x2f,0xc9,0x64,0x2a,
+  0xc5,0xdd,0x6,0x59,0xf1,0x2c,0xd,0x23,0x26,0x8d,0x4e,0x9c,0x31,0x8e,0x60,0x23,
+  0x86,0x3e,0x95,0x19,0x62,0x30,0xd3,0xb7,0xaa,0x17,0xf6,0x70,0x17,0x77,0x73,0x19,
+  0xc2,0xd5,0xf6,0x9a,0xe0,0x64,0x59,0xfa,0xa2,0x7,0xa6,0x77,0xca,0xf4,0xed,0x7f,
+  0xcd,0x3,0x93,0x9d,0x3a,0x9b,0xe,0xba,0xe0,0xf0,0x82,0x86,0x11,0x93,0x72,0x81,
+  0x29,0x84,0x30,0x5c,0xa8,0x95,0xc,0x5a,0xbd,0x4c,0xf0,0x66,0x88,0x59,0x2e,0x11,
+  0x8f,0x52,0x46,0xcd,0xe,0xee,0x80,0x9f,0xf,0xec,0x75,0x38,0x1c,0xea,0xb3,0x22,
+  0x80,0x1c,0xe2,0x8b,0x1c,0xde,0xae,0xae,0x38,0x64,0x7f,0xd1,0xff,0xea,0x7f,0x15,
+  0x81,0xd1,0x43,0x1c,0x83,0x6e,0x88,0x99,0xc6,0x11,0x63,0xb5,0x82,0x47,0xf9,0x61,
+  0xc8,0x64,0xf0,0x3d,0xb8,0x66,0x88,0x59,0x80,0x64,0x53,0xa9,0x12,0xff,0xd6,0x58,
+  0x94,0xe3,0x4a,0x2c,0xf,0x5,0xc7,0x75,0x87,0x7c,0xd,0x8b,0x27,0x72,0x74,0x64,
+  0xba,0xe6,0x4c,0x4f,0xbd,0xa5,0x9b,0x30,0xc9,0xe4,0x64,0x71,0xc3,0x4f,0x7a,0x2,
+  0x70,0xe2,0x35,0x90,0x18,0xcd,0x65,0x2,0x99,0x8c,0xc4,0xb1,0xc7,0x66,0x88,0xc1,
+  0xf2,0xcf,0x55,0x11,0x43,0x8f,0x5,0xe1,0xc4,0xcc,0x94,0x88,0xa9,0xab,0x8e,0xa1,
+  0x71,0xcf,0xce,0x60,0xec,0xd8,0xf6,0xe9,0xb0,0x66,0xfa,0xff,0x31,0xaf,0x60,0x92,
+  0x15,0x9b,0x10,0xb2,0xc9,0xdb,0x45,0xb1,0x3c,0x8d,0x24,0x86,0xd8,0xc7,0xc1,0x33,
+  0x66,0x1,0x35,0x93,0x41,0x1c,0x91,0xfa,0xfb,0x6a,0x86,0x18,0xd,0xdd,0x88,0x58,
+  0xc9,0xcc,0x28,0x6f,0x75,0x92,0x25,0x65,0xcd,0x6f,0x9a,0x95,0x8d,0x1,0x97,0x55,
+  0x34,0x76,0x7f,0x74,0x6c,0xa4,0xfe,0xf3,0xec,0xbd,0x3f,0xca,0xe9,0x97,0x64,0xca,
+  0xe0,0x10,0x4b,0x47,0xbc,0x5c,0x87,0x63,0x23,0x89,0x61,0x67,0x9f,0xcb,0x79,0xea,
+  0xaa,0xd9,0x99,0xc4,0xb3,0xec,0x98,0x25,0x86,0x7c,0x58,0x76,0xdc,0xd7,0xeb,0x1d,
+  0x8a,0x49,0xdd,0x92,0x2c,0x10,0x78,0x3d,0x9b,0x37,0x16,0x3b,0x36,0x54,0x5f,0xb,
+  0xf8,0xa9,0xb7,0xa,0xa,0xc6,0x8,0xc,0xf3,0x97,0x26,0x22,0x9c,0x4c,0x88,0x8d,
+  0x25,0x46,0xb3,0xf8,0x91,0x1d,0x58,0x5c,0x3d,0x93,0xc0,0x82,0xb0,0x72,0x2,0x37,
+  0xa5,0x63,0xb4,0x39,0xd8,0x6e,0xe7,0xa,0xa2,0x5e,0x14,0xec,0x63,0xc7,0xbb,0xbe,
+  0xd6,0x1a,0xc4,0x15,0x88,0xc6,0x8e,0x8e,0x6c,0xa9,0xd7,0xd8,0x14,0x2e,0x1a,0x30,
+  0xc9,0x64,0x5a,0xb8,0x57,0x3b,0x19,0xa8,0xe,0xf4,0x69,0x30,0x31,0x1a,0xb1,0x27,
+  0x54,0x47,0xa6,0x8c,0x54,0x34,0xb9,0x69,0x62,0xb4,0xc5,0xf0,0xd9,0x31,0x95,0x2a,
+  0x68,0x24,0xc6,0xb1,0xc4,0x9,0x2d,0x12,0x40,0x48,0x56,0x33,0xb4,0x64,0xf3,0x44,
+  0x98,0x9e,0xa9,0x8b,0x3d,0x13,0xde,0x5b,0xd4,0x2f,0x9c,0x11,0xa9,0xec,0xbd,0xcd,
+  0x56,0x6f,0x27,0x6c,0x34,0x31,0x54,0x13,0xf8,0x91,0x98,0xa9,0x2a,0x35,0x53,0xca,
+  0x48,0x80,0x75,0x86,0x39,0x1d,0xa3,0x91,0x8f,0xe0,0xbb,0x5,0x8b,0xd8,0xec,0x8e,
+  0x45,0x8d,0x70,0x48,0x65,0x5,0xd7,0x34,0xc9,0x6a,0xc6,0xc7,0x25,0x4b,0x3,0x74,
+  0xe5,0xe7,0xe8,0x8b,0x83,0x66,0xf5,0x4c,0xff,0xab,0x3f,0x2a,0x8c,0x47,0x80,0x82,
+  0xd1,0x3b,0x22,0xde,0x6c,0x1d,0x43,0xc5,0x40,0x96,0x8e,0xcb,0x5b,0x33,0x69,0x85,
+  0xac,0xea,0x26,0x89,0xd1,0x2c,0x9f,0x97,0x37,0x2d,0xb7,0xf3,0x8e,0x50,0x94,0x44,
+  0x41,0xb2,0x1a,0xef,0x5,0xb1,0xf4,0x4,0xa9,0x9e,0x19,0x1b,0xdd,0xbf,0xbd,0xbf,
+  0x56,0x6a,0xc2,0x5b,0x76,0xbc,0xfe,0x83,0x53,0x89,0xbc,0xc5,0x5b,0x36,0xa7,0xe6,
+  0x1a,0x4,0xc6,0x90,0xc7,0xc6,0xeb,0x18,0xc6,0x8c,0x4b,0x8f,0x3f,0x45,0x4b,0x36,
+  0x1d,0x91,0xde,0x78,0x6a,0x7e,0x54,0xd2,0x34,0xc7,0xdf,0xef,0x91,0xf5,0x7a,0xd0,
+  0xfc,0xc8,0xc6,0xbc,0x92,0x92,0x28,0x48,0x56,0xe3,0xab,0x54,0x4b,0xaf,0x9f,0x2d,
+  0x31,0x8f,0x1d,0x1e,0xda,0xb9,0x4d,0x1d,0x9a,0xf0,0xae,0xc1,0x91,0x63,0x2c,0x32,
+  0x73,0x3c,0xae,0x33,0x93,0x16,0x6e,0x86,0xcb,0x77,0x8e,0x31,0x29,0x42,0x53,0x88,
+  0xa1,0xb2,0x70,0x47,0xe0,0x1d,0x3,0xec,0x86,0x93,0x70,0xf8,0xa0,0x41,0xa2,0x66,
+  0x75,0x8c,0xa6,0x79,0xa2,0x87,0x9f,0x91,0x62,0x26,0xbc,0x7b,0x34,0x66,0x9c,0x47,
+  0x48,0xa2,0x20,0x59,0x4d,0x30,0x8,0x13,0x5b,0x6f,0x50,0xf,0x64,0x19,0x3b,0x36,
+  0x3c,0xb4,0x4b,0x69,0x82,0xf7,0xed,0xfd,0x47,0x8e,0xeb,0x81,0xbc,0xac,0x9c,0x8c,
+  0x27,0xd3,0xe8,0x7b,0x9b,0x36,0x4e,0xb0,0x9b,0x45,0xc,0xd5,0x33,0xfe,0x38,0x64,
+  0x3,0x67,0x68,0xbc,0x95,0x8c,0x19,0x59,0x26,0x57,0xf3,0xc4,0xd0,0x25,0x9c,0xb1,
+  0xe1,0x21,0x94,0x99,0xed,0x43,0xc3,0x34,0xb1,0xa0,0x31,0x44,0x9d,0xa2,0xe0,0xc8,
+  0xf9,0x64,0xc0,0x62,0x8e,0x18,0xaa,0xa2,0x2d,0x2e,0x7f,0x30,0x9a,0xa3,0x66,0xf4,
+  0xf0,0x81,0xc1,0xad,0x5b,0xfa,0xc3,0x90,0xba,0x9,0x87,0xfb,0x7,0xb6,0xe,0xbe,
+  0xfe,0xe6,0x68,0x91,0x16,0xfa,0xcb,0x48,0xb0,0xcf,0x6d,0xdc,0x5,0x57,0xa5,0xf6,
+  0xb3,0x1c,0x17,0x82,0xb5,0x57,0x5c,0xf4,0x84,0x46,0x6a,0xc5,0xe2,0x16,0x35,0xd7,
+  0xc3,0xd9,0x22,0xec,0xf0,0xc7,0x27,0x33,0x46,0x6c,0xb2,0x99,0xd4,0x84,0x4f,0x29,
+  0x75,0x5c,0xee,0x26,0x89,0x13,0x78,0x18,0xb9,0xf0,0x37,0xe2,0xa5,0x66,0xc2,0xe8,
+  0x6b,0x83,0xb4,0xf,0x78,0x6f,0x6f,0xb8,0x7f,0xcb,0xd6,0x67,0xf,0x1c,0xca,0x49,
+  0xde,0x98,0x93,0x84,0x93,0x33,0x46,0xf0,0x27,0xa5,0xd4,0xc6,0x9c,0x2e,0x20,0xf6,
+  0xde,0x0,0xbd,0xd3,0x5c,0x19,0x1b,0x3d,0x78,0x60,0x64,0xcf,0xee,0x9d,0x3b,0xb6,
+  0xf,0xd0,0x52,0xe0,0x3d,0x4c,0x3f,0x6f,0xdb,0xb5,0x6b,0x70,0xf7,0x9e,0x91,0x3,
+  0x7,0x4f,0xe8,0xd1,0x52,0xa5,0x12,0xf4,0xb9,0xa9,0x40,0x88,0x7,0x99,0xb8,0x4e,
+  0xc8,0x49,0x4d,0x8d,0x11,0x93,0xb5,0xed,0xde,0x60,0x94,0xa9,0xc7,0xc,0x55,0x90,
+  0xf4,0x3f,0x69,0x1a,0xd6,0x13,0xf1,0x83,0x2b,0x61,0x26,0x2f,0x88,0xfc,0x9c,0xe4,
+  0x54,0xfe,0xe8,0xc1,0x91,0xdd,0xb4,0x3,0xa,0xd2,0xef,0xa7,0xc2,0xdf,0xbe,0xf3,
+  0x99,0x3d,0x23,0x7,0x75,0x23,0x20,0x57,0x8c,0x79,0x2a,0x1a,0x47,0xc,0x7d,0xa,
+  0x9b,0x8b,0x8a,0xae,0xc,0x82,0xb1,0xb1,0xd1,0xa3,0x87,0xe,0xd3,0x32,0x9c,0x2b,
+  0x7,0xe9,0xc7,0x63,0xc7,0x8f,0x8f,0x95,0x2b,0x96,0x5c,0xf5,0x48,0xa0,0xb7,0xb0,
+  0x4,0x60,0xf7,0x43,0xc7,0x71,0x62,0xe1,0x25,0xd3,0xdb,0x15,0x40,0xeb,0x36,0x67,
+  0xf,0x55,0xe,0x5e,0x2f,0xfd,0x8f,0x5b,0x71,0x83,0x46,0xfd,0xef,0x99,0xd8,0xbd,
+  0x5,0x85,0x7f,0xb4,0x28,0x7d,0x2a,0xfc,0x43,0x47,0x2b,0x94,0x3a,0x15,0xbc,0x31,
+  0x25,0x4f,0x43,0x89,0xa1,0x2a,0x82,0xd8,0xdc,0xfe,0x60,0xa4,0x1c,0x9b,0x4a,0x4d,
+  0x62,0xfc,0xbf,0x68,0x30,0xd0,0x47,0x73,0x88,0x97,0xf4,0x3d,0xb1,0x4,0xc5,0x3e,
+  0xd5,0x3a,0x9e,0x17,0x57,0xff,0x8e,0x6a,0xa1,0x16,0xe9,0x36,0xf7,0x8a,0x97,0x97,
+  0xdb,0xb,0x91,0x40,0x9f,0x71,0xae,0x84,0x19,0x30,0xa5,0xef,0xeb,0xa6,0xed,0x89,
+  0xd5,0xe5,0xf1,0x51,0x6c,0x30,0x54,0x98,0x6a,0x9,0xfa,0xbd,0x45,0xe5,0x52,0x92,
+  0x37,0x59,0x16,0x13,0x18,0xc0,0x29,0x99,0x3c,0x1c,0x2d,0xd4,0x71,0xcd,0xbc,0x15,
+  0x5b,0xaf,0x2f,0x37,0x1f,0x11,0xd0,0xe2,0xf7,0x3a,0x5b,0x48,0x9a,0x84,0x26,0x4d,
+  0x73,0x7b,0xfd,0x1,0xe1,0x2d,0x53,0xcd,0xe2,0xf3,0x2c,0x73,0x8a,0x32,0xc4,0x5a,
+  0xbc,0x9,0x5e,0x80,0xe4,0x99,0x6,0xaf,0x9c,0x35,0xb3,0xc3,0xeb,0x70,0x6d,0x8b,
+  0xbd,0xa7,0x8f,0xae,0xe3,0x18,0xa,0xd5,0xea,0x6e,0xa1,0xe8,0xeb,0x70,0xdd,0x9a,
+  0x9b,0x60,0x4b,0xf,0xc4,0xe2,0x70,0xb1,0xf1,0xbd,0xaf,0x50,0xe8,0x40,0xef,0x76,
+  0x39,0xe8,0x28,0x84,0x2c,0x5f,0x10,0x4f,0xd2,0x38,0x1,0x89,0xb5,0xd0,0x4b,0x51,
+  0xb3,0x58,0x1a,0xfa,0x43,0x96,0xbc,0xce,0x55,0x12,0xbf,0x87,0x1a,0x59,0x34,0xb1,
+  0x9d,0xd4,0xca,0x51,0x43,0xef,0xb3,0x2e,0x17,0xb3,0xf9,0xab,0xa7,0x4d,0x29,0xf5,
+  0x13,0xfc,0xea,0x72,0x27,0x9d,0x46,0x66,0x88,0x4,0xa8,0xf5,0x56,0xc9,0x4c,0xc7,
+  0xec,0x9d,0x21,0x3d,0xd7,0xc4,0xdb,0xa4,0x11,0x6f,0xa5,0xc8,0x4d,0xd9,0xb4,0xa8,
+  0x4d,0xbc,0xdf,0xce,0xa5,0x9b,0x2f,0x1,0x42,0x7d,0xaa,0xb9,0xc9,0x76,0x46,0xfd,
+  0xac,0xf3,0xe6,0xdf,0x7e,0xe7,0xe,0x9a,0x21,0x1,0x5b,0x8f,0x8f,0x25,0x4c,0x80,
+  0x77,0x9f,0x36,0xe3,0xc6,0x3a,0xd7,0x6c,0x5d,0x9,0x10,0x4b,0x2f,0xf7,0x84,0xc8,
+  0xd6,0xbd,0xe3,0xce,0x9d,0x75,0x24,0xd0,0x91,0x40,0x47,0x2,0x1d,0x9,0x74,0x24,
+  0xd0,0x91,0x40,0x47,0x2,0x1d,0x9,0x74,0x24,0xd0,0x91,0x40,0x1b,0x4a,0xe0,0xff,
+  0x1,0x93,0x4,0x54,0x1a,0xa8,0x8d,0x92,0x85,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,
+  0x44,0xae,0x42,0x60,0x82,
+  
+};
+
+static const unsigned char qt_resource_name[] = {
+  // QtGSTPlayer
+  0x0,0xb,
+  0x9,0xc3,0x96,0xc2,
+  0x0,0x51,
+  0x0,0x74,0x0,0x47,0x0,0x53,0x0,0x54,0x0,0x50,0x0,0x6c,0x0,0x61,0x0,0x79,0x0,0x65,0x0,0x72,
+    // folder.png
+  0x0,0xa,
+  0xa,0xc8,0xfb,0x7,
+  0x0,0x66,
+  0x0,0x6f,0x0,0x6c,0x0,0x64,0x0,0x65,0x0,0x72,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67,
+    // settings.png
+  0x0,0xc,
+  0xb,0xdf,0x21,0x47,
+  0x0,0x73,
+  0x0,0x65,0x0,0x74,0x0,0x74,0x0,0x69,0x0,0x6e,0x0,0x67,0x0,0x73,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67,
+  
+};
+
+static const unsigned char qt_resource_struct[] = {
+  // :
+  0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+  // :/QtGSTPlayer
+  0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x2,
+  // :/QtGSTPlayer/folder.png
+  0x0,0x0,0x0,0x1c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+  // :/QtGSTPlayer/settings.png
+  0x0,0x0,0x0,0x36,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x20,0xb6,
+
+};
+
+QT_BEGIN_NAMESPACE
+
+extern Q_CORE_EXPORT bool qRegisterResourceData
+    (int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+extern Q_CORE_EXPORT bool qUnregisterResourceData
+    (int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+QT_END_NAMESPACE
+
+
+int QT_MANGLE_NAMESPACE(qInitResources_QtGSTPlayer)()
+{
+    QT_PREPEND_NAMESPACE(qRegisterResourceData)
+        (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
+    return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_QtGSTPlayer))
+
+int QT_MANGLE_NAMESPACE(qCleanupResources_QtGSTPlayer)()
+{
+    QT_PREPEND_NAMESPACE(qUnregisterResourceData)
+       (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
+    return 1;
+}
+
+Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_QtGSTPlayer))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QtGSTPlayer/record_play.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/data/gst_dll_2001F41F.txt	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstappu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstaudioresampleu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstaudiou.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstcddau.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstdecodebin2u.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstdecodebinu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstffmpegcolorspaceu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstinterfacesu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstnetbufferu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstpbutilsu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstplaybinu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstrtpu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgsttagu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgsttcpu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstvideoscaleu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/bwins/libgstvideou.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/config.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstappu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstaudioresampleu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstaudiou.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstcddau.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstdecodebin2u.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstdecodebinu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstgdpu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstinterfacesu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstnetbufferu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstplaybinu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstrtpu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgsttagu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgsttcpu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstvideoscaleu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstvideotestsrcu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/eabi/libgstvideou.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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/group/bld.inf	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/ffmpegcolorspace.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstffmpegcolorspace.dll
--- a/gst_plugins_base/group/gstadder.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstadder.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstadder.dll
--- a/gst_plugins_base/group/gstaudio.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstaudio.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstaudioconvert.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstaudioconvert.dll
--- a/gst_plugins_base/group/gstaudiorate.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstaudiorate.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstaudiorate.dll
--- a/gst_plugins_base/group/gstaudioresample.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstaudioresample.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstcdda.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstdecodebin.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET			libgstdecodebin.dll
--- a/gst_plugins_base/group/gstfft.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstfft.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstfft.dll
--- a/gst_plugins_base/group/gstinterfaces.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstinterfaces.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET          libgstinterfaces.dll
--- a/gst_plugins_base/group/gstpbutils.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstpbutils.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -20,6 +20,7 @@
 *
 */
 
+
 #include <platform_paths.hrh>                    
 
 TARGET			libgstpbutils.dll
--- a/gst_plugins_base/group/gstplayback.mmp	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstplayback.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstplaybin.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstsubparse.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstvideo.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstvideotestsrc.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/group/gstvolume.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/app/gstapp-marshal.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,5 @@
+BOOLEAN:UINT64
+ENUM:OBJECT
+ENUM:VOID
+VOID:UINT
+
--- a/gst_plugins_base/gst-libs/gst/app/gstappsink.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/app/gstappsink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/app/gstappsink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/app/gstappsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/audio.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/audio.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudioclock.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudioclock.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiofilter.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstringbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/gstringbuffer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/multichannel.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/audio/multichannel.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/cdda/gstcddabasesrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f32.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_f64.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s16.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/_kiss_fft_guts_s32.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/gstfft.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/gstfftf32.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/gstfftf64.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/gstffts16.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/gstffts32.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fft_s16.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fft_s32.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f32.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_f64.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s16.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/fft/kiss_fftr_s32.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/floatcast/floatcast.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalance.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalance.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/colorbalancechannel.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/interfaces-enumtypes.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixertrack.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/mixertrack.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/navigation.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/navigation.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/propertyprobe.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tuner.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tuner.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunerchannel.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunernorm.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/tunernorm.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/videoorientation.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/interfaces/xoverlay.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/netbuffer/gstnetbuffer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/pbutils/descriptions.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/pbutils/install-plugins.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/pbutils/missing-plugins.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/pbutils/pbutils-enumtypes.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/pbutils/pbutils.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/riff/riff-ids.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/riff/riff-media.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/riff/riff-read.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/riff/riff.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertpaudiopayload.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertpdepayload.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtcpbuffer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtppayloads.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspbase64.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspconnection.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspdefs.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspextension.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsprange.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtsptransport.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/sdp/gstsdpmessage.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/tag/gstid3tag.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/tag/gstvorbistag.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/tag/tag.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/tag/tags.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/video/gstvideofilter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/video/video.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/video/video.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/adder/gstadder.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/adder/gstadder.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/app/gstapp.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioconvert/audioconvert.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioconvert/audioconvert.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioconvert/gstaudioconvert.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioconvert/gstaudioconvert.h	Wed Mar 24 18:04:17 2010 -0500
@@ -48,8 +48,8 @@
 
   AudioConvertCtx ctx;
 
-  DitherType dither;
-  NoiseShapingType ns;
+  GstAudioConvertDithering dither;
+  GstAudioConvertNoiseShaping ns;
 };
 
 struct _GstAudioConvertClass
--- a/gst_plugins_base/gst/audioconvert/gstaudioquantize.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioconvert/gstaudioquantize.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioconvert/gstchannelmix.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audiorate/gstaudiorate.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioresample/gstaudioresample.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audioresample/gstaudioresample.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/audiotestsrc/gstaudiotestsrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/ffmpegcolorspace/avcodec.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcodecmap.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/ffmpegcolorspace/gstffmpegcolorspace.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/ffmpegcolorspace/imgconvert.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/ffmpegcolorspace/imgconvert_template.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/gdp/gstgdpdepay.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/gdp/gstgdpdepay.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/gdp/gstgdppay.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/gdp/gstgdppay.h	Wed Mar 24 18:04:17 2010 -0500
@@ -38,6 +38,11 @@
 typedef struct _GstGDPPay GstGDPPay;
 typedef struct _GstGDPPayClass GstGDPPayClass;
 
+/**
+ * GstGDPPay:
+ *
+ * Private gdppay element structure.
+ */
 struct _GstGDPPay
 {
   GstElement element;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gst_plugins_base/gst/playback/README	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/decodetest.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstdecodebin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstdecodebin2.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplay-enum.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplay-enum.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplay-marshal.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplay-marshal.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplay-marshal.list	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplayback.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplaybasebin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplaybasebin.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplaybin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplaybin2.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplaysink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstplaysink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstqueue2.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gstscreenshot.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gststreaminfo.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gststreamselector.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/gsturidecodebin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/test.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/test4.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/test5.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/test6.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/playback/test7.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/subparse/gstssaparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/subparse/gstssaparse.h	Wed Mar 24 18:04:17 2010 -0500
@@ -40,6 +40,7 @@
   GstPad         *srcpad;
 
   gboolean        framed;
+  gboolean        send_tags;
 
   gchar          *ini;
 };
--- a/gst_plugins_base/gst/subparse/gstsubparse.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/subparse/gstsubparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/subparse/gstsubparse.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/subparse/samiparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/subparse/tmplayerparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gstmultifdsink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gstmultifdsink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcp-enumtypes.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcp-marshal.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcp-marshal.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcp-marshal.list	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcp.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcp.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcpclientsink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcpclientsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcpserversink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/tcp/gsttcpserversrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/typefind/gsttypefindfunctions.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videorate/gstvideorate.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videorate/gstvideorate.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/gstvideoscale.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/gstvideoscale.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/vs_4tap.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/vs_4tap.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/vs_image.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/vs_image.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/vs_scanline.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videoscale/vs_scanline.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videotestsrc/gstvideotestsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videotestsrc/gstvideotestsrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videotestsrc/videotestsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/videotestsrc/videotestsrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/volume/gstvolume.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst/volume/gstvolume.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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/tsrc/check/elements/adder/src/adder.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/adder/src/adder.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/audioconvert/src/audioconvert.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/audiorate/src/audiorate.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/audioresample/src/audioresample.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/audiotestsrc/src/audiotestsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/createelementbase/src/createelementbase.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/decodebin/src/decodebin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/ffmpegcolorspace/src/ffmpegcolorspace.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/gdpdepay/src/gdpdepay.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/multifdsink/src/multifdsink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/playbin/src/playbin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/subparse/src/subparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/videorate/src/videorate.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/elements/volume/src/volume.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/generic/clock-selection/src/clock-selection.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/generic/states/src/states.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/gst/typefindfunctions/src/typefindfunctions.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/fft/src/fft.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/netbuffer/src/netbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/pbutils/src/pbutils.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/rtp/src/rtp.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/tag/src/tag.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/taudio/src/taudio.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/libs/video/src/video.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/pipelines/simple-launch-lines/src/simple-launch-lines.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/check/pipelines/streamheader/src/streamheader.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/tsrc/examples/dynamic/addstream/src/addstream.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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/libpng/gstpng.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/group/gstautodetect.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/autodetect/gstautoaudiosink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/autodetect/gstautoaudiosink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/autodetect/gstautodetect.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/autodetect/gstautovideosink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/wavenc/gstwavenc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/wavenc/gstwavenc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/wavenc/riff.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/wavparse/gstwavparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_good/gst/wavparse/gstwavparse.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_symbian/config.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/conf/GStreamerTestClass.cfg	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/group/GStreamerTestClass.pkg	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/inc/GStreamerTestClass.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_symbian/tsrc/gstreamertestmodule/src/GStreamerTestClassBlocks.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/bwins/libgstbaseu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/bwins/libgstcoreelementsu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/bwins/libgstreameru.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/config.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/eabi/libgstbaseu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/eabi/libgstcoreelementsu.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/eabi/libgstreameru.def	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/group/gstbase.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/group/gstindexers.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/group/gstreamer.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/glib-compat-private.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gst.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gst.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gst_global.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gst_private.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstbin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstbin.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstbuffer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstbus.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstbus.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstcaps.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstcaps.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstchildproxy.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstchildproxy.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstclock.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstclock.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstconfig.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstdebugutils.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstdebugutils.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstelement.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstelement.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstelementfactory.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstelementfactory.h	Wed Mar 24 18:04:17 2010 -0500
@@ -65,7 +65,7 @@
   gchar *description;
   gchar *author;
 
-  /*< private > */
+  /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 
--- a/gstreamer_core/gst/gstenumtypes.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstenumtypes.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstenumtypes.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsterror.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsterror.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstevent.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstevent.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstformat.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstghostpad.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstghostpad.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstindex.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstindexfactory.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstinfo.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstinfo.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstinterface.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstinterface.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstiterator.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstiterator.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstmacros.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstmessage.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstmessage.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstminiobject.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstminiobject.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstobject.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstobject.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpad.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpad.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpadtemplate.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstparamspecs.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstparamspecs.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstparse.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstparse.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpipeline.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpipeline.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstplugin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstplugin.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpluginfeature.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpoll.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstpoll.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstquark.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstquark.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstquery.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstquery.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstregistry.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstregistrybinary.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstregistrybinary.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstsegment.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstsegment.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gststructure.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gststructure.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstsystemclock.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstsystemclock.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttaglist.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttaglist.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttagsetter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttagsetter.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttask.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttask.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttrace.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttrace.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttypefind.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttypefind.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsttypefindfactory.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsturi.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gsturi.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstutils.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstutils.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstvalue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstvalue.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstversion.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/gstxml.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/helpfile.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/parse/grammar.tab.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/parse/grammar.tab.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/parse/lex._gst_parse_yy.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/parse/parse.l	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/gst/parse/types.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstadapter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstadapter.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstbasesink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstbasesink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstbasesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstbasesrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstbasetransform.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstbasetransform.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstcollectpads.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstcollectpads.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstdataqueue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstdataqueue.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gstpushsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gsttypefindhelper.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/base/gsttypefindhelper.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/check/gstbufferstraw.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/check/gstcheck.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/check/gstcheck.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/check/std_log_result.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstcontroller.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstcontroller.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstcontrollerprivate.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstcontrolsource.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gsthelper.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstinterpolation.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstinterpolationcontrolsource.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstinterpolationcontrolsourceprivate.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/gstlfocontrolsource.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/controller/lib.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/dataprotocol/dataprotocol.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/net/gstnetclientclock.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/net/gstnettimepacket.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/net/gstnettimepacket.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/libs/gst/net/gstnettimeprovider.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstcapsfilter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstelements.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfakesink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfakesink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfakesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfakesrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfdsink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfdsink.h	Wed Mar 24 18:04:17 2010 -0500
@@ -58,6 +58,7 @@
 
   int fd;
   guint64 bytes_written;
+  guint64 current_pos;
 };
 
 struct _GstFdSinkClass {
--- a/gstreamer_core/plugins/elements/gstfdsrc.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfdsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfdsrc.h	Wed Mar 24 18:04:17 2010 -0500
@@ -62,6 +62,9 @@
   gint fd;
   gboolean seekable_fd;
 
+  /* poll timeout */
+  guint64 timeout;
+
   gchar *uri;
 
   GstPoll *fdset;
--- a/gstreamer_core/plugins/elements/gstfilesink.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfilesink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstfilesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstidentity.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstidentity.h	Wed Mar 24 18:04:17 2010 -0500
@@ -73,6 +73,7 @@
   gchar 	*last_message;
   guint64        offset;
   gboolean       signal_handoffs;
+  GStaticRecMutex  notify_lock;
 };
 
 struct _GstIdentityClass {
--- a/gstreamer_core/plugins/elements/gstmultiqueue.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstmultiqueue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gstqueue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gsttee.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gsttee.h	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gsttypefindelement.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/elements/gsttypefindelement.h	Wed Mar 24 18:04:17 2010 -0500
@@ -59,6 +59,7 @@
   GstBuffer *		store;
 
   GList *               cached_events;
+  GstCaps *             force_caps;
 };
 
 struct _GstTypeFindElementClass {
--- a/gstreamer_core/plugins/indexers/gstfileindex.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/indexers/gstfileindex.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/indexers/gstindexers.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/plugins/indexers/gstmemindex.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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/tsrc/check/elements/createelementcore/src/createelementcore.c	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/createelementcore/src/createelementcore.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/fakesink/src/fakesink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/fakesrc/src/fakesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/fdsrc/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/fdsrc/src/fdsrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/filesink/src/filesink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/filesrc/src/filesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/gstqueue/src/gstqueue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/identity/src/identity.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/multiqueue/src/multiqueue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/elements/tee/src/tee.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/generic/gststates/src/gststates.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/generic/sinks/src/sinks.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gst/src/gst.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstbin/src/gstbin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstbuffer/src/gstbuffer.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstbus/src/gstbus.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstcaps/src/gstcaps.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstelement/src/gstelement.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstevent/src/gstevent.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstghostpad/src/gstghostpad.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstindex/src/gstindex.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstinterface/src/gstinterface.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstiterator/src/gstiterator.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstmessage/src/gstmessage.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstminiobject/src/gstminiobject.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstobject/src/gstobject.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstpad/src/gstpad.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstparamspecs/src/gstparamspecs.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstpipeline/src/gstpipeline.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstplugin/src/gstplugin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstpoll/src/gstpoll.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstquery/src/gstquery.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstregistry/src/gstregistry.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstsegment/src/gstsegment.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gststructure/src/gststructure.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstsystemclock/src/gstsystemclock.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gsttag/src/gsttag.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gsttagsetter/src/gsttagsetter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gsttask/src/gsttask.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gsturi/src/gsturi.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstutils/src/gstutils.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/gst/gstvalue/src/gstvalue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/adapter/src/adapter.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/basesrc/src/basesrc.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/collectpads/src/collectpads.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/controller/src/controller.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/gdp/src/gdp.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/gstnetclientclock/src/gstnetclientclock.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/gstnettimeprovider/src/gstnettimeprovider.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/libsabi/src/libsabi.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/libs/typefindhelper/src/typefindhelper.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/pipelines/cleanup/src/cleanup.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/pipelines/core-simple-launch-lines/src/core-simple-launch-lines.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/pipelines/parse-disabled/src/parse-disabled.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/pipelines/parse-launch/src/parse-launch.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/check/pipelines/stress/src/stress.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/adapter/src/adapter_test.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/controller/src/audio-example.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/helloworld/src/helloworld.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/launch/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/launch/src/launch.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/launch/src/mp3parselaunch.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/bin/src/bin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/createelements/src/elementcreate.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/elementfactory/src/elementfactory.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/getelements/src/elementget.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/init/src/init.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/linkelements/src/elementlink.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/makeelements/src/elementmake.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_decodebin/src/manual_decodebin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_dynamic/src/manual_dynamic.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_ghostpad/src/manual_ghostpad.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_helloworld/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_helloworld/src/manual_helloworld.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_playbin/src/manual_playbin.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/manual_typefind/src/manual_typefind.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/pad/src/pad.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/query/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/manual/query/src/query.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/metadata/src/read-metadata.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/queue/src/queue.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/examples/typefind/src/typefind.c	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstreamer_core/tsrc/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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 the License "Symbian Foundation License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.symbianfoundation.org/legal/sfl-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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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 the License "Symbian Foundation License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.symbianfoundation.org/legal/sfl-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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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 the License "Symbian Foundation License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.symbianfoundation.org/legal/sfl-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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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 the License "Symbian Foundation License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.symbianfoundation.org/legal/sfl-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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstregistrygenerator/group/gstregistrygenerator.mmp	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/gstregistrygenerator/src/gstregistrygenerator.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -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/internal/gstplayer/data/gstplayer.rss	Wed Mar 24 17:58:42 2010 -0500
+++ b/internal/gstplayer/data/gstplayer.rss	Wed Mar 24 18:04:17 2010 -0500
@@ -126,6 +126,7 @@
     items=
         {
         MENU_ITEM{command = EGSTPlayerRecordWav;txt = "Record WAV";},        
+        MENU_ITEM{command = EGSTPlayerRecordAac;txt = "Record AAC";}, 
         MENU_ITEM{command = EGSTPlayerRecordRaw;txt = "Record RAW";},
         MENU_ITEM{command = EGSTPlayerRecordAmr;txt = "Record AMR";},        
         MENU_ITEM{command = EGSTPlayerRecordG711;txt = "Record G711";},
--- a/internal/gstplayer/inc/gstplayer.hrh	Wed Mar 24 17:58:42 2010 -0500
+++ b/internal/gstplayer/inc/gstplayer.hrh	Wed Mar 24 18:04:17 2010 -0500
@@ -75,7 +75,8 @@
     EGSTPlayerSrcPadCaps,
     
     EGSTPlayerNegotiatedSinkCaps,
-    EGSTPlayerNegotiatedSrcCaps
+    EGSTPlayerNegotiatedSrcCaps,
+    EGSTPlayerRecordAac
     
     
     };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/gstplayer/inc/gstreamer.h	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,51 @@
+#include <e32def.h>
+#include <e32cmn.h>
+#include <gst/gst.h>
+#include <string.h>
+#include "gstplayerappview.h"
+
+extern GstElement *pipeline, *source, *wavparse,*sink,*conv,*resample,*decoder;
+extern GstBus *bus;
+
+extern CGSTPlayerAppView *iGstView;
+
+
+int GstreamerNew(TFileName filename);
+int GstreamerPlay(TFileName filename);
+int gst_play_mp3();
+int gst_play_wave();
+int gst_play_raw();
+int gst_play_amr();
+int gst_play_g711();
+int gst_play_g729();
+int gst_play_ilbc();
+
+int gst_record_raw();
+int gst_record_wav();
+int gst_record_amr();
+int gst_record_g711();
+int gst_record_aac();
+int gst_record_g729();
+int gst_record_ilbc();
+int gst_current_volume();
+int gst_max_volume();
+int gst_volume_up();
+int gst_volume_down();
+
+void ShownoteL();
+
+int gst_current_gain();
+int gst_max_gain();
+int gst_gain_up();
+int gst_gain_down();
+
+int gst_balance();
+void samplesplayed();
+void samplesrecorded();
+void samplesrecorded();
+void getsinkpadcaps();
+void negotiatedsinkcaps();
+void getsrcpadcaps();
+void negotiatedsrccaps();
+
+
--- a/internal/gstplayer/src/GSTPlayerappui.cpp	Wed Mar 24 17:58:42 2010 -0500
+++ b/internal/gstplayer/src/GSTPlayerappui.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -247,7 +247,8 @@
             break;
             
         case EGSTPlayerPause:
-                   if (pipeline!=NULL )
+                   if (pipeline!=NULL && pipeline ->current_state
+                           == GST_STATE_PLAYING)
                        {
 
                        gst_element_set_state(pipeline, GST_STATE_PAUSED);
@@ -257,7 +258,8 @@
                    break;    
                    
         case EGSTPlayerResume:
-               if (pipeline!=NULL)
+               if (pipeline!=NULL && pipeline ->current_state
+                       == GST_STATE_PAUSED)
                    {
 
                    gst_element_set_state(pipeline, GST_STATE_PLAYING);
@@ -279,6 +281,19 @@
             gst_record_wav();
             }
             break;
+        case EGSTPlayerRecordAac:
+            {
+            if (pipeline!=NULL && pipeline ->current_state
+                    == GST_STATE_PLAYING)
+                {
+
+                gst_element_set_state(pipeline, GST_STATE_NULL);
+                //gst_object_unref (GST_OBJECT (pipeline));                 
+
+                }
+            gst_record_aac();
+            }
+            break;            
 
         case EGSTPlayerRecordRaw:
             {
--- a/internal/gstplayer/src/SymGstreamer.cpp	Wed Mar 24 17:58:42 2010 -0500
+++ b/internal/gstplayer/src/SymGstreamer.cpp	Wed Mar 24 18:04:17 2010 -0500
@@ -33,7 +33,7 @@
 
 #include "gstplayerappview.h"
 
-GstElement *pipeline, *source, *wavparse,*sink,*decoder,*conv,*resample,*record,*fakesink,*filesink,*encoder,*filter,*wavenc;
+GstElement *pipeline, *source, *wavparse,*sink,*decoder,*conv,*resample,*record,*fakesink,*filesink,*encoder,*filter,*wavenc, *amrmux, *aacenc, *mp4mux;
 GstBus *bus;
 GstCaps* caps;
 GstState current,pending;
@@ -316,46 +316,33 @@
  return 0;  
 }
  
-
  int gst_play_wave()
  {
     /* create elements */
-     if(!pipeline)
-         {
-         pipeline = gst_pipeline_new ("pipeline");
-         bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
-         gst_bus_add_watch (bus, bus_call, NULL);
-         gst_object_unref (bus);
-         }
-
-     if(!source)
-         {
-         source = gst_element_factory_make ("filesrc", "pavsrc");
-         g_object_set (G_OBJECT (source), "location", carray, NULL);
-         gst_bin_add (GST_BIN (pipeline), source);
-         }
+  pipeline = gst_pipeline_new ("pipeline");
+  source = gst_element_factory_make ("filesrc", "pavsrc");
+  wavparse = gst_element_factory_make ("wavparse", "parse");
+ 
+  /* set filename property on the file source */
+  g_object_set (G_OBJECT (source), "location", carray, NULL);
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  gst_bus_add_watch (bus, bus_call, NULL);
+  gst_object_unref (bus);
+  gst_bin_add_many (GST_BIN (pipeline), source, wavparse, NULL);
+  if (!gst_element_link (source, wavparse))
+     g_error ("link(src, wavparse) failed!\n");
 
-     if(!wavparse)
-         {
-         wavparse = gst_element_factory_make ("wavparse", "parse");
-         gst_bin_add (GST_BIN (pipeline), wavparse );
-         g_signal_connect (wavparse, "pad-added", G_CALLBACK (new_pad_cb),pipeline);
-         }
- 
-      /* set filename property on the file source */
-      if (!gst_element_link (source, wavparse))
-          {
-          g_print("could not link elements!");
-          return -1;
-          }
-          
-
-      gst_element_set_state (pipeline, GST_STATE_PLAYING); 
-      return 0; 
+  
+  g_signal_connect (wavparse, "pad-added", G_CALLBACK (new_pad_cb),pipeline);
+    
+  gst_element_set_state (pipeline, GST_STATE_PLAYING); 
+  return 0; 
  }
  
  int gst_record_wav()
     {
+     
+     iGstView->DrawText(_L("Recording Wave"),KRgbBlack);
 
     /* create a new bin to hold the elements */
     pipeline = gst_pipeline_new("pipeline");
@@ -366,7 +353,7 @@
         g_print("could not create \"record\" element!");
         return -1;
         }
-    
+    //g_object_set (G_OBJECT (record), "num-buffers", 5000 , NULL);
     filesink = gst_element_factory_make("filesink", "filesink");
     if (!filesink)
         {
@@ -409,16 +396,97 @@
     gst_element_link_filtered (record, wavenc, caps);
     gst_element_link (wavenc, filesink);
     gst_caps_unref (caps);
-
+    iGstView->DrawText(_L("pipeline created\n"),KRgbBlack);
     /* start recording */
     gst_element_set_state(pipeline, GST_STATE_PLAYING);
+    iGstView->DrawText(_L("set to play wave file\n"),KRgbBlack);
+    return 0;
+    }
+ 
+ 
+ int gst_record_aac()
+    {
+     GstPad *qtsinkpad,*aacencsrcpad;
+     iGstView->DrawText(_L("Recording aac"),KRgbBlack);
 
+    /* create a new bin to hold the elements */
+    pipeline = gst_pipeline_new("pipeline");
+
+    record = gst_element_factory_make("devsoundsrc", "record_audio");
+    if (!record)
+        {
+        g_print("could not create \"record\" element!");
+        return -1;
+        }
+    //g_object_set (G_OBJECT (record), "num-buffers", 5000 , NULL);
+    filesink = gst_element_factory_make("filesink", "filesink");
+    if (!filesink)
+        {
+        g_print("could not create \"filesink\" element!");
+        return -1;
+        }
+
+    aacenc = gst_element_factory_make("nokiaaacenc", "nokiaaacenc");
+    if (!aacenc)
+        {
+        g_print("could not create \"aacenc\" element!");
+        return -1;
+        }
+    
+    mp4mux = gst_element_factory_make("mp4mux", "mp4mux");
+    if (!mp4mux)
+        {
+        g_print("could not create \"mp4mux\" element!");
+        return -1;
+        }    
+    //name = gst_pad_get_name( sinkpad );    
+
+    _LIT(KFILENAME,"c:\\data\\test.mp4");
+    TFileName fn;
+    fn.Append(KFILENAME);
+    TInt ret;
+    // char carray[FILENAME];
+    ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
+
+    g_object_set(G_OBJECT (filesink), "location", carray, NULL);
+    bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
+    gst_bus_add_watch(bus, bus_call, NULL);
+    gst_object_unref(bus);
+
+    /* add objects to the main pipeline */
+    gst_bin_add_many(GST_BIN (pipeline),record,aacenc,mp4mux,filesink, NULL);
+
+    /* link the elements */
+    //gst_element_link_many(record, aacenc,filesink, NULL);
+    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);
+    
+    gst_element_link_filtered (record, aacenc, caps);
+    qtsinkpad  = gst_element_get_request_pad( mp4mux, "audio_%d");
+    aacencsrcpad  = gst_element_get_pad( aacenc, "src");  
+    if (gst_pad_link (aacencsrcpad,qtsinkpad) != GST_PAD_LINK_OK) {
+
+    g_print("gst_pad_link (aacencsrcpad,qtsinkpad) failed");
+    return -1;
+    }       
+    //gst_element_link (aacenc, filesink);
+    gst_element_link (mp4mux, filesink);
+    gst_caps_unref (caps);
+    iGstView->DrawText(_L("pipeline created\n"),KRgbBlack);
+    /* start recording */
+    gst_element_set_state(pipeline, GST_STATE_PLAYING);
+    iGstView->DrawText(_L("set to play aac file\n"),KRgbBlack);
     return 0;
     }
  
  int gst_record_amr()
  {
- iGstView->DrawText(_L("Recording AMR"),KRgbRed);
+ iGstView->DrawText(_L("Recording AMR-NB"),KRgbRed);
 
    /* create a new bin to hold the elements */
   pipeline = gst_pipeline_new ("pipeline");
@@ -432,12 +500,21 @@
     return -1;
   }
 
+            
+      amrmux = gst_element_factory_make ("amrmux", "muxer"); 
+ // encoder = gst_element_factory_make ("wavenc", NULL); 
+  if (!amrmux) {
+    g_print ("could not create \"amrmuxer\" element!");
+    iGstView->DrawText(_L("amrmuxer not available"),KRgbRed);
+    return -1;
+  }
+
   filesink = gst_element_factory_make("filesink", "filesink");
       if (!filesink)
           {
           g_print("could not create \"filesink\" element!");
           return -1;
-          }
+          }        
 
   caps = gst_caps_new_simple ("audio/amr",
              "width", G_TYPE_INT, 8,
@@ -465,9 +542,12 @@
   
 
   /* add objects to the main pipeline */
-  gst_bin_add_many(GST_BIN (pipeline),record,filesink , NULL);
+  gst_bin_add_many(GST_BIN (pipeline),record,amrmux,filesink , NULL);
   /* link the elements */
-  gst_element_link_filtered (record, filesink, caps);
+  gst_element_link_filtered (record, amrmux, caps);
+  
+  gst_element_link( amrmux, filesink );
+  
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
   
   return 0;
@@ -536,7 +616,7 @@
      g_print ("could not create \"record\" element!");
      return -1;
    }
- 
+
    filesink = gst_element_factory_make("filesink", "filesink");
        if (!filesink)
            {
@@ -642,7 +722,6 @@
     return -1;
   }
   //g_print ("record created");
-
   filesink = gst_element_factory_make("filesink", "filesink");
       if (!filesink)
           {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/miscfiles/copyplugins.bat	Wed Mar 24 18:04:17 2010 -0500
@@ -0,0 +1,27 @@
+md \epoc32\release\winscw\udeb\z\sys\bin\plugins
+
+COPY \epoc32\release\winscw\udeb\libgstcoreelements.dll         \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstcoreelements.dll
+COPY \epoc32\release\winscw\udeb\libgstcoreindexers.dll         \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstcoreindexers.dll
+COPY \epoc32\release\winscw\udeb\libgstwavparse.dll             \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstwavparse.dll
+COPY \epoc32\release\winscw\udeb\libgstwavenc.dll               \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstwavenc.dll
+COPY \epoc32\release\winscw\udeb\libgstdevsoundsink.dll         \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdevsoundsink.dll
+COPY \epoc32\release\winscw\udeb\libgstdevsoundsrc.dll          \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdevsoundsrc.dll
+COPY \epoc32\release\winscw\udeb\libgstaudioconvert.dll         \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudioconvert.dll
+COPY \epoc32\release\winscw\udeb\libgstaudioresample.dll        \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudioresample.dll
+COPY \epoc32\release\winscw\udeb\libgstaudiotestsrc.dll         \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudiotestsrc.dll
+COPY \epoc32\release\winscw\udeb\libgstdecodebin.dll            \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdecodebin.dll
+COPY \epoc32\release\winscw\udeb\libgstdecodebin2.dll           \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdecodebin2.dll
+COPY \epoc32\release\winscw\udeb\libgstplaybin.dll              \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstplaybin.dll
+COPY \epoc32\release\winscw\udeb\libgsttypefindfunctions.dll    \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgsttypefindfunctions.dll
+COPY \epoc32\release\winscw\udeb\libgstqueue2.dll               \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstqueue2.dll
+COPY \epoc32\release\winscw\udeb\libgstaudiorate.dll            \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudiorate.dll
+COPY \epoc32\release\winscw\udeb\libgstautodetect.dll           \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstautodetect.dll
+COPY \epoc32\release\winscw\udeb\libgstapp.dll                  \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstapp.dll
+COPY \epoc32\release\winscw\udeb\libgstsubparse.dll             \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstsubparse.dll
+COPY \epoc32\release\winscw\udeb\libgstgdp.dll                  \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstgdp.dll
+COPY \epoc32\release\winscw\udeb\libgstadder.dll                \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstadder.dll
+COPY \epoc32\release\winscw\udeb\libgstvolume.dll               \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstvolume.dll
+COPY \epoc32\release\winscw\udeb\libgsttcp.dll                  \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgsttcp.dll
+COPY \epoc32\release\winscw\udeb\gstqtmux.dll                  \epoc32\release\winscw\udeb\z\sys\bin\plugins\gstqtmux.dll
+COPY \epoc32\release\winscw\udeb\libgstnokiaaacenc.dll                  \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstnokiaaacenc.dll
+COPY \epoc32\release\winscw\udeb\libgstamrmux.dll                  \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstamrmux.dll
\ No newline at end of file
--- a/rom/gstreamer.iby	Wed Mar 24 17:58:42 2010 -0500
+++ b/rom/gstreamer.iby	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/sis/gstreamer.pkg	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ b/tsrc/group/bld.inf	Wed Mar 24 18:04:17 2010 -0500
@@ -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	Wed Mar 24 17:58:42 2010 -0500
+++ /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"